From cb477131198ed1508777dc79ff72505da2f163e7 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 20 Jun 2021 12:00:30 +0800 Subject: [PATCH] Update jpgraph --- web/public_php/admin/jpgraph/README | 63 + .../jpgraph/barcode/demoapp/barcode_image.php | 75 + .../jpgraph/barcode/demoapp/barcode_menu.php | 125 + .../admin/jpgraph/barcode/demoapp/index.html | 10 + .../examples/barcode_errhandling_ex0.php | 16 + .../jpgraph/barcode/examples/barcode_ex0.php | 11 + .../jpgraph/barcode/examples/barcode_ex1.php | 14 + .../jpgraph/barcode/examples/barcode_ex2.php | 14 + .../jpgraph/barcode/examples/barcode_ex3.php | 17 + .../jpgraph/barcode/examples/barcode_ex4.php | 12 + .../barcode/examples/barcode_usps_example.php | 74 + .../admin/jpgraph/barcode/mkbarcode.php | 281 + web/public_php/admin/jpgraph/flag_mapping | 237 + web/public_php/admin/jpgraph/flags.dat | Bin 974899 -> 982587 bytes .../admin/jpgraph/flags_thumb100x100.dat | Bin 684410 -> 687530 bytes .../admin/jpgraph/flags_thumb35x35.dat | Bin 213479 -> 214310 bytes .../admin/jpgraph/flags_thumb60x60.dat | Bin 373938 -> 375469 bytes .../admin/jpgraph/fonts/DejaVuSans-Bold.ttf | Bin 0 -> 634184 bytes .../jpgraph/fonts/DejaVuSans-BoldOblique.ttf | Bin 0 -> 574636 bytes .../jpgraph/fonts/DejaVuSans-Oblique.ttf | Bin 0 -> 574456 bytes .../admin/jpgraph/fonts/DejaVuSans.ttf | Bin 0 -> 683528 bytes .../admin/jpgraph/fonts/FF_FONT0-Bold.gdf | Bin 0 -> 13456 bytes .../admin/jpgraph/fonts/FF_FONT0.gdf | Bin 0 -> 13456 bytes .../admin/jpgraph/fonts/FF_FONT1-Bold.gdf | Bin 0 -> 18832 bytes .../admin/jpgraph/fonts/FF_FONT1.gdf | Bin 0 -> 18832 bytes .../admin/jpgraph/fonts/FF_FONT2-Bold.gdf | Bin 0 -> 25104 bytes .../admin/jpgraph/fonts/FF_FONT2.gdf | Bin 0 -> 25104 bytes web/public_php/admin/jpgraph/gd_image.inc.php | 2306 +++ .../admin/jpgraph/imageSmoothArc.php | 344 + .../admin/jpgraph/imgdata_balls.inc | 1064 -- .../admin/jpgraph/imgdata_balls.inc.php | 1061 ++ .../admin/jpgraph/imgdata_bevels.inc | 105 - .../admin/jpgraph/imgdata_bevels.inc.php | 104 + .../admin/jpgraph/imgdata_diamonds.inc | 178 - .../admin/jpgraph/imgdata_diamonds.inc.php | 177 + .../admin/jpgraph/imgdata_pushpins.inc | 518 - .../admin/jpgraph/imgdata_pushpins.inc.php | 517 + .../admin/jpgraph/imgdata_squares.inc | 151 - .../admin/jpgraph/imgdata_squares.inc.php | 150 + .../admin/jpgraph/imgdata_stars.inc | 145 - .../admin/jpgraph/imgdata_stars.inc.php | 144 + web/public_php/admin/jpgraph/jpg-config.inc | 201 - .../admin/jpgraph/jpg-config.inc.php | 138 + web/public_php/admin/jpgraph/jpgraph.php | 14196 ++++++---------- .../admin/jpgraph/jpgraph_antispam-digits.php | 410 +- .../admin/jpgraph/jpgraph_antispam.php | 1240 +- web/public_php/admin/jpgraph/jpgraph_bar.php | 2164 +-- .../admin/jpgraph/jpgraph_canvas.php | 172 +- .../admin/jpgraph/jpgraph_canvtools.php | 1039 +- .../admin/jpgraph/jpgraph_contour.php | 587 + web/public_php/admin/jpgraph/jpgraph_date.php | 997 +- .../admin/jpgraph/jpgraph_errhandler.inc.php | 369 + .../admin/jpgraph/jpgraph_error.php | 314 +- .../admin/jpgraph/jpgraph_flags.php | 747 +- .../admin/jpgraph/jpgraph_gantt.php | 7731 +++++---- .../admin/jpgraph/jpgraph_gb2312.php | 3105 ++-- .../admin/jpgraph/jpgraph_gradient.php | 811 +- .../admin/jpgraph/jpgraph_iconplot.php | 380 +- .../admin/jpgraph/jpgraph_imgtrans.php | 447 +- web/public_php/admin/jpgraph/jpgraph_led.php | 311 + .../admin/jpgraph/jpgraph_legend.inc.php | 494 + web/public_php/admin/jpgraph/jpgraph_line.php | 1307 +- web/public_php/admin/jpgraph/jpgraph_log.php | 573 +- .../jpgraph/jpgraph_meshinterpolate.inc.php | 105 + .../admin/jpgraph/jpgraph_mgraph.php | 345 + web/public_php/admin/jpgraph/jpgraph_pie.php | 2840 ++-- .../admin/jpgraph/jpgraph_pie3d.php | 1845 +- .../admin/jpgraph/jpgraph_plotband.php | 1270 +- .../admin/jpgraph/jpgraph_plotline.php | 142 + .../admin/jpgraph/jpgraph_plotmark.inc | 482 - .../admin/jpgraph/jpgraph_plotmark.inc.php | 504 + .../admin/jpgraph/jpgraph_polar.php | 1744 +- .../admin/jpgraph/jpgraph_radar.php | 1508 +- .../admin/jpgraph/jpgraph_regstat.php | 417 +- .../admin/jpgraph/jpgraph_rgb.inc.php | 615 + .../admin/jpgraph/jpgraph_scatter.php | 467 +- .../admin/jpgraph/jpgraph_stock.php | 381 +- .../admin/jpgraph/jpgraph_table.php | 1331 ++ .../admin/jpgraph/jpgraph_text.inc.php | 327 + .../admin/jpgraph/jpgraph_theme.inc.php | 136 + .../admin/jpgraph/jpgraph_ttf.inc.php | 631 + .../admin/jpgraph/jpgraph_utils.inc | 251 - .../admin/jpgraph/jpgraph_utils.inc.php | 685 + .../admin/jpgraph/jpgraph_windrose.php | 1566 ++ web/public_php/admin/jpgraph/lang/de.inc.php | 552 + web/public_php/admin/jpgraph/lang/en.inc.php | 1040 +- .../admin/jpgraph/lang/prod.inc.php | 386 + .../admin/jpgraph/themes/AquaTheme.class.php | 201 + .../admin/jpgraph/themes/GreenTheme.class.php | 182 + .../admin/jpgraph/themes/OceanTheme.class.php | 184 + .../jpgraph/themes/OrangeTheme.class.php | 184 + .../jpgraph/themes/PastelTheme.class.php | 179 + .../admin/jpgraph/themes/RoseTheme.class.php | 184 + .../admin/jpgraph/themes/SoftyTheme.class.php | 213 + .../jpgraph/themes/UniversalTheme.class.php | 187 + .../admin/jpgraph/themes/VividTheme.class.php | 179 + 96 files changed, 39339 insertions(+), 27570 deletions(-) create mode 100644 web/public_php/admin/jpgraph/README create mode 100644 web/public_php/admin/jpgraph/barcode/demoapp/barcode_image.php create mode 100644 web/public_php/admin/jpgraph/barcode/demoapp/barcode_menu.php create mode 100644 web/public_php/admin/jpgraph/barcode/demoapp/index.html create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_errhandling_ex0.php create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_ex0.php create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_ex1.php create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_ex2.php create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_ex3.php create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_ex4.php create mode 100644 web/public_php/admin/jpgraph/barcode/examples/barcode_usps_example.php create mode 100644 web/public_php/admin/jpgraph/barcode/mkbarcode.php create mode 100644 web/public_php/admin/jpgraph/flag_mapping create mode 100644 web/public_php/admin/jpgraph/fonts/DejaVuSans-Bold.ttf create mode 100644 web/public_php/admin/jpgraph/fonts/DejaVuSans-BoldOblique.ttf create mode 100644 web/public_php/admin/jpgraph/fonts/DejaVuSans-Oblique.ttf create mode 100644 web/public_php/admin/jpgraph/fonts/DejaVuSans.ttf create mode 100644 web/public_php/admin/jpgraph/fonts/FF_FONT0-Bold.gdf create mode 100644 web/public_php/admin/jpgraph/fonts/FF_FONT0.gdf create mode 100644 web/public_php/admin/jpgraph/fonts/FF_FONT1-Bold.gdf create mode 100644 web/public_php/admin/jpgraph/fonts/FF_FONT1.gdf create mode 100644 web/public_php/admin/jpgraph/fonts/FF_FONT2-Bold.gdf create mode 100644 web/public_php/admin/jpgraph/fonts/FF_FONT2.gdf create mode 100644 web/public_php/admin/jpgraph/gd_image.inc.php create mode 100644 web/public_php/admin/jpgraph/imageSmoothArc.php delete mode 100644 web/public_php/admin/jpgraph/imgdata_balls.inc create mode 100644 web/public_php/admin/jpgraph/imgdata_balls.inc.php delete mode 100644 web/public_php/admin/jpgraph/imgdata_bevels.inc create mode 100644 web/public_php/admin/jpgraph/imgdata_bevels.inc.php delete mode 100644 web/public_php/admin/jpgraph/imgdata_diamonds.inc create mode 100644 web/public_php/admin/jpgraph/imgdata_diamonds.inc.php delete mode 100644 web/public_php/admin/jpgraph/imgdata_pushpins.inc create mode 100644 web/public_php/admin/jpgraph/imgdata_pushpins.inc.php delete mode 100644 web/public_php/admin/jpgraph/imgdata_squares.inc create mode 100644 web/public_php/admin/jpgraph/imgdata_squares.inc.php delete mode 100644 web/public_php/admin/jpgraph/imgdata_stars.inc create mode 100644 web/public_php/admin/jpgraph/imgdata_stars.inc.php delete mode 100644 web/public_php/admin/jpgraph/jpg-config.inc create mode 100644 web/public_php/admin/jpgraph/jpg-config.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_contour.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_errhandler.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_led.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_legend.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_meshinterpolate.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_mgraph.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_plotline.php delete mode 100644 web/public_php/admin/jpgraph/jpgraph_plotmark.inc create mode 100644 web/public_php/admin/jpgraph/jpgraph_plotmark.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_rgb.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_table.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_text.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_theme.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_ttf.inc.php delete mode 100644 web/public_php/admin/jpgraph/jpgraph_utils.inc create mode 100644 web/public_php/admin/jpgraph/jpgraph_utils.inc.php create mode 100644 web/public_php/admin/jpgraph/jpgraph_windrose.php create mode 100644 web/public_php/admin/jpgraph/lang/de.inc.php create mode 100644 web/public_php/admin/jpgraph/lang/prod.inc.php create mode 100644 web/public_php/admin/jpgraph/themes/AquaTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/GreenTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/OceanTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/OrangeTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/PastelTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/RoseTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/SoftyTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/UniversalTheme.class.php create mode 100644 web/public_php/admin/jpgraph/themes/VividTheme.class.php diff --git a/web/public_php/admin/jpgraph/README b/web/public_php/admin/jpgraph/README new file mode 100644 index 000000000..9c47db9dd --- /dev/null +++ b/web/public_php/admin/jpgraph/README @@ -0,0 +1,63 @@ +README FOR JPGRAPH 4.3.4 +========================= + +This package contains the JpGraph PHP library version 4.3.4 + +The library is Copyright (C) 2000-2010 Asial Corporatoin and +released under dual license QPL 1.0 for open source and educational +use and JpGraph Professional License for commercial use. + +Please see full license details at +http://jpgraph.net/pro/ +http://jpgraph.net/download/ + + +Requirements: +------------- +Miminum: +* PHP 5.1.0 or higher +* GD 2.0.28 or higher +Note: Earlier versions might work but is unsupported. + +Recommended: +* >= PHP 5.2.0 +* PHP Builtin GD library + +Installation +------------ +1. Make sure that the PHP version is compatible with the stated + requirements and that the PHP installation has support for + the GD library. Please run phpinfo() to check if GD library + is supported in the installation. + If the GD library doesn't seem to be installed + please consult the PHP manual under section "Image" for + instructions on where to find this library. Please refer to + the manual section "Verifying your PHP installation" + +2. Unzip and copy the files to a directory of your choice where Your + httpd sever can access them. + For a global site installation you should copy the files to + somewhere in the PHP search path. + +3. Check that the default directory paths in jpg-config.inc.php + for cache directory and TTF directory suits your installation. + Note1: The default directories are different depending on if + the library is running on Windows or UNIX. + Note2: Apache/PHP must have write permission to your cache + directory if you enable the cache feature. By default the cache + is disabled. + + +Documentation +------------- +The installation includes HTML documentation and reference guide for the +library. The portal page for all documentation is +/docs/index.html + + +Bug reports and suggestions +--------------------------- +Should be reported using the contact form at + +http://jpgraph.net/contact/ + diff --git a/web/public_php/admin/jpgraph/barcode/demoapp/barcode_image.php b/web/public_php/admin/jpgraph/barcode/demoapp/barcode_image.php new file mode 100644 index 000000000..2ad88fd6a --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/demoapp/barcode_image.php @@ -0,0 +1,75 @@ + 5 ) { + echo "

Module width must be between 1 and 5 pixels

"; +} +elseif( $data==="" ) { + echo "

Please enter data to be encoded, select symbology and press 'Ok'.

"; + echo "Note: Data must be valid for the choosen encoding."; +} +elseif( $code==-1 ) { + echo "

No code symbology selected.

"; +} +elseif( $height < 10 || $height > 500 ) { + echo "

Height must be in range [10, 500]

"; +} +elseif( $scale < 0.1 || $scale > 15 ) { + echo "

Scale must be in range [0.1, 15]

"; +} +else { + if( $code==20 ) { + $encoder = BarcodeFactory::Create(6); + $encoder->UseExtended(); + } + else { + $encoder = BarcodeFactory::Create($code); + } + $b = $backend=='EPS' ? 'PS' : $backend; + $b = substr($backend,0,5) == 'IMAGE' ? 'IMAGE' : $b; + $e = BackendFactory::Create($b,$encoder); + if( substr($backend,0,5) == 'IMAGE' ) { + if( substr($backend,5,1) == 'J' ) + $e->SetImgFormat('JPEG'); + } + if( $e ) { + if( $backend == 'EPS' ) + $e->SetEPS(); + if( $pswidth!='' ) + $modwidth = $pswidth; + $e->SetModuleWidth($modwidth); + $e->AddChecksum($checksum); + $e->NoText($notext); + $e->SetScale($scale); + $e->SetVertical($vertical); + $e->ShowFrame($showframe); + $e->SetHeight($height); + $r = $e->Stroke($data,$file,$info,$info); + if( $r ) + echo nl2br(htmlspecialchars($r)); + if( $file != '' ) + echo "

Wrote file $file."; + } + else + echo "

Can't create choosen backend: $backend.

"; +} + +?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/barcode/demoapp/barcode_menu.php b/web/public_php/admin/jpgraph/barcode/demoapp/barcode_menu.php new file mode 100644 index 000000000..ea5030665 --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/demoapp/barcode_menu.php @@ -0,0 +1,125 @@ +

JpGraph Barcode 1.0

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Data:
+ +
+Encoding:
+ +
+Module width:
+ +
+Add checksum:
+ +
+Hide text:
+ +
+Show frame:
+ +
+Vertical layout:
+ +
+Height:
+ +
+Scale:
+ +
+Write to file:
+ +
+Format:
+ +
+PS module width: + +
+
+(If specified will override Module width above)
+
+Debug info:
+ +
+
+ +
+
+ +

+


+ + + diff --git a/web/public_php/admin/jpgraph/barcode/demoapp/index.html b/web/public_php/admin/jpgraph/barcode/demoapp/index.html new file mode 100644 index 000000000..e65107cba --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/demoapp/index.html @@ -0,0 +1,10 @@ + + + +Barcode SYSTEMTEST + + +; + + + diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_errhandling_ex0.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_errhandling_ex0.php new file mode 100644 index 000000000..4f5b5393b --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_errhandling_ex0.php @@ -0,0 +1,16 @@ +Stroke('abc123'); +} catch( JpGraphException $e ) { + //echo 'Error: ' . $e->getMessage()."\n"; + JpGraphError::Raise($e->getMessage()); +} + +?> diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_ex0.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex0.php new file mode 100644 index 000000000..021b5c7cc --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex0.php @@ -0,0 +1,11 @@ +Stroke('ABC123'); + +?> diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_ex1.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex1.php new file mode 100644 index 000000000..df7653b5c --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex1.php @@ -0,0 +1,14 @@ +SetModuleWidth(2); +$e->SetHeight(20); +echo nl2br($e->Stroke('3125134772')); + + +?> diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_ex2.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex2.php new file mode 100644 index 000000000..8fce58e62 --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex2.php @@ -0,0 +1,14 @@ +SetModuleWidth(2); +$e->SetHeight(70); +$ps = $e->Stroke('3125134772'); +echo nl2br(htmlspecialchars($ps)); + +?> diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_ex3.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex3.php new file mode 100644 index 000000000..a63f4ad43 --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex3.php @@ -0,0 +1,17 @@ +"; +$encoder = BarcodeFactory::Create(ENCODING_CODEI25); +$e = BackendFactory::Create(BACKEND_PS,$encoder); +$e->SetModuleWidth(2); +$e->SetHeight(70); +$e->SetEPS(); +$ps = $e->Stroke('3125134772'); +echo nl2br(htmlspecialchars($ps)); + + +?> diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_ex4.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex4.php new file mode 100644 index 000000000..721b56baf --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_ex4.php @@ -0,0 +1,12 @@ +SetModuleWidth(2); +$e->Stroke('1234'); + +?> diff --git a/web/public_php/admin/jpgraph/barcode/examples/barcode_usps_example.php b/web/public_php/admin/jpgraph/barcode/examples/barcode_usps_example.php new file mode 100644 index 000000000..80469beaf --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/examples/barcode_usps_example.php @@ -0,0 +1,74 @@ +_USPS_chkd(substr($data,8)); + $data = '420'. $aZIP . '~191' . $aServiceType . $aDUNS . $aSeqNbr; + return $data . $cd; + } + + // Get type 2 of confirmation code (without ZIP) + function GetPIC($aServiceType,$aDUNS,$aSeqNbr) { + // Convert to USPS format with AI=91 + $data = '91' . $aServiceType . $aDUNS . $aSeqNbr; + $cd = $this->_USPS_chkd($data); + return $data . $cd; + } + +} + +$usps = new USPS_Confirmation(); +$zip = '92663'; +$service = '21'; +$DUNS = '805213907'; +$seqnr = '04508735'; +$data = $usps->GetPICwithZIP($zip,$service,$DUNS,$seqnr); +//$data = $usps->GetPIC('01','123456789','00000001'); + +$encoder = BarcodeFactory::Create(ENCODING_EAN128); +$e = BackendFactory::Create(BACKEND_IMAGE,$encoder); +$e->SetModuleWidth(2); +$e->SetFont(FF_ARIAL,FS_NORMAL,14); +$e->Stroke($data); + +?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/barcode/mkbarcode.php b/web/public_php/admin/jpgraph/barcode/mkbarcode.php new file mode 100644 index 000000000..57ef6ec07 --- /dev/null +++ b/web/public_php/admin/jpgraph/barcode/mkbarcode.php @@ -0,0 +1,281 @@ +argv = ($_SERVER['argv']); + $this->argc = ($_SERVER['argc']); + } + + function PrintUsage() { + $n = $this->argv[0]; + echo "$n -b [-r -h -c -o -m -s -y -f ] datastring \n". + "Create the specified barcode\n". + "-b What symbology to use, one of the following strings (case insensitive)\n". + " UPCA \n". + " UPCE \n". + " EAN128 \n". + " EAN13 \n". + " EAN8 \n". + " CODE11 \n". + " CODE39 \n". + " CODE128 \n". + " CODE25 \n". + " CODEI25 \n". + " CODABAR \n". + " BOOKLAND \n". + "-c Add checkdigit for symbologies where this is optional\n". + "-o Output format. 0=Image, 1=PS, 2=EPS\n". + "-m Module width\n". + "-s Scale factor\n". + "-h Show this help\n". + "-f Filename to write to\n". + "-r Rotate barcode 90 degrees\n". + "-y height Set height in pixels\n". + "-x Hide the human readable text\n". + "--silent Silent. Don't give any error mesages\n"; + exit(1); + } + + function Get() { + $barcode='code39'; + $hide=false; + $checkdigit=false; + $modulewidth=2; + $scale=1; + $output=0; + $filename=''; + $data = ''; + $rotate = false; + $silent=false; + $height = 70; + if( ($n=$this->GetNum()) > 0 ) { + $i=1; + while( $i <= $n ) { + switch( $this->argv[$i] ) { + case '-h': + $this->PrintUsage(); + exit(0); + break; + case '-b': + $barcode = $this->argv[++$i]; + break; + case '-o': + $output = (int)$this->argv[++$i]; + break; + case '-y': + $height = (int)$this->argv[++$i]; + break; + case '-x': + $hide=true; + break; + case '-r': + $rotate=true; + break; + case '-c': + $checkdigit=true; + break; + case '--silent': + $silent=true; + break; + case '-s': + $scale = (float)$this->argv[++$i]; + break; + case '-m': + $modulewidth = (float)$this->argv[++$i]; + break; + case '-f': + $filename = $this->argv[++$i]; + break; + default: + if( $data == '' ) { + $data = $this->argv[$i]; + } + else { + $this->PrintUsage(); + die("Illegal specified parameters"); + } + break; + } + ++$i; + } + + } + + if( $output < 0 || $output > 2 ) { + fwrite(STDERR,"Unkown output format ($output)\n"); + exit(1); + } + + if( $output === 0 ) { + $modulewidth = floor($modulewidth); + } + + // Sanity check + if( $modulewidth > 15 ) { + fwrite(STDERR,"Too large modulewidth\n"); + exit(1); + } + + // Sanity check + if( $height > 1000 ) { + fwrite(STDERR,"Too large height\n"); + exit(1); + } + + // Sanity check + if( $scale > 15 ) { + fwrite(STDERR,"Too large scale factor\n"); + exit(1); + } + + if( strlen($filename) > 256 ) { + fwrite(STDERR,"Too long filename\n"); + exit(1); + } + + if( trim($data) == '' ) { + fwrite(STDERR,"No input data specified\n"); + exit(1); + } + + $barcodes = array( + 'UPCA' => ENCODING_UPCA, + 'UPCE' => ENCODING_UPCE, + 'EAN128' => ENCODING_EAN128, + 'EAN13' => ENCODING_EAN13, + 'EAN8' => ENCODING_EAN8, + 'CODE11' => ENCODING_CODE11, + 'CODE39' => ENCODING_CODE39, + 'CODE128' => ENCODING_CODE128, + 'CODE25' => ENCODING_CODE25, + 'CODEI25' => ENCODING_CODEI25, + 'CODABAR' => ENCODING_CODABAR, + 'BOOKLAND' => ENCODING_BOOKLAND, + ); + $barcode = strtoupper($barcode); + if( key_exists($barcode,$barcodes) ) { + $barcode = $barcodes[$barcode]; + } + else { + fwrite(STDERR,'Specified barcode symbology ('.$barcode.") is not supported\n"); + exit(1); + } + + $ret = array( + 'barcode' => $barcode, + 'hide' => $hide, + 'modulewidth' => $modulewidth, + 'scale' => $scale, + 'output' => $output, + 'data' => $data, + 'silent' => $silent, + 'rotate' => $rotate, + 'height' => $height, + 'checkdigit' => $checkdigit, + 'filename' => $filename + ); + + return $ret; + } + + function _Dump() { + var_dump($this->argv); + } + + function GetNum() { + return $this->argc-1; + } +} + +//---------------------------------------------------------------------- +// CLASS Driver +// Main driver class to create barcodes with the parmeters specified on +// the command line. +//---------------------------------------------------------------------- +class Driver { + + private $iParams; + static public $silent=false; + + static public function ErrHandlerPS(Exception $e) { + if( !Driver::$silent ) + fwrite(STDERR,$e->getMessage()."\n"); + exit(1); + } + + static public function ErrHandlerImg(Exception $e) { + if( !Driver::$silent ) + fwrite(STDERR,$e->getMessage()."\n"); + $errobj = new JpGraphErrObjectImg(); + $errobj->Raise($e->getMessage()); + exit(1); + } + + function Run($aParams) { + + $this->iParams = $aParams; + + Driver::$silent = $aParams['silent']; + + $encoder = BarcodeFactory::Create($aParams['barcode']); + $encoder->AddChecksum($aParams['checkdigit']); + switch( $aParams['output'] ) { + case 0: + $e = BackendFactory::Create(BACKEND_IMAGE,$encoder); + set_exception_handler(array('Driver','ErrHandlerImg')); + break; + case 1: + $e = BackendFactory::Create(BACKEND_PS,$encoder); + set_exception_handler(array('Driver','ErrHandlerPS')); + break; + case 2: + $e = BackendFactory::Create(BACKEND_PS,$encoder); + $e->SetEPS(); + set_exception_handler(array('Driver','ErrHandlerPS')); + break; + } + $e->SetHeight($aParams['height']); + $e->SetVertical($aParams['rotate']); + $e->SetModuleWidth($aParams['modulewidth']); + $e->SetScale($aParams['scale']); + $e->HideText($aParams['hide']); + if( $aParams['output'] === 0 ) { + $err = $e->Stroke($aParams['data'], $aParams['filename']); + } + else { + $s = $e->Stroke($aParams['data'], $aParams['filename']); + if( $aParams['filename'] == '' ) { + // If no filename specified then return the generated postscript + echo $s; + } + } + } +} + +$pa = new ParseArgs(); +$params = $pa->Get(); +$driver = new Driver(); +$driver->Run($params); + +// Successfull termination +exit(0); + +?> diff --git a/web/public_php/admin/jpgraph/flag_mapping b/web/public_php/admin/jpgraph/flag_mapping new file mode 100644 index 000000000..7f9c3c5fa --- /dev/null +++ b/web/public_php/admin/jpgraph/flag_mapping @@ -0,0 +1,237 @@ +class JpCountryFlags { + +$iCountryFlags = array( + 'Afghanistan' => 'afgh.gif', + 'Republic of Angola' => 'agla.gif', + 'Republic of Albania' => 'alba.gif', + 'Alderney' => 'alde.gif', + 'Democratic and Popular Republic of Algeria' => 'alge.gif', + 'Territory of American Samoa' => 'amsa.gif', + 'Principality of Andorra' => 'andr.gif', + 'British Overseas Territory of Anguilla' => 'angu.gif', + 'Antarctica' => 'anta.gif', + 'Argentine Republic' => 'arge.gif', + 'League of Arab States' => 'arle.gif', + 'Republic of Armenia' => 'arme.gif', + 'Aruba' => 'arub.gif', + 'Commonwealth of Australia' => 'astl.gif', + 'Republic of Austria' => 'aust.gif', + 'Azerbaijani Republic' => 'azer.gif', + 'British Antarctic Territory' => 'bant.gif', + 'Kingdom of Belgium' => 'belg.gif', + 'British Overseas Territory of Bermuda' => 'berm.gif', + 'Commonwealth of the Bahamas' => 'bhms.gif', + 'Kingdom of Bahrain' => 'bhrn.gif', + 'Republic of Belarus' => 'blru.gif', + 'Republic of Bolivia' => 'blva.gif', + 'Belize' => 'blze.gif', + 'Republic of Benin' => 'bnin.gif', + 'Republic of Botswana' => 'bots.gif', + 'Federative Republic of Brazil' => 'braz.gif', + 'Barbados' => 'brbd.gif', + 'British Indian Ocean Territory' => 'brin.gif', + 'Brunei Darussalam' => 'brun.gif', + 'Republic of Burkina' => 'bufa.gif', + 'Republic of Bulgaria' => 'bulg.gif', + 'Republic of Burundi' => 'buru.gif', + 'Overseas Territory of the British Virgin Islands' => 'bvis.gif', + 'Central African Republic' => 'cafr.gif', + 'Kingdom of Cambodia' => 'camb.gif', + 'Republic of Cameroon' => 'came.gif', + 'Dominion of Canada' => 'cana.gif', + 'Caribbean Community' => 'cari.gif', + 'Republic of Cape Verde' => 'cave.gif', + 'Republic of Chad' => 'chad.gif', + 'Republic of Chile' => 'chil.gif', + 'Territory of Christmas Island' => 'chms.gif', + 'Commonwealth of Independent States' => 'cins.gif', + 'Cook Islands' => 'ckis.gif', + 'Republic of Colombia' => 'clmb.gif', + 'Territory of Cocos Islands' => 'cois.gif', + 'Commonwealth' => 'comn.gif', + 'Union of the Comoros' => 'como.gif', + 'Republic of the Congo' => 'cong.gif', + 'Republic of Costa Rica' => 'corc.gif', + 'Republic of Croatia' => 'croa.gif', + 'Republic of Cuba' => 'cuba.gif', + 'British Overseas Territory of the Cayman Islands' => 'cyis.gif', + 'Republic of Cyprus' => 'cypr.gif', + 'The Czech Republic' => 'czec.gif', + 'Kingdom of Denmark' => 'denm.gif', + 'Republic of Djibouti' => 'djib.gif', + 'Commonwealth of Dominica' => 'domn.gif', + 'Dominican Republic' => 'dore.gif', + 'Republic of Ecuador' => 'ecua.gif', + 'Arab Republic of Egypt' => 'egyp.gif', + 'Republic of El Salvador' => 'elsa.gif', + 'England' => 'engl.gif', + 'Republic of Equatorial Guinea' => 'eqgu.gif', + 'State of Eritrea' => 'erit.gif', + 'Republic of Estonia' => 'estn.gif', + 'Ethiopia' => 'ethp.gif', + 'European Union' => 'euun.gif', + 'British Overseas Territory of the Falkland Islands' => 'fais.gif', + 'International Federation of Vexillological Associations' => 'fiav.gif', + 'Republic of Fiji' => 'fiji.gif', + 'Republic of Finland' => 'finl.gif', + 'Territory of French Polynesia' => 'fpol.gif', + 'French Republic' => 'fran.gif', + 'Overseas Department of French Guiana' => 'frgu.gif', + 'Gabonese Republic' => 'gabn.gif', + 'Republic of the Gambia' => 'gamb.gif', + 'Republic of Georgia' => 'geor.gif', + 'Federal Republic of Germany' => 'germ.gif', + 'Republic of Ghana' => 'ghan.gif', + 'Gibraltar' => 'gibr.gif', + 'Hellenic Republic' => 'grec.gif', + 'State of Grenada' => 'gren.gif', + 'Overseas Department of Guadeloupe' => 'guad.gif', + 'Territory of Guam' => 'guam.gif', + 'Republic of Guatemala' => 'guat.gif', + 'The Bailiwick of Guernsey' => 'guer.gif', + 'Republic of Guinea' => 'guin.gif', + 'Republic of Haiti' => 'hait.gif', + 'Hong Kong Special Administrative Region' => 'hokn.gif', + 'Republic of Honduras' => 'hond.gif', + 'Republic of Hungary' => 'hung.gif', + 'Republic of Iceland' => 'icel.gif', + 'International Committee of the Red Cross' => 'icrc.gif', + 'Republic of India' => 'inda.gif', + 'Republic of Indonesia' => 'indn.gif', + 'Republic of Iraq' => 'iraq.gif', + 'Republic of Ireland' => 'irel.gif', + 'Organization of the Islamic Conference' => 'isco.gif', + 'Isle of Man' => 'isma.gif', + 'State of Israel' => 'isra.gif', + 'Italian Republic' => 'ital.gif', + 'Jamaica' => 'jama.gif', + 'Japan' => 'japa.gif', + 'The Bailiwick of Jersey' => 'jers.gif', + 'Hashemite Kingdom of Jordan' => 'jord.gif', + 'Republic of Kazakhstan' => 'kazk.gif', + 'Republic of Kenya' => 'keny.gif', + 'Republic of Kiribati' => 'kirb.gif', + 'State of Kuwait' => 'kuwa.gif', + 'Kyrgyz Republic' => 'kyrg.gif', + 'Republic of Latvia' => 'latv.gif', + 'Lebanese Republic' => 'leba.gif', + 'Kingdom of Lesotho' => 'lest.gif', + 'Republic of Liberia' => 'libe.gif', + 'Principality of Liechtenstein' => 'liec.gif', + 'Republic of Lithuania' => 'lith.gif', + 'Grand Duchy of Luxembourg' => 'luxe.gif', + 'Macao Special Administrative Region' => 'maca.gif', + 'Republic of Macedonia' => 'mace.gif', + 'Republic of Madagascar' => 'mada.gif', + 'Republic of the Marshall Islands' => 'mais.gif', + 'Republic of Maldives' => 'mald.gif', + 'Republic of Mali' => 'mali.gif', + 'Federation of Malaysia' => 'mals018.gif', + 'Republic of Malta' => 'malt.gif', + 'Republic of Malawi' => 'malw.gif', + 'Overseas Department of Martinique' => 'mart.gif', + 'Islamic Republic of Mauritania' => 'maur.gif', + 'Territorial Collectivity of Mayotte' => 'mayt.gif', + 'United Mexican States' => 'mexc.gif', + 'Federated States of Micronesia' => 'micr.gif', + 'Midway Islands' => 'miis.gif', + 'Republic of Moldova' => 'mold.gif', + 'Principality of Monaco' => 'mona.gif', + 'Republic of Mongolia' => 'mong.gif', + 'British Overseas Territory of Montserrat' => 'mont.gif', + 'Kingdom of Morocco' => 'morc.gif', + 'Republic of Mozambique' => 'moza.gif', + 'Republic of Mauritius' => 'mrts.gif', + 'Union of Myanmar' => 'myan.gif', + 'Republic of Namibia' => 'namb.gif', + 'North Atlantic Treaty Organization' => 'nato.gif', + 'Republic of Nauru' => 'naur.gif', + 'Turkish Republic of Northern Cyprus' => 'ncyp.gif', + 'Netherlands Antilles' => 'nean.gif', + 'Kingdom of Nepal' => 'nepa.gif', + 'Kingdom of the Netherlands' => 'neth.gif', + 'Territory of Norfolk Island' => 'nfis.gif', + 'Federal Republic of Nigeria' => 'ngra.gif', + 'Republic of Nicaragua' => 'nica.gif', + 'Republic of Niger' => 'nigr.gif', + 'Niue' => 'niue.gif', + 'Commonwealth of the Northern Mariana Islands' => 'nmar.gif', + 'Province of Northern Ireland' => 'noir.gif', + 'Nordic Council' => 'nord.gif', + 'Kingdom of Norway' => 'norw.gif', + 'Territory of New Caledonia and Dependencies' => 'nwca.gif', + 'New Zealand' => 'nwze.gif', + 'Organization of American States' => 'oast.gif', + 'Organization of African Unity' => 'oaun.gif', + 'International Olympic Committee' => 'olym.gif', + 'Sultanate of Oman' => 'oman.gif', + 'Organization of Petroleum Exporting Countries' => 'opec.gif', + 'Islamic Republic of Pakistan' => 'paks.gif', + 'Republic of Palau' => 'pala.gif', + 'Independent State of Papua New Guinea' => 'pang.gif', + 'Republic of Paraguay' => 'para.gif', + 'Republic of the Philippines' => 'phil.gif', + 'British Overseas Territory of the Pitcairn Islands' => 'piis.gif', + 'Republic of Poland' => 'pola.gif', + 'Republic of Portugal' => 'port.gif', + 'Commonwealth of Puerto Rico' => 'purc.gif', + 'State of Qatar' => 'qata.gif', + 'Russian Federation' => 'russ.gif', + 'Republic of Rwanda' => 'rwan.gif', + 'Kingdom of Saudi Arabia' => 'saar.gif', + 'Republic of San Marino' => 'sama.gif', + 'Nordic Sami Conference' => 'sami.gif', + 'Sark' => 'sark.gif', + 'Scotland' => 'scot.gif', + 'Principality of Seborga' => 'sebo.gif', + 'Republic of Sierra Leone' => 'sile.gif', + 'Republic of Singapore' => 'sing.gif', + 'Republic of Korea' => 'skor.gif', + 'Republic of Slovenia' => 'slva.gif', + 'Somali Republic' => 'smla.gif', + 'Republic of Somaliland' => 'smld.gif', + 'Republic of South Africa' => 'soaf.gif', + 'Solomon Islands' => 'sois.gif', + 'Kingdom of Spain' => 'span.gif', + 'Secretariat of the Pacific Community' => 'spco.gif', + 'Democratic Socialist Republic of Sri Lanka' => 'srla.gif', + 'Saint Lucia' => 'stlu.gif', + 'Republic of the Sudan' => 'suda.gif', + 'Republic of Suriname' => 'surn.gif', + 'Slovak Republic' => 'svka.gif', + 'Kingdom of Sweden' => 'swdn.gif', + 'Swiss Confederation' => 'swit.gif', + 'Syrian Arab Republic' => 'syra.gif', + 'Kingdom of Swaziland' => 'szld.gif', + 'Republic of China' => 'taiw.gif', + 'Republic of Tajikistan' => 'tajk.gif', + 'United Republic of Tanzania' => 'tanz.gif', + 'Kingdom of Thailand' => 'thal.gif', + 'Autonomous Region of Tibet' => 'tibe.gif', + 'Turkmenistan' => 'tkst.gif', + 'Togolese Republic' => 'togo.gif', + 'Tokelau' => 'toke.gif', + 'Kingdom of Tonga' => 'tong.gif', + 'Tristan da Cunha' => 'trdc.gif', + 'Tromelin' => 'tris.gif', + 'Republic of Tunisia' => 'tuns.gif', + 'Republic of Turkey' => 'turk.gif', + 'Tuvalu' => 'tuva.gif', + 'United Arab Emirates' => 'uaem.gif', + 'Republic of Uganda' => 'ugan.gif', + 'Ukraine' => 'ukrn.gif', + 'United Kingdom of Great Britain' => 'unkg.gif', + 'United Nations' => 'unna.gif', + 'United States of America' => 'unst.gif', + 'Oriental Republic of Uruguay' => 'urgy.gif', + 'Virgin Islands of the United States' => 'usvs.gif', + 'Republic of Uzbekistan' => 'uzbk.gif', + 'State of the Vatican City' => 'vacy.gif', + 'Republic of Vanuatu' => 'vant.gif', + 'Bolivarian Republic of Venezuela' => 'venz.gif', + 'Republic of Yemen' => 'yemn.gif', + 'Democratic Republic of Congo' => 'zare.gif', + 'Republic of Zimbabwe' => 'zbwe.gif' +) ; + + diff --git a/web/public_php/admin/jpgraph/flags.dat b/web/public_php/admin/jpgraph/flags.dat index 87e33ac8331428191055751092d1245d852e19d8..1cd2e72345fa62b81201376256dc29a708c54347 100644 GIT binary patch delta 7793 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 P#5_REyInSuPi`szcV89q diff --git a/web/public_php/admin/jpgraph/flags_thumb100x100.dat b/web/public_php/admin/jpgraph/flags_thumb100x100.dat index a1014f085280b4ffb508a6356e80c2ae5c6849b2..545e7ade5805e60e3ee1eb23e5c93f4b1aac78d4 100644 GIT binary patch delta 3126 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 diff --git a/web/public_php/admin/jpgraph/flags_thumb35x35.dat b/web/public_php/admin/jpgraph/flags_thumb35x35.dat index da7ffa0145dc8712c06147183879c0d54e307df9..7335011ec99e98dba5d52d6a02a5e0453d69cce4 100644 GIT binary patch delta 818 zcmV-21I_&BgAJyN4FzF3GcYr;1;KP3b7gX3B0FI^GCF%{IxstFIyX5nJ83#GJ99cW zIhXM>11En8a7bBm000180001900~M>!2kdN33hNnX8-^IBLDyZ7XXoIP6q%00<=j) zK~zY`y_HW$R8bVh&pG#wzWL{bX8uWW9H-PIA~Y8w8YQ@>Ad)aEs7;GD1?^k6Yaz6W z)-9qUY865l8Ke`G=0bup7-w__N5+|E<~i@Zds=@)T8^W=A^W&I9-RC5z3;o{-iyRg>HjG4q_LN&%x62hC@3l?g@$eTdf|A6LY+h;KZEj(YUV_c8H<4 zC&7O#w#r1Y;+c=u(eLFWSxZ}%0bYxbi5U;FBH*8<|5}P!$=BXM-dj zDl_!~lPMXF>d94{m?Xn6BQXF60Nd+x04W7YNt=2P8Pk!4^z-{Bo0zDw+JaU*0p{n_ zvrr~lCmjK{bwn^of%4w%lNO7D64ZZsrH39;a?N$l?v@!=D8 zqjLx)2YZ{PqpYx|I;$hI@6zEHvZHJjgb*DEc~bM%o@u{2Og^7ol4ayEm&<9Iwq@Cf z##TljWWUT)bEBFMy8`~oo7WumHFhxokk|F?NC3dhW^~C)t_q(|?yp5G@xt7h^skiH w^%Adu67;`Fh|)BS{O*Gc!}tMHJUY`&p@G(y0a^hTgUED;$aDd>$aDf9&AvW+n*aa+ delta 29 kcmZ41#rwROmo?GK*uZEb>%o#{){1u43dZfM6-BO<# z%)Z6zaYCUH0FfhH85m0+`CV36bb0 ze?_{_CDD}N6P(c#-pNg}a;!1lZZlQ~tN1~0O>3}pTr_2{EY?@UnX&qj?1e*eN!W-! zW9?`%e>m!1`xvaM&;I-o?=ZBAS-GZtmw0ezU>+z3&f( z&ICnlP6T@L&-&+&mOy9(Ur4J;|0MwryKC;+RZ1`f-|XAreC5^?o&+813oE96Bm$ zrrr4Egu6V#ii3%+ZmZ|I`_bj8U3r*X z{FPqWnWT&BRP_`}iM6Xa-uj(g(IyWh>V8Z;5{{xvm4{N?yDkFVqNP~$s8QkL^u+8Yn$hR`M4TKe0FX{53r3HHOs37YbLP1V zGM(l{0e#j?Jz7f*EXUX3w}k!=Bb`kCFaMg}Mc+l=X)z(uJeSR;9Ucd_H_UAI5A*Yi h|D9n6K9dpQ7K296hepr=hepr>hepr?w?@zeY~&>)&?W!? delta 37 qcmZ4cRczBsG1f#YV*{g&to9e0?XR`lUt?+E}Z><{<= diff --git a/web/public_php/admin/jpgraph/fonts/DejaVuSans-Bold.ttf b/web/public_php/admin/jpgraph/fonts/DejaVuSans-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ac313d269caed984fa1bb5c811330546e1249a25 GIT binary patch literal 634184 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

%kztcV#zk}e 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�)&bU0HSU>GA}oHha} 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 z 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 z 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 zⅈ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

u6JTv0Tn6OB===ZNx1nSC-ZzjP2L- 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 z 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 ~u)_bK}Pg4}4??MlNhO;bvdi*^ledba7{ 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

t^u_5RHBh!i1(o`7<dOrQH5;as%Dc? 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�dCRp=zUF}_`)_2m^bu*fSoS28eGIQ1 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�XLWN^w!@- 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

dt+%8+82Xh+<7?Ar2r^hMNkz4)aXqMA(1Iro1 zwD;Kh`*P(}HbtrSy`%&7HMeE%L2vb{?~Bb4`+|shGg{{N<6R73a#@G z{96aDoAK}T7DOXpLUlLm^}4pRp@RRVJ%{#?4O0BBMNY`8kpuS?ZMn&MwUiao%nV8M zYA$3dog?Ar_o){SBO0ga#ab%k|LA*Ay9T!-EMnJ9)doOu^wrjASJ$%bI>`RFB3 zzTe~b+wv0NT0Z8(xG9IKljbV53A~C1A)YU$5q}RNea~*g9oVI>v%Py1kNk@72Z++w zlvv*n@+1CH{(B(rk)vL%Lk?62ZdoX%y9JO%q6le6$~=&R#x(<7aM*=MMCsCsY?W1z zw8X{M9c@USf$UXk`;FadR@Z7z^w>G-F!nl1d#I8z~4>q<6?)l z%s%q|0lnw-=|8&f`9p{G9i^od=Py~De@ktCK8{Ss;%3Uud3m*2DRBwD3q3ARnle1K zVEMOSUW)~QFgPIw5EPSn@?<)3f&ZvmjuQcfv3{$($_8m$%}mPvMR7@0gq4X(%NzVF zfRhQ6Vv`2e{4Q15E>HaVkeOIn8+&ifWrMqAD>r0!TPfcoaN_HztXz5Dz5OqrISX8l zTtww=8$MSPLL}BD1^WlRY`@fG&r+)PEDJne@S~dAsIlhjEWzE8iDP z_2>POy*f)~%HD_jSIeq4HF3hiwyjtv7Kv*)&(}WuFI%u!`$+roH|)I^zH-x?pjBCg zasfs1ox+4~Fawqak$4mQAd)X36OtbN@joKx`TuHrf(8oS zqj7!9;e#gObC0rnd1(JDftFO3$oh9{*{5LDf3^=B$_5XZ#cr$bTM{>7n_6;o?BvPs ztJgI2-!u_sE%*!YI9Gwca$%cxpj!ZO0}{!*q-6fvN)RKZ5;w96Xlod;d{Lq0pBMoV z>YlU_ADiUTiB`Kx9w#U&eWBr#e;+d6*ZjU0vl1@KC7Pp1a9?QRpPJ*WZ zJK2!IJXOGXN?%hu1)h?LC2A@0HsyRWIEv3l$eV@eGYTi?(nt=An}UQS_9T(_l-tO{ zlP}Y+NT90`R+e2^hW~5Ji{{TSVjq^ZoIk&%c?XbjBSOQUqoR~&qoRCsl=&HLmuvaU z+bY9+x2CsU!9H3JwPckI0bNyqp$hT|b;Wg+&{mZ6hry$Ra3ak>$_n@FZMCW^d5s~L zeSf(@US^TYn~@*h39+o-b-*4HVwsfHO8+IczDK>V*!P%X*&?@0*n;I$4(D54Mv?0g zET@7p@00rQcQr&4l*SF3!z!Lkg;Bft=bx0@EMmx4YU}IkYZXP9Kj3-g6VOn>ZXPZb ziUiWKSRyG25RhHrtJXRl9-E6?gzyy^GaR>6?9f0#Z^aaAy zdoXAvnXtniI~y<}JqS8~tG=9X0!#kHJj z$BgbZATO@{z3U!)sQ`P9XwQSP8u!NWI|~X5E5S1MB-mz&Bvi2X0h)yp9Kq<>*IHS{ z#;>ECd$MBU3v1a3nyXJ9`@+^soovk2 z0_?0nTeQkf;x*Z@|AhRaL`pgAXCWn&^H=>tdyLC}HiG0o8!?_%oEjH#_?E&rIYy>WWoLGx(vio)7`bO}pn(zgb zul)!9Ew|SZkWg~)Q;?I!@IQ?HC`4cW{r##Rd{gmD`$i6B=(*dFKmTfyv=wTZ>8>^77Zq`6wckXx^= zs~bJEjpA$g=uTyAt?zbaRzs)Pmeig|Dv_>8sCk| zzx`LpH#QuRZ}hLzA*%&FYLz~5q?(^#YV(? z@(1z0$aq$7;?MA?_3!iebF0Ajh^?SLVp;n4xEm7BaJ%q)I|hP#v$6kdCp}XPgVpi( z5Tbhh+58zXKfQhN3=2;@(>(xauf%w^A!dc=4*Z$mr#rEYyRd0|xWfj|@Ne+_W!g{r z`|`l|BlvslbHw{q&?oov?>o}7aeptq$85y=t!Td$uiuG3oA|8a&+sc95ApY%`7?N) z?#9ITUFey7H}xz24Bd|Q#^b#h4{G9>e6qIuK0~yG=V$Rud*kgS&+v?#!sK({`2yov z9n0VM2|O?3@B8v+U`_sszwamBgD1!G_x<@ZWUsidm$GQ0{g)v%`59ZfAsz63ME7y< z?*|6zZ{p8`jQVmFJtuB8-a9gQ`$LRpRPg7q z{25eHuj0?+M1Axx>Vq<z$-$$xh>^nIpqPe>!lF?PmvWDT#|a z`axWr`rmb0vDOy%vPg5#A^G{p;V<+eznKh9g{`7M?zm?v>)&vY_1ErXGxS&i!fOZ( z_N@i!NnWhP_jdtS7e&7+b7*%H!dpeOMKTu2{_=5e4E@VNGNiJjgtugmG%$&^nw&de zZm+4z*xoDO(Y|8JwjWtm$RVXV_^K3j{^r_e z|D^p@t(tjw@6^XOuGf&>-6o$m^+ncV^9F)Pkv0K$mjRx9$Og<_8}@i{C*55rwmFkI z6vrx{hyfR!<-o~}3TW)Yq84z9afY(ZbNh34KXTFFjy?A7?^4=%z@`tLj?Ok|b@7j$1v!i>tyUcdZn@^;T`?N87f1w8!D! zZ_d3_dw*ijng3xn?fWCRl=3?^Wd1Z3%~Hm*Jx^)twY&|bE~k=f_sDCz&W`TbR-2xr z{Yz`FeGC5mi2aUu?K}YVKF1?;dq6iqF>TOd-e*5HysvKXf29qVQ~k+0v(_Sby8w7| zV6X9K&?z*IXz)fWNb)LbuYgYfNeIl6>+Go@8!eyiy~pM}&KlV`JJHcYCaX;!Z3}(a zHa(K7jDE-A*yVqAQciJk_JHL`Fv_0S)-7LuzxH3m2mkxPx?K(jtLQMl1O6|$w4~%x zW-rd3JSnHP|F@qHl8dyT2ByU`UwoSXpq%~W@~8IgdusWU*(~qXTR!;u>kn>u)jwCB zKIrprr`YZCMu$Vb-@gyPOB^|x8lN_hIR~a;M6)rr2dp#_qQNRG6h03Si-xrc@{|#c z*d2TJun&W2#99-LaHEs!2+P5(rcc+xF0r`RRzuS6u@$99kZa!w?67b4p1 z9hL-9Q=pB5EF;}^3)gKPF5CVFnvLbU2!1QxZ^Uzd{vLKXp7r?(*_p(jiRm8X^^^JY zy=bqNKd12LTkyP*e-F8c?>D2qur*TovrcEUm&Tu0p#CaeKOKA^ORq~8MCRDKKvFm` zd&mjF479bo`R0bZBF3;u@-AP#`k#guQ3A>6F2WBvny*KUx%s~@D<9l^0oA@) z`N&tWR^H`@CICH*?gNzOQv=7^1hu=<75VJu?iOZduT$rDdihQ!})RcZH zE#h52-(hqk@5)b3jd!_R>B;#8^or{EH-~m^v-DjI`BzS-H|daUQDGwx8WnTEtS~vB z4A<$afH6KU&YhNAK>q?HX~{>O2B55m3)htNO=;obFQ^KV;ksS!^yI#J?UX(#smQ8( zBm{W71@<(vIxRTe@-a; zqi+k~i8-y!9%ty_MT2J&VZ)vWJ7b(QNt%YybF!Huq#gW4g;FD8QgOanSKx?O7A=Uw zBjH)kUPR0!s1x8XIiBch@*2JNf84kt(i=6Z=lbaugB_H;oB_ZSz>Cfk{%->R6zmc7 zHc%uFZ~Uq6z7VFtd~-I!-Nn+S(jsZ`nZuqfEdGP$bMqrr`!BG6d`+1hM4B2W|NjC+}T$6#Jh$swTvMT4v?9hpuOvMr}EeftHQ(-%-4e4i9 z&5Guk4V)Rm=T=eXc(CylFKAq(z13eAu0V7$Bo}kLQ{|EUlOX5tPt0jU_BAf@UlZor zqv?T}Fw77HTz2AnkIVlrnmmo+5MqMr=aUo?b1X11xOAntm}b@^xWZNQeb#8gnEHwC zL&?BNQmd3Xj(U>!5c3%WOo3=~yZo9lwkB#PnBxI{NyKWPp`T0wTY5*{yOZfmd9PJ+ zkOXtP)Y=oylCY2x0Zy)4P5nf$_k?fUpEAZsnsNoQ8`zjoO zubxmrg&nB&+f!A}kh4}DReT&B^@}iI3Wa7w%PHvcrlabV6?|hIHBVX~EtIZ0F8`Qw zg0sk((EH(7O_|VG#k-ox76^-H)~>OZZ(akz)KP|QHBY)uS}m=m+!Du`y=MsfO|Tn& z9ip7XmiRR&)g%KW(xNZOz8Hmg)iP;=bf;F zlFy(m5|+MCpCk5()ke^72Zi=AX=>4@LT`i`lU8-AUK;9axKsU)Hx@bCJj0e@)useA zJe#mij_+_I(+WG&3_s5B{X3a9f(7u#{=fPQ26&QKf%Z((#vGOlLSqV9O~i)PK1d4K zc7r6ua~f&)rrJWk1Sh8wt7s~sPC2I0WaOFlK@#`>MeJi5w-3THhTVcxQ^;8gEe?Os zdJisA<}780>5erb5q-H_x-m$@a662nPlR7M+D(JE zQS^nXTFeXc^Apm8s#(Zr(l#WZz~h6$FysF;rfEowhTaM36;#U-q0yef8*8u*EmUWJfT1lmr^&_0Px*VI{Pp>sfuoQ6T(6f-ZF_8b*qHLipmSO)DI$D4jDJrksB z%&BvhY`_t`Od$wD=BI4a&v-FSRqZ?P0<;d|d%c zJl25tiH*;nA&?PyLu`v=JV{0uiwF~R4`+{BV>Yy|FdBP7CX-Ee`lD}(JPc!eHyJ7F z0UGyl7sSGu=}pDdEn(;qYWFr?R~RiBdZrn$XHoH1x1domw;F;BhSR~ReN?!SpE!_s zI*9iF^EBd(rd=lH?PzJ9zOryjbMS8?R5$WUOa;=Y?yo?WQ!uofom8i4e21~oh;|}s zgRLB=FMY)7fJvd|vhtd3swsO(TGO(OWzqh$>^pN&^>paGxN+>`G_1Q&D;}h^*l31* zE@=OR^t9xacAm@BKhrv``I+J*M*q3PDNXSMB<#&H?0dmGqj0uyCHC_^ian#RVjuBa z&A~l6W(>p>AZN=*I30Cv>vy&T$*03#=SaBOvaT5%|FNzOnZcW8jQy~eO%;JiGq>!a zA+QC9|I>JBjp*pr;2nq7a{2yaM6fL$JQ@CumBt=|j@a8h87rDP)-28w zpKVsX8a60)ns_})NZe;Pu*r9&ohGU+f%5>RLj4DMUO>?{2N8gC(;g0vuP^57n5Ino zW&T7cF`CPe3L8B3pV-w1p;90w7TA<#5HVy*7!jjJ^<1YMxwnw7Iig@RXUw=|XpH|B z2{v&fALF$AkzbXpr{JpmN~Atj2d25nZ^kVRn^^4cyhvFeK7%lEc|-QTheDin#&YmXUU&BQ|x&5*JsWEf1VR7InB+o7T-kV0Lj7m&4D;e zfxVX26Fg^%Q-sXq6T#dZP#8Eb)cj-=axHjkcF3uuX2x+iNfhj#h;vW0_o)`=FarB5 zt**&Q-NNQFPr?)AmpP2h;EIGJlf{t~J&=QQ0#C9z43@COv-&2+zI=mrw5Q@+^De{F z^xW_{!x8#i@k7HBAHJ#SpM>*G$v-(M2bikAQQbzXWxuZM4a*kigwNV!Ryjxf*s$yq z8nZXfE*ie=J7>;6`8B-T@S>*q-IFuv^M>QI|66`=Sk9A>2Q+xSsIhPS^_k;7!5Qa} zP1F2LDH!Ltn{a*|W44(&H5@CQ4Vx=Az`Muyt$z;Eyrzo%AM>um%h>-#pF6B1{$KRN z!_6|Qk0^ZeT&c4(M4B#LE!`U8opXEBa-utl8>3~Oji=O3&>EKT@vD$? zYlgH`s*@fzG_92|oGw9T+POj4leqt9liW=T3Y<+Q2=Nz#TH_A2Tpw(fUXb=Tg_BIP=>Il*okB?BoMX9D4OE<6 zHVorOiuL)$uuB9VersqqliQjrKz$CX$L9AW&G5$Aoll%{Hd^oo*G2J~z zhJ20|Yrz!iRu9uG4ewtHpE1P0Jhl8}0+!GdhD`%TBs-(I6_OUMk*mvnXaTjEU5kI- z)L6@2W5a7uezbl;o-EIA*0{*OG|abVel*J@G3uq54tAhO+sj)v@}~V#|N6EtUn{}! z7t}Z#nb|^T4Mr@$u)6gDGz7eQDhYSMKg6f!ABIU60ACI{QMCly^Nx9XPE?-j9jW;L zX5>Ou95>&rPCxQ{)K!A&Vh+&_Y?b)I4I(+O2j@d^%scY?o1Hy;MK|-DsCpkpUKHG+ zK{rx};ES-NI7>21gG%o(L6=6-#wH>kK?h{*GtIt{Pe$*X^kRGDXh%M8OT>{+3ITy- zUDC35!wM4i?4MeC)2jnR3D8jPf-T~qnN)2*nUEumcmQ^*e`JN;ia-nad{A87S_*&3 zm`>G@H^*s)pjaseACg~{=lwe2;Bj`@LN{wpR8uZn3<@bMKgFAM1&O(cwelWsq7mz< zg96+4n`6^OsG%swni03au63HSp($78+{P9CTH|^y#{w(g;Cx01?hIQ{pLZsI2%U5K z*i*vdzoT{XG&540Vv96CqUr2?qjTw2d4qErI_?|WA5uX`W;xD%qEN)iOv1R#s$$|g zsIoXGQ)#j_74qCO-5Ckg!1tn}CHNN0P}52dW&gQw1Z#a`*+6PPR9uu98{900hyT&W zSy+=B7s)Hbd~5sMI$w|zH85X{oTw&>Pe(o3<`BCW0Eon?vTW_!s-KKls&$rHdiR`s zj)m2krX6JpM6H_ZK-)IiFhHSI(kV zKxLC@E%m|=FszISwQ-u7HH@7&roj3&4G%mgsy9{lP18eMqpX0GaZ!C;qHJMBycXB)Gv{8Dh=GEz-`4lX!rlX#64Fq(I^*$Qf z({1%l&X^tcOK8%}VTI6GO;f4V{GkRjrt=F(M|-qFXlKNJM1EA$K4@0zHNlQMi$raT zd3W{*eG-$e>D0$L9-a1$V^2Ik>bVqu`X%geZp5mZ${}Yxrqy(gv92))U(m>p8rJx- z_z_kEh1dP1HfK}QbvDHeW&OhhaKgEW!M3S2eiNJ@^|VLd1bG1T79G|cvo&;WqM5nm zOfF%Z3D%+e0zzz)S-2&JZdP6+-G}=o-e|m9)f`re)erjhbhw3=nnORE{?V^x5rnW8 z?^f(-3P2F5Hgr2nY+Bbvd|SWUr$quho!gae}wZrk^A)jhW8nMYKLWpbHpb#8N`%2 zCWn}1=Y*dcmUS%thq0Cue6I)PJ`I_p|ChYi@H}PlLz+VqoME3f9G8VSA^}Ze?1l~` zJhOTS@Emx>lN`SckywGYjnBijZFC$qIu@SwEdGeWd)9q^bT0_yK0QO+XZ3*32^*%F znKB&LoCS-h`59F(Q%FWv^Z4qo#J$K>b5dU#xljMU@TScfYMDs?lRkF1N%cSIcOOSy zn|tcRyv^k*a?m-)R?|a#egCTqe&6^EE<%LF-iE@}Kg#Y(0|FcyagK zAa0Xf{59aJKo#T)(o$9)j|po}80@(c1Sp%wDG&mN>^)?i9imXO#`jbuGh> z443=Vv{HHW@{B|=&JEsdW=}FSym1z}wfVhC^MvAAWnszcPl`Q?#y$XAo82zGDSaya zr*SldGhDO8;4RvmH+npkZpvz_Id7JR8uKD)6E$hE+W8C&HRX9>Xi5P7xrL$6P+UJW zG7`$;yxUM;A+Q9{T)7NG*xOhuF!pvD+YLivdQ|Ncwij6VJunc{5eXEr@-PV}o9>6q z4f8emA;@uh!uUxb$Eo155aHc4*0VQvzA@pFhMp2^8ZgZ<4? zYUDxn{n-|Ktd;Epo(J`J)iJ8{wq16zTFF+cI$isH2M=|?S6vU4mPj>E#Ez(W!aZW# z=;v|YY_-Jj+j;DzPVUN1W0-guGh$rL6Um~+v6n;*soJRF#^)`C zcFPzsQhzHwCHbhz6h(FIcD;nb9Nt?}GkmneWqX5u#^j>!XzE+#eXEkH1I))u<$S0p z*N0l2ZI=_}0#+b*lrNA+$+OuEIU-JqV_8xbYcI8D_6Y=|lBZSf`20@W5$z{}&9@zR z?r-}>%8(XT=Onq}6i>8+Ns2Q$dY9_imF7H}>0)t`BWYBMV^l<@YyYABhul^8LlAex zLuq_+l^Z`q2M%v0hc{Eo41pKVKs?HIc%ODfWu?j!7!oDt<=Qh?UU|o|(xfbw$;wJQ zc4K9+C@%E-s#;`4=eJxsV^n^(lB(p~xa^iok6>00P70Jx+hQZzqb3%FA3|+$?^Ut^}AyoY(F8Z>=o6Ks$`RoI#k*2aP8kMP`lg2 zsDoqFfx{nyWepC%GcbyBE3<<$LhDz1hz+7uVuTEpSfQ;NA%Pb>c}0#q|NT4PyXm2a zZnFKP9of1y1hyNhBNdfNM;(fd1z_74?ELLD7O-z=7~6tiqMZ(8RzUu!PveK@O}z_2Ohr57OPFSeFS;Y=Naj3S%uhB z0T@ZVL&5ScR0sgyTwsL?4U$d%yY}w2ee@P&>zClYt$dC+Bu_OEpg5f9VJ~&i72_r; zp^&8b8Is~AU0N_FB!=u8gl|*zZzTrC&LQS@?7s7J*@<6*!#S5j$l=dM{HI7#1pwHH zKPZu@n62aG4%{?`H%0h4x^W}^*X!U5s)Jf0J}-GtBU!JxbmK<+kIHP_##+%P>L0TQ z+C(mFs!QKc%Ypi}^o0S#F}n^MU`RwQH-4yhUWvL_L)wfJtx`RQUY`TZfAO!xr%YOT z?2zMM@;y=^#*mPl)P*JT*uLGN;_rN=u(Hgai1M<0xDp*J%8Sa9?Eku;M~|-4FYhxX zgBn(-4?FFik3 zuIxOo{EF_CHGucnu|w!{l|0&I_pCIY*0A)|P15rK-AdASa|gAc%d<;;t2 zJ3E&T8+v2BIwZou9NOVom&~-qmglxiN$TdYx9X7JCZ#JYn!)TejLQaQbyU-euf8fP z|L&UP(%~BmGS|&!-cQb3oRHS1s6}LpuAcZ#JqJlLjZf*Jd;qJv1S91j5jYOQXDQ}A zp|lbOjRt|Tyc~H{tDafK zUpQ=Pw&Ij>qzb@hWK`GbZ*RjY0GaL@(@GQUsVdRAq;0q5_ilMh`_07O-M!t@x-$FP zjR)qcNuKt(MY))1kyQg~+eg}B^4iSX(Jl3Ny*;I)*LQxOc^6->e$Xf;zp!TMLzCy+ zJ)rZ-UQ^lF#TVA(wTMjXoY|slahHS$pjq%Z@qo*oc)9URc*pZXAwg-dl}7-s&DbjvbR$YU>>TQnFn|iF4$g@*4cTM1ELX z2l(a-__V{aJpdnSNz-uefg^E=G(li9kD4&f77{8?`f+y`rXuX=g55r)&??j$SU>QJ>J^ zDN39z_fS)T-+AmSsRezfbyvr$19Z56MYir(C*l)1MzpJSw{_?52|jwi$$SruFWJhJ zNscz8*CJs3DU*D^RVLXtX!mYpQ$YghfHuljWIG^vr2f@8Zdjp=R%={6qc%j6`M<^G ziNalza=O~loh~J~4j%H6O%3(i9u7@a)xkr;6Hx!@aH;#$ zeegl=(@(3DHRpp`SGM~>F88z_v{7<9v>!|J$CF)Ao`Y}bD+m%LFP9{9Wyc)t9Txkt zciW5c6~nT(U7@H;W);S3qyGAqI=P|#?)g0?GgsMpCCQlI>{k0U&-)YKU5I!1jxEGHj8ndvzoYL;1e~^NK8B$0Y$?vp_->m1-DG=9xtGzV zI*-4bYWus~3vKc`dYjWQhJ}{z(5Adre>V#6#^Bv_fop;qXvKN-> zSemC`{$f^4^VE&=g{)ZHPd`+QHa}AaV~%2ObQ3;j1$fqFhtoOkm6^9J*z?|hC%@3` z(9oe9-c-Kx#cN-FTTE~qdlWL$BNsx(KEh?-QrZ4ark^Nd#5`(6V* zvQB&5p6A%@DzYt=cQWV?Qh-A4$&*F-vEjTN>Rm5?HmDqyFxN-l+h0^JpmwC4{&=*L zChBYZn+i=6~vITcpC z>>V&GDtp@l_JoF&cTU;#()$?GdKl;vblms0BzsK%?;bzOLgva-^Me+>5RwO@hECbNl2}X?Z8EqB2)&lc> z1#bcK_tIb3F110xOkNJj+V9`PANIbc=4r&=x1-__@OPBdraCE7-oREws2d>k(^Vxs z(ixQ=5gF~;UwWw2<-;$?{zIjQA^UN45H*%lQRdFOU7on-P5=FG?6Dnqq+!`3kEkoq zE_+sa{d5*fZatthwTcpJYpouVSfabKa2Wb zqa5|vVbsTWfp%n+!@diukM?;xu=9e-sU6r`yq#jS!|g)pp!%Yc@3>dA!`p}ZkM?=F z^WP{(J4QKhMtnO6II~Hqh&Yarw@9i(Rh&$+1Zo<-`5~12&_8zbuIQl{z=)uS* z;omu=%<4F%j&N*|S%fM%?J8oGy91w=mLNPxs4Zhx9q`|Kz*|>WXG3U;`)pSk{mLWM zEs_IYtB42D*YNwP-&SxR=u7P~e2CA$2jF@2A*BwSn<#avj!8`JZA*80+$=q&carPy zq5a!k?h<#sTbWQ*b%?;Pj&jt;IhFdzwVrxs`$LBh@pytODZ8VqFq=X2NiHc{!tz;J zB8%C<>^pX7M_KDZV|Ho(V2SJomN@gDa(C_M4tnK}$Pi`PKXyI5jPL;eCjd_i>AY%p zN*dsajdCWdi7egKJ0{h&n*)_tl31UpOi0#&igDC?q6w(jKGTXePck>CkA4wSQ!AzLC1Ym%S1(?ntS;I>zRdBcmO5 zXS$-wQLcl#OMSab5AJryBOF*AZIhjf!tBb5$W;u?P|72&t(cpYr7_rrIm(s(kF~E} zdFrWGw6EA~rM0|8o4_9M5B1N|`IGk(Ep@Dpbw=5w*vN>ebi2c*#JF~c^yIWfDJ;Ui zB3hxIARF9>?G}J-bBxZED}9%<*+y^RVfl7zcY>dlB4b?k2qoI-h)7p$3X3wj+pCYu zu0$wmq(fc7Rz(KJm1p*qVCl&0#`iwh4f7TFQ}-zgAdjV1EP~|$6=mu^?T~iAcK*VLfIMiiE`@DXh zS^L3VysqySR0S;0LL&@D-3TeaIw~Scb)?(WbXkpb`3~*pvSYhldBADoNIl#Yvl-S# z4q3^z!3}eE$Rl^WO<+>rd~75WczaP&%j)Q;7&S88X-|hph=xeeTYSc8dqA;sjwmhV zZIXmAT0MHt+q_vmo}hNs6$YG9s-!m?DVhb-Z|AM9;u?YAG}=^GG|b^G>J5gB89GI^ zr^`&GA$Ju+enzdgKj4t-g?1?^16_%a$`YSdVtqd-uf1I-*VF;oI*$hMr?;i5jKB)p z7V(H^D?vFJrY$~3hm>6%0YRLu+9AeyQ#3$(z4U-uFVloB!QA03(dc+X3w*Z_R3HN6 zEBI@_?eFm8vZT({vGF;*)6%0|=`1nb-a8wFJ-D?Rj+qaCMY9RIgiYDNT$vjp*1Kuc z5O-YGjut&Z57(_S(y8hRG?u zs&SjV_lzBTk9U(28%Dj`LC~2AD=(DQ>V%Fi+DxEoe0iEM4q}s z1LgJ3NOuFsJB^YLHXaHi82up&2X7^bj7Vr)>@k(fojZaq+)1AFpc4Kh4Bu?3&#Aj}ZS}zMp zOt2CUgaGQcLYi#KAJP8M!Gj0)mcW5c%%#vU0}5sL57)`p|6A$aFh|{>Y+{kq@4DCblddOeZtHF5 zKBJ)N=-4QT;{CgSLAyuqu}y2-uDU{RH@`Z9V2)OK%Lkhdu{=KnVm=S-+ic%q9%M+B z)p7AzZrDT#PB}Ks8PPkFBpj4B)?~@Vh`~xxeMVeLeWYaylO32Qx_I6bu;Bb8J~N5@6jJdP-sHY^rH4zwQasE?5B z_39QmT2~U(J_1da9uf|iUBK=Q?W30ge~dkXy3kc5bwMbNa@I#mj(Xb`u7zM&qJ6H@ z^dWG2+UP)U9x|2N7FOJ-&Ui`n$o6R0LA1;jdUX`=0^#Yf;znpCp_yc-j+$!^$e-NG z-l??OUG}I>!j0K_w5?u|0R5I|LxBq1SbIp2(*s@9$pb?AkY5VmMvaPB z9H1_l54;O5Q-K%WLojXv9mp^Fi_H%7_QBI68`ZUFI}-7}*45ETEz%t6o>)0OT1_F= z*)LRK1gnpWS)nA=N4a1}V&#(d;UN%6(~4U^*a^jb4SAEcj};FqFD~xp|6m6jIcwSI z!SBIh**0PD;-&p2`EzXt{F_!ydiTMV#9F$(qyA&17E-(Fn3%M*r1VIeo7f9Jh6zEW ztKP1zkmF-Gb8#4mx4>OS*A|cx-Zr|{Tmg8%5k}W0Kmiz>90x532Wdb-qDxMXRih0M z2*tpGJ8ngcQXfUObO;WtpxE=QScuYL89jQg*)61>4$b4Mt_KW!{;EF%29H!-9TlIb zM!3^$l3h)39X_~qlEfxd!FJk>IRJ~_9$D{Lq1z-?2sT$cqT(atZFUTp;vZ_&aO#9cj-Y+** zR|V!fhb2ksRUMs}qDCjAJLL$KCBv}-G;#o%=vb!|5mO(zBEjHm0Z(jvOuRF~slx-^ z&ex|xKuVCGQ=Bo4psE`^;fZiy={9`6fulq<+9SY9u!406I5MEp=R(t9igz>yD2g?L zMtcL6q>w4{-vEmf)?|buQdMl}Oo?#qKj?E;3FRrrvv@_trl1ve?xFA9nx(J_SOz$B z=;@o~o0&WTiWEx@VB$nJLi>g#K6^m@M0@QBtKz~%#3HDVNLYfA5z!!UI`keKFSD0e zHC`do+w3cxay|U6(!=Nnp?tdGpB zS6!)jV!q=ADXa4MveKkv+7kkKLwGC461F`N@nHTBm?AG9{^QasD+)Hg_wK~i2ebtb zj$N^gY5u+sj-7iO)7W@|pe}b@J6Km%q9}yO>S8cG>UW{Q-1UNY`-~ zJyN<FXwAJaN%k5}bK8%Py0?7hOSBL`K6~jzmw?(P7>X3>8a9a<%_4 zOGkljz=F`ph=tfkqYnjMVE1ZwLb59hK9v+5iHNT=%bp}qN6iZK#oCy=-VqfS0Tu13 zS4jwTJ;)aVxj76URiH9}PF2;q?Vw@qV7t6*fc7-o1Q38v9kl`U3cH+O@xVUlSsfqW zA~p+db3&vuDP6W_sZxqQZWEfgxJ1Hpj3a7=JDG9g+=R!1?f^7ovg>F!;qgDFbu-Xn zfWu+beFf6jZh@cVxU3j=e0)?yLb~Dr)e-;Wq~IWt=!$iDh#s-g&J~Heq9XiYt(5G? z09gb;3ZPMUHk1hR7yx-2K|}Zw_7jhF*bpr$fEgL3%IQuA#F-f_dd6NaKcF}T({YoV zBp14Q7GV=#zC4nmMHGqICf5-C1MwmUBL1*P>@ljE9vMO6#}YBBj&Rni56BTV-Y)zf zVQcG6C%mnp(K8WfSaBHe3KQE#XrZu?@|y1lc_f;x zGvFnDwIzTaGPL3OPdg%QDiq=F-8APSd$J8M+cr4r6~qJqB=*Ht$IEUzlO;E_mh4uT zTZQ&?xDL4v;g{2OXbj6?4*cXKDu47}&Mvr2D^YLIX0mT=JsYlp9V|?59Z#a)Na=!Y z5s0{|q#Sw2QRvu?j@1b2xzy6Nle%^|oU$9!#tzjP(zUGuT?ab%&t>0eGcEnYa1#Is zTpd)dE*$4#=3CA*IL1 zMyI<}if8Qyd+Ww~OnOv3b4S*DR>Wl1$B}e6#5V`<9adz)w_(JM^uvv5gtgk^AyJvP zc|t)}R>rIcwHVe#i)M$}6W3MuX1&I*-7nvuEEw9mTi4o&{!PRO{#<2&TzmbxtJjaa znlb-2NM^1}190X@U8~*Md4RJ;mXw|VIOA0pk7rpRjm-q4p2+&d74Dd94(jn>CAacK z(E2M6oETg%a9DURw&Io0ni?miCjwlL>eizWgjmw4FrW+lKX@8t;B(h31p*)_m+`eQt4`%KM1JK9ks3w+bdwB5dgnm6WQb zmngeh?~IH#l`8ear947JMo$Uy2S!(r;ozH75qx#*oge@ScU&Junz+ldf=FR60V2^TIsjqJad6idJ`3)`Kxe_76*m7S zi)~5kG_=l;Wlxu~pvVsTeB3a4hS}?t6^Kg_6-$LlDaZwLQW-?HB!W`5JH@rt*hO%Yu z|3}`Nz*$wC>)!9$Q#TDLAP(t9MVXaJ29ZgLqM{N+1x3WDk*E>|ybkmo`g#_vu6wTTx!u8rkArzL?uk{_+HRfzZJd38(?R%!gmSnMegep>4Od~eEK5$)v46gr=Qc{3s8`0diXJqRG)KhkHee({hqoTn;+Kek?KeI z6!f=yqDM}?=(yu9%6|#U=X(>HIn0hSqd)DduOnZcio%DIFHXiifB$O9$hZBN@2yf< zd{H{~_POSBsVM%mw68SO-PoWgipD$5uxaN3Z+DD#nqg~wauqU&)6o5GtA3bckjoEo zku{s*C)WKecr8D;?HSuNyDn?)Gxk`UL^!)Hta!#5*XkR3(U|7J=0_UBrBT)goNwno zjwzi@*_@LfF!M8OpE9iSA*}FL*dWL-z%V=?v|@>n^52bF&{xK_s88R)1bbD2 zw}6Ni^fxsc;S1w?B)TbjW`4-6{pp_dy|W0{-^rUd_xVF%XfKSn`EjsGX&Fndh1Glo z-e6cS6vDHFe@|phQ3Qo@2-DqsPw@Ws!u-TX^Hur4y~aKlbYUEiME8Vyn8t9Q_nb)i zMoD>(Ldr{`L7R9JpZN@8R+~?GQ)A-8sw8RG%di$}ne+rc4Wk9~_VxYzgto3(WXW6k zH!q*T*01a5+h0De{e8Z$zt4c05LXFrOg;nJ6I(N50<^Fh-R^#hjxKPMK1Q?TriovD zjGB}-h?2=&!#Jap_T+E>qA0y)6s3={Cym@dT(;~h!A0B>bZXTQ6u6fz)@`Jy2Tl2?$I(h#tl$n1m=QDXe7wy7a>=&Eesb$&h!zvEFt#gZo z`!R0qEgyk@J}>Hb8|0-ZC(()FH}r?04fg`!;Sr9O7|Y>TcBhX^*BfW;Gr+87+&IP%N1I zrisE};d7lmf+*TOQ7nhQ-*eC3zI^O#%gHFyey5@m@G-nWT8dK=+ti>c^RvV-HN}Hh zgX(OUn#hm#4CH(2Rb}EcyDvyeaY`afucAeT4 z5U&{DtJhO}CII8(Th@)|-#YKh0$a~HlUmyUe#|)Awe&3&q633=@!r|pSJrLMM&<-9 z*4N#giG5geIEO-$Ty<&OY2UnhW*`?e65P4+xB?}h3xF~XC z?a_6=tNZlO!=CAS)C;iRd9c>;C^NBc-?~y-Q)jc zZ|`Zjs$7ES8r{$RI(BM&D(;hP7iXgC!;|}B+`ntP;;ln>?d!jp{r-N2YYcnjwZ}c& z`!4q@qkZaz?aiI-?VUaT&)?VCtqH*nKfC37=ELwfvqb#C4o)i-+&N3utn5_$cRb(& zc7_vL{34#>tWx~5x(9iV9gB%FKTCGNZ}Rt}B|1xXW%R!Aen~&w|LxxH=fh_oeLj57 zNX4h-5(>9jqD<}{F7DB`p?gU`xqEo^?)h+Z<|?1giLu`)oejd%{d_tnMt+dLUmULP z=hNBfzK7rB!^lUZll}a}J0U(b%wM9H+&|8{Q%i+%;Xu9n|3k5RJ{-l94`*WRW>TPY zvx#1E&xhk@$qMczF}df%DY)BAzWFUlv?lyNEBuMkRCvZPzDe$X$-75x3f&Wn za@eG^k{$i5r0XVlEPs}-Zj;VTcJwood))Kk_}Mpw<9hoH_3>PBc(jjvc-#*jkKMfI zdGtuQxa7n2`_H33p3lc?mAfBnkj_c0?Ww+Y|GGgsC;3Soub17wZjjD`d;Tmd3yU2O z{9Zo&{FcUqd_6`veTX|}3KTEt%exoSHMQVQx+piDiH+6NhvW5FA5LPw`fw%&UH61T z|IzWld^i(>m_&c3(sJb1@W ziC8;U-P-dPUJJ*;WB*tkOgQF-+Vkt~YkI)K$g<$#+AA*Fzez0dWb_w1d+dKu_p#&p zH$A6r;sbTfUcR+%zhwJl5xZ5jfoU#rT6Cbj4e5A{n$%l{dct5wT_qG)BS*G^GlVi zmJc>c*6|npcJ&oq+g!Cj2`G&p|E)_JBw)(7e^Q9ABtd*#!ua@ru$TB66plwcy?=|z zdyiJ7G4{Bo7eBiCibD^%rKQInJE2kRCtuVezPd-}^E6&iKPB&}{avd1zcGGFG*!^c z>+aqr!DmC{9no-E~*;Udhq)6PJHJUvj^qIQ@EOxJB;YDR%dE z-yoa`VS4H|MPDxpXF`}B+Iev}1^0Y+zmg#EV8hVQw5b@6?| ze{!$k-x%pw`=r9ppFQ96d_MffXV3TC&xc>QZ};#U0!M2;k{@R#20J1h3-wZb_I#qB zY0tZJhS1NX=fjaZ{U!6rv;K7R!i6VawEv*b?C???%+}4>H99o^`F8D-&983a*M8HV z5SL7kvICJ{VcKE?vEdAi%agc zDT%>$Tco%Bj9=+l1{U#CAA`C79{%r-{NBc6zVByA@qat`5X=Gd!Fb@|{0KY-?f|#p zcRRS>!w3;O!R{g9x5sa=7M#0WAD?5_B)VYkXY2X>tM!TAT*qvEWSk>6Cw>C%*WvyL z{M2F&w`*b>^Je@x9l|Z6 zyeRj*q2ztssSB@%Vo(P^r!Hn<{s!z&`4{TJ?Zr_2eq_VEE{frGp}KaHe5>voo8(IQYsB?RTEEP6J-b%+X`=ObtK3H=qcDGDQz_@I50AEqr-(_ubG*~0iJ z^1Q&VAm3By6XtMzp{@_4FCxFLpXhe5#9Bu#wDnCdw)JJ>ZGDqL)bUgFt7mZUQTmN* zY<&stiAyM>LR(QE&_A~&)WTP-Bej!8?alieZ}W}YMPA3bPs2DulYA^BA7fnW4bog_ zU!^`ipzlz(VVdjXpx+S16}A=I_J!Lz8;?IeOot^Ts+Y=snbR zJZAG_UF}pK(`e`0Ip4LOergI@n-cpSW>|M&`4rL<#6ylBrw->`mO zHYK$-#SyX6-9vDAIM&GiLXupg)Z02PV_G4jxk{FWjx5#f9 z`Q4A_|3Q3BnMXW{j(p7YG4Q$Ax9yg242|Etr|(YuhusuA$I`K{TRPFl((#duuij7H zrDvzao8ULg7zNbMy&nR!oBbjy?2*X7?Aqv2c1HAL`$lAdt&Kl|CK-c6#E&Mdc6#O+ z9|LF`Q{o$KR{T_(939Dc@8DMqyl;x0MmmqT6u36F3A=-`;CBVyb3}hi*%jJbVJx@U zUrFD3`bx^UFs9SDpdl|m2U-M^VzjGbsJ;y>Jub;M7nkMjHsvg@M9*mc2Wxlbdl>^j=; zu*f%U7{9O8*8N3ltRv;Mkh$GL<^xZHr$IJy9ey33<-t6GW3CS3C<61px4CAX5nO}0 zc+WL+Cft}yeOD-ihZ|d0*@b)<^TQw5c%Jz=*Y{%n1#>v&O0YeW$>lKrGkOJSA7$T< z)RK=M=F<}Wo4wr_`1N$X73;vfN@4LE*;f0Q*=}a$wQIq0z$#%4@9niO;XV)Z9Zc35 zYTa!I_!-x0Ft>vX0sb6yhvUv#l_PfpZiR4nx5q8ZedgD7JhS^&z?+KT_uS5}CG5T) z+{<%sVRi;rf_7jy2;<|8+T#!7lv$K!Pj}6o_-Dmr7prA8S75f{dI`_`74ry8!q|N@ zY2htg`3&<*PukMUXXv?8~wl|u#U}e|`xQRCI$IZ3#PW%Vf!sn#%ow+|GcIN&b z9h&=d;?~^X5P%vD0~9Ar7UVIk)%AiZ4I+ z&T6ji{X6p^m3d#g1;3-?g*lQ;>Ol2yI_3T$cKqV!cCRllb00@aU$#-DTqp1oe-b~n zq-~3}(^%+Zj=%qT-Sd26h<)3`E4|-3$B&?l@GI~f{zrK_LQT}yyU*9W-aX9U+YPGs zV|nf-d#dz52Q5N$UQx2xg&an#;zvf*zYP~|8QT{FBXLDUJ zOSUstWlqRWpli_9lqQqyd!_wtUKp>}w~za=xDBLl`ZfItD|x%0$>U$Yh>rQ^+tD#Q z$0WK__E!?`G&_Pa=&1IJw!F?&?w8rAv1jeLSRL1c?K!W1uLIYB>Vf)K-uIYCa6Opx z_ewl!M@dVk*;>ZZ^(8UPM=;N!91`g94%$zcPS=UoRbk!~nywkIw~`xjyAs#ZAE6zu zzhcw-gOb~=b$p}kADXW7`m}m`ev3BQmv(lcbq~{&a4qtV7KT+)P95~}bp_nQ`Ch>c z=c($;&<6E#ooggC>*ET`r7#~3`{B^6ug^mN5nj9Yr7_xyYslM7u^FZ@tQT)HuG@H_ ze!_C9H>cTM)aR7aW_DLeH+1qU{&(0D@vA6{74}5wJ$7u#W7gg0#v1-}6cz#^3QaT=hJh zcd9Xz@%J$QGr#6Qx}SFF-K3-aBz|q)o_KAKJ7dk$iMd>FwXe(HWBBQ4Kl0}i{cK#} z`8yNO+Bn@WtY;+7k-wjW;mf4YEBLuH@ok~1XH6&GCm$F z`&ggLy0#LBP%cNx{$%_f+SE|3UpyDT7dNimPjn!f?!mKX?^6{qBzMm*3EY|L#*W1Oc z77k_N@C3-^;n%^>3%C>$g#Y+Ob$;{7pYb&-zehWHgPH5s@bNRZN2mKbWN<0*JRSRu zjfu{-lVUIPZh9E=?p!| z#7>HT13S+pt|!kYTI*;Q|E!D1JO{VVfD}0r`&qhVgQX+0?S0Z%>+=;~ql~^{4^f^g zXsZ*WALO2JGjWntdfP3TZk4fP><%{_@uTd%5Yd@7P2d@Su1VG^g(aAvgJQ$&Y%m-=1#SnU!Jq=hW2PfN*4psXv2k{u=gZSXSnDI_+V{h}?#m4Gzc;hK zOv19+n^`EYXl?F^*kJIxyy^K5QD2r`rbXrH<>+O&H>h06M@bj%Uq$(2dO3&i>%GD2 zp#i85uagFtgCFX?xQ@Ke_EP3v_E&-ph4S`t_cily9o^T`8{=)<9QV2AV!T^N$7`(8 z_^-Lh%d}VK0*ME>cblyRgPEiH9A$0fSFAlP!EGI5<1C?PkFHkG&PCv~>>ly^ME6exKV$nwK#SR>r6D z9pEd z*B zwy4?n=^wryeKNN(b_w4K{$gw5*8shpLSN@@V_7@7%J0R0#=UU`zti((e5{?47?1rt?vEs% z^LUQ9$lusl3+k#R7|L^}Vs^K0$JznhSnnGj+aG%ezBzmkdpFR7wa=3<+si&aah}Xd z-ebn2_d$sf1@{y4rk?3$$=LM5bq}kIeoFk^F>8sx9qz6dPe+)RO5&c&^(z2>v8zbK zB<#ys3chPa;V>l4fq6HA!`H!@4sFkjn`xk$nEXAAc0L(`v+G-LiU z2F+f|_Z7#X*c}}T=5wsI9B4D#U;RDqm#$_$eKJ@`JpXCe7pGPBw{Y7FJe_`jAL*@6 zTbRbs^suO}8Nm#jQ9MVH{Ts%w!+GB-VV+(>`uD)EL&!bh?{;W5k;c3ogl6a-nxXq1b9?mbl=;`~INHN0 z%pcc>=6`#<-zQ$cT=@DJ>k{?w>ktKZ-nrH@x4J&Q6SECv5t^ZUXol{4%*CFIiJ6xaOcWx8sVjc}bGjtEl(0z}&J$gR*xe#E+ zpGH#!lpM*Nwiu@p?k?OKnN1ES-LKjy`!eanXT)RFo3G37fnSG^dtxo&pFkbBcJBnC z8M=pN=)T9y=fV4qEwr6;XjA9VZt`%uP*i?iW?}iA5|*9v@BPLNj4j1@-M$ge<9f{N zOU9Gm{qlXn=lX;2d+a-Q4*h^5-yam(w`(x*F!l5>`OL%Z_1CdV?o&pdkJ5|xjl{hT z!qM|(2iS}dr7@lb;WhL38KtwO*HHHjG%BriAnzUQhyvVRe@)qxdEevTW)tn~n&?ZE zwS#qKPiGlzxcUBhG&P&y2(P1WRb0RJ6`K2?=W9` z$J$5#jCoG}{UXYWvcBUkwn)O)oqXMgcQgFof(H1uBlPy~uX6W$y=*S)O1%VM=a|QH zAMvg?n|Hl(){lr=-!c5#MPHj5TWrs`TP(?Q{_L~N4R{ZaUd^|nPb?n2&Tff*2zm(T zME}6J_Y1ovxXF=wAv%J!-q-l{b3XTfR=_{;ld@BzWnAA1TIXt`%UBnyv7>qK{f2P7 zof_|feG=>c*rVs>5&4~sifpm7-7UC^IT_yxV*ZWbWN@aP8u3oT{1*E;!)^%u@E-k~=gq%4@tvj@^X

)=DXfIrtX#nYv^HOM*d>`qBrwh%1yqL`*X}enRhn;bMx90(L;Vu zgRiHyroQv0f7|wJt>e1Z>i01CejDEX_jMg-o}_QKUt;>2bc8)K_1|#4ALX09_Z7bW zkT+TLkMRQ){K7}*PM-NCbnS5{!Q7$saNf@wn?CMFzQOy*b?k-sMsByReGiDcvmeCQ zgnfOZu^F$;$Gwi(?c=WVXoR&y?>c|Nw|08OU%ag$hYbIzKt(2!}{2l>F+Gj zH>_=(?>t`!>cQ)Txq2KVc&;Sz9gFcjx+MNri}||i-Vk5LeNgfo&%J61zCDzbOyoIV zYy1N6URsji*V#*1*DYOX3BEOylwQHF#82hdViI_zxGEfiF$f{eA^2W-zDDl#8pMSp5990djaf@vI`ASBU2>p8q+|UW9o+LV=3=zFnD?F(30 zp9jh-v?nI>4Bw1PuI76#-;I6Th%t8q%fU*@^-tjU;N60jwqpO7Z;qeQ#-q_+G4J48 zGk$Ldv;CRIdO&CSZ+M|j{JW5UKYj)9eVRUy&q==L!QOFmZ)H?+JAV0|U2+K~-?I~Z zZ_a=F_I&0y=!RzGA;vu1_-l&3e^z^N1J+yZRj`+TzJBh&?|8ys|EFMtAM-t|tW$@3 zJ7lt6^JD{<_2;?%vDN(eJBTc`ZSnJL8{zn~zK*=lf1a+gH8!O=`;&qct z)>1)qm-6U)a^EdrFneJS_2;=B9R0D~<#|__%Y);5J&3it&WYv0We#7j_cbfhFxl;n zfUgt(&cA41J5O`YzIFok%fL7=5u6XsiSxZKkxHl zpZofpmiHC6Be-*^Z{N>*F-U{k^o@vlWLbCK@8&Y!`P2p`PGPAYMmemi+T5&ukk7{_>fQk(jV9YQ-F z>hnXtpE#ZGatm22ecPrn|2Z%Au04p`D4&nAZqYybH0#Fyu*>7)b2ZWDtb*@7=Q75e zQgVfjZSq5#8^7P$$KRyv29c&;@a}k%eT_NnL$T}l^CH*L?!6!QA?wnMS*zS;7erpS zGb69(4q|`&z}T^NR!Lz`b=g1a_f~(i;O6GHzzK!x%L=BuxqTvgX=czzX%A*RMSXrN zpQn;btVQW()}m|%-D1dT;{yYVb(?;XAS>rw7r{|AN#xA zH2nV={}*Eaq1*;0X4ydAw+Fia81sMnyeY1yCjYP-JS;aU$7^Ej+wt&8-+8nn+EVZk z=5+Sex(I4>__40wpu%$x7oKy|+oa$3=ZoBB_j}(f_z6w-cN7>4mK2#E6#R9= zJQMr|Oa>dleZa#4(Kyc(((UoqU;F**_xQ7^*gZ}+3(wY@dr7a~3l;(L&L4;qWcOza z{=>3T{O-TF{3aCq^~3#}*oWm!w+llWUMtM+;}6Kc$KmNOimP#Y*)y2G-%ss_?-Z=D zU*z**M`9=6!N>C59bkXT5r2_08AW!^Cv@do=zK?fJnf zF=%gaJyzM~#A2{KsGvE~;loo^iF4rYSvR1=h!p3&LcF=F# z;D{V(54c&Bu6K*}a`!X~R>%GKEo&k(KuY+HGg)qJ>j$ac-Jy@Tb z<%q6iKlgI`eEj(|yZ%DMxs{PjgRx8{~^RxWPd>z6EX|tiSM{wJwBfPne0u1-mmb)9#G!U@sbTf_TLK z#dBVtpM$%{H}fqIU=PdZP3$1J$?u0~dWp?)gxCKc%?}$r_g1Mz=a4qd&kE)kFQdlo zG%Pp#G`L^z_a6HYPX|}i*WXRr>4)|p`bjXbFbDg2XeOpcb|j|KpM)lPjaBe&WcE)_ zWAtU_Y%g0TG-F2xPth)qYI2;-cQhSYFz>Xf*n>nZXHnOU+%S| zAMie*2$3H)ybkZ>-4hmhh|RB$<;`NdJ?3d4jr~e~L|nwndv1b0;(Y$fYSQyhKQ!;F zAjVp79+5+0Zv^Z1a{Z@<_uXIUx7dGiIRDOl52F}iIRAe)!#sLAgQ{OyeIoTT!$b%?iRTzZ@ND(U%w9PYmb@e#5>D>3DE;S|9pH(-feI9Jia~d zuHUbM_(a}WLFhMjIct=_bzcl#5cwN>d)yjdhkhHoH@*)2$*f_&2z_Y+6I@*|-M&x6 z`my%kkMxZq&9Cf1^lO$VMtvBK^TB&-nAc*nI9;VXY;y5Ex7UXkrmZ;KMcfDU^@4{* zAMphJ-4&SQ!D5gEX-8}}*GJ23aY=;3V!ni+v2{R?HJI{kg)my&J9OyljP+XE2p} zYq(w!*=$Rqzh!N;)|MpNS_*gW+x#zq`zb23;28F;&evE9?Dv|hmhg^X8yAW7_MOw_-NIyrqC$ znEuW&3X~;Y*4*T$`ML|v$6V&%y?knXbMPNvDE`iEgo6s#Zk|?j&)E-3-wS zJ880cz~kUON#TUyd6*8r_h5Ijj%ZX9vNAd zSRP44X0hfri*KhRSZf>M?~k6x;C?WIu!uA8vbq^8#C}&EkwbYF1kZx^K|9bNj0V?p zFAFAO_w}p?h=1N!0db&>|E=)%ORvvj)9ri1R@_4r?g!f%`E?zE;J`fC54YSA48rs} zD69$8*PVys^>_`K1N?o?aUFBjtH7B){zU)5eDojo6xXZ3BK8Ka0*ml>0XQF=>1cAI zUDuR(EeOqh+5P@?v>l_(blo?iseRw`=l*ZM|3!KKpK$O0_WJv;rvHCJ9q&7j^cmv; zeUSf7M_}>m*=y|hEq1`Y&#fCUXRLSA+_8?&Ut~hy1Qa zA?*KyX1G@M-hV@!E67t@!VS%S*g?1^TJK(TpL@%wpFDi@+Y=!n%9HhL-$Pzx{Fr-xYLbHeNW3?%#je-}Nm&v+et*f&adGnIpZ`Zkz*Z;=Ll<#o8hyO%ejtO7p3&rR0NqpmKfv&?n zOz)zdXKYH@2Yk2dh@SW>dWjQR>;FFA?Fwfe|LTy*rA` zCHd?6Z&OqFUe=CpSdZE{(JPsEUrQT$(8|I*tKGKF)x>|xnb2POGp&^K6!ulp)^auV z=5^N8zlFtrhh`}copFosTM7IYR)pWZ@^a!E;`M}ginniX8%^ff&|rmC1%I#~M)qUR zUmLqP($2>E_2=BV|CQW%Uf~q^C;qpo^EnRhFXBml1EMUCk~P-D!G69TiQiL>_t_KR z$tIlTYckEAY&MAZ63)c=?t*BRpUpjp@22nZ4swi*DLDbHbY-phCBRH>zzef z{0!au?0X%+o`x&gWBb4PT4%zBaqeUzYku~+vf$G>;&XWL@E z^Jo6{YI1%pc4htyo15WTv*_!jX9D>xoIm@j*NipyBo5A>Lvu4MH~Qq6^use_$FVng z8S9IF#_dI$8HVd;)M7_+jo^rSU@<0C#3IFH69l`#VF;?nl8)Y71-^pJW zxrO&+=5`eP9^z&+JbO7gfBrHuIe!LI>E|4#UpG#_w`<&WHnUhyI*)fcYjj_ttN(Jn zH>zhpt60|C-*c(scI*XjeC_8Kf5rV@Qdir#-{@NBM7<8b$^Dsx;paw+u62HtcidPt z<+T|t`FT>m?vcN4towwYFI{32!gkPDAAZ)6?=&+b>}QWWLU?`#^&Go1b{h7Dw2Ol7 zLj8p08tN_7S6DBhS?_;lt~+V%9-Eo_2=gQM_#I4|55^pYIm$KD_+M!se%IiC_rv zzK;DWAMo32SKGw+W9-*EgWpqJY_qh_#LaE|F5r4+@mYSK74}hOdc$WQj?=UW2gUN3)?QVwo zdI9WItOfclsgJRbusO`)_(i4=;dSwtRy=pMh>Rw8wO29zQQPboaCQi3b?NLH>-so3anin>^!Z z_NTfDIJ+PF$W6v!&hSTmSK!Ql z{I}RaOy~UFGv8;q&`&4qiMT zFSZx^*_XXRn<$#6HE=I_A1Hn|D7K^d0BLNtpzIqx&6+lU&01Ld+(x)VZWYXLF2ddH zYPgs6hx^E-Uv4P&{<-P!fE*|6ZD8(Rcu=l6d^Ugks)e1OTMv)RZH6lqW>TCIr^OlZ zEQLH#o{N#OT2lI07U|!B0%*(lhZFN>@cL=LFxC{JfE$qp*R4#BTw_j2n%DdCgyalTRfsrxV6DgKvu7iGn1 z0{nL*r_P?!j^qL+7Uu!t9nMWYbuRlCK047mZHD`cy{tMZgiZ>f6a9?eO^Q?Ev^XR7 zQtD(?vS-EB&dOIO<*QS$!~GB=Oqw^s|Dqr3RJM!Wql>kyTLm9VEq5U$?&3Ar#rlbd z%4HbOcCq2P3GmsJKo=V=`xv>8lb=d)Qk)W}#ToH~;)leG#1D%f5kD$ktk9kiFA*;l zFIS8!#4E+C#H+>6%g-9|3*r~WFDcBm;wteg;;i^*;%f2F#c%1Ucf{|B-xq%%{;Tr) znRBqe#~ZX1A0R$h?q3sEh+TDE0#{v^z*W~JaMg7Qyso>@Z##DuAMN1>-NZe_$B282 z`-=N}3TfjW?^9yeXP02J_^)#L%>B?#VbyY%vR!r48SVOU_b8NkFYL-ZO1e4#3vA#zySBP{`35O^(KWl^u=yT6h=sZj3d~o|kS4vzx-~Cav9aQ#joePB+4tY268@3+&-^rzdfjUSc1cy4!K2p}YE!?xcSe_M!4QjMR2Vht6Zf z<0$j)q+}ZG?WMcY(A_)@-Ia#!N<(*>q3~ykXN%{E=Zfcvf1-Hji|-TPFJ7QDJg6`q z5-$=zEPh1%sCcnb^@Mndc&T`~c!hYSc$Ijy_<8Xf@eAS?#V;v$YsKr7!q>zf_+4s{ zvI=^73WHlLHwfF+kOx8w%@~i1nd!X^!!pv z)NWmu67Cq)g_B`0vGRa2o9Wb1!MWmz35^O6w)1 z^^($hNol<_e)Uoh+)FL17j;26>UDclBO9$ZeeYVhJt6ldWOo^wTLcfI#Cp@;y31KS z)my!8Z+cy~pDXry>8+Ho3ab#3;*>Zo&WIN%oCg*1L*hl^hsBSG9~CcFyibUih`rD0 zZO{I9OaEK0@41>^0Jx zvLe4_I~fyuYh>(A54MWgxz|e{m0=&1VIRtHn)Rg&m%`o;_ocqp!tLeKky`Fczc&Hy zPkr@8+wOCao*GIleJSBZ@Y&)q;&JjhN$g{HUrN=VN{UnBv^XQ4p;#6u%m)?bL*hl^ zhsBSG9~CcFEKi7+h?k0&i&uzOidTtOi=P*-5x*dQQT&q9xmLVRDS1u&f#0Q1An)kh z?E^f8lpZdWp4)ekyJP7MI>MFWq&Ou`i!*RPN_Z&TlJ|>#lq5OWR*TbJiF8Wd09&%Eg5~sx( z@eIZIV6G*89#RO4WPe!vi1<s6KEl%(v=jS?-!C}EL#7t+gSL0t zaW)wDu=fn~NxD0fa_En4oxNx1k9yrchM9SP`selVq}&MD z%d@}wg#MJLhv0oee|jfp?-TlK?%iK=Z`PL-{#@}q@q-HaA@L&d!{SH8kBS$IpAat* zFBLBruMn>kuM)2oKd;oT5x*dQQT&q9zgGN#`$WCui&Fa72B@VEK!*onKa^4$K*`L6 zhmw~8l!?1|nGB#z+&&uR51?dL!Q;r$07}OFd%GS$$+$f!PKndvjQBx?`H*;#_+jxQ z;zz}c70VOiCE}&x<>D3MmEu+6)#B%so;BhZ#4n2dO`lad@dxgcevpNPWS--9XX);2@f`77@jS8jNCO#joxMjI$e8QA zPS3t3_Wop`=Booq!zDHl^)7{XQQCt@NprX*W9T3|l<{&$$G8vE z-QnbA5IuwY97AmmBDIIZ(}-)3dVoRd0S2L157T>qK`7SQXKsVYk+aX-2BBMLpSca< zozeM0#r2SQk@#WpBjQKJixvA5;w9px;^pEM;+5i6;??5kmD)Ap7sM}$eLgmbcT(pM z+$XvvUz8Ot8m$JY)&^5neC<&^4wn01^~1yL0^CpI?o7BP%? zS;a`6iBO7SZ3YO$}9U0}Wrb^&==YvZKkakTo)*bk)!$0-ftl!kGnaHCCP zt(D)zr5|v1eNNIE(Io38dp~kFNprJF%+37nAi|l%`l{Pq^OMwXPqOJY7rU<)O=3pv zeq8yJq6xbVOjAmj(c^y_{pV1) zKcgq(3D44}iU-je=+7(48>!?! zkJndsE6rDTE6rDTE6rDT`5i@tFiY$!dzH$2rSe{>yjPNUPs!uD>+gM)dhe^$dtasA z`zrO`SE={DO1<}0>bp@;Bea zu9iyaxzgT{{Vnl3;`hYwi$4(mM(nz()JkKe))*^U1;Rxujg_ngxxJOxS9B{`=OK?; z(XFH&-R`ZRGVm4MO0DQtYDKp)@D<%kYT5m4m!H2nYi+i&iLb|2vg*iFO?*AJl65?M zYCX16>#>#e3{m#t_m+HelcZJ{l3I~YYDGFJog}4`q;!&$ zPLk3|QaVWnu9Kv6l9W!8(n(S}NlGV4=_DzgB&Cz2bdr=#l7Z_aDV-#>dY_b9l2S`j zYDr2hNvS0%wIrpMq|}mz*N@__-Eh(ubCAFlamXy?zl3G$yONz4OU4{Rgy;n&|Eh(ubCAFlamXy?z zl3G&gRZ>z*N@__-Eh(ubCAFlamXy?zl3G$yOG;`rNm@F|NGBQTBqN<< zq!U(@D2|^U8R;Y=on)kwjC7KbPBPL-Mmpi|5TKKc zbdr%yGSW##I>|^U8R;Y=on)kwjC7KbPBPL-MmotzCmHD^Bb{WVlZ|^U8R;Y=on)kwjC7KbPBPL-MmotzCmHD^Bb{WVlZY zv%l@mpcY`_g|#w#H?#W9b~l=F_BHvt<^OK^znl5FyZd*jyR|ZZw^ruw*2?_dgy#OM zbT=!mb|#Ow6N|HdGrgOX!=!K{?B7i9CWS+7mR6)^q41^H{S9=M(!-t)+5JnwETw9e zQZ-BInWgm1QhH`7J+qXaSxV0=#XC!J%_1(sR9v$a*KEZ#TXD@+TG zE3Vm!YqsK=t+-|@uGxxfw&I$txMnM^*@|nn;+mtl<|wW?iffMIV*d(p%~4!)6xSTZ zHAivHQCxEr*Br$)M{&(jTyqrH9K|(9am`U&a~0QI#Wh!P%~f3Nk|D0SifgXo;{8u9 zUZ-;v*IdOlS8>f%TyquIT*Wn4am`g+a~0P-#WhcH%~M?S6c>AO2y>p|ny0wtDXw|S z*F42FPjSstT=NvyJjFFnam`a)^Ay)S#q|@d=>9}2y7Oh9FZ+G6-zWS1vfnTJ0(#5l zwm@rW3$%u|fV5qLi@(Dzpr3U1HM9ju=4)sR z%-7Hsn6IHNV0GQu*U%Q2uc0k4Uqf5K>bkS9p)D|9Lt9|JhPHs!Ay2KZp)KGGk+ZL% zEuasa3Hut_0G5;pv`B^DHE9GaU{H&CpmGa}e(mL8I`B^1DtK?^u{H&56 z{`v}jR?E+7`B^PLtL104{JeygHrq>DnR$s)nt&t- zuhIx!r4hVJBY2fY@G6bqRT{yoG=f)=s#QGeZ;@3R!K*ZaS7`*V(g8173HAux=Q19 zmB#BTjn`Egud6g(S82Si(s*5^@w!Umbrl+mSe3@>thAApHnP%2R@%r)8(C>1D{W+@ zjjXgmsiBRmw2_rIveHIY+Q>>9S!p9HZDgg5thAApHnP%2R@%r)8=N1D{W+@jjXhhl{T`{MpoL$N*h^eBP(rWrH!n#k(D;G(gtS^sllwYk(D;G(neO= z$VwYoX(KCbWTlO)w2_rIveHIY+Q>>9S!pAy8C_P|$VwYoX(KCbWTlO)w2_rIveHIY z+Q>>9S!p9HZDgg5thAApHnP%2R@%r)8(C>1D{W+@jjXhhl{T`{MpoL$N*h^eBP(rW zrH!n#k(D;G(neO=sFpUWrHyK7qgvXimNu%TjcRG5TH2_VHdwPm8`aWAwX{(!ZB$De z)zU__v{5Z>aF&X?sFpUWrHyK7qgtw{mMW^HifXB%TB@j)DypT5YN?`Hs;HJKs-=o* zsiIn{sFo_Kr3!wTNii-JFBh*6yDF-sifXB%T1u#v5~`(yYAK;wN~o3+s-=W#DWO_Q zsFo6{rG#oJp;}6)mJ+I^glZ|FT1u#v5~`(yYAK;wN~o3ws-=NyX`osfsFnt*rGaW` zpjsNJR_#}-_N!I<)vEn!)qb^Vzgo3lt=g|v?N_Vbt5xsSs`qu&+Gb86_*k<}YRP1jm_BR##n~LR4h5V*Mep4ZTz<9mc*pI-7wuO-Ig}tn{ zDC8|XiwiZyT|&UF5VjD)M(n;5uSTPG4XvpMcHhBOqa9o|+QC&rnh(dtcW~8c2Um?+ zO^w=14YS0}xcd&S8d`^k;5)c#XdTYJgR6$t;p{uOYG@tKzJsfV*5T|sxN6LIaMhUa z;Hoj-!Bu0vgR91T2Um^SOO4t~joM3%deIv7qBZJ8Yt)O@sJ+yvz0_#eP>psC)o9mH zjdl&y(7SqSeFs;K^k1VLTs493;Hn9Z@f>LfR}E^s#A>vIi_`bG=Tu5Ll~PWnlv63? zR7yFOQck6mQz_+CN;#EMPNkGnDdkj3Ih9gQrIb@C?;>{xQ+m^2 zzDmQa3BY`nhFKMd`6>7xG=84qs4rc#?BlV=BqT!S8159(lB48 zVZKVke3gdzDh=~h8s@7s%vWicuhKAIrD48G!+e#7`6>Hl8arR5gMbAr3!vulDNvH zigKxbArHXQ?qFkydmnzDoigKxbArHXQ?qFkydmnzDoigKx2iuqQdul1{IXsM%YzRAyrf`j;zP-s;H1EDx``Ese<2* zlz&%6g;Y@?Ra8h76;efoR8b*SR7e#SQbmQ&LwL$nQ6W`SNEH=8rm zu^of9^pnnfU4;2+1oJfjX010kQhtt}42(!ZwW``ln4nvq7hA=w}VRjh8>@bAcVF@bAcVF`{yJ$PY<}4x1SwfhdT`*?}Va^i5DKTdWv1i1rD`RKH7iKLMW|b6X{SxLZ zA62hD%gxO~Tvs(=2Dq(YVFI6(n+cztn*fiN{d~EP6|*x9 z_e!NCDNc#g;*5BD-8B5nkWXf+*qN!q%v51!sxUKEc%jnpfcR;-Jfj$wEA|!QmEu+6 z)naz3@hrR4;C15H#2XaO7TIfL&pFdWlB3`t*$q(A(NDszmR;V;;7+o4 z5qsJ0vZKY_IES#yy35`}Onbzox9ojn?<+fJH*oJ?$M+J{6@>@NeUMyEQ@m%%g}r~= z9W6dTcOdq$Irby^C=Ank!}Q)Ty*Etn4bywW)5Wx6?6hK-Rt(dMVOlXvD~1;+-i3F*~BMVGV2-6e7^n@@Y3(Uv@GqS+!U56Q2VD_%V>|KZ1yAHE=9cE;K7uRip z8ChWVuEXqIhuOOhGqS+!U5DAb4zqV1X74)8$O5x>9cJ%3%*X;WvcQZiFe3}h$O1F6 zz>F-d=K9D2GqS*pEHEPr%*X;Wvb6HAD%|xRvekxGpXATjc&b@$cdJt+v7swfYGDX{(Rj-SYp2 zVie;sj(xWV+svZ4$0nL3Ht{PFoxwb?oxfIgC)i@vgkNH4f}bY%X|kHX1U3jP;ix!a zG~<^knh!VIuNl~Cw*O?a7Wi$+GcCse{IqHd#shv|;eh342lg>Lh@<8Q5%$4T!A`S7 z@Oubher*(325>9C!mNVuD@a$H4Q7Yp_plg9nH@gTtSw<4F%G6Dc?@~!H5?E}?>hm0`x1ZOcg>E)>~|}FUTu-tz|Llac5tSic#oeCUNt*mwb_tC z1#ta!;y!Vt*-7MaC}9mHO{cU0n5XVE8-{t>LO|H3$IQ;a?-_(Oyfq*X-)IlEn2jJ^ zBet5IIRs1uggugbBbS(+bray3v(|vkW@i)T+1rdiUj}&YoQuIsvr!w&Mw7SEF9YHm zz1{3w;yL#?FcOf)bMFMp%+4ds^9cLAEFjD=rC<=4Xm)-dv$2?CQ(!)L)$9V|x}XhM zWHyfLafE##VPA;f3yJ^2d4M=Cngx~s!o7%axn&o(2ZVj`C@>We=C_7}@!%%FGv8Vc zwwPVo43N(8JUf1e*|)j=c2_VCT+5#tY7K^h$$&U7Bc98)f?Bi7xpz5!FX#T{gmL+; z06&+L-^(|FZTu;K7{JdJgTPL+@3a7Yz!-27m<5&q!u`%>vnxsemH5AMB)Asb2^N8M zfb?ET7!wF%!Vr)$o7fC21Ux_S6SGNNPwELqfvI37cnrL2c2#>Y3`_*LU$q>(3bvYk zcN5rVHW@#YN$cc`0nbmK5AZjcu&0a%JIt;=1mNfDQGl?n#?RI30O`AiXRd7xNZ+-D zaqXR83CM!YX4lMs0!zRq zvuQj#Z6|*M@@25W?3R?-t;BchYO~u&Q)Ma00{kYg09(yccbcWg1D?rDHoLtuc+712 z#r*k6!u!DxvpWdmj)`Ei*`1{4hfB=W(x`9 zfrVxdE;DU6)qlEuxPcRHz45os4 z0Dq5e;m_`rg0^4?xEQ3sd_X=QdlhU2wPuf#r^ma3p@2L-J`v#ear{1x-^cO$IDQus z?h{MEyI{N762f0H9E=Ayfmwk2OR`|I+0qzj1Ns2`Eydqb{5{zk;O|NNJ&C_3cbGlZ z473M>z$h>gq`-Wz9J~s)f?EFk5YI2`3WkDl;977eSOnI9O<@!%#f z3oHRyuo>(yd%78*?4IcghJxv!mOoj#&};>MS5gP7cy{%*;7+gztO1+AHnV4Apbh8) zhJ*0{|If|>JpXLg?72h0e6#2A`}`GVYlfM<&=uhJBG0{upO>i5mr`ag4+1>9mS@(I zhAP5(1-DlS`<3NpS?V)eYxXnJTs_9@=dJmvB<`)#RH?+N?& zTg|r40$hL83|wpWu>s6KVE%zP{;=BYlUL0?oox2Uo4|InKg|b(vu&pNpQp1wr_BD+ z8Ei58PyFG<{>Js+mYe;(joA*u{*1KzV+h#5pTrsu$jeTi{}=B6B94EpGut(fzoR(@ zkj@(J*Y*Sx`CYH}fUxU`H;4b+4t{-SnFYaA3nKhkyvQaCqF3-IU7LY-E#Q}*-+Jj|)u$wde zYtFOHvG2$I{RnTrmjPkzx6Ok6n*rkAev_?4Ypd)lJHvM zr{xX{T3rkX>wsGUVYMdS)?>gT@Tvs|67PYe=fEXkiv$#Ev?m~)6;r_{7PN^0^3sOuHu!6k z1zP~=J(Tbd<@rMi^U#R^_rrMpuu%a2hb;mxgY6a^-WK!$!vJv|{w~;NL0bcz0b#VA z1(pHgXv_U0ngO0Wg6EFlxg$u|5v#!_K$u6i06oD?U?Es%K|9>q4F$yA?qz`AcAtP+ z3)&N2`?i4a+K&OZg2w>Qb>Nu}gxz6-1szKP;R=&6r-S)mGuUoHr%~VvK)jvif#nu- z?hFQj@!(pJ0`9)mf-bEA;ddDYxZj0mx;zF*Uzc~mCl(xa93af2NYha>!4j|z@cdD= z794#DAWcUP17iSwk6vg&SMt=g4d@Dpzw0)D|8BTUm_;MA^w=Z4`vjC7vH^=X88 z+D;2j=eg5gwcrfObod$zzA+MPwqV3e3(lMhwp%drVhhe9eP?AYIC~7h?Ht_B;ki*) zSTMRR=m~~^k>F(u&Lxg>2Z7;WoCW7`eIDr?^S{WuAGpfLwDIHDec#`6PL9~njF5GV z5HdmtvCT{~)2wDDGiOXgsF|86no6CSX$T>N5JCtcgpd`RmEG*NE5x?6HoGA#%GZ~t4`D^#;&6Fs(w)? zSAn*Zo6rVwokGo1Mnq-vnq3O!o=t!Dgs4*^z~@sN&?o9NYMoXj>hv5@IWb_)xen;h zC4M#Wt7%^y4|1)pLLJDrCJqA_5tWyUMldEn55t%g#eKh87mGnr1r?xnVJ1dJox%7s zTG1)$OkRtKEgBNF-iJ0(#ZhR$n5Ys#If&GWOgdQRgL#I-eX>4yr)?3mAK0m#B;4K<$ef(1LMM)oGwkHFYkI0du{i zUeu+Gy|f98yL14ohZ^Q_896R16?J(8QjiDQFK1r0QLwMWm=tv-b*@SVuUGq!gJw~6 z4j5NQ&TFbb{IzLd9@jFDYdgUB>(Wt&K~eSb=n-{&0R}|fK>Q6YqHc^plc)yj+>{{d zW%wM2n=wotFd59+kg z-_n3K^nm%ckpDhn?~6w=(vbt=@2f)#21MQOAR5%YKLzBxzX;W61arB+7sHqo^#HLC zBp?msd0-IZqFN)-AnHN#JjmDwiGL^wynl#s4^y{|IXuF6?swG>sQqZIsCL@gM@2ox z`^TvFcp|z){gCz__KNE8BM$*E?g?I>VC;`l(Io207*L}#770i}2C_vx6@d;>KW4dq z5()Z#QY5M?8l9q^t`POpSk#F6SsaM%&cvjspOf)@ z^Gl`Z#)znwnOi?`{iC9O&Dd8WK+fO9qDj<1gQ!=@^(t+z67$;{QNODM^B5%dHLF(C z>lLEjNJcuSH^jK17Ey1K^UZ2eZxw;@Z%vB&eU+%;Ec9bo)Z5JKZQ9>qPVdn62bN=m zIgYe}G4CcI8+?8*8Y##FW8aTL2B`CXHE0{9ZIqZ%YK+o0+KCZSAJF~*Z67eN4~YA) z9%G{ZSb=U)V@W6g@gK#2{*QV^aqq4ER0HPnXKIZ*Apbc19~1X+m#DuagV#?|(IaXi z9ZjORA6I|1uN~;ah^S8)^J$K#zX{sF945&(nGND5iTNxGzVM?3U82Q7ECw+yT6LgLv`&E^{TLN(h%>~QB#eo6GQk-BZR^^V4c@zJ z(1c#mo+8wvO>{&GvOq4L(dzAT5CHMsXwdJa-)lb)iQb-k+w&TkjymvuheWi1Iy=T9 z73A1)K=gMQ_nl@;h>nUvJm`MY=RDhhjHK7BjUHY9-{Y*L>6e@b5Qhm6TrB=;^0T0Xuex$AM^9o zgP6U^v-gPTS>%}2D|#RD?b9GSE(QV7`$nMv#O%j<*pE5xp903m6C0lg@*Y4=?&CH0 z?)tzC(Fd{a4kGtK9ikHi@uS+nTnEu#I= zqF2O;J}DA)pyolm(WjB`v`W#Z z6L&iGa>$#LjaJdQi6EZ)W4*cp)L7GiQPFuxsKbcp{ALidHcRw69|9NHBIdh+qySr>PRE{O*9OL;A=6n&Nh;?L?AT}I9_ zV#;YN4~Py#fck-M(HrR7Fd=#)pEvS(Q!-edia0cYzRd;b!KCQ3GthxP41xZ0@<7dV z>cQB`SR{eiO8P44tE7)-zq*ndm4g@;eQqSEb8ZU!C_*(F(T-k_|GXF^BY-xHiatLP zf*mZv@*&FB<;J^k0ye|;~8F)8|n z0BS+Z4aD5gk5SP#I*3IQs?jaFfo;}6?glLEfp#yyw5q*mw28k#@GZ^2<_(ncAR)IM+GN)S|Q0rD|-O8MACH7Y4d@KF8(tjKM zw=w72l8}KsRH7cO=*FPv+Y``+VbM(~pudU!JL187@94q+#zfy40Uwf)3FdSsbGowu zPI*bf6C-qWLoveJ}m@GWQli5$J27@4gJM?DzG8WxSuyd@s}Y^Z9{9F!q5Q z@VPYto#+?+U=67A5P2V>?!$3l{XFbP5e7uJ@xF~ZkC5|`9t>eZ^bZ2475!)=822dS z9wqkCUeWE;Y;QoD=*OawfI75@ew_M`#~>c5$U-Sj`Q-LHiTcXcYaUD0GT`lD;SDdy*VaGPaW(omJ=-{giHCg89DCiCz%j{%Qrt^XjnZ-;(RMzfmfB$U!`^F(LX* z;@@I!Z;|gU=K0pB=-+3e4uhhHiRI6H^l-1}w-Z3_w~2YD0L+E&wECS9Op5*kdHxWG zWYnVtouWrlkbzp!@5aCn+TV)>%kX|8$TiB`M$^$J`UCntAnt=|w1Ju*rh$2W*nt7j ze=G&i8!Rdk0Ml~5$)*3FeXKR z8jU0n_bG9o689-_pAz>eai0?RDRF-z?r#Z5LpB1aMKe0lk5SQ+4q}mn4CJ8_^=L&m zhA}DnvuGqB4cQ2w7R~5HKSo7=?jROP$Uq({QIA%1V-Vw_zlcTx(vXb+YSD~N^kY5UJPSW%=XbpKnC(qiF&l68-o}Z6B&s(q`;3NRHG5?=*6&@9UR0W z2^q*kCF;?NZVX~v%#M+WLkj#TLNyxEj$RC7Qp|Uvk$^O0BY;{oqZ9oY6%*wk5k;s5 zxuVDw)r(<}YbSE;lz=plYo`j-p%pzC!i1QeqY#f&WT6x_Xhs(XF)oJZE@l_9wqb!U)o z26bmpcLsH55;v2&Gt-fWO4NgVGrK|DOyYKp1a)^M->&4_mAbo9ch?q>Z`T2giHV7T z56Q?x5vtJymLsMgqhfY*5Q`*aAP>~utsZUY#ju#&1;p)6zTN#G-|ociPTcOz=mfF5 z+t_h2dqjfxJ(7@yY%pezYBZu9#P31;9+P5Xqmck&V~LFopcc*OL_bEw?CBsDNytDR zDp8MCbYl?XV!j)RIHbUjB2=Rh?dZiYCdKR(jRd428v)d!8J+0Is2HDvSR^3>d8kA^ zTG5R`5W6?Adq*P<^zYpaa_!v@`e)HUi(Ipkz&4td19Hu(1+lZb!1kQQ_S}c<$+IrA z59@y)_K|&v-KPR|VB7E04f5_oY#gz1#KsXDN8Y#s5F1Bq9I5`x3iv9GJtt z#PaOS>`UyvHE2Qy`Ync7K zte^OH42U^^IUi65`VaJ>0+V76N&#~_h#UuXiAjh?!vEdD9b#tpfMq>IK+Z$Rb%-AU zG>A!z0CPxWZi&Pmng(he%GkqVz~{pXP>o(NpTntrIPHgLqXNTXl46koawV}0Nz5~8 z0OMkgAkPuR9Z`!RF-J20BU3=^k<>hLRLoKFp#P{&O#I`Lshv#SqZ`E>!?GU3`(rx9 z9LwB~WezFiPhrj}MQ8@|IL;6Hk7FLk5q})*$1&!(Uf6!d9Up;MB!cnBXMr5YSD_v) zV9v+)VOY%f=uc%#Y6Awu%t=MJn7Qd<<|SZKOd4b6M1 zf!7o0&nQ5nn8nOvG5HqfpayLi5wnE6OY+1lCErr=X9iF!=EQa}%Q8XCvI#NEskxjO zKd~$PXclvlfP5?ITiGNgt4ho&+E!JfOH4MkPmMyinA4KbFXr@7F*)SSZ4k4XIjqS7 z`SW^N%Uj$k zri6SY)F~lHX%WW6oK+1zm&Jp&GUi&Ih)e{~Bql(f0C_j?c>{SiM#H|cjy92d6LZ;= z2Xbv{MmL7VR5*x38uCz$W^`j1jNcrIIHVyP%wcmin$e44jEgy&xU&;Lt+O*g?Ab-A zL_ONki$M^7PBe%;$B#S^cTOW((FtPD85C2QBj#LQ&!g=;+Ro$s`ROPSQx$_AF&9*b zxsdg95$)AQXaup$N5gwHOd{8GV0cXhv*x=4_(jyYY!T&}6cn3!uD#9WsO^3?l4 zUwtWt#qj*hTweilT;BomT+f&rsC7dX$aP~BsC6UbZX`!TBFM=zGjmf6vcTt?nA6Rf zs6(HaTcW_{TljnnpBu^1Sc4%kwpg;qDla70x=Lbi`JQM{#$nh|74`+k-Z7g3~3Nk^Swl;K$ zdBg|uJVN^;jQ>FsX#WB0|Is=z?Tl&90?XAtD&{f9JvJ!jaR)5t)Wj`6;=6 z+Aij2)a_2jfS8}xi1|e+hQ&O?T%TcFPZ6rojBe2PYy{##`?F(Wo@4xTmFN`nJblkI zuU_i(wuyOxJTLT!d69ZAR$)}kFNy6Vu8;Zk)qy&{$_6!lH6rGvQVfcDIT6%&c}z?{ z{r$B4+Aro6#=g=i<~M?Lu&e|04>X`p%&Tz-i21F9Ix)W^?suhNd4ET(!8{Q68gZ`? z_u814*Xe(q{QO?PywQR#F+)D&pcw;V-i$;Nvc$Z_*tcl=J+Z^&dpkzVJJfk+Sj-=Y zA0cLhz7amZOU`$zz?|P567yaJSU>M&g7){?K>PbXupI9ece`1~jPxnInmQ&A1#$LSwW zL=Nm{=J0V6I>h`X1?^%!VcwtAU{uUR9H=+ZCFZX_RG?SPr{wvR_)nR~r^90YM*CzW zs5?0*=CgS4p63$g^E~kS1)sm@6-VOGAdZSa0y0pFdT}&un)kW~L*f`e+Qo6=LBETB z7yW!kcigFH#(+4UOjLqc&#*WVQD96&I-1Z0@@*&Zf%fglvmNu;j=t^a^CpS2eIop* z0DaqcU_hKm+9PYwFU}5;pnnJ2cdo;vIJ=N*mn!gimnO7_G=0%6=mxPfs52uI zAEjw!^AG`(Zs873c6MB*KphG@=uOm=q_8xh188{7LjBF)oRmN6>x*b2}mc z+K=c4?MKEU4YVKG1mcgR{V3XxBF|CeIjRA~A4Pj|3{p^ldURq~oTH;a`_Xxz{b=$W zJt@vHiJ%^@9Mqx< zqvCvzd3`Sf6==qQINa+xsnkkkd@6ZUhsBu_2XfA-K@XVYTj)!kn?nMoKB9@YhXVQiIWorKd75STTUOym&>@^bOg|Z9*l{znwqOi zL9NxyWlbXZyrvCf;^gr;kN5e!=JUFi*R@%wLJRsaCeFH8BqK+hf=qOZQ%J2cVmG9K z_ZtSp*%*&naW?rdDo#a*IGY)}xl5eNG;z*n-JPEe@>Vh5swQzR6mc$U#ke@tjK7%p zi>Y}@jX0P3Ff2|D{g;)Bb9s_DS9XeX6?3_oJav=e)aQYi>x(cX&JAhk5$8tc*3cx* zO?~3rOy4bnc2N5kYBfe934R1nk9KixV-B}Xh;utRnrOeHPMkaAK;K>Dxrbu`L#5Pb02Z{r-<`FB&x(|B~L4_55|h~Py}kkdALoSM+U|D zL4`PvGKY5FKQ<=L56Rn6iAiyuAoq`2#d$In%%d|4)Om`}KPJzQvr#L~Psr8Ph(U3l zW)4sD{^?0^ewqp1|11&Y=AO>^#jrTf@Y+K^_i4`a=*<@Ag*tJ#A9H@`7pE^roL@DF z^AclT9v7#dzF!NN!z(S~{ANg;R~hrWSagUpSOMBzD+0^*S{r&`+a|<$JqqM_ozHLN zi8I95H<|xi2^bOQ_od-eiR*+&RDk(p zkSC*ET#I9ngiI8n6%*p(JndS-vMpsEOB=0X6)X$qVHf9N*9zJ>|GGHux>hD)P+Y5G(JZc$JH?evUv{^+PLC2-PNTS1 z^SXLiTx&+el`kNEE!K^TtAKok2%r)6^Q5>o#-a$F7!lW|803K5o9M5|0LxxM-{w^C z{%q!THvQ)a($OTY$^^8E>)d2R-s%3kSt@5qU0R z+(l`~2FqE^Se{Y1F0K_9=UUgLjJb3~T$j;)SvqLDY*<{E`@opXTQDxJE2t5~xGR{? z6`knAsJLnwTbqDXFs7E++D3F>P+V6E=)aQwE9t+I{wwLflKv~{zl#2==)a2kR~4ZS zofs0=)saXB?N?WUaaS|$YQ|kXA+EYukhhNhI_6&23g*Q%!gY-g8K?m5*YsdiT-Qb+ z1v#h%`L3n?I@+(J{kj4)g81vmQ=f<;P`{q`dgAK`LH+AvL4B@6uIs6PeJiMcJ>zbm z{tX$R{tdL>K)xGB#dRZfZcG97Z>$CRZlt||_6FJ;sNc{C;v2|w6ZLN@0{L%h1^I8H z{bustoB{IROgqnBTsPBxOFXhc{4Jdr6Bo~5T#cEiL<}F5#k;p?guf*KoyAl!I-!nO+W!!LH_ngkiVUA?Tl+5 z71v|rf2;^i7!=pz7*V7Kj|1>#%>KE6~1k9zI@!ieh`gt;l`$Y~I z^GpDf;_9iwkhq>rMJ8&|4Pu`i7uR#tdX75JrGUK8^ZxlUarF}4TPLm;XnQdVsOg*7uQR%pw>&Bp#IB@d6{+gGIM^J{+B1k)t>=s|C-#tCdVuE zy)q`Q-!S*zRANY61N05lgXMfR2gLoB@xP;uXHc%!l2C;nalKBB*R#+B;@?OEIo}}m z4d(F%Z9~x@=Me2f%@`Edn~Zxi9prhl9Yf-JD-z7(tsK;$3(W2JKJ&EpAmOZk;S{6N^gpi`&T-w<})U?nrTaqL7DxxFg!cy@GPd1@Y0W;~A{q8El6cDPTR$j71Sxm%I8wzFo(}9g~Ov zh>7XNu()^20`GSl75DCu;@+bk$hRLk_G=XP{)wmnbB@o%khl*>!yw3U067k1E(g+gAo&k$7570&AZJ3UxDRGN z2isTTXEUeSj5&mShma>R148=n?nfu}DA`nn1q8C&ZmZ zOcME%>d=k>knafMk4OalM=<6H@*F|T5!5@P1HE7lM>>cBxsOZ*b3C#FwV=+C_>hcD6rc(XXhRQ%Fd^vQUZ|G@%217!mhUK@1X+jvQ2=4lU@y0LH|f z837-Xk%~b2^RK)2MM8<4&W-X?@~8ov}Gd=*OtIa~;Hjw%jyvucr3uR&lSP_L>4v zdkuNlw1FIX#N_clpZNR?aML8_qu5CejV}avJpTnh*{T(evFE{zyb9O zl0a->6v%f5?PrkV43_H*;?ES&cP6!qm}8NB?ZFTx#J!%r^|Y^NuEl-~V_e)Nj4z?B zGzGMm7NHuAXh$!IEu9qiS zR8XUW8Wq&o>_a-JvAGf5pvKwMIGY-0Q{(J9bbuP?L?Q{)IENbNP~#kGR0`rjjmkn#C*~RnYZ!A) zlen)H_|c3JkmI@t#2_BYNJkb5P=OjWpamW1!2m`uA@2GJ#2_BYNJkb5P=OjWpamW1 z!2m`uA@1uV5QBImBOO^NKm}^hfEIM12Ll+vgt%{rKn&u+^4`!d?i*R&8|iCceKfR- z`=(T|PHxV^Fvi7wi-TyyAqm9Z;zu3=s74#8(@5K`K5^d`EAHFL(bO;QJ8Q&!mxC^G zH{ySWk#uoCnkMeYho zW`}ro9Tm@RIpWzPRy=#gh-WXqc=qlRPh3De`_i|6i+Bzo$3gw#na%h^8J{HLIig!U zNA-&5m}v2&(Eq(`@yyK-&-_X>iDyBPcotG;;edG3tHiU2{MaA!)FNVd#eTe6zWMrZlouI}^j9=-1@hj87_?2BC_sSuRi6@Kv zSxKk`W3w2WMc*p&t@5J?)o4UJsJUtwlj1o!8W~{h$=%{Ph4@p(#gk2Z_NaJHrQWHu zpGwCI~gW}1dFNeIjmEz%=?pbYL`^B>+0gTTp5Kq2?9PoK9F>8rg zJ0zZUDd-eWK`Q7gq(WeSxyE@m5nDljMH7hGoQFa2oSg}l;~Z+7GbEnM zMATqFJm>QM+&YYi=R9(r*CQUTHJeJ|rU(r6A_gHV|{^ z5Xe;%g?NywhFmqo)zqK~9q7Y|crFvfAQ{A6R)IRSpbG;S6VK%l@PW9?GchTiE7(3) z&{s=eEq%50)zVj6fGRYg4Lumbgm|uuLOfEDg;La@2_5LehirHo-x`1N z)cYMJ>Dbj%@1tbRD6oT@s@gOuctYv|c~;K0;>ctES#>FURQasrNhVdyM(+)cYN!;FyW2_fazQ*c+$b z?<5h&J}L90L`r3|lu4niV+{wyC-JgI4&e1LN#uWr^KLZ}KAB5QK*~`j`I0N^C4tsO zQcV18-p!FB{^yfrU*;+ge#&P|K4UiW&paZ%-=gY~j0{!vQ)wf$&S0j+%+byxmzn-! z71OAF2IEeW4P;ou_}pMNJ2xNi?GpKzcQOAgC1y2CQb?SS8JAE!H`wPDnO9P}xvX$q zLBJQk<^bPeiHV2%R&VyrEewubJ(eQ&i+zW~0h|%ksjGkH@|!au*wkZ%)nQgHj0vySXGvU|>K_M5{* zPRcJUFDxnc9X9)LK5d!mEAtCYZ_5CmtPN(fdz_DbF0{vm7iVorG3z$K8kgW+8(^y) z!++oG5VlunOK)T=&Sq>0uVrk>{9wK^_Mm*)i}`1Op@Bf@F^3$I#|qxKVRm`RhO#yJ zYfH-3<+xGn8m4p9<|Jmx>=KRl}v%c=^=i_W*&uey>3)vdp;5&PE%nj~^_N-CH z!RBLotmU8EuC*=CpLWSIgZb76vrQjOHn)%MZENLEofX#wtJrO7+#-R_}%FH|kG zkA?Pk+aF*S_DokCJeQXSv)QA=924bW%Lf0o?~>{6|v$6g)0yxJuQ1ZT1Jk(o=B zjkEhZ`VtBTYFiW@D;3_TDJe|mczD(mh%wiQ^qH|bwbzhQ0_uL+sa#S z{qXVq^-CRIbD{k$w4a5R(9X-wGPKuCFVUvp`mkrL@N)nC3ZWy-?t%8KZueHZg!UK+ z@8Nb&u}e}CT<-GVnmB`qHNo{AnpJrFttHAXuRTwPw~$?OyC>Rh657Mcxw6=!(;uv4 z*V$@f?A^@tHkjU0;dN@~v+bFnn2|QG-OKD6m|k1qV`X}c+2bI*k8e57E}gx9u`~BF z7dwwF_qEX4uq`(K-`}2gIqlfcwqGB74SnA7SpTMN5eQz1?3LA?1?&>pySwQ%^-W{# z+0ourhURap+jVY_>Zpv&O_^Y16k}R zFQ4t6VvhwoQ+vN_&qv|CdmVAp*VRy^@Hx~jU1%mYKD1`T*}}_cd%k&@!du&3C+reT z?_qXHeaz?E&S2|0UtJ&D9!KTDW5I53Tfr{DmRr~!1);kGJ2ShseZhYg^U0o9!t2>b zRH(%+YiN%Q9RZ;;vRyBhy?W#amo9Y8nx4<5;69cYT~U_Oj6RC4*{q{|jGV>^>E`CWVf&V$K4g;~;#zZKO`&7E2bcmoF8;Ep3;`Zm&}Q z7rJ`cquyR+!snSSw|i*L;TG>U*PGB9u-7bm9k*Aw(0*@cZ1vXv-ch0jQ@!<)mM+!>7@#N@3co}=z6&J%l$1~<};@S zvQ(CEHL%yerF`FY?mT5v&DQ`M*j4vInN>YqF_Ed{{-f> zAeeVaaFiWq*PNZ{9Axs(WmH{6h82vmpKR+2UNebX&Zy8l?E15_T|(>%?wlJD2G!_IsDD z9h!$-|0hl5v-^Nu{tW(S*R5TT%Yzl>)4G_pP~K2h`|ZsxiJiAyJ9gXKZEEMYh)=e{ zT>3&=#jekc;HT;J7TOo=Hl4$W#le}|@peh<8VPM3JNqq{#BSrSZk?~&JG?}ND%f0h zyV*6B5v;PDH9MbeWiy3Z>>9EAmEH5_u>{k5Txh?y>pL79S_^jjED3Je6It@m7769E z-;lRl3cH?d2n9wT-ivs=mbg^y2L!|pqwbHIw=*l<=mZtL~yBhns6;kfX)Z#s8`)={|j)?3i- zt#)08W*9n?*!2*~8`_sbN5WUnNujg+e6DNu3RyaJT`Om7=uS8My)Sf~pT4&VU3<2? z@3d7T%r3)8yBi(*KlYyHcM!2hVKxz{pREi&c#NCzZu$Zr1tK= zj69oy?*qYE74tclS%hM3%-MVne^=S^`A>NE)7v2QZ04)mAiONwu7B@V>)+lPma_+i zzDpGb*RZ{xoXw2vlG&MtzL$k6+s}3ltPS?rd)DwQ?RuQv`|Q2-F~PCn`%t@t_Fl=} zp@;STCTGwc6N&x1nGw(K_B z^1dv*huJM0`UYXQ+`sdAkgdDz^Pte)@ZWnLWM>h2I`wt;;?w7eE$`&l1oz?a69gM$ zpG$<-*tW;omQNGI`|`Hu342|%$JGDCbEPf+WF+)l$v&5}XSS`Mk4>M`|NnZfH2s9Z z9uNQTJy-H>b%p((d#+^HqkR(dzwNn_eSW#^bEWBH`oHsB$@>k@3;sLLl|pxNq4T{x z*6q3fo1ZJ$tHQtkxzhCU7Jf=(ul=*QC;s|BF`gBitGz1;pM}HYLf_9rcM|{Go-T#% zctUqrp{G*IS>s#&X+~&yLU&C6*{4hPDcs*%yY^dDcn$vVe#+!!f3?@*uinl4_n$J^ zYx)1yr%YbHac=pPY5KeFfAcAmH~6gNo1QY+Bf~y*`OiOPvd`J<6S;5ml*xWG|Ia*S zvdt|vbB+mHQK(m(ga$3E4uXa9foiI10if$%SW{@$AWcRisAY;$Lo%2_A;%M)+# zsf_(JTVz4-2U_;0YW8<>U;aMM7hj&A?^~T;RI=%S*}iY_!?xMJg+-f73(9?k>q|?@ z0{MBqwPhvieRIn4H~K<90t?p&{*Z1%=!bM$mhpP0tMhxbTwiEvU;Y};d+;~@pLg5e z?S1Q?{B5z^!ODf@-dtaxEH^KIeQw#AzLK@m0ihobdcB$XW$O#egFl)pEcX@Um*w*t z!F6T1#VmRP%g)+k7(WH%M`{VaK#4E6c(bpRpV{#%yOPxbehOH~D#-P%;dhE&A_E2a z;q|m;P09LF!fimHfb9HyFu%B*Ei@~*N@g8EvOHgId3nj2!d&Wk^GeoiSf5`U$PL&Z z@vSW^;@5}qHe+yrZ+Xeuz$RAztOJ5GDa$V{E6LliCO?=auaI9v7Ovh9$hULw+6rF| zNZ|L2Yl=4H*_muA3>1`X2r!xTg;RxWh2U>2`GsGJZ$mi?Y8NNLw?5x4wKw?7$MS*% z-*k-xTl0{TGGBQ~>&p&C}VmV8S*)Pg` z>q|J`zHYI7fz74)YjY_yJ2a`SmvMdWW)4b*=M}Ckv^!dEQGi{KHzdu?%L^`fa2*GK zd74|soHrEZmU->!%F8b=Tvr@i-RnZfDue7En!AQ19J$3`uGMniS1Q@X_EI3Y!g7mz zUz=cROn4sC*_d8&(Pm%a7Q4CEo({_Li*wh9ww8TU?qfyT?Gipb^4aI|%Yu0}m6YX` z`(}N4ikM}W*e;dr@XoS_?X2J`W6NYr9WSf%Ig)JF4QvCu-8PmK26qiRF25qc5#!4( zE#>gaU0uZPUov&dA+ufW-tcilo!o%0Ah(=#pI`jt+7G6r-1Od^=i5-6H#Onusd|Hx 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 literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/fonts/FF_FONT0.gdf b/web/public_php/admin/jpgraph/fonts/FF_FONT0.gdf new file mode 100644 index 0000000000000000000000000000000000000000..e231b71314a9c610c3ec07463c8da6d7b81015b4 GIT binary patch literal 13456 zcmeHJO`0n=2%Onu@lKKZpDITQRRsbh)b_k2UpDUP!3gSyroHfAUteE;+W#N+|I7aW zz3ZD&XRHqDmdf{+l^9C#N2$ot`L@gDkVZZkaFT#5;1@V{ITZ(DAlk2m0GBL_y~sz~ zc~W7uOfFv({6Qo-l2sgAeZ+opODk4^Gxv6UEPNDBMyW8>xw;3!KD8?oL+wOXR?9R&)C7R)Ke3pm)aE{6Vg&dNcJZ!Z|S zY2L!!7X||>ifki{7aRU{kO(3!z!^MlbU_>t-=~GQ1i4f;ChHEM7YfIH&)RU5diBvLE!aI0734Ws(hMJ+~;O~o5!9sO!C}=PaPA z?xP&!!ip#5C};hkLY&2S;=62UX=9dQox`;-fN%x@dDNLvp$kaxMU35bs>^XEH-vls z0ib&$+L4Zhh4%t1@kLU=jn8>p0WIQtw3Dg>l}^b@H8-R3#^W)OyQ4{hh3PFB1VFv{ zsvh0J7*vWbX;y#?E`4WeOh&XgbKL2C46^lfQ-tsExUmAXa>Vis4^In}X)1z^OpzHo zDB<2OmPCfNju|au^UhUg$5FxklyAmZLjf_}f=v^cMfL%CF7)Qq>N+ewfmYK)>ABqn z$Z*_QzL>ksK9E0~e0iX0&hZ~*ZDIZt$HV-VcYO%D_yaY^RF;>IjY zjgKdZ`0%}2GFRVt?+ZC3;k)KkvV1Yj?eZZB5w6A?OZD)@DZahN*0W61BJH43;m)8m zF>4JL)BRw)=nyAaNygWq>+dTh07CzE*_zqj0# zR5_v}k9sq{b)V}T`-T3YP$sw3+I%aw4ZNyL?K!^E_-Fm<{Zpk6_x+81cJlM7=C3DrC&|QFB1PHRO?;zJXP$RPruMkovcVD zew6ts+h_LfzSnO>)2z8E(nVG!J*`-2T;FiAq%u=?2Tm@9`1yOGCsXcr&QcwJHukDd zUYJg`#!O6Ta8c=BtCv)6+feI>JZlBTmFS!_xIuCKf zEL*KY52)PZTgH-st^eCc86wl;715D&f)W{gRO~ZNBy^t4=ei1u@G*VIsLv<`SUeYg+H*;=1nZ3}rges=Y+oUQfQ)wYm_<7Zb7 R%h_6=U2O|_IKH#1zX90U34#Cs literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/fonts/FF_FONT1-Bold.gdf b/web/public_php/admin/jpgraph/fonts/FF_FONT1-Bold.gdf new file mode 100644 index 0000000000000000000000000000000000000000..d62f0b3bb7e4fbd2cda2f1741604b65b42df4b76 GIT binary patch literal 18832 zcmeH}Te2KC4n(Cd|I8w0|Erp%82JE66v66;G!BPd9qs}FA`g=6QuzMw$B!TXjqe}v z{ZD-VpP!#UNq-|$7ZzNLDF2L4)E#Qa_t{FtIzD5@ns6ufRLgLgOM~8%U^GU`W=CR{ zmSt*4F4#zOf75YKP~tdn?P_rvkTTQNnMK{TaWo(gx}DvlD>du~`K%&ZVU{EhSBsZw zrX20gto3QdDJ!*{gYoKeWJx6F1D#HY{Q-bsV{8#=cfI#oVB=YW)7t>StGYi2rYVr6RdV-_Ij^n;=E(Bmp;`Rbk}gF{~~(3p~lu^=80-$%UF294C?9$ z9ylHIVl^@s=bqX&r__DL+)%SXD|t~o)nW{rv^fGh*(Tux&6OyJi^L)Lt9a%fCTLkn zcDyupb{Cqu1yz=vX1M_LMhh*E5UFJa#bkDB#YVT!uv}m?Si`szKRs+zIdMlXB8>U=_6#qHoW#RT%u0ehN5gM$MtJqzvYK;M7DEeLbnsZ>%81>y+?E+ zxIq0B?#_OiVxE{WpxD(Wo~MuY+>uE}ipn1CN7=;_b*sY|ok6H18B3O%SGlKM1CW4$ zq-7tjIOmXT9~a*Un-qm#WJ+EjCnu=m>Nu1q8Cl*!?}oll)a49!Eo8j&fF~P8(EpR$ z@D7bV6N&SQ-iNo5d6Ty=o#cJy@X5F0fcEY9V6WkV9$*|4S3zj7&^80t-NXG>RZ-14 zbzc+HKGO)SrAI`=djhLvdjM+-rR_yPK`#UUUguxZ z{A0>*hy;<~4=n$c^=%Mqdwz?vCCfMLCxv8O<4cBbsa)1e(P+T6dgKgkF(k8NBx!d5 zPm3$lV?DefpFplR3b72nxJ~bO)D;Ozr))qLq+jjR-Bv?0`Lf&Y-tGl zixzU6B(ucs z3QEHz(ewjxSX<4F39%qd0cEyD$V#21>ezIeXCiB~5EU7!qqt0~}i#!;|c?;LeK3=AdY{5pye15p2t_4nv*l0+~(m~yPgg{9~WLF}=1Z;-c>t(IfPlwT zj!Xi@b?lg@j{1}#)Docm69)Z;R}ctuZ=Zj&x9b-4)Xkyh*719{oW{uK7Q-$%Nh?6vTw<6*`d var{Seb8&~Q=RTkNJiHnom!Eg(d6zzZX%2$tU3%W7!>jRe`FWTAvG3BKjN1_> literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/fonts/FF_FONT1.gdf b/web/public_php/admin/jpgraph/fonts/FF_FONT1.gdf new file mode 100644 index 0000000000000000000000000000000000000000..7b5b0f628b7662425416f5b6ffa5ade11ffba6db GIT binary patch literal 18832 zcmeHKTXN(^4D){FCx^)WPnDyD1i&WQ4@ncpRjEYUQL_nxAp0?1`_HehuRrYl&EDVb z{n6(a)gPGNh7ub1>&sD&VH)8ZPF4MdXD+4cidFtnmdzVe8fL}+0_Lzdz9f&Ou~5Vo zVW)|n36_im8;hlAvKU(xM=zkd`cUa1swWG5nmav0x|uj1yHsnM&56Zza6-dHbuk0m zyIqc6!y;|FAOv{~wx@AMjs_Ujx9L}4Z9*4P$2QDW`Zr^>`g5t#=kt{BGS%oTL%6Nt zGiMf*uOsFWn4*h5F#7tQM1fO!9BykjZqXLpsqXq@tInp(I{Fn>iH+!$=1B8&dyDyC z?NW(CXoWwMvNM3OgiV*h>^!Z@z=F#QaI9gY8ZE`boYFPB*aOYnYa>IijJ3_yvvEWR zdmiRKo!fhn*UjY_U1+AX&HQnbAfV@iG`0y>v2B9D2YI3#n1oMbo<^k4_NuuN^Scm< z*WifONu*v|M%S?_)j3;ozP&PZ#t69PV9pW?>_F9YRr_}Hf6B#>8dAIc83nX;G_LA} zs_|?TKmeNYV`Yf63He;zU`8IaE@Mq=INm~Z1ub7Yo@NBHEHZ*Nl*WXu)CJodY8S@h z${RX$;xVTXn+!tdnAlYg^S`aRC>0=k(PGhw(*wNTZ?%UX)P$!&HV+M`WT_S5wxmY{9i_+m) zPd4?FEyhUhg&B>E{$k=P&T^Z^rbv~EIjT4j>Q31|T!SP*fj$!5ojmA(t-warB&mn0 znuf`ki!-~MjiOVFCizom3EB*cW`>Q@pM||oa9y6HG#T4dW-Fo%J-5ufVIPzvasy)y|MU;jF^#TOchH>m8rFPJ=YXB$Y+cQ19LQ$@ze*&(`E@iKb zS!inmb#sL^FSfe(sWwLtVjp`$h2nIh!(Q;;;7$9&-TL{)a+k0*aJ5OXSJBy~8K>AY z8ESTw$;+}-xE&YGUKaA}y{xiRlb#RJsWa*d6s5}C%zK|%fwI^sQcgN-vo#wD4V*Xq zq<6qaXILpKgnoJoE*imPV0btHANV<%MNfc)dU&Viwa$bz+j zG1_gHBg9N3Ko9H(;6ZhPb(gGBo)bFu0bN$Jq@Dmv!up^PO9e6(F7KqU!P_0&i)ksF z$*vrtUKDR&Pu_F|Tc0PD(2bCkv@ST5_Ui>*0IEP=N6v9h`$yb()c2U-`g zt_Fs-z;L_F(eo^OPbMx}h#z%opo^I{vSsM7Vokc4n}mN{#Qt>yNfI!hIqCR3ndcd$*5LZb`3Z{NHiARgVboe!lzp=%PFzy?5!o zOAoHeBg%W1-n;bZqC6nIcj^Cmm-bhKx50jO_TQdm`u^ze8~%1Z|7k$c2eEzizb%J~ z`@g&nm5#8Qk5+~~CPd&{UnKv_a@n>mXyqD_PIMj39PO;BzlfuG=6#~MYX(^St=-!V z@7Q2pp4xRmdu2QqCE9qQ*h6Crs38%W5$h>?ujFT*8iU~$*tCLsEu!R&j!e~Zl^-Xi z{7$_RZ81nX((~QRHMER-r)yq$_gdZ<7AzBuwsz?Vy4MUM78uTbS}`0yZUhX((HXYPTqjjw`vQ^oGc4BQzapSr=a2v#vzXb&^BX_!$H*HW@Vx z;YSt4Oet4$Z%8KH@#Zang`ME|c;tk^cQ6qhH5KTZ-b_bK6_29| zHM4W1&_Z)EgW0kBR|(SGk=WpkK+~2pH0#9Gs(&|U^#cn*#d{f^B$zJZHn?4kA&S#rB$Nu8F&07dd>dr zVfRFBnsl_~Ee8dL!tC)Jl+YD*9H@3!zb7CbX6IB@#cNVaQJ`UTFfL0Mk!j7TRX>|Y zJyz@;eWvt;ttBlhdy;$NyqZ^ElGCo8@pnJp{XE}}&m!+#dhgO_H|ETK@6vmh&bQ;U L$a|Omvv=t)tCkB= literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/fonts/FF_FONT2-Bold.gdf b/web/public_php/admin/jpgraph/fonts/FF_FONT2-Bold.gdf new file mode 100644 index 0000000000000000000000000000000000000000..6e402847c2aa02b57e2bc3eefd85ed391b798cc7 GIT binary patch literal 25104 zcmdT}TejV{4om*})iHGbqv}vf0EAwaEbVP4ZGB@yBtd}GIqh2M{rks{AAiOBN4$T= z``>wf{?sg|I8N@qAs=Z}5(*BiUl@+gef%?@GGUfWzNZ)3b>JZ4VWU9HN&x9n?+#6! zN5$5mA^D3BWV264Ipr8RNNdOno5;*wXz*Rw)U@;q-+j~pE9wcrEGvoDEP{py)Xig3 zqQgzsd3n&Chg<}jwqN0eP!c(j8%utfaAAW(+2QsANQ{sFt0Ru-J2$HE;&McZMc_CNxAl>?aVyt=KEF6vM>!T{48co1 z=iZv#5@>nL=!>87`|kSl8uP2zeu)kndSAJV8uy}eb7(v^NB(;7H)KxS)#qIwj(fLx zUt8JLJO@ty=w*9qC@8aSl-*RN=O-9OMW4Vp<&!5TI&>{CWzjTu7_vz-|ALqyp7;P! zMn{{AKq3c@eSb7kyTMMs$uD?F-#!{wvtxXa%e>{fJo#96pBBG0QZdKRy?jqMdvKny zE<4V;@zi~KA@q3;qb9oMT{n7i#jEdoek+GQ@2Rj>?4a$8dA%sH?0m&6pchZCJ&Q=O z(F{{)%Y*olp~o`$OFUaISN28hQPaeQYGLif;LOl{*+LzhQ zh+nV%``8oRxrGnQWtnDfgBU&EJk5fdU)DbJ0zNbC1aXcd{_OBh^RC8wqaQ!oK4-`wJWPjons+t&QK^%|$}_vj#d9aPsj>fP zKkqL?n;JJZwVa0N!{qE=AnIB$5D&=>GP(KCk3A9@HCFLPc2!P0s>a9aS|gjBN73W0 z^e%ZTCYJsoU!2E09515h2{y;)1nI;9zjoBD>4#u^u@2RZn(Ta`o+&44-Hl>xpq zL=L^iUgtED6!mj(sq+_uA{lEMaoBX~(DT&Vh#}Fw5tt*)vBaul^|H$dYN=zPUbc_u zZvG%@9hW!gvTYBLKhNT7f!~B)?_kaxF$X)Gujs2Aq5l*tyZ^>R48nW=7JuWYZ&>BF zargai+Z)<54f_~poHuj!F}|ri)3T3o#(6VmALEg(}5r44#NXFo7>%P5q;)g+$a10k z8zs%ena(DsevvFgWZ{~h@i!JjIn@0JMt*~ZBc8-5h;jb4W{BcBZ`?2?XFa0jD@vo^ z!`tcqT#02jMksskxl+k`3ScCMu4SA9^mOf))*;AhgKVPVYP_PC`iEfSi|lfKji$bw z=+>(Y26EGu`N*(+z`V~WcKuX1w`=^YG$7O`FH*?!j|LoE$qzA@vfM&$n-{)1VJf7HB#vIna+A-su%5vf<9bX=jlwfL?jX@UI0Bd9ZUlq#YLZ)j`Dg`j7EyC2E-+59thhxOZ!-RZWYPYvln|GkB+H zE%#Ustze$r)nnbW&*Pr**RWzFz=xr+PUHTGb(2CL9;FhyuvEJ&_?JYZTaHDW8}VpdJE_7Wj$9g^JX ztO% z6Y;daa~OhFuPLQYzwzLgVGoT)dj#p57aD^>A7<2g<+<>*L~O*u0{QELA$f~J&CG^q zUOPe8)myYmBDl?qW5fg?$K8BDk4N@jVc);9BkKcw>f{Ounz7uJvnxmC3(E&$7Zk<0 zfw;J%`BMreCavV>ZQo~87&i(Lqo@B~_)(`X$oNR?pxHjggO*1W`xqaI9W>j=c+m2Q zVjtrpv4dv&7!O(=QS4)UBzDkjALBvGBZ_^DkHij|?PEM>c|@^~@sZd;vwe&QEsrSn zF+LJIXts~>pyd(8KE_942hH{|9<)57*vI%t?4a2`#)Fne6#Ez-i5)cC$9T~4h+-e( zBe8>K`xp;e9#QOLd?a?zY#-x6%Oi??jE}?)n(bpeXn91jkMWV%L9=~~2Q7~%_Ax#Z aJ7~6#@u1}q#XiPIVh7FkF&?zcDE|PX+!N3M literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/fonts/FF_FONT2.gdf b/web/public_php/admin/jpgraph/fonts/FF_FONT2.gdf new file mode 100644 index 0000000000000000000000000000000000000000..50bca09e089de70c5634670e3789da40b17d2849 GIT binary patch literal 25104 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 D--8Uy literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/gd_image.inc.php b/web/public_php/admin/jpgraph/gd_image.inc.php new file mode 100644 index 000000000..58abab0d7 --- /dev/null +++ b/web/public_php/admin/jpgraph/gd_image.inc.php @@ -0,0 +1,2306 @@ +original_width = $aWidth; + $this->original_height = $aHeight; + $this->CreateImgCanvas($aWidth, $aHeight); + + if( $aSetAutoMargin ) { + $this->SetAutoMargin(); + } + + if( !$this->SetImgFormat($aFormat) ) { + JpGraphError::RaiseL(25081,$aFormat);//("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]"); + } + $this->ttf = new TTF(); + $this->langconv = new LanguageConv(); + + $this->ff_font0 = imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT0.gdf"); + $this->ff_font1 = imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1.gdf"); + $this->ff_font2 = imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2.gdf"); + $this->ff_font1_bold = imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1-Bold.gdf"); + $this->ff_font2_bold = imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2-Bold.gdf"); + } + + // Enable interlacing in images + function SetInterlace($aFlg=true) { + $this->iInterlace=$aFlg; + } + + // Should we use anti-aliasing. Note: This really slows down graphics! + function SetAntiAliasing($aFlg=true) { + $this->use_anti_aliasing = $aFlg; + if( function_exists('imageantialias') ) { + imageantialias($this->img,$aFlg); + } + else { + 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.') + } + } + + function GetAntiAliasing() { + return $this->use_anti_aliasing ; + } + + function CreateRawCanvas($aWidth=0,$aHeight=0) { + + $aWidth *= SUPERSAMPLING_SCALE; + $aHeight *= SUPERSAMPLING_SCALE; + + if( $aWidth <= 1 || $aHeight <= 1 ) { + JpGraphError::RaiseL(25082,$aWidth,$aHeight);//("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)"); + } + + $this->img = @imagecreatetruecolor($aWidth, $aHeight); + if( $this->img < 1 ) { + JpGraphError::RaiseL(25126); + //die("Can't create truecolor image. Check that you really have GD2 library installed."); + } + $this->SetAlphaBlending(); + + if( $this->iInterlace ) { + imageinterlace($this->img,1); + } + if( $this->rgb != null ) { + $this->rgb->img = $this->img ; + } + else { + $this->rgb = new RGB($this->img); + } + } + + function CloneCanvasH() { + $oldimage = $this->img; + $this->CreateRawCanvas($this->width,$this->height); + imagecopy($this->img,$oldimage,0,0,0,0,$this->width,$this->height); + return $oldimage; + } + + function CreateImgCanvas($aWidth=0,$aHeight=0) { + + $old = array($this->img,$this->width,$this->height); + + $aWidth = round($aWidth); + $aHeight = round($aHeight); + + $this->width=$aWidth; + $this->height=$aHeight; + + + if( $aWidth==0 || $aHeight==0 ) { + // We will set the final size later. + // Note: The size must be specified before any other + // img routines that stroke anything are called. + $this->img = null; + $this->rgb = null; + return $old; + } + + $this->CreateRawCanvas($aWidth,$aHeight); + // Set canvas color (will also be the background color for a + // a pallett image + $this->SetColor($this->canvascolor); + $this->FilledRectangle(0,0,$this->width-1,$this->height-1); + + return $old ; + } + + function CopyCanvasH($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY,$aWidth,$aHeight,$aw=-1,$ah=-1) { + if( $aw === -1 ) { + $aw = $aWidth; + $ah = $aHeight; + $f = 'imagecopyresized'; + } + else { + $f = 'imagecopyresampled'; + } + $f($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY, $aWidth,$aHeight,$aw,$ah); + } + + function Copy($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1) { + $this->CopyCanvasH($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight); + } + + function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) { + if( $aMix == 100 ) { + $this->CopyCanvasH($this->img,$fromImg, + $toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight); + } + else { + if( ($fromWidth != -1 && ($fromWidth != $toWidth)) || ($fromHeight != -1 && ($fromHeight != $fromHeight)) ) { + // Create a new canvas that will hold the re-scaled original from image + if( $toWidth <= 1 || $toHeight <= 1 ) { + JpGraphError::RaiseL(25083);//('Illegal image size when copying image. Size for copied to image is 1 pixel or less.'); + } + + $tmpimg = @imagecreatetruecolor($toWidth, $toHeight); + + if( $tmpimg < 1 ) { + JpGraphError::RaiseL(25084);//('Failed to create temporary GD canvas. Out of memory ?'); + } + $this->CopyCanvasH($tmpimg,$fromImg,0,0,0,0, + $toWidth,$toHeight,$fromWidth,$fromHeight); + $fromImg = $tmpimg; + } + imagecopymerge($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$aMix); + } + } + + static function GetWidth($aImg) { + return imagesx($aImg); + } + + static function GetHeight($aImg) { + return imagesy($aImg); + } + + static function CreateFromString($aStr) { + $img = imagecreatefromstring($aStr); + if( $img === false ) { + 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.'); + } + return $img; + } + + function SetCanvasH($aHdl) { + $this->img = $aHdl; + $this->rgb->img = $aHdl; + } + + function SetCanvasColor($aColor) { + $this->canvascolor = $aColor ; + } + + function SetAlphaBlending($aFlg=true) { + ImageAlphaBlending($this->img,$aFlg); + } + + function SetAutoMargin() { + $min_bm=5; + $lm = min(40,$this->width/7); + $rm = min(20,$this->width/10); + $tm = max(5,$this->height/7); + $bm = max($min_bm,$this->height/6); + $this->SetMargin($lm,$rm,$tm,$bm); + } + + //--------------- + // PUBLIC METHODS + + function SetFont($family,$style=FS_NORMAL,$size=10) { + $this->font_family=$family; + $this->font_style=$style; + $this->font_size=$size*SUPERSAMPLING_SCALE; + $this->font_file=''; + if( ($this->font_family==FF_FONT1 || $this->font_family==FF_FONT2) && $this->font_style==FS_BOLD ){ + ++$this->font_family; + } + if( $this->font_family > FF_FONT2+1 ) { // A TTF font so get the font file + + // Check that this PHP has support for TTF fonts + if( !function_exists('imagettfbbox') ) { + // use internal font when php is configured without '--with-ttf' + $this->font_family = FF_FONT1; +// JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.'); + } else { + $this->font_file = $this->ttf->File($this->font_family,$this->font_style); + } + } + } + + // Get the specific height for a text string + function GetTextHeight($txt="",$angle=0) { + $tmp = preg_split('/\n/',$txt); + $n = count($tmp); + $m=0; + for($i=0; $i< $n; ++$i) { + $m = max($m,strlen($tmp[$i])); + } + + if( $this->font_family <= FF_FONT2+1 ) { + if( $angle==0 ) { + $h = imagefontheight($this->font_family); + if( $h === false ) { + JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); + } + + return $n*$h; + } + else { + $w = @imagefontwidth($this->font_family); + if( $w === false ) { + JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); + } + + return $m*$w; + } + } + else { + $bbox = $this->GetTTFBBox($txt,$angle); + return $bbox[1]-$bbox[5]+1; + } + } + + // Estimate font height + function GetFontHeight($angle=0) { + $txt = "XOMg"; + return $this->GetTextHeight($txt,$angle); + } + + // Approximate font width with width of letter "O" + function GetFontWidth($angle=0) { + $txt = 'O'; + return $this->GetTextWidth($txt,$angle); + } + + // Get actual width of text in absolute pixels. Note that the width is the + // texts projected with onto the x-axis. Call with angle=0 to get the true + // etxt width. + function GetTextWidth($txt,$angle=0) { + + $tmp = preg_split('/\n/',$txt); + $n = count($tmp); + if( $this->font_family <= FF_FONT2+1 ) { + + $m=0; + for($i=0; $i < $n; ++$i) { + $l=strlen($tmp[$i]); + if( $l > $m ) { + $m = $l; + } + } + + if( $angle==0 ) { + $w = @imagefontwidth($this->font_family); + if( $w === false ) { + JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); + } + return $m*$w; + } + else { + // 90 degrees internal so height becomes width + $h = @imagefontheight($this->font_family); + if( $h === false ) { + JpGraphError::RaiseL(25089);//('You have a misconfigured GD font support. The call to imagefontheight() fails.'); + } + return $n*$h; + } + } + else { + // For TTF fonts we must walk through a lines and find the + // widest one which we use as the width of the multi-line + // paragraph + $m=0; + for( $i=0; $i < $n; ++$i ) { + $bbox = $this->GetTTFBBox($tmp[$i],$angle); + $mm = $bbox[2] - $bbox[0]; + if( $mm > $m ) + $m = $mm; + } + return $m; + } + } + + + // Draw text with a box around it + function StrokeBoxedText($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black", + $shadowcolor=false,$paragraph_align="left", + $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) { + + $oldx = $this->lastx; + $oldy = $this->lasty; + + if( !is_numeric($dir) ) { + if( $dir=="h" ) $dir=0; + elseif( $dir=="v" ) $dir=90; + else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]"); + } + + if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) { + $width=$this->GetTextWidth($txt,$dir) ; + $height=$this->GetTextHeight($txt,$dir) ; + } + else { + $width=$this->GetBBoxWidth($txt,$dir) ; + $height=$this->GetBBoxHeight($txt,$dir) ; + } + + $height += 2*$ymarg; + $width += 2*$xmarg; + + if( $this->text_halign=="right" ) $x -= $width; + elseif( $this->text_halign=="center" ) $x -= $width/2; + + if( $this->text_valign=="bottom" ) $y -= $height; + elseif( $this->text_valign=="center" ) $y -= $height/2; + + $olda = $this->SetAngle(0); + + if( $shadowcolor ) { + $this->PushColor($shadowcolor); + $this->FilledRoundedRectangle($x-$xmarg+$dropwidth,$y-$ymarg+$dropwidth, + $x+$width+$dropwidth,$y+$height-$ymarg+$dropwidth, + $cornerradius); + $this->PopColor(); + $this->PushColor($fcolor); + $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg, + $x+$width,$y+$height-$ymarg, + $cornerradius); + $this->PopColor(); + $this->PushColor($bcolor); + $this->RoundedRectangle($x-$xmarg,$y-$ymarg, + $x+$width,$y+$height-$ymarg,$cornerradius); + $this->PopColor(); + } + else { + if( $fcolor ) { + $oc=$this->current_color; + $this->SetColor($fcolor); + $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius); + $this->current_color=$oc; + } + if( $bcolor ) { + $oc=$this->current_color; + $this->SetColor($bcolor); + $this->RoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius); + $this->current_color=$oc; + } + } + + $h=$this->text_halign; + $v=$this->text_valign; + $this->SetTextAlign("left","top"); + + $debug=false; + $this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug); + + $bb = array($x-$xmarg,$y+$height-$ymarg,$x+$width,$y+$height-$ymarg, + $x+$width,$y-$ymarg,$x-$xmarg,$y-$ymarg); + $this->SetTextAlign($h,$v); + + $this->SetAngle($olda); + $this->lastx = $oldx; + $this->lasty = $oldy; + + return $bb; + } + + // Draw text with a box around it. This time the box will be rotated + // with the text. The previous method will just make a larger enough non-rotated + // box to hold the text inside. + function StrokeBoxedText2($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black", + $shadowcolor=false,$paragraph_align="left", + $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) { + + // This version of boxed text will stroke a rotated box round the text + // thta will follow the angle of the text. + // This has two implications: + // 1) This methos will only support TTF fonts + // 2) The only two alignment that makes sense are centered or baselined + + if( $this->font_family <= FF_FONT2+1 ) { + JpGraphError::RaiseL(25131);//StrokeBoxedText2() Only support TTF fonts and not built in bitmap fonts + } + + $oldx = $this->lastx; + $oldy = $this->lasty; + $dir = $this->NormAngle($dir); + + if( !is_numeric($dir) ) { + if( $dir=="h" ) $dir=0; + elseif( $dir=="v" ) $dir=90; + else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]"); + } + + $width=$this->GetTextWidth($txt,0) + 2*$xmarg; + $height=$this->GetTextHeight($txt,0) + 2*$ymarg ; + $rect_width=$this->GetBBoxWidth($txt,$dir) ; + $rect_height=$this->GetBBoxHeight($txt,$dir) ; + + $baseline_offset = $this->bbox_cache[1]-1; + + if( $this->text_halign=="center" ) { + if( $dir >= 0 && $dir <= 90 ) { + + $x -= $rect_width/2; + $x += sin($dir*M_PI/180)*$height; + $y += $rect_height/2; + + } elseif( $dir >= 270 && $dir <= 360 ) { + + $x -= $rect_width/2; + $y -= $rect_height/2; + $y += cos($dir*M_PI/180)*$height; + + } elseif( $dir >= 90 && $dir <= 180 ) { + + $x += $rect_width/2; + $y += $rect_height/2; + $y += cos($dir*M_PI/180)*$height; + + } + else { + // $dir > 180 && $dir < 270 + $x += $rect_width/2; + $x += sin($dir*M_PI/180)*$height; + $y -= $rect_height/2; + } + } + + // Rotate the box around this point + $this->SetCenter($x,$y); + $olda = $this->SetAngle(-$dir); + + // We need to use adjusted coordinats for the box to be able + // to draw the box below the baseline. This cannot be done before since + // the rotating point must be the original x,y since that is arounbf the + // point where the text will rotate and we cannot change this since + // that is where the GD/GreeType will rotate the text + + + // For smaller <14pt font we need to do some additional + // adjustments to make it look good + if( $this->font_size < 14 ) { + $x -= 2; + $y += 2; + } + else { + // $y += $baseline_offset; + } + + if( $shadowcolor ) { + $this->PushColor($shadowcolor); + $this->FilledRectangle($x-$xmarg+$dropwidth,$y+$ymarg+$dropwidth-$height, + $x+$width+$dropwidth,$y+$ymarg+$dropwidth); + //$cornerradius); + $this->PopColor(); + $this->PushColor($fcolor); + $this->FilledRectangle($x-$xmarg, $y+$ymarg-$height, + $x+$width, $y+$ymarg); + //$cornerradius); + $this->PopColor(); + $this->PushColor($bcolor); + $this->Rectangle($x-$xmarg,$y+$ymarg-$height, + $x+$width,$y+$ymarg); + //$cornerradius); + $this->PopColor(); + } + else { + if( $fcolor ) { + $oc=$this->current_color; + $this->SetColor($fcolor); + $this->FilledRectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius); + $this->current_color=$oc; + } + if( $bcolor ) { + $oc=$this->current_color; + $this->SetColor($bcolor); + $this->Rectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius); + $this->current_color=$oc; + } + } + + if( $this->font_size < 14 ) { + $x += 2; + $y -= 2; + } + else { + + // Restore the original y before we stroke the text + // $y -= $baseline_offset; + + } + + $this->SetCenter(0,0); + $this->SetAngle($olda); + + $h=$this->text_halign; + $v=$this->text_valign; + if( $this->text_halign == 'center') { + $this->SetTextAlign('center','basepoint'); + } + else { + $this->SetTextAlign('basepoint','basepoint'); + } + + $debug=false; + $this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug); + + $bb = array($x-$xmarg, $y+$height-$ymarg, + $x+$width, $y+$height-$ymarg, + $x+$width, $y-$ymarg, + $x-$xmarg, $y-$ymarg); + + $this->SetTextAlign($h,$v); + $this->SetAngle($olda); + + $this->lastx = $oldx; + $this->lasty = $oldy; + + return $bb; + } + + // Set text alignment + function SetTextAlign($halign,$valign="bottom") { + $this->text_halign=$halign; + $this->text_valign=$valign; + } + + function _StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$aDebug=false) { + + if( is_numeric($dir) && $dir!=90 && $dir!=0) + JpGraphError::RaiseL(25091);//(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead."); + + $h=$this->GetTextHeight($txt); + $fh=$this->GetFontHeight(); + $w=$this->GetTextWidth($txt); + + if( $this->text_halign=="right") { + $x -= $dir==0 ? $w : $h; + } + elseif( $this->text_halign=="center" ) { + // For center we subtract 1 pixel since this makes the middle + // be prefectly in the middle + $x -= $dir==0 ? $w/2-1 : $h/2; + } + if( $this->text_valign=="top" ) { + $y += $dir==0 ? $h : $w; + } + elseif( $this->text_valign=="center" ) { + $y += $dir==0 ? $h/2 : $w/2; + } + + $use_font = $this->font_family; + + if( $dir==90 ) { + imagestringup($this->img,$use_font,$x,$y,$txt,$this->current_color); + $aBoundingBox = array(round($x),round($y),round($x),round($y-$w),round($x+$h),round($y-$w),round($x+$h),round($y)); + if( $aDebug ) { + // Draw bounding box + $this->PushColor('green'); + $this->Polygon($aBoundingBox,true); + $this->PopColor(); + } + } + else { + if( preg_match('/\n/',$txt) ) { + $tmp = preg_split('/\n/',$txt); + for($i=0; $i < count($tmp); ++$i) { + $w1 = $this->GetTextWidth($tmp[$i]); + if( $paragraph_align=="left" ) { + imagestring($this->img,$use_font,$x,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); + } + elseif( $paragraph_align=="right" ) { + imagestring($this->img,$use_font,$x+($w-$w1),$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); + } + else { + imagestring($this->img,$use_font,$x+$w/2-$w1/2,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); + } + } + } + else { + //Put the text + imagestring($this->img,$use_font,$x,$y-$h+1,$txt,$this->current_color); + } + if( $aDebug ) { + // Draw the bounding rectangle and the bounding box + $p1 = array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y)); + + // Draw bounding box + $this->PushColor('green'); + $this->Polygon($p1,true); + $this->PopColor(); + + } + $aBoundingBox=array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y)); + } + } + + function AddTxtCR($aTxt) { + // If the user has just specified a '\n' + // instead of '\n\t' we have to add '\r' since + // the width will be too muchy otherwise since when + // we print we stroke the individually lines by hand. + $e = explode("\n",$aTxt); + $n = count($e); + for($i=0; $i<$n; ++$i) { + $e[$i]=str_replace("\r","",$e[$i]); + } + return implode("\n\r",$e); + } + + function NormAngle($a) { + // Normalize angle in degrees + // Normalize angle to be between 0-360 + while( $a > 360 ) + $a -= 360; + while( $a < -360 ) + $a += 360; + if( $a < 0 ) + $a = 360 + $a; + return $a; + } + + function imagettfbbox_fixed($size, $angle, $fontfile, $text) { + + + if( ! USE_LIBRARY_IMAGETTFBBOX ) { + + $bbox = @imagettfbbox($size, $angle, $fontfile, $text); + if( $bbox === false ) { + JpGraphError::RaiseL(25092,$this->font_file); + //("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."); + } + $this->bbox_cache = $bbox; + return $bbox; + } + + // The built in imagettfbbox is buggy for angles != 0 so + // we calculate this manually by getting the bounding box at + // angle = 0 and then rotate the bounding box manually + $bbox = @imagettfbbox($size, 0, $fontfile, $text); + if( $bbox === false ) { + JpGraphError::RaiseL(25092,$this->font_file); + //("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."); + } + + $angle = $this->NormAngle($angle); + + $a = $angle*M_PI/180; + $ca = cos($a); + $sa = sin($a); + $ret = array(); + + // We always add 1 pixel to the left since the left edge of the bounding + // box is sometimes coinciding with the first pixel of the text + //$bbox[0] -= 1; + //$bbox[6] -= 1; + + // For roatated text we need to add extra width for rotated + // text since the kerning and stroking of the TTF is not the same as for + // text at a 0 degree angle + + if( $angle > 0.001 && abs($angle-360) > 0.001 ) { + $h = abs($bbox[7]-$bbox[1]); + $w = abs($bbox[2]-$bbox[0]); + + $bbox[0] -= 2; + $bbox[6] -= 2; + // The width is underestimated so compensate for that + $bbox[2] += round($w*0.06); + $bbox[4] += round($w*0.06); + + // and we also need to compensate with increased height + $bbox[5] -= round($h*0.1); + $bbox[7] -= round($h*0.1); + + if( $angle > 90 ) { + // For angles > 90 we also need to extend the height further down + // by the baseline since that is also one more problem + $bbox[1] += round($h*0.15); + $bbox[3] += round($h*0.15); + + // and also make it slighty less height + $bbox[7] += round($h*0.05); + $bbox[5] += round($h*0.05); + + // And we need to move the box slightly top the rright (from a tetx perspective) + $bbox[0] += round($w*0.02); + $bbox[6] += round($w*0.02); + + if( $angle > 180 ) { + // And we need to move the box slightly to the left (from a text perspective) + $bbox[0] -= round($w*0.02); + $bbox[6] -= round($w*0.02); + $bbox[2] -= round($w*0.02); + $bbox[4] -= round($w*0.02); + + } + + } + for($i = 0; $i < 7; $i += 2) { + $ret[$i] = round($bbox[$i] * $ca + $bbox[$i+1] * $sa); + $ret[$i+1] = round($bbox[$i+1] * $ca - $bbox[$i] * $sa); + } + $this->bbox_cache = $ret; + return $ret; + } + else { + $this->bbox_cache = $bbox; + return $bbox; + } + } + + // Deprecated + function GetTTFBBox($aTxt,$aAngle=0) { + $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt); + return $bbox; + } + + function GetBBoxTTF($aTxt,$aAngle=0) { + // Normalize the bounding box to become a minimum + // enscribing rectangle + + $aTxt = $this->AddTxtCR($aTxt); + + if( !is_readable($this->font_file) ) { + JpGraphError::RaiseL(25093,$this->font_file); + //('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.'); + } + $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt); + + if( $aAngle==0 ) return $bbox; + + if( $aAngle >= 0 ) { + if( $aAngle <= 90 ) { //<=0 + $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1], + $bbox[2],$bbox[5],$bbox[6],$bbox[5]); + } + elseif( $aAngle <= 180 ) { //<= 2 + $bbox = array($bbox[4],$bbox[7],$bbox[0],$bbox[7], + $bbox[0],$bbox[3],$bbox[4],$bbox[3]); + } + elseif( $aAngle <= 270 ) { //<= 3 + $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5], + $bbox[6],$bbox[1],$bbox[2],$bbox[1]); + } + else { + $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], + $bbox[4],$bbox[7],$bbox[0],$bbox[7]); + } + } + elseif( $aAngle < 0 ) { + if( $aAngle <= -270 ) { // <= -3 + $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1], + $bbox[2],$bbox[5],$bbox[6],$bbox[5]); + } + elseif( $aAngle <= -180 ) { // <= -2 + $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], + $bbox[4],$bbox[7],$bbox[0],$bbox[7]); + } + elseif( $aAngle <= -90 ) { // <= -1 + $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5], + $bbox[6],$bbox[1],$bbox[2],$bbox[1]); + } + else { + $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], + $bbox[4],$bbox[7],$bbox[0],$bbox[7]); + } + } + return $bbox; + } + + function GetBBoxHeight($aTxt,$aAngle=0) { + $box = $this->GetBBoxTTF($aTxt,$aAngle); + return abs($box[7]-$box[1]); + } + + function GetBBoxWidth($aTxt,$aAngle=0) { + $box = $this->GetBBoxTTF($aTxt,$aAngle); + return $box[2]-$box[0]+1; + } + + + function _StrokeTTF($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$debug=false) { + + // Setup default inter line margin for paragraphs to be + // 3% of the font height. + $ConstLineSpacing = 0.03 ; + + // Remember the anchor point before adjustment + if( $debug ) { + $ox=$x; + $oy=$y; + } + + if( !preg_match('/\n/',$txt) || ($dir>0 && preg_match('/\n/',$txt)) ) { + // Format a single line + + $txt = $this->AddTxtCR($txt); + $bbox=$this->GetBBoxTTF($txt,$dir); + $width = $this->GetBBoxWidth($txt,$dir); + $height = $this->GetBBoxHeight($txt,$dir); + + // The special alignment "basepoint" is mostly used internally + // in the library. This will put the anchor position at the left + // basepoint of the tetx. This is the default anchor point for + // TTF text. + + if( $this->text_valign != 'basepoint' ) { + // Align x,y ot lower left corner of bbox + + + if( $this->text_halign=='right' ) { + $x -= $width; + $x -= $bbox[0]; + } + elseif( $this->text_halign=='center' ) { + $x -= $width/2; + $x -= $bbox[0]; + } + elseif( $this->text_halign=='baseline' ) { + // This is only support for text at 90 degree !! + // Do nothing the text is drawn at baseline by default + } + + if( $this->text_valign=='top' ) { + $y -= $bbox[1]; // Adjust to bottom of text + $y += $height; + } + elseif( $this->text_valign=='center' ) { + $y -= $bbox[1]; // Adjust to bottom of text + $y += $height/2; + } + elseif( $this->text_valign=='baseline' ) { + // This is only support for text at 0 degree !! + // Do nothing the text is drawn at baseline by default + } + } + ImageTTFText ($this->img, $this->font_size, $dir, $x, $y, + $this->current_color,$this->font_file,$txt); + + // Calculate and return the co-ordinates for the bounding box + $box = $this->imagettfbbox_fixed($this->font_size,$dir,$this->font_file,$txt); + $p1 = array(); + + for($i=0; $i < 4; ++$i) { + $p1[] = round($box[$i*2]+$x); + $p1[] = round($box[$i*2+1]+$y); + } + $aBoundingBox = $p1; + + // Debugging code to highlight the bonding box and bounding rectangle + // For text at 0 degrees the bounding box and bounding rectangle are the + // same + if( $debug ) { + // Draw the bounding rectangle and the bounding box + + $p = array(); + $p1 = array(); + + for($i=0; $i < 4; ++$i) { + $p[] = $bbox[$i*2]+$x ; + $p[] = $bbox[$i*2+1]+$y; + $p1[] = $box[$i*2]+$x ; + $p1[] = $box[$i*2+1]+$y ; + } + + // Draw bounding box + $this->PushColor('green'); + $this->Polygon($p1,true); + $this->PopColor(); + + // Draw bounding rectangle + $this->PushColor('darkgreen'); + $this->Polygon($p,true); + $this->PopColor(); + + // Draw a cross at the anchor point + $this->PushColor('red'); + $this->Line($ox-15,$oy,$ox+15,$oy); + $this->Line($ox,$oy-15,$ox,$oy+15); + $this->PopColor(); + } + } + else { + // Format a text paragraph + $fh=$this->GetFontHeight(); + + // Line margin is 25% of font height + $linemargin=round($fh*$ConstLineSpacing); + $fh += $linemargin; + $w=$this->GetTextWidth($txt); + + $y -= $linemargin/2; + $tmp = preg_split('/\n/',$txt); + $nl = count($tmp); + $h = $nl * $fh; + + if( $this->text_halign=='right') { + $x -= $dir==0 ? $w : $h; + } + elseif( $this->text_halign=='center' ) { + $x -= $dir==0 ? $w/2 : $h/2; + } + + if( $this->text_valign=='top' ) { + $y += $dir==0 ? $h : $w; + } + elseif( $this->text_valign=='center' ) { + $y += $dir==0 ? $h/2 : $w/2; + } + + // Here comes a tricky bit. + // Since we have to give the position for the string at the + // baseline this means thaht text will move slightly up + // and down depending on any of it's character descend below + // the baseline, for example a 'g'. To adjust the Y-position + // we therefore adjust the text with the baseline Y-offset + // as used for the current font and size. This will keep the + // baseline at a fixed positoned disregarding the actual + // characters in the string. + $standardbox = $this->GetTTFBBox('Gg',$dir); + $yadj = $standardbox[1]; + $xadj = $standardbox[0]; + $aBoundingBox = array(); + for($i=0; $i < $nl; ++$i) { + $wl = $this->GetTextWidth($tmp[$i]); + $bbox = $this->GetTTFBBox($tmp[$i],$dir); + if( $paragraph_align=='left' ) { + $xl = $x; + } + elseif( $paragraph_align=='right' ) { + $xl = $x + ($w-$wl); + } + else { + // Center + $xl = $x + $w/2 - $wl/2 ; + } + + // In theory we should adjust with full pre-lead to get the lines + // lined up but this doesn't look good so therfore we only adjust with + // half th pre-lead + $xl -= $bbox[0]/2; + $yl = $y - $yadj; + //$xl = $xl- $xadj; + ImageTTFText($this->img, $this->font_size, $dir, $xl, $yl-($h-$fh)+$fh*$i, + $this->current_color,$this->font_file,$tmp[$i]); + + // echo "xl=$xl,".$tmp[$i]."
"; + if( $debug ) { + // Draw the bounding rectangle around each line + $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$tmp[$i]); + $p = array(); + for($j=0; $j < 4; ++$j) { + $p[] = $bbox[$j*2]+$xl; + $p[] = $bbox[$j*2+1]+$yl-($h-$fh)+$fh*$i; + } + + // Draw bounding rectangle + $this->PushColor('darkgreen'); + $this->Polygon($p,true); + $this->PopColor(); + } + } + + // Get the bounding box + $bbox = $this->GetBBoxTTF($txt,$dir); + for($j=0; $j < 4; ++$j) { + $bbox[$j*2]+= round($x); + $bbox[$j*2+1]+= round($y - ($h-$fh) - $yadj); + } + $aBoundingBox = $bbox; + + if( $debug ) { + // Draw a cross at the anchor point + $this->PushColor('red'); + $this->Line($ox-25,$oy,$ox+25,$oy); + $this->Line($ox,$oy-25,$ox,$oy+25); + $this->PopColor(); + } + + } + } + + function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) { + + $x = round($x); + $y = round($y); + + // Do special language encoding + $txt = $this->langconv->Convert($txt,$this->font_family); + + if( !is_numeric($dir) ) { + JpGraphError::RaiseL(25094);//(" Direction for text most be given as an angle between 0 and 90."); + } + + if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) { + $this->_StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug); + } + elseif( $this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT) { + $this->_StrokeTTF($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug); + } + else { + JpGraphError::RaiseL(25095);//(" Unknown font font family specification. "); + } + return $boundingbox; + } + + function SetMargin($lm,$rm,$tm,$bm) { + + $this->left_margin=$lm; + $this->right_margin=$rm; + $this->top_margin=$tm; + $this->bottom_margin=$bm; + + $this->plotwidth = $this->width - $this->left_margin - $this->right_margin; + $this->plotheight = $this->height - $this->top_margin - $this->bottom_margin; + + if( $this->width > 0 && $this->height > 0 ) { + if( $this->plotwidth < 0 || $this->plotheight < 0 ) { + JpGraphError::RaiseL(25130, $this->plotwidth, $this->plotheight); + //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."); + } + } + } + + function SetTransparent($color) { + imagecolortransparent ($this->img,$this->rgb->allocate($color)); + } + + function SetColor($color,$aAlpha=0) { + $this->current_color_name = $color; + $this->current_color=$this->rgb->allocate($color,$aAlpha); + if( $this->current_color == -1 ) { + $tc=imagecolorstotal($this->img); + JpGraphError::RaiseL(25096); + //("Can't allocate any more colors. Image has already allocated maximum of $tc colors. 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."); + } + return $this->current_color; + } + + function PushColor($color) { + if( $color != "" ) { + $this->colorstack[$this->colorstackidx]=$this->current_color_name; + $this->colorstack[$this->colorstackidx+1]=$this->current_color; + $this->colorstackidx+=2; + $this->SetColor($color); + } + else { + JpGraphError::RaiseL(25097);//("Color specified as empty string in PushColor()."); + } + } + + function PopColor() { + if( $this->colorstackidx < 1 ) { + JpGraphError::RaiseL(25098);//(" Negative Color stack index. Unmatched call to PopColor()"); + } + $this->current_color=$this->colorstack[--$this->colorstackidx]; + $this->current_color_name=$this->colorstack[--$this->colorstackidx]; + } + + + function SetLineWeight($weight) { + $old = $this->line_weight; + imagesetthickness($this->img,$weight); + $this->line_weight = $weight; + return $old; + } + + function SetStartPoint($x,$y) { + $this->lastx=round($x); + $this->lasty=round($y); + } + + function Arc($cx,$cy,$w,$h,$s,$e) { + // GD Arc doesn't like negative angles + while( $s < 0) $s += 360; + while( $e < 0) $e += 360; + imagearc($this->img,round($cx),round($cy),round($w),round($h),$s,$e,$this->current_color); + } + + function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') { + $s = round($s); + $e = round($e); + while( $s < 0 ) $s += 360; + while( $e < 0 ) $e += 360; + if( $style=='' ) + $style=IMG_ARC_PIE; + if( abs($s-$e) > 0 ) { + imagefilledarc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style); +// $this->DrawImageSmoothArc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style); + } + } + + function FilledCakeSlice($cx,$cy,$w,$h,$s,$e) { + $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name); + } + + function CakeSlice($xc,$yc,$w,$h,$s,$e,$fillcolor="",$arccolor="") { + $s = round($s); $e = round($e); + $w = round($w); $h = round($h); + $xc = round($xc); $yc = round($yc); + if( $s == $e ) { + // A full circle. We draw this a plain circle + $this->PushColor($fillcolor); + imagefilledellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color); + + // If antialiasing is used then we often don't have any color no the surrounding + // arc. So, we need to check for this special case so we don't send an empty + // color to the push function. In this case we use the fill color for the arc as well + if( $arccolor != '' ) { + $this->PopColor(); + $this->PushColor($arccolor); + } + imageellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color); + $this->Line($xc,$yc,cos($s*M_PI/180)*$w+$xc,$yc+sin($s*M_PI/180)*$h); + $this->PopColor(); + } + else { + $this->PushColor($fillcolor); + $this->FilledArc($xc,$yc,2*$w,2*$h,$s,$e); + $this->PopColor(); + if( $arccolor != "" ) { + $this->PushColor($arccolor); + // We add 2 pixels to make the Arc() better aligned with + // the filled arc. + imagefilledarc($this->img,$xc,$yc,2*$w,2*$h,$s,$e,$this->current_color,IMG_ARC_NOFILL | IMG_ARC_EDGED ) ; + $this->PopColor(); + } + } + } + + function Ellipse($xc,$yc,$w,$h) { + $this->Arc($xc,$yc,$w,$h,0,360); + } + + function Circle($xc,$yc,$r) { + imageellipse($this->img,round($xc),round($yc),$r*2,$r*2,$this->current_color); +// $this->DrawImageSmoothArc($this->img,round($xc),round($yc),$r*2+1,$r*2+1,0,360,$this->current_color); +// $this->imageSmoothCircle($this->img, round($xc),round($yc), $r*2+1, $this->current_color); + } + + function FilledCircle($xc,$yc,$r) { + imagefilledellipse($this->img,round($xc),round($yc),2*$r,2*$r,$this->current_color); +// $this->DrawImageSmoothArc($this->img, round($xc), round($yc), 2*$r, 2*$r, 0, 360, $this->current_color); + } + + // Linear Color InterPolation + function lip($f,$t,$p) { + $p = round($p,1); + $r = $f[0] + ($t[0]-$f[0])*$p; + $g = $f[1] + ($t[1]-$f[1])*$p; + $b = $f[2] + ($t[2]-$f[2])*$p; + return array($r,$g,$b); + } + + // Set line style dashed, dotted etc + function SetLineStyle($s) { + if( is_numeric($s) ) { + if( $s<1 || $s>4 ) { + JpGraphError::RaiseL(25101,$s);//(" Illegal numeric argument to SetLineStyle(): ($s)"); + } + } + elseif( is_string($s) ) { + if( $s == "solid" ) $s=1; + elseif( $s == "dotted" ) $s=2; + elseif( $s == "dashed" ) $s=3; + elseif( $s == "longdashed" ) $s=4; + else { + JpGraphError::RaiseL(25102,$s);//(" Illegal string argument to SetLineStyle(): $s"); + } + } + else { + JpGraphError::RaiseL(25103,$s);//(" Illegal argument to SetLineStyle $s"); + } + $old = $this->line_style; + $this->line_style=$s; + return $old; + } + + // Same as Line but take the line_style into account + function StyleLine($x1,$y1,$x2,$y2,$aStyle='', $from_grid_class = false) { + if( $this->line_weight <= 0 ) return; + + if( $aStyle === '' ) { + $aStyle = $this->line_style; + } + + $dashed_line_method = 'DashedLine'; + if ($from_grid_class) { + $dashed_line_method = 'DashedLineForGrid'; + } + + // Add error check since dashed line will only work if anti-alias is disabled + // this is a limitation in GD + + if( $aStyle == 1 ) { + // Solid style. We can handle anti-aliasing for this + $this->Line($x1,$y1,$x2,$y2); + } + else { + // Since the GD routines doesn't handle AA for styled line + // we have no option than to turn it off to get any lines at + // all if the weight > 1 + $oldaa = $this->GetAntiAliasing(); + if( $oldaa && $this->line_weight > 1 ) { + $this->SetAntiAliasing(false); + } + + switch( $aStyle ) { + case 2: // Dotted + $this->$dashed_line_method($x1,$y1,$x2,$y2,2,6); + break; + case 3: // Dashed + $this->$dashed_line_method($x1,$y1,$x2,$y2,5,9); + break; + case 4: // Longdashes + $this->$dashed_line_method($x1,$y1,$x2,$y2,9,13); + break; + default: + JpGraphError::RaiseL(25104,$this->line_style);//(" Unknown line style: $this->line_style "); + break; + } + if( $oldaa ) { + $this->SetAntiAliasing(true); + } + } + } + + function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) { + + if( $this->line_weight <= 0 ) return; + + // Add error check to make sure anti-alias is not enabled. + // Dashed line does not work with anti-alias enabled. This + // is a limitation in GD. + if( $this->use_anti_aliasing ) { +// JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines. + } + + $x1 = round($x1); + $x2 = round($x2); + $y1 = round($y1); + $y2 = round($y2); + + $dash_length *= SUPERSAMPLING_SCALE; + $dash_space *= SUPERSAMPLING_SCALE; + + $style = array_fill(0,$dash_length,$this->current_color); + $style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT); + imagesetstyle($this->img, $style); + imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); + + $this->lastx = $x2; + $this->lasty = $y2; + } + + function DashedLineForGrid($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) { + + if( $this->line_weight <= 0 ) return; + + // Add error check to make sure anti-alias is not enabled. + // Dashed line does not work with anti-alias enabled. This + // is a limitation in GD. + if( $this->use_anti_aliasing ) { +// JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines. + } + + $x1 = round($x1); + $x2 = round($x2); + $y1 = round($y1); + $y2 = round($y2); + + /* + $dash_length *= $this->scale; + $dash_space *= $this->scale; + */ + + $dash_length = 2; + $dash_length = 4; + imagesetthickness($this->img, 1); + $style = array_fill(0,$dash_length, $this->current_color); //hexdec('CCCCCC')); + $style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT); + imagesetstyle($this->img, $style); + imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); + + $this->lastx = $x2; + $this->lasty = $y2; + } + + function Line($x1,$y1,$x2,$y2) { + + if( $this->line_weight <= 0 ) return; + + $x1 = round($x1); + $x2 = round($x2); + $y1 = round($y1); + $y2 = round($y2); + + imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); +// $this->DrawLine($this->img, $x1, $y1, $x2, $y2, $this->line_weight, $this->current_color); + $this->lastx=$x2; + $this->lasty=$y2; + } + + function Polygon($p,$closed=FALSE,$fast=FALSE) { + + if( $this->line_weight <= 0 ) return; + + $n=count($p); + $oldx = $p[0]; + $oldy = $p[1]; + if( $fast ) { + for( $i=2; $i < $n; $i+=2 ) { + imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->current_color); + $oldx = $p[$i]; + $oldy = $p[$i+1]; + } + if( $closed ) { + imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->current_color); + } + } + else { + for( $i=2; $i < $n; $i+=2 ) { + $this->StyleLine($oldx,$oldy,$p[$i],$p[$i+1]); + $oldx = $p[$i]; + $oldy = $p[$i+1]; + } + if( $closed ) { + $this->StyleLine($oldx,$oldy,$p[0],$p[1]); + } + } + } + + function FilledPolygon($pts) { + $n=count($pts); + if( $n == 0 ) { + JpGraphError::RaiseL(25105);//('NULL data specified for a filled polygon. Check that your data is not NULL.'); + } + for($i=0; $i < $n; ++$i) { + $pts[$i] = round($pts[$i]); + } + $old = $this->line_weight; + imagesetthickness($this->img,1); + imagefilledpolygon($this->img,$pts,count($pts)/2,$this->current_color); + $this->line_weight = $old; + imagesetthickness($this->img,$old); + } + + function Rectangle($xl,$yu,$xr,$yl) { + $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu)); + } + + function FilledRectangle($xl,$yu,$xr,$yl) { + $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl)); + } + + function FilledRectangle2($xl,$yu,$xr,$yl,$color1,$color2,$style=1) { + // Fill a rectangle with lines of two colors + if( $style===1 ) { + // Horizontal stripe + if( $yl < $yu ) { + $t = $yl; $yl=$yu; $yu=$t; + } + for( $y=$yu; $y <= $yl; ++$y) { + $this->SetColor($color1); + $this->Line($xl,$y,$xr,$y); + ++$y; + $this->SetColor($color2); + $this->Line($xl,$y,$xr,$y); + } + } + else { + if( $xl < $xl ) { + $t = $xl; $xl=$xr; $xr=$t; + } + for( $x=$xl; $x <= $xr; ++$x) { + $this->SetColor($color1); + $this->Line($x,$yu,$x,$yl); + ++$x; + $this->SetColor($color2); + $this->Line($x,$yu,$x,$yl); + } + } + } + + function ShadowRectangle($xl,$yu,$xr,$yl,$fcolor=false,$shadow_width=4,$shadow_color='darkgray',$useAlpha=true) { + // This is complicated by the fact that we must also handle the case where + // the reactangle has no fill color + $xl = floor($xl); + $yu = floor($yu); + $xr = floor($xr); + $yl = floor($yl); + $this->PushColor($shadow_color); + $shadowAlpha=0; + $this->SetLineWeight(1); + $this->SetLineStyle('solid'); + $basecolor = $this->rgb->Color($shadow_color); + $shadow_color = array($basecolor[0],$basecolor[1],$basecolor[2],); + for( $i=0; $i < $shadow_width; ++$i ) { + $this->SetColor($shadow_color,$shadowAlpha); + $this->Line($xr-$shadow_width+$i, $yu+$shadow_width, + $xr-$shadow_width+$i, $yl-$shadow_width-1+$i); + $this->Line($xl+$shadow_width, $yl-$shadow_width+$i, + $xr-$shadow_width+$i, $yl-$shadow_width+$i); + if( $useAlpha ) $shadowAlpha += 1.0/$shadow_width; + } + + $this->PopColor(); + if( $fcolor==false ) { + $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); + } + else { + $this->PushColor($fcolor); + $this->FilledRectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); + $this->PopColor(); + $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); + } + } + + function FilledRoundedRectangle($xt,$yt,$xr,$yl,$r=5) { + if( $r==0 ) { + $this->FilledRectangle($xt,$yt,$xr,$yl); + return; + } + + // To avoid overlapping fillings (which will look strange + // when alphablending is enabled) we have no choice but + // to fill the five distinct areas one by one. + + // Center square + $this->FilledRectangle($xt+$r,$yt+$r,$xr-$r,$yl-$r); + // Top band + $this->FilledRectangle($xt+$r,$yt,$xr-$r,$yt+$r); + // Bottom band + $this->FilledRectangle($xt+$r,$yl-$r,$xr-$r,$yl); + // Left band + $this->FilledRectangle($xt,$yt+$r,$xt+$r,$yl-$r); + // Right band + $this->FilledRectangle($xr-$r,$yt+$r,$xr,$yl-$r); + + // Topleft & Topright arc + $this->FilledArc($xt+$r,$yt+$r,$r*2,$r*2,180,270); + $this->FilledArc($xr-$r,$yt+$r,$r*2,$r*2,270,360); + + // Bottomleft & Bottom right arc + $this->FilledArc($xt+$r,$yl-$r,$r*2,$r*2,90,180); + $this->FilledArc($xr-$r,$yl-$r,$r*2,$r*2,0,90); + + } + + function RoundedRectangle($xt,$yt,$xr,$yl,$r=5) { + + if( $r==0 ) { + $this->Rectangle($xt,$yt,$xr,$yl); + return; + } + + // Top & Bottom line + $this->Line($xt+$r,$yt,$xr-$r,$yt); + $this->Line($xt+$r,$yl,$xr-$r,$yl); + + // Left & Right line + $this->Line($xt,$yt+$r,$xt,$yl-$r); + $this->Line($xr,$yt+$r,$xr,$yl-$r); + + // Topleft & Topright arc + $this->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); + $this->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); + + // Bottomleft & Bottomright arc + $this->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); + $this->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); + } + + function FilledBevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='darkgray@0.4') { + $this->FilledRectangle($x1,$y1,$x2,$y2); + $this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2); + } + + function Bevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='black@0.5') { + $this->PushColor($color1); + for( $i=0; $i < $depth; ++$i ) { + $this->Line($x1+$i,$y1+$i,$x1+$i,$y2-$i); + $this->Line($x1+$i,$y1+$i,$x2-$i,$y1+$i); + } + $this->PopColor(); + + $this->PushColor($color2); + for( $i=0; $i < $depth; ++$i ) { + $this->Line($x1+$i,$y2-$i,$x2-$i,$y2-$i); + $this->Line($x2-$i,$y1+$i,$x2-$i,$y2-$i-1); + } + $this->PopColor(); + } + + function StyleLineTo($x,$y) { + $this->StyleLine($this->lastx,$this->lasty,$x,$y); + $this->lastx=$x; + $this->lasty=$y; + } + + function LineTo($x,$y) { + $this->Line($this->lastx,$this->lasty,$x,$y); + $this->lastx=$x; + $this->lasty=$y; + } + + function Point($x,$y) { + imagesetpixel($this->img,round($x),round($y),$this->current_color); + } + + function Fill($x,$y) { + imagefill($this->img,round($x),round($y),$this->current_color); + } + + function FillToBorder($x,$y,$aBordColor) { + $bc = $this->rgb->allocate($aBordColor); + if( $bc == -1 ) { + JpGraphError::RaiseL(25106);//('Image::FillToBorder : Can not allocate more colors'); + } + imagefilltoborder($this->img,round($x),round($y),$bc,$this->current_color); + } + + function SetExpired($aFlg=true) { + $this->expired = $aFlg; + } + + // Generate image header + function Headers() { + + // In case we are running from the command line with the client version of + // PHP we can't send any headers. + $sapi = php_sapi_name(); + if( $sapi == 'cli' ) return; + + // These parameters are set by headers_sent() but they might cause + // an undefined variable error unless they are initilized + $file=''; + $lineno=''; + if( headers_sent($file,$lineno) ) { + $file=basename($file); + $t = new ErrMsgText(); + $msg = $t->Get(10,$file,$lineno); + die($msg); + } + + if ($this->expired) { + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT"); + header("Cache-Control: no-cache, must-revalidate"); + header("Pragma: no-cache"); + } + header("Content-type: image/$this->img_format"); + } + + // Adjust image quality for formats that allow this + function SetQuality($q) { + $this->quality = $q; + } + + // Stream image to browser or to file + function Stream($aFile=NULL) { + $this->DoSupersampling(); + + $func="image".$this->img_format; + if( $this->img_format=="jpeg" && $this->quality != null ) { + $res = @$func($this->img,$aFile,$this->quality); + + if(!$res){ + if($aFile != NULL){ + JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission."); + }else{ + 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."); + } + + } + } + else { + if( $aFile != NULL ) { + $res = @$func($this->img,$aFile); + if( !$res ) { + JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission."); + } + } + else { + $res = @$func($this->img); + if( !$res ) { + 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."); + } + + } + } + } + + // Do SuperSampling using $scale + function DoSupersampling() { + if (SUPERSAMPLING_SCALE <= 1) { + return $this->img; + } + + $dst_img = @imagecreatetruecolor($this->original_width, $this->original_height); + imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, $this->width, $this->height); + $this->Destroy(); + return $this->img = $dst_img; + } + + // Clear resources used by image (this is normally not used since all resources are/should be + // returned when the script terminates + function Destroy() { + imagedestroy($this->img); + } + + // Specify image format. Note depending on your installation + // of PHP not all formats may be supported. + function SetImgFormat($aFormat,$aQuality=75) { + $this->quality = $aQuality; + $aFormat = strtolower($aFormat); + $tst = true; + $supported = imagetypes(); + if( $aFormat=="auto" ) { + if( $supported & IMG_PNG ) $this->img_format="png"; + elseif( $supported & IMG_JPG ) $this->img_format="jpeg"; + elseif( $supported & IMG_GIF ) $this->img_format="gif"; + elseif( $supported & IMG_WBMP ) $this->img_format="wbmp"; + elseif( $supported & IMG_XPM ) $this->img_format="xpm"; + else { + 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."); + } + return true; + } + else { + if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) { + if( $aFormat=="jpeg" && !($supported & IMG_JPG) ) $tst=false; + elseif( $aFormat=="png" && !($supported & IMG_PNG) ) $tst=false; + elseif( $aFormat=="gif" && !($supported & IMG_GIF) ) $tst=false; + elseif( $aFormat=="wbmp" && !($supported & IMG_WBMP) ) $tst=false; + elseif( $aFormat=="xpm" && !($supported & IMG_XPM) ) $tst=false; + else { + $this->img_format=$aFormat; + return true; + } + } + else { + $tst=false; + } + if( !$tst ) { + JpGraphError::RaiseL(25110,$aFormat);//(" Your PHP installation does not support the chosen graphic format: $aFormat"); + } + } + } + + /** + * Draw Line + */ + function DrawLine($im, $x1, $y1, $x2, $y2, $weight, $color) { + if ($weight == 1) { + return imageline($im,$x1,$y1,$x2,$y2,$color); + } + + $angle=(atan2(($y1 - $y2), ($x2 - $x1))); + + $dist_x = $weight * (sin($angle)) / 2; + $dist_y = $weight * (cos($angle)) / 2; + + $p1x=ceil(($x1 + $dist_x)); + $p1y=ceil(($y1 + $dist_y)); + $p2x=ceil(($x2 + $dist_x)); + $p2y=ceil(($y2 + $dist_y)); + $p3x=ceil(($x2 - $dist_x)); + $p3y=ceil(($y2 - $dist_y)); + $p4x=ceil(($x1 - $dist_x)); + $p4y=ceil(($y1 - $dist_y)); + + $array=array($p1x,$p1y,$p2x,$p2y,$p3x,$p3y,$p4x,$p4y); + imagefilledpolygon ( $im, $array, (count($array)/2), $color ); + + // for antialias + imageline($im, $p1x, $p1y, $p2x, $p2y, $color); + imageline($im, $p3x, $p3y, $p4x, $p4y, $color); + return; + + + + return imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); + $weight = 8; + if ($weight <= 1) { + return imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); + } + + $pts = array(); + + $weight /= 2; + + if ($y2 - $y1 == 0) { + // x line + $pts = array(); + $pts[] = $x1; $pts[] = $y1 - $weight; + $pts[] = $x1; $pts[] = $y1 + $weight; + $pts[] = $x2; $pts[] = $y2 + $weight; + $pts[] = $x2; $pts[] = $y2 - $weight; + + } elseif ($x2 - $x1 == 0) { + // y line + $pts = array(); + $pts[] = $x1 - $weight; $pts[] = $y1; + $pts[] = $x1 + $weight; $pts[] = $y1; + $pts[] = $x2 + $weight; $pts[] = $y2; + $pts[] = $x2 - $weight; $pts[] = $y2; + + } else { + + var_dump($x1, $x2, $y1, $y2); + $length = sqrt(pow($x2 - $x1, 2) + pow($y2 - $y1, 2)); + var_dump($length);exit; + exit; + +/* + $lean = ($y2 - $y1) / ($x2 - $x1); + $lean2 = -1 / $lean; + $sin = $lean / ($y2 - $y1); + $cos = $lean / ($x2 - $x1); + + $pts[] = $x1 + (-$weight * $sin); $pts[] = $y1 + (-$weight * $cos); + $pts[] = $x1 + (+$weight * $sin); $pts[] = $y1 + (+$weight * $cos); + $pts[] = $x2 + (+$weight * $sin); $pts[] = $y2 + (+$weight * $cos); + $pts[] = $x2 + (-$weight * $sin); $pts[] = $y2 + (-$weight * $cos); +*/ + } + +//print_r($pts);exit; + if (count($pts)/2 < 3) { + return; + } + + imagesetthickness($im, 1); + imagefilledpolygon($im, $pts,count($pts)/2, $color); + + + $weight *= 2; + +// $this->DrawImageSmoothArc($im, $x1, $y1, $weight, $weight, 0, 360, $color); +// $this->DrawImageSmoothArc($im, $x2, $y2, $weight, $weight, 0, 360, $color); + } + + + function DrawImageSmoothArc($im, $xc, $yc, $w, $h, $s, $e, $color, $style = null) { + $tmp = $s; + $s = (360 - $e) / 180 * M_PI; + $e = (360 - $tmp) / 180 * M_PI; + return imageSmoothArc($im, round($xc), round($yc), round($w), round($h), $this->CreateColorForImageSmoothArc($color), $s, $e); + } + + function CreateColorForImageSmoothArc($color) { + $alpha = $color >> 24 & 0xFF; + $red = $color >> 16 & 0xFF; + $green = $color >> 8 & 0xFF; + $blue = $color & 0xFF; + +//var_dump($alpha, $red, $green, $blue);exit; + + return array($red, $green, $blue, $alpha); + } + + function imageSmoothCircle( &$img, $cx, $cy, $cr, $color ) { + $ir = $cr; + $ix = 0; + $iy = $ir; + $ig = 2 * $ir - 3; + $idgr = -6; + $idgd = 4 * $ir - 10; + $fill = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], 0 ); + imageLine( $img, $cx + $cr - 1, $cy, $cx, $cy, $fill ); + imageLine( $img, $cx - $cr + 1, $cy, $cx - 1, $cy, $fill ); + imageLine( $img, $cx, $cy + $cr - 1, $cx, $cy + 1, $fill ); + imageLine( $img, $cx, $cy - $cr + 1, $cx, $cy - 1, $fill ); + $draw = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], 42 ); + imageSetPixel( $img, $cx + $cr, $cy, $draw ); + imageSetPixel( $img, $cx - $cr, $cy, $draw ); + imageSetPixel( $img, $cx, $cy + $cr, $draw ); + imageSetPixel( $img, $cx, $cy - $cr, $draw ); + while ( $ix <= $iy - 2 ) { + if ( $ig < 0 ) { + $ig += $idgd; + $idgd -= 8; + $iy--; + } else { + $ig += $idgr; + $idgd -= 4; + } + $idgr -= 4; + $ix++; + imageLine( $img, $cx + $ix, $cy + $iy - 1, $cx + $ix, $cy + $ix, $fill ); + imageLine( $img, $cx + $ix, $cy - $iy + 1, $cx + $ix, $cy - $ix, $fill ); + imageLine( $img, $cx - $ix, $cy + $iy - 1, $cx - $ix, $cy + $ix, $fill ); + imageLine( $img, $cx - $ix, $cy - $iy + 1, $cx - $ix, $cy - $ix, $fill ); + imageLine( $img, $cx + $iy - 1, $cy + $ix, $cx + $ix, $cy + $ix, $fill ); + imageLine( $img, $cx + $iy - 1, $cy - $ix, $cx + $ix, $cy - $ix, $fill ); + imageLine( $img, $cx - $iy + 1, $cy + $ix, $cx - $ix, $cy + $ix, $fill ); + imageLine( $img, $cx - $iy + 1, $cy - $ix, $cx - $ix, $cy - $ix, $fill ); + $filled = 0; + for ( $xx = $ix - 0.45; $xx < $ix + 0.5; $xx += 0.2 ) { + for ( $yy = $iy - 0.45; $yy < $iy + 0.5; $yy += 0.2 ) { + if ( sqrt( pow( $xx, 2 ) + pow( $yy, 2 ) ) < $cr ) $filled += 4; + } + } + $draw = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], ( 100 - $filled ) ); + imageSetPixel( $img, $cx + $ix, $cy + $iy, $draw ); + imageSetPixel( $img, $cx + $ix, $cy - $iy, $draw ); + imageSetPixel( $img, $cx - $ix, $cy + $iy, $draw ); + imageSetPixel( $img, $cx - $ix, $cy - $iy, $draw ); + imageSetPixel( $img, $cx + $iy, $cy + $ix, $draw ); + imageSetPixel( $img, $cx + $iy, $cy - $ix, $draw ); + imageSetPixel( $img, $cx - $iy, $cy + $ix, $draw ); + imageSetPixel( $img, $cx - $iy, $cy - $ix, $draw ); + } + } + + function __get($name) { + + if (strpos($name, 'raw_') !== false) { + // if $name == 'raw_left_margin' , return $this->_left_margin; + $variable_name = '_' . str_replace('raw_', '', $name); + return $this->$variable_name; + } + + $variable_name = '_' . $name; + + if (isset($this->$variable_name)) { + return $this->$variable_name * SUPERSAMPLING_SCALE; + } else { + JpGraphError::RaiseL('25132', $name); + } + } + + function __set($name, $value) { + $this->{'_'.$name} = $value; + } + +} // CLASS + +//=================================================== +// CLASS RotImage +// Description: Exactly as Image but draws the image at +// a specified angle around a specified rotation point. +//=================================================== +class RotImage extends Image { + public $a=0; + public $dx=0,$dy=0,$transx=0,$transy=0; + private $m=array(); + + function __construct($aWidth,$aHeight,$a=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) { + parent::__construct($aWidth,$aHeight,$aFormat,$aSetAutoMargin); + $this->dx=$this->width/2; + $this->dy=$this->height/2; + $this->SetAngle($a); + } + + function SetCenter($dx,$dy) { + $old_dx = $this->dx; + $old_dy = $this->dy; + $this->dx=$dx; + $this->dy=$dy; + $this->SetAngle($this->a); + return array($old_dx,$old_dy); + } + + function SetTranslation($dx,$dy) { + $old = array($this->transx,$this->transy); + $this->transx = $dx; + $this->transy = $dy; + return $old; + } + + function UpdateRotMatrice() { + $a = $this->a; + $a *= M_PI/180; + $sa=sin($a); $ca=cos($a); + // Create the rotation matrix + $this->m[0][0] = $ca; + $this->m[0][1] = -$sa; + $this->m[0][2] = $this->dx*(1-$ca) + $sa*$this->dy ; + $this->m[1][0] = $sa; + $this->m[1][1] = $ca; + $this->m[1][2] = $this->dy*(1-$ca) - $sa*$this->dx ; + } + + function SetAngle($a) { + $tmp = $this->a; + $this->a = $a; + $this->UpdateRotMatrice(); + return $tmp; + } + + function Circle($xc,$yc,$r) { + list($xc,$yc) = $this->Rotate($xc,$yc); + parent::Circle($xc,$yc,$r); + } + + function FilledCircle($xc,$yc,$r) { + list($xc,$yc) = $this->Rotate($xc,$yc); + parent::FilledCircle($xc,$yc,$r); + } + + + function Arc($xc,$yc,$w,$h,$s,$e) { + list($xc,$yc) = $this->Rotate($xc,$yc); + $s += $this->a; + $e += $this->a; + parent::Arc($xc,$yc,$w,$h,$s,$e); + } + + function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') { + list($xc,$yc) = $this->Rotate($xc,$yc); + $s += $this->a; + $e += $this->a; + parent::FilledArc($xc,$yc,$w,$h,$s,$e); + } + + function SetMargin($lm,$rm,$tm,$bm) { + parent::SetMargin($lm,$rm,$tm,$bm); + $this->UpdateRotMatrice(); + } + + function Rotate($x,$y) { + // Optimization. Ignore rotation if Angle==0 || Angle==360 + if( $this->a == 0 || $this->a == 360 ) { + return array($x + $this->transx, $y + $this->transy ); + } + else { + $x1=round($this->m[0][0]*$x + $this->m[0][1]*$y,1) + $this->m[0][2] + $this->transx; + $y1=round($this->m[1][0]*$x + $this->m[1][1]*$y,1) + $this->m[1][2] + $this->transy; + return array($x1,$y1); + } + } + + function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) { + list($toX,$toY) = $this->Rotate($toX,$toY); + parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix); + + } + + function ArrRotate($pnts) { + $n = count($pnts)-1; + for($i=0; $i < $n; $i+=2) { + list ($x,$y) = $this->Rotate($pnts[$i],$pnts[$i+1]); + $pnts[$i] = $x; $pnts[$i+1] = $y; + } + return $pnts; + } + + function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) { + list($x1,$y1) = $this->Rotate($x1,$y1); + list($x2,$y2) = $this->Rotate($x2,$y2); + parent::DashedLine($x1,$y1,$x2,$y2,$dash_length,$dash_space); + } + + function Line($x1,$y1,$x2,$y2) { + list($x1,$y1) = $this->Rotate($x1,$y1); + list($x2,$y2) = $this->Rotate($x2,$y2); + parent::Line($x1,$y1,$x2,$y2); + } + + function Rectangle($x1,$y1,$x2,$y2) { + // Rectangle uses Line() so it will be rotated through that call + parent::Rectangle($x1,$y1,$x2,$y2); + } + + function FilledRectangle($x1,$y1,$x2,$y2) { + if( $y1==$y2 || $x1==$x2 ) + $this->Line($x1,$y1,$x2,$y2); + else + $this->FilledPolygon(array($x1,$y1,$x2,$y1,$x2,$y2,$x1,$y2)); + } + + function Polygon($pnts,$closed=FALSE,$fast=FALSE) { + // Polygon uses Line() so it will be rotated through that call unless + // fast drawing routines are used in which case a rotate is needed + if( $fast ) { + parent::Polygon($this->ArrRotate($pnts)); + } + else { + parent::Polygon($pnts,$closed,$fast); + } + } + + function FilledPolygon($pnts) { + parent::FilledPolygon($this->ArrRotate($pnts)); + } + + function Point($x,$y) { + list($xp,$yp) = $this->Rotate($x,$y); + parent::Point($xp,$yp); + } + + function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) { + list($xp,$yp) = $this->Rotate($x,$y); + return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug); + } +} + +//======================================================================= +// CLASS ImgStreamCache +// Description: Handle caching of graphs to files. All image output goes +// through this class +//======================================================================= +class ImgStreamCache { + private $cache_dir, $timeout=0; // Infinite timeout + //--------------- + // CONSTRUCTOR + function __construct($aCacheDir=CACHE_DIR) { + $this->cache_dir = $aCacheDir; + } + + //--------------- + // PUBLIC METHODS + + // Specify a timeout (in minutes) for the file. If the file is older then the + // timeout value it will be overwritten with a newer version. + // If timeout is set to 0 this is the same as infinite large timeout and if + // timeout is set to -1 this is the same as infinite small timeout + function SetTimeout($aTimeout) { + $this->timeout=$aTimeout; + } + + // Output image to browser and also write it to the cache + function PutAndStream($aImage,$aCacheFileName,$aInline,$aStrokeFileName) { + + // Check if we should always stroke the image to a file + if( _FORCE_IMGTOFILE ) { + $aStrokeFileName = _FORCE_IMGDIR.GenImgName(); + } + + if( $aStrokeFileName != '' ) { + + if( $aStrokeFileName == 'auto' ) { + $aStrokeFileName = GenImgName(); + } + + if( file_exists($aStrokeFileName) ) { + + // Wait for lock (to make sure no readers are trying to access the image) + $fd = fopen($aStrokeFileName,'w'); + $lock = flock($fd, LOCK_EX); + + // Since the image write routines only accepts a filename which must not + // exist we need to delete the old file first + if( !@unlink($aStrokeFileName) ) { + $lock = flock($fd, LOCK_UN); + JpGraphError::RaiseL(25111,$aStrokeFileName); + //(" Can't delete cached image $aStrokeFileName. Permission problem?"); + } + $aImage->Stream($aStrokeFileName); + $lock = flock($fd, LOCK_UN); + fclose($fd); + + } + else { + $aImage->Stream($aStrokeFileName); + } + + return; + } + + if( $aCacheFileName != '' && USE_CACHE) { + + $aCacheFileName = $this->cache_dir . $aCacheFileName; + if( file_exists($aCacheFileName) ) { + if( !$aInline ) { + // If we are generating image off-line (just writing to the cache) + // and the file exists and is still valid (no timeout) + // then do nothing, just return. + $diff=time()-filemtime($aCacheFileName); + if( $diff < 0 ) { + JpGraphError::RaiseL(25112,$aCacheFileName); + //(" Cached imagefile ($aCacheFileName) has file date in the future!!"); + } + if( $this->timeout>0 && ($diff <= $this->timeout*60) ) return; + } + + // Wait for lock (to make sure no readers are trying to access the image) + $fd = fopen($aCacheFileName,'w'); + $lock = flock($fd, LOCK_EX); + + if( !@unlink($aCacheFileName) ) { + $lock = flock($fd, LOCK_UN); + JpGraphError::RaiseL(25113,$aStrokeFileName); + //(" Can't delete cached image $aStrokeFileName. Permission problem?"); + } + $aImage->Stream($aCacheFileName); + $lock = flock($fd, LOCK_UN); + fclose($fd); + + } + else { + $this->MakeDirs(dirname($aCacheFileName)); + if( !is_writeable(dirname($aCacheFileName)) ) { + 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.'); + } + $aImage->Stream($aCacheFileName); + } + + $res=true; + // Set group to specified + if( CACHE_FILE_GROUP != '' ) { + $res = @chgrp($aCacheFileName,CACHE_FILE_GROUP); + } + if( CACHE_FILE_MOD != '' ) { + $res = @chmod($aCacheFileName,CACHE_FILE_MOD); + } + if( !$res ) { + JpGraphError::RaiseL(25115,$aStrokeFileName); + //(" Can't set permission for cached image $aStrokeFileName. Permission problem?"); + } + + $aImage->Destroy(); + if( $aInline ) { + if ($fh = @fopen($aCacheFileName, "rb") ) { + $aImage->Headers(); + fpassthru($fh); + return; + } + else { + JpGraphError::RaiseL(25116,$aFile);//(" Cant open file from cache [$aFile]"); + } + } + } + elseif( $aInline ) { + $aImage->Headers(); + $aImage->Stream(); + return; + } + } + + function IsValid($aCacheFileName) { + $aCacheFileName = $this->cache_dir.$aCacheFileName; + if ( USE_CACHE && file_exists($aCacheFileName) ) { + $diff=time()-filemtime($aCacheFileName); + if( $this->timeout>0 && ($diff > $this->timeout*60) ) { + return false; + } + else { + return true; + } + } + else { + return false; + } + } + + function StreamImgFile($aImage,$aCacheFileName) { + $aCacheFileName = $this->cache_dir.$aCacheFileName; + if ( $fh = @fopen($aCacheFileName, 'rb') ) { + $lock = flock($fh, LOCK_SH); + $aImage->Headers(); + fpassthru($fh); + $lock = flock($fh, LOCK_UN); + fclose($fh); + return true; + } + else { + JpGraphError::RaiseL(25117,$aCacheFileName);//(" Can't open cached image \"$aCacheFileName\" for reading."); + } + } + + // Check if a given image is in cache and in that case + // pass it directly on to web browser. Return false if the + // image file doesn't exist or exists but is to old + function GetAndStream($aImage,$aCacheFileName) { + if( $this->Isvalid($aCacheFileName) ) { + return $this->StreamImgFile($aImage,$aCacheFileName); + } + else { + return false; + } + } + + //--------------- + // PRIVATE METHODS + // Create all necessary directories in a path + function MakeDirs($aFile) { + $dirs = array(); + // In order to better work when open_basedir is enabled + // we do not create directories in the root path + while ( $aFile != '/' && !(file_exists($aFile)) ) { + $dirs[] = $aFile.'/'; + $aFile = dirname($aFile); + } + for ($i = sizeof($dirs)-1; $i>=0; $i--) { + if(! @mkdir($dirs[$i],0777) ) { + JpGraphError::RaiseL(25118,$aFile);//(" Can't create directory $aFile. Make sure PHP has write permission to this directory."); + } + // We also specify mode here after we have changed group. + // This is necessary if Apache user doesn't belong the + // default group and hence can't specify group permission + // in the previous mkdir() call + if( CACHE_FILE_GROUP != "" ) { + $res=true; + $res =@chgrp($dirs[$i],CACHE_FILE_GROUP); + $res = @chmod($dirs[$i],0777); + if( !$res ) { + JpGraphError::RaiseL(25119,$aFile);//(" Can't set permissions for $aFile. Permission problems?"); + } + } + } + return true; + } +} // CLASS Cache + +?> diff --git a/web/public_php/admin/jpgraph/imageSmoothArc.php b/web/public_php/admin/jpgraph/imageSmoothArc.php new file mode 100644 index 000000000..a1d581ff4 --- /dev/null +++ b/web/public_php/admin/jpgraph/imageSmoothArc.php @@ -0,0 +1,344 @@ += abs($yStart)) { + $aaStartX = true; + } else { + $aaStartX = false; + } + if ($xStop >= $yStop) { + $aaStopX = true; + } else { + $aaStopX = false; + } + //$xp = +1; $yp = -1; $xa = +1; $ya = 0; + for ( $x = 0; $x < $a; $x += 1 ) { + /*$y = $b * sqrt( 1 - ($x*$x)/($a*$a) ); + + $error = $y - (int)($y); + $y = (int)($y); + + $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );*/ + + $_y1 = $dyStop*$x; + $_y2 = $dyStart*$x; + if ($xStart > $xStop) + { + $error1 = $_y1 - (int)($_y1); + $error2 = 1 - $_y2 + (int)$_y2; + $_y1 = $_y1-$error1; + $_y2 = $_y2+$error2; + } + else + { + $error1 = 1 - $_y1 + (int)$_y1; + $error2 = $_y2 - (int)($_y2); + $_y1 = $_y1+$error1; + $_y2 = $_y2-$error2; + } + /* + if ($aaStopX) + $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 ); + if ($aaStartX) + $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 ); + */ + + if ($seg == 0 || $seg == 2) + { + $i = $seg; + if (!($start > $i*M_PI/2 && $x > $xStart)) { + if ($i == 0) { + $xp = +1; $yp = -1; $xa = +1; $ya = 0; + } else { + $xp = -1; $yp = +1; $xa = 0; $ya = +1; + } + if ( $stop < ($i+1)*(M_PI/2) && $x <= $xStop ) { + $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 ); + $y1 = $_y1; if ($aaStopX) imageSetPixel($img, $cx+$xp*($x)+$xa, $cy+$yp*($y1+1)+$ya, $diffColor1); + + } else { + $y = $b * sqrt( 1 - ($x*$x)/($a*$a) ); + $error = $y - (int)($y); + $y = (int)($y); + $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error ); + $y1 = $y; if ($x < $aaAngleX ) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y1+1)+$ya, $diffColor); + } + if ($start > $i*M_PI/2 && $x <= $xStart) { + $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 ); + $y2 = $_y2; if ($aaStartX) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y2-1)+$ya, $diffColor2); + } else { + $y2 = 0; + } + if ($y2 <= $y1) imageLine($img, $cx+$xp*$x+$xa, $cy+$yp*$y1+$ya , $cx+$xp*$x+$xa, $cy+$yp*$y2+$ya, $fillColor); + } + } + + if ($seg == 1 || $seg == 3) + { + $i = $seg; + if (!($stop < ($i+1)*M_PI/2 && $x > $xStop)) { + if ($i == 1) { + $xp = -1; $yp = -1; $xa = 0; $ya = 0; + } else { + $xp = +1; $yp = +1; $xa = 1; $ya = 1; + } + if ( $start > $i*M_PI/2 && $x < $xStart ) { + $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 ); + $y1 = $_y2; if ($aaStartX) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y1+1)+$ya, $diffColor2); + + } else { + $y = $b * sqrt( 1 - ($x*$x)/($a*$a) ); + $error = $y - (int)($y); + $y = (int) $y; + $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error ); + $y1 = $y; if ($x < $aaAngleX ) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y1+1)+$ya, $diffColor); + } + if ($stop < ($i+1)*M_PI/2 && $x <= $xStop) { + $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 ); + $y2 = $_y1; if ($aaStopX) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y2-1)+$ya, $diffColor1); + } else { + $y2 = 0; + } + if ($y2 <= $y1) imageLine($img, $cx+$xp*$x+$xa, $cy+$yp*$y1+$ya, $cx+$xp*$x+$xa, $cy+$yp*$y2+$ya, $fillColor); + } + } + } + + ///YYYYY + + for ( $y = 0; $y < $b; $y += 1 ) { + /*$x = $a * sqrt( 1 - ($y*$y)/($b*$b) ); + + $error = $x - (int)($x); + $x = (int)($x); + + $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error ); + */ + $_x1 = $dxStop*$y; + $_x2 = $dxStart*$y; + if ($yStart > $yStop) + { + $error1 = $_x1 - (int)($_x1); + $error2 = 1 - $_x2 + (int)$_x2; + $_x1 = $_x1-$error1; + $_x2 = $_x2+$error2; + } + else + { + $error1 = 1 - $_x1 + (int)$_x1; + $error2 = $_x2 - (int)($_x2); + $_x1 = $_x1+$error1; + $_x2 = $_x2-$error2; + } +/* + if (!$aaStopX) + $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 ); + if (!$aaStartX) + $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 ); +*/ + + if ($seg == 0 || $seg == 2) + { + $i = $seg; + if (!($start > $i*M_PI/2 && $y > $yStop)) { + if ($i == 0) { + $xp = +1; $yp = -1; $xa = 1; $ya = 0; + } else { + $xp = -1; $yp = +1; $xa = 0; $ya = 1; + } + if ( $stop < ($i+1)*(M_PI/2) && $y <= $yStop ) { + $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 ); + $x1 = $_x1; if (!$aaStopX) imageSetPixel($img, $cx+$xp*($x1-1)+$xa, $cy+$yp*($y)+$ya, $diffColor1); + } + if ($start > $i*M_PI/2 && $y < $yStart) { + $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 ); + $x2 = $_x2; if (!$aaStartX) imageSetPixel($img, $cx+$xp*($x2+1)+$xa, $cy+$yp*($y)+$ya, $diffColor2); + } else { + $x = $a * sqrt( 1 - ($y*$y)/($b*$b) ); + $error = $x - (int)($x); + $x = (int)($x); + $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error ); + $x1 = $x; if ($y < $aaAngleY && $y <= $yStop ) imageSetPixel($img, $cx+$xp*($x1+1)+$xa, $cy+$yp*$y+$ya, $diffColor); + } + } + } + + if ($seg == 1 || $seg == 3) + { + $i = $seg; + if (!($stop < ($i+1)*M_PI/2 && $y > $yStart)) { + if ($i == 1) { + $xp = -1; $yp = -1; $xa = 0; $ya = 0; + } else { + $xp = +1; $yp = +1; $xa = 1; $ya = 1; + } + if ( $start > $i*M_PI/2 && $y < $yStart ) { + $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 ); + $x1 = $_x2; if (!$aaStartX) imageSetPixel($img, $cx+$xp*($x1-1)+$xa, $cy+$yp*$y+$ya, $diffColor2); + } + if ($stop < ($i+1)*M_PI/2 && $y <= $yStop) { + $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 ); + $x2 = $_x1; if (!$aaStopX) imageSetPixel($img, $cx+$xp*($x2+1)+$xa, $cy+$yp*$y+$ya, $diffColor1); + } else { + $x = $a * sqrt( 1 - ($y*$y)/($b*$b) ); + $error = $x - (int)($x); + $x = (int)($x); + $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error ); + $x1 = $x; if ($y < $aaAngleY && $y < $yStart) imageSetPixel($img,$cx+$xp*($x1+1)+$xa, $cy+$yp*$y+$ya, $diffColor); + } + } + } + } +} + + +function imageSmoothArc ( &$img, $cx, $cy, $w, $h, $color, $start, $stop) +{ + // Originally written from scratch by Ulrich Mierendorff, 06/2006 + // Rewritten and improved, 04/2007, 07/2007 + // compared to old version: + // + Support for transparency added + // + Improved quality of edges & antialiasing + + // note: This function does not represent the fastest way to draw elliptical + // arcs. It was written without reading any papers on that subject. Better + // algorithms may be twice as fast or even more. + + // what it cannot do: It does not support outlined arcs, only filled + + // Parameters: + // $cx - Center of ellipse, X-coord + // $cy - Center of ellipse, Y-coord + // $w - Width of ellipse ($w >= 2) + // $h - Height of ellipse ($h >= 2 ) + // $color - Color of ellipse as a four component array with RGBA + // $start - Starting angle of the arc, no limited range! + // $stop - Stop angle of the arc, no limited range! + // $start _can_ be greater than $stop! + // If any value is not in the given range, results are undefined! + + // This script does not use any special algorithms, everything is completely + // written from scratch; see http://de.wikipedia.org/wiki/Ellipse for formulas. + + while ($start < 0) + $start += 2*M_PI; + while ($stop < 0) + $stop += 2*M_PI; + + while ($start > 2*M_PI) + $start -= 2*M_PI; + + while ($stop > 2*M_PI) + $stop -= 2*M_PI; + + + if ($start > $stop) + { + imageSmoothArc ( $img, $cx, $cy, $w, $h, $color, $start, 2*M_PI); + imageSmoothArc ( $img, $cx, $cy, $w, $h, $color, 0, $stop); + return; + } + + $a = 1.0*round ($w/2); + $b = 1.0*round ($h/2); + $cx = 1.0*round ($cx); + $cy = 1.0*round ($cy); + + $aaAngle = atan(($b*$b)/($a*$a)*tan(0.25*M_PI)); + $aaAngleX = $a*cos($aaAngle); + $aaAngleY = $b*sin($aaAngle); + + $a -= 0.5; // looks better... + $b -= 0.5; + + for ($i=0; $i<4;$i++) + { + if ($start < ($i+1)*M_PI/2) + { + if ($start > $i*M_PI/2) + { + if ($stop > ($i+1)*M_PI/2) + { + imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY , $color, $start, ($i+1)*M_PI/2, $i); + } + else + { + imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $start, $stop, $i); + break; + } + } + else + { + if ($stop > ($i+1)*M_PI/2) + { + imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $i*M_PI/2, ($i+1)*M_PI/2, $i); + } + else + { + imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $i*M_PI/2, $stop, $i); + break; + } + } + } + } +} +?> diff --git a/web/public_php/admin/jpgraph/imgdata_balls.inc b/web/public_php/admin/jpgraph/imgdata_balls.inc deleted file mode 100644 index f876bb885..000000000 --- a/web/public_php/admin/jpgraph/imgdata_balls.inc +++ /dev/null @@ -1,1064 +0,0 @@ - 'imgdata_large', - MARK_IMG_MBALL => 'imgdata_small', - MARK_IMG_SBALL => 'imgdata_xsmall', - MARK_IMG_BALL => 'imgdata_xsmall'); - var $colors_1 = array('blue','lightblue','brown','darkgreen', - 'green','purple','red','gray','yellow','silver','gray'); - var $index_1 = array('blue'=>9,'lightblue'=>1,'brown'=>6,'darkgreen'=>7, - 'green'=>8,'purple'=>4,'red'=>0,'gray'=>5,'silver'=>3,'yellow'=>2); - var $maxidx_1 = 9 ; - - var $colors_2 = array('blue','bluegreen','brown','cyan', - 'darkgray','greengray','gray','green', - 'greenblue','lightblue','lightred', - 'purple','red','white','yellow'); - - - var $index_2 = array('blue'=>9,'bluegreen'=>13,'brown'=>8,'cyan'=>12, - 'darkgray'=>5,'greengray'=>6,'gray'=>2,'green'=>10, - 'greenblue'=>3,'lightblue'=>1,'lightred'=>14, - 'purple'=>7,'red'=>0,'white'=>11,'yellow'=>4); - - var $maxidx_2 = 14 ; - - - var $colors_3 = array('bluegreen','cyan','darkgray','greengray', - 'gray','graypurple','green','greenblue','lightblue', - 'lightred','navy','orange','purple','red','yellow'); - - var $index_3 = array('bluegreen'=>1,'cyan'=>11,'darkgray'=>14,'greengray'=>10, - 'gray'=>3,'graypurple'=>4,'green'=>9,'greenblue'=>7, - 'lightblue'=>13,'lightred'=>0,'navy'=>2,'orange'=>12, - 'purple'=>8,'red'=>5,'yellow'=>6); - var $maxidx_3 = 14 ; - - var $colors,$index,$maxidx; - var $imgdata_large ; - var $imgdata_small ; - var $imgdata_xsmall ; - - - function GetImg($aMark,$aIdx) { - switch( $aMark ) { - case MARK_IMG_SBALL: - case MARK_IMG_BALL: - $this->colors = $this->colors_3; - $this->index = $this->index_3 ; - $this->maxidx = $this->maxidx_3 ; - break; - case MARK_IMG_MBALL: - $this->colors = $this->colors_2; - $this->index = $this->index_2 ; - $this->maxidx = $this->maxidx_2 ; - break; - default: - $this->colors = $this->colors_1; - $this->index = $this->index_1 ; - $this->maxidx = $this->maxidx_1 ; - break; - } - return parent::GetImg($aMark,$aIdx); - } - - function ImgData_Balls() { - -//========================================================== -// File: bl_red.png -//========================================================== - $this->imgdata_large[0][0]= 1072 ; - $this->imgdata_large[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAByF'. - 'BMVEX/////////xsb/vb3/lIz/hIT/e3v/c3P/c2v/a2v/Y2P/'. - 'UlL/Skr/SkL/Qjn/MTH/MSn/KSn/ISH/IRj/GBj/GBD/EBD/EA'. - 'j/CAj/CAD/AAD3QkL3MTH3KSn3KSH3GBj3EBD3CAj3AAD1zMzv'. - 'QkLvISHvIRjvGBjvEBDvEAjvAADnUlLnSkrnMTnnKSnnIRjnGB'. - 'DnEBDnCAjnAADec3PeSkreISHeGBjeGBDeEAjWhITWa2vWUlLW'. - 'SkrWISnWGBjWEBDWEAjWCAjWAADOnp7Oa2vOGCHOGBjOGBDOEB'. - 'DOCAjOAADJrq7Gt7fGGBjGEBDGCAjGAADEpKS/v7+9QkK9GBC9'. - 'EBC9CAi9AAC1e3u1a2u1Skq1KSm1EBC1CAi1AACtEBCtCBCtCA'. - 'itAACngYGlCAilAACghIScOTmcCAicAACYgYGUGAiUCAiUAAiU'. - 'AACMKSmMEACMAACEa2uEGAiEAAB7GBh7CAB7AABzOTlzGBBzCA'. - 'BzAABrSkprOTlrGBhrAABjOTljAABaQkJaOTlaCABaAABSKSlS'. - 'GBhSAABKKSlKGBhKAABCGBhCCABCAAA5CAA5AAAxCAAxAAApCA'. - 'ApAAAhAAAYAACc9eRyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. - 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFD'. - 'UHLytKAAAB4UlEQVR4nGNgIAK4mGjrmNq6BmFIWMmISUpKSmk5'. - 'B8ZEokj4qoiLiQCBgqald3xaBpKMj6y4sLCQkJCIvIaFV0RaUR'. - 'lCSk5cWEiAn19ASN7QwisuraihHiajKyEixM/NwckjoKrvEACU'. - 'qumpg7pAUlREiJdNmZmLT9/cMzwps7Smc3I2WEpGUkxYkJuFiY'. - 'lTxszePzY1v7Shc2oX2D+K4iLCgjzsrOw8embuYUmZeTVtPVOn'. - 'gqSslYAOF+Ln4ZHWtXMPTcjMrWno7J82rRgoZWOsqaCgrqaqqm'. - 'fn5peQmlsK1DR52vRaoFSIs5GRoYG5ub27n19CYm5pdVPnxKnT'. - 'pjWDpLydnZwcHTz8QxMSEnJLgDL9U6dNnQ6Sio4PDAgICA+PTU'. - 'zNzSkph8hADIxKS46Pj0tKTc3MLSksqWrtmQySAjuDIT8rKy0r'. - 'Kz+vtLSmur6jb9JUIJgGdjxDQUVRUVFpaUVNQ1NrZ9+kKVOmTZ'. - 'k6vR0sldJUAwQNTU2dnX0TgOJTQLrSIYFY2dPW1NbW2TNxwtQp'. - 'U6ZMmjJt2rRGWNB3TO7vnzh5MsgSoB6gy7sREdY7bRrQEDAGOb'. - 'wXOQW0TJsOEpwClmxBTTbZ7UDVIPkp7dkYaYqhuLa5trYYUxwL'. - 'AADzm6uekAAcXAAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bl_bluegreen.png -//========================================================== - $this->imgdata_large[1][0]= 1368 ; - $this->imgdata_large[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMMFi8hE9b2uAAABOVJREFUeNq9lk2sJFUVx3+3qv'. - 'tW95t57zFvhiFxmCFRUJRoNCQiJARMhiFx/Igxii5goTG6ZDAu'. - '/EhcSCIrTAgLEiKsJ8ywABNZEMJXEDYCukAmjgjzBkK/j35V1d'. - '333FtV97io97pfzwxfG86qcu/N+Z3zP+fcW/Apmfk4hx57+R/6'. - 'Rqmc9ykhsWjlsUngAA1fXIQ7b73pI/186IGHnn9dH/8frC8v4I'. - 'PiG53uaerR4GmKkv31mB8cyfjd946ZTwR66qVX9OTWIi8UKUv9'. - 'BOrZXpYZvFeiBvzI0fgSUSFKwbVG+Pl1V3HH0VvNR4KeeukV/f'. - 'PmMmdHhst76aXD64AbeVQ9bjNHaiGOC2o3wLrAb2/4LL/84ffn'. - 'fCdzkOdayKpLppBemrBsU5Y1Zdmm9LJdGU6E/t4M24Q26jRDRL'. - 'j3mdc49cSTekFsMzs5XuTsyLDUNSDQ25NwKOly9YIl22MYhJr/'. - 'uoDtBBoT0CxBRGYOAhibIaOCe//2MpfM6KHnX9cXipSlbkKWmS'. - 'nk9iv38J0jixw7vJfrTMYBOvhSoQHJBS09ANELloAGDxW8tfoW'. - 'J+5/UC8CPS0LU7r3SpYarr7M8rmFjMPLXT6/33L4si7Z2GCrQC'. - '+0ctlOaNs9DReV8vSLr85ndPLpZ/WNvHW+01kAVFBOGvJx0wYg'. - 'Sp47RIQ4Emwa8FGJXlDxSCFo5YlVgAo2hwPue/hRndboTV3EW2'. - 'Wp3k6wBp8q56QiWzecW6vwQfnPRkAWhFgILnq08jQ+R2nlUzzN'. - 'uES9Q7Vd+9fba7NmWJW61db2247qACmcjxXr45psYphsFGSLBu'. - 'kIajxqtjNwHkvAjQt0sg3crhPA2+fPz0CuyNFOghsGsr19mnFg'. - 'DGwrRm8UoAtNmQPQtRXDgdC4HImCFEKcCE0oieUWUYq2LtbiGp'. - 'mBQmppfIkjw45DK0QNNkvQ0jMBtPL0UnDRM1rN+cxKwzvOo2NP'. - 'tykR9a1kfpZNDLMG6QDYJqCTBvUe1+uxs+YKyPoGrTwY2HhvC4'. - 'CDWQd5d4xNApNQEEMgjgLdUCLBQ5cprL/trwNwKG2IUmDqDFd5'. - 'sr5BWrlxuSdLDFEFlqAzXGc4zFjupqh6uqYihpxJcEgp026l2w'. - '7wFUv7Z6AvrfRo/n0OYzPwIKE3HUKAJg2otMBiElnsF7wngis9'. - '3ZDjNnLi7huCWUZfueZKTu/M0V3HvmkOFDVxVKDG04ScejSgW5'. - 'V0q5JYFEghuDLHlTmToqDeGOCKIVtrW9hsdmXufEcNLPSXuPHa'. - 'a+bvuh9df5AH/v5PDFmbWQC3Mx+TVvfGVTRB2CodNgT2JBX003'. - 'aANZAYS/BxCv32TV/l2C03G7jgmfjGiT/qmeEmibEYm7XzAO2k'. - 'A+pbgHhBgydqu54YO5eRiLCy7yDvPP6Xqf+5Z+Lu277OYuOpiw'. - 'H15oBmlNOMcmK5RbP+PrEscGU+DSAxdg4CICIkxnLP8aNz63Og'. - 'H3/rdvOb795GVhuaYo0oBc3GGrEsUPVTwO6a7LYd+X51x3Hu/t'. - 'lP5tS65FN+6okn9U+n/sqb596dTvhOF+02myXTmkQNrOw7yD3H'. - 'j14E+UDQjp24/0E9/eKrbA4HH3aMK1b2ccvXvswjv//1J/s5ud'. - 'Due/hRPfP+OmfOrk7vrn7a48ihA3zh8CH+8Iuffiw/n4r9H1ZZ'. - '0zz7G56hAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bl_yellow.png -//========================================================== - $this->imgdata_large[2][0]= 1101 ; - $this->imgdata_large[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'. - 'BMVEX//////////+///+f//9b//8b//73//7X//63//6X//5T/'. - '/4z//4T//3P//2v//1r//0r//0L//zH//yn//yH//xj//xD//w'. - 'j//wD/90L/9zn/9zH/9xj/9xD/9wj/9wD39yn37zn37zH37yH3'. - '7xD37wj37wDv70Lv50rv50Lv5znv5yHv5xjv5wjv5wDn51Ln5x'. - 'Dn3jHn3iHn3hjn3hDn3gje3oze3nPe3lLe1oze1nPe1lLe1ine'. - '1iHe1hje1hDe1gje1gDW1qXW1mvWzqXWzkLWzhjWzhDWzgjWzg'. - 'DOzrXOzq3OzpzOzgDOxkrOxinOxhjOxhDOxgjOxgDGxqXGxnvG'. - 'xmvGvRjGvRDGvQjGvQDFxbnAvr6/v7+9vaW9vZS9vQi9vQC9tR'. - 'C9tQi9tQC7u7W1tZS1tXu1tTG1tQi1rRC1rQi1rQCtrYytrSGt'. - 'rQitrQCtpYStpSGtpQitpQClpYSlpXulpQClnBClnAilnACcnG'. - 'ucnAicnACclAiclACUlFqUlCmUlAiUlACUjFKUjAiUjACMjFKM'. - 'jEqMjACMhACEhACEewB7ezF7exB7ewB7cwBzcylzcwBzaxBzaw'. - 'BraxhrawhrawBrYxBrYwBjYwBjWgBaWgBaUgCXBwRMAAAAAXRS'. - 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. - 'LdfvwAAAAHdElNRQfTAwkRFBKiJZ4hAAAB7ElEQVR4nI3S+1vS'. - 'UBgHcB67WJmIMWAVdDHEDLBC6Go0slj3Ft0m9RRBWQEmFZFDEM'. - 'Qgt0EMFBY7p/+198hj1kM/9N1+++x73rOd6XT/kStnTx4fPzd9'. - 'uwfOjFhomj7smAhwj/6Cm2O0xUwy6g7cCL99uCW3jtBmE7lsdr'. - 'fvejgpzP7uEDFRRoqy2k8xQPnypo2BUMP6waF9Vpf3ciiSzErL'. - 'XTkPc0zDe3bsHDAcc00yoVgqL3UWN2iENpspff+2vn6D0+NnZ9'. - '6lC5K6RuSqBTZn1O/a3rd7v/MSez+WyIpVFX8GuuCA9SjD4N6B'. - 'oRNTfo5PCAVR0fBXoIuOQzab1XjwwNHx00GOj8/nKtV1DdeArk'. - '24R+0ul9PjmbrHPYl+EipyU0OoQSjg8/m83kl/MMhx0fjCkqio'. - 'SMOE7t4JMAzDsizH81AqSdW2hroLPg4/CEF4PhKNx98vlevrbY'. - 'QQXgV6kXwVfjkTiSXmhYVcSa7DIE1DOENe7GM6lUym0l+EXKks'. - 'K20VAeH2M0JvVgrZfL5Qqkiy0lRVaMBd7H7EZUmsiJJcrTdVja'. - 'wGpdbTLj3/3qwrUOjAfGgg4LnNA5tdQx14Hm00QFBm65hfNzAm'. - '+yIFhFtzuj+z2MI/MQn6Uez5pz4Ua41G7VumB/6RX4zMr1TKBr'. - 'SXAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bl_silver.png -//========================================================== - $this->imgdata_large[3][0]= 1481 ; - $this->imgdata_large[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAADAF'. - 'BMVEUAAADOzs7Gxsa9vb21tbXOxsbOzsbGzsb3///O1ta1vb2c'. - 'paVSWlpKWlpSY2ve5+97hIze7/9aY2vO5/9zhJRaa3tSY3PGzt'. - 'aMlJxrc3tja3NKUlpCSlK1vcZze4RSWmPW5/+Upb3G3v9zhJxS'. - 'Y3t7jKVaa4TO3veltc6ElK1re5Rjc4ycpbV7hJRaY3M5QlLn7/'. - '/Gzt6lrb2EjJzO3v9ja3vG1ve9zu+1xueltdacrc6UpcaMnL1C'. - 'SlqElLV7jK1zhKVre5zW3u/O1ue1vc6ttcaMlKVze4xrc4RSWm'. - 'tKUmPG1v+9zve1xu+tveeltd6crdbe5/+9xt6cpb17hJxaY3s5'. - 'QlrW3vfO1u/Gzue1vdattc6lrcaUnLWMlK2EjKVze5Rrc4xja4'. - 'RSWnNKUmtCSmO9xuecpcZ7hKVaY4TW3v/O1vfGzu+1vd6ttdal'. - 'rc69xu+UnL2MlLWEjK1ze5xrc5R7hK1ja4zO1v+1veettd6lrd'. - 'aMlL3Gzv/39//W1t7Gxs61tb29vcatrbWlpa2cnKWUlJyEhIx7'. - 'e4TW1ufGxta1tcZSUlqcnK3W1u+UlKW9vda1tc57e4ytrcalpb'. - '1ra3vOzu9jY3OUlK29vd6MjKWEhJxaWmtSUmNzc4xKSlpjY3tK'. - 'SmNCQlqUjJzOxs7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. - 'AAAAAAAAAAAAAAAAAAAAAAAAD///9fnkWVAAAAAnRSTlP/AOW3'. - 'MEoAAAABYktHRP+lB/LFAAAACXBIWXMAAABFAAAARQBP+QatAA'. - 'AB/klEQVR42mNgxAsYqCdd3+lcb4hLmj8wMMvEu8DCMqYbU9op'. - 'UEFB2MTb26eyysomFl06XEEhUCHLpAKo2z/fujikEUVaXUFBMB'. - 'BouLePuV+VVWGRciIXknSEsImCQd3//xwmPr65llaFcSFJHkjS'. - '3iYmWUDZ//8NfCr989NjNUMSUyTg0jneSiaCINn/gmlVQM12qg'. - 'lJnp5waTMTE5NAkCyHWZW/lXWNfUlikmdYK0zax7siS4EDKJtd'. - 'mQeU1XRwLBdLkRGASucWmGVnZ4dnhZvn5lmm29iVOWpnJqcuko'. - 'JKR1Wm5eTkRKYF5eblp9sU2ZeUJiV7zbfVg0pH56UFBQXNjIqK'. - 'jgkujItX1koKTVmYajsdKu2qETVhwgSXiUDZ2Bn9xqUeoZ5e0t'. - 'LzYYZ3B092ndjtOnmKTmycW1s7SHa+l5dtB8zlccE6RlN0dGbM'. - 'mDVbd5KupNBcL6+F82XgHouLj5vRP2PWLGNdd4+ppnxe8tJec6'. - 'XnNsKkm0uVQ5RDRHQTPTym68nPlZbvkfYCexsa5rpJ2qXa5Umm'. - 'ocmec3m8vHjmSs+fgxyhC5JDQ8WSPT2lvbzm8vDIe0nbtiBLN8'. - '8BigNdu1B6Lsje+fPbUFMLi5TMfGmvHi/puUAv23q2YCTFNqH5'. - 'MvPnSwPh3HasCbm3XUpv+nS5VtrkEkwAANSTpGHdye9PAAAASn'. - 'RFWHRzaWduYXR1cmUANGJkODkyYmE4MWZhNTk4MTIyNDJjNjUx'. - 'NzZhY2UxMDAzOGFhZjdhZWIyNzliNTM2ZGFmZDlkM2RiNDU3Zm'. - 'NlNT9CliMAAAAASUVORK5CYII=' ; - -//========================================================== -// File: bl_purple.png -//========================================================== - $this->imgdata_large[4][0]= 1149 ; - $this->imgdata_large[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACAV'. - 'BMVEX/////////7///5///1v//xv//rf//pf//lP//jP//hP//'. - 'c///a///Wv//Wvf/Uv//Sv//Qv//Qvf/Off/Mf//Kf//If//If'. - 'f/GP//GPf/EP//EPf/CP//CPf/CO//AP//APf3Oe/3Kff3Ke/3'. - 'Ie/3GO/3EO/3AO/vSu/vSufvOefvMefvIefvGOfvEOfvCOfvAO'. - 'fnUufnSufnMd7nId7nGN7nGNbnEN7nCN7nAN7ejN7ejNbec97e'. - 'c9beUtbeQtbeIdbeGNbeENbeCNbeANbWpdbWa9bWQs7WGM7WEM'. - '7WCM7WAM7Otc7Orc7OnM7OSsbOIb3OGMbOEMbOCMbOAM7OAMbG'. - 'pcbGnMbGe8bGa8bGKbXGEL3GCL3GAL3FucXBu73AvsC/v7+9pb'. - '29Ka29GLW9ELW9CLW9AL29ALW5rrm1lLW1e7W1MbW1GKW1EK21'. - 'CLW1CK21AK2tjK2thKWtMaWtIaWtGJytCK2tCKWtAK2tAKWlhK'. - 'Wle6WlEJylCJylAKWlAJyca5ycGJScEJScCJScAJycAJSUWpSU'. - 'UoyUKZSUEIyUCIyUAJSUAIyMUoyMSoyMIYSMEISMCISMAIyMAI'. - 'SECHuEAISEAHt7MXt7EHt7CHt7AHt7AHNzKXNzEGtzAHNzAGtr'. - 'GGtrEGNrCGtrAGtrAGNjCFpjAGNjAFpaAFpaAFIpZn4bAAAAAX'. - 'RSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsS'. - 'AdLdfvwAAAAHdElNRQfTAwkRFB0ymoOwAAAB9UlEQVR4nGNgIA'. - 'K42hhqGtm5+WFIWClKycvLK6gbuARGoEj4aMjLSElISUir6Tt7'. - 'x+aEIWR8leQlwEBSTc/CK7awLguuR0lGQkJMVFRUTFJVzwko1d'. - 'oFk9OQl5IQE+Dh5hVR0TV3CkkvbJgyASJjDZIR5GBl5eRX0TH1'. - 'DEqrbJ2ypBEspSgvJSXKw8bMxMavbOLoGZNf1TZlybw4oIyfLN'. - 'BxotxsLEzsQiaOHkFpBQ2905esrAZK2SpIAaUEuDm5+LTNPAKj'. - 'C+pbps1evrIDKGWnLictKSkuLKyoZQyUya9o7Z2+YMXKGUApew'. - 'M9PTVdXR0TEwf3wOjUirruafOXL18xFyjl72Kpb25qaurg4REU'. - 'EFVe2zJ5zpLlK1aCpbydnZ2dnDwDA6NTopLLeiZNXbB8BcTAyP'. - 'TQ0JDg4KCY1NS83JKmiVOBepYvX9UPlAovzEiPSU/LLyior2vq'. - 'mjZr3vLlIF01IC+XVhUWFlZW1Lc290ycOGfxohVATSsXx4Oksn'. - 'vaWlsb2tq6J0+bM2/RohVA81asbIcEYueU3t7JU6ZNnwNyGkhm'. - '+cp5CRCppJnzZ8+ZM3/JUogECBbBIixr8Yqly8FCy8F6ltUgoj'. - 'lz7sqVK2ByK+cVMSCDxoUrwWDVysXt8WhJKqG4Y8bcuTP6qrGk'. - 'QwwAABiMu7T4HMi4AAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bl_gray.png -//========================================================== - $this->imgdata_large[5][0]= 905 ; - $this->imgdata_large[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAABO1'. - 'BMVEX////////3///39/fv7+/e5+fW3t7Wzs7WxsbG1tbGzsbG'. - 'xsbDxMS/v7++wMC+v7+9zsa9xsa9vb29tbW9ra29pa24uLi1xs'. - 'a1vb21tbWxtrattbWmpqalra2cra2cpaWcnJycjIyUpaWUnJyU'. - 'lJSUjIyMnJyMnJSMlJSMlIyMjJSMjIyElJSElIyEjIyEhIR7jI'. - 'x7hIR7hHt7e3t7e3N7e2tzhIRze3tze3Nzc3Nre3trc3Nrc2tr'. - 'a2tjc3Njc2tja3Nja2tjY2NjWlpaa2taY2taY2NaY1paWlpaUl'. - 'JSY2NSY1pSWlpSWlJSUlJSUkpKWlpKWlJKUlpKUlJKUkpKSkpK'. - 'SkJCUlJCUkJCSkpCSkJCQkI5Sko5QkI5Qjk5OUI5OTkxQkIxOT'. - 'kxMTkxMTEpMTEhMTEhKSkYISEpy7AFAAAAAXRSTlMAQObYZgAA'. - 'AAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdE'. - 'lNRQfTAwkRFQfW40uLAAABx0lEQVR4nI3SbXfSMBQA4NV3nce5'. - 'TecAHUywRMHSgFuBCFsQUqwBS1OsWQh0GTj//y8wZUzdwQ/efM'. - 'tzcm/uuXdj4z9ic/PR9k4qk1qDnf0X2/uZzKt8GaRvSubg4LVp'. - 'mkWzCGAT/i3Zsm2XNQHLsm2n2937LaaNnGoJFAEo27B50qN0ay'. - 'Wg26lXsw8fP8nmzcJb2CbsnF5JmmCE8ncN404KvLfsYwd7/MdV'. - 'Pdgl/VbKMIzbuwVgVZw2JlSKJTVJ3609vWUY957lgAUd1KNcqr'. - 'yWnOcOPn8q7d5/8PywAqsOOiVDrn42NFk+HQ7dVuXNYeFdBTpN'. - 'nY5JdZl8xI5Y+HXYaTVqEDp1hAnRohZM03EUjMdhn5wghOoNnD'. - 'wSK7KiiDPqEtz+iD4ctdyAifNYzUnScBSxwPd6GLfRURW7Ay5i'. - 'pS5bmrY8348C5vvUI+TLiIVSJrVA0heK/GDkJxYMRoyfCSmk4s'. - 'uWc3yic/oBo4yF374LGQs5Xw0GyQljI8bYmEsxVUoKxa6HMpAT'. - 'vgyhU2mR8uU1pXmsa8ezqb6U4mwWF/5MeY8uLtQ0nmmQ8UWYvb'. - 'EcJaYWar7QhztrO5Wr4Q4hDbAG/4hfTAF2iCiWrCEAAAAASUVO'. - 'RK5CYII=' ; - -//========================================================== -// File: bl_brown.png -//========================================================== - $this->imgdata_large[6][0]= 1053 ; - $this->imgdata_large[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAABoV'. - 'BMVEX////Gzs7GvbXGrZTGpXu9nHO1nHO1nIy9taXGxs7GtaXO'. - 'nHPGlFrGjEq9hEq1hEqte0Klczmcazmce1KtnIzGxsbGvb3OlF'. - 'LOlFq9hFKte0qcc0KUYzGEWimMc1K9ta3OnGvOnGPWnGO9jFq9'. - 'jFKlc0KUazmMYzl7UilzUjGtpZzGxr3GnGPWpWvepXO1hFJ7Wj'. - 'FrSiFjUjG1ra3GnHPvxpT/5733zpythFKUa0KEYzlzUilaOSF7'. - 'Wjm9jErvvYz/99b///f/78bnrYS1hFqle0p7UjFrSiljQiFCMR'. - 'iMhHO9lGvGjFLWnGv/3q3////erXuthEqlc0paQiFKMRhSQin/'. - '1qX/997//++cc0pjSilaQilKORhCKRiclIy9pYzGlGPntYT33q'. - '3vvZSEWjlSOSE5KRB7c2O1lHutczmthFqte1JrWkqtjGtCKRBa'. - 'SjmljGuca0KMYzGMaznOztaclISUYzmEWjFKOSF7a1qEYzFaSi'. - 'GUjISEa0pKOSm9vb2llIxaQhg5IQiEc2tzY0paORilnJy1raVS'. - 'OSljUkJjWkKTpvQWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. - 'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkREiei'. - 'zP2EAAAB9UlEQVR4nGWS/VfSUBjHL5QluhhBxtwyWcCus5Blpm'. - 'wDC4ONaWXCyBi7RMZmpQ2Bypm9W/byV3cHHo/W88s95/s5z/d5'. - 'uwCcCh/4L3zAf+bs0NC588On9QAYGSUuBINk6GI4cmnsBLk8Go'. - '1SFEGMkzRzZeLq5JE8FvDHouw1lqXiCZJOcnCKnx4AcP0GBqmZ'. - 'mRgRT9MMB4Wbs7cGSXNRik3dnp9fiMUzNCNKgpzN9bsaWaQo9s'. - '7dfH7pXiFTZCBU1JK27LmtBO8TDx7mV1eXHqXXyiIUFLWiVzHx'. - 'BxcJIvV4/cn6wkqmWOOwmVE3UQOAp6HxRKL5bGPj+VwhUhalFq'. - '8alm5vAt+LlySZTsebzcKrraIIW4JqZC3N3ga+1+EQTZKZta1M'. - 'pCZCSeDViqVrThsEdsLJZLJYLpZrHVGScrKBvTQNtQHY6XIM02'. - 'E6Ik7odRW1Dzy3N28n3kGuB3tQagm7UMBFXI/sATAs7L5vdbEs'. - '8Lycm923NB0j5wMe6KOsKIIyxcuqauxbrmlqyEWfPmPy5assY1'. - 'U1SvWKZWom9nK/HfQ3+v2HYZSMStayTNN0PYKqg11P1nWsWq7u'. - '4gJeY8g9PLrddNXRdW8Iryv86I3ja/9s26gvukhDdvUQnIjlKr'. - 'IdZCNH+3Xw779qbG63f//ZOzb6C4+ofdbzERrSAAAAAElFTkSu'. - 'QmCC' ; - -//========================================================== -// File: bl_darkgreen.png -//========================================================== - $this->imgdata_large[7][0]= 1113 ; - $this->imgdata_large[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'. - 'BMVEX////////3///v///n/+/e99bW/+/W99bO786/v7++vr69'. - '/96999a7wb24vbu1/9a1zqW1u7itxrWosq6l772l1qWlxrWlxq'. - '2lva2cxpSU562U3q2UxqWUvaWUpZyM77WM57WMvYyMtZyMrZyM'. - 'pZSMnJSEvZyEtYyErZSElIx7zpR7xpx7xpR7vZR7jIRz1pRzxp'. - 'RzjIRrzpRrzoxrxoxrtYRrrYxrrXtrpYRrhHNjzoxjxoxjxoRj'. - 'vYRjtYRjrXtjpXtjlGNje2tazoxazoRaxoxaxoRavYRatYRatX'. - 'tarXtapXNanHNajFpae2tSzoRSxoRSvXtStXtSrXtSrXNSpXNS'. - 'nHNSnGtSlGtSlGNSjGtSjGNKvXtKtXNKrXNKpWtKnGtKlGNKjG'. - 'NKhGNKhFJKc1pKa1JCrWtCpWtCnGtClGNCjGNCjFpChFpCe1JC'. - 'a1JCY1I5pWs5nGM5lGM5jFo5hFo5e1o5c0o5WkoxjFoxhFoxhF'. - 'Ixe1Ixc1Ixc0oxa0ophFIpe0opc0opa0opa0IpY0IpWkIpWjkp'. - 'UkIpUjkhc0oha0IhY0IhWjkhWjEhUjkhUjEhSjEhSikhQjEhQi'. - 'kYWjkYSjEYSikYQjEYQikQSikQQikQQiEQOSExf8saAAAAAXRS'. - 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. - 'LdfvwAAAAHdElNRQfTAwkRFCaDkWqUAAAB+ElEQVR4nI3S+1vS'. - 'UBgHcGZlPV0ks/vFrmQWFimJjiwiYUJWjFBWFhClyZCy5hLrwA'. - 'x2EIwJC1w7zf2vnU0re+iHvs9++7x7zznvORbLf+TA6ct9fYMX'. - 'jrfAUYefpp+/iM1ykxf/lmuhUZ/PTwXC8dml5Wcd23o5H5Mk6b'. - '5NUU8icXbhS67rNzn9JDnguOEYGQtEEtwC+Crs3RJ76P5A/znr'. - 'vsNX7wQnEiwHCtK7TTkW8rvdZ9uJtvZTLkxpHhSrP66bNEj7/P'. - '3WNoLYeeSWQQCIpe9lQw7RNEU5rDsIYtcJ14Nocg7kRUlBNkxn'. - 'YmGKcp7cv3vPwR7XOJPmc0VYU3Sv0e9NOBAYG7Hbz/cMjTMveZ'. - 'CHkqxuTBv0PhYJB4N3XR6PJ5rMAPMnpGUxDX1IxSeMTEaZp1OZ'. - 'nGAIQiYtsalUIhFlmGTy3sO3AizJCKn6DKYryxzHsWyaneMzr6'. - 'cWxRVZVlFTe4SpE3zm+U/4+whyiwJcWVMQNr3XONirVWAklxcE'. - 'EdbqchPhjhVzGpeqhUKhWBQhLElr9fo3pDaQPrw5xOl1CGG1JE'. - 'k1uYEBIVkrb02+o6RItfq6rBhbw/tuINT96766KhuqYpY3UFPF'. - 'BbY/19yZ1XF1U0UNBa9T7rZsz80K0jWk6bpWGW55UzbvTHZ+3t'. - 'vbAv/IT+K1uCmhIrKJAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bl_green.png -//========================================================== - $this->imgdata_large[8][0]= 1484 ; - $this->imgdata_large[8][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMMFjM4kcoDJQAABVlJREFUeNq9ll2MJFUVx3/11V'. - 'Vd/TE9vU0v4zLDwJIF16jBqLAPhsRXEiDqg0QTJiQSjcSNvCzw'. - 'sBEDDxizhvAAxBgf1oR9QF9NiE9ESFZkQyZB5WtddmdnZ3qqqr'. - 'uqbt367Cofqu3ZZpWVaDzJfbkf53//55z/PVdZXV3l/2H6f7Lp'. - '5VdOV/4Nb+GmHpUeA7AdBNxc3kafNb73jRPK9Xwon8ToxVefqU'. - 'b91wibH5EkCQBCizFihTSviHUHR0hWws9xe3wvJ7/7nPKpgX5y'. - '9oFqt3eOgWniRBoAbUBGGqZUibSYaeoT2B5bnkdaSA6793Cv/S'. - 'QPPbihXBfo5VdOV+8dfgnvwAU62YH5fCZ12sDujFkwyegCqTrB'. - 'iUOKTOJKj8jr88jS8zy6cXwBTP048nuHX0I0nDlIp7RpTG7kM0'. - 'sdyAYsTVukUuWGhlWHMq0ITL92lnUp9R1Obz/GmTNnqn9bDD8/'. - '+0D1oX0O0zQZZDYCsK2j3Gl9jQqDfHiei8GfiKVLlsZkJaBAN1'. - '0i6PgwUbB0GxG5/PrtE/xLRr959Znqw9452oVNI+jiJhnr1pe4'. - 'k29zB1/nFr5Kj7tpt1YYhJ0FJ7nUYbcJQBgahN2MzeCP/OipR6'. - 'prgN6Qr6ELFQFUWoRpNVjlKwxZB8DCpE+PtfEKqV1cUzxpVudu'. - 'GTBHA5Y1g99e+dUio9O/P1Vpq+/WE5GGjDSMoAtAQjrf3C52IP'. - 'QxpY4WK2hpReka9Gfrhqgz0bACRoCWjDh56kQ1z9FeuUUQxVhK'. - 'B92sD1VahM+bAJgcoJhGjP/6Ln8rAgDiRCVRKiIzxMkkodBJ85'. - 'im1IlEHbE4k1xyNveL4YP8HarmGJIOpqyjeQmfNHmTvnqZTWBt'. - 'vIJXpPwlukJSuSTKGK3pEwtJmiX00ZlInTyNscImO6XBITvH1c'. - '8vVt2OucdKvIyeKRTNCivsEMgcpg6taYs30nfq0Gqg6hOSSFJ4'. - 'BSnJPht0IqEjWmOGocEI6F0J94F0qaL6BntTF0MtUfweKQKAPU'. - 'Wwp4OcVnQAmVb0p9DLOzjEhEKnGRmoRc7EzRGlwA6NujAKG4yP'. - '6Sjwc4aVznZ7DK0xXdkDoJf0kGmFBniFBOBGcZSCCSKd0IwN0k'. - 'IS+QZWCGVZex4BnUxya3+Zt9iugQbcRFpIAtuHvAZulPUdLhUJ'. - 'RqegI3WcqaSXddlT3idsWMSRRGkEtNwmyTifAwyBo7LP+11J0e'. - '7tM7pZOYblHkBLcqZ5LcYtw6Wbd4CM3SpE9foYZsIHoqDKCrbz'. - 'mLSQtPwmuhXgtBLs0GBdbXOhFGB7WBKO2F8GXt9/VO97Ya3atF'. - '7nUHnwGjGGQqcPxFEdFqURkEidiZszAERoYIsGju1hq21kWee3'. - 'bw15+8WpsvAy3K1+i3JkkhZyPpxxjjPOsfOYiZ+TFhLPzQnHOU'. - 'tpzGB2dgA4tscIkKIx19Cxg/fPL7vQJu47eXt1VvsDK8pwPueZ'. - 'PuZoQMOqhRoJHSs0kKLBWjvjYinmeQGw1TaX1RFdfZ3LMzYLjA'. - 'C++dkn6AaH2Nobk6cxEzdnuG0TdC8zvdJkN0hqkFkO/jwL0fxa'. - 'so8sBcuFzQ+/+MRC+BeAHnpwQzn++ee5KT9Eshuy46dcKAXm32'. - '0uzPQhS4GttkH2GQID2Wc0Y4LtAbDxhZ/x5A+e/uTG9+jGceXH'. - '9/ySnnIXnUzOxXe1038mW3ZynNmam4yYWkO+f9cv+Oljz16/lV'. - '9tDz/9nerc1hm8ZEScSRK7VvtYl1i1dklsOKyvc+zg/bzw1O8+'. - '/efkajt56kR1ydlEJBc5H46xzbrJ3dY9wrB7hGcff+6/+279L+'. - '0fHxyiE8XMLl4AAAAASUVORK5CYII=' ; - -//========================================================== -// File: bl_blue.png -//========================================================== - $this->imgdata_large[9][0]= 1169 ; - $this->imgdata_large[9][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACEF'. - 'BMVEX/////////7//35//v1v/exv/Wvf/Wrf/Wpf/Orf+/v7+9'. - 'tc69jP+9hP+5ucW1tc6tlP+rq7Wlpdalpcalpb2cnM6cnMacc/'. - '+cWv+UlLWUjN6UjK2Uc/+Ma/+MUv+EhKWEa/+EQvd7e8Z7e7V7'. - 'e6V7c957Wv9za9Zza8ZzSv9ra5xrSv9rOf9rMe9jUudjQv9jOe'. - '9aWpRaUt5aUpRaSu9aSudSUoxSSs5SSoxSMf9KQtZKOfdKMedK'. - 'Kf9KKe9CKf9CKb1CKa1CIfdCIedCId45MXs5Kfc5If85Iec5Id'. - 'Y5GP8xMbUxMXsxKc4xKZQxIf8xGP8xGO8xGN4xGNYxGL0xGK0p'. - 'KXMpIYwpGP8pGO8pGOcpGNYpGM4pEP8pEPcpEOcpEN4pENYpEM'. - 'YpEL0hGKUhEP8hEPchEO8hEOchEN4hENYhEM4hEMYhELUhCP8h'. - 'CO8hCN4YGJwYGGsYEL0YEK0YEHMYCN4YCM4YCMYYCL0YCKUYAP'. - '8QEJQQEIwQEHsQEGsQCM4QCLUQCK0QCKUQCJwQCJQQCIwQCHMQ'. - 'CGsQAP8QAPcQAO8QAOcQAN4QANYQAM4QAMYQAL0QALUQAKUQAJ'. - 'QQAIQICGsICGMIAO8IANYIAL0IALUIAK0IAKUIAJwIAJQIAIwI'. - 'AIQIAHsIAHMIAGsIAGMAAN4AAMYAAK0AAJQAAIwAAIQAAHMAAG'. - 'sAAGMAAFrR1dDlAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFRPMOZ'. - '/2AAAB+klEQVR4nGNgIAIIqeqZmBqpi2JISNml5lVXV3d198Yo'. - 'oUjwm1SnxsbGRsSm5ZfNXO4tjCTjVh0ABhFx6QV9E1Y0S8JkuN'. - '3yAgLc7W3t/QPi4jPKJ8ye1yoIlTKpjvVy15eVUbN0i4zKLJ8w'. - 'ae6qcKgLqmMj3PUFWFl5NJ0CExLLJzbNW7BWCyxlXR0ba6/Axs'. - 'zELmfnkRBT0QiSKgXJCOflxUbYy3KyMHEoOrtEZ1c2TZ6/cMl6'. - 'eaCUamdsbIC7tjgPr4SBS3BMMVDTwkXr1hsDpYy6UmMj/O0tdX'. - 'QNbDxjknJLWqYsXLx0vStQynxGflpkZGCgs7Onp29SbtNkoMy6'. - 'pevCgFJWy3oyMuKjgoKCPWNCvEuqWhcsWrJ06XqQlPnMvrKyrM'. - 'TomJjkZAfHlNa2qdOWrlu63gcopbG8v7+hvLwip7g4JdSxsLZu'. - '8dKlS9ettwBKic2eNXHChIkTG5tKqgpr2uo6loLAehWQx0LnzJ'. - '49p6mpeXLLlNq6RUvqly6dvnR9Bx9ISnnlvLmT582bMr9t4aL2'. - '+vrp60GaDCGB6Ld6wfwFCxYCJZYsXQ+SmL6+FBryInVrFi1atH'. - 'jJkqVQsH6pNCzCJNvXrQW6CmQJREYFEc2CYevXrwMLAyXXl0oz'. - 'IAOt0vVQUGSIkabkDV3DwlzNVDAksAAAfUbNQRCwr88AAAAASU'. - 'VORK5CYII=' ; - -//========================================================== -// File: bs_red.png -//========================================================== - $this->imgdata_small[0][0]= 437 ; - $this->imgdata_small[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'. - 'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'. - 'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'. - 'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'. - 'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'. - 'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. - 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGDNEMgOYAAAAm0'. - 'lEQVR4nI3Q3RKCIBAFYGZMy9RKzX7MVUAUlQTe/+kS0K49d3wD'. - '7JlFaG+CvIR3FvzPXgpLatxevVVS+Jzv0BDGk/UJwOkQ1ph2g/'. - 'Ct5ACX4wNT1o/zzUoJUFUGBiGfVnDTYGJgmrWy8iKEtp0Bpd2d'. - 'jLGu56MB7f4JOOfDJAwoNwslk/jOUi+Jts6RVNrC1hkhPy50Ef'. - 'u79/ADQMQSGQ8bBywAAAAASUVORK5CYII=' ; - - -//========================================================== -// File: bs_lightblue.png -//========================================================== - $this->imgdata_small[1][0]= 657 ; - $this->imgdata_small[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABVl'. - 'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'. - 'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'. - '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'. - 'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'. - 'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'. - 'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'. - 'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'. - 'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'. - 'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'. - 'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. - 'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGTok'. - '9Yp9AAAAtElEQVR4nGNgIBaw8wkpKghzwvksPAKiUsraprYiLF'. - 'ARXkE2JiZ1PXMHXzGIAIekOFBE08TGLTCOCyzCLyvDxsZqZOnk'. - 'E56kAhaRV9NQUjW2tPcMjs9wBYsY6Oobmlk7egRGpxZmgkW0zC'. - '2s7Jy9giKT8gohaiQcnVzc/UNjkrMLCyHmcHr7BYREJKTlFxbm'. - 'QOxiEIuKTUzJKgQCaZibpdOzQfwCOZibGRi4dcJyw3S4iQ4HAL'. - 'qvIlIAMH7YAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bs_gray.png -//========================================================== - $this->imgdata_small[2][0]= 550 ; - $this->imgdata_small[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAABI1'. - 'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'. - 'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'. - 'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'. - 'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'. - 'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'. - 'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'. - '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'. - 'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'. - 'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIA'. - 'AAsSAdLdfvwAAAAHdElNRQfTAwkUGiIctEHoAAAAfElEQVR4nI'. - '2N2xKDIAwF+bZ2kAa8cNFosBD//yvKWGh9dN+yk9kjxH28R7ze'. - 'wzBOYSX6CaNB927Z9qZ66KTSNmBM7UU9Hx2c5qjmJaWCaV5j4t'. - 'o1ANr40sn5a+x4biElrqHgrXMeac/c1nEpFHG0LSFoo/jO/BeF'. - 'lJnFbT58ayUf0BpA8wAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bs_greenblue.png -//========================================================== - $this->imgdata_small[3][0]= 503 ; - $this->imgdata_small[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAxl'. - 'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'. - '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'. - '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'. - 'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'. - 'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'. - 'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'. - 'dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfT'. - 'AwkUGTIqLgJPAAAAqklEQVR4nI2QVxOCMBCEM6Mi2OiCvSslJB'. - 'CUoqjn//9TYgCfubf9Zu9uZxFqO+rscO7b6l/LljMZX29J2pNr'. - 'YjmX4ZaIEs2NeiWO19NNacl8rHAyD4LR6jjw6PMRdTjZE0JOiU'. - 'dDv2ALTlzRvSdCCfAHGCc7yRPSrAQRQOWxKc3C/IUjBlDdUcM8'. - '97vFGwBY9QsZGBc/A4DWZNbeXIPWZEZI0c2lqSute/gCO9MXGY'. - '4/IOkAAAAASUVORK5CYII=' ; - -//========================================================== -// File: bs_yellow.png -//========================================================== - $this->imgdata_small[4][0]= 507 ; - $this->imgdata_small[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAzF'. - 'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'. - 'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'. - 'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'. - 'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'. - 'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'. - '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'. - 'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAH'. - 'dElNRQfTAwkUGSDZl3MHAAAAqElEQVR4nI3QWRNDMBAA4My09E'. - 'IF1SME0VT1okXvM/3//6kEfbZv+81eswA0DfHxRpOV+M+zkDGG'. - 'rL63zCoJ2ef2RLZDIqNqYexyvFrY9ePkxGWdpvfzC7tEGtIRly'. - 'nqzboFKMlizAXbNnZyiFUKAy4bZ+B6W0lRaQDLmg4h/k7eFwDL'. - 'OWIky8qhXUBQ7gKGmsxpC+ah1TdriwByqG8GQNDNr6kLjf/wAx'. - 'KgEq+FpPbfAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bs_darkgray.png -//========================================================== - $this->imgdata_small[5][0]= 611 ; - $this->imgdata_small[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAABJl'. - 'BMVEX////////o8v/f6O7W4OnR3PXL1OTL0evEyLvCzePAwMC/'. - 'v7a8wsq7t7C1xum1vtS1q6GzopmyxeKsrsOqvNWoq7anvN+nsb'. - 'qhrcGgqbGfpq6cp7+bqMuVmJKRm7yPlKKMnL6FkKWFipOEkLSE'. - 'j6qEhoqAiaB+jqd8haF7hZR4iJt4g5l3hZl2gIt2cod1hJVzeY'. - 'VzboJvhp9sfJJsb41peY1pd5xpdoVod4xndI5lcHxka4BjcYVg'. - 'Z3BfboFbb4lbZnZbYntaZ4laZYVZV3JYYWpXX3JWWm5VX4RVW2'. - 'NUYX9SXHxPWn5OVFxNWWtNVXVMVWFKV3xHUGZGU3dGTldFSlxE'. - 'Sk9ESXBCRlNBS3k/SGs/RU4+R1k9R2U6RFU2PUg0PEQxNU0ECL'. - 'QWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA'. - 'CxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGQmbJetrAAAAtklEQV'. - 'R4nGNgwAK4JZTNNOWlYDxhMT4ZDTOzQE1uMF9CiJWVU0LbxDlS'. - 'G8QVF+FnZ2KRNHAIiPUHaZGSlmZj5lH19A1KjLUA8lXU5MWllF'. - 'yjo30TYr2BfG19G11b37CEeN84H38gX1HbwTUkOjo+zjfG3hLI'. - 'l1exCvCNCwnxjfMz0gTyRdXNHXx9fUNCQu2MwU6SN3ZwD42LCH'. - 'W30IK4T8vUJSAkNMhDiwPqYiktXWN9JZj7UQAAjWEfhlG+kScA'. - 'AAAASUVORK5CYII=' ; - - -//========================================================== -// File: bs_darkgreen.png -//========================================================== - $this->imgdata_small[6][0]= 666 ; - $this->imgdata_small[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABX1'. - 'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'. - 'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'. - 'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'. - 'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'. - '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'. - 'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'. - 'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'. - 'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'. - 'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'. - 'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. - 'RQfTAwkUGRjxlcuZAAAAtElEQVR4nGNgIBZw8osqqIpzw/msfI'. - 'IiUmr6lo6SbFARASEOJiYtQ2uXADmIAJeEGFBE18LBMySBBywi'. - 'LC/LwcFiZuvmH5WiAxZR0tRW1DC3dfYJS8zyAouYGBibWtm7+o'. - 'TEpZfkgEX0rG3snNx9Q2NSCksgaqRd3Ty8gyLiU/NKSiDmcPsF'. - 'BodHJ2UUlZTkQ+xikIlNSE7LLgECZagL2VQyc0H8YnV2uD94jS'. - 'ILIo14iQ4HALarJBNwbJVNAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bs_purple.png -//========================================================== - $this->imgdata_small[7][0]= 447 ; - $this->imgdata_small[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAnF'. - 'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'. - 'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'. - 'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'. - 'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'. - 'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. - 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGS'. - 'o5QpoZAAAAnElEQVR4nI3Q2xJDMBAG4MyQokWrZz3oSkJISJH3'. - 'f7dK0Gv/Xb7J7vyzCK0NjtPsHuH/2wlhTE7LnTNLCO/TFQjjIp'. - 'hHAA6bY06LSqppMAY47x+04HXTba2kAFlmQKr+YuVDCGUG2k6/'. - 'rNwYK8rKwKCnPxHnVS0aA3rag4UQslUGhrlk0Kpv1+sx3tLZ6w'. - 'dtYemMkOsnz8R3V9/hB87DEu2Wos5+AAAAAElFTkSuQmCC' ; - - -//========================================================== -// File: bs_brown.png -//========================================================== - $this->imgdata_small[8][0]= 677 ; - $this->imgdata_small[8][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABaF'. - 'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'. - 'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'. - 'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'. - 'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'. - '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'. - 'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'. - 'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'. - 'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'. - 'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'. - 'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'. - 'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLd'. - 'fvwAAAAHdElNRQfTAwkUGho0tvl2AAAAtklEQVR4nGNgIBaoSg'. - 'mLKGpowfkGMty8AqJKpi4mRlAROR5ONg4JFUv3YHOIgDo/HwsT'. - 'q6yps29EsjZYREFIkJ2ZS9/OMzA20wEsIi8uKSZtaOPmH5WSFw'. - 'YW0VRW07Vw8vCLSMguLwCL6FlaObp6B0TGZxSXQ9TouHv6+IXG'. - 'JGYWlpdDzNEKCgmPjkvLKS0vL4LYxWAen5SelV8OBNZQFxrZ5h'. - 'aC+GX2MDczMBh7pZakehkTHQ4AA0Am/jsB5gkAAAAASUVORK5C'. - 'YII=' ; - -//========================================================== -// File: bs_blue.png -//========================================================== - $this->imgdata_small[9][0]= 436 ; - $this->imgdata_small[9][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'. - 'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'. - 'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'. - 'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'. - 'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'. - 'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. - 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGhNNakHSAAAAmk'. - 'lEQVR4nI3P2xKCIBAGYGfM6SBWo1nauIqogaDA+z9dK9Lhrv47'. - 'vtl/2A2CfxNlJRRp9IETYGraJeEb7ocLNKznia8A7Db7umWDUG'. - 'sxAzhurxRHxok4KQGqCuEhlL45oU1D2w5BztY4KRhj/bCAsetM'. - '2uObjwvY8/oX50JItYDxSyZSTrO2mNhvGMbaWAevnbFIcpuTr7'. - 't+5AkyfBIKSJHdSQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bs_green.png -//========================================================== - $this->imgdata_small[10][0]= 452 ; - $this->imgdata_small[10][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAn1'. - 'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'. - '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'. - 'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'. - '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'. - 'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'. - 'AIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAw'. - 'kUGgW5vvSDAAAAnklEQVR4nI3QSxKCMAwA0M4gqCgoiiJ+kEAL'. - 'LQUq0PufzX7ENdnlJZNkgtDS2CYZvK6bf+7EoKLA9cH5SQzv6A'. - 'YloTywsAbYr44FrlgrXCMJwHl3xxVtuuFkJAPIcw2tGB9GcFli'. - 'oqEf5GTkSUhVMw2TtD0XSlnDOw3SznE5520vNEi7CwW9+Ayjyq'. - 'U/3+yPuq5gvhkhL0xlGnqL//AFf14UIh4mkEkAAAAASUVORK5C'. - 'YII=' ; - - -//========================================================== -// File: bs_white.png -//========================================================== - $this->imgdata_small[11][0]= 480 ; - $this->imgdata_small[11][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMLFTsY/ewvBQAAAW1JREFUeJytkz2u4jAUhT/jic'. - 'gfBUKiZhE0bIKeVbCWrIKenp6eDiGlCEEEBArIxvzGU4xeZjLk'. - 'jWb05lRXuvbx+exr4bouX1Xjyw7Atz81F4uFBYjjGIDhcCjq1o'. - 'k6nN1uZwFerxfP55Msy1itVmRZBsB4PK6YveHkeW5d18XzPIIg'. - 'wPd9Wq0WnU6HMAxJkoQoiuynOIfDwUopkVIihKAoCgAcx6Hdbm'. - 'OMIU1T5vN55eBKEikljUYDIX6kFUKU9e8aDAZlmjcca+1b7TgO'. - '1+uVy+VS9nzfr8e53++VzdZaiqIgz3OMMWitOZ/PaK0JgqDeRC'. - 'mF53lIKYGfr3O73TDGoJQiTVO01nS73XqT4/FIs9kkCAIej0eZ'. - 'brPZEMcxSZKgtQZgMpmIWpN+vy+m06n1PK9yTx8Gy+WS/X5Pr9'. - 'er9GuHLYoiG4YhSilOpxPr9Zrtdlti/JriU5MPjUYjq7UuEWaz'. - '2d+P/b/qv/zi75oetJcv7QQXAAAAAElFTkSuQmCC' ; - - -//========================================================== -// File: bs_cyan.png -//========================================================== - $this->imgdata_small[12][0]= 633 ; - $this->imgdata_small[12][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABPl'. - 'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'. - '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'. - 'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'. - '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'. - 'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'. - '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'. - '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'. - 'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'. - 'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'. - 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. - 'AHdElNRQfTAwkUGQDi+VPPAAAAtElEQVR4nGNgIBawikipyIiy'. - 'wfksfJpGRkamNtr8LFARPiMFHmFDcztXfwGoFi0jLiZuZRtnry'. - 'BddrCIiJEGL6eklYO7X3iCOFhE2thESdHawdUnJDZFDiyiamZh'. - 'aevk5h0UlZSpBhaRtbN3dPHwDY5MSM+EqBFzc/f0DgiLTkjLzI'. - 'SYw6bjHxgaEZeckZmpD7GLQSAqJj4xNRMIBGFuFtRLA/ENhGBu'. - 'ZmDgkJBXl5fgIDocAAKcINaFePT4AAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bs_bluegreen.png -//========================================================== - $this->imgdata_small[13][0]= 493 ; - $this->imgdata_small[13][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAvV'. - 'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'. - 'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'. - '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'. - 'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'. - '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'. - 'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'. - 'AJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGxNUcXCT'. - 'AAAAqUlEQVR4nI2Q1xKCMBREM2NHLCCogAGCjd6SqLT8/2cZKT'. - '6zb3tm987OBWCsXoejp8rC35fi4+l6gXFZlD0Rz6fZ1tdDmKR9'. - 'RdOmkzmP7DDpilfX3SzvRgQ/Vr1uiZplfsCBiVf03RJd140wgj'. - 'kmNqMtuYXcxyYmNWJdRoYwzpM9qRvGujuCmSR7q7ARY00/MiWk'. - 'sCnjkobNEm1+HknDZgAqR0GKU43+wxdu2hYzbsHU6AAAAABJRU'. - '5ErkJggg==' ; - -//========================================================== -// File: bs_lightred.png -//========================================================== - $this->imgdata_small[14][0]= 532 ; - $this->imgdata_small[14][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAA3l'. - 'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'. - 'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'. - 'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'. - 'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'. - 'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'. - 'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'. - 'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. - 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGjoP2Nm+AAAAr0'. - 'lEQVR4nGNgIBaYiOk62imYwPnMkiIyso76yhJSzFARMxkRNk49'. - 'a3t5OW6oFk1LVkYOfWUHKxUXiEYzLS12DnN3VXkjIRtFsIiSk5'. - '6evqGqhYGKugAfWMRa1FpD2UHeQEXQRlgALCJur+rgbCUNFOAS'. - 'hqjRkZe3MpBTcwEKCEPMMTGSs3Xz8OQHCnBBHckt6OJpIyAMBD'. - 'wwN/MYc4H4LK4wNzMwmGrzcvFqmxIdDgDiHRT6VVQkrAAAAABJ'. - 'RU5ErkJggg==' ; - -//========================================================== -// File: bxs_lightred.png -//========================================================== - $this->imgdata_xsmall[0][0]= 432 ; - $this->imgdata_xsmall[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAA3l'. - 'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'. - 'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'. - 'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'. - 'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'. - 'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'. - 'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'. - 'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. - 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKBOgGhWjAAAAS0'. - 'lEQVR4nGNgQAEmunYmEJaMCKe1vBxYzJKVQ9lKBSSupKdnaKGi'. - 'zgdkiqs6WKnYcIGYJnK2HvzCwmCNgi42wsLCECNMeXlNUY0HAL'. - 'DaB7Du8MiEAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bxs_bluegreen.png -//========================================================== - $this->imgdata_xsmall[1][0]= 397 ; - $this->imgdata_xsmall[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAvV'. - 'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'. - 'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'. - '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'. - 'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'. - '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'. - 'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'. - 'AJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKDVyF5Be'. - 'AAAASUlEQVR4nGNgQAFmYqJcEJaEOJ+UrD5YTJKFTZrfGCQuaq'. - 'glLWvMaQ5kqujo6hnbKIKYXPr68gp2dmCNJiZAlh3ECGsREWtU'. - '4wF1kwdpAHfnSwAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bxs_navy.png -//========================================================== - $this->imgdata_xsmall[2][0]= 353 ; - $this->imgdata_xsmall[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'. - 'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'. - 'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'. - 'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'. - 'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'. - 'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. - 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJxXO4axZAAAAR0'. - 'lEQVR4nGNgQAGskhKsEJaslIi8ijpYTJaDU1FVAyQuKSujoKKh'. - 'LQ5kSigpqWro6oOYrOoaWroGBmCNWiCWAdQwUVFWVOMBOp4GCJ'. - 's5S60AAAAASUVORK5CYII=' ; - -//========================================================== -// File: bxs_gray.png -//========================================================== - $this->imgdata_xsmall[3][0]= 492 ; - $this->imgdata_xsmall[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABI1'. - 'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'. - 'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'. - 'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'. - 'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'. - 'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'. - 'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'. - '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'. - 'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'. - 'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEA'. - 'AAsRAX9kX5EAAAAHdElNRQfTAwkUKC74clmyAAAAQklEQVR4nG'. - 'NgQAVBYVCGt5dXYEQ0mOnp5h4QFgVmeri6+4dHxYMVeHoFRUTH'. - 'gTUFBIZBWAwMkZEx8bFQM2Lj0UwHANc/DV6yq/BiAAAAAElFTk'. - 'SuQmCC' ; - -//========================================================== -// File: bxs_graypurple.png -//========================================================== - $this->imgdata_xsmall[4][0]= 542 ; - $this->imgdata_xsmall[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABSl'. - 'BMVEX////////11P/MqdvKrNfAwMC+u7+9u7+4rr24lsi3rby3'. - 'lMe1rLq1o720q7i0oL20ksSzoryyqbaykMGxlb2wkL+vnbiujb'. - '2sjLuri7qpl7GoirWoibenmK2mla6mjLKmhrSllauki7CjhrCj'. - 'hLGihLChg6+ggq2fkqadkKOcfqqai6Gag6WYe6WXeqSWeaOTd6'. - 'CTd5+Rdp6RdZ6RdZ2Qg5eOc5qMcpiLcZeJb5WIbpOHbZKGbJGE'. - 'a4+CaY2AZ4t/Z4p/Zop/Zol+Zol7ZIZ6Y4V5YoR1ZH11X391Xn'. - '9zXX1yXXtxXHtvWnluWXhsV3VqVnNpVXJoVHFnU3BmUm9jUGth'. - 'VGdgTmheTGZcS2RcSmRaSWJYR19XRl5SQllRQlhQQVdPQFZOP1'. - 'VLPlFJO09IPE5IOk5FOEtEN0lDOEpDOElDNklCNkc/M0XhbrfD'. - 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. - 'EAAAsRAX9kX5EAAAAHdElNRQfTAwkUKCgREfyHAAAATUlEQVR4'. - 'nGNgQAEcIko8EBY3M5Ougy+IxSXMwmTsFsAHZMqrSRvZB0W7A5'. - 'k6FlYugXEZICaPr394Um4uSAFDRFRCbm4uxAihsDAhVOMBHT0L'. - 'hkeRpo8AAAAASUVORK5CYII=' ; - -//========================================================== -// File: bxs_red.png -//========================================================== - $this->imgdata_xsmall[5][0]= 357 ; - $this->imgdata_xsmall[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'. - 'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'. - 'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'. - 'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'. - 'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'. - 'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. - 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIyjy5SVMAAAAS0'. - 'lEQVR4nGNgQAFsUpJsEJastIi8ijpYTJaDU0FVgxXIlJKVUVDR'. - '0BYHMiUUlVQ1dPVBTDZ1dS1dAwOQAgYtbSDLAGIEq6goK6rxAD'. - 'yXBg73lwGUAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: bxs_yellow.png -//========================================================== - $this->imgdata_xsmall[6][0]= 414 ; - $this->imgdata_xsmall[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAzF'. - 'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'. - 'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'. - 'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'. - 'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'. - 'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'. - '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'. - 'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAH'. - 'dElNRQfTAwkUIzoBXFQEAAAAS0lEQVR4nGNgQAFsDhJsEJaTo5'. - '2skj5YzMnSSk7ZwBzIlOSUklPiMxYHMnW4FXT5VNVBTDZeXiNV'. - 'QUGQAgYBYyBLEGIEq5gYK6rxAH4kBmHBaMQQAAAAAElFTkSuQm'. - 'CC' ; - -//========================================================== -// File: bxs_greenblue.png -//========================================================== - $this->imgdata_xsmall[7][0]= 410 ; - $this->imgdata_xsmall[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAxl'. - 'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'. - '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'. - '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'. - 'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'. - 'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'. - 'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'. - 'dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfT'. - 'AwkUJy5/6kV9AAAATUlEQVR4nGNgQAGCyuyCEJaGugKHviVYzF'. - 'hO3sxCWwDIVNLTM9PXtpEGMhW12Cy0DR1ATEFLSxZ7BweQAgYd'. - 'HUMHBweIEQKiogKoxgMAo/4H5AfSehsAAAAASUVORK5CYII=' ; - -//========================================================== -// File: bxs_purple.png -//========================================================== - $this->imgdata_xsmall[8][0]= 364 ; - $this->imgdata_xsmall[8][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAnF'. - 'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'. - 'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'. - 'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'. - 'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'. - 'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. - 'HUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIj'. - 'mBTjT/AAAASUlEQVR4nGNgQAGskhKsEJaCrJiSuhZYTEFASFlD'. - 'GyQuqSCnrK6tJwpkiquoamgbGIGYrFpaugbGxmCNunpAljHECB'. - 'ZBQRZU4wFSMAZsXeM71AAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bxs_green.png -//========================================================== - $this->imgdata_xsmall[9][0]= 370 ; - $this->imgdata_xsmall[9][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAn1'. - 'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'. - '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'. - 'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'. - '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'. - 'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'. - 'AIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAw'. - 'kUKBrZxq0HAAAATElEQVR4nGNgQAGccrIcEJaivISyhjaIxa7I'. - 'I6CiqcMKZMopKqho6OhLA5kyqmqaOobGICartraeoYkJSAGDnj'. - '6QZQIxgk1Skg3VeABlVgbItqEBUwAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bxs_darkgreen.png -//========================================================== - $this->imgdata_xsmall[10][0]= 563 ; - $this->imgdata_xsmall[10][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABX1'. - 'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'. - 'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'. - 'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'. - 'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'. - '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'. - 'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'. - 'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'. - 'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'. - 'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'. - 'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'. - 'RQfTAwkUKCFozUQjAAAATUlEQVR4nGNgQAGcoqrcEJYQB5OhSw'. - 'CIxSXGwWThGcIDZCppK5o7hyV6AZl6NnbuoSmFICZ3YHB0RkkJ'. - 'SAFDbEJaSUkJxAjeyEheVOMBQj4MOEkWew4AAAAASUVORK5CYI'. - 'I=' ; - -//========================================================== -// File: bxs_cyan.png -//========================================================== - $this->imgdata_xsmall[11][0]= 530 ; - $this->imgdata_xsmall[11][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABPl'. - 'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'. - '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'. - 'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'. - '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'. - 'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'. - '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'. - '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'. - 'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'. - 'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'. - 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAA'. - 'AHdElNRQfTAwkUKQFKuFWqAAAATUlEQVR4nGNgQAGsUjJsEJaR'. - 'grC5qz9YzIiL28YriB3IlDZRsnYNiZUDMmXtHT2CE9JBTDb/wI'. - 'jkzEyQAoaomMTMzEyIERzy8hyoxgMAN2MLVPW0f4gAAAAASUVO'. - 'RK5CYII=' ; - -//========================================================== -// File: bxs_orange.png -//========================================================== - $this->imgdata_xsmall[12][0]= 572 ; - $this->imgdata_xsmall[12][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABaF'. - 'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'. - 'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'. - 'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'. - 'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'. - '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'. - 'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'. - 'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'. - 'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'. - 'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'. - 'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'. - 'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9k'. - 'X5EAAAAHdElNRQfTAwkUJBSSy88MAAAATUlEQVR4nGNgQAGqwo'. - 'paEBYPJ4eKezCIpc7HwmrqG6ENZMpLihm6RaWEAZl6Vo7ekRnF'. - 'IKZWSHhcTnk5SAFDfFJWeXk5xAjj1FRjVOMBeFwNcWYSLjsAAA'. - 'AASUVORK5CYII=' ; - -//========================================================== -// File: bxs_lightblue.png -//========================================================== - $this->imgdata_xsmall[13][0]= 554 ; - $this->imgdata_xsmall[13][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABVl'. - 'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'. - 'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'. - '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'. - 'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'. - 'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'. - 'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'. - 'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'. - 'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'. - 'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'. - 'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. - 'gAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJziL'. - 'PvAsAAAATUlEQVR4nGNgQAHsQgqcEJYgG5Oegy+IxSHOxmTiFs'. - 'gFZMprKBnbB8e7AplaFlbOQUl5ICanX0BEWmEhSAFDVGxKYWEh'. - 'xAjusDBuVOMBJO8LrFHRAykAAAAASUVORK5CYII=' ; - -//========================================================== -// File: bxs_darkgray.png -//========================================================== - $this->imgdata_xsmall[14][0]= 574 ; - $this->imgdata_xsmall[14][1]= - 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABm'. - 'JLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAB'. - 'iElEQVR42k3QPU8TYRwA8P//ebkXrgdIColXRAOEkJqbaExMut'. - 'DBhE1GNjYHPg+DG6ODiU6QOLjVxITBcFKBYCstlAC2Bz17fe76'. - 'vLD6+wg/1FpTRFR5lpaub/u1eGBGaAT4HneD4OlXx7avtDYUjT'. - 'HQabd2Ti8e3vVSKzxrtHS32wIpFVldno22Nqvvg2Bhl0gp/aNm'. - 'vJ3qqXAtLIva+ks1H0wqlSXi4+d6+OFTfRsAfHJx2d1od24rZP'. - 'xP2HzopINr1mkesX7ccojqif0v9crxWXODZTno3+dNGA7uWLsd'. - 'mUYU4fHJCViMG9umLBmM4L6fagZGg9QKfjZ+Qfy3C3G/B3mugF'. - 'IHHNcDf64E3KJALApk2p8CSolUUqLjFkyxOGMsTtFyJ+Wz57NQ'. - '8DghS4sLB0svioeZZo7nPhFoUKZDIVFbglkTTnl5/rC8snjAkJ'. - 'Bk/XV5LxHC/v7tR8jzTFPbg8LENK9WX0Vv31T2AEmCSmlKCCoh'. - 'ROnP1U1tPFYjJBRcbtzSf+GPsFTAQBq1n4AAAABKdEVYdHNpZ2'. - '5hdHVyZQBiYzYyMDIyNjgwYThjODMyMmUxNjk0NWUzZjljOGFh'. - 'N2VmZWFhMjA4OTE2ZjkwOTdhZWE1MzYyMjk0MWRkM2I5EqaPDA'. - 'AAAABJRU5ErkJggg==' ; - } -} - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/imgdata_balls.inc.php b/web/public_php/admin/jpgraph/imgdata_balls.inc.php new file mode 100644 index 000000000..ee5db4927 --- /dev/null +++ b/web/public_php/admin/jpgraph/imgdata_balls.inc.php @@ -0,0 +1,1061 @@ + 'imgdata_large', + MARK_IMG_MBALL => 'imgdata_small', + MARK_IMG_SBALL => 'imgdata_xsmall', + MARK_IMG_BALL => 'imgdata_xsmall'); + protected $colors,$index,$maxidx; + private $colors_1 = array('blue','lightblue','brown','darkgreen', + 'green','purple','red','gray','yellow','silver','gray'); + private $index_1 = array('blue'=>9,'lightblue'=>1,'brown'=>6,'darkgreen'=>7, + 'green'=>8,'purple'=>4,'red'=>0,'gray'=>5,'silver'=>3,'yellow'=>2); + private $maxidx_1 = 9 ; + + private $colors_2 = array('blue','bluegreen','brown','cyan', + 'darkgray','greengray','gray','green', + 'greenblue','lightblue','lightred', + 'purple','red','white','yellow'); + + + private $index_2 = array('blue'=>9,'bluegreen'=>13,'brown'=>8,'cyan'=>12, + 'darkgray'=>5,'greengray'=>6,'gray'=>2,'green'=>10, + 'greenblue'=>3,'lightblue'=>1,'lightred'=>14, + 'purple'=>7,'red'=>0,'white'=>11,'yellow'=>4); + + private $maxidx_2 = 14 ; + + + private $colors_3 = array('bluegreen','cyan','darkgray','greengray', + 'gray','graypurple','green','greenblue','lightblue', + 'lightred','navy','orange','purple','red','yellow'); + + private $index_3 = array('bluegreen'=>1,'cyan'=>11,'darkgray'=>14,'greengray'=>10, + 'gray'=>3,'graypurple'=>4,'green'=>9,'greenblue'=>7, + 'lightblue'=>13,'lightred'=>0,'navy'=>2,'orange'=>12, + 'purple'=>8,'red'=>5,'yellow'=>6); + private $maxidx_3 = 14 ; + + protected $imgdata_large, $imgdata_small, $imgdata_xsmall ; + + + function GetImg($aMark,$aIdx) { + switch( $aMark ) { + case MARK_IMG_SBALL: + case MARK_IMG_BALL: + $this->colors = $this->colors_3; + $this->index = $this->index_3 ; + $this->maxidx = $this->maxidx_3 ; + break; + case MARK_IMG_MBALL: + $this->colors = $this->colors_2; + $this->index = $this->index_2 ; + $this->maxidx = $this->maxidx_2 ; + break; + default: + $this->colors = $this->colors_1; + $this->index = $this->index_1 ; + $this->maxidx = $this->maxidx_1 ; + break; + } + return parent::GetImg($aMark,$aIdx); + } + + function __construct() { + + //========================================================== + // File: bl_red.png + //========================================================== + $this->imgdata_large[0][0]= 1072 ; + $this->imgdata_large[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAByF'. + 'BMVEX/////////xsb/vb3/lIz/hIT/e3v/c3P/c2v/a2v/Y2P/'. + 'UlL/Skr/SkL/Qjn/MTH/MSn/KSn/ISH/IRj/GBj/GBD/EBD/EA'. + 'j/CAj/CAD/AAD3QkL3MTH3KSn3KSH3GBj3EBD3CAj3AAD1zMzv'. + 'QkLvISHvIRjvGBjvEBDvEAjvAADnUlLnSkrnMTnnKSnnIRjnGB'. + 'DnEBDnCAjnAADec3PeSkreISHeGBjeGBDeEAjWhITWa2vWUlLW'. + 'SkrWISnWGBjWEBDWEAjWCAjWAADOnp7Oa2vOGCHOGBjOGBDOEB'. + 'DOCAjOAADJrq7Gt7fGGBjGEBDGCAjGAADEpKS/v7+9QkK9GBC9'. + 'EBC9CAi9AAC1e3u1a2u1Skq1KSm1EBC1CAi1AACtEBCtCBCtCA'. + 'itAACngYGlCAilAACghIScOTmcCAicAACYgYGUGAiUCAiUAAiU'. + 'AACMKSmMEACMAACEa2uEGAiEAAB7GBh7CAB7AABzOTlzGBBzCA'. + 'BzAABrSkprOTlrGBhrAABjOTljAABaQkJaOTlaCABaAABSKSlS'. + 'GBhSAABKKSlKGBhKAABCGBhCCABCAAA5CAA5AAAxCAAxAAApCA'. + 'ApAAAhAAAYAACc9eRyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. + 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFD'. + 'UHLytKAAAB4UlEQVR4nGNgIAK4mGjrmNq6BmFIWMmISUpKSmk5'. + 'B8ZEokj4qoiLiQCBgqald3xaBpKMj6y4sLCQkJCIvIaFV0RaUR'. + 'lCSk5cWEiAn19ASN7QwisuraihHiajKyEixM/NwckjoKrvEACU'. + 'qumpg7pAUlREiJdNmZmLT9/cMzwps7Smc3I2WEpGUkxYkJuFiY'. + 'lTxszePzY1v7Shc2oX2D+K4iLCgjzsrOw8embuYUmZeTVtPVOn'. + 'gqSslYAOF+Ln4ZHWtXMPTcjMrWno7J82rRgoZWOsqaCgrqaqqm'. + 'fn5peQmlsK1DR52vRaoFSIs5GRoYG5ub27n19CYm5pdVPnxKnT'. + 'pjWDpLydnZwcHTz8QxMSEnJLgDL9U6dNnQ6Sio4PDAgICA+PTU'. + 'zNzSkph8hADIxKS46Pj0tKTc3MLSksqWrtmQySAjuDIT8rKy0r'. + 'Kz+vtLSmur6jb9JUIJgGdjxDQUVRUVFpaUVNQ1NrZ9+kKVOmTZ'. + 'k6vR0sldJUAwQNTU2dnX0TgOJTQLrSIYFY2dPW1NbW2TNxwtQp'. + 'U6ZMmjJt2rRGWNB3TO7vnzh5MsgSoB6gy7sREdY7bRrQEDAGOb'. + 'wXOQW0TJsOEpwClmxBTTbZ7UDVIPkp7dkYaYqhuLa5trYYUxwL'. + 'AADzm6uekAAcXAAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bl_bluegreen.png + //========================================================== + $this->imgdata_large[1][0]= 1368 ; + $this->imgdata_large[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMMFi8hE9b2uAAABOVJREFUeNq9lk2sJFUVx3+3qv'. + 'tW95t57zFvhiFxmCFRUJRoNCQiJARMhiFx/Igxii5goTG6ZDAu'. + '/EhcSCIrTAgLEiKsJ8ywABNZEMJXEDYCukAmjgjzBkK/j35V1d'. + '333FtV97io97pfzwxfG86qcu/N+Z3zP+fcW/Apmfk4hx57+R/6'. + 'Rqmc9ykhsWjlsUngAA1fXIQ7b73pI/186IGHnn9dH/8frC8v4I'. + 'PiG53uaerR4GmKkv31mB8cyfjd946ZTwR66qVX9OTWIi8UKUv9'. + 'BOrZXpYZvFeiBvzI0fgSUSFKwbVG+Pl1V3HH0VvNR4KeeukV/f'. + 'PmMmdHhst76aXD64AbeVQ9bjNHaiGOC2o3wLrAb2/4LL/84ffn'. + 'fCdzkOdayKpLppBemrBsU5Y1Zdmm9LJdGU6E/t4M24Q26jRDRL'. + 'j3mdc49cSTekFsMzs5XuTsyLDUNSDQ25NwKOly9YIl22MYhJr/'. + 'uoDtBBoT0CxBRGYOAhibIaOCe//2MpfM6KHnX9cXipSlbkKWmS'. + 'nk9iv38J0jixw7vJfrTMYBOvhSoQHJBS09ANELloAGDxW8tfoW'. + 'J+5/UC8CPS0LU7r3SpYarr7M8rmFjMPLXT6/33L4si7Z2GCrQC'. + '+0ctlOaNs9DReV8vSLr85ndPLpZ/WNvHW+01kAVFBOGvJx0wYg'. + 'Sp47RIQ4Emwa8FGJXlDxSCFo5YlVgAo2hwPue/hRndboTV3EW2'. + 'Wp3k6wBp8q56QiWzecW6vwQfnPRkAWhFgILnq08jQ+R2nlUzzN'. + 'uES9Q7Vd+9fba7NmWJW61db2247qACmcjxXr45psYphsFGSLBu'. + 'kIajxqtjNwHkvAjQt0sg3crhPA2+fPz0CuyNFOghsGsr19mnFg'. + 'DGwrRm8UoAtNmQPQtRXDgdC4HImCFEKcCE0oieUWUYq2LtbiGp'. + 'mBQmppfIkjw45DK0QNNkvQ0jMBtPL0UnDRM1rN+cxKwzvOo2NP'. + 'tykR9a1kfpZNDLMG6QDYJqCTBvUe1+uxs+YKyPoGrTwY2HhvC4'. + 'CDWQd5d4xNApNQEEMgjgLdUCLBQ5cprL/trwNwKG2IUmDqDFd5'. + 'sr5BWrlxuSdLDFEFlqAzXGc4zFjupqh6uqYihpxJcEgp026l2w'. + '7wFUv7Z6AvrfRo/n0OYzPwIKE3HUKAJg2otMBiElnsF7wngis9'. + '3ZDjNnLi7huCWUZfueZKTu/M0V3HvmkOFDVxVKDG04ScejSgW5'. + 'V0q5JYFEghuDLHlTmToqDeGOCKIVtrW9hsdmXufEcNLPSXuPHa'. + 'a+bvuh9df5AH/v5PDFmbWQC3Mx+TVvfGVTRB2CodNgT2JBX003'. + 'aANZAYS/BxCv32TV/l2C03G7jgmfjGiT/qmeEmibEYm7XzAO2k'. + 'A+pbgHhBgydqu54YO5eRiLCy7yDvPP6Xqf+5Z+Lu277OYuOpiw'. + 'H15oBmlNOMcmK5RbP+PrEscGU+DSAxdg4CICIkxnLP8aNz63Og'. + 'H3/rdvOb795GVhuaYo0oBc3GGrEsUPVTwO6a7LYd+X51x3Hu/t'. + 'lP5tS65FN+6okn9U+n/sqb596dTvhOF+02myXTmkQNrOw7yD3H'. + 'j14E+UDQjp24/0E9/eKrbA4HH3aMK1b2ccvXvswjv//1J/s5ud'. + 'Due/hRPfP+OmfOrk7vrn7a48ihA3zh8CH+8Iuffiw/n4r9H1ZZ'. + '0zz7G56hAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bl_yellow.png + //========================================================== + $this->imgdata_large[2][0]= 1101 ; + $this->imgdata_large[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'. + 'BMVEX//////////+///+f//9b//8b//73//7X//63//6X//5T/'. + '/4z//4T//3P//2v//1r//0r//0L//zH//yn//yH//xj//xD//w'. + 'j//wD/90L/9zn/9zH/9xj/9xD/9wj/9wD39yn37zn37zH37yH3'. + '7xD37wj37wDv70Lv50rv50Lv5znv5yHv5xjv5wjv5wDn51Ln5x'. + 'Dn3jHn3iHn3hjn3hDn3gje3oze3nPe3lLe1oze1nPe1lLe1ine'. + '1iHe1hje1hDe1gje1gDW1qXW1mvWzqXWzkLWzhjWzhDWzgjWzg'. + 'DOzrXOzq3OzpzOzgDOxkrOxinOxhjOxhDOxgjOxgDGxqXGxnvG'. + 'xmvGvRjGvRDGvQjGvQDFxbnAvr6/v7+9vaW9vZS9vQi9vQC9tR'. + 'C9tQi9tQC7u7W1tZS1tXu1tTG1tQi1rRC1rQi1rQCtrYytrSGt'. + 'rQitrQCtpYStpSGtpQitpQClpYSlpXulpQClnBClnAilnACcnG'. + 'ucnAicnACclAiclACUlFqUlCmUlAiUlACUjFKUjAiUjACMjFKM'. + 'jEqMjACMhACEhACEewB7ezF7exB7ewB7cwBzcylzcwBzaxBzaw'. + 'BraxhrawhrawBrYxBrYwBjYwBjWgBaWgBaUgCXBwRMAAAAAXRS'. + 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. + 'LdfvwAAAAHdElNRQfTAwkRFBKiJZ4hAAAB7ElEQVR4nI3S+1vS'. + 'UBgHcB67WJmIMWAVdDHEDLBC6Go0slj3Ft0m9RRBWQEmFZFDEM'. + 'Qgt0EMFBY7p/+198hj1kM/9N1+++x73rOd6XT/kStnTx4fPzd9'. + 'uwfOjFhomj7smAhwj/6Cm2O0xUwy6g7cCL99uCW3jtBmE7lsdr'. + 'fvejgpzP7uEDFRRoqy2k8xQPnypo2BUMP6waF9Vpf3ciiSzErL'. + 'XTkPc0zDe3bsHDAcc00yoVgqL3UWN2iENpspff+2vn6D0+NnZ9'. + '6lC5K6RuSqBTZn1O/a3rd7v/MSez+WyIpVFX8GuuCA9SjD4N6B'. + 'oRNTfo5PCAVR0fBXoIuOQzab1XjwwNHx00GOj8/nKtV1DdeArk'. + '24R+0ul9PjmbrHPYl+EipyU0OoQSjg8/m83kl/MMhx0fjCkqio'. + 'SMOE7t4JMAzDsizH81AqSdW2hroLPg4/CEF4PhKNx98vlevrbY'. + 'QQXgV6kXwVfjkTiSXmhYVcSa7DIE1DOENe7GM6lUym0l+EXKks'. + 'K20VAeH2M0JvVgrZfL5Qqkiy0lRVaMBd7H7EZUmsiJJcrTdVja'. + 'wGpdbTLj3/3qwrUOjAfGgg4LnNA5tdQx14Hm00QFBm65hfNzAm'. + '+yIFhFtzuj+z2MI/MQn6Uez5pz4Ua41G7VumB/6RX4zMr1TKBr'. + 'SXAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bl_silver.png + //========================================================== + $this->imgdata_large[3][0]= 1481 ; + $this->imgdata_large[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAADAF'. + 'BMVEUAAADOzs7Gxsa9vb21tbXOxsbOzsbGzsb3///O1ta1vb2c'. + 'paVSWlpKWlpSY2ve5+97hIze7/9aY2vO5/9zhJRaa3tSY3PGzt'. + 'aMlJxrc3tja3NKUlpCSlK1vcZze4RSWmPW5/+Upb3G3v9zhJxS'. + 'Y3t7jKVaa4TO3veltc6ElK1re5Rjc4ycpbV7hJRaY3M5QlLn7/'. + '/Gzt6lrb2EjJzO3v9ja3vG1ve9zu+1xueltdacrc6UpcaMnL1C'. + 'SlqElLV7jK1zhKVre5zW3u/O1ue1vc6ttcaMlKVze4xrc4RSWm'. + 'tKUmPG1v+9zve1xu+tveeltd6crdbe5/+9xt6cpb17hJxaY3s5'. + 'QlrW3vfO1u/Gzue1vdattc6lrcaUnLWMlK2EjKVze5Rrc4xja4'. + 'RSWnNKUmtCSmO9xuecpcZ7hKVaY4TW3v/O1vfGzu+1vd6ttdal'. + 'rc69xu+UnL2MlLWEjK1ze5xrc5R7hK1ja4zO1v+1veettd6lrd'. + 'aMlL3Gzv/39//W1t7Gxs61tb29vcatrbWlpa2cnKWUlJyEhIx7'. + 'e4TW1ufGxta1tcZSUlqcnK3W1u+UlKW9vda1tc57e4ytrcalpb'. + '1ra3vOzu9jY3OUlK29vd6MjKWEhJxaWmtSUmNzc4xKSlpjY3tK'. + 'SmNCQlqUjJzOxs7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. + 'AAAAAAAAAAAAAAAAAAAAAAAAD///9fnkWVAAAAAnRSTlP/AOW3'. + 'MEoAAAABYktHRP+lB/LFAAAACXBIWXMAAABFAAAARQBP+QatAA'. + 'AB/klEQVR42mNgxAsYqCdd3+lcb4hLmj8wMMvEu8DCMqYbU9op'. + 'UEFB2MTb26eyysomFl06XEEhUCHLpAKo2z/fujikEUVaXUFBMB'. + 'BouLePuV+VVWGRciIXknSEsImCQd3//xwmPr65llaFcSFJHkjS'. + '3iYmWUDZ//8NfCr989NjNUMSUyTg0jneSiaCINn/gmlVQM12qg'. + 'lJnp5waTMTE5NAkCyHWZW/lXWNfUlikmdYK0zax7siS4EDKJtd'. + 'mQeU1XRwLBdLkRGASucWmGVnZ4dnhZvn5lmm29iVOWpnJqcuko'. + 'JKR1Wm5eTkRKYF5eblp9sU2ZeUJiV7zbfVg0pH56UFBQXNjIqK'. + 'jgkujItX1koKTVmYajsdKu2qETVhwgSXiUDZ2Bn9xqUeoZ5e0t'. + 'LzYYZ3B092ndjtOnmKTmycW1s7SHa+l5dtB8zlccE6RlN0dGbM'. + 'mDVbd5KupNBcL6+F82XgHouLj5vRP2PWLGNdd4+ppnxe8tJec6'. + 'XnNsKkm0uVQ5RDRHQTPTym68nPlZbvkfYCexsa5rpJ2qXa5Umm'. + 'ocmec3m8vHjmSs+fgxyhC5JDQ8WSPT2lvbzm8vDIe0nbtiBLN8'. + '8BigNdu1B6Lsje+fPbUFMLi5TMfGmvHi/puUAv23q2YCTFNqH5'. + 'MvPnSwPh3HasCbm3XUpv+nS5VtrkEkwAANSTpGHdye9PAAAASn'. + 'RFWHRzaWduYXR1cmUANGJkODkyYmE4MWZhNTk4MTIyNDJjNjUx'. + 'NzZhY2UxMDAzOGFhZjdhZWIyNzliNTM2ZGFmZDlkM2RiNDU3Zm'. + 'NlNT9CliMAAAAASUVORK5CYII=' ; + + //========================================================== + // File: bl_purple.png + //========================================================== + $this->imgdata_large[4][0]= 1149 ; + $this->imgdata_large[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACAV'. + 'BMVEX/////////7///5///1v//xv//rf//pf//lP//jP//hP//'. + 'c///a///Wv//Wvf/Uv//Sv//Qv//Qvf/Off/Mf//Kf//If//If'. + 'f/GP//GPf/EP//EPf/CP//CPf/CO//AP//APf3Oe/3Kff3Ke/3'. + 'Ie/3GO/3EO/3AO/vSu/vSufvOefvMefvIefvGOfvEOfvCOfvAO'. + 'fnUufnSufnMd7nId7nGN7nGNbnEN7nCN7nAN7ejN7ejNbec97e'. + 'c9beUtbeQtbeIdbeGNbeENbeCNbeANbWpdbWa9bWQs7WGM7WEM'. + '7WCM7WAM7Otc7Orc7OnM7OSsbOIb3OGMbOEMbOCMbOAM7OAMbG'. + 'pcbGnMbGe8bGa8bGKbXGEL3GCL3GAL3FucXBu73AvsC/v7+9pb'. + '29Ka29GLW9ELW9CLW9AL29ALW5rrm1lLW1e7W1MbW1GKW1EK21'. + 'CLW1CK21AK2tjK2thKWtMaWtIaWtGJytCK2tCKWtAK2tAKWlhK'. + 'Wle6WlEJylCJylAKWlAJyca5ycGJScEJScCJScAJycAJSUWpSU'. + 'UoyUKZSUEIyUCIyUAJSUAIyMUoyMSoyMIYSMEISMCISMAIyMAI'. + 'SECHuEAISEAHt7MXt7EHt7CHt7AHt7AHNzKXNzEGtzAHNzAGtr'. + 'GGtrEGNrCGtrAGtrAGNjCFpjAGNjAFpaAFpaAFIpZn4bAAAAAX'. + 'RSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsS'. + 'AdLdfvwAAAAHdElNRQfTAwkRFB0ymoOwAAAB9UlEQVR4nGNgIA'. + 'K42hhqGtm5+WFIWClKycvLK6gbuARGoEj4aMjLSElISUir6Tt7'. + 'x+aEIWR8leQlwEBSTc/CK7awLguuR0lGQkJMVFRUTFJVzwko1d'. + 'oFk9OQl5IQE+Dh5hVR0TV3CkkvbJgyASJjDZIR5GBl5eRX0TH1'. + 'DEqrbJ2ypBEspSgvJSXKw8bMxMavbOLoGZNf1TZlybw4oIyfLN'. + 'BxotxsLEzsQiaOHkFpBQ2905esrAZK2SpIAaUEuDm5+LTNPAKj'. + 'C+pbps1evrIDKGWnLictKSkuLKyoZQyUya9o7Z2+YMXKGUApew'. + 'M9PTVdXR0TEwf3wOjUirruafOXL18xFyjl72Kpb25qaurg4REU'. + 'EFVe2zJ5zpLlK1aCpbydnZ2dnDwDA6NTopLLeiZNXbB8BcTAyP'. + 'TQ0JDg4KCY1NS83JKmiVOBepYvX9UPlAovzEiPSU/LLyior2vq'. + 'mjZr3vLlIF01IC+XVhUWFlZW1Lc290ycOGfxohVATSsXx4Oksn'. + 'vaWlsb2tq6J0+bM2/RohVA81asbIcEYueU3t7JU6ZNnwNyGkhm'. + '+cp5CRCppJnzZ8+ZM3/JUogECBbBIixr8Yqly8FCy8F6ltUgoj'. + 'lz7sqVK2ByK+cVMSCDxoUrwWDVysXt8WhJKqG4Y8bcuTP6qrGk'. + 'QwwAABiMu7T4HMi4AAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bl_gray.png + //========================================================== + $this->imgdata_large[5][0]= 905 ; + $this->imgdata_large[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAABO1'. + 'BMVEX////////3///39/fv7+/e5+fW3t7Wzs7WxsbG1tbGzsbG'. + 'xsbDxMS/v7++wMC+v7+9zsa9xsa9vb29tbW9ra29pa24uLi1xs'. + 'a1vb21tbWxtrattbWmpqalra2cra2cpaWcnJycjIyUpaWUnJyU'. + 'lJSUjIyMnJyMnJSMlJSMlIyMjJSMjIyElJSElIyEjIyEhIR7jI'. + 'x7hIR7hHt7e3t7e3N7e2tzhIRze3tze3Nzc3Nre3trc3Nrc2tr'. + 'a2tjc3Njc2tja3Nja2tjY2NjWlpaa2taY2taY2NaY1paWlpaUl'. + 'JSY2NSY1pSWlpSWlJSUlJSUkpKWlpKWlJKUlpKUlJKUkpKSkpK'. + 'SkJCUlJCUkJCSkpCSkJCQkI5Sko5QkI5Qjk5OUI5OTkxQkIxOT'. + 'kxMTkxMTEpMTEhMTEhKSkYISEpy7AFAAAAAXRSTlMAQObYZgAA'. + 'AAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdE'. + 'lNRQfTAwkRFQfW40uLAAABx0lEQVR4nI3SbXfSMBQA4NV3nce5'. + 'TecAHUywRMHSgFuBCFsQUqwBS1OsWQh0GTj//y8wZUzdwQ/efM'. + 'tzcm/uuXdj4z9ic/PR9k4qk1qDnf0X2/uZzKt8GaRvSubg4LVp'. + 'mkWzCGAT/i3Zsm2XNQHLsm2n2937LaaNnGoJFAEo27B50qN0ay'. + 'Wg26lXsw8fP8nmzcJb2CbsnF5JmmCE8ncN404KvLfsYwd7/MdV'. + 'Pdgl/VbKMIzbuwVgVZw2JlSKJTVJ3609vWUY957lgAUd1KNcqr'. + 'yWnOcOPn8q7d5/8PywAqsOOiVDrn42NFk+HQ7dVuXNYeFdBTpN'. + 'nY5JdZl8xI5Y+HXYaTVqEDp1hAnRohZM03EUjMdhn5wghOoNnD'. + 'wSK7KiiDPqEtz+iD4ctdyAifNYzUnScBSxwPd6GLfRURW7Ay5i'. + 'pS5bmrY8348C5vvUI+TLiIVSJrVA0heK/GDkJxYMRoyfCSmk4s'. + 'uWc3yic/oBo4yF374LGQs5Xw0GyQljI8bYmEsxVUoKxa6HMpAT'. + 'vgyhU2mR8uU1pXmsa8ezqb6U4mwWF/5MeY8uLtQ0nmmQ8UWYvb'. + 'EcJaYWar7QhztrO5Wr4Q4hDbAG/4hfTAF2iCiWrCEAAAAASUVO'. + 'RK5CYII=' ; + + //========================================================== + // File: bl_brown.png + //========================================================== + $this->imgdata_large[6][0]= 1053 ; + $this->imgdata_large[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAABoV'. + 'BMVEX////Gzs7GvbXGrZTGpXu9nHO1nHO1nIy9taXGxs7GtaXO'. + 'nHPGlFrGjEq9hEq1hEqte0Klczmcazmce1KtnIzGxsbGvb3OlF'. + 'LOlFq9hFKte0qcc0KUYzGEWimMc1K9ta3OnGvOnGPWnGO9jFq9'. + 'jFKlc0KUazmMYzl7UilzUjGtpZzGxr3GnGPWpWvepXO1hFJ7Wj'. + 'FrSiFjUjG1ra3GnHPvxpT/5733zpythFKUa0KEYzlzUilaOSF7'. + 'Wjm9jErvvYz/99b///f/78bnrYS1hFqle0p7UjFrSiljQiFCMR'. + 'iMhHO9lGvGjFLWnGv/3q3////erXuthEqlc0paQiFKMRhSQin/'. + '1qX/997//++cc0pjSilaQilKORhCKRiclIy9pYzGlGPntYT33q'. + '3vvZSEWjlSOSE5KRB7c2O1lHutczmthFqte1JrWkqtjGtCKRBa'. + 'SjmljGuca0KMYzGMaznOztaclISUYzmEWjFKOSF7a1qEYzFaSi'. + 'GUjISEa0pKOSm9vb2llIxaQhg5IQiEc2tzY0paORilnJy1raVS'. + 'OSljUkJjWkKTpvQWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. + 'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkREiei'. + 'zP2EAAAB9UlEQVR4nGWS/VfSUBjHL5QluhhBxtwyWcCus5Blpm'. + 'wDC4ONaWXCyBi7RMZmpQ2Bypm9W/byV3cHHo/W88s95/s5z/d5'. + 'uwCcCh/4L3zAf+bs0NC588On9QAYGSUuBINk6GI4cmnsBLk8Go'. + '1SFEGMkzRzZeLq5JE8FvDHouw1lqXiCZJOcnCKnx4AcP0GBqmZ'. + 'mRgRT9MMB4Wbs7cGSXNRik3dnp9fiMUzNCNKgpzN9bsaWaQo9s'. + '7dfH7pXiFTZCBU1JK27LmtBO8TDx7mV1eXHqXXyiIUFLWiVzHx'. + 'BxcJIvV4/cn6wkqmWOOwmVE3UQOAp6HxRKL5bGPj+VwhUhalFq'. + '8alm5vAt+LlySZTsebzcKrraIIW4JqZC3N3ga+1+EQTZKZta1M'. + 'pCZCSeDViqVrThsEdsLJZLJYLpZrHVGScrKBvTQNtQHY6XIM02'. + 'E6Ik7odRW1Dzy3N28n3kGuB3tQagm7UMBFXI/sATAs7L5vdbEs'. + '8Lycm923NB0j5wMe6KOsKIIyxcuqauxbrmlqyEWfPmPy5assY1'. + 'U1SvWKZWom9nK/HfQ3+v2HYZSMStayTNN0PYKqg11P1nWsWq7u'. + '4gJeY8g9PLrddNXRdW8Iryv86I3ja/9s26gvukhDdvUQnIjlKr'. + 'IdZCNH+3Xw779qbG63f//ZOzb6C4+ofdbzERrSAAAAAElFTkSu'. + 'QmCC' ; + + //========================================================== + // File: bl_darkgreen.png + //========================================================== + $this->imgdata_large[7][0]= 1113 ; + $this->imgdata_large[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'. + 'BMVEX////////3///v///n/+/e99bW/+/W99bO786/v7++vr69'. + '/96999a7wb24vbu1/9a1zqW1u7itxrWosq6l772l1qWlxrWlxq'. + '2lva2cxpSU562U3q2UxqWUvaWUpZyM77WM57WMvYyMtZyMrZyM'. + 'pZSMnJSEvZyEtYyErZSElIx7zpR7xpx7xpR7vZR7jIRz1pRzxp'. + 'RzjIRrzpRrzoxrxoxrtYRrrYxrrXtrpYRrhHNjzoxjxoxjxoRj'. + 'vYRjtYRjrXtjpXtjlGNje2tazoxazoRaxoxaxoRavYRatYRatX'. + 'tarXtapXNanHNajFpae2tSzoRSxoRSvXtStXtSrXtSrXNSpXNS'. + 'nHNSnGtSlGtSlGNSjGtSjGNKvXtKtXNKrXNKpWtKnGtKlGNKjG'. + 'NKhGNKhFJKc1pKa1JCrWtCpWtCnGtClGNCjGNCjFpChFpCe1JC'. + 'a1JCY1I5pWs5nGM5lGM5jFo5hFo5e1o5c0o5WkoxjFoxhFoxhF'. + 'Ixe1Ixc1Ixc0oxa0ophFIpe0opc0opa0opa0IpY0IpWkIpWjkp'. + 'UkIpUjkhc0oha0IhY0IhWjkhWjEhUjkhUjEhSjEhSikhQjEhQi'. + 'kYWjkYSjEYSikYQjEYQikQSikQQikQQiEQOSExf8saAAAAAXRS'. + 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. + 'LdfvwAAAAHdElNRQfTAwkRFCaDkWqUAAAB+ElEQVR4nI3S+1vS'. + 'UBgHcGZlPV0ks/vFrmQWFimJjiwiYUJWjFBWFhClyZCy5hLrwA'. + 'x2EIwJC1w7zf2vnU0re+iHvs9++7x7zznvORbLf+TA6ct9fYMX'. + 'jrfAUYefpp+/iM1ykxf/lmuhUZ/PTwXC8dml5Wcd23o5H5Mk6b'. + '5NUU8icXbhS67rNzn9JDnguOEYGQtEEtwC+Crs3RJ76P5A/znr'. + 'vsNX7wQnEiwHCtK7TTkW8rvdZ9uJtvZTLkxpHhSrP66bNEj7/P'. + '3WNoLYeeSWQQCIpe9lQw7RNEU5rDsIYtcJ14Nocg7kRUlBNkxn'. + 'YmGKcp7cv3vPwR7XOJPmc0VYU3Sv0e9NOBAYG7Hbz/cMjTMveZ'. + 'CHkqxuTBv0PhYJB4N3XR6PJ5rMAPMnpGUxDX1IxSeMTEaZp1OZ'. + 'nGAIQiYtsalUIhFlmGTy3sO3AizJCKn6DKYryxzHsWyaneMzr6'. + 'cWxRVZVlFTe4SpE3zm+U/4+whyiwJcWVMQNr3XONirVWAklxcE'. + 'EdbqchPhjhVzGpeqhUKhWBQhLElr9fo3pDaQPrw5xOl1CGG1JE'. + 'k1uYEBIVkrb02+o6RItfq6rBhbw/tuINT96766KhuqYpY3UFPF'. + 'BbY/19yZ1XF1U0UNBa9T7rZsz80K0jWk6bpWGW55UzbvTHZ+3t'. + 'vbAv/IT+K1uCmhIrKJAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bl_green.png + //========================================================== + $this->imgdata_large[8][0]= 1484 ; + $this->imgdata_large[8][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMMFjM4kcoDJQAABVlJREFUeNq9ll2MJFUVx3/11V'. + 'Vd/TE9vU0v4zLDwJIF16jBqLAPhsRXEiDqg0QTJiQSjcSNvCzw'. + 'sBEDDxizhvAAxBgf1oR9QF9NiE9ESFZkQyZB5WtddmdnZ3qqqr'. + 'uqbt367Cofqu3ZZpWVaDzJfbkf53//55z/PVdZXV3l/2H6f7Lp'. + '5VdOV/4Nb+GmHpUeA7AdBNxc3kafNb73jRPK9Xwon8ToxVefqU'. + 'b91wibH5EkCQBCizFihTSviHUHR0hWws9xe3wvJ7/7nPKpgX5y'. + '9oFqt3eOgWniRBoAbUBGGqZUibSYaeoT2B5bnkdaSA6793Cv/S'. + 'QPPbihXBfo5VdOV+8dfgnvwAU62YH5fCZ12sDujFkwyegCqTrB'. + 'iUOKTOJKj8jr88jS8zy6cXwBTP048nuHX0I0nDlIp7RpTG7kM0'. + 'sdyAYsTVukUuWGhlWHMq0ITL92lnUp9R1Obz/GmTNnqn9bDD8/'. + '+0D1oX0O0zQZZDYCsK2j3Gl9jQqDfHiei8GfiKVLlsZkJaBAN1'. + '0i6PgwUbB0GxG5/PrtE/xLRr959Znqw9452oVNI+jiJhnr1pe4'. + 'k29zB1/nFr5Kj7tpt1YYhJ0FJ7nUYbcJQBgahN2MzeCP/OipR6'. + 'prgN6Qr6ELFQFUWoRpNVjlKwxZB8DCpE+PtfEKqV1cUzxpVudu'. + 'GTBHA5Y1g99e+dUio9O/P1Vpq+/WE5GGjDSMoAtAQjrf3C52IP'. + 'QxpY4WK2hpReka9Gfrhqgz0bACRoCWjDh56kQ1z9FeuUUQxVhK'. + 'B92sD1VahM+bAJgcoJhGjP/6Ln8rAgDiRCVRKiIzxMkkodBJ85'. + 'im1IlEHbE4k1xyNveL4YP8HarmGJIOpqyjeQmfNHmTvnqZTWBt'. + 'vIJXpPwlukJSuSTKGK3pEwtJmiX00ZlInTyNscImO6XBITvH1c'. + '8vVt2OucdKvIyeKRTNCivsEMgcpg6taYs30nfq0Gqg6hOSSFJ4'. + 'BSnJPht0IqEjWmOGocEI6F0J94F0qaL6BntTF0MtUfweKQKAPU'. + 'Wwp4OcVnQAmVb0p9DLOzjEhEKnGRmoRc7EzRGlwA6NujAKG4yP'. + '6Sjwc4aVznZ7DK0xXdkDoJf0kGmFBniFBOBGcZSCCSKd0IwN0k'. + 'IS+QZWCGVZex4BnUxya3+Zt9iugQbcRFpIAtuHvAZulPUdLhUJ'. + 'RqegI3WcqaSXddlT3idsWMSRRGkEtNwmyTifAwyBo7LP+11J0e'. + '7tM7pZOYblHkBLcqZ5LcYtw6Wbd4CM3SpE9foYZsIHoqDKCrbz'. + 'mLSQtPwmuhXgtBLs0GBdbXOhFGB7WBKO2F8GXt9/VO97Ya3atF'. + '7nUHnwGjGGQqcPxFEdFqURkEidiZszAERoYIsGju1hq21kWee3'. + 'bw15+8WpsvAy3K1+i3JkkhZyPpxxjjPOsfOYiZ+TFhLPzQnHOU'. + 'tpzGB2dgA4tscIkKIx19Cxg/fPL7vQJu47eXt1VvsDK8pwPueZ'. + 'PuZoQMOqhRoJHSs0kKLBWjvjYinmeQGw1TaX1RFdfZ3LMzYLjA'. + 'C++dkn6AaH2Nobk6cxEzdnuG0TdC8zvdJkN0hqkFkO/jwL0fxa'. + 'so8sBcuFzQ+/+MRC+BeAHnpwQzn++ee5KT9Eshuy46dcKAXm32'. + '0uzPQhS4GttkH2GQID2Wc0Y4LtAbDxhZ/x5A+e/uTG9+jGceXH'. + '9/ySnnIXnUzOxXe1038mW3ZynNmam4yYWkO+f9cv+Oljz16/lV'. + '9tDz/9nerc1hm8ZEScSRK7VvtYl1i1dklsOKyvc+zg/bzw1O8+'. + '/efkajt56kR1ydlEJBc5H46xzbrJ3dY9wrB7hGcff+6/+279L+'. + '0fHxyiE8XMLl4AAAAASUVORK5CYII=' ; + + //========================================================== + // File: bl_blue.png + //========================================================== + $this->imgdata_large[9][0]= 1169 ; + $this->imgdata_large[9][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACEF'. + 'BMVEX/////////7//35//v1v/exv/Wvf/Wrf/Wpf/Orf+/v7+9'. + 'tc69jP+9hP+5ucW1tc6tlP+rq7Wlpdalpcalpb2cnM6cnMacc/'. + '+cWv+UlLWUjN6UjK2Uc/+Ma/+MUv+EhKWEa/+EQvd7e8Z7e7V7'. + 'e6V7c957Wv9za9Zza8ZzSv9ra5xrSv9rOf9rMe9jUudjQv9jOe'. + '9aWpRaUt5aUpRaSu9aSudSUoxSSs5SSoxSMf9KQtZKOfdKMedK'. + 'Kf9KKe9CKf9CKb1CKa1CIfdCIedCId45MXs5Kfc5If85Iec5Id'. + 'Y5GP8xMbUxMXsxKc4xKZQxIf8xGP8xGO8xGN4xGNYxGL0xGK0p'. + 'KXMpIYwpGP8pGO8pGOcpGNYpGM4pEP8pEPcpEOcpEN4pENYpEM'. + 'YpEL0hGKUhEP8hEPchEO8hEOchEN4hENYhEM4hEMYhELUhCP8h'. + 'CO8hCN4YGJwYGGsYEL0YEK0YEHMYCN4YCM4YCMYYCL0YCKUYAP'. + '8QEJQQEIwQEHsQEGsQCM4QCLUQCK0QCKUQCJwQCJQQCIwQCHMQ'. + 'CGsQAP8QAPcQAO8QAOcQAN4QANYQAM4QAMYQAL0QALUQAKUQAJ'. + 'QQAIQICGsICGMIAO8IANYIAL0IALUIAK0IAKUIAJwIAJQIAIwI'. + 'AIQIAHsIAHMIAGsIAGMAAN4AAMYAAK0AAJQAAIwAAIQAAHMAAG'. + 'sAAGMAAFrR1dDlAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFRPMOZ'. + '/2AAAB+klEQVR4nGNgIAIIqeqZmBqpi2JISNml5lVXV3d198Yo'. + 'oUjwm1SnxsbGRsSm5ZfNXO4tjCTjVh0ABhFx6QV9E1Y0S8JkuN'. + '3yAgLc7W3t/QPi4jPKJ8ye1yoIlTKpjvVy15eVUbN0i4zKLJ8w'. + 'ae6qcKgLqmMj3PUFWFl5NJ0CExLLJzbNW7BWCyxlXR0ba6/Axs'. + 'zELmfnkRBT0QiSKgXJCOflxUbYy3KyMHEoOrtEZ1c2TZ6/cMl6'. + 'eaCUamdsbIC7tjgPr4SBS3BMMVDTwkXr1hsDpYy6UmMj/O0tdX'. + 'QNbDxjknJLWqYsXLx0vStQynxGflpkZGCgs7Onp29SbtNkoMy6'. + 'pevCgFJWy3oyMuKjgoKCPWNCvEuqWhcsWrJ06XqQlPnMvrKyrM'. + 'TomJjkZAfHlNa2qdOWrlu63gcopbG8v7+hvLwip7g4JdSxsLZu'. + '8dKlS9ettwBKic2eNXHChIkTG5tKqgpr2uo6loLAehWQx0LnzJ'. + '49p6mpeXLLlNq6RUvqly6dvnR9Bx9ISnnlvLmT582bMr9t4aL2'. + '+vrp60GaDCGB6Ld6wfwFCxYCJZYsXQ+SmL6+FBryInVrFi1atH'. + 'jJkqVQsH6pNCzCJNvXrQW6CmQJREYFEc2CYevXrwMLAyXXl0oz'. + 'IAOt0vVQUGSIkabkDV3DwlzNVDAksAAAfUbNQRCwr88AAAAASU'. + 'VORK5CYII=' ; + + //========================================================== + // File: bs_red.png + //========================================================== + $this->imgdata_small[0][0]= 437 ; + $this->imgdata_small[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'. + 'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'. + 'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'. + 'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'. + 'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'. + 'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. + 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGDNEMgOYAAAAm0'. + 'lEQVR4nI3Q3RKCIBAFYGZMy9RKzX7MVUAUlQTe/+kS0K49d3wD'. + '7JlFaG+CvIR3FvzPXgpLatxevVVS+Jzv0BDGk/UJwOkQ1ph2g/'. + 'Ct5ACX4wNT1o/zzUoJUFUGBiGfVnDTYGJgmrWy8iKEtp0Bpd2d'. + 'jLGu56MB7f4JOOfDJAwoNwslk/jOUi+Jts6RVNrC1hkhPy50Ef'. + 'u79/ADQMQSGQ8bBywAAAAASUVORK5CYII=' ; + + + //========================================================== + // File: bs_lightblue.png + //========================================================== + $this->imgdata_small[1][0]= 657 ; + $this->imgdata_small[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABVl'. + 'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'. + 'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'. + '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'. + 'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'. + 'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'. + 'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'. + 'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'. + 'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'. + 'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'. + 'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. + 'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGTok'. + '9Yp9AAAAtElEQVR4nGNgIBaw8wkpKghzwvksPAKiUsraprYiLF'. + 'ARXkE2JiZ1PXMHXzGIAIekOFBE08TGLTCOCyzCLyvDxsZqZOnk'. + 'E56kAhaRV9NQUjW2tPcMjs9wBYsY6Oobmlk7egRGpxZmgkW0zC'. + '2s7Jy9giKT8gohaiQcnVzc/UNjkrMLCyHmcHr7BYREJKTlFxbm'. + 'QOxiEIuKTUzJKgQCaZibpdOzQfwCOZibGRi4dcJyw3S4iQ4HAL'. + 'qvIlIAMH7YAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bs_gray.png + //========================================================== + $this->imgdata_small[2][0]= 550 ; + $this->imgdata_small[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAABI1'. + 'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'. + 'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'. + 'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'. + 'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'. + 'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'. + 'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'. + '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'. + 'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'. + 'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIA'. + 'AAsSAdLdfvwAAAAHdElNRQfTAwkUGiIctEHoAAAAfElEQVR4nI'. + '2N2xKDIAwF+bZ2kAa8cNFosBD//yvKWGh9dN+yk9kjxH28R7ze'. + 'wzBOYSX6CaNB927Z9qZ66KTSNmBM7UU9Hx2c5qjmJaWCaV5j4t'. + 'o1ANr40sn5a+x4biElrqHgrXMeac/c1nEpFHG0LSFoo/jO/BeF'. + 'lJnFbT58ayUf0BpA8wAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bs_greenblue.png + //========================================================== + $this->imgdata_small[3][0]= 503 ; + $this->imgdata_small[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAxl'. + 'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'. + '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'. + '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'. + 'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'. + 'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'. + 'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'. + 'dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfT'. + 'AwkUGTIqLgJPAAAAqklEQVR4nI2QVxOCMBCEM6Mi2OiCvSslJB'. + 'CUoqjn//9TYgCfubf9Zu9uZxFqO+rscO7b6l/LljMZX29J2pNr'. + 'YjmX4ZaIEs2NeiWO19NNacl8rHAyD4LR6jjw6PMRdTjZE0JOiU'. + 'dDv2ALTlzRvSdCCfAHGCc7yRPSrAQRQOWxKc3C/IUjBlDdUcM8'. + '97vFGwBY9QsZGBc/A4DWZNbeXIPWZEZI0c2lqSute/gCO9MXGY'. + '4/IOkAAAAASUVORK5CYII=' ; + + //========================================================== + // File: bs_yellow.png + //========================================================== + $this->imgdata_small[4][0]= 507 ; + $this->imgdata_small[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAzF'. + 'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'. + 'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'. + 'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'. + 'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'. + 'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'. + '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'. + 'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAH'. + 'dElNRQfTAwkUGSDZl3MHAAAAqElEQVR4nI3QWRNDMBAA4My09E'. + 'IF1SME0VT1okXvM/3//6kEfbZv+81eswA0DfHxRpOV+M+zkDGG'. + 'rL63zCoJ2ef2RLZDIqNqYexyvFrY9ePkxGWdpvfzC7tEGtIRly'. + 'nqzboFKMlizAXbNnZyiFUKAy4bZ+B6W0lRaQDLmg4h/k7eFwDL'. + 'OWIky8qhXUBQ7gKGmsxpC+ah1TdriwByqG8GQNDNr6kLjf/wAx'. + 'KgEq+FpPbfAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bs_darkgray.png + //========================================================== + $this->imgdata_small[5][0]= 611 ; + $this->imgdata_small[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAABJl'. + 'BMVEX////////o8v/f6O7W4OnR3PXL1OTL0evEyLvCzePAwMC/'. + 'v7a8wsq7t7C1xum1vtS1q6GzopmyxeKsrsOqvNWoq7anvN+nsb'. + 'qhrcGgqbGfpq6cp7+bqMuVmJKRm7yPlKKMnL6FkKWFipOEkLSE'. + 'j6qEhoqAiaB+jqd8haF7hZR4iJt4g5l3hZl2gIt2cod1hJVzeY'. + 'VzboJvhp9sfJJsb41peY1pd5xpdoVod4xndI5lcHxka4BjcYVg'. + 'Z3BfboFbb4lbZnZbYntaZ4laZYVZV3JYYWpXX3JWWm5VX4RVW2'. + 'NUYX9SXHxPWn5OVFxNWWtNVXVMVWFKV3xHUGZGU3dGTldFSlxE'. + 'Sk9ESXBCRlNBS3k/SGs/RU4+R1k9R2U6RFU2PUg0PEQxNU0ECL'. + 'QWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA'. + 'CxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGQmbJetrAAAAtklEQV'. + 'R4nGNgwAK4JZTNNOWlYDxhMT4ZDTOzQE1uMF9CiJWVU0LbxDlS'. + 'G8QVF+FnZ2KRNHAIiPUHaZGSlmZj5lH19A1KjLUA8lXU5MWllF'. + 'yjo30TYr2BfG19G11b37CEeN84H38gX1HbwTUkOjo+zjfG3hLI'. + 'l1exCvCNCwnxjfMz0gTyRdXNHXx9fUNCQu2MwU6SN3ZwD42LCH'. + 'W30IK4T8vUJSAkNMhDiwPqYiktXWN9JZj7UQAAjWEfhlG+kScA'. + 'AAAASUVORK5CYII=' ; + + + //========================================================== + // File: bs_darkgreen.png + //========================================================== + $this->imgdata_small[6][0]= 666 ; + $this->imgdata_small[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABX1'. + 'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'. + 'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'. + 'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'. + 'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'. + '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'. + 'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'. + 'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'. + 'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'. + 'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'. + 'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. + 'RQfTAwkUGRjxlcuZAAAAtElEQVR4nGNgIBZw8osqqIpzw/msfI'. + 'IiUmr6lo6SbFARASEOJiYtQ2uXADmIAJeEGFBE18LBMySBBywi'. + 'LC/LwcFiZuvmH5WiAxZR0tRW1DC3dfYJS8zyAouYGBibWtm7+o'. + 'TEpZfkgEX0rG3snNx9Q2NSCksgaqRd3Ty8gyLiU/NKSiDmcPsF'. + 'BodHJ2UUlZTkQ+xikIlNSE7LLgECZagL2VQyc0H8YnV2uD94jS'. + 'ILIo14iQ4HALarJBNwbJVNAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bs_purple.png + //========================================================== + $this->imgdata_small[7][0]= 447 ; + $this->imgdata_small[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAnF'. + 'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'. + 'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'. + 'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'. + 'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'. + 'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. + 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGS'. + 'o5QpoZAAAAnElEQVR4nI3Q2xJDMBAG4MyQokWrZz3oSkJISJH3'. + 'f7dK0Gv/Xb7J7vyzCK0NjtPsHuH/2wlhTE7LnTNLCO/TFQjjIp'. + 'hHAA6bY06LSqppMAY47x+04HXTba2kAFlmQKr+YuVDCGUG2k6/'. + 'rNwYK8rKwKCnPxHnVS0aA3rag4UQslUGhrlk0Kpv1+sx3tLZ6w'. + 'dtYemMkOsnz8R3V9/hB87DEu2Wos5+AAAAAElFTkSuQmCC' ; + + + //========================================================== + // File: bs_brown.png + //========================================================== + $this->imgdata_small[8][0]= 677 ; + $this->imgdata_small[8][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABaF'. + 'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'. + 'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'. + 'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'. + 'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'. + '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'. + 'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'. + 'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'. + 'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'. + 'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'. + 'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'. + 'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLd'. + 'fvwAAAAHdElNRQfTAwkUGho0tvl2AAAAtklEQVR4nGNgIBaoSg'. + 'mLKGpowfkGMty8AqJKpi4mRlAROR5ONg4JFUv3YHOIgDo/HwsT'. + 'q6yps29EsjZYREFIkJ2ZS9/OMzA20wEsIi8uKSZtaOPmH5WSFw'. + 'YW0VRW07Vw8vCLSMguLwCL6FlaObp6B0TGZxSXQ9TouHv6+IXG'. + 'JGYWlpdDzNEKCgmPjkvLKS0vL4LYxWAen5SelV8OBNZQFxrZ5h'. + 'aC+GX2MDczMBh7pZakehkTHQ4AA0Am/jsB5gkAAAAASUVORK5C'. + 'YII=' ; + + //========================================================== + // File: bs_blue.png + //========================================================== + $this->imgdata_small[9][0]= 436 ; + $this->imgdata_small[9][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'. + 'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'. + 'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'. + 'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'. + 'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'. + 'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. + 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGhNNakHSAAAAmk'. + 'lEQVR4nI3P2xKCIBAGYGfM6SBWo1nauIqogaDA+z9dK9Lhrv47'. + 'vtl/2A2CfxNlJRRp9IETYGraJeEb7ocLNKznia8A7Db7umWDUG'. + 'sxAzhurxRHxok4KQGqCuEhlL45oU1D2w5BztY4KRhj/bCAsetM'. + '2uObjwvY8/oX50JItYDxSyZSTrO2mNhvGMbaWAevnbFIcpuTr7'. + 't+5AkyfBIKSJHdSQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bs_green.png + //========================================================== + $this->imgdata_small[10][0]= 452 ; + $this->imgdata_small[10][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAn1'. + 'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'. + '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'. + 'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'. + '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'. + 'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'. + 'AIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAw'. + 'kUGgW5vvSDAAAAnklEQVR4nI3QSxKCMAwA0M4gqCgoiiJ+kEAL'. + 'LQUq0PufzX7ENdnlJZNkgtDS2CYZvK6bf+7EoKLA9cH5SQzv6A'. + 'YloTywsAbYr44FrlgrXCMJwHl3xxVtuuFkJAPIcw2tGB9GcFli'. + 'oqEf5GTkSUhVMw2TtD0XSlnDOw3SznE5520vNEi7CwW9+Ayjyq'. + 'U/3+yPuq5gvhkhL0xlGnqL//AFf14UIh4mkEkAAAAASUVORK5C'. + 'YII=' ; + + + //========================================================== + // File: bs_white.png + //========================================================== + $this->imgdata_small[11][0]= 480 ; + $this->imgdata_small[11][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMLFTsY/ewvBQAAAW1JREFUeJytkz2u4jAUhT/jic'. + 'gfBUKiZhE0bIKeVbCWrIKenp6eDiGlCEEEBArIxvzGU4xeZjLk'. + 'jWb05lRXuvbx+exr4bouX1Xjyw7Atz81F4uFBYjjGIDhcCjq1o'. + 'k6nN1uZwFerxfP55Msy1itVmRZBsB4PK6YveHkeW5d18XzPIIg'. + 'wPd9Wq0WnU6HMAxJkoQoiuynOIfDwUopkVIihKAoCgAcx6Hdbm'. + 'OMIU1T5vN55eBKEikljUYDIX6kFUKU9e8aDAZlmjcca+1b7TgO'. + '1+uVy+VS9nzfr8e53++VzdZaiqIgz3OMMWitOZ/PaK0JgqDeRC'. + 'mF53lIKYGfr3O73TDGoJQiTVO01nS73XqT4/FIs9kkCAIej0eZ'. + 'brPZEMcxSZKgtQZgMpmIWpN+vy+m06n1PK9yTx8Gy+WS/X5Pr9'. + 'er9GuHLYoiG4YhSilOpxPr9Zrtdlti/JriU5MPjUYjq7UuEWaz'. + '2d+P/b/qv/zi75oetJcv7QQXAAAAAElFTkSuQmCC' ; + + + //========================================================== + // File: bs_cyan.png + //========================================================== + $this->imgdata_small[12][0]= 633 ; + $this->imgdata_small[12][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABPl'. + 'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'. + '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'. + 'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'. + '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'. + 'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'. + '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'. + '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'. + 'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'. + 'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'. + 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. + 'AHdElNRQfTAwkUGQDi+VPPAAAAtElEQVR4nGNgIBawikipyIiy'. + 'wfksfJpGRkamNtr8LFARPiMFHmFDcztXfwGoFi0jLiZuZRtnry'. + 'BddrCIiJEGL6eklYO7X3iCOFhE2thESdHawdUnJDZFDiyiamZh'. + 'aevk5h0UlZSpBhaRtbN3dPHwDY5MSM+EqBFzc/f0DgiLTkjLzI'. + 'SYw6bjHxgaEZeckZmpD7GLQSAqJj4xNRMIBGFuFtRLA/ENhGBu'. + 'ZmDgkJBXl5fgIDocAAKcINaFePT4AAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bs_bluegreen.png + //========================================================== + $this->imgdata_small[13][0]= 493 ; + $this->imgdata_small[13][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAvV'. + 'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'. + 'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'. + '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'. + 'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'. + '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'. + 'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'. + 'AJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGxNUcXCT'. + 'AAAAqUlEQVR4nI2Q1xKCMBREM2NHLCCogAGCjd6SqLT8/2cZKT'. + '6zb3tm987OBWCsXoejp8rC35fi4+l6gXFZlD0Rz6fZ1tdDmKR9'. + 'RdOmkzmP7DDpilfX3SzvRgQ/Vr1uiZplfsCBiVf03RJd140wgj'. + 'kmNqMtuYXcxyYmNWJdRoYwzpM9qRvGujuCmSR7q7ARY00/MiWk'. + 'sCnjkobNEm1+HknDZgAqR0GKU43+wxdu2hYzbsHU6AAAAABJRU'. + '5ErkJggg==' ; + + //========================================================== + // File: bs_lightred.png + //========================================================== + $this->imgdata_small[14][0]= 532 ; + $this->imgdata_small[14][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAA3l'. + 'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'. + 'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'. + 'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'. + 'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'. + 'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'. + 'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'. + 'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. + 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGjoP2Nm+AAAAr0'. + 'lEQVR4nGNgIBaYiOk62imYwPnMkiIyso76yhJSzFARMxkRNk49'. + 'a3t5OW6oFk1LVkYOfWUHKxUXiEYzLS12DnN3VXkjIRtFsIiSk5'. + '6evqGqhYGKugAfWMRa1FpD2UHeQEXQRlgALCJur+rgbCUNFOAS'. + 'hqjRkZe3MpBTcwEKCEPMMTGSs3Xz8OQHCnBBHckt6OJpIyAMBD'. + 'wwN/MYc4H4LK4wNzMwmGrzcvFqmxIdDgDiHRT6VVQkrAAAAABJ'. + 'RU5ErkJggg==' ; + + //========================================================== + // File: bxs_lightred.png + //========================================================== + $this->imgdata_xsmall[0][0]= 432 ; + $this->imgdata_xsmall[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAA3l'. + 'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'. + 'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'. + 'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'. + 'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'. + 'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'. + 'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'. + 'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. + 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKBOgGhWjAAAAS0'. + 'lEQVR4nGNgQAEmunYmEJaMCKe1vBxYzJKVQ9lKBSSupKdnaKGi'. + 'zgdkiqs6WKnYcIGYJnK2HvzCwmCNgi42wsLCECNMeXlNUY0HAL'. + 'DaB7Du8MiEAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bxs_bluegreen.png + //========================================================== + $this->imgdata_xsmall[1][0]= 397 ; + $this->imgdata_xsmall[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAvV'. + 'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'. + 'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'. + '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'. + 'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'. + '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'. + 'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'. + 'AJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKDVyF5Be'. + 'AAAASUlEQVR4nGNgQAFmYqJcEJaEOJ+UrD5YTJKFTZrfGCQuaq'. + 'glLWvMaQ5kqujo6hnbKIKYXPr68gp2dmCNJiZAlh3ECGsREWtU'. + '4wF1kwdpAHfnSwAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bxs_navy.png + //========================================================== + $this->imgdata_xsmall[2][0]= 353 ; + $this->imgdata_xsmall[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'. + 'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'. + 'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'. + 'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'. + 'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'. + 'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. + 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJxXO4axZAAAAR0'. + 'lEQVR4nGNgQAGskhKsEJaslIi8ijpYTJaDU1FVAyQuKSujoKKh'. + 'LQ5kSigpqWro6oOYrOoaWroGBmCNWiCWAdQwUVFWVOMBOp4GCJ'. + 's5S60AAAAASUVORK5CYII=' ; + + //========================================================== + // File: bxs_gray.png + //========================================================== + $this->imgdata_xsmall[3][0]= 492 ; + $this->imgdata_xsmall[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABI1'. + 'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'. + 'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'. + 'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'. + 'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'. + 'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'. + 'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'. + '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'. + 'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'. + 'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEA'. + 'AAsRAX9kX5EAAAAHdElNRQfTAwkUKC74clmyAAAAQklEQVR4nG'. + 'NgQAVBYVCGt5dXYEQ0mOnp5h4QFgVmeri6+4dHxYMVeHoFRUTH'. + 'gTUFBIZBWAwMkZEx8bFQM2Lj0UwHANc/DV6yq/BiAAAAAElFTk'. + 'SuQmCC' ; + + //========================================================== + // File: bxs_graypurple.png + //========================================================== + $this->imgdata_xsmall[4][0]= 542 ; + $this->imgdata_xsmall[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABSl'. + 'BMVEX////////11P/MqdvKrNfAwMC+u7+9u7+4rr24lsi3rby3'. + 'lMe1rLq1o720q7i0oL20ksSzoryyqbaykMGxlb2wkL+vnbiujb'. + '2sjLuri7qpl7GoirWoibenmK2mla6mjLKmhrSllauki7CjhrCj'. + 'hLGihLChg6+ggq2fkqadkKOcfqqai6Gag6WYe6WXeqSWeaOTd6'. + 'CTd5+Rdp6RdZ6RdZ2Qg5eOc5qMcpiLcZeJb5WIbpOHbZKGbJGE'. + 'a4+CaY2AZ4t/Z4p/Zop/Zol+Zol7ZIZ6Y4V5YoR1ZH11X391Xn'. + '9zXX1yXXtxXHtvWnluWXhsV3VqVnNpVXJoVHFnU3BmUm9jUGth'. + 'VGdgTmheTGZcS2RcSmRaSWJYR19XRl5SQllRQlhQQVdPQFZOP1'. + 'VLPlFJO09IPE5IOk5FOEtEN0lDOEpDOElDNklCNkc/M0XhbrfD'. + 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. + 'EAAAsRAX9kX5EAAAAHdElNRQfTAwkUKCgREfyHAAAATUlEQVR4'. + 'nGNgQAEcIko8EBY3M5Ougy+IxSXMwmTsFsAHZMqrSRvZB0W7A5'. + 'k6FlYugXEZICaPr394Um4uSAFDRFRCbm4uxAihsDAhVOMBHT0L'. + 'hkeRpo8AAAAASUVORK5CYII=' ; + + //========================================================== + // File: bxs_red.png + //========================================================== + $this->imgdata_xsmall[5][0]= 357 ; + $this->imgdata_xsmall[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'. + 'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'. + 'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'. + 'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'. + 'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'. + 'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. + 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIyjy5SVMAAAAS0'. + 'lEQVR4nGNgQAFsUpJsEJastIi8ijpYTJaDU0FVgxXIlJKVUVDR'. + '0BYHMiUUlVQ1dPVBTDZ1dS1dAwOQAgYtbSDLAGIEq6goK6rxAD'. + 'yXBg73lwGUAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: bxs_yellow.png + //========================================================== + $this->imgdata_xsmall[6][0]= 414 ; + $this->imgdata_xsmall[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAzF'. + 'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'. + 'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'. + 'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'. + 'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'. + 'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'. + '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'. + 'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAH'. + 'dElNRQfTAwkUIzoBXFQEAAAAS0lEQVR4nGNgQAFsDhJsEJaTo5'. + '2skj5YzMnSSk7ZwBzIlOSUklPiMxYHMnW4FXT5VNVBTDZeXiNV'. + 'QUGQAgYBYyBLEGIEq5gYK6rxAH4kBmHBaMQQAAAAAElFTkSuQm'. + 'CC' ; + + //========================================================== + // File: bxs_greenblue.png + //========================================================== + $this->imgdata_xsmall[7][0]= 410 ; + $this->imgdata_xsmall[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAxl'. + 'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'. + '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'. + '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'. + 'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'. + 'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'. + 'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'. + 'dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfT'. + 'AwkUJy5/6kV9AAAATUlEQVR4nGNgQAGCyuyCEJaGugKHviVYzF'. + 'hO3sxCWwDIVNLTM9PXtpEGMhW12Cy0DR1ATEFLSxZ7BweQAgYd'. + 'HUMHBweIEQKiogKoxgMAo/4H5AfSehsAAAAASUVORK5CYII=' ; + + //========================================================== + // File: bxs_purple.png + //========================================================== + $this->imgdata_xsmall[8][0]= 364 ; + $this->imgdata_xsmall[8][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAnF'. + 'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'. + 'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'. + 'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'. + 'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'. + 'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. + 'HUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIj'. + 'mBTjT/AAAASUlEQVR4nGNgQAGskhKsEJaCrJiSuhZYTEFASFlD'. + 'GyQuqSCnrK6tJwpkiquoamgbGIGYrFpaugbGxmCNunpAljHECB'. + 'ZBQRZU4wFSMAZsXeM71AAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bxs_green.png + //========================================================== + $this->imgdata_xsmall[9][0]= 370 ; + $this->imgdata_xsmall[9][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAn1'. + 'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'. + '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'. + 'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'. + '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'. + 'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'. + 'AIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAw'. + 'kUKBrZxq0HAAAATElEQVR4nGNgQAGccrIcEJaivISyhjaIxa7I'. + 'I6CiqcMKZMopKqho6OhLA5kyqmqaOobGICartraeoYkJSAGDnj'. + '6QZQIxgk1Skg3VeABlVgbItqEBUwAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bxs_darkgreen.png + //========================================================== + $this->imgdata_xsmall[10][0]= 563 ; + $this->imgdata_xsmall[10][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABX1'. + 'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'. + 'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'. + 'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'. + 'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'. + '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'. + 'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'. + 'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'. + 'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'. + 'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'. + 'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'. + 'RQfTAwkUKCFozUQjAAAATUlEQVR4nGNgQAGcoqrcEJYQB5OhSw'. + 'CIxSXGwWThGcIDZCppK5o7hyV6AZl6NnbuoSmFICZ3YHB0RkkJ'. + 'SAFDbEJaSUkJxAjeyEheVOMBQj4MOEkWew4AAAAASUVORK5CYI'. + 'I=' ; + + //========================================================== + // File: bxs_cyan.png + //========================================================== + $this->imgdata_xsmall[11][0]= 530 ; + $this->imgdata_xsmall[11][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABPl'. + 'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'. + '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'. + 'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'. + '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'. + 'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'. + '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'. + '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'. + 'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'. + 'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'. + 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAA'. + 'AHdElNRQfTAwkUKQFKuFWqAAAATUlEQVR4nGNgQAGsUjJsEJaR'. + 'grC5qz9YzIiL28YriB3IlDZRsnYNiZUDMmXtHT2CE9JBTDb/wI'. + 'jkzEyQAoaomMTMzEyIERzy8hyoxgMAN2MLVPW0f4gAAAAASUVO'. + 'RK5CYII=' ; + + //========================================================== + // File: bxs_orange.png + //========================================================== + $this->imgdata_xsmall[12][0]= 572 ; + $this->imgdata_xsmall[12][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABaF'. + 'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'. + 'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'. + 'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'. + 'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'. + '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'. + 'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'. + 'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'. + 'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'. + 'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'. + 'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'. + 'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9k'. + 'X5EAAAAHdElNRQfTAwkUJBSSy88MAAAATUlEQVR4nGNgQAGqwo'. + 'paEBYPJ4eKezCIpc7HwmrqG6ENZMpLihm6RaWEAZl6Vo7ekRnF'. + 'IKZWSHhcTnk5SAFDfFJWeXk5xAjj1FRjVOMBeFwNcWYSLjsAAA'. + 'AASUVORK5CYII=' ; + + //========================================================== + // File: bxs_lightblue.png + //========================================================== + $this->imgdata_xsmall[13][0]= 554 ; + $this->imgdata_xsmall[13][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABVl'. + 'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'. + 'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'. + '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'. + 'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'. + 'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'. + 'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'. + 'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'. + 'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'. + 'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'. + 'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. + 'gAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJziL'. + 'PvAsAAAATUlEQVR4nGNgQAHsQgqcEJYgG5Oegy+IxSHOxmTiFs'. + 'gFZMprKBnbB8e7AplaFlbOQUl5ICanX0BEWmEhSAFDVGxKYWEh'. + 'xAjusDBuVOMBJO8LrFHRAykAAAAASUVORK5CYII=' ; + + //========================================================== + // File: bxs_darkgray.png + //========================================================== + $this->imgdata_xsmall[14][0]= 574 ; + $this->imgdata_xsmall[14][1]= + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABm'. + 'JLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAB'. + 'iElEQVR42k3QPU8TYRwA8P//ebkXrgdIColXRAOEkJqbaExMut'. + 'DBhE1GNjYHPg+DG6ODiU6QOLjVxITBcFKBYCstlAC2Bz17fe76'. + 'vLD6+wg/1FpTRFR5lpaub/u1eGBGaAT4HneD4OlXx7avtDYUjT'. + 'HQabd2Ti8e3vVSKzxrtHS32wIpFVldno22Nqvvg2Bhl0gp/aNm'. + 'vJ3qqXAtLIva+ks1H0wqlSXi4+d6+OFTfRsAfHJx2d1od24rZP'. + 'xP2HzopINr1mkesX7ccojqif0v9crxWXODZTno3+dNGA7uWLsd'. + 'mUYU4fHJCViMG9umLBmM4L6fagZGg9QKfjZ+Qfy3C3G/B3mugF'. + 'IHHNcDf64E3KJALApk2p8CSolUUqLjFkyxOGMsTtFyJ+Wz57NQ'. + '8DghS4sLB0svioeZZo7nPhFoUKZDIVFbglkTTnl5/rC8snjAkJ'. + 'Bk/XV5LxHC/v7tR8jzTFPbg8LENK9WX0Vv31T2AEmCSmlKCCoh'. + 'ROnP1U1tPFYjJBRcbtzSf+GPsFTAQBq1n4AAAABKdEVYdHNpZ2'. + '5hdHVyZQBiYzYyMDIyNjgwYThjODMyMmUxNjk0NWUzZjljOGFh'. + 'N2VmZWFhMjA4OTE2ZjkwOTdhZWE1MzYyMjk0MWRkM2I5EqaPDA'. + 'AAAABJRU5ErkJggg==' ; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/imgdata_bevels.inc b/web/public_php/admin/jpgraph/imgdata_bevels.inc deleted file mode 100644 index a5142796e..000000000 --- a/web/public_php/admin/jpgraph/imgdata_bevels.inc +++ /dev/null @@ -1,105 +0,0 @@ - 'imgdata'); - - var $colors = array('green','purple','orange','red','yellow'); - var $index = array('green'=>1,'purple'=>4,'orange'=>2,'red'=>0,'yellow'=>3); - var $maxidx = 4 ; - - var $imgdata ; - - function ImgData_Bevels() { -//========================================================== -// File: bullets_balls_red_013.png -//========================================================== - $this->imgdata[0][0]= 337 ; - $this->imgdata[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. - 'BMVEX////////27t/f3+LFwcmNxMuxm62DmqKth1VpZmIWg6fv'. - 'HCa7K0BwMEytCjFnIyUlEBg9vhQvAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. - 'RQfTAxcBNhk+pYJVAAAAl0lEQVR4nE2Q2xLDIAgFHUWBKJf//9'. - 'oekmbafVDZARRbK/pYTKP9WNcNv64zzUdd9BjmrgnsVXRNSzO3'. - 'CJ5ahdhy0XKQkxld1kxb45j7dp0x2lBNOyVgQpMaoadX7Hs7zr'. - 'P1yKj47DKBnKaBKiSAkNss7O6PkMx6kIgYXISQJpcZCqdY6KR+'. - 'J1PkS5Xob/h7MNz8x6D3fz5DKQjpkZOBYAAAAABJRU5ErkJggg'. - '==' ; - -//========================================================== -// File: bullets_balls_green_013.png -//========================================================== - $this->imgdata[1][0]= 344 ; - $this->imgdata[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. - 'BMVEX////////27t/e3+K3vriUub/Dm18j4xc3ob10k0ItqQlU'. - 'e5JBmwpxY1ENaKBgUh0iHgwsSre9AAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. - 'RQfTAxcBNTfJXtxZAAAAnklEQVR4nE2QWY4EMQhDUVhSIRC4/2'. - 'kbaqLp9p+f2AxAayAzDfiK9znPORuvH0x8Ss9z6I9sHp6tcxE9'. - 'nLmWmebmt5F5p2AR0+C9AWpLBjXRaZsCAT3SqklVp0YkAWaGtd'. - 'c5Z41/STYpPzW7BjyiRrwkVmQto/Cw9tNEMvsgcekyCyFPboIu'. - 'IsuXiKffYB4NK4r/h6d4g9HPPwCR7i8+GscIiiaonUAAAAAASU'. - 'VORK5CYII=' ; - -//========================================================== -// File: bullets_balls_oy_035.png -//========================================================== - $this->imgdata[2][0]= 341 ; - $this->imgdata[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. - 'BMVEX////////27t/f3+K5tbqNwcjnkjXjbxR2i5anfEoNkbis'. - 'PBxpU0sZbZejKgdqIRIlERIwYtkYAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. - 'RQfTAxcBNgK0wEu5AAAAm0lEQVR4nE3QVxIEIQgEUErAgTHA/U'. - '+7zbipf9RXgoGo0liMmX6RdSPLPtZM9F4LuuSIaZtZWffiU6Iz'. - 'Y8SOMF0NogBj30ioGRGLZgiPvce1TbIRz6oBQEbOFGK0rIoxrn'. - '5hDomMA1cfGRCaRVhjS3gkzheM+4HtnlkXcvdZhWG4qZawewe6'. - '9Jnz/TKLB/ML6HUepn//QczazuwFO/0Ivpolhi4AAAAASUVORK'. - '5CYII=' ; - -//========================================================== -// File: bullets_balls_oy_036.png -//========================================================== - $this->imgdata[3][0]= 340 ; - $this->imgdata[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. - 'BMVEX////////27t/e3+LO3hfYzz65ubiNwci6uQ12ipadgVGa'. - 'fwsNkbhnVkcaZ5dwSA8lFg7CEepmAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'. - 'RQfTAxcCBySi1nevAAAAjElEQVR4nFXPWw7EIAgFUNMoCMhj/6'. - 'staKczc/2RkwjS2glQ+w3YytgXCXCZpRo8gJdGxZadJws13CUP'. - '4SZI4MYiUxypeiGGw1XShVBTNN9kLXP2GRrZPFvKgd7z/sqGGV'. - '7C7r7r3l09alYN3iA8Yn+ImdVrNoEeSRqJPAaHfhZzLYwXstdZ'. - 'rP3n2bvdAI4INwtihiwAAAAASUVORK5CYII=' ; - -//========================================================== -// File: bullets_balls_pp_019.png -//========================================================== - $this->imgdata[4][0]= 334 ; - $this->imgdata[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. - 'BMVEX////+/v7i4eO/w8eHxcvKroNVormtfkjrMN2BeXQrepPc'. - 'Esy4IL+OFaR7F25LHF8mFRh5XXtUAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. - 'RQfTAxcBNgkjEpIxAAAAlElEQVR4nE2QAQ7FIAhDDTAVndL7n3'. - 'ZV/7JfEwMvFIWUlkTMVNInbVv5ZeJqG7Smh2QTBwJBpsdizAZP'. - '5NyW0awhK8kYodnZxS6ECvPRp2sI+y7PBv1mN02KH7h77QCJ8D'. - '4VvY5NUgEmCwj6ZMzHtJRgRSXwC1gfcqJJH0GBnSnK1kUQ72DY'. - 'CPBv+MCS/e0jib77eQAJxwiEWm7hFwAAAABJRU5ErkJggg==' ; - - } -} - - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/imgdata_bevels.inc.php b/web/public_php/admin/jpgraph/imgdata_bevels.inc.php new file mode 100644 index 000000000..c98fa571f --- /dev/null +++ b/web/public_php/admin/jpgraph/imgdata_bevels.inc.php @@ -0,0 +1,104 @@ + 'imgdata'); + + protected $colors = array('green','purple','orange','red','yellow'); + protected $index = array('green'=>1,'purple'=>4,'orange'=>2,'red'=>0,'yellow'=>3); + protected $maxidx = 4 ; + + protected $imgdata ; + + function __construct() { + //========================================================== + // File: bullets_balls_red_013.png + //========================================================== + $this->imgdata[0][0]= 337 ; + $this->imgdata[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. + 'BMVEX////////27t/f3+LFwcmNxMuxm62DmqKth1VpZmIWg6fv'. + 'HCa7K0BwMEytCjFnIyUlEBg9vhQvAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. + 'RQfTAxcBNhk+pYJVAAAAl0lEQVR4nE2Q2xLDIAgFHUWBKJf//9'. + 'oekmbafVDZARRbK/pYTKP9WNcNv64zzUdd9BjmrgnsVXRNSzO3'. + 'CJ5ahdhy0XKQkxld1kxb45j7dp0x2lBNOyVgQpMaoadX7Hs7zr'. + 'P1yKj47DKBnKaBKiSAkNss7O6PkMx6kIgYXISQJpcZCqdY6KR+'. + 'J1PkS5Xob/h7MNz8x6D3fz5DKQjpkZOBYAAAAABJRU5ErkJggg'. + '==' ; + + //========================================================== + // File: bullets_balls_green_013.png + //========================================================== + $this->imgdata[1][0]= 344 ; + $this->imgdata[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. + 'BMVEX////////27t/e3+K3vriUub/Dm18j4xc3ob10k0ItqQlU'. + 'e5JBmwpxY1ENaKBgUh0iHgwsSre9AAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. + 'RQfTAxcBNTfJXtxZAAAAnklEQVR4nE2QWY4EMQhDUVhSIRC4/2'. + 'kbaqLp9p+f2AxAayAzDfiK9znPORuvH0x8Ss9z6I9sHp6tcxE9'. + 'nLmWmebmt5F5p2AR0+C9AWpLBjXRaZsCAT3SqklVp0YkAWaGtd'. + 'c5Z41/STYpPzW7BjyiRrwkVmQto/Cw9tNEMvsgcekyCyFPboIu'. + 'IsuXiKffYB4NK4r/h6d4g9HPPwCR7i8+GscIiiaonUAAAAAASU'. + 'VORK5CYII=' ; + + //========================================================== + // File: bullets_balls_oy_035.png + //========================================================== + $this->imgdata[2][0]= 341 ; + $this->imgdata[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. + 'BMVEX////////27t/f3+K5tbqNwcjnkjXjbxR2i5anfEoNkbis'. + 'PBxpU0sZbZejKgdqIRIlERIwYtkYAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. + 'RQfTAxcBNgK0wEu5AAAAm0lEQVR4nE3QVxIEIQgEUErAgTHA/U'. + '+7zbipf9RXgoGo0liMmX6RdSPLPtZM9F4LuuSIaZtZWffiU6Iz'. + 'Y8SOMF0NogBj30ioGRGLZgiPvce1TbIRz6oBQEbOFGK0rIoxrn'. + '5hDomMA1cfGRCaRVhjS3gkzheM+4HtnlkXcvdZhWG4qZawewe6'. + '9Jnz/TKLB/ML6HUepn//QczazuwFO/0Ivpolhi4AAAAASUVORK'. + '5CYII=' ; + + //========================================================== + // File: bullets_balls_oy_036.png + //========================================================== + $this->imgdata[3][0]= 340 ; + $this->imgdata[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. + 'BMVEX////////27t/e3+LO3hfYzz65ubiNwci6uQ12ipadgVGa'. + 'fwsNkbhnVkcaZ5dwSA8lFg7CEepmAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'. + 'RQfTAxcCBySi1nevAAAAjElEQVR4nFXPWw7EIAgFUNMoCMhj/6'. + 'staKczc/2RkwjS2glQ+w3YytgXCXCZpRo8gJdGxZadJws13CUP'. + '4SZI4MYiUxypeiGGw1XShVBTNN9kLXP2GRrZPFvKgd7z/sqGGV'. + '7C7r7r3l09alYN3iA8Yn+ImdVrNoEeSRqJPAaHfhZzLYwXstdZ'. + 'rP3n2bvdAI4INwtihiwAAAAASUVORK5CYII=' ; + + //========================================================== + // File: bullets_balls_pp_019.png + //========================================================== + $this->imgdata[4][0]= 334 ; + $this->imgdata[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. + 'BMVEX////+/v7i4eO/w8eHxcvKroNVormtfkjrMN2BeXQrepPc'. + 'Esy4IL+OFaR7F25LHF8mFRh5XXtUAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. + 'RQfTAxcBNgkjEpIxAAAAlElEQVR4nE2QAQ7FIAhDDTAVndL7n3'. + 'ZV/7JfEwMvFIWUlkTMVNInbVv5ZeJqG7Smh2QTBwJBpsdizAZP'. + '5NyW0awhK8kYodnZxS6ECvPRp2sI+y7PBv1mN02KH7h77QCJ8D'. + '4VvY5NUgEmCwj6ZMzHtJRgRSXwC1gfcqJJH0GBnSnK1kUQ72DY'. + 'CPBv+MCS/e0jib77eQAJxwiEWm7hFwAAAABJRU5ErkJggg==' ; + + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/imgdata_diamonds.inc b/web/public_php/admin/jpgraph/imgdata_diamonds.inc deleted file mode 100644 index c7f44629d..000000000 --- a/web/public_php/admin/jpgraph/imgdata_diamonds.inc +++ /dev/null @@ -1,178 +0,0 @@ -'imgdata'); - var $colors = array('lightblue','darkblue','gray', - 'blue','pink','purple','red','yellow'); - var $index = array('lightblue' =>7,'darkblue'=>2,'gray'=>6, - 'blue'=>4,'pink'=>1,'purple'=>5,'red'=>0,'yellow'=>3); - - var $maxidx = 7 ; - var $imgdata ; - - function ImgData_Diamonds() { -//========================================================== -// File: diam_red.png -//========================================================== - $this->imgdata[0][0]= 668 ; - $this->imgdata[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'. - 'BMVEX///////+cAAD/AADOAABjAABrAADWGBjOCAj/CAj/GBj/'. - 'EBCcCAiMOTl7KSl7ISFzGBilGBjOEBBrCAjv5+eMQkK1QkKtMT'. - 'GtKSnWKSn/KSlzEBCcEBDexsb/tbXOe3ucWlqcUlKUSkr/e3vn'. - 'a2u9UlL/a2uEMTHeUlLeSkqtOTn/UlL/SkrWOTn/QkL/OTmlIS'. - 'H/MTH/ISH39/f/9/f35+fezs7/5+fvzs7WtbXOra3nvb3/zs7G'. - 'nJzvtbXGlJTepaW9jIy1hITWlJS1e3uta2ulY2P/lJTnhITne3'. - 'vGY2O9Wlr/c3PeY2O1Skr/Y2P/WlreQkLWISGlEBCglEUaAAAA'. - 'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'. - 'sSAdLdfvwAAAAHdElNRQfTAwsWEw5WI4qnAAABGUlEQVR4nHXQ'. - '1XLDMBAFUKUCM1NiO8zcpIxpp8z0//9SWY7b2LHv6EU6s1qtAN'. - 'iMBAojLPkigpJvogKC4pxDuQipjanlICXof1RQDkYEF21mKIfg'. - '/GGKtjAmOKt9oSyuCU7OhyiDCQnjowGfRnooCJIkiWJvv8NxnG'. - 'nyNAwFcekvZpPP3mu7Vrp8fOq8DYbTyjdnAvBj7Jbd7nP95urs'. - '+MC2D6unF+Cu0VJULQBAlsOQuueN3Hrp2nGUvqppemBZ0aU7Se'. - 'SXvYZFMKaLJn7MH3btJmZEMEmGSOreqy0SI/4ffo3uiUOYEACy'. - 'OFopmNWlP5uZd9uPWmUoxvK9ilO9NtBo6mS7KkZD0fOJYqgGBU'. - 'S/T7OKCAA9tfsFOicXcbxt29cAAAAASUVORK5CYII=' ; - -//========================================================== -// File: diam_pink.png -//========================================================== - $this->imgdata[1][0]= 262 ; - $this->imgdata[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. - 'BMVEX///+AgID/M5n/Zpn/zMz/mZn1xELhAAAAAXRSTlMAQObY'. - 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. - 'AHdElNRQfTAwsWEi3tX8qUAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. - 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. - '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. - 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. - '==' ; - -//========================================================== -// File: diam_blue.png -//========================================================== - $this->imgdata[2][0]= 662 ; - $this->imgdata[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA+V'. - 'BMVEX///+AgIAAAJwAAP8AAM4AAGMAAGsQEP8YGHMQEHMYGP8Q'. - 'EKUICJwICM5KSpQxMYQpKXsYGNYQEM4ICGsICP97e85aWpw5OY'. - 'xSUv85ObVCQt4xMa0pKa0hIaUpKf+9vd6EhLVra+dzc/9SUr1r'. - 'a/9aWt5SUt5CQrVaWv9KSv8hIXs5Of8xMf8pKdYhIdYYGKUhIf'. - '/Ozs739//v7/fn5+/v7//n5/fW1ufOzufOzu/W1v+trc69veel'. - 'pc6trd6UlMa9vf+MjL21tfe1tf+UlNZzc61ra6Wlpf+EhOeMjP'. - '9ra8ZSUpyEhP9CQoxKSrVCQv85Od4xMdYQENZnJhlWAAAAAXRS'. - 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. - 'LdfvwAAAAHdElNRQfTAwsWEx3Snct5AAABFklEQVR4nHXR5XbD'. - 'IBgGYM6AuHsaqbvOfeuknev9X8xISbplSd5/8JyXwwcA/I0AKm'. - 'PFchVBdvKNKggKQx2VIoRwMZihMiQE49YUlWBCcPL0hYq4ITh+'. - 'qKECUoLDZWqoQNA766F/mJHlHXblPJJNiyURhM5eU9cNw5BlmS'. - 'IrLOLxhzfotF7vwO2j3ez2ap/TmW4AIM7DoN9+tu+vLk6Pdg9O'. - '6ufXjfXLm6pxPACSJIpRFAa+/26DhuK6qjbiON40k0N3skjOvm'. - 'NijBmchF5mi+1jhQqDmWyIzPp1hUlrv8On5l+6mMm1tigFNyrt'. - '5R97g+FKKyGKkTNKesXPJTZXOFIrUoKiypcTQVHjK4g8H2dWEQ'. - 'B8bvUDLSQXSr41rmEAAAAASUVORK5CYII=' ; - -//========================================================== -// File: diam_yellow.png -//========================================================== - $this->imgdata[3][0]= 262 ; - $this->imgdata[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. - 'BMVEX///+AgIBmMwCZZgD/zADMmQD/QLMZAAAAAXRSTlMAQObY'. - 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. - 'AHdElNRQfTAwsWEwcv/zIDAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. - 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. - '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. - 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. - '==' ; - -//========================================================== -// File: diam_lightblue.png -//========================================================== - $this->imgdata[4][0]= 671 ; - $this->imgdata[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/1'. - 'BMVEX///+AgIAAnP8A//8Azv8AY/8Aa/8I//8Y1v8Izv8Y//8Q'. - '//8InP8Qzv8Ypf85jP8he/8Yc/8Ia/8pe/8p//8p1v9Ctf8xrf'. - '8prf8QnP8Qc/9CjP+1//97//9r//9S//9K//9C//85//8x//8h'. - '//9r5/9K3v9S3v851v97zv9Svf85rf8hpf/G3v9SnP9anP9KlP'. - '8xhP/n7//v7+f3///n///O//+U//9z//9j//9a//975/9C3v8h'. - '1v+E5/+17/9j3v/O7//n9/+95/+l3v9jxv+U1v8Qpf9avf9Ktf'. - '+Uxv+11v97tf9rrf+cxv+Mvf9jpf+tzv+Etf/O3v/39/8Akkxr'. - 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. - 'IAAAsSAdLdfvwAAAAHdElNRQfTAwsWEiHk6Ya/AAABGUlEQVR4'. - 'nHXQ13KDMBAF0J2o0E01GHDvJa7p3em95/+/JQJMYjDc0Yt0Zr'. - 'VaAaxHgtxwbSGPkGQpOIeQ2ORxJiJmNWYZyAhZR0WcgQGhViU0'. - 'nEGoedDHGxgRapRPcRpXhOr7XZzCmLjaXk9IIjvkOEmSRLG62+'. - 'F5XlEElhA5sW21GvXj6mGlDBfnJ51lr9svnvEKwH1hu2QPbwd3'. - 'N9eXVzuL7/Hn29frdKaamgcgy67L3HFG9gDefV+dm5qme4YRXL'. - 'oVR374mRqUELZYosf84XAxISFRQuMh4rrH8YxGSP6HX6H97NNQ'. - 'KEAaR08qCeuSnx2a8zIPWqUowtKHSRK91rAw0elmVYQFVc8mhq'. - '7p5RD7Ps3IIwA9sfsFxFUX6eZ4Zh4AAAAASUVORK5CYII=' ; - -//========================================================== -// File: diam_purple.png -//========================================================== - $this->imgdata[5][0]= 657 ; - $this->imgdata[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'. - 'BMVEX///////8xAP/OAP+cAP9jAP9rAP+cCP85CP/OEP9SKf/O'. - 'CP9CEP9zGP9rCP+lGP/WOf/WIf9KIf9jOf+MQv+EMf97If9zEP'. - '+1Sv+lIf/ne//eUv/na//n5//Oxv/Wzv+chP9zUv97Wv9rQv9a'. - 'Mf9KGP/v5/+te/97Kf+9Y/+tOf+tKf+lEP/vtf/WMf/WKf/v7+'. - 'f39/+tnP+9rf9rSv9jQv9CGP+ljP+EY//Gtf+tlP+Ma/9zSv/e'. - 'zv+UUv+9lP+cWv+lY/+cUv+MOf+EKf+UQv/Opf/OhP/Ga/+1Qv'. - '/Oe/+9Uv/ntf/eWv/eSv/WGP/3zv/vlP/WEP//9/+pL4oHAAAA'. - 'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'. - 'sSAdLdfvwAAAAHdElNRQfTAwsWEjX+M1LCAAABDklEQVR4nHXQ'. - '1bLDIBAGYFqIEW+ksbr7cXd3ff93OUCamdOE/Mxw882yywLwPz'. - '+gNKotlRFUVnNUQlCxTMRFCKEdE+MgpJaEiIOU4DKaoSIygtb3'. - 'FBUQrm3xjPK4JvXjK0A5hFniYSBtIilQVYUm+X0KTVNiYah+2q'. - 'ulFb8nUbSovD2+TCavwXQWmnMA6ro+di+uR5cPzfPhVqPV3N1p'. - 'n3b3+rimAWAYhP3xnXd7P6oc9vadPsa1wYEs00dFQRAFehlX21'. - '25Sg9NOgwF5jeNTjVL9om0TjDc1lmeCKZ17nFPzhPtSRt6J06R'. - 'WKUoeG3MoXRa/wjLHGLodwZcotPqjsYngnWslRBZH91hWTbpD2'. - 'EdF1ECWW1SAAAAAElFTkSuQmCC' ; - -//========================================================== -// File: diam_gray.png -//========================================================== - $this->imgdata[6][0]= 262 ; - $this->imgdata[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. - 'BMVEX//////wAzMzNmZmbMzMyZmZlq4Qo5AAAAAXRSTlMAQObY'. - 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. - 'AHdElNRQfTAwsWExZFTxLxAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. - 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. - '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. - 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. - '==' ; - -//========================================================== -// File: diam_blgr.png -//========================================================== - $this->imgdata[7][0]= 262 ; - $this->imgdata[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. - 'BMVEX///+AgIBmzP9m///M//+Z//8hMmBVAAAAAXRSTlMAQObY'. - 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. - 'AHdElNRQfTAwsWEwCxm6egAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. - 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. - '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. - 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. - '==' ; - } -} - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/imgdata_diamonds.inc.php b/web/public_php/admin/jpgraph/imgdata_diamonds.inc.php new file mode 100644 index 000000000..a0d6a4215 --- /dev/null +++ b/web/public_php/admin/jpgraph/imgdata_diamonds.inc.php @@ -0,0 +1,177 @@ +'imgdata'); + protected $colors = array('lightblue','darkblue','gray', + 'blue','pink','purple','red','yellow'); + protected $index = array('lightblue' =>7,'darkblue'=>2,'gray'=>6, + 'blue'=>4,'pink'=>1,'purple'=>5,'red'=>0,'yellow'=>3); + + protected $maxidx = 7 ; + protected $imgdata ; + + function __construct() { + //========================================================== + // File: diam_red.png + //========================================================== + $this->imgdata[0][0]= 668 ; + $this->imgdata[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'. + 'BMVEX///////+cAAD/AADOAABjAABrAADWGBjOCAj/CAj/GBj/'. + 'EBCcCAiMOTl7KSl7ISFzGBilGBjOEBBrCAjv5+eMQkK1QkKtMT'. + 'GtKSnWKSn/KSlzEBCcEBDexsb/tbXOe3ucWlqcUlKUSkr/e3vn'. + 'a2u9UlL/a2uEMTHeUlLeSkqtOTn/UlL/SkrWOTn/QkL/OTmlIS'. + 'H/MTH/ISH39/f/9/f35+fezs7/5+fvzs7WtbXOra3nvb3/zs7G'. + 'nJzvtbXGlJTepaW9jIy1hITWlJS1e3uta2ulY2P/lJTnhITne3'. + 'vGY2O9Wlr/c3PeY2O1Skr/Y2P/WlreQkLWISGlEBCglEUaAAAA'. + 'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'. + 'sSAdLdfvwAAAAHdElNRQfTAwsWEw5WI4qnAAABGUlEQVR4nHXQ'. + '1XLDMBAFUKUCM1NiO8zcpIxpp8z0//9SWY7b2LHv6EU6s1qtAN'. + 'iMBAojLPkigpJvogKC4pxDuQipjanlICXof1RQDkYEF21mKIfg'. + '/GGKtjAmOKt9oSyuCU7OhyiDCQnjowGfRnooCJIkiWJvv8NxnG'. + 'nyNAwFcekvZpPP3mu7Vrp8fOq8DYbTyjdnAvBj7Jbd7nP95urs'. + '+MC2D6unF+Cu0VJULQBAlsOQuueN3Hrp2nGUvqppemBZ0aU7Se'. + 'SXvYZFMKaLJn7MH3btJmZEMEmGSOreqy0SI/4ffo3uiUOYEACy'. + 'OFopmNWlP5uZd9uPWmUoxvK9ilO9NtBo6mS7KkZD0fOJYqgGBU'. + 'S/T7OKCAA9tfsFOicXcbxt29cAAAAASUVORK5CYII=' ; + + //========================================================== + // File: diam_pink.png + //========================================================== + $this->imgdata[1][0]= 262 ; + $this->imgdata[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. + 'BMVEX///+AgID/M5n/Zpn/zMz/mZn1xELhAAAAAXRSTlMAQObY'. + 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. + 'AHdElNRQfTAwsWEi3tX8qUAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. + 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. + '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. + 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. + '==' ; + + //========================================================== + // File: diam_blue.png + //========================================================== + $this->imgdata[2][0]= 662 ; + $this->imgdata[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA+V'. + 'BMVEX///+AgIAAAJwAAP8AAM4AAGMAAGsQEP8YGHMQEHMYGP8Q'. + 'EKUICJwICM5KSpQxMYQpKXsYGNYQEM4ICGsICP97e85aWpw5OY'. + 'xSUv85ObVCQt4xMa0pKa0hIaUpKf+9vd6EhLVra+dzc/9SUr1r'. + 'a/9aWt5SUt5CQrVaWv9KSv8hIXs5Of8xMf8pKdYhIdYYGKUhIf'. + '/Ozs739//v7/fn5+/v7//n5/fW1ufOzufOzu/W1v+trc69veel'. + 'pc6trd6UlMa9vf+MjL21tfe1tf+UlNZzc61ra6Wlpf+EhOeMjP'. + '9ra8ZSUpyEhP9CQoxKSrVCQv85Od4xMdYQENZnJhlWAAAAAXRS'. + 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. + 'LdfvwAAAAHdElNRQfTAwsWEx3Snct5AAABFklEQVR4nHXR5XbD'. + 'IBgGYM6AuHsaqbvOfeuknev9X8xISbplSd5/8JyXwwcA/I0AKm'. + 'PFchVBdvKNKggKQx2VIoRwMZihMiQE49YUlWBCcPL0hYq4ITh+'. + 'qKECUoLDZWqoQNA766F/mJHlHXblPJJNiyURhM5eU9cNw5BlmS'. + 'IrLOLxhzfotF7vwO2j3ez2ap/TmW4AIM7DoN9+tu+vLk6Pdg9O'. + '6ufXjfXLm6pxPACSJIpRFAa+/26DhuK6qjbiON40k0N3skjOvm'. + 'NijBmchF5mi+1jhQqDmWyIzPp1hUlrv8On5l+6mMm1tigFNyrt'. + '5R97g+FKKyGKkTNKesXPJTZXOFIrUoKiypcTQVHjK4g8H2dWEQ'. + 'B8bvUDLSQXSr41rmEAAAAASUVORK5CYII=' ; + + //========================================================== + // File: diam_yellow.png + //========================================================== + $this->imgdata[3][0]= 262 ; + $this->imgdata[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. + 'BMVEX///+AgIBmMwCZZgD/zADMmQD/QLMZAAAAAXRSTlMAQObY'. + 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. + 'AHdElNRQfTAwsWEwcv/zIDAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. + 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. + '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. + 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. + '==' ; + + //========================================================== + // File: diam_lightblue.png + //========================================================== + $this->imgdata[4][0]= 671 ; + $this->imgdata[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/1'. + 'BMVEX///+AgIAAnP8A//8Azv8AY/8Aa/8I//8Y1v8Izv8Y//8Q'. + '//8InP8Qzv8Ypf85jP8he/8Yc/8Ia/8pe/8p//8p1v9Ctf8xrf'. + '8prf8QnP8Qc/9CjP+1//97//9r//9S//9K//9C//85//8x//8h'. + '//9r5/9K3v9S3v851v97zv9Svf85rf8hpf/G3v9SnP9anP9KlP'. + '8xhP/n7//v7+f3///n///O//+U//9z//9j//9a//975/9C3v8h'. + '1v+E5/+17/9j3v/O7//n9/+95/+l3v9jxv+U1v8Qpf9avf9Ktf'. + '+Uxv+11v97tf9rrf+cxv+Mvf9jpf+tzv+Etf/O3v/39/8Akkxr'. + 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. + 'IAAAsSAdLdfvwAAAAHdElNRQfTAwsWEiHk6Ya/AAABGUlEQVR4'. + 'nHXQ13KDMBAF0J2o0E01GHDvJa7p3em95/+/JQJMYjDc0Yt0Zr'. + 'VaAaxHgtxwbSGPkGQpOIeQ2ORxJiJmNWYZyAhZR0WcgQGhViU0'. + 'nEGoedDHGxgRapRPcRpXhOr7XZzCmLjaXk9IIjvkOEmSRLG62+'. + 'F5XlEElhA5sW21GvXj6mGlDBfnJ51lr9svnvEKwH1hu2QPbwd3'. + 'N9eXVzuL7/Hn29frdKaamgcgy67L3HFG9gDefV+dm5qme4YRXL'. + 'oVR374mRqUELZYosf84XAxISFRQuMh4rrH8YxGSP6HX6H97NNQ'. + 'KEAaR08qCeuSnx2a8zIPWqUowtKHSRK91rAw0elmVYQFVc8mhq'. + '7p5RD7Ps3IIwA9sfsFxFUX6eZ4Zh4AAAAASUVORK5CYII=' ; + + //========================================================== + // File: diam_purple.png + //========================================================== + $this->imgdata[5][0]= 657 ; + $this->imgdata[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'. + 'BMVEX///////8xAP/OAP+cAP9jAP9rAP+cCP85CP/OEP9SKf/O'. + 'CP9CEP9zGP9rCP+lGP/WOf/WIf9KIf9jOf+MQv+EMf97If9zEP'. + '+1Sv+lIf/ne//eUv/na//n5//Oxv/Wzv+chP9zUv97Wv9rQv9a'. + 'Mf9KGP/v5/+te/97Kf+9Y/+tOf+tKf+lEP/vtf/WMf/WKf/v7+'. + 'f39/+tnP+9rf9rSv9jQv9CGP+ljP+EY//Gtf+tlP+Ma/9zSv/e'. + 'zv+UUv+9lP+cWv+lY/+cUv+MOf+EKf+UQv/Opf/OhP/Ga/+1Qv'. + '/Oe/+9Uv/ntf/eWv/eSv/WGP/3zv/vlP/WEP//9/+pL4oHAAAA'. + 'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'. + 'sSAdLdfvwAAAAHdElNRQfTAwsWEjX+M1LCAAABDklEQVR4nHXQ'. + '1bLDIBAGYFqIEW+ksbr7cXd3ff93OUCamdOE/Mxw882yywLwPz'. + '+gNKotlRFUVnNUQlCxTMRFCKEdE+MgpJaEiIOU4DKaoSIygtb3'. + 'FBUQrm3xjPK4JvXjK0A5hFniYSBtIilQVYUm+X0KTVNiYah+2q'. + 'ulFb8nUbSovD2+TCavwXQWmnMA6ro+di+uR5cPzfPhVqPV3N1p'. + 'n3b3+rimAWAYhP3xnXd7P6oc9vadPsa1wYEs00dFQRAFehlX21'. + '25Sg9NOgwF5jeNTjVL9om0TjDc1lmeCKZ17nFPzhPtSRt6J06R'. + 'WKUoeG3MoXRa/wjLHGLodwZcotPqjsYngnWslRBZH91hWTbpD2'. + 'EdF1ECWW1SAAAAAElFTkSuQmCC' ; + + //========================================================== + // File: diam_gray.png + //========================================================== + $this->imgdata[6][0]= 262 ; + $this->imgdata[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. + 'BMVEX//////wAzMzNmZmbMzMyZmZlq4Qo5AAAAAXRSTlMAQObY'. + 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. + 'AHdElNRQfTAwsWExZFTxLxAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. + 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. + '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. + 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. + '==' ; + + //========================================================== + // File: diam_blgr.png + //========================================================== + $this->imgdata[7][0]= 262 ; + $this->imgdata[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. + 'BMVEX///+AgIBmzP9m///M//+Z//8hMmBVAAAAAXRSTlMAQObY'. + 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. + 'AHdElNRQfTAwsWEwCxm6egAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. + 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. + '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. + 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. + '==' ; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/imgdata_pushpins.inc b/web/public_php/admin/jpgraph/imgdata_pushpins.inc deleted file mode 100644 index f330ebb6f..000000000 --- a/web/public_php/admin/jpgraph/imgdata_pushpins.inc +++ /dev/null @@ -1,518 +0,0 @@ - 'imgdata_small', - MARK_IMG_SPUSHPIN => 'imgdata_small', - MARK_IMG_LPUSHPIN => 'imgdata_large'); - - var $colors = array('blue','green','orange','pink','red'); - var $index = array('red' => 0, 'orange' => 1, 'pink' => 2, 'blue' => 3, 'green' => 4 ) ; - var $maxidx = 4 ; - var $imgdata_large, $imgdata_small ; - - function ImgData_PushPins() { - - // The anchor should be where the needle "hits" the paper - // (bottom left corner) - $this->anchor_x = 0; - $this->anchor_y = 1; - -//========================================================== -// File: ppl_red.png -//========================================================== - $this->imgdata_large[0][0]= 2490 ; - $this->imgdata_large[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMKBh4Ryh89CgAACUdJREFUeJy9mNtTFFcexz+/7p'. - '4Lw1wZJKDGCAwmDAqUySamcCq1ed6k9mn3UfMP7F+1T3nYqn2J'. - 'lZdoDEjpbq0KG8EBFBFBEJye6Zmenkv32Ydu5GYiUMmeqq6uqT'. - '6Xz3zP73aOcIKmAQkIFyD3N/jrBPwlKjLQEglVlJKyUjR3u7cc'. - 'WLoP3/4dvv03LNrQ8I6x1rFbDML9kOmHvh7IRHU9JKmUSG8vpF'. - 'IoXX/TV0AiEM5A5jT0noFMFMJHXUt/d5f9TUAbhtQ3cPFruDog'. - '8klHMnmO0dGYe/myOJGINEwTz3F2higFXgy8PpAkOC+h8hoaCt'. - '4ppHFcQAWSgOQlyI/p+lUjmRxWAwNJd3xca/f34yoFi4tgmjtD'. - 'NIFkJ4xcgBCgVqEBFJ9DqcZea/gNAAVEg7AOGYnHe9XoaJd3+X'. - 'LISSSwnz6lsbKCZ9sHh4UVdBkwdA6cPwNnIfJPmC3Ctgft3wwQ'. - 'QPkvTZJJnbExzfvsM2nMzVG7e5fG48d4lnXwTwEYCjJxuHQBog'. - 'BHUfKkgAIIhiGk06hTp/Dm5qS1uYlXLvtWd4gPgIiCrAEcVckT'. - 'Ab5p7TaYJrK1hQaEenrwSiVfQdc91P0kSp7Ii89D5ksY/kAkLy'. - 'IZXFdXkQjS1YUSEbdcRu168V6+HTUNIKJDRwdE+sBIQmP9Ld59'. - 'bEBA3of4F/D+uXb7rGaaCSmXI3pPj64PDaHCYfEqFVSjgWo2D2'. - '73XlJNQTgCyQykIuBWoNKEeh1aLXBPBCggGdBOgxZVSjoajVhH'. - 'o5HWlIpq4bCQSgm9vXhK4ZZKh5SUYygp4J1EQVUD9xlU18BJQD'. - 'bUbJ5T5XJStyxN9fSI099P3baxV1dRloW2h2ivx/yakg2ot6F1'. - 'EkCa4G1D+zVEq5ArKTWM42Q6HUczQV7U66w9e0ZpdRXlOIQ5vF'. - 'VHUXILKify4jiEzkOqC3peQMoBQymFlMt4Dx6wUSxSsm2UZXEK'. - 'P30QvOUt8/2Sd78CdWwFDTA+gsw3cOlPcPUD+CQB52oQ21RKXM'. - 'eRhGXhOg7VoKrx8KuS4ygZhVg3ZI8FGIfwR9BVgAtfwxdXdP3L'. - '86nUR91dXelNXTeWWy10paQHX602YAP1ADASAL7LJvFtMpOCc0'. - 'cG3FHuGlz6Gr4YEpnoTCbzsdHRbOzy5RCRiLRMk5rjyOtAimwA'. - 'U4U3SurBN/0wnAASBCVDIKpB4kiAB5Ub0/UvO9LpPAMDGfn005'. - 'AxPCzxep3Q6iqPLUseBoufCZRsAE6g5g5kKIDfKUj3wnpAG8QB'. - '/Z1OIqANQuI65AtwNScyYXR2XlAXL2YZHzcklRKWl5GVFXFtGx'. - 'MoAiV/EQaAGH6BUQNWgQpwFngv+Ca8KUAQEBcwgTJHyMV7679R'. - 'XS8YqdSI6u/PMD5ukMtJY3GR2uQkr5aXeWVZOEALmA8WsIAxfL'. - 'd0goVLAdCOd+/YpgqeVtBv4yiA++q/RKKXixe7GB8PSyoljcVF'. - 'yg8fyubyMpulEk2lyAIfAAvAC+B+oOQFoAt/+0rAejB/EzjNri'. - 'vvqNnCd64jxcE39V8spnP+vMbAgDSePKE2NcXm06dslMuUlcID'. - 'TuFvqwXMBU8N39bGgRR+ki0Dz4L5DSAe9NGD7zq+6kcN1L6H2b'. - 'ao5WWaQHllRTafPmWrVMJUimoAQrBYJFjQwre7B6A8YAi8LCgD'. - '5DVo6/hbb/iHK1KggvFeD3hHziQKEMuiNTNDbXGRTdtmw7Iwla'. - 'KGH0oqwbscLOoG46rAY6AOzRhY74PT6QuUKEN4PegXxd/yEDTT'. - 'YMWOk+oEaLkuFdNk0zTZwjfkavDUArXWgGXgFb4dEShXhfYqlI'. - 'ow3w9rg3B6ED60IOOA5oEYQBrcpG+mj9bg0VG8GMJhVDZLyzAo'. - 'VSq8rFYxXXefcjVgG9+uisDrXUCApoKSBcUHMBmHhfcgNwhtD3'. - 'q9IG6Lr15b4OUTmPwBJt8JqGuapp05o0mhoHnptLQfPsR+8IBK'. - 'uYyNH3yr+B77LHheA3tK1Ta+IrMeTL2C6Xl48TOsNWDDgAz7s5'. - '/r+krP/eddCsbj8fDQ4GBm9MqVvvRXX2VULBayRGRzaYn1SoWa'. - 'UjgB4PIB5QK4ZgBXBKaAHxQsrED1H7CRgCUPwgHZDqACmhWwXv'. - '2aDRqGYeRyufS169cvThQKV88PDuYbW1vJ5VRK+5euqxWlPMdX'. - 'SRqgreHbZGN3ijfKBXBTAeh2Fdwi2MofshP/dvKwCmKhp4m83Y'. - 'vj8Xg4l8tlCoXC0MTExMTFkZE/1m37wvLGRvKRacoD1209E7Fc'. - 'pZwYREOQqEJ4z3HskHLsz4AoXykPIBSN0t3dTTQafROoHdumXC'. - '4fjoMiog0ODiauX7+eLxQKV3O53ETdti88nJnJ3rl505ifmWm3'. - 'arWSodR8GNbycDoNHy5C5jFold1k8d+DyvELNwg93d18/vnn9P'. - 'X1oes6nufx/Plz7t+/fxhQKSWJRCI5NjaWHxkZKdj1+sjSwkJm'. - '+uZN/dZ337VqCwullGUVdZjsgIUC5LqhrUPvCugWuApeApPAzY'. - 'PKHWyaphGNRunt7WVwcBARwfM8Ojo6sCzrMKBhGLphGFEF2Wq1'. - '2jc7M5OZ/vHH0MPbt93awkJJmeZsC6ZaMK3DCwvWdNioQUb5B6'. - 'AdBR+9SzkAz/NwHIeXL18iIui6TjgcJplMMjY2th8wHo+Hh4aG'. - 'MsPDw6fddru7+Phxx51bt/RbN260qwsLpZhlFZsw9QJ+2Pbrga'. - 'oJG2FY2oKwuTtVEz9uV34NbqdtbW0xPT1NNBoF4MyZM1y5coWu'. - 'rq5dQBHRcrlc4tq1a/l8Pj9RMs38ndu3Ez//9JNXLRZNyuXZJk'. - 'xVYKoExQpsK/+IaAuYb7no8zjC/R+A4zisrq7u+53NZjl16tQ+'. - 'QIlEIslsNpuPRCJXZ2dnh2/duNFRW1oy07a96MKd575yxRqU1B'. - '5vPMpF5HHa1tYW9+7do7Ozc/eQpZTSQ6FQt1Lq8pMnT/5w7969'. - 'nuLcXE1rNufO9fRMhlKpOyvt9qPtVmvb25fFfvvWbrepVCqHwo'. - 'xaX19vff/996ZhGC8qlkW9Wt1Onz073fXxxz+6MB+9e9dUjuO+'. - '7ebq9wLdB9hoNCrr6+s/4wf3FCJW3fPmTZhXsNWCprjuW66Dfr'. - '928KAfBhJAEgiJSLuzs7OSTqctoFkqlZRt26j/I+L/AGjPTN4d'. - 'Nqn4AAAAAElFTkSuQmCC' ; - -//========================================================== -// File: ppl_orange.png -//========================================================== - $this->imgdata_large[1][0]= 2753 ; - $this->imgdata_large[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMLFQ0VCkHCzQAACk5JREFUeJytmGtzG0d2hp8zNw'. - 'AEcRdJ6EJK9FL0CqZUm9jWbkwq3vhDstl8dmLvz8rP2H8Q75ZT'. - 'pkRfpLgqsS6WIFEKGYkiSBCDO+banQ8DUpRWEkklXQUUqlCDfv'. - 'rp857pgfAOQ4AMOJdg4R/hX96Hf06bvDc5iT07i8yeg8ksiIAI'. - '4TBi/ds9/vivD/njapNHvRBfHXMu410AM+BUoVSF05NQsi1sO4'. - '8402AXwLQTuP31OAZO2aG0MEn14iSlnI1z3LnMk8IZYJyBwjIs'. - '/TWsVIWPJkvMFS4zMfMhUp5BsoCpAAEBLYKaMFGn00jBxnvu02'. - '35+JHmSJEnBpQEcPo38MmCxd/nS9Ry71Ga/g1W9a8gn0GsHkgA'. - '6DGjxkqb5CoO+YxF3A3p+jGjQUzoK+L/V0ADzFMwtSR8eLbAr8'. - 'uXOTf9NzhTc0geSLUQcYHgYEH786RMg0zWJHV2Aitv4x/HpHVS'. - 'QA2YBqTTGIUq5qkPMWaWkVwPnPtAA/BevmZcjxaaUtHh8pJJGu'. - 'DpCB9FvT7A7YT7S3p5vFMNzmWo/O0MSx/Ms3TqI8r59zFTfUQe'. - 'I7SBODE3tnfoIxYnNHligwik0zAzDdVpyKbA8sff5YAeMEwgkV'. - 'cufQeTJzZoCsaFLKXPTnNpoUTNsSgJmNoGsuNQjIDwYD2HlnZy'. - 'k++yxTKXZfKTU8zOpjhneeQYkorSmGERtIlICBKRbLX+y98YN3'. - 'ADcNIm+bJD4U3pPnmbEaRgYVRTGBkDSSsmxKfY7ZLuDJA4hdjl'. - 'JEgyBB2SJOvQ9RzTpNKoEwNq0CNFvOXR3/HxMgYVPObaz8kPmh'. - 'hkEWMatAfRONGGvLizyOE9P8KkpwhPDAgQKJQbELUD0oOIhbbH'. - 'JeVTmowxjAgZutB5AoOngA+2DdYrcTyOyYZP9+QpBvI29vwEhb'. - 'It042BVQgDy9KTMfkwQG1A9ACCLlgBBGUwxxoc52WDh2ATyEPp'. - '1hoaPvrEBh0Dq5an9OUsl/9hylk5b5c+mowLc4E2Jtw4Eoljyf'. - 'ogA/AGEAagNRjGyUxOmEycyVA5EWDBxrmUp3ytLIv/NJP69Goh'. - '+9mFydIvS5PZYkvH1oY/RFtKymlwBFQAgQd+kAA6qSQ8pvn2mp'. - 'SkJkuVFHPHBnQMrEt5Sl+e4/Lvp51PF1PF5Xy6WMvOWZXMom8z'. - 'OZTQ8+j5sbQiMEwopsCIwRtBGIJSCdzbTGo9NimkDcgdC7Bg49'. - 'TG5n4/nfr0Si77WdYp1YzyZEkWPdteaEnB7pPqBTxuIf/VgciE'. - 'SgasCPwh+GNIkaNNag1RiPge5pEhMQVjfoLcF+eoXSvbKxedwn'. - 'LKzC3KWbOi5/sW5a44/SHFUSgVA7SCzRG0AvA9mPOgFIETgu4n'. - 'Ww0wNQWFAqRSL6D2ZQYBdDrQ7R7jXiwgRcvIL02makuTmWtpM/'. - '+BlLMl5vuWzLVEuwH6oYnR1KS8kJINGXMM2YdfRlALoQoQQKeb'. - 'bDVwoMdxQMaLCwLo96HZTF5HbrEhmOftianfZisfzueKv7ZmrX'. - 'MsjhxKXZGBjzyeEHmSE3oWiggtyVGmE8DTIXTC5NxgAxOAGUM8'. - 'fun9mnSSLQ/CxNzOTgJ3LIMgoGwkKBiiMyaVviHVkdCO4FEKNv'. - 'LQzWBYHfITPa4UBVM0LR/WB7ARJsdDDTjA6deYFIFUOimJ3d0E'. - 'sNdLavYYgBpthqKcjiiJRO8K6CK0CsJTjfQAGaJtD9vQFAxNNQ'. - '1FB0yBAfA8gdMAIagLoCVAen0M00zMOTYShNDtoHs9CAIUoI4E'. - '1IBihCdNhsMhsj6NuV7BCC2IBpBqQaaFOENCCeiEsO1BO4RQgy'. - 'I5Hm4k4oIU9MrgZSAdBeTabZz+ODxKQRRBFBJo6IUc51anYRQo'. - 'dto+24FNxYCiaWKkQsj00KkO4gxRRkAngJ868M0u3OkkM+hxQA'. - 'cQ7YD7GO5XYSsPZybh/TCkFIYY+kWniTW4Q7jXgHvHMhiRpmuW'. - 'ca08GZkkZ/nY6TZMNhCnf2CuPoDVJvxpB+q9BHA8Ag1uH+oP4c'. - 'YEPCzDwmzSLquShHW/E0YRbG/BjZtw40hAy7aNzJlzRn75E6N0'. - 'qiwTzafI7kOU3gWrhzZC2iHcbsPqLlxvJnCt4KC1RYAL3I5hzY'. - 'Xv/huePYCtITQMKEnyB4KQvMURuJvw889HGSwUCs7CwkLpo6tX'. - 'Ty/+7nel6VLGDn/8N9m+eZuo1UP8iNhLau6b3RfmOsHBGTUYw9'. - 'WBNeDrGB4+h/4qNLKwTnLbHj9CJw/6GoIh9Jpvq0HHcayFhYXi'. - 'l3/4w9LK8vLKexfma3G/mb/3n1njTivS7tNQaaU1grQDjJ868D'. - 'Axx6vmxnBrY9C9IcSbSXbavNjb/S3eN6/0m1JcKBScixcvllZW'. - 'Vi6uLC8v12q1v/M8b/HxVjP//YYr32yE4dYWvShO0ogi14xwxq'. - 'F4rbnxZ3cMjtpvEEeMvwA0TdOYn5/PffHFF7Vr166tvPeLXyx7'. - 'nrd4+/btyg/frFo//Xgncnd67qCn78earQqcmYD3fSi1wPCTSV'. - '3gzqvm9uFOMl5nUAqFQn5paal26dKla57vf7D+6FHph9VV88af'. - 'vgq79bo70e3VT2l9A3hYg4UiRALVHTCHSZvYBm4A//6quf8zoG'. - '3bpuM4acMwKr1+//SDe/dK31+/bv90/Xrcq9fduNW6rbVeC+E7'. - 'gWdD2DKg4UEpBmPcm10RuScida31ntb62HAigoigDw6Gh0axWH'. - 'QWFhZKi4uLZ+I4PrVer2e+u37dXPvqq6hbr7tOp1NXWq89h6/b'. - '8FBB34WGBesdcPrj38lkMkGlUuml0+mu53nR3t4eo9HoSLhMJk'. - 'OlUiGdTuN5Hq7rvgA0TdO4cOFC7vPPP6/VarXldqdTu7m2lrv7'. - '7beq++BBO263b/tKrfWSXlbvwJ6CuAtDgTYiaBFMw6BSqfDxxx'. - '+rarWqGo0GN2/eZGtrC6XenAkRoVKpcPXqVWZmZmg0Gty6desF'. - 'oIhIOp3Ol8vlmmVZK3fv3Lm09uc/Zwbr653ccPgoNIzvnmn99Z'. - '7W9QG46lAaM5mM2l95GIYUi0VOnz7N7OwsWmsymQzyuse5Q8Mw'. - 'DNLpNDMzM5w/f/7A6AGgUkoajYa9urpayOXzUz/fvZutr68Pim'. - 'F4/2y1+n2o9Q/ru7uPesPhXnyo4A+vfHp6mmazybNnz9jZ2UFr'. - 'TbPZJAhe+8/aS0Mphed5NBoNABqNBqPR6MWBVWstvu/nnj9/Pv'. - 'vo0aPq5uZmPBgM/qcwPf39xV/9ajU1M3Nvq9PZaw8GoT50PjdN'. - 'k6mpKa5cucL58+eJ45j19XWePHnCzs4OnudhmiaWZRGGIVH05r'. - 'yEYYjrumxubrKxsfFyDQJ6NBp1Pc+7C4jWumBaVm+kVL2l1H2l'. - '1G6otS+H6V6z8u3tbVzXpdFooJRicXGRqakptre3uXXr1ltrcT'. - 'Qa8ezZszemWAE9rfUdYBOwtVLRbrPZ+48ff+wDvuu6Sr3MB4Dr'. - 'uty6desgfa1WC3iRyrNnz4pSSmezWUzTfGtYtNYcdvC/9sMlgP'. - 'n5N4cAAAAASUVORK5CYII=' ; - -//========================================================== -// File: ppl_pink.png -//========================================================== - $this->imgdata_large[2][0]= 2779 ; - $this->imgdata_large[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMLFQolY9lkpgAACmhJREFUeJy9mOtzFNl5h5+3b9'. - 'Mz0kzPBWmEVtIiWYhIiC0HCDhB8lb8ISk7nzdZ5+/zJ/8BTmpT'. - '660CZLwG1pVFgBkgGIHECEaa+/T9nHzQCCQuRpCNz6mp6g893U'. - '8/c37ve3qEjxiC4OA4n/Lp/EUu/tsMM/+aEWduVBx7WhdkShcY'. - 'xUH2zo0Dwod/5N6vf8V//PoGdx8M8EOFPtK9jI8BdHCcMuVSmf'. - 'LxHLmSZdm2U8xIbmKETDGDZZnIy4dBbCynyGhphurEDBOlHFnn'. - 'qPcyPxTOwDCOccw7w5nlBRZWylI+ny/mZ6rL1dzUZ5/IWGZU3D'. - 'ZIOMQDDaJcHDVGWUbJBi9odVr0QoVSPzigIEaZ8vgSS/8wZU3/'. - 'k1fylipz5dLM2WlrZqHKaGCKbEbontq3KAKWQyZfZKTgYqc9Bp'. - '2I2PcJ4ogk/UEBQcwipbFZmT13vDBx8fhnE1Ofnp9yJopFyT3X'. - 'yANfks0QHSQMDaL37pOxMLIu2UyVkjVKLjyKSeuD8dAYCFkso1'. - 'gYMaeWJ40T56cl8yAi/O4FSa2P6kYczIDsgVpAqcDImZPMuAB1'. - 'dkLQtcc8a/bwox8IUHAxZVxGZMouSLVYwKuMkD5IxN+JSdsRJB'. - 'pexuTVgYYM6EoGmxkmg3/hEhNUMr/hd7dqbOzExMn/GRDAxWZc'. - 'j3I8HiXfMjF2FQowKw7pjoN6E/Llw/GBJj8qxVOMlX4ipxc/lY'. - 'kl2zBLkmrTcEzMkoNoRLVidLi/9g+Z3I+1xRHX5EcAihxnbPRv'. - 'OTU9kZSmpKPy9FTGrLimPZ1H+UiyGaF67w6n7E1DwMngFDxGvc'. - 'w70v0xZUby5IxjlIyMssUJrJwVWkXBdbXvSvwEibcSdKCAFI16'. - '4/sc0SRo9cGAGq1DwvQFzV6DVuBiV4zYnlEts6A2TSPcSiXoxo'. - 'QqJCEEFMbQ2b69o5qMiOOPqIMQkagu/aSL7waE8101WFShLjk9'. - 'yxgEvjRUiyYd+gwAjY2J9VpXfZ/JEXLhDp3OR6U4T97+hEnPwx'. - 'tv4HsRjy2tTQSFzQgDUnwSLBQRI+x1ZgcH87Vcv4SF19Kt0ezS'. - '1h9s0Ma25pgr/YJfnLnEysok0+ezjM6EBLldGqKIJYuDRhOQEJ'. - 'Oih8X9Q0xmcXNjlCofBJgn78wxVz7L2YWf8tPPz1hnfjbjzfxN'. - 'qVwutq2etZXUQSXikcXGIgUiUkJSDIQMJgYGJsaB3c7b1qQ4GZ'. - 'xSkdGZIwMeNLfK6uezMnvJK3pLxeVixfvMsyVjSNSO6IV9adPG'. - 'AArkEEz8oUkFmBjYGO80qfd6pCWIayD59wIKcsjcKqufn7JO/S'. - 'xfyi+5c24pey5rZ09mJRNkiDdT/tzbkBr3SYkpMYpgEaIJSYhI'. - 'kSOY1GhilAQk5ntDIojxCZ/kf87Pl85xbuWEnLiUy+cW3NNuJX'. - 'MmY5meKf6mT7wZS+THdOjxlG06tIlIOMZxchSxcFFEGAwAGGME'. - 'jwyZYSnWL3cXWiIUbUI6hO/vxXuFOV84ycmlBWthNeflTjuzTi'. - 'lzJmM5s46Ej0J63/ZoPmoy6PYxtYVNhmfs0mbAND1mmKVMBY1L'. - 'mxA1LN7WgXQbCApNhKJHRIM+DQbv7yQGhjnJ5NgFuXBuxpu5mD'. - 'udm3LPuY7pmZLUE6L1SIJaIPFuDAqyw9lnwDYv6NFHkWJh4ZDB'. - 'wCBFD3uMxsTAwcBAiElpE/KcPg36dIiOvpsRxDCyhmlP2YY9ZU'. - 'v8NMb/1id+FGO0DTztkSXLOONUqeITsMkW2zwnJEIDFhYGx+A1'. - 'kwK4mASkvKDPc3p0iYhRRwYUhZLUTyV6Eu0t4s1Y4kcx6W6KaM'. - 'EZThcXH59RRhGEgIAddnBwNEBKqqpUtWBIF22YDIhJsbEkJqFN'. - 'qLtERHs7GnUkwISEQAf0uj30bY39PzbiC6qrDu2cExJ69Nhhhz'. - '59UlIUipCQOnVi4sjG7ubJBy6um0C+he/0iDHQKIQERYyKFLqr'. - 'SI/W6kJCnvOcrWSLSquC1/Jw9Ks3R0FQKHr0uMc9bnCDGjX69A'. - 'H0XlcJkibN5jOe/alCZStHbjJL9lSMLkXExvCXRiDV6GZEeGeX'. - '3TvvBVQoEjfBL/v0rT75Th7VU5C8gktI6NLlMY+5yU3WWGODDf'. - 'r098tHpNFNH7/2lKdXXdz7efLzVaqJIBOCmK8AJUlI6g0aV+9y'. - '9+p7AR3bMQpTBWPy7yeN6fy0jNwewfpvC9Xe+3kFoUuXe9zj5n'. - 'BusEGHjh6GIAGawC2FWuvSvbbF1maFylZAsC1ISZADBiVNSJrP'. - 'eX73MY//skHP85z5+fnSxQsXj//4n39cmnPn7LbZlsajBmEnBL'. - '1nuEGDG9x4aa5Ldz+h0RCuBqwBv1Wo+7vs9r7n++0MmYeAM+zB'. - '+61EK1QUEnbbtN+9Bh3Hsebn54u//PdfLq9eWl2ZnZ1dSnaSwu'. - 'Pin40b9g3doKE0WoNIl65xj3v75njd3BBubQi6ExKmDWkMRKSl'. - 'tSbVKQcMao1Go5Ugb0+x53nOyZMnSysrKydXLq1cWlxa/McgCB'. - 'Yev3hU+GPrD3I5/q94k3pXYQY58q6B5Bs0HB//neaGx00gyWaz'. - 'VCoV7bquCoKAnZ0dfN/f03egLGj0m3XQNE1jdnY2/+WXXy6trq'. - '6uzP3oR5eCIFi4detW5feXL1vr679Let37zVB3/mQytjXJwmSB'. - 'wikHp9ShY0RESqObwPrr5oBERKhUKly4cIFqtUq9XufmzZtsbW'. - '2hXvuDwTTNtxZq8TyvsLy8vLS4uLgahOHphw8elL69fNlc++qr'. - 'uFOrNXPddm1cczVL5f5P+Lv5MuOJgTGxwYbZpZsCdeAq8M1Bcw'. - 'CGYeC6LtVqlRMnTjAyMkKn0yGXyx0N0LZt03Ec1zCMSrfXO37v'. - 'zp3S769csb+/ciXt1mrNdHf3ltZ6Lca8ZpJsduhtCdb2gEFJoQ'. - 'xADYHuHDS3f32lFEEQUK/XGRkZoVAocP78eZaXl9FaI/Jq25Uk'. - 'yWHAYrHozM/PlxYWFibTND32sFbLXrtyxVz76qukXas1M61WTW'. - 'm99gx+20TdN9jqtfjP7QzOwwYNp037Zd0DukDnIByA1pqdnR2+'. - '++472u02Z8+eZWJiAsMwDsEBRNGBzYJpmsaJEyfyX3zxxdLS0t'. - 'KlVqu1dP3q1cLta9ekU6u1dat1J9b6Sk9kraV1rYXegW7apDYw'. - 'kFY6fPc4MNTw88bwfZ/NzU2UUnieRxAEiAiGcXiXfcigiIjruo'. - 'VyubxkWdbK7fX1xWvffFMInjzBM82uMT5+p++6V1UUrSe7u03t'. - '+8lezlKt3gHyl0aSJDQaDa5fv876+vo+w6FzDq1BpZRsb2/bly'. - '9f9vL5/Njdu3fzG0+eMJHNxsfn532vXN5NPG/7abPZal6/Hvfe'. - 'kroPHfsm98f7AHW9Xo+//vrrlmVZm71+37QNw3JnZ9PK4uJGpV'. - 'pt4Dh+vLGhsrmcfv1iHzu01m89HjIdCon2fb8TBMHtvYeRUn50'. - '1Oj4vqp3Ok1f5LYSadfr9dQfDN642P/XeF2DA+SBAuA4jkOhUK'. - 'BQKESO43S11p3BYBDt7u4y+CtB/i/q7jp1GMiw2AAAAABJRU5E'. - 'rkJggg==' ; - -//========================================================== -// File: ppl_blue.png -//========================================================== - $this->imgdata_large[3][0]= 2284 ; - $this->imgdata_large[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMLFRAiTZAL3gAACHlJREFUeJy9mGtv29YZgJ9zKF'. - 'F3y/Q9jh05tuQkarKgbYasde0UBdZgwNou/Vqga/sD9mP2B4a1'. - 'BbZ9atFPxb5sqOtmXbI19bqsluPYiR3HN90vFEWRZx/IJI5zqa'. - 'x0OwBBSgR5Hj7v+55zSEFXTUgIJyA9C6/9RsjMjAyFIxxJCDc7'. - 'iBqKgyZACGg3G2x9+xXf/fG33P3mC9qNKsp1O+1JdkEnQTdgIO'. - 'ttCSMUi8gj072MnugllAyB9G8rBGi6RsToJTF6iuRoFi1kHKZf'. - '7fB8Iggj0/Dy23D2dakNTR3JDsXPvzstxmZGRMER1EwHhQAEgE'. - 'CLhIkPD6InY9S3djGLJVBtQP1Qb4HDAyoJYQOOZkPx49nhTH9i'. - '7MUBGT7egxkJgd70wZS/CUkoZtA/fRoE1DZ2ACiv52ibReCp4e'. - '7CIEHomxDiuVdGTqUnf/ZeOjR8fpiVXZul5ZrY3bWwbdcLr/dA'. - 'AAIpAwQjUWIjQ+g9HZvswiCgBVF9/SI6OSLGzo0i+oLi6+Utbq'. - '+bKEftgwOE/0Ohocf66M+cBjo22U2RQLIHMhmYnvaOpR9S8bSU'. - 'UqCURGpRkuMZMm9cIvPGJZLj0yBjT2LprkiSkykx9cuXIhOnUs'. - 'm+QNC2XdG02ggBTcvFabsPWwTPpBAChSCgh4kYBpoeplWp47Qs'. - '7EYDt21xINzd5GCAxLExRl89Z+nHjpbKMmjbmkgfDzI0JEW53K'. - 'Jaa6NcAOEX8v52uJzsBlAS6u0hcnTIccPRqhWPCUcLD+s1EaUp'. - 'HCEhEMCyHNpt9SjgIU12A6iw6xb123vYhaaKjB9tlgMD5X+uBp'. - 'zdkpg6azA8EaNQtKlVba+Xez4eCntnJrsDdFsW5nYFpxlFN846'. - 'DXe8utkM4mhi+EgQmjYbS2WqexZKk6BpjwJ2YlK5VjeA3pNDiH'. - 'YjRWPzPE7tmBo8EWwGhkXx+z3uXL7D3rU97LIF8RBEAl6lK/Uo'. - '6JNM1rZ2aTcr3eUgIQOGTgbdwXMGyRejenLYTvQGbAdRuetSud'. - 'OivVuFZgtCEgICghICnZoMhmlVTPR49LCAEkQUhk/B7KXe0MWf'. - 'nxj8xVR/cDheK14WZmtVMJSBnlGoN6FmQq0FLfdwJgORKPHRo/'. - 'Snzx4G0F/FjJ4KiOdmjPCrrx8bffnMybMv9MQGNG3rzlVqtR1B'. - 'sh/CYXCD4Aag1oCW7ZnUOjSp6WFi/QNEB8Y7BfTNjZyCmUvJ0I'. - 'XXT47MTp98Ybon9VZCk8cVazfqlNargsY34G7ByAlIjkHd9CCr'. - 'LbBdiHViUgiECuDKYCdz8b2cywREdiYZOj8zNnLuzOTzx6ODp+'. - 'OaGaqwVzBFqz0Idhz2loE7YEwBLaAJLQcKbW8qjAcBF5Jh0AMP'. - 'IOHe6kxgtb3UMO2OxkF//ffK28nQqxfvm3szrtnDVa799Qb/+v'. - 'NtsbNSpm3tAv8B+w7Ub0FhAyoBcMPec9oK6raXk48ziQBXQcmC'. - 'pT3YqHa0mpEBkTR6wz/Jjo2cy04+fzwxdDquNfQKO7sFUbpu0c'. - 'wp3JoAYsA42Bbkl4GCryUNDEM7Avm6Z/CgSYBWG8pNuFuDu1Wo'. - 'tjoxKIJGeHIiM/jmK9NnX5ycuJQMtUcqXPvLDTa+qIie4hAJ1U'. - 'vdrmO2HaDfB931twJgAn1A4lGT96obPHPLBbhVgUoTHHWo9aAA'. - 'JVAKpyKEmQNzWRENAsL18ycKjAFN/9gCNvzLB/390MMmE7pnDi'. - 'Bvwt0K5Jv3O+0oB22nJ1Vvjb/UMhOpcKknqN1OiMB2DNHU2G5s'. - 'sVndpGJVcZXjX1IAlvw9PmhRQcOFPhsSDkiBrQR1G7brgs0a7D'. - 'ag3FK4rguqBXarI4Nt1SJv5gls7TEWtJDRBO2GwnIs8maevFnA'. - 'Gx6awLZvzeTBu4kFbLigijC47pscpx0xyDfkvtUEnlarCDtrUC'. - 't2HGIhvPHVdVwqjTIrxRU2a5uUrYoP0QZ2gMvACl7+3V/LuKDq'. - 'sJuDy597516+CEezIHXv7vcgXQu2l+Bvn8He9Y4AE4kgk5P9DE'. - 'R6aFdq5Et5Nit3yTf3m9sBcsAN3+D98c0Fit5JawE25r1zg1Fo'. - '5B8GFD7g+nVYnu8EUEop9XTa0N/9dUbqcphP/rDJzbUClVbpgR'. - 'y2fXM3fND95qj75J8AC6BWPINfVSBieK+x+6cS5UCzCLu3oFV9'. - 'GqCMx2NGOp2Znpv7aXZudsool3T5J/179sxVlHJ4kGPrP2COBX'. - '/7DmiApWCjxIMXpYNznYuXM+6TAKWUMppOZzLvv//ery5cuDCT'. - 'SqVS336bCwr1JfAPB9r+2KAFwJS+OcETzZHz/7v3etl6ipz77X'. - 'GAMh6PG+l0OjM3NzczOzs3k0pNnFlbW43+e/GKtMqrblSsF03V'. - 'WHcJA0PjIAzvg9JTze2H67g9DjAwOTmZ+uCDD96anZ2dnZiYmF'. - '5dW41++Lvfa1fnr7qllVK9103mXNTnJgPA+YugsvB3HTaEl+Qs'. - 'AZ/yeHPPDCiTyaRx5syZbGoilV1dW00szC9oV+avusuLy0Xd0X'. - 'MgFkDM+zkYBZEHV8f7wwKu84zmngQoNU0LaZoWUa4K31y5qX/8'. - '4cfyyvwVN5/L10NOKNeg8UmDxoKF5Vfj1xXAgD0JrgAcvBDfel'. - 'a4g4AykUgY6XR6emJiIru2ttZXq9S0K19eUcuLy8WQE8o5OAsN'. - 'Ggsmpl+NpoL1g9X4UBU+C9xDgEKIwNTUVOqdd955M9mbnJ3/cj'. - '6Vu5aTheXCQXNdVeMzAwJSCGEA2XKpnF1cXIzlFnOVhJPIKdR+'. - 'c88ctq4AlVKsrKzw0UcfKcC5uXqzXnNqSzb2pwLxOHP/l7Z/BN'. - 'eB01LKt4HTrusKvGr8jB+hGn8MQAkYQMrfw4Nq/MFPtf+rdvDb'. - 'k8QL+/5Z4Uepxm7bfwHuTAVUWpWaqAAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: ppl_green.png -//========================================================== - $this->imgdata_large[4][0]= 2854 ; - $this->imgdata_large[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMLFQ4hANhluwAACrNJREFUeJytmF1zE1eagJ+3u9'. - 'XdkvUty2AbmLEtEzDBgZ0UpDBOalNTUzU3czl7tct/2n+wt3M/'. - 'NVM12SSTQQSyW2TA+QAJQogtYYFtyfrqL3WfvWj5g8AEjzfvhS'. - 'SXjk8//Zz3Pf3qCMcJAWxMKlT4kH+jwu/FknnJSUItKFHzCrKA'. - 'BggBQx5ziz/wn/yBz3hED4/oaJfSjgVoYjJJgTLTZCjohp7IGT'. - 'k5aZ4kb+bRTR30Q7djj8f/kpPMUSCFedRL6W8e8qMQNE6S4xpv'. - 'c5HrTPFubiJ3ZnlyOXV59rJYU5Z00h1c3d0brxAiUkScRijisk'. - '6XLTyiN3s8HuAJpniXa/q8/pt8Or+0kF8oXJm5YiydWcIpOrJu'. - 'rjOQwd54AQwsMpTJYhPSoYuLQ58An/DnBQSdImXO8avsTPbqpc'. - 'lLp67OXDVzMznZLGxSs2qyIRu4at8gKHQEC50kE1icxqCAdxST'. - 'xjEA44tqaJlERl8uLWvvnX5PHuQfcCdxh5qq0aX76vj4WgWyXO'. - 'QiNgBP8IAaddr08X8+wHFmJSQhBbPAZGoSZSt5wQs6qoNC7UEd'. - '4AEoLIQSCaCCy78Dv8Tiv1hjjW1CRj8XIAgEKqDtt9keboMJZa'. - 'vMjuzQVd3Xr9prTJo+GF/jKZea95R25Lxs8jg5qFGiwDnOS0mW'. - 'NE0rjNRIt3WbklUCA9mV3Zdz8OBT/JfCQLB0SKYVVjGFYSfx/E'. - '26ow4e6uDujlPFQpE0FU6P8qNTHdXJdEdda0qf0itWBVM3pa/3'. - 'ccUlIECJet0cAJoeYk5EZCeS5IwEoerSxccJBwRqFFf38QCTaO'. - 'TRVFKJm3NTbtLNSyh2IkhIXsvLCesEGNCWdmwyruSD/z9kUlRc'. - '3bqNlSxhJNJ43p5JITrOEis8Qtr0cXEpU/JT/pmO18n2vb42pU'. - '3JnDnHMBqyPlpnoAaxhr2llv1ZUBqEGlqYwDQMsskMOcMgVL3Y'. - 'ZOQTHAcQQiIGjHCwCaiovjrv4hbcpKuJJjIcDHm685RGr4GLCx'. - 'YHkAcrLoAoDSLBiAQrMkjqybHJCbxgh+7xAC1MpsgzwRwD3qHL'. - 'WyTIBdlAa6u2rHfXaew06PV78ZZjAwleNnkolECoH5i090wOcY'. - '+TgwYzFHiPi1zkOkXexeAMASnVU+LiyiA1wFUuaqggACLizeWw'. - 'ycMzyssmVYKkbpGyC5T+OUALk2mKLHKWf+ED/az+YW42d66YL+'. - 'aNrmEEzQCFEnKw368EgEvcN1m80eTIQIt0TFOjMJHkzNEBBYPp'. - 'sblf8QHzrORO5JaWZ5ZLl6cuJyyxpNPv4PZdoT+GyIxBfI5uUg'. - 'eJMCwP2/bIHO1JEudcgUUWOceKNq99mCvnzs5PzRcuTV4y5mRO'. - 'SMIjo47z5S7a94oQCNKgJsZwO7D/IDNg3/LLhRNXt4JohBb4aG'. - '82GLdXcf93mQ+Y43r2RHZp+cRy6cqJK4l8MS+tdItaqiYtc0Mm'. - 'QpfJARh98HYh9IiXVcaAo58wGb+LBAjbSPgCOcoSa0wzxXtc08'. - '/pv8mfyL+9MLVQvDJ1JVHJV6SZbFI1qtTsB+KlehRtRTGE8Afo'. - 'P4DRcAxiEudhAHjjzz+ubgX4oHowakHQOlqzICQwyVPITGVOXi'. - 'xfLF6aumzmczl5lHzMff2+fCdPaGttEkXoLQAO9B7C6EugPYby'. - 'gVPjGXc5eIbNAJPjGwiAbaAJUQv8wVG7GROkJFpyOqn/ovgLba'. - '44L0+sDaraXb6jzq7aBQWjBOyUoHcaopOgmaA3IRyNDZnA1HjO'. - 'HSBkr7eEFDAEngHrQCf+/s2A8cSiSkqcKUeeTjwFy2Jd78t3+L'. - 'TR4itIiBLwLQhzkJyB5Cx4HXDaENVQCBAQcRqFIHTRaBIvuYXg'. - 'AdsouuNxEL0ZUBHnSQp66R73zYfUtQ6OytKT8RckQAJQoLtgO5'. - 'BJgj0D/WfgdyHaAHx8THoUcbGx8ciwhUl3bDEiToURPooeI7pH'. - 'MziK9Yd9nU5a6GgKjOH41vsgI4hAcyC5AZkapF+AoYNrjjsuhx'. - 'FbtPmeB5ykyQQzTPAWAQWC8S9oAI0QRRuPb9jkmyMZNAOTklvC'. - 'GGYZaFkGmkVAh8h4DtKFMIBunG+pB5B5AIkGBDsQ+qBiL20caj'. - 'zhJknq5KlgMkLjJHJos4kYEbFJi5vc5eYbATVN02bNWe19+32t'. - 'aJWlFm3wbf8Rz5NbDFJdlOFBF/g7cBf0JkrbBb+F6j1DOduEkU'. - '8bWCOiSofPWadBnSZDWmgUkEMGhZCINut8S/0NBtPptFlZrBSu'. - 'vnt1+ndnflfIp9OJ/279Ubbbd+lP7KBKPoEBsgnqLph/BRzwdS'. - 'LnBUFvHcfdpRsGPAGqwMco6jynz+e0SPKYCHMfLX5VKHwcenR+'. - 'Igd1XTcqlUr+xn/cePv91fevzy8sLO2OtrOpWkqL7gXKSAVRdh'. - 'ZFEmEXoYkwBNqovoc/3GHH3aUR+jwC1oD/AWrANi4hGwyBzqEG'. - 'Vvb77Dgi0eT1VZzJZMxKpVJYXV1dXF1dXVm6sPSvruue3Xzcyj'. - '6/syvDzwj0lNazK6Fj5LFCRZouZpBABj6jXouu3+Np6HNvDHaf'. - 'g91t74msbMuOJicnSSaTKKUQEUQEpRSO69But1/dB0VEm5uby9'. - 'y4cWNpdXX1+sLCworrume//PuXpeqnVeOban0U1PW2kcx+O9L7'. - 'Te9sUB4lWFR9SqNtNGcHx+/RDD2+Am4D94CnQA8OjjlEhMnyJC'. - 'srK8zOzu7BiYioMAzZ2Njg9u3brwIqpSSXy2WXl5eXLly4sOo4'. - 'zoV6vV6oflrVP/7Tx8Hmw1Zb6ydqmpWp7ha8h4O3gjOhzVANmF'. - 'XPMNQWvdDnCXCXuHR+APqH4fbCtm2mp6eZn59H13WJuYXRaKSU'. - 'UiSTyVcBdV3XDcOwRaTU7/en19bWCn/79G+JL/76RbhZ22y7u+'. - '6ahl71nPDz/nO17m7wAxlabFOihy4+DvAcqAMbPzZ3OFzX5dmz'. - 'Z2iahoiosUUVhiGNRgPHcV4GzGQy5uLiYuH8+fMzo9FoslarJW'. - '9+elP75E+fBJu1zY7qqpqBUW3T/niohnVvy+1zm5aVtp+WE2XT'. - 'nrHFzbjh1tYLz3XdPjD4R3BKKba2tqhWq4dzUO3noBPn4H5PKy'. - 'LaO++8U7hx48byhQsXVne7u6tf3/v64t3P7mbq9+odt+OuaWi3'. - 'PLxbW2ytubjbQCgiMnt6VlaurWgz0zM0m02q1WrUaDSUUuqI56'. - 'ivDxE5MCgiYllWtlwuL5mmufLV/a/O/uXPf9Ff1F+80Lv6Yx29'. - '2qHzyZBh3cdvc7gaTZuZkzPh/Py8ACqVSv1/uPZDKXUAGEWRtF'. - 'qtxEcffZTL5XLF+2v39fqjeivshA/TpP83JLwzYFBzcA4370Cc'. - 'S81nTRBUs9lkOByi1GuOPI4Rh3+26JZlnSkWi781DOPXvV4v3+'. - '/2G0R8kSBxB/jew+tERK+c49m2TblcxrZtXNfl+fPneJ6HZVmU'. - 'y2VJJpNyaJ9TSinlOA5bW1u4rntkQA0oAG8D54gb9W3ianxM3A'. - 'e/cn73U3Hq1Cm5du2aPjs7a+ztcSIShmE4ajQa6tatWzQajZ+0'. - 'fbiKI+It4SvijVUj7kL2qvGfgkskEqTTaZmcnDROnTplJhIJTU'. - 'QiwPd9P/Q8T6XTaQzDIAiCfzjP/wFVfszuFqdHXgAAAABJRU5E'. - 'rkJggg==' ; - - -//========================================================== -// File: pp_red.png -//========================================================== - $this->imgdata_small[0][0]= 384 ; - $this->imgdata_small[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. - 'B3RJTUUH0wMJFhouFobZrQAAAQ1JREFUeJyV1dFtwyAQBuD/og'. - 'xQdYxa8gRY6hJ0jK6QdohMkTEuE5wUj5ERen05IoLvID7Jkn2G'. - 'j8MgTMyMXqRlUQBYq9ydmaL2h1cwqD7l30t+L1iwlbYFRegY7I'. - 'SHjkEifGg4ww3aBa/l4+9AhxWWr/dLhEunXUGHq6yGniw3QkOw'. - '3jJ7UBd82n/VVAlAtvsfp98lAj2sAJOhU4AeQ7DC1ubVBODWDJ'. - 'TtCsEWa6u5M1NeFs1NzgdtuhHGtj+9Q2IDppQUAL6Cyrlz0gDN'. - 'ohSMiJCt861672EiAhEhESG3woJ9V9OKTkwRKbdqz4cHmFLSFg'. - 's69+LvAZKdeZ/n89uLnd2g0S+gjd5g8zzjH5Y/eLLi+NPEAAAA'. - 'AElFTkSuQmCC' ; - -//========================================================== -// File: pp_orange.png -//========================================================== - $this->imgdata_small[1][0]= 403 ; - $this->imgdata_small[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. - 'B3RJTUUH0wMJFhwAnApz5AAAASBJREFUeJyN1dFthDAMBuDf7S'. - '3BCm2VCRKpS4QxbhikW6IewzcBqm6Fm6JyH7iEEByCn5AJH38g'. - 'BBIRHNUzBAWAGNfe/SrUGv92CtNt309BrfFdMGPjvt9CD8Fyml'. - 'ZZaDchRgA/59FDMD18pvNoNyHxMnUmgLmPHoJ+CqqfMaNAH22C'. - 'fgqKRwR+GRpxGjXBEiuXDBWQhTK3plxijyWWvtKVS5KNG1xM8I'. - 'OBr7geV1WupDqpmTAPKjCqLhxk/z0PImQmjKrAuI6vMXlhFroD'. - 'vfdqITXWqg2YMSJEAFcReoag6UXU2DzPG8w5t09YYsAyLWvHrL'. - 'HUy6D3XmvMAAhAay8kAJpBosX4vt0G4+4Jam6s6Rz1fgFG0ncA'. - 'f3XfOQcA+Acv5IUSdQw9hgAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: pp_pink.png -//========================================================== - $this->imgdata_small[2][0]= 419 ; - $this->imgdata_small[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. - 'B3RJTUUH0wMJFhsQzvz1RwAAATBJREFUeJyd1MFthDAQheF/oi'. - 'gF+JYWQKICkCJRA1vGtrDbxFbhGvY0HVjCLeS2BeTiHFgTB2wg'. - 'eRISstCnmcG2qCpbuXf3ADBQzWsPfZfS9y9HsEu4/Fo33Wf4Fx'. - 'gxL3a1XkI3wbTNXHLoboVeLFUYDqObYBy+Fw/Uh9DdCmtOwIjF'. - 'YvG76CZoOhNGRmpO8zz30CJoOhMAqlDxFzQLppgXj2XaNlP7FF'. - 'GLL7ccMYCBgZERgCvXLBrfi2DEclmiKZwFY4tp6sW26bVfnede'. - 'e5Hc5dC2bUgrXGKqWrwcXnNYDjmCrcCIiQgDcFYV05kQ8SXmnB'. - 'NgPiVN06wrTDGAhz5EWY/FOccTk+cTnHM/YNu2YYllgFxCWuUM'. - 'ikzGx+2Gc+4N+CoJW8n+5a2UKm2aBoBvGA6L7wfl8aoAAAAASU'. - 'VORK5CYII=' ; - - -//========================================================== -// File: pp_blue.png -//========================================================== - $this->imgdata_small[3][0]= 883 ; - $this->imgdata_small[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAACi1'. - 'BMVEX///8AAAAAADMAAGYAAJkAAMwAAP8zAAAzADMzAGYzAJkz'. - 'AMwzAP9mAABmADNmAGZmAJlmAMxmAP+ZAACZADOZAGaZAJmZAM'. - 'yZAP/MAADMADPMAGbMAJnMAMzMAP//AAD/ADP/AGb/AJn/AMz/'. - 'AP8AMwAAMzMAM2YAM5kAM8wAM/8zMwAzMzMzM2YzM5kzM8wzM/'. - '9mMwBmMzNmM2ZmM5lmM8xmM/+ZMwCZMzOZM2aZM5mZM8yZM//M'. - 'MwDMMzPMM2bMM5nMM8zMM///MwD/MzP/M2b/M5n/M8z/M/8AZg'. - 'AAZjMAZmYAZpkAZswAZv8zZgAzZjMzZmYzZpkzZswzZv9mZgBm'. - 'ZjNmZmZmZplmZsxmZv+ZZgCZZjOZZmaZZpmZZsyZZv/MZgDMZj'. - 'PMZmbMZpnMZszMZv//ZgD/ZjP/Zmb/Zpn/Zsz/Zv8AmQAAmTMA'. - 'mWYAmZkAmcwAmf8zmQAzmTMzmWYzmZkzmcwzmf9mmQBmmTNmmW'. - 'ZmmZlmmcxmmf+ZmQCZmTOZmWaZmZmZmcyZmf/MmQDMmTPMmWbM'. - 'mZnMmczMmf//mQD/mTP/mWb/mZn/mcz/mf8AzAAAzDMAzGYAzJ'. - 'kAzMwAzP8zzAAzzDMzzGYzzJkzzMwzzP9mzABmzDNmzGZmzJlm'. - 'zMxmzP+ZzACZzDOZzGaZzJmZzMyZzP/MzADMzDPMzGbMzJnMzM'. - 'zMzP//zAD/zDP/zGb/zJn/zMz/zP8A/wAA/zMA/2YA/5kA/8wA'. - '//8z/wAz/zMz/2Yz/5kz/8wz//9m/wBm/zNm/2Zm/5lm/8xm//'. - '+Z/wCZ/zOZ/2aZ/5mZ/8yZ///M/wDM/zPM/2bM/5nM/8zM////'. - '/wD//zP//2b//5n//8z///9jJVUgAAAAAXRSTlMAQObYZgAAAA'. - 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. - 'RQfTAwkWGTNerea3AAAAYUlEQVR4nHXNwQ3AIAxDUUfyoROxRZ'. - 'icARin0EBTIP3Hp1gBRqSqYo0seqjZpnngojlWBir5+b8o06lM'. - 'ha5uFKEpDZulV8l52axhVzqaCdxQp32qVSSwC1wN3fYiw7b76w'. - 'bN4SMue4/KbwAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: pp_green.png -//========================================================== - $this->imgdata_small[4][0]= 447 ; - $this->imgdata_small[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. - 'B3RJTUUH0wMJFhkLdq9eKQAAAUxJREFUeJyN1LFVwzAQxvH/8f'. - 'IeDS0FLKABlN6eIwPYAzCHB0gWYI2jj+i1ABUTQN4TRSQ7iiWZ'. - 'qxLn9Mt9ydmiqrSq930AYFiu6YdKrf/hP1gYQn6960PxwBaYMG'. - 'E9UA3dBFtVQjdBOQmBakLennK0CapRwbZRZ3N0O/IeEsqp3HKL'. - 'Smtt5pUZgTPg4gdDud+6xoS97wM2rsxxmRSoTgoVcMZsXJkBho'. - 'SmKqCuOuEtls6nmGMFPTUmxBKx/MeyNfQGLoOOiC2ddsxb1Kzv'. - 'ZzUqu5IXbGDvBJf+hDisi77qFSuhq7Xpuu66TyJLRGbsXVUPxV'. - 'SxsgkzDMt0mKT3/RcjL8C5hHnvJToXY0xYRZ4xnVKsV/S+a8YA'. - 'AvCb3s9g13UhYj+TTo93B3fApRV1FVlEAD6H42DjN9/WvzDYuJ'. - 'dL5b1/ji+/IX8EGWP4AwRii8PdFHTqAAAAAElFTkSuQmCC' ; - } -} - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/imgdata_pushpins.inc.php b/web/public_php/admin/jpgraph/imgdata_pushpins.inc.php new file mode 100644 index 000000000..e59b7427b --- /dev/null +++ b/web/public_php/admin/jpgraph/imgdata_pushpins.inc.php @@ -0,0 +1,517 @@ + 'imgdata_small', + MARK_IMG_SPUSHPIN => 'imgdata_small', + MARK_IMG_LPUSHPIN => 'imgdata_large'); + + protected $colors = array('blue','green','orange','pink','red'); + protected $index = array('red' => 0, 'orange' => 1, 'pink' => 2, 'blue' => 3, 'green' => 4 ) ; + protected $maxidx = 4 ; + protected $imgdata_large, $imgdata_small ; + + function __construct() { + + // The anchor should be where the needle "hits" the paper + // (bottom left corner) + $this->anchor_x = 0; + $this->anchor_y = 1; + + //========================================================== + // File: ppl_red.png + //========================================================== + $this->imgdata_large[0][0]= 2490 ; + $this->imgdata_large[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMKBh4Ryh89CgAACUdJREFUeJy9mNtTFFcexz+/7p'. + '4Lw1wZJKDGCAwmDAqUySamcCq1ed6k9mn3UfMP7F+1T3nYqn2J'. + 'lZdoDEjpbq0KG8EBFBFBEJye6Zmenkv32Ydu5GYiUMmeqq6uqT'. + '6Xz3zP73aOcIKmAQkIFyD3N/jrBPwlKjLQEglVlJKyUjR3u7cc'. + 'WLoP3/4dvv03LNrQ8I6x1rFbDML9kOmHvh7IRHU9JKmUSG8vpF'. + 'IoXX/TV0AiEM5A5jT0noFMFMJHXUt/d5f9TUAbhtQ3cPFruDog'. + '8klHMnmO0dGYe/myOJGINEwTz3F2higFXgy8PpAkOC+h8hoaCt'. + '4ppHFcQAWSgOQlyI/p+lUjmRxWAwNJd3xca/f34yoFi4tgmjtD'. + 'NIFkJ4xcgBCgVqEBFJ9DqcZea/gNAAVEg7AOGYnHe9XoaJd3+X'. + 'LISSSwnz6lsbKCZ9sHh4UVdBkwdA6cPwNnIfJPmC3Ctgft3wwQ'. + 'QPkvTZJJnbExzfvsM2nMzVG7e5fG48d4lnXwTwEYCjJxuHQBog'. + 'BHUfKkgAIIhiGk06hTp/Dm5qS1uYlXLvtWd4gPgIiCrAEcVckT'. + 'Ab5p7TaYJrK1hQaEenrwSiVfQdc91P0kSp7Ii89D5ksY/kAkLy'. + 'IZXFdXkQjS1YUSEbdcRu168V6+HTUNIKJDRwdE+sBIQmP9Ld59'. + 'bEBA3of4F/D+uXb7rGaaCSmXI3pPj64PDaHCYfEqFVSjgWo2D2'. + '73XlJNQTgCyQykIuBWoNKEeh1aLXBPBCggGdBOgxZVSjoajVhH'. + 'o5HWlIpq4bCQSgm9vXhK4ZZKh5SUYygp4J1EQVUD9xlU18BJQD'. + 'bUbJ5T5XJStyxN9fSI099P3baxV1dRloW2h2ivx/yakg2ot6F1'. + 'EkCa4G1D+zVEq5ArKTWM42Q6HUczQV7U66w9e0ZpdRXlOIQ5vF'. + 'VHUXILKify4jiEzkOqC3peQMoBQymFlMt4Dx6wUSxSsm2UZXEK'. + 'P30QvOUt8/2Sd78CdWwFDTA+gsw3cOlPcPUD+CQB52oQ21RKXM'. + 'eRhGXhOg7VoKrx8KuS4ygZhVg3ZI8FGIfwR9BVgAtfwxdXdP3L'. + '86nUR91dXelNXTeWWy10paQHX602YAP1ADASAL7LJvFtMpOCc0'. + 'cG3FHuGlz6Gr4YEpnoTCbzsdHRbOzy5RCRiLRMk5rjyOtAimwA'. + 'U4U3SurBN/0wnAASBCVDIKpB4kiAB5Ub0/UvO9LpPAMDGfn005'. + 'AxPCzxep3Q6iqPLUseBoufCZRsAE6g5g5kKIDfKUj3wnpAG8QB'. + '/Z1OIqANQuI65AtwNScyYXR2XlAXL2YZHzcklRKWl5GVFXFtGx'. + 'MoAiV/EQaAGH6BUQNWgQpwFngv+Ca8KUAQEBcwgTJHyMV7679R'. + 'XS8YqdSI6u/PMD5ukMtJY3GR2uQkr5aXeWVZOEALmA8WsIAxfL'. + 'd0goVLAdCOd+/YpgqeVtBv4yiA++q/RKKXixe7GB8PSyoljcVF'. + 'yg8fyubyMpulEk2lyAIfAAvAC+B+oOQFoAt/+0rAejB/EzjNri'. + 'vvqNnCd64jxcE39V8spnP+vMbAgDSePKE2NcXm06dslMuUlcID'. + 'TuFvqwXMBU8N39bGgRR+ki0Dz4L5DSAe9NGD7zq+6kcN1L6H2b'. + 'ao5WWaQHllRTafPmWrVMJUimoAQrBYJFjQwre7B6A8YAi8LCgD'. + '5DVo6/hbb/iHK1KggvFeD3hHziQKEMuiNTNDbXGRTdtmw7Iwla'. + 'KGH0oqwbscLOoG46rAY6AOzRhY74PT6QuUKEN4PegXxd/yEDTT'. + 'YMWOk+oEaLkuFdNk0zTZwjfkavDUArXWgGXgFb4dEShXhfYqlI'. + 'ow3w9rg3B6ED60IOOA5oEYQBrcpG+mj9bg0VG8GMJhVDZLyzAo'. + 'VSq8rFYxXXefcjVgG9+uisDrXUCApoKSBcUHMBmHhfcgNwhtD3'. + 'q9IG6Lr15b4OUTmPwBJt8JqGuapp05o0mhoHnptLQfPsR+8IBK'. + 'uYyNH3yr+B77LHheA3tK1Ta+IrMeTL2C6Xl48TOsNWDDgAz7s5'. + '/r+krP/eddCsbj8fDQ4GBm9MqVvvRXX2VULBayRGRzaYn1SoWa'. + 'UjgB4PIB5QK4ZgBXBKaAHxQsrED1H7CRgCUPwgHZDqACmhWwXv'. + '2aDRqGYeRyufS169cvThQKV88PDuYbW1vJ5VRK+5euqxWlPMdX'. + 'SRqgreHbZGN3ijfKBXBTAeh2Fdwi2MofshP/dvKwCmKhp4m83Y'. + 'vj8Xg4l8tlCoXC0MTExMTFkZE/1m37wvLGRvKRacoD1209E7Fc'. + 'pZwYREOQqEJ4z3HskHLsz4AoXykPIBSN0t3dTTQafROoHdumXC'. + '4fjoMiog0ODiauX7+eLxQKV3O53ETdti88nJnJ3rl505ifmWm3'. + 'arWSodR8GNbycDoNHy5C5jFold1k8d+DyvELNwg93d18/vnn9P'. + 'X1oes6nufx/Plz7t+/fxhQKSWJRCI5NjaWHxkZKdj1+sjSwkJm'. + '+uZN/dZ337VqCwullGUVdZjsgIUC5LqhrUPvCugWuApeApPAzY'. + 'PKHWyaphGNRunt7WVwcBARwfM8Ojo6sCzrMKBhGLphGFEF2Wq1'. + '2jc7M5OZ/vHH0MPbt93awkJJmeZsC6ZaMK3DCwvWdNioQUb5B6'. + 'AdBR+9SzkAz/NwHIeXL18iIui6TjgcJplMMjY2th8wHo+Hh4aG'. + 'MsPDw6fddru7+Phxx51bt/RbN260qwsLpZhlFZsw9QJ+2Pbrga'. + 'oJG2FY2oKwuTtVEz9uV34NbqdtbW0xPT1NNBoF4MyZM1y5coWu'. + 'rq5dQBHRcrlc4tq1a/l8Pj9RMs38ndu3Ez//9JNXLRZNyuXZJk'. + 'xVYKoExQpsK/+IaAuYb7no8zjC/R+A4zisrq7u+53NZjl16tQ+'. + 'QIlEIslsNpuPRCJXZ2dnh2/duNFRW1oy07a96MKd575yxRqU1B'. + '5vPMpF5HHa1tYW9+7do7Ozc/eQpZTSQ6FQt1Lq8pMnT/5w7969'. + 'nuLcXE1rNufO9fRMhlKpOyvt9qPtVmvb25fFfvvWbrepVCqHwo'. + 'xaX19vff/996ZhGC8qlkW9Wt1Onz073fXxxz+6MB+9e9dUjuO+'. + '7ebq9wLdB9hoNCrr6+s/4wf3FCJW3fPmTZhXsNWCprjuW66Dfr'. + '928KAfBhJAEgiJSLuzs7OSTqctoFkqlZRt26j/I+L/AGjPTN4d'. + 'Nqn4AAAAAElFTkSuQmCC' ; + + //========================================================== + // File: ppl_orange.png + //========================================================== + $this->imgdata_large[1][0]= 2753 ; + $this->imgdata_large[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMLFQ0VCkHCzQAACk5JREFUeJytmGtzG0d2hp8zNw'. + 'AEcRdJ6EJK9FL0CqZUm9jWbkwq3vhDstl8dmLvz8rP2H8Q75ZT'. + 'pkRfpLgqsS6WIFEKGYkiSBCDO+banQ8DUpRWEkklXQUUqlCDfv'. + 'rp857pgfAOQ4AMOJdg4R/hX96Hf06bvDc5iT07i8yeg8ksiIAI'. + '4TBi/ds9/vivD/njapNHvRBfHXMu410AM+BUoVSF05NQsi1sO4'. + '8402AXwLQTuP31OAZO2aG0MEn14iSlnI1z3LnMk8IZYJyBwjIs'. + '/TWsVIWPJkvMFS4zMfMhUp5BsoCpAAEBLYKaMFGn00jBxnvu02'. + '35+JHmSJEnBpQEcPo38MmCxd/nS9Ry71Ga/g1W9a8gn0GsHkgA'. + '6DGjxkqb5CoO+YxF3A3p+jGjQUzoK+L/V0ADzFMwtSR8eLbAr8'. + 'uXOTf9NzhTc0geSLUQcYHgYEH786RMg0zWJHV2Aitv4x/HpHVS'. + 'QA2YBqTTGIUq5qkPMWaWkVwPnPtAA/BevmZcjxaaUtHh8pJJGu'. + 'DpCB9FvT7A7YT7S3p5vFMNzmWo/O0MSx/Ms3TqI8r59zFTfUQe'. + 'I7SBODE3tnfoIxYnNHligwik0zAzDdVpyKbA8sff5YAeMEwgkV'. + 'cufQeTJzZoCsaFLKXPTnNpoUTNsSgJmNoGsuNQjIDwYD2HlnZy'. + 'k++yxTKXZfKTU8zOpjhneeQYkorSmGERtIlICBKRbLX+y98YN3'. + 'ADcNIm+bJD4U3pPnmbEaRgYVRTGBkDSSsmxKfY7ZLuDJA4hdjl'. + 'JEgyBB2SJOvQ9RzTpNKoEwNq0CNFvOXR3/HxMgYVPObaz8kPmh'. + 'hkEWMatAfRONGGvLizyOE9P8KkpwhPDAgQKJQbELUD0oOIhbbH'. + 'JeVTmowxjAgZutB5AoOngA+2DdYrcTyOyYZP9+QpBvI29vwEhb'. + 'It042BVQgDy9KTMfkwQG1A9ACCLlgBBGUwxxoc52WDh2ATyEPp'. + '1hoaPvrEBh0Dq5an9OUsl/9hylk5b5c+mowLc4E2Jtw4Eoljyf'. + 'ogA/AGEAagNRjGyUxOmEycyVA5EWDBxrmUp3ytLIv/NJP69Goh'. + '+9mFydIvS5PZYkvH1oY/RFtKymlwBFQAgQd+kAA6qSQ8pvn2mp'. + 'SkJkuVFHPHBnQMrEt5Sl+e4/Lvp51PF1PF5Xy6WMvOWZXMom8z'. + 'OZTQ8+j5sbQiMEwopsCIwRtBGIJSCdzbTGo9NimkDcgdC7Bg49'. + 'TG5n4/nfr0Si77WdYp1YzyZEkWPdteaEnB7pPqBTxuIf/VgciE'. + 'SgasCPwh+GNIkaNNag1RiPge5pEhMQVjfoLcF+eoXSvbKxedwn'. + 'LKzC3KWbOi5/sW5a44/SHFUSgVA7SCzRG0AvA9mPOgFIETgu4n'. + 'Ww0wNQWFAqRSL6D2ZQYBdDrQ7R7jXiwgRcvIL02makuTmWtpM/'. + '+BlLMl5vuWzLVEuwH6oYnR1KS8kJINGXMM2YdfRlALoQoQQKeb'. + 'bDVwoMdxQMaLCwLo96HZTF5HbrEhmOftianfZisfzueKv7ZmrX'. + 'MsjhxKXZGBjzyeEHmSE3oWiggtyVGmE8DTIXTC5NxgAxOAGUM8'. + 'fun9mnSSLQ/CxNzOTgJ3LIMgoGwkKBiiMyaVviHVkdCO4FEKNv'. + 'LQzWBYHfITPa4UBVM0LR/WB7ARJsdDDTjA6deYFIFUOimJ3d0E'. + 'sNdLavYYgBpthqKcjiiJRO8K6CK0CsJTjfQAGaJtD9vQFAxNNQ'. + '1FB0yBAfA8gdMAIagLoCVAen0M00zMOTYShNDtoHs9CAIUoI4E'. + '1IBihCdNhsMhsj6NuV7BCC2IBpBqQaaFOENCCeiEsO1BO4RQgy'. + 'I5Hm4k4oIU9MrgZSAdBeTabZz+ODxKQRRBFBJo6IUc51anYRQo'. + 'dto+24FNxYCiaWKkQsj00KkO4gxRRkAngJ868M0u3OkkM+hxQA'. + 'cQ7YD7GO5XYSsPZybh/TCkFIYY+kWniTW4Q7jXgHvHMhiRpmuW'. + 'ca08GZkkZ/nY6TZMNhCnf2CuPoDVJvxpB+q9BHA8Ag1uH+oP4c'. + 'YEPCzDwmzSLquShHW/E0YRbG/BjZtw40hAy7aNzJlzRn75E6N0'. + 'qiwTzafI7kOU3gWrhzZC2iHcbsPqLlxvJnCt4KC1RYAL3I5hzY'. + 'Xv/huePYCtITQMKEnyB4KQvMURuJvw889HGSwUCs7CwkLpo6tX'. + 'Ty/+7nel6VLGDn/8N9m+eZuo1UP8iNhLau6b3RfmOsHBGTUYw9'. + 'WBNeDrGB4+h/4qNLKwTnLbHj9CJw/6GoIh9Jpvq0HHcayFhYXi'. + 'l3/4w9LK8vLKexfma3G/mb/3n1njTivS7tNQaaU1grQDjJ868D'. + 'Axx6vmxnBrY9C9IcSbSXbavNjb/S3eN6/0m1JcKBScixcvllZW'. + 'Vi6uLC8v12q1v/M8b/HxVjP//YYr32yE4dYWvShO0ogi14xwxq'. + 'F4rbnxZ3cMjtpvEEeMvwA0TdOYn5/PffHFF7Vr166tvPeLXyx7'. + 'nrd4+/btyg/frFo//Xgncnd67qCn78earQqcmYD3fSi1wPCTSV'. + '3gzqvm9uFOMl5nUAqFQn5paal26dKla57vf7D+6FHph9VV88af'. + 'vgq79bo70e3VT2l9A3hYg4UiRALVHTCHSZvYBm4A//6quf8zoG'. + '3bpuM4acMwKr1+//SDe/dK31+/bv90/Xrcq9fduNW6rbVeC+E7'. + 'gWdD2DKg4UEpBmPcm10RuScida31ntb62HAigoigDw6Gh0axWH'. + 'QWFhZKi4uLZ+I4PrVer2e+u37dXPvqq6hbr7tOp1NXWq89h6/b'. + '8FBB34WGBesdcPrj38lkMkGlUuml0+mu53nR3t4eo9HoSLhMJk'. + 'OlUiGdTuN5Hq7rvgA0TdO4cOFC7vPPP6/VarXldqdTu7m2lrv7'. + '7beq++BBO263b/tKrfWSXlbvwJ6CuAtDgTYiaBFMw6BSqfDxxx'. + '+rarWqGo0GN2/eZGtrC6XenAkRoVKpcPXqVWZmZmg0Gty6desF'. + 'oIhIOp3Ol8vlmmVZK3fv3Lm09uc/Zwbr653ccPgoNIzvnmn99Z'. + '7W9QG46lAaM5mM2l95GIYUi0VOnz7N7OwsWmsymQzyuse5Q8Mw'. + 'DNLpNDMzM5w/f/7A6AGgUkoajYa9urpayOXzUz/fvZutr68Pim'. + 'F4/2y1+n2o9Q/ru7uPesPhXnyo4A+vfHp6mmazybNnz9jZ2UFr'. + 'TbPZJAhe+8/aS0Mphed5NBoNABqNBqPR6MWBVWstvu/nnj9/Pv'. + 'vo0aPq5uZmPBgM/qcwPf39xV/9ajU1M3Nvq9PZaw8GoT50PjdN'. + 'k6mpKa5cucL58+eJ45j19XWePHnCzs4OnudhmiaWZRGGIVH05r'. + 'yEYYjrumxubrKxsfFyDQJ6NBp1Pc+7C4jWumBaVm+kVL2l1H2l'. + '1G6otS+H6V6z8u3tbVzXpdFooJRicXGRqakptre3uXXr1ltrcT'. + 'Qa8ezZszemWAE9rfUdYBOwtVLRbrPZ+48ff+wDvuu6Sr3MB4Dr'. + 'uty6desgfa1WC3iRyrNnz4pSSmezWUzTfGtYtNYcdvC/9sMlgP'. + 'n5N4cAAAAASUVORK5CYII=' ; + + //========================================================== + // File: ppl_pink.png + //========================================================== + $this->imgdata_large[2][0]= 2779 ; + $this->imgdata_large[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMLFQolY9lkpgAACmhJREFUeJy9mOtzFNl5h5+3b9'. + 'Mz0kzPBWmEVtIiWYhIiC0HCDhB8lb8ISk7nzdZ5+/zJ/8BTmpT'. + '660CZLwG1pVFgBkgGIHECEaa+/T9nHzQCCQuRpCNz6mp6g893U'. + '8/c37ve3qEjxiC4OA4n/Lp/EUu/tsMM/+aEWduVBx7WhdkShcY'. + 'xUH2zo0Dwod/5N6vf8V//PoGdx8M8EOFPtK9jI8BdHCcMuVSmf'. + 'LxHLmSZdm2U8xIbmKETDGDZZnIy4dBbCynyGhphurEDBOlHFnn'. + 'qPcyPxTOwDCOccw7w5nlBRZWylI+ny/mZ6rL1dzUZ5/IWGZU3D'. + 'ZIOMQDDaJcHDVGWUbJBi9odVr0QoVSPzigIEaZ8vgSS/8wZU3/'. + 'k1fylipz5dLM2WlrZqHKaGCKbEbontq3KAKWQyZfZKTgYqc9Bp'. + '2I2PcJ4ogk/UEBQcwipbFZmT13vDBx8fhnE1Ofnp9yJopFyT3X'. + 'yANfks0QHSQMDaL37pOxMLIu2UyVkjVKLjyKSeuD8dAYCFkso1'. + 'gYMaeWJ40T56cl8yAi/O4FSa2P6kYczIDsgVpAqcDImZPMuAB1'. + 'dkLQtcc8a/bwox8IUHAxZVxGZMouSLVYwKuMkD5IxN+JSdsRJB'. + 'pexuTVgYYM6EoGmxkmg3/hEhNUMr/hd7dqbOzExMn/GRDAxWZc'. + 'j3I8HiXfMjF2FQowKw7pjoN6E/Llw/GBJj8qxVOMlX4ipxc/lY'. + 'kl2zBLkmrTcEzMkoNoRLVidLi/9g+Z3I+1xRHX5EcAihxnbPRv'. + 'OTU9kZSmpKPy9FTGrLimPZ1H+UiyGaF67w6n7E1DwMngFDxGvc'. + 'w70v0xZUby5IxjlIyMssUJrJwVWkXBdbXvSvwEibcSdKCAFI16'. + '4/sc0SRo9cGAGq1DwvQFzV6DVuBiV4zYnlEts6A2TSPcSiXoxo'. + 'QqJCEEFMbQ2b69o5qMiOOPqIMQkagu/aSL7waE8101WFShLjk9'. + 'yxgEvjRUiyYd+gwAjY2J9VpXfZ/JEXLhDp3OR6U4T97+hEnPwx'. + 'tv4HsRjy2tTQSFzQgDUnwSLBQRI+x1ZgcH87Vcv4SF19Kt0ezS'. + '1h9s0Ma25pgr/YJfnLnEysok0+ezjM6EBLldGqKIJYuDRhOQEJ'. + 'Oih8X9Q0xmcXNjlCofBJgn78wxVz7L2YWf8tPPz1hnfjbjzfxN'. + 'qVwutq2etZXUQSXikcXGIgUiUkJSDIQMJgYGJsaB3c7b1qQ4GZ'. + 'xSkdGZIwMeNLfK6uezMnvJK3pLxeVixfvMsyVjSNSO6IV9adPG'. + 'AArkEEz8oUkFmBjYGO80qfd6pCWIayD59wIKcsjcKqufn7JO/S'. + 'xfyi+5c24pey5rZ09mJRNkiDdT/tzbkBr3SYkpMYpgEaIJSYhI'. + 'kSOY1GhilAQk5ntDIojxCZ/kf87Pl85xbuWEnLiUy+cW3NNuJX'. + 'MmY5meKf6mT7wZS+THdOjxlG06tIlIOMZxchSxcFFEGAwAGGME'. + 'jwyZYSnWL3cXWiIUbUI6hO/vxXuFOV84ycmlBWthNeflTjuzTi'. + 'lzJmM5s46Ej0J63/ZoPmoy6PYxtYVNhmfs0mbAND1mmKVMBY1L'. + 'mxA1LN7WgXQbCApNhKJHRIM+DQbv7yQGhjnJ5NgFuXBuxpu5mD'. + 'udm3LPuY7pmZLUE6L1SIJaIPFuDAqyw9lnwDYv6NFHkWJh4ZDB'. + 'wCBFD3uMxsTAwcBAiElpE/KcPg36dIiOvpsRxDCyhmlP2YY9ZU'. + 'v8NMb/1id+FGO0DTztkSXLOONUqeITsMkW2zwnJEIDFhYGx+A1'. + 'kwK4mASkvKDPc3p0iYhRRwYUhZLUTyV6Eu0t4s1Y4kcx6W6KaM'. + 'EZThcXH59RRhGEgIAddnBwNEBKqqpUtWBIF22YDIhJsbEkJqFN'. + 'qLtERHs7GnUkwISEQAf0uj30bY39PzbiC6qrDu2cExJ69Nhhhz'. + '59UlIUipCQOnVi4sjG7ubJBy6um0C+he/0iDHQKIQERYyKFLqr'. + 'SI/W6kJCnvOcrWSLSquC1/Jw9Ks3R0FQKHr0uMc9bnCDGjX69A'. + 'H0XlcJkibN5jOe/alCZStHbjJL9lSMLkXExvCXRiDV6GZEeGeX'. + '3TvvBVQoEjfBL/v0rT75Th7VU5C8gktI6NLlMY+5yU3WWGODDf'. + 'r098tHpNFNH7/2lKdXXdz7efLzVaqJIBOCmK8AJUlI6g0aV+9y'. + '9+p7AR3bMQpTBWPy7yeN6fy0jNwewfpvC9Xe+3kFoUuXe9zj5n'. + 'BusEGHjh6GIAGawC2FWuvSvbbF1maFylZAsC1ISZADBiVNSJrP'. + 'eX73MY//skHP85z5+fnSxQsXj//4n39cmnPn7LbZlsajBmEnBL'. + '1nuEGDG9x4aa5Ldz+h0RCuBqwBv1Wo+7vs9r7n++0MmYeAM+zB'. + '+61EK1QUEnbbtN+9Bh3Hsebn54u//PdfLq9eWl2ZnZ1dSnaSwu'. + 'Pin40b9g3doKE0WoNIl65xj3v75njd3BBubQi6ExKmDWkMRKSl'. + 'tSbVKQcMao1Go5Ugb0+x53nOyZMnSysrKydXLq1cWlxa/McgCB'. + 'Yev3hU+GPrD3I5/q94k3pXYQY58q6B5Bs0HB//neaGx00gyWaz'. + 'VCoV7bquCoKAnZ0dfN/f03egLGj0m3XQNE1jdnY2/+WXXy6trq'. + '6uzP3oR5eCIFi4detW5feXL1vr679Let37zVB3/mQytjXJwmSB'. + 'wikHp9ShY0RESqObwPrr5oBERKhUKly4cIFqtUq9XufmzZtsbW'. + '2hXvuDwTTNtxZq8TyvsLy8vLS4uLgahOHphw8elL69fNlc++qr'. + 'uFOrNXPddm1cczVL5f5P+Lv5MuOJgTGxwYbZpZsCdeAq8M1Bcw'. + 'CGYeC6LtVqlRMnTjAyMkKn0yGXyx0N0LZt03Ec1zCMSrfXO37v'. + 'zp3S769csb+/ciXt1mrNdHf3ltZ6Lca8ZpJsduhtCdb2gEFJoQ'. + 'xADYHuHDS3f32lFEEQUK/XGRkZoVAocP78eZaXl9FaI/Jq25Uk'. + 'yWHAYrHozM/PlxYWFibTND32sFbLXrtyxVz76qukXas1M61WTW'. + 'm99gx+20TdN9jqtfjP7QzOwwYNp037Zd0DukDnIByA1pqdnR2+'. + '++472u02Z8+eZWJiAsMwDsEBRNGBzYJpmsaJEyfyX3zxxdLS0t'. + 'KlVqu1dP3q1cLta9ekU6u1dat1J9b6Sk9kraV1rYXegW7apDYw'. + 'kFY6fPc4MNTw88bwfZ/NzU2UUnieRxAEiAiGcXiXfcigiIjruo'. + 'VyubxkWdbK7fX1xWvffFMInjzBM82uMT5+p++6V1UUrSe7u03t'. + '+8lezlKt3gHyl0aSJDQaDa5fv876+vo+w6FzDq1BpZRsb2/bly'. + '9f9vL5/Njdu3fzG0+eMJHNxsfn532vXN5NPG/7abPZal6/Hvfe'. + 'kroPHfsm98f7AHW9Xo+//vrrlmVZm71+37QNw3JnZ9PK4uJGpV'. + 'pt4Dh+vLGhsrmcfv1iHzu01m89HjIdCon2fb8TBMHtvYeRUn50'. + '1Oj4vqp3Ok1f5LYSadfr9dQfDN642P/XeF2DA+SBAuA4jkOhUK'. + 'BQKESO43S11p3BYBDt7u4y+CtB/i/q7jp1GMiw2AAAAABJRU5E'. + 'rkJggg==' ; + + //========================================================== + // File: ppl_blue.png + //========================================================== + $this->imgdata_large[3][0]= 2284 ; + $this->imgdata_large[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMLFRAiTZAL3gAACHlJREFUeJy9mGtv29YZgJ9zKF'. + 'F3y/Q9jh05tuQkarKgbYasde0UBdZgwNou/Vqga/sD9mP2B4a1'. + 'BbZ9atFPxb5sqOtmXbI19bqsluPYiR3HN90vFEWRZx/IJI5zqa'. + 'x0OwBBSgR5Hj7v+55zSEFXTUgIJyA9C6/9RsjMjAyFIxxJCDc7'. + 'iBqKgyZACGg3G2x9+xXf/fG33P3mC9qNKsp1O+1JdkEnQTdgIO'. + 'ttCSMUi8gj072MnugllAyB9G8rBGi6RsToJTF6iuRoFi1kHKZf'. + '7fB8Iggj0/Dy23D2dakNTR3JDsXPvzstxmZGRMER1EwHhQAEgE'. + 'CLhIkPD6InY9S3djGLJVBtQP1Qb4HDAyoJYQOOZkPx49nhTH9i'. + '7MUBGT7egxkJgd70wZS/CUkoZtA/fRoE1DZ2ACiv52ibReCp4e'. + '7CIEHomxDiuVdGTqUnf/ZeOjR8fpiVXZul5ZrY3bWwbdcLr/dA'. + 'AAIpAwQjUWIjQ+g9HZvswiCgBVF9/SI6OSLGzo0i+oLi6+Utbq'. + '+bKEftgwOE/0Ohocf66M+cBjo22U2RQLIHMhmYnvaOpR9S8bSU'. + 'UqCURGpRkuMZMm9cIvPGJZLj0yBjT2LprkiSkykx9cuXIhOnUs'. + 'm+QNC2XdG02ggBTcvFabsPWwTPpBAChSCgh4kYBpoeplWp47Qs'. + '7EYDt21xINzd5GCAxLExRl89Z+nHjpbKMmjbmkgfDzI0JEW53K'. + 'Jaa6NcAOEX8v52uJzsBlAS6u0hcnTIccPRqhWPCUcLD+s1EaUp'. + 'HCEhEMCyHNpt9SjgIU12A6iw6xb123vYhaaKjB9tlgMD5X+uBp'. + 'zdkpg6azA8EaNQtKlVba+Xez4eCntnJrsDdFsW5nYFpxlFN846'. + 'DXe8utkM4mhi+EgQmjYbS2WqexZKk6BpjwJ2YlK5VjeA3pNDiH'. + 'YjRWPzPE7tmBo8EWwGhkXx+z3uXL7D3rU97LIF8RBEAl6lK/Uo'. + '6JNM1rZ2aTcr3eUgIQOGTgbdwXMGyRejenLYTvQGbAdRuetSud'. + 'OivVuFZgtCEgICghICnZoMhmlVTPR49LCAEkQUhk/B7KXe0MWf'. + 'nxj8xVR/cDheK14WZmtVMJSBnlGoN6FmQq0FLfdwJgORKPHRo/'. + 'Snzx4G0F/FjJ4KiOdmjPCrrx8bffnMybMv9MQGNG3rzlVqtR1B'. + 'sh/CYXCD4Aag1oCW7ZnUOjSp6WFi/QNEB8Y7BfTNjZyCmUvJ0I'. + 'XXT47MTp98Ybon9VZCk8cVazfqlNargsY34G7ByAlIjkHd9CCr'. + 'LbBdiHViUgiECuDKYCdz8b2cywREdiYZOj8zNnLuzOTzx6ODp+'. + 'OaGaqwVzBFqz0Idhz2loE7YEwBLaAJLQcKbW8qjAcBF5Jh0AMP'. + 'IOHe6kxgtb3UMO2OxkF//ffK28nQqxfvm3szrtnDVa799Qb/+v'. + 'NtsbNSpm3tAv8B+w7Ub0FhAyoBcMPec9oK6raXk48ziQBXQcmC'. + 'pT3YqHa0mpEBkTR6wz/Jjo2cy04+fzwxdDquNfQKO7sFUbpu0c'. + 'wp3JoAYsA42Bbkl4GCryUNDEM7Avm6Z/CgSYBWG8pNuFuDu1Wo'. + 'tjoxKIJGeHIiM/jmK9NnX5ycuJQMtUcqXPvLDTa+qIie4hAJ1U'. + 'vdrmO2HaDfB931twJgAn1A4lGT96obPHPLBbhVgUoTHHWo9aAA'. + 'JVAKpyKEmQNzWRENAsL18ycKjAFN/9gCNvzLB/390MMmE7pnDi'. + 'Bvwt0K5Jv3O+0oB22nJ1Vvjb/UMhOpcKknqN1OiMB2DNHU2G5s'. + 'sVndpGJVcZXjX1IAlvw9PmhRQcOFPhsSDkiBrQR1G7brgs0a7D'. + 'ag3FK4rguqBXarI4Nt1SJv5gls7TEWtJDRBO2GwnIs8maevFnA'. + 'Gx6awLZvzeTBu4kFbLigijC47pscpx0xyDfkvtUEnlarCDtrUC'. + 't2HGIhvPHVdVwqjTIrxRU2a5uUrYoP0QZ2gMvACl7+3V/LuKDq'. + 'sJuDy597516+CEezIHXv7vcgXQu2l+Bvn8He9Y4AE4kgk5P9DE'. + 'R6aFdq5Et5Nit3yTf3m9sBcsAN3+D98c0Fit5JawE25r1zg1Fo'. + '5B8GFD7g+nVYnu8EUEop9XTa0N/9dUbqcphP/rDJzbUClVbpgR'. + 'y2fXM3fND95qj75J8AC6BWPINfVSBieK+x+6cS5UCzCLu3oFV9'. + 'GqCMx2NGOp2Znpv7aXZudsool3T5J/179sxVlHJ4kGPrP2COBX'. + '/7DmiApWCjxIMXpYNznYuXM+6TAKWUMppOZzLvv//ery5cuDCT'. + 'SqVS336bCwr1JfAPB9r+2KAFwJS+OcETzZHz/7v3etl6ipz77X'. + 'GAMh6PG+l0OjM3NzczOzs3k0pNnFlbW43+e/GKtMqrblSsF03V'. + 'WHcJA0PjIAzvg9JTze2H67g9DjAwOTmZ+uCDD96anZ2dnZiYmF'. + '5dW41++Lvfa1fnr7qllVK9103mXNTnJgPA+YugsvB3HTaEl+Qs'. + 'AZ/yeHPPDCiTyaRx5syZbGoilV1dW00szC9oV+avusuLy0Xd0X'. + 'MgFkDM+zkYBZEHV8f7wwKu84zmngQoNU0LaZoWUa4K31y5qX/8'. + '4cfyyvwVN5/L10NOKNeg8UmDxoKF5Vfj1xXAgD0JrgAcvBDfel'. + 'a4g4AykUgY6XR6emJiIru2ttZXq9S0K19eUcuLy8WQE8o5OAsN'. + 'Ggsmpl+NpoL1g9X4UBU+C9xDgEKIwNTUVOqdd955M9mbnJ3/cj'. + '6Vu5aTheXCQXNdVeMzAwJSCGEA2XKpnF1cXIzlFnOVhJPIKdR+'. + 'c88ctq4AlVKsrKzw0UcfKcC5uXqzXnNqSzb2pwLxOHP/l7Z/BN'. + 'eB01LKt4HTrusKvGr8jB+hGn8MQAkYQMrfw4Nq/MFPtf+rdvDb'. + 'k8QL+/5Z4Uepxm7bfwHuTAVUWpWaqAAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: ppl_green.png + //========================================================== + $this->imgdata_large[4][0]= 2854 ; + $this->imgdata_large[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMLFQ4hANhluwAACrNJREFUeJytmF1zE1eagJ+3u9'. + 'XdkvUty2AbmLEtEzDBgZ0UpDBOalNTUzU3czl7tct/2n+wt3M/'. + 'NVM12SSTQQSyW2TA+QAJQogtYYFtyfrqL3WfvWj5g8AEjzfvhS'. + 'SXjk8//Zz3Pf3qCMcJAWxMKlT4kH+jwu/FknnJSUItKFHzCrKA'. + 'BggBQx5ziz/wn/yBz3hED4/oaJfSjgVoYjJJgTLTZCjohp7IGT'. + 'k5aZ4kb+bRTR30Q7djj8f/kpPMUSCFedRL6W8e8qMQNE6S4xpv'. + 'c5HrTPFubiJ3ZnlyOXV59rJYU5Z00h1c3d0brxAiUkScRijisk'. + '6XLTyiN3s8HuAJpniXa/q8/pt8Or+0kF8oXJm5YiydWcIpOrJu'. + 'rjOQwd54AQwsMpTJYhPSoYuLQ58An/DnBQSdImXO8avsTPbqpc'. + 'lLp67OXDVzMznZLGxSs2qyIRu4at8gKHQEC50kE1icxqCAdxST'. + 'xjEA44tqaJlERl8uLWvvnX5PHuQfcCdxh5qq0aX76vj4WgWyXO'. + 'QiNgBP8IAaddr08X8+wHFmJSQhBbPAZGoSZSt5wQs6qoNC7UEd'. + '4AEoLIQSCaCCy78Dv8Tiv1hjjW1CRj8XIAgEKqDtt9keboMJZa'. + 'vMjuzQVd3Xr9prTJo+GF/jKZea95R25Lxs8jg5qFGiwDnOS0mW'. + 'NE0rjNRIt3WbklUCA9mV3Zdz8OBT/JfCQLB0SKYVVjGFYSfx/E'. + '26ow4e6uDujlPFQpE0FU6P8qNTHdXJdEdda0qf0itWBVM3pa/3'. + 'ccUlIECJet0cAJoeYk5EZCeS5IwEoerSxccJBwRqFFf38QCTaO'. + 'TRVFKJm3NTbtLNSyh2IkhIXsvLCesEGNCWdmwyruSD/z9kUlRc'. + '3bqNlSxhJNJ43p5JITrOEis8Qtr0cXEpU/JT/pmO18n2vb42pU'. + '3JnDnHMBqyPlpnoAaxhr2llv1ZUBqEGlqYwDQMsskMOcMgVL3Y'. + 'ZOQTHAcQQiIGjHCwCaiovjrv4hbcpKuJJjIcDHm685RGr4GLCx'. + 'YHkAcrLoAoDSLBiAQrMkjqybHJCbxgh+7xAC1MpsgzwRwD3qHL'. + 'WyTIBdlAa6u2rHfXaew06PV78ZZjAwleNnkolECoH5i090wOcY'. + '+TgwYzFHiPi1zkOkXexeAMASnVU+LiyiA1wFUuaqggACLizeWw'. + 'ycMzyssmVYKkbpGyC5T+OUALk2mKLHKWf+ED/az+YW42d66YL+'. + 'aNrmEEzQCFEnKw368EgEvcN1m80eTIQIt0TFOjMJHkzNEBBYPp'. + 'sblf8QHzrORO5JaWZ5ZLl6cuJyyxpNPv4PZdoT+GyIxBfI5uUg'. + 'eJMCwP2/bIHO1JEudcgUUWOceKNq99mCvnzs5PzRcuTV4y5mRO'. + 'SMIjo47z5S7a94oQCNKgJsZwO7D/IDNg3/LLhRNXt4JohBb4aG'. + '82GLdXcf93mQ+Y43r2RHZp+cRy6cqJK4l8MS+tdItaqiYtc0Mm'. + 'QpfJARh98HYh9IiXVcaAo58wGb+LBAjbSPgCOcoSa0wzxXtc08'. + '/pv8mfyL+9MLVQvDJ1JVHJV6SZbFI1qtTsB+KlehRtRTGE8Afo'. + 'P4DRcAxiEudhAHjjzz+ubgX4oHowakHQOlqzICQwyVPITGVOXi'. + 'xfLF6aumzmczl5lHzMff2+fCdPaGttEkXoLQAO9B7C6EugPYby'. + 'gVPjGXc5eIbNAJPjGwiAbaAJUQv8wVG7GROkJFpyOqn/ovgLba'. + '44L0+sDaraXb6jzq7aBQWjBOyUoHcaopOgmaA3IRyNDZnA1HjO'. + 'HSBkr7eEFDAEngHrQCf+/s2A8cSiSkqcKUeeTjwFy2Jd78t3+L'. + 'TR4itIiBLwLQhzkJyB5Cx4HXDaENVQCBAQcRqFIHTRaBIvuYXg'. + 'AdsouuNxEL0ZUBHnSQp66R73zYfUtQ6OytKT8RckQAJQoLtgO5'. + 'BJgj0D/WfgdyHaAHx8THoUcbGx8ciwhUl3bDEiToURPooeI7pH'. + 'MziK9Yd9nU5a6GgKjOH41vsgI4hAcyC5AZkapF+AoYNrjjsuhx'. + 'FbtPmeB5ykyQQzTPAWAQWC8S9oAI0QRRuPb9jkmyMZNAOTklvC'. + 'GGYZaFkGmkVAh8h4DtKFMIBunG+pB5B5AIkGBDsQ+qBiL20caj'. + 'zhJknq5KlgMkLjJHJos4kYEbFJi5vc5eYbATVN02bNWe19+32t'. + 'aJWlFm3wbf8Rz5NbDFJdlOFBF/g7cBf0JkrbBb+F6j1DOduEkU'. + '8bWCOiSofPWadBnSZDWmgUkEMGhZCINut8S/0NBtPptFlZrBSu'. + 'vnt1+ndnflfIp9OJ/279Ubbbd+lP7KBKPoEBsgnqLph/BRzwdS'. + 'LnBUFvHcfdpRsGPAGqwMco6jynz+e0SPKYCHMfLX5VKHwcenR+'. + 'Igd1XTcqlUr+xn/cePv91fevzy8sLO2OtrOpWkqL7gXKSAVRdh'. + 'ZFEmEXoYkwBNqovoc/3GHH3aUR+jwC1oD/AWrANi4hGwyBzqEG'. + 'Vvb77Dgi0eT1VZzJZMxKpVJYXV1dXF1dXVm6sPSvruue3Xzcyj'. + '6/syvDzwj0lNazK6Fj5LFCRZouZpBABj6jXouu3+Np6HNvDHaf'. + 'g91t74msbMuOJicnSSaTKKUQEUQEpRSO69But1/dB0VEm5uby9'. + 'y4cWNpdXX1+sLCworrume//PuXpeqnVeOban0U1PW2kcx+O9L7'. + 'Te9sUB4lWFR9SqNtNGcHx+/RDD2+Am4D94CnQA8OjjlEhMnyJC'. + 'srK8zOzu7BiYioMAzZ2Njg9u3brwIqpSSXy2WXl5eXLly4sOo4'. + 'zoV6vV6oflrVP/7Tx8Hmw1Zb6ydqmpWp7ha8h4O3gjOhzVANmF'. + 'XPMNQWvdDnCXCXuHR+APqH4fbCtm2mp6eZn59H13WJuYXRaKSU'. + 'UiSTyVcBdV3XDcOwRaTU7/en19bWCn/79G+JL/76RbhZ22y7u+'. + '6ahl71nPDz/nO17m7wAxlabFOihy4+DvAcqAMbPzZ3OFzX5dmz'. + 'Z2iahoiosUUVhiGNRgPHcV4GzGQy5uLiYuH8+fMzo9FoslarJW'. + '9+elP75E+fBJu1zY7qqpqBUW3T/niohnVvy+1zm5aVtp+WE2XT'. + 'nrHFzbjh1tYLz3XdPjD4R3BKKba2tqhWq4dzUO3noBPn4H5PKy'. + 'LaO++8U7hx48byhQsXVne7u6tf3/v64t3P7mbq9+odt+OuaWi3'. + 'PLxbW2ytubjbQCgiMnt6VlaurWgz0zM0m02q1WrUaDSUUuqI56'. + 'ivDxE5MCgiYllWtlwuL5mmufLV/a/O/uXPf9Ff1F+80Lv6Yx29'. + '2qHzyZBh3cdvc7gaTZuZkzPh/Py8ACqVSv1/uPZDKXUAGEWRtF'. + 'qtxEcffZTL5XLF+2v39fqjeivshA/TpP83JLwzYFBzcA4370Cc'. + 'S81nTRBUs9lkOByi1GuOPI4Rh3+26JZlnSkWi781DOPXvV4v3+'. + '/2G0R8kSBxB/jew+tERK+c49m2TblcxrZtXNfl+fPneJ6HZVmU'. + 'y2VJJpNyaJ9TSinlOA5bW1u4rntkQA0oAG8D54gb9W3ianxM3A'. + 'e/cn73U3Hq1Cm5du2aPjs7a+ztcSIShmE4ajQa6tatWzQajZ+0'. + 'fbiKI+It4SvijVUj7kL2qvGfgkskEqTTaZmcnDROnTplJhIJTU'. + 'QiwPd9P/Q8T6XTaQzDIAiCfzjP/wFVfszuFqdHXgAAAABJRU5E'. + 'rkJggg==' ; + + + //========================================================== + // File: pp_red.png + //========================================================== + $this->imgdata_small[0][0]= 384 ; + $this->imgdata_small[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. + 'B3RJTUUH0wMJFhouFobZrQAAAQ1JREFUeJyV1dFtwyAQBuD/og'. + 'xQdYxa8gRY6hJ0jK6QdohMkTEuE5wUj5ERen05IoLvID7Jkn2G'. + 'j8MgTMyMXqRlUQBYq9ydmaL2h1cwqD7l30t+L1iwlbYFRegY7I'. + 'SHjkEifGg4ww3aBa/l4+9AhxWWr/dLhEunXUGHq6yGniw3QkOw'. + '3jJ7UBd82n/VVAlAtvsfp98lAj2sAJOhU4AeQ7DC1ubVBODWDJ'. + 'TtCsEWa6u5M1NeFs1NzgdtuhHGtj+9Q2IDppQUAL6Cyrlz0gDN'. + 'ohSMiJCt861672EiAhEhESG3woJ9V9OKTkwRKbdqz4cHmFLSFg'. + 's69+LvAZKdeZ/n89uLnd2g0S+gjd5g8zzjH5Y/eLLi+NPEAAAA'. + 'AElFTkSuQmCC' ; + + //========================================================== + // File: pp_orange.png + //========================================================== + $this->imgdata_small[1][0]= 403 ; + $this->imgdata_small[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. + 'B3RJTUUH0wMJFhwAnApz5AAAASBJREFUeJyN1dFthDAMBuDf7S'. + '3BCm2VCRKpS4QxbhikW6IewzcBqm6Fm6JyH7iEEByCn5AJH38g'. + 'BBIRHNUzBAWAGNfe/SrUGv92CtNt309BrfFdMGPjvt9CD8Fyml'. + 'ZZaDchRgA/59FDMD18pvNoNyHxMnUmgLmPHoJ+CqqfMaNAH22C'. + 'fgqKRwR+GRpxGjXBEiuXDBWQhTK3plxijyWWvtKVS5KNG1xM8I'. + 'OBr7geV1WupDqpmTAPKjCqLhxk/z0PImQmjKrAuI6vMXlhFroD'. + 'vfdqITXWqg2YMSJEAFcReoag6UXU2DzPG8w5t09YYsAyLWvHrL'. + 'HUy6D3XmvMAAhAay8kAJpBosX4vt0G4+4Jam6s6Rz1fgFG0ncA'. + 'f3XfOQcA+Acv5IUSdQw9hgAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: pp_pink.png + //========================================================== + $this->imgdata_small[2][0]= 419 ; + $this->imgdata_small[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. + 'B3RJTUUH0wMJFhsQzvz1RwAAATBJREFUeJyd1MFthDAQheF/oi'. + 'gF+JYWQKICkCJRA1vGtrDbxFbhGvY0HVjCLeS2BeTiHFgTB2wg'. + 'eRISstCnmcG2qCpbuXf3ADBQzWsPfZfS9y9HsEu4/Fo33Wf4Fx'. + 'gxL3a1XkI3wbTNXHLoboVeLFUYDqObYBy+Fw/Uh9DdCmtOwIjF'. + 'YvG76CZoOhNGRmpO8zz30CJoOhMAqlDxFzQLppgXj2XaNlP7FF'. + 'GLL7ccMYCBgZERgCvXLBrfi2DEclmiKZwFY4tp6sW26bVfnede'. + 'e5Hc5dC2bUgrXGKqWrwcXnNYDjmCrcCIiQgDcFYV05kQ8SXmnB'. + 'NgPiVN06wrTDGAhz5EWY/FOccTk+cTnHM/YNu2YYllgFxCWuUM'. + 'ikzGx+2Gc+4N+CoJW8n+5a2UKm2aBoBvGA6L7wfl8aoAAAAASU'. + 'VORK5CYII=' ; + + + //========================================================== + // File: pp_blue.png + //========================================================== + $this->imgdata_small[3][0]= 883 ; + $this->imgdata_small[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAACi1'. + 'BMVEX///8AAAAAADMAAGYAAJkAAMwAAP8zAAAzADMzAGYzAJkz'. + 'AMwzAP9mAABmADNmAGZmAJlmAMxmAP+ZAACZADOZAGaZAJmZAM'. + 'yZAP/MAADMADPMAGbMAJnMAMzMAP//AAD/ADP/AGb/AJn/AMz/'. + 'AP8AMwAAMzMAM2YAM5kAM8wAM/8zMwAzMzMzM2YzM5kzM8wzM/'. + '9mMwBmMzNmM2ZmM5lmM8xmM/+ZMwCZMzOZM2aZM5mZM8yZM//M'. + 'MwDMMzPMM2bMM5nMM8zMM///MwD/MzP/M2b/M5n/M8z/M/8AZg'. + 'AAZjMAZmYAZpkAZswAZv8zZgAzZjMzZmYzZpkzZswzZv9mZgBm'. + 'ZjNmZmZmZplmZsxmZv+ZZgCZZjOZZmaZZpmZZsyZZv/MZgDMZj'. + 'PMZmbMZpnMZszMZv//ZgD/ZjP/Zmb/Zpn/Zsz/Zv8AmQAAmTMA'. + 'mWYAmZkAmcwAmf8zmQAzmTMzmWYzmZkzmcwzmf9mmQBmmTNmmW'. + 'ZmmZlmmcxmmf+ZmQCZmTOZmWaZmZmZmcyZmf/MmQDMmTPMmWbM'. + 'mZnMmczMmf//mQD/mTP/mWb/mZn/mcz/mf8AzAAAzDMAzGYAzJ'. + 'kAzMwAzP8zzAAzzDMzzGYzzJkzzMwzzP9mzABmzDNmzGZmzJlm'. + 'zMxmzP+ZzACZzDOZzGaZzJmZzMyZzP/MzADMzDPMzGbMzJnMzM'. + 'zMzP//zAD/zDP/zGb/zJn/zMz/zP8A/wAA/zMA/2YA/5kA/8wA'. + '//8z/wAz/zMz/2Yz/5kz/8wz//9m/wBm/zNm/2Zm/5lm/8xm//'. + '+Z/wCZ/zOZ/2aZ/5mZ/8yZ///M/wDM/zPM/2bM/5nM/8zM////'. + '/wD//zP//2b//5n//8z///9jJVUgAAAAAXRSTlMAQObYZgAAAA'. + 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. + 'RQfTAwkWGTNerea3AAAAYUlEQVR4nHXNwQ3AIAxDUUfyoROxRZ'. + 'icARin0EBTIP3Hp1gBRqSqYo0seqjZpnngojlWBir5+b8o06lM'. + 'ha5uFKEpDZulV8l52axhVzqaCdxQp32qVSSwC1wN3fYiw7b76w'. + 'bN4SMue4/KbwAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: pp_green.png + //========================================================== + $this->imgdata_small[4][0]= 447 ; + $this->imgdata_small[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. + 'B3RJTUUH0wMJFhkLdq9eKQAAAUxJREFUeJyN1LFVwzAQxvH/8f'. + 'IeDS0FLKABlN6eIwPYAzCHB0gWYI2jj+i1ABUTQN4TRSQ7iiWZ'. + 'qxLn9Mt9ydmiqrSq930AYFiu6YdKrf/hP1gYQn6960PxwBaYMG'. + 'E9UA3dBFtVQjdBOQmBakLennK0CapRwbZRZ3N0O/IeEsqp3HKL'. + 'Smtt5pUZgTPg4gdDud+6xoS97wM2rsxxmRSoTgoVcMZsXJkBho'. + 'SmKqCuOuEtls6nmGMFPTUmxBKx/MeyNfQGLoOOiC2ddsxb1Kzv'. + 'ZzUqu5IXbGDvBJf+hDisi77qFSuhq7Xpuu66TyJLRGbsXVUPxV'. + 'SxsgkzDMt0mKT3/RcjL8C5hHnvJToXY0xYRZ4xnVKsV/S+a8YA'. + 'AvCb3s9g13UhYj+TTo93B3fApRV1FVlEAD6H42DjN9/WvzDYuJ'. + 'dL5b1/ji+/IX8EGWP4AwRii8PdFHTqAAAAAElFTkSuQmCC' ; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/imgdata_squares.inc b/web/public_php/admin/jpgraph/imgdata_squares.inc deleted file mode 100644 index bfae58d0c..000000000 --- a/web/public_php/admin/jpgraph/imgdata_squares.inc +++ /dev/null @@ -1,151 +0,0 @@ -'imgdata'); - - var $colors = array('bluegreen','blue','green', - 'lightblue','orange','purple','red','yellow'); - var $index = array('bluegreen' =>2,'blue'=>5,'green'=>6, - 'lightblue'=>0,'orange'=>7,'purple'=>4,'red'=>3,'yellow'=>1); - var $maxidx = 7 ; - var $imgdata ; - - function ImgData_Squares () { -//========================================================== -//sq_lblue.png -//========================================================== - $this->imgdata[0][0]= 362 ; - $this->imgdata[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAABm'. - 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. - 'B3RJTUUH0wMLFgojiPx/ygAAAPdJREFUeNpj/P377+kzHx89/c'. - 'VAHNBQ5VBX52HavPWWjg6nnDQbkXoUFTnnL7zD9PPXrz17HxCj'. - 'E6Jn6fL7H7/+ZWJgYCBGJ7IeBgYGJogofp1oehDa8OjE1IOiDa'. - 'tOrHoYGBhY0NwD0enirMDAwMDFxYRVD7ptyDrNTAU0NXix6sGu'. - 'jYGBgZOT9e/f/0xMjFyczFgVsGAKCfBza2kKzpl3hIuT1c9Xb/'. - 'PW58/foKchJqx6tmy98vbjj8cvPm/afMnXW1JShA2fNmQ9EBFc'. - 'Opnw6MGjkwm/Hlw6mQjqwaqTiRg9mDoZv//4M2/+UYJ64EBWgj'. - 'cm2hwA8l24oNDl+DMAAAAASUVORK5CYII=' ; - -//========================================================== -//sq_yellow.png -//========================================================== - $this->imgdata[1][0]= 338 ; - $this->imgdata[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAWl'. - 'BMVEX////+/+H+/9/9/9v8/8P8/8H8/7v8/7n6/4P5/335/3n5'. - '/3X4/1f4/1P3/031/w30/wn0/wPt+ADp9ADm8ADk7gDc5gDa5A'. - 'DL1ADFzgCwuACqsgClrABzeAC9M0MzAAAAAWJLR0QAiAUdSAAA'. - 'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEDlOgDj'. - 'EAAAB+SURBVHjaVcpbCsQgDEDRGERGKopjDa2a/W9zfLWj9/Nw'. - 'Ac21ZRBOtZlRN9ApzSYFaDUj79KIorRDbJNO9bN/GUSh2ZRJFJ'. - 'S18iorURBiyksO8buT0zkfYaUqzI91ckfhWhoGXTLzsDjI68Sz'. - 'pGMjrzPzauA/iXk1AtykmvgBC8UcWUdc9HkAAAAASUVORK5CYI'. - 'I=' ; - -//========================================================== -//sq_blgr.png -//========================================================== - $this->imgdata[2][0]= 347 ; - $this->imgdata[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAZl'. - 'BMVEX////0+vv0+vrz+fry+frv+Png7e/d7e/a6+zY6+250tSz'. - '0tSyztCtztGM0NWIz9SDzdNfsLVcrrRZrbJOp61MpqtIr7dHn6'. - 'RErrZArLQ6q7M2g4kygYcsp68npa4ctr8QZ20JnqepKsl4AAAA'. - 'AWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU'. - '1FB9MDCxYEByp8tpUAAAB7SURBVHjaVcjRFoIgDADQWZpWJpjY'. - 'MsnG//9kzIFn3McLzfArDA3MndFjrhvgfDHFBEB9pt0CVzwrY3'. - 'n2yicjhY4vTSp0nbXtN+hCV53SHDWe61dZY+/9463r2XuifHAM'. - '0SoH+6xEcovUlCfefeFSIwfTTQ3fB+pi4lV/bTIgvmaA7a0AAA'. - 'AASUVORK5CYII=' ; - -//========================================================== -//sq_red.png -//========================================================== - $this->imgdata[3][0]= 324 ; - $this->imgdata[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'. - 'BMVEX////++Pn99/j99ff99fb98/X98/T98PL55uj43+P24+bw'. - 'kKPvjaHviJ3teJHpxMnoL2Pjs73WW3rWNljVWXnUVnbUK1DTJk'. - '3SUHPOBz/KQmmxPVmuOFasNFOeIkWVka/fAAAAAWJLR0QAiAUd'. - 'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEHd'. - 'ceT+8AAABtSURBVHjaVchbAkMwEAXQq6i3VrQiQfa/zDYTw8z5'. - 'PCjGt9JVWFt1XWPh1fWNdfDy+tq6WPfRUPENNKnSnXNWPB4uv2'. - 'b54nSZ8jHrMtOxvWZZZtpD4KP6xLkO9/AhzhaCOMhJh68cOjzV'. - '/K/4Ac2cG+nBcaRuAAAAAElFTkSuQmCC' ; - -//========================================================== -//sq_pink.png -//========================================================== - $this->imgdata[4][0]= 445 ; - $this->imgdata[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAApV'. - 'BMVEX////6+Pz69/v49Pr38/r17/jr4+/l3Onj2efh1ua/L+i+'. - 'q8m+Lue9Lua8qsS8LuW8LeS7pca5LOG4LN+2Y9O2YNW1ZdO1Kt'. - 'y0atC0aNGzb82zbc6zKtuzKdqycsuwa8qtJtOISZ2GRpuFN6GE'. - 'NqCDQpmCMZ+BPpd/LJ1/K519S5B9Jpx9Jpt9JZt6RY11BJZ1BJ'. - 'V0BJV0BJRzBJNvNoRtIoJUEmdZ/XbrAAAAAWJLR0QAiAUdSAAA'. - 'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYDF3iKMD'. - 'YAAACeSURBVHjaVczbEoIgGARgCiMtrexoWpaa2FHUgvd/tH4Y'. - 'BnEvv9ldhNPradPnnGBUTtPDzMRPSIF46SaBoR25dYjz3I20Lb'. - 'ek6BgQz73Il7KKpSgCO0pTHU0886J1sCe0ZYbALjGhjFnEM2es'. - 'VhZVI4d+B1QtfnV47ywCEaKeP/p7JdLejSYt0j6NIiOq1wJZIs'. - 'QTDA0ELHwhPBCwyR/Cni9cOmzJtwAAAABJRU5ErkJggg==' ; - -//========================================================== -//sq_blue.png -//========================================================== - $this->imgdata[5][0]= 283 ; - $this->imgdata[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAQl'. - 'BMVEX////4+fz39/z19vvy8vru7/ni4+7g4fHW1ue8vteXmt6B'. - 'hdhiZ7FQVaZETcxCSJo1Oq4zNoMjKakhJHcKFaMEC2jRVYdWAA'. - 'AAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0'. - 'SU1FB9MDCxYDN0PkEP4AAABfSURBVHjaVchHAoAgDATAVcCCIF'. - 'j4/1elJEjmOFDHKVgDv4iz640gLs+LMF6ZUv/VqcXXplU7Gqpy'. - 'PFzBT5qml9NzlOX259riWHlS4kOffviHD8PQYZx2EFMPRkw+9Q'. - 'FSnRPeWEDzKAAAAABJRU5ErkJggg==' ; - -//========================================================== -//sq_green.png -//========================================================== - $this->imgdata[6][0]= 325 ; - $this->imgdata[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'. - 'BMVEX////2+vX1+vX1+fT0+fPz+PPx9/Dv9u7u9e3h7uHe697a'. - '6dnO2s3I1sa10LOvza2ay5aEwYBWlE9TqE5Tkk1RkEpMrUJMg0'. - 'hKiUNGpEFBojw8oTcsbScaYBMWlwmMT0NtAAAAAWJLR0QAiAUd'. - 'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEFd'. - 'nFx90AAABuSURBVHjaVc9HAoAgDADB2HuJWLDx/2cKBITscW4L'. - '5byzMIWtZobNDZIZtrcCGZsRQ8GwvRSRNxIiMuysODKG3alikl'. - 'ueOPlpKTLBaRmOZxQxaXlfb5ZWI9om4WntrXiDSJzp7SBkwMQa'. - 'FEy0VR/NAB2kNuj7rgAAAABJRU5ErkJggg==' ; - -//========================================================== -//sq_orange.png -//========================================================== - $this->imgdata[7][0]= 321 ; - $this->imgdata[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAUV'. - 'BMVEX/////8+n/8uf/8OP/59H/5Mv/zqH/zJ3/ypv/yJf/vYH/'. - 'u33/uXn/n0n/nUX/m0H/lzn/ljf/lDP/kS3/kCv/iR//hxv/fg'. - 'n/fAX/eQDYZgDW6ia5AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAL'. - 'EgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEJIgbx+cAAAB2SURBVH'. - 'jaVczRCoQwDETRbLAWLZSGUA35/w/dVI0283i4DODew3YESmWW'. - 'kg5gWkoQAe6TleUQI/66Sy7i56+kLk7cht2N0+hcnJgQu0SqiC'. - '1SzSIbzWSi6gavqJ63wSduRi2f+kwyD5rEukwCdZ1kGAMGMfv9'. - 'AbWuGMOr5COSAAAAAElFTkSuQmCC' ; - } -} - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/imgdata_squares.inc.php b/web/public_php/admin/jpgraph/imgdata_squares.inc.php new file mode 100644 index 000000000..895dc936d --- /dev/null +++ b/web/public_php/admin/jpgraph/imgdata_squares.inc.php @@ -0,0 +1,150 @@ +'imgdata'); + + protected $colors = array('bluegreen','blue','green', + 'lightblue','orange','purple','red','yellow'); + protected $index = array('bluegreen' =>2,'blue'=>5,'green'=>6, + 'lightblue'=>0,'orange'=>7,'purple'=>4,'red'=>3,'yellow'=>1); + protected $maxidx = 7 ; + protected $imgdata ; + + function ImgData_Squares () { + //========================================================== + //sq_lblue.png + //========================================================== + $this->imgdata[0][0]= 362 ; + $this->imgdata[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAABm'. + 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. + 'B3RJTUUH0wMLFgojiPx/ygAAAPdJREFUeNpj/P377+kzHx89/c'. + 'VAHNBQ5VBX52HavPWWjg6nnDQbkXoUFTnnL7zD9PPXrz17HxCj'. + 'E6Jn6fL7H7/+ZWJgYCBGJ7IeBgYGJogofp1oehDa8OjE1IOiDa'. + 'tOrHoYGBhY0NwD0enirMDAwMDFxYRVD7ptyDrNTAU0NXix6sGu'. + 'jYGBgZOT9e/f/0xMjFyczFgVsGAKCfBza2kKzpl3hIuT1c9Xb/'. + 'PW58/foKchJqx6tmy98vbjj8cvPm/afMnXW1JShA2fNmQ9EBFc'. + 'Opnw6MGjkwm/Hlw6mQjqwaqTiRg9mDoZv//4M2/+UYJ64EBWgj'. + 'cm2hwA8l24oNDl+DMAAAAASUVORK5CYII=' ; + + //========================================================== + //sq_yellow.png + //========================================================== + $this->imgdata[1][0]= 338 ; + $this->imgdata[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAWl'. + 'BMVEX////+/+H+/9/9/9v8/8P8/8H8/7v8/7n6/4P5/335/3n5'. + '/3X4/1f4/1P3/031/w30/wn0/wPt+ADp9ADm8ADk7gDc5gDa5A'. + 'DL1ADFzgCwuACqsgClrABzeAC9M0MzAAAAAWJLR0QAiAUdSAAA'. + 'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEDlOgDj'. + 'EAAAB+SURBVHjaVcpbCsQgDEDRGERGKopjDa2a/W9zfLWj9/Nw'. + 'Ac21ZRBOtZlRN9ApzSYFaDUj79KIorRDbJNO9bN/GUSh2ZRJFJ'. + 'S18iorURBiyksO8buT0zkfYaUqzI91ckfhWhoGXTLzsDjI68Sz'. + 'pGMjrzPzauA/iXk1AtykmvgBC8UcWUdc9HkAAAAASUVORK5CYI'. + 'I=' ; + + //========================================================== + //sq_blgr.png + //========================================================== + $this->imgdata[2][0]= 347 ; + $this->imgdata[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAZl'. + 'BMVEX////0+vv0+vrz+fry+frv+Png7e/d7e/a6+zY6+250tSz'. + '0tSyztCtztGM0NWIz9SDzdNfsLVcrrRZrbJOp61MpqtIr7dHn6'. + 'RErrZArLQ6q7M2g4kygYcsp68npa4ctr8QZ20JnqepKsl4AAAA'. + 'AWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU'. + '1FB9MDCxYEByp8tpUAAAB7SURBVHjaVcjRFoIgDADQWZpWJpjY'. + 'MsnG//9kzIFn3McLzfArDA3MndFjrhvgfDHFBEB9pt0CVzwrY3'. + 'n2yicjhY4vTSp0nbXtN+hCV53SHDWe61dZY+/9463r2XuifHAM'. + '0SoH+6xEcovUlCfefeFSIwfTTQ3fB+pi4lV/bTIgvmaA7a0AAA'. + 'AASUVORK5CYII=' ; + + //========================================================== + //sq_red.png + //========================================================== + $this->imgdata[3][0]= 324 ; + $this->imgdata[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'. + 'BMVEX////++Pn99/j99ff99fb98/X98/T98PL55uj43+P24+bw'. + 'kKPvjaHviJ3teJHpxMnoL2Pjs73WW3rWNljVWXnUVnbUK1DTJk'. + '3SUHPOBz/KQmmxPVmuOFasNFOeIkWVka/fAAAAAWJLR0QAiAUd'. + 'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEHd'. + 'ceT+8AAABtSURBVHjaVchbAkMwEAXQq6i3VrQiQfa/zDYTw8z5'. + 'PCjGt9JVWFt1XWPh1fWNdfDy+tq6WPfRUPENNKnSnXNWPB4uv2'. + 'b54nSZ8jHrMtOxvWZZZtpD4KP6xLkO9/AhzhaCOMhJh68cOjzV'. + '/K/4Ac2cG+nBcaRuAAAAAElFTkSuQmCC' ; + + //========================================================== + //sq_pink.png + //========================================================== + $this->imgdata[4][0]= 445 ; + $this->imgdata[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAApV'. + 'BMVEX////6+Pz69/v49Pr38/r17/jr4+/l3Onj2efh1ua/L+i+'. + 'q8m+Lue9Lua8qsS8LuW8LeS7pca5LOG4LN+2Y9O2YNW1ZdO1Kt'. + 'y0atC0aNGzb82zbc6zKtuzKdqycsuwa8qtJtOISZ2GRpuFN6GE'. + 'NqCDQpmCMZ+BPpd/LJ1/K519S5B9Jpx9Jpt9JZt6RY11BJZ1BJ'. + 'V0BJV0BJRzBJNvNoRtIoJUEmdZ/XbrAAAAAWJLR0QAiAUdSAAA'. + 'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYDF3iKMD'. + 'YAAACeSURBVHjaVczbEoIgGARgCiMtrexoWpaa2FHUgvd/tH4Y'. + 'BnEvv9ldhNPradPnnGBUTtPDzMRPSIF46SaBoR25dYjz3I20Lb'. + 'ek6BgQz73Il7KKpSgCO0pTHU0886J1sCe0ZYbALjGhjFnEM2es'. + 'VhZVI4d+B1QtfnV47ywCEaKeP/p7JdLejSYt0j6NIiOq1wJZIs'. + 'QTDA0ELHwhPBCwyR/Cni9cOmzJtwAAAABJRU5ErkJggg==' ; + + //========================================================== + //sq_blue.png + //========================================================== + $this->imgdata[5][0]= 283 ; + $this->imgdata[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAQl'. + 'BMVEX////4+fz39/z19vvy8vru7/ni4+7g4fHW1ue8vteXmt6B'. + 'hdhiZ7FQVaZETcxCSJo1Oq4zNoMjKakhJHcKFaMEC2jRVYdWAA'. + 'AAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0'. + 'SU1FB9MDCxYDN0PkEP4AAABfSURBVHjaVchHAoAgDATAVcCCIF'. + 'j4/1elJEjmOFDHKVgDv4iz640gLs+LMF6ZUv/VqcXXplU7Gqpy'. + 'PFzBT5qml9NzlOX259riWHlS4kOffviHD8PQYZx2EFMPRkw+9Q'. + 'FSnRPeWEDzKAAAAABJRU5ErkJggg==' ; + + //========================================================== + //sq_green.png + //========================================================== + $this->imgdata[6][0]= 325 ; + $this->imgdata[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'. + 'BMVEX////2+vX1+vX1+fT0+fPz+PPx9/Dv9u7u9e3h7uHe697a'. + '6dnO2s3I1sa10LOvza2ay5aEwYBWlE9TqE5Tkk1RkEpMrUJMg0'. + 'hKiUNGpEFBojw8oTcsbScaYBMWlwmMT0NtAAAAAWJLR0QAiAUd'. + 'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEFd'. + 'nFx90AAABuSURBVHjaVc9HAoAgDADB2HuJWLDx/2cKBITscW4L'. + '5byzMIWtZobNDZIZtrcCGZsRQ8GwvRSRNxIiMuysODKG3alikl'. + 'ueOPlpKTLBaRmOZxQxaXlfb5ZWI9om4WntrXiDSJzp7SBkwMQa'. + 'FEy0VR/NAB2kNuj7rgAAAABJRU5ErkJggg==' ; + + //========================================================== + //sq_orange.png + //========================================================== + $this->imgdata[7][0]= 321 ; + $this->imgdata[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAUV'. + 'BMVEX/////8+n/8uf/8OP/59H/5Mv/zqH/zJ3/ypv/yJf/vYH/'. + 'u33/uXn/n0n/nUX/m0H/lzn/ljf/lDP/kS3/kCv/iR//hxv/fg'. + 'n/fAX/eQDYZgDW6ia5AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAL'. + 'EgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEJIgbx+cAAAB2SURBVH'. + 'jaVczRCoQwDETRbLAWLZSGUA35/w/dVI0283i4DODew3YESmWW'. + 'kg5gWkoQAe6TleUQI/66Sy7i56+kLk7cht2N0+hcnJgQu0SqiC'. + '1SzSIbzWSi6gavqJ63wSduRi2f+kwyD5rEukwCdZ1kGAMGMfv9'. + 'AbWuGMOr5COSAAAAAElFTkSuQmCC' ; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/imgdata_stars.inc b/web/public_php/admin/jpgraph/imgdata_stars.inc deleted file mode 100644 index de96ee063..000000000 --- a/web/public_php/admin/jpgraph/imgdata_stars.inc +++ /dev/null @@ -1,145 +0,0 @@ - 'imgdata'); - - var $colors = array('bluegreen','lightblue','purple','blue','green','pink','red','yellow'); - var $index = array('bluegreen'=>3,'lightblue'=>4,'purple'=>1, - 'blue'=>5,'green'=>0,'pink'=>7,'red'=>2,'yellow'=>6); - var $maxidx = 7 ; - var $imgdata ; - - function ImgData_Stars() { -//========================================================== -// File: bstar_green_001.png -//========================================================== - $this->imgdata[0][0]= 329 ; - $this->imgdata[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAAUV'. - 'BMVEX///////+/v7+83rqcyY2Q/4R7/15y/1tp/05p/0lg/zdX'. - '/zdX/zVV/zdO/zFJ9TFJvDFD4yg+8Bw+3iU68hwurhYotxYosx'. - 'YokBoTfwANgQFUp7DWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. - 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJj'. - 'CRyxgTAAAAcUlEQVR4nH3MSw6AIAwEUBL/IKBWwXL/g0pLojUS'. - 'ZzGLl8ko9Zumhr5iy66/GH0dp49llNPB5sTotDY5PVuLG6tnM9'. - 'CVKSIe1joSgPsAKSuANNaENFQvTAGzmheSkUpMBWeJZwqBT8wo'. - 'hmysD4bnnPsC/x8ItUdGPfAAAAAASUVORK5CYII=' ; -//========================================================== -// File: bstar_blred.png -//========================================================== - $this->imgdata[1][0]= 325 ; - $this->imgdata[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v79uRJ6jWPOSUtKrb+ejWO+gWPaGTruJTr6rZvF2'. - 'RqC2ocqdVuCeV+egV/GsnLuIXL66rMSpcOyATbipY/OdWOp+VK'. - 'aTU9WhV+yJKBoLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJwynv1'. - 'XVAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bstar_red_001.png -//========================================================== - $this->imgdata[2][0]= 325 ; - $this->imgdata[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v7+eRFHzWG3SUmHnb37vWGr2WHG7Tlm+TljxZneg'. - 'Rk3KoaXgVmXnV2nxV227nJ++XGzErK3scIS4TVzzY3fqWG2mVF'. - 'zVU2PsV2rJFw9VAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJzCI0C'. - 'lSAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bstar_blgr_001.png -//========================================================== - $this->imgdata[3][0]= 325 ; - $this->imgdata[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v79Ehp5Yx/NSq9Jvw+dYwu9YzfZOmbtOmb5myPFG'. - 'gqChvcpWteBXvedXxvGcsbtcpb6su8RwzOxNmrhjyvNYwupUjK'. - 'ZTr9VXwOyJhmWNAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJTC65k'. - 'vQAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bstar_blgr_002.png -//========================================================== - $this->imgdata[4][0]= 325 ; - $this->imgdata[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v79EnpxY8/FS0dJv5+dY7+9Y9vBOubtOur5m8fFG'. - 'nKChycpW3uBX5+ZX8e2curtcvrqswsRw7OdNuLZj8/BY6udUpK'. - 'ZT1dRX7OtNkrW5AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJgXHeN'. - 'wwAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bstar_blue_001.png -//========================================================== - $this->imgdata[5][0]= 325 ; - $this->imgdata[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v79EY55Yi/NSetJvledYiO9YkPZOb7tObr5mkvFG'. - 'X6ChrcpWgOBXhedXi/Gcpbtcf76sssRwnOxNcbhjk/NYiepUbK'. - 'ZTfdVXh+ynNEzzAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJhStyP'. - 'zCAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bstar_oy_007.png -//========================================================== - $this->imgdata[6][0]= 325 ; - $this->imgdata[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v7+ejUTz11jSvVLn02/v1lj21li7q06+r07x2mag'. - 'lUbKxKHgy1bnz1fx1Ve7t5y+qlzEwqzs03C4pE3z2WPqz1imml'. - 'TVv1Ps01dGRjeyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJjsGGc'. - 'GbAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - -//========================================================== -// File: bstar_lred.png -//========================================================== - $this->imgdata[7][0]= 325 ; - $this->imgdata[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. - 'BMVEX///+/v7+eRJPzWN3SUr7nb9TvWNj2WOS7Tqi+TqnxZtyg'. - 'Ro/KocPgVsjnV9LxV927nLa+XLTErL7scN24TarzY9/qWNemVJ'. - 'jVU8LsV9VCwcc9AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. - 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJxi9ZY'. - 'GoAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. - 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. - 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. - 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; - } -} - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/imgdata_stars.inc.php b/web/public_php/admin/jpgraph/imgdata_stars.inc.php new file mode 100644 index 000000000..bc696902a --- /dev/null +++ b/web/public_php/admin/jpgraph/imgdata_stars.inc.php @@ -0,0 +1,144 @@ + 'imgdata'); + + protected $colors = array('bluegreen','lightblue','purple','blue','green','pink','red','yellow'); + protected $index = array('bluegreen'=>3,'lightblue'=>4,'purple'=>1, + 'blue'=>5,'green'=>0,'pink'=>7,'red'=>2,'yellow'=>6); + protected $maxidx = 7 ; + protected $imgdata ; + + function __construct() { + //========================================================== + // File: bstar_green_001.png + //========================================================== + $this->imgdata[0][0]= 329 ; + $this->imgdata[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAAUV'. + 'BMVEX///////+/v7+83rqcyY2Q/4R7/15y/1tp/05p/0lg/zdX'. + '/zdX/zVV/zdO/zFJ9TFJvDFD4yg+8Bw+3iU68hwurhYotxYosx'. + 'YokBoTfwANgQFUp7DWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. + 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJj'. + 'CRyxgTAAAAcUlEQVR4nH3MSw6AIAwEUBL/IKBWwXL/g0pLojUS'. + 'ZzGLl8ko9Zumhr5iy66/GH0dp49llNPB5sTotDY5PVuLG6tnM9'. + 'CVKSIe1joSgPsAKSuANNaENFQvTAGzmheSkUpMBWeJZwqBT8wo'. + 'hmysD4bnnPsC/x8ItUdGPfAAAAAASUVORK5CYII=' ; + //========================================================== + // File: bstar_blred.png + //========================================================== + $this->imgdata[1][0]= 325 ; + $this->imgdata[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v79uRJ6jWPOSUtKrb+ejWO+gWPaGTruJTr6rZvF2'. + 'RqC2ocqdVuCeV+egV/GsnLuIXL66rMSpcOyATbipY/OdWOp+VK'. + 'aTU9WhV+yJKBoLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJwynv1'. + 'XVAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bstar_red_001.png + //========================================================== + $this->imgdata[2][0]= 325 ; + $this->imgdata[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v7+eRFHzWG3SUmHnb37vWGr2WHG7Tlm+TljxZneg'. + 'Rk3KoaXgVmXnV2nxV227nJ++XGzErK3scIS4TVzzY3fqWG2mVF'. + 'zVU2PsV2rJFw9VAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJzCI0C'. + 'lSAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bstar_blgr_001.png + //========================================================== + $this->imgdata[3][0]= 325 ; + $this->imgdata[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v79Ehp5Yx/NSq9Jvw+dYwu9YzfZOmbtOmb5myPFG'. + 'gqChvcpWteBXvedXxvGcsbtcpb6su8RwzOxNmrhjyvNYwupUjK'. + 'ZTr9VXwOyJhmWNAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJTC65k'. + 'vQAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bstar_blgr_002.png + //========================================================== + $this->imgdata[4][0]= 325 ; + $this->imgdata[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v79EnpxY8/FS0dJv5+dY7+9Y9vBOubtOur5m8fFG'. + 'nKChycpW3uBX5+ZX8e2curtcvrqswsRw7OdNuLZj8/BY6udUpK'. + 'ZT1dRX7OtNkrW5AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJgXHeN'. + 'wwAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bstar_blue_001.png + //========================================================== + $this->imgdata[5][0]= 325 ; + $this->imgdata[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v79EY55Yi/NSetJvledYiO9YkPZOb7tObr5mkvFG'. + 'X6ChrcpWgOBXhedXi/Gcpbtcf76sssRwnOxNcbhjk/NYiepUbK'. + 'ZTfdVXh+ynNEzzAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJhStyP'. + 'zCAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bstar_oy_007.png + //========================================================== + $this->imgdata[6][0]= 325 ; + $this->imgdata[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v7+ejUTz11jSvVLn02/v1lj21li7q06+r07x2mag'. + 'lUbKxKHgy1bnz1fx1Ve7t5y+qlzEwqzs03C4pE3z2WPqz1imml'. + 'TVv1Ps01dGRjeyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJjsGGc'. + 'GbAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + + //========================================================== + // File: bstar_lred.png + //========================================================== + $this->imgdata[7][0]= 325 ; + $this->imgdata[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. + 'BMVEX///+/v7+eRJPzWN3SUr7nb9TvWNj2WOS7Tqi+TqnxZtyg'. + 'Ro/KocPgVsjnV9LxV927nLa+XLTErL7scN24TarzY9/qWNemVJ'. + 'jVU8LsV9VCwcc9AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. + 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJxi9ZY'. + 'GoAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. + 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. + 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. + 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/jpg-config.inc b/web/public_php/admin/jpgraph/jpg-config.inc deleted file mode 100644 index 968246d2f..000000000 --- a/web/public_php/admin/jpgraph/jpg-config.inc +++ /dev/null @@ -1,201 +0,0 @@ - \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/jpg-config.inc.php b/web/public_php/admin/jpgraph/jpg-config.inc.php new file mode 100644 index 000000000..ea16c1e22 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpg-config.inc.php @@ -0,0 +1,138 @@ + diff --git a/web/public_php/admin/jpgraph/jpgraph.php b/web/public_php/admin/jpgraph/jpgraph.php index 0d0dfbfbf..5b49397b1 100644 --- a/web/public_php/admin/jpgraph/jpgraph.php +++ b/web/public_php/admin/jpgraph/jpgraph.php @@ -1,8567 +1,5629 @@ -Get(11,$file,$lineno); - die($msg); - } - else { - DEFINE('CACHE_DIR', $_SERVER['TEMP'] . '/'); - } - } else { - DEFINE('CACHE_DIR','/tmp/jpgraph_cache/'); - } - } -} -elseif( !defined('CACHE_DIR') ) { - DEFINE('CACHE_DIR', ''); -} - -if (!defined('TTF_DIR')) { - if (strstr( PHP_OS, 'WIN') ) { - $sroot = getenv('SystemRoot'); - if( empty($sroot) ) { - $t = new ErrMsgText(); - $msg = $t->Get(12,$file,$lineno); - die($msg); - } - else { - DEFINE('TTF_DIR', $sroot.'/fonts/'); - } - } else { - DEFINE('TTF_DIR','/usr/X11R6/lib/X11/fonts/truetype/'); - } -} - -//------------------------------------------------------------------ -// Constants which are used as parameters for the method calls -//------------------------------------------------------------------ - -// TTF Font families -DEFINE("FF_COURIER",10); -DEFINE("FF_VERDANA",11); -DEFINE("FF_TIMES",12); -DEFINE("FF_COMIC",14); -DEFINE("FF_ARIAL",15); -DEFINE("FF_GEORGIA",16); -DEFINE("FF_TREBUCHE",17); - -// Gnome Vera font -// Available from http://www.gnome.org/fonts/ -DEFINE("FF_VERA",19); -DEFINE("FF_VERAMONO",20); -DEFINE("FF_VERASERIF",21); - -// Chinese font -DEFINE("FF_SIMSUN",30); -DEFINE("FF_CHINESE",31); -DEFINE("FF_BIG5",31); - -// Japanese font -DEFINE("FF_MINCHO",40); -DEFINE("FF_PMINCHO",41); -DEFINE("FF_GOTHIC",42); -DEFINE("FF_PGOTHIC",43); - -// Limits for TTF fonts -DEFINE('_FF_FIRST',10); -DEFINE('_FF_LAST',43); - -// Older deprecated fonts -DEFINE("FF_BOOK",91); // Deprecated fonts from 1.9 -DEFINE("FF_HANDWRT",92); // Deprecated fonts from 1.9 - -// TTF Font styles -DEFINE("FS_NORMAL",9001); -DEFINE("FS_BOLD",9002); -DEFINE("FS_ITALIC",9003); -DEFINE("FS_BOLDIT",9004); -DEFINE("FS_BOLDITALIC",9004); - -//Definitions for internal font, new style -DEFINE("FF_FONT0",1); -DEFINE("FF_FONT1",2); -DEFINE("FF_FONT2",4); - -// Tick density -DEFINE("TICKD_DENSE",1); -DEFINE("TICKD_NORMAL",2); -DEFINE("TICKD_SPARSE",3); -DEFINE("TICKD_VERYSPARSE",4); - -// Side for ticks and labels. -DEFINE("SIDE_LEFT",-1); -DEFINE("SIDE_RIGHT",1); -DEFINE("SIDE_DOWN",-1); -DEFINE("SIDE_BOTTOM",-1); -DEFINE("SIDE_UP",1); -DEFINE("SIDE_TOP",1); - -// Legend type stacked vertical or horizontal -DEFINE("LEGEND_VERT",0); -DEFINE("LEGEND_HOR",1); - -// Mark types for plot marks -DEFINE("MARK_SQUARE",1); -DEFINE("MARK_UTRIANGLE",2); -DEFINE("MARK_DTRIANGLE",3); -DEFINE("MARK_DIAMOND",4); -DEFINE("MARK_CIRCLE",5); -DEFINE("MARK_FILLEDCIRCLE",6); -DEFINE("MARK_CROSS",7); -DEFINE("MARK_STAR",8); -DEFINE("MARK_X",9); -DEFINE("MARK_LEFTTRIANGLE",10); -DEFINE("MARK_RIGHTTRIANGLE",11); -DEFINE("MARK_FLASH",12); -DEFINE("MARK_IMG",13); -DEFINE("MARK_FLAG1",14); -DEFINE("MARK_FLAG2",15); -DEFINE("MARK_FLAG3",16); -DEFINE("MARK_FLAG4",17); - -// Builtin images -DEFINE("MARK_IMG_PUSHPIN",50); -DEFINE("MARK_IMG_SPUSHPIN",50); -DEFINE("MARK_IMG_LPUSHPIN",51); -DEFINE("MARK_IMG_DIAMOND",52); -DEFINE("MARK_IMG_SQUARE",53); -DEFINE("MARK_IMG_STAR",54); -DEFINE("MARK_IMG_BALL",55); -DEFINE("MARK_IMG_SBALL",55); -DEFINE("MARK_IMG_MBALL",56); -DEFINE("MARK_IMG_LBALL",57); -DEFINE("MARK_IMG_BEVEL",58); - -// Inline defines -DEFINE("INLINE_YES",1); -DEFINE("INLINE_NO",0); - -// Format for background images -DEFINE("BGIMG_FILLPLOT",1); -DEFINE("BGIMG_FILLFRAME",2); -DEFINE("BGIMG_COPY",3); -DEFINE("BGIMG_CENTER",4); - -// Depth of objects -DEFINE("DEPTH_BACK",0); -DEFINE("DEPTH_FRONT",1); - -// Direction -DEFINE("VERTICAL",1); -DEFINE("HORIZONTAL",0); - - -// Axis styles for scientific style axis -DEFINE('AXSTYLE_SIMPLE',1); -DEFINE('AXSTYLE_BOXIN',2); -DEFINE('AXSTYLE_BOXOUT',3); -DEFINE('AXSTYLE_YBOXIN',4); -DEFINE('AXSTYLE_YBOXOUT',5); - -// Style for title backgrounds -DEFINE('TITLEBKG_STYLE1',1); -DEFINE('TITLEBKG_STYLE2',2); -DEFINE('TITLEBKG_STYLE3',3); -DEFINE('TITLEBKG_FRAME_NONE',0); -DEFINE('TITLEBKG_FRAME_FULL',1); -DEFINE('TITLEBKG_FRAME_BOTTOM',2); -DEFINE('TITLEBKG_FRAME_BEVEL',3); -DEFINE('TITLEBKG_FILLSTYLE_HSTRIPED',1); -DEFINE('TITLEBKG_FILLSTYLE_VSTRIPED',2); -DEFINE('TITLEBKG_FILLSTYLE_SOLID',3); - -// Style for background gradient fills -DEFINE('BGRAD_FRAME',1); -DEFINE('BGRAD_MARGIN',2); -DEFINE('BGRAD_PLOT',3); - -// Width of tab titles -DEFINE('TABTITLE_WIDTHFIT',0); -DEFINE('TABTITLE_WIDTHFULL',-1); - -// Defines for 3D skew directions -DEFINE('SKEW3D_UP',0); -DEFINE('SKEW3D_DOWN',1); -DEFINE('SKEW3D_LEFT',2); -DEFINE('SKEW3D_RIGHT',3); - - - -// -// Get hold of gradient class (In Version 2.x) -// A client of the library has to manually include this -// -require_once 'jpgraph_gradient.php'; - - -class ErrMsgText { - var $lt=NULL; - var $supportedLocales = array('en'); - function __construct() { - GLOBAL $__jpg_err_locale; - if( !in_array($__jpg_err_locale,$this->supportedLocales) ) - $aLoc = 'en'; - require_once('lang/'.$__jpg_err_locale.'.inc.php'); - $this->lt = $_jpg_messages; - } - - function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { - if( !isset($this->lt[$errnbr]) ) { - return 'Internal error: The specified error message does not exist in the chosen locale. (Please blame the translator...))'; - } - $ea = $this->lt[$errnbr]; - $j=0; - if( $a1 !== null ) { - $argv[$j++] = $a1; - if( $a2 !== null ) { - $argv[$j++] = $a2; - if( $a3 !== null ) { - $argv[$j++] = $a3; - if( $a4 !== null ) { - $argv[$j++] = $a4; - if( $a5 !== null ) { - $argv[$j++] = $a5; - } - } - } - } - } - $numargs = $j; - if( $ea[1] != $numargs ) { - // Error message argument count do not match. - // Just return the error message without arguments. - return $ea[0]; - } - switch( $numargs ) { - case 1: - $msg = sprintf($ea[0],$argv[0]); - break; - case 2: - $msg = sprintf($ea[0],$argv[0],$argv[1]); - break; - case 3: - $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]); - break; - case 4: - $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]); - break; - case 5: - $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]); - break; - case 0: - default: - $msg = sprintf($ea[0]); - break; - } - return $msg; - } -} - -// -// A wrapper class that is used to access the specified error object -// (to hide the global error parameter and avoid having a GLOBAL directive -// in all methods. -// -GLOBAL $__jpg_err; -GLOBAL $__jpg_err_locale ; -$__jpg_err_locale = 'en'; -class JpGraphError { - static function Install($aErrObject) { - GLOBAL $__jpg_err; - $__jpg_err = $aErrObject; - } - static function Raise($aMsg,$aHalt=true){ - GLOBAL $__jpg_err; - $tmp = new $__jpg_err; - $tmp->Raise($aMsg,$aHalt); - } - static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { - GLOBAL $__jpg_err; - $t = new ErrMsgText(); - $msg = $t->Get($errnbr,$a1,$a2,$a3,$a4,$a5); - $tmp = new $__jpg_err; - $tmp->Raise($msg); - } -} - -// -// ... and install the default error handler -// -if( USE_IMAGE_ERROR_HANDLER ) { - $__jpg_err = "JpGraphErrObjectImg"; -} -else { - $__jpg_err = "JpGraphErrObject"; -} - -// -// Make GD sanity check -// -if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) { - JpGraphError::RaiseL(25001); -//("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)"); -} - -// -// Routine to determine if GD1 or GD2 is installed -// -function CheckGDVersion() { - $GDfuncList = get_extension_funcs('gd'); - if( !$GDfuncList ) return 0 ; - else { - if( in_array('imagegd2',$GDfuncList) && - in_array('imagecreatetruecolor',$GDfuncList)) - return 2; - else - return 1; - } -} - -// -// Check what version of the GD library is installed. -// -$GLOBALS['gd2'] = false; -if( USE_LIBRARY_GD2 === 'auto' ) { - $gdversion = CheckGDVersion(); - if( $gdversion == 2 ) { - $GLOBALS['gd2'] = true; - $GLOBALS['copyfunc'] = 'imagecopyresampled'; - } - elseif( $gdversion == 1 ) { - $GLOBALS['gd2'] = false; - $GLOBALS['copyfunc'] = 'imagecopyresized'; - } - else { - JpGraphError::RaiseL(25002); -//(" Your PHP installation does not seem to have the required GD library. Please see the PHP documentation on how to install and enable the GD library."); - } -} -else { - $GLOBALS['gd2'] = USE_LIBRARY_GD2; - $GLOBALS['copyfunc'] = USE_LIBRARY_GD2 ? 'imagecopyresampled' : 'imagecopyresized'; -} - - -// -// First of all set up a default error handler -// - - -//============================================================= -// The default trivial text error handler. -//============================================================= -class JpGraphErrObject { - - var $iTitle = "JpGraph Error"; - var $iDest = false; - - function __construct() { - // Empty. Reserved for future use - } - - function SetTitle($aTitle) { - $this->iTitle = $aTitle; - } - - function SetStrokeDest($aDest) { - $this->iDest = $aDest; - } - - // If aHalt is true then execution can't continue. Typical used for fatal errors. - function Raise($aMsg,$aHalt=true) { - $aMsg = $this->iTitle.' '.$aMsg; - if ($this->iDest) { - $f = @fopen($this->iDest,'a'); - if( $f ) { - @fwrite($f,$aMsg); - @fclose($f); - } - } - else { - echo $aMsg; - } - if( $aHalt ) - die(); - } -} - -//============================================================== -// An image based error handler -//============================================================== -class JpGraphErrObjectImg extends JpGraphErrObject { - - function Raise($aMsg,$aHalt=true) { - $img_iconerror = - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'. - 'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. - 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'. - 'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. - 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. - 'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'. - '2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'. - 'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'. - 'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'. - 'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'. - '6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'. - 'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'. - 'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'. - 'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'. - 'qL72fwAAAABJRU5ErkJggg==' ; - - if( function_exists("imagetypes") ) - $supported = imagetypes(); - else - $supported = 0; - - if( !function_exists('imagecreatefromstring') ) - $supported = 0; - - if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) { - // Special case for headers already sent or that the installation doesn't support - // the PNG format (which the error icon is encoded in). - // Dont return an image since it can't be displayed - die($this->iTitle.' '.$aMsg); - } - - $aMsg = wordwrap($aMsg,55); - $lines = substr_count($aMsg,"\n"); - - // Create the error icon GD - $erricon = Image::CreateFromString(base64_decode($img_iconerror)); - - // Create an image that contains the error text. - $w=400; - $h=100 + 15*max(0,$lines-3); - - $img = new Image($w,$h); - - // Drop shadow - $img->SetColor("gray"); - $img->FilledRectangle(5,5,$w-1,$h-1,10); - $img->SetColor("gray:0.7"); - $img->FilledRectangle(5,5,$w-3,$h-3,10); - - // Window background - $img->SetColor("lightblue"); - $img->FilledRectangle(1,1,$w-5,$h-5); - $img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40); - - // Window border - $img->SetColor("black"); - $img->Rectangle(1,1,$w-5,$h-5); - $img->Rectangle(0,0,$w-4,$h-4); - - // Window top row - $img->SetColor("darkred"); - for($y=3; $y < 18; $y += 2 ) - $img->Line(1,$y,$w-6,$y); - - // "White shadow" - $img->SetColor("white"); - - // Left window edge - $img->Line(2,2,2,$h-5); - $img->Line(2,2,$w-6,2); - - // "Gray button shadow" - $img->SetColor("darkgray"); - - // Gray window shadow - $img->Line(2,$h-6,$w-5,$h-6); - $img->Line(3,$h-7,$w-5,$h-7); - - // Window title - $m = floor($w/2-5); - $l = 100; - $img->SetColor("lightgray:1.3"); - $img->FilledRectangle($m-$l,2,$m+$l,16); - - // Stroke text - $img->SetColor("darkred"); - $img->SetFont(FF_FONT2,FS_BOLD); - $img->StrokeText($m-50,15,$this->iTitle); - $img->SetColor("black"); - $img->SetFont(FF_FONT1,FS_NORMAL); - $txt = new Text($aMsg,52,25); - $txt->Align("left","top"); - $txt->Stroke($img); - if ($this->iDest) { - $img->Stream($this->iDest); - } else { - $img->Headers(); - $img->Stream(); - } - if( $aHalt ) - die(); - } -} - -// -// Setup PHP error handler -// -function _phpErrorHandler($errno,$errmsg,$filename, $linenum, $vars) { - // Respect current error level - if( $errno & error_reporting() ) { - JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg); - } -} - -if( INSTALL_PHP_ERR_HANDLER ) { - set_error_handler("_phpErrorHandler"); -} - -// -//Check if there were any warnings, perhaps some wrong includes by the user -// -if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && - !preg_match('|Deprecated|', $GLOBALS['php_errormsg'])) { - JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']); -} - - -// Useful mathematical function -function sign($a) {return $a >= 0 ? 1 : -1;} - -// Utility function to generate an image name based on the filename we -// are running from and assuming we use auto detection of graphic format -// (top level), i.e it is safe to call this function -// from a script that uses JpGraph -function GenImgName() { - global $_SERVER; - - // Determine what format we should use when we save the images - $supported = imagetypes(); - if( $supported & IMG_PNG ) $img_format="png"; - elseif( $supported & IMG_GIF ) $img_format="gif"; - elseif( $supported & IMG_JPG ) $img_format="jpeg"; - - if( !isset($_SERVER['PHP_SELF']) ) - JpGraphError::RaiseL(25005); -//(" 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."); - $fname = basename($_SERVER['PHP_SELF']); - if( !empty($_SERVER['QUERY_STRING']) ) { - $q = @$_SERVER['QUERY_STRING']; - $fname .= '?'.preg_replace("/\W/", "_", $q).'.'.$img_format; - } - else { - $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format; - } - return $fname; -} - -class LanguageConv { - var $g2312 = null ; - - function Convert($aTxt,$aFF) { - if( LANGUAGE_CYRILLIC ) { - if( CYRILLIC_FROM_WINDOWS ) { - $aTxt = convert_cyr_string($aTxt, "w", "k"); - } - $isostring = convert_cyr_string($aTxt, "k", "i"); - $unistring = LanguageConv::iso2uni($isostring); - return $unistring; - } - elseif( $aFF === FF_SIMSUN ) { - // Do Chinese conversion - if( $this->g2312 == null ) { - include_once 'jpgraph_gb2312.php' ; - $this->g2312 = new GB2312toUTF8(); - } - return $this->g2312->gb2utf8($aTxt); - } - elseif( $aFF === FF_CHINESE ) { - if( !function_exists('iconv') ) { - JpGraphError::RaiseL(25006); -//('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).'); - } - return iconv('BIG5','UTF-8',$aTxt); - } - else - return $aTxt; - } - - // Translate iso encoding to unicode - function iso2uni ($isoline){ - $uniline=''; - for ($i=0; $i < strlen($isoline); $i++){ - $thischar=substr($isoline,$i,1); - $charcode=ord($thischar); - $uniline.=($charcode>175) ? "&#" . (1040+($charcode-176)). ";" : $thischar; - } - return $uniline; - } -} - -//=================================================== -// CLASS JpgTimer -// Description: General timing utility class to handle -// time measurement of generating graphs. Multiple -// timers can be started. -//=================================================== -class JpgTimer { - var $start; - var $idx; -//--------------- -// CONSTRUCTOR - function __construct() { - $this->idx=0; - } - -//--------------- -// PUBLIC METHODS - - // Push a new timer start on stack - function Push() { - list($ms,$s)=explode(" ",microtime()); - $this->start[$this->idx++]=floor($ms*1000) + 1000*$s; - } - - // Pop the latest timer start and return the diff with the - // current time - function Pop() { - assert($this->idx>0); - list($ms,$s)=explode(" ",microtime()); - $etime=floor($ms*1000) + (1000*$s); - $this->idx--; - return $etime-$this->start[$this->idx]; - } -} // Class - -$gJpgBrandTiming = BRAND_TIMING; -//=================================================== -// CLASS DateLocale -// Description: Hold localized text used in dates -//=================================================== -class DateLocale { - - var $iLocale = 'C'; // environmental locale be used by default - - var $iDayAbb = null; - var $iShortDay = null; - var $iShortMonth = null; - var $iMonthName = null; - -//--------------- -// CONSTRUCTOR - function __construct() { - settype($this->iDayAbb, 'array'); - settype($this->iShortDay, 'array'); - settype($this->iShortMonth, 'array'); - settype($this->iMonthName, 'array'); - - - $this->Set('C'); - } - -//--------------- -// PUBLIC METHODS - function Set($aLocale) { - if ( in_array($aLocale, array_keys($this->iDayAbb)) ){ - $this->iLocale = $aLocale; - return TRUE; // already cached nothing else to do! - } - - $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME - $res = @setlocale(LC_TIME, $aLocale); - if ( ! $res ){ - JpGraphError::RaiseL(25007,$aLocale); -//("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."); - return FALSE; - } - - $this->iLocale = $aLocale; - - for ( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ){ - $day = strftime('%a', strtotime("$ofs day")); - $day{0} = strtoupper($day{0}); - $this->iDayAbb[$aLocale][]= $day{0}; - $this->iShortDay[$aLocale][]= $day; - } - - for($i=1; $i<=12; ++$i) { - list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01"))); - $this->iShortMonth[$aLocale][] = ucfirst($short); - $this->iMonthName [$aLocale][] = ucfirst($full); - } - - // Return to original locale - setlocale(LC_TIME, $pLocale); - - return TRUE; - } - - - function GetDayAbb() { - return $this->iDayAbb[$this->iLocale]; - } - - function GetShortDay() { - return $this->iShortDay[$this->iLocale]; - } - - function GetShortMonth() { - return $this->iShortMonth[$this->iLocale]; - } - - function GetShortMonthName($aNbr) { - return $this->iShortMonth[$this->iLocale][$aNbr]; - } - - function GetLongMonthName($aNbr) { - return $this->iMonthName[$this->iLocale][$aNbr]; - } - - function GetMonth() { - return $this->iMonthName[$this->iLocale]; - } -} - -$gDateLocale = new DateLocale(); -$gJpgDateLocale = new DateLocale(); - - -//======================================================= -// CLASS Footer -// Description: Encapsulates the footer line in the Graph -//======================================================= -class Footer { - var $left,$center,$right; - var $iLeftMargin = 3; - var $iRightMargin = 3; - var $iBottomMargin = 3; - - function __construct() { - $this->left = new Text(); - $this->left->ParagraphAlign('left'); - $this->center = new Text(); - $this->center->ParagraphAlign('center'); - $this->right = new Text(); - $this->right->ParagraphAlign('right'); - } - - function Stroke(&$aImg) { - $y = $aImg->height - $this->iBottomMargin; - $x = $this->iLeftMargin; - $this->left->Align('left','bottom'); - $this->left->Stroke($aImg,$x,$y); - - $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2; - $this->center->Align('center','bottom'); - $this->center->Stroke($aImg,$x,$y); - - $x = $aImg->width - $this->iRightMargin; - $this->right->Align('right','bottom'); - $this->right->Stroke($aImg,$x,$y); - } -} - - -//=================================================== -// CLASS Graph -// Description: Main class to handle graphs -//=================================================== -class Graph { - var $cache=null; // Cache object (singleton) - var $img=null; // Img object (singleton) - var $plots=array(); // Array of all plot object in the graph (for Y 1 axis) - var $y2plots=array();// Array of all plot object in the graph (for Y 2 axis) - var $ynplots=array(); - var $xscale=null; // X Scale object (could be instance of LinearScale or LogScale - var $yscale=null,$y2scale=null, $ynscale=array(); - var $iIcons = array(); // Array of Icons to add to - var $cache_name; // File name to be used for the current graph in the cache directory - var $xgrid=null; // X Grid object (linear or logarithmic) - var $ygrid=null,$y2grid=null; - var $doframe=true,$frame_color=array(0,0,0), $frame_weight=1; // Frame around graph - var $boxed=false, $box_color=array(0,0,0), $box_weight=1; // Box around plot area - var $doshadow=false,$shadow_width=4,$shadow_color=array(102,102,102); // Shadow for graph - var $xaxis=null; // X-axis (instane of Axis class) - var $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class) - var $margin_color=array(200,200,200); // Margin color of graph - var $plotarea_color=array(255,255,255); // Plot area color - var $title,$subtitle,$subsubtitle; // Title and subtitle(s) text object - var $axtype="linlin"; // Type of axis - var $xtick_factor; // Factot to determine the maximum number of ticks depending on the plot with - var $texts=null, $y2texts=null; // Text object to ge shown in the graph - var $lines=null, $y2lines=null; - var $bands=null, $y2bands=null; - var $text_scale_off=0, $text_scale_abscenteroff=-1; // Text scale offset in fractions and for centering bars in absolute pixels - var $background_image="",$background_image_type=-1,$background_image_format="png"; - var $background_image_bright=0,$background_image_contr=0,$background_image_sat=0; - var $image_bright=0, $image_contr=0, $image_sat=0; - var $inline; - var $showcsim=0,$csimcolor="red"; //debug stuff, draw the csim boundaris on the image if <>0 - var $grid_depth=DEPTH_BACK; // Draw grid under all plots as default - var $iAxisStyle = AXSTYLE_SIMPLE; - var $iCSIMdisplay=false,$iHasStroked = false; - var $footer; - var $csimcachename = '', $csimcachetimeout = 0; - var $iDoClipping = false; - var $y2orderback=true; - var $tabtitle; - var $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN; - var $bkg_gradfrom='navy', $bkg_gradto='silver'; - var $titlebackground = false; - var $titlebackground_color = 'lightblue', - $titlebackground_style = 1, - $titlebackground_framecolor = 'blue', - $titlebackground_framestyle = 2, - $titlebackground_frameweight = 1, - $titlebackground_bevelheight = 3 ; - var $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID; - var $titlebkg_scolor1='black',$titlebkg_scolor2='white'; - var $framebevel = false, $framebeveldepth = 2 ; - var $framebevelborder = false, $framebevelbordercolor='black'; - var $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4'; - var $background_image_mix=100; - var $background_cflag = ''; - var $background_cflag_type = BGIMG_FILLPLOT; - var $background_cflag_mix = 100; - var $iImgTrans=false, - $iImgTransHorizon = 100,$iImgTransSkewDist=150, - $iImgTransDirection = 1, $iImgTransMinSize = true, - $iImgTransFillColor='white',$iImgTransHighQ=false, - $iImgTransBorder=false,$iImgTransHorizonPos=0.5; - var $iYAxisDeltaPos=50; - var $iIconDepth=DEPTH_BACK; - var $iAxisLblBgType = 0, - $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black', - $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black'; - var $iTables=NULL; - -//--------------- -// CONSTRUCTOR - - // aWIdth Width in pixels of image - // aHeight Height in pixels of image - // aCachedName Name for image file in cache directory - // aTimeOut Timeout in minutes for image in cache - // aInline If true the image is streamed back in the call to Stroke() - // If false the image is just created in the cache - function __construct($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) { - GLOBAL $gJpgBrandTiming; - // If timing is used create a new timing object - if( $gJpgBrandTiming ) { - global $tim; - $tim = new JpgTimer(); - $tim->Push(); - } - - if( !is_numeric($aWidth) || !is_numeric($aHeight) ) { - JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric'); - } - - // Automatically generate the image file name based on the name of the script that - // generates the graph - if( $aCachedName=="auto" ) - $aCachedName=GenImgName(); - - // Should the image be streamed back to the browser or only to the cache? - $this->inline=$aInline; - - $this->img = new RotImage($aWidth,$aHeight); - - $this->cache = new ImgStreamCache($this->img); - $this->cache->SetTimeOut($aTimeOut); - - $this->title = new Text(); - $this->title->ParagraphAlign('center'); - $this->title->SetFont(FF_FONT2,FS_BOLD); - $this->title->SetMargin(3); - $this->title->SetAlign('center'); - - $this->subtitle = new Text(); - $this->subtitle->ParagraphAlign('center'); - $this->subtitle->SetMargin(2); - $this->subtitle->SetAlign('center'); - - $this->subsubtitle = new Text(); - $this->subsubtitle->ParagraphAlign('center'); - $this->subsubtitle->SetMargin(2); - $this->subsubtitle->SetAlign('center'); - - $this->legend = new Legend(); - $this->footer = new Footer(); - - // Window doesn't like '?' in the file name so replace it with an '_' - $aCachedName = str_replace("?","_",$aCachedName); - - // If the cached version exist just read it directly from the - // cache, stream it back to browser and exit - if( $aCachedName!="" && READ_CACHE && $aInline ) - if( $this->cache->GetAndStream($aCachedName) ) { - exit(); - } - - $this->cache_name = $aCachedName; - $this->SetTickDensity(); // Normal density - - $this->tabtitle = new GraphTabTitle(); - } -//--------------- -// PUBLIC METHODS - // Enable final image perspective transformation - function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) { - $this->iImgTrans = true; - $this->iImgTransHorizon = $aHorizon; - $this->iImgTransSkewDist= $aSkewDist; - $this->iImgTransDirection = $aDir; - $this->iImgTransMinSize = $aMinSize; - $this->iImgTransFillColor=$aFillColor; - $this->iImgTransHighQ=$aQuality; - $this->iImgTransBorder=$aBorder; - $this->iImgTransHorizonPos=$aHorizonPos; - } - - // Set Image format and optional quality - function SetImgFormat($aFormat,$aQuality=75) { - $this->img->SetImgFormat($aFormat,$aQuality); - } - - // Should the grid be in front or back of the plot? - function SetGridDepth($aDepth) { - $this->grid_depth=$aDepth; - } - - function SetIconDepth($aDepth) { - $this->iIconDepth=$aDepth; - } - - // Specify graph angle 0-360 degrees. - function SetAngle($aAngle) { - $this->img->SetAngle($aAngle); - } - - function SetAlphaBlending($aFlg=true) { - $this->img->SetAlphaBlending($aFlg); - } - - // Shortcut to image margin - function SetMargin($lm,$rm,$tm,$bm) { - $this->img->SetMargin($lm,$rm,$tm,$bm); - } - - function SetY2OrderBack($aBack=true) { - $this->y2orderback = $aBack; - } - - // Rotate the graph 90 degrees and set the margin - // when we have done a 90 degree rotation - function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) { - $lm = $lm ==0 ? floor(0.2 * $this->img->width) : $lm ; - $rm = $rm ==0 ? floor(0.1 * $this->img->width) : $rm ; - $tm = $tm ==0 ? floor(0.2 * $this->img->height) : $tm ; - $bm = $bm ==0 ? floor(0.1 * $this->img->height) : $bm ; - - $adj = ($this->img->height - $this->img->width)/2; - $this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj); - $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2)); - $this->SetAngle(90); - if( empty($this->yaxis) || empty($this->xaxis) ) { - JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()'); - } - $this->xaxis->SetLabelAlign('right','center'); - $this->yaxis->SetLabelAlign('center','bottom'); - } - - function SetClipping($aFlg=true) { - $this->iDoClipping = $aFlg ; - } - - // Add a plot object to the graph - function Add(&$aPlot) { - if( $aPlot == null ) - JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph."); - if( is_array($aPlot) && count($aPlot) > 0 ) - $cl = $aPlot[0]; - else - $cl = $aPlot; - - if( is_a($cl,'Text') ) - $this->AddText($aPlot); - elseif( is_a($cl,'PlotLine') ) - $this->AddLine($aPlot); - elseif( is_a($cl,'PlotBand') ) - $this->AddBand($aPlot); - elseif( is_a($cl,'IconPlot') ) - $this->AddIcon($aPlot); - elseif( is_a($cl,'GTextTable') ) - $this->AddTable($aPlot); - else - $this->plots[] = &$aPlot; - } - - - function AddTable(&$aTable) { - if( is_array($aTable) ) { - for($i=0; $i < count($aTable); ++$i ) - $this->iTables[]=&$aTable[$i]; - } - else { - $this->iTables[] = &$aTable ; - } - } - - function AddIcon(&$aIcon) { - if( is_array($aIcon) ) { - for($i=0; $i < count($aIcon); ++$i ) - $this->iIcons[]=&$aIcon[$i]; - } - else { - $this->iIcons[] = &$aIcon ; - } - } - - // Add plot to second Y-scale - function AddY2(&$aPlot) { - if( $aPlot == null ) - JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph."); - - if( is_array($aPlot) && count($aPlot) > 0 ) - $cl = $aPlot[0]; - else - $cl = $aPlot; - - if( is_a($cl,'Text') ) - $this->AddText($aPlot,true); - elseif( is_a($cl,'PlotLine') ) - $this->AddLine($aPlot,true); - elseif( is_a($cl,'PlotBand') ) - $this->AddBand($aPlot,true); - else - $this->y2plots[] = &$aPlot; - } - - // Add plot to second Y-scale - function AddY($aN,&$aPlot) { - - if( $aPlot == null ) - JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph."); - - if( is_array($aPlot) && count($aPlot) > 0 ) - $cl = $aPlot[0]; - else - $cl = $aPlot; - - if( is_a($cl,'Text') || is_a($cl,'PlotLine') || is_a($cl,'PlotBand') ) - JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis'); - else - $this->ynplots[$aN][] = &$aPlot; - } - - // Add text object to the graph - function AddText(&$aTxt,$aToY2=false) { - if( $aTxt == null ) - JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph."); - if( $aToY2 ) { - if( is_array($aTxt) ) { - for($i=0; $i < count($aTxt); ++$i ) - $this->y2texts[]=&$aTxt[$i]; - } - else - $this->y2texts[] = &$aTxt; - } - else { - if( is_array($aTxt) ) { - for($i=0; $i < count($aTxt); ++$i ) - $this->texts[]=&$aTxt[$i]; - } - else - $this->texts[] = &$aTxt; - } - } - - // Add a line object (class PlotLine) to the graph - function AddLine(&$aLine,$aToY2=false) { - if( $aLine == null ) - JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph."); - - if( $aToY2 ) { - if( is_array($aLine) ) { - for($i=0; $i < count($aLine); ++$i ) - $this->y2lines[]=&$aLine[$i]; - } - else - $this->y2lines[] = &$aLine; - } - else { - if( is_array($aLine) ) { - for($i=0; $i < count($aLine); ++$i ) - $this->lines[]=&$aLine[$i]; - } - else - $this->lines[] = &$aLine; - } - } - - // Add vertical or horizontal band - function AddBand(&$aBand,$aToY2=false) { - if( $aBand == null ) - JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph."); - - if( $aToY2 ) { - if( is_array($aBand) ) { - for($i=0; $i < count($aBand); ++$i ) - $this->y2bands[] = &$aBand[$i]; - } - else - $this->y2bands[] = &$aBand; - } - else { - if( is_array($aBand) ) { - for($i=0; $i < count($aBand); ++$i ) - $this->bands[] = &$aBand[$i]; - } - else - $this->bands[] = &$aBand; - } - } - - function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) { - $this->bkg_gradtype=$aGradType; - $this->bkg_gradstyle=$aStyle; - $this->bkg_gradfrom = $aFrom; - $this->bkg_gradto = $aTo; - } - - // Set a country flag in the background - function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) { - $this->background_cflag = $aName; - $this->background_cflag_type = $aBgType; - $this->background_cflag_mix = $aMix; - } - - // Alias for the above method - function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) { - $this->background_cflag = $aName; - $this->background_cflag_type = $aBgType; - $this->background_cflag_mix = $aMix; - } - - - // Specify a background image - function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat="auto") { - - if( $GLOBALS['gd2'] && !USE_TRUECOLOR ) { - 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 must 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."); - } - - // Get extension to determine image type - if( $aImgFormat == "auto" ) { - $e = explode('.',$aFileName); - if( !$e ) { - 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'); - } - - $valid_formats = array('png', 'jpg', 'gif'); - $aImgFormat = strtolower($e[count($e)-1]); - if ($aImgFormat == 'jpeg') { - $aImgFormat = 'jpg'; - } - elseif (!in_array($aImgFormat, $valid_formats) ) { - JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName); - } - } - - $this->background_image = $aFileName; - $this->background_image_type=$aBgType; - $this->background_image_format=$aImgFormat; - } - - function SetBackgroundImageMix($aMix) { - $this->background_image_mix = $aMix ; - } - - // Adjust brightness and constrast for background image - function AdjBackgroundImage($aBright,$aContr=0,$aSat=0) { - $this->background_image_bright=$aBright; - $this->background_image_contr=$aContr; - $this->background_image_sat=$aSat; - } - - // Adjust brightness and constrast for image - function AdjImage($aBright,$aContr=0,$aSat=0) { - $this->image_bright=$aBright; - $this->image_contr=$aContr; - $this->image_sat=$aSat; - } - - // Specify axis style (boxed or single) - function SetAxisStyle($aStyle) { - $this->iAxisStyle = $aStyle ; - } - - // Set a frame around the plot area - function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) { - $this->boxed = $aDrawPlotFrame; - $this->box_weight = $aPlotFrameWeight; - $this->box_color = $aPlotFrameColor; - } - - // Specify color for the plotarea (not the margins) - function SetColor($aColor) { - $this->plotarea_color=$aColor; - } - - // Specify color for the margins (all areas outside the plotarea) - function SetMarginColor($aColor) { - $this->margin_color=$aColor; - } - - // Set a frame around the entire image - function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) { - $this->doframe = $aDrawImgFrame; - $this->frame_color = $aImgFrameColor; - $this->frame_weight = $aImgFrameWeight; - } - - function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) { - $this->framebevel = $aFlg ; - $this->framebeveldepth = $aDepth ; - $this->framebevelborder = $aBorder ; - $this->framebevelbordercolor = $aBorderColor ; - $this->framebevelcolor1 = $aColor1 ; - $this->framebevelcolor2 = $aColor2 ; - - $this->doshadow = false ; - } - - // Set the shadow around the whole image - function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor=array(102,102,102)) { - $this->doshadow = $aShowShadow; - $this->shadow_color = $aShadowColor; - $this->shadow_width = $aShadowWidth; - $this->footer->iBottomMargin += $aShadowWidth; - $this->footer->iRightMargin += $aShadowWidth; - } - - // Specify x,y scale. Note that if you manually specify the scale - // you must also specify the tick distance with a call to Ticks::Set() - function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) { - $this->axtype = $aAxisType; - - if( $aYMax < $aYMin || $aXMax < $aXMin ) - JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.'); - - $yt=substr($aAxisType,-3,3); - if( $yt=="lin" ) - $this->yscale = new LinearScale($aYMin,$aYMax); - elseif( $yt == "int" ) { - $this->yscale = new LinearScale($aYMin,$aYMax); - $this->yscale->SetIntScale(); - } - elseif( $yt=="log" ) - $this->yscale = new LogScale($aYMin,$aYMax); - else - JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)"); - - $xt=substr($aAxisType,0,3); - if( $xt == "lin" || $xt == "tex" ) { - $this->xscale = new LinearScale($aXMin,$aXMax,"x"); - $this->xscale->textscale = ($xt == "tex"); - } - elseif( $xt == "int" ) { - $this->xscale = new LinearScale($aXMin,$aXMax,"x"); - $this->xscale->SetIntScale(); - } - elseif( $xt == "dat" ) { - $this->xscale = new DateScale($aXMin,$aXMax,"x"); - } - elseif( $xt == "log" ) - $this->xscale = new LogScale($aXMin,$aXMax,"x"); - else - JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)"); - - $this->xaxis = new Axis($this->img,$this->xscale); - $this->yaxis = new Axis($this->img,$this->yscale); - $this->xgrid = new Grid($this->xaxis); - $this->ygrid = new Grid($this->yaxis); - $this->ygrid->Show(); - } - - // Specify secondary Y scale - function SetY2Scale($aAxisType="lin",$aY2Min=1,$aY2Max=1) { - if( $aAxisType=="lin" ) - $this->y2scale = new LinearScale($aY2Min,$aY2Max); - elseif( $aAxisType == "int" ) { - $this->y2scale = new LinearScale($aY2Min,$aY2Max); - $this->y2scale->SetIntScale(); - } - elseif( $aAxisType=="log" ) { - $this->y2scale = new LogScale($aY2Min,$aY2Max); - } - else JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)"); - - $this->y2axis = new Axis($this->img,$this->y2scale); - $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT); - $this->y2axis->SetLabelSide(SIDE_RIGHT); - $this->y2axis->SetPos('max'); - $this->y2axis->SetTitleSide(SIDE_RIGHT); - - // Deafult position is the max x-value - $this->y2grid = new Grid($this->y2axis); - } - - // Set the delta position (in pixels) between the multiple Y-axis - function SetYDeltaDist($aDist) { - $this->iYAxisDeltaPos = $aDist; - } - - // Specify secondary Y scale - function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) { - - if( $aAxisType=="lin" ) - $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax); - elseif( $aAxisType == "int" ) { - $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax); - $this->ynscale[$aN]->SetIntScale(); - } - elseif( $aAxisType=="log" ) { - $this->ynscale[$aN] = new LogScale($aYMin,$aYMax); - } - else JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)"); - - $this->ynaxis[$aN] = new Axis($this->img,$this->ynscale[$aN]); - $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT); - $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT); - } - - - // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse' - // The dividing factor have been determined heuristically according to my aesthetic - // sense (or lack off) y.m.m.v ! - function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) { - $this->xtick_factor=30; - $this->ytick_factor=25; - switch( $aYDensity ) { - case TICKD_DENSE: - $this->ytick_factor=12; - break; - case TICKD_NORMAL: - $this->ytick_factor=25; - break; - case TICKD_SPARSE: - $this->ytick_factor=40; - break; - case TICKD_VERYSPARSE: - $this->ytick_factor=100; - break; - default: - JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy"); - } - switch( $aXDensity ) { - case TICKD_DENSE: - $this->xtick_factor=15; - break; - case TICKD_NORMAL: - $this->xtick_factor=30; - break; - case TICKD_SPARSE: - $this->xtick_factor=45; - break; - case TICKD_VERYSPARSE: - $this->xtick_factor=60; - break; - default: - JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx"); - } - } - - - // Get a string of all image map areas - function GetCSIMareas() { - if( !$this->iHasStroked ) - $this->Stroke(_CSIM_SPECIALFILE); - - $csim = $this->title->GetCSIMAreas(); - $csim .= $this->subtitle->GetCSIMAreas(); - $csim .= $this->subsubtitle->GetCSIMAreas(); - $csim .= $this->legend->GetCSIMAreas(); - - if( $this->y2axis != NULL ) { - $csim .= $this->y2axis->title->GetCSIMAreas(); - } - - if( $this->texts != null ) { - $n = count($this->texts); - for($i=0; $i < $n; ++$i ) { - $csim .= $this->texts[$i]->GetCSIMAreas(); - } - } - - if( $this->y2texts != null && $this->y2scale != null ) { - $n = count($this->y2texts); - for($i=0; $i < $n; ++$i ) { - $csim .= $this->y2texts[$i]->GetCSIMAreas(); - } - } - - if( $this->yaxis != null && $this->xaxis != null ) { - $csim .= $this->yaxis->title->GetCSIMAreas(); - $csim .= $this->xaxis->title->GetCSIMAreas(); - } - - $n = count($this->plots); - for( $i=0; $i < $n; ++$i ) - $csim .= $this->plots[$i]->GetCSIMareas(); - - $n = count($this->y2plots); - for( $i=0; $i < $n; ++$i ) - $csim .= $this->y2plots[$i]->GetCSIMareas(); - - $n = count($this->ynaxis); - for( $i=0; $i < $n; ++$i ) { - $m = count($this->ynplots[$i]); - for($j=0; $j < $m; ++$j ) { - $csim .= $this->ynplots[$i][$j]->GetCSIMareas(); - } - } - - $n = count($this->iTables); - for( $i=0; $i < $n; ++$i ) { - $csim .= $this->iTables[$i]->GetCSIMareas(); - } - - return $csim; - } - - // Get a complete .. tag for the final image map - function GetHTMLImageMap($aMapName) { - //$im = "\n"; - $im = "\n"; - $im .= $this->GetCSIMareas(); - $im .= ""; - return $im; - } - - function CheckCSIMCache($aCacheName,$aTimeOut=60) { - global $_SERVER; - - if( $aCacheName=='auto' ) - $aCacheName=basename($_SERVER['PHP_SELF']); - - $this->csimcachename = CSIMCACHE_DIR.$aCacheName; - $this->csimcachetimeout = $aTimeOut; - - // First determine if we need to check for a cached version - // This differs from the standard cache in the sense that the - // image and CSIM map HTML file is written relative to the directory - // the script executes in and not the specified cache directory. - // The reason for this is that the cache directory is not necessarily - // accessible from the HTTP server. - if( $this->csimcachename != '' ) { - $dir = dirname($this->csimcachename); - $base = basename($this->csimcachename); - $base = strtok($base,'.'); - $suffix = strtok('.'); - $basecsim = $dir.'/'.$base.'_csim_.html'; - $baseimg = $dir.'/'.$base.'.'.$this->img->img_format; - - $timedout=false; - - // Does it exist at all ? - - if( file_exists($basecsim) && file_exists($baseimg) ) { - // Check that it hasn't timed out - $diff=time()-filemtime($basecsim); - if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) { - $timedout=true; - @unlink($basecsim); - @unlink($baseimg); - } - else { - if ($fh = @fopen($basecsim, "r")) { - fpassthru($fh); - return true; - } - else - JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading."); - } - } - } - return false; - } - - function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) { - if( $aCSIMName=='' ) { - // create a random map name - srand ((double) microtime() * 1000000); - $r = rand(0,100000); - $aCSIMName='__mapname'.$r.'__'; - } - - if( $aScriptName=='auto' ) - $aScriptName=basename($_SERVER['PHP_SELF']); - - if( empty($_GET[_CSIM_DISPLAY]) ) { - // First determine if we need to check for a cached version - // This differs from the standard cache in the sense that the - // image and CSIM map HTML file is written relative to the directory - // the script executes in and not the specified cache directory. - // The reason for this is that the cache directory is not necessarily - // accessible from the HTTP server. - if( $this->csimcachename != '' ) { - $dir = dirname($this->csimcachename); - $base = basename($this->csimcachename); - $base = strtok($base,'.'); - $suffix = strtok('.'); - $basecsim = $dir.'/'.$base.'_csim_.html'; - $baseimg = $base.'.'.$this->img->img_format; - - // Check that apache can write to directory specified - - if( file_exists($dir) && !is_writeable($dir) ) { - JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.'); - } - - // Make sure directory exists - $this->cache->MakeDirs($dir); - - // Write the image file - $this->Stroke(CSIMCACHE_DIR.$baseimg); - - // Construct wrapper HTML and write to file and send it back to browser - $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n". - 'title->GetTextHeight($this->img) + $this->title->margin + 5 : 0 ) + - ($this->subtitle->t != '' ? - $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 : 0 ) + - ($this->subsubtitle->t != '' ? - $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 : 0 ) ; - - - $btotrequired = 0; - if($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels ) { - // Minimum bottom margin - if( $this->xaxis->title->t != '' ) { - if( $this->img->a == 90 ) - $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 5 ; - else - $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 5 ; - } - else - $btotrequired = 0; - - if( $this->img->a == 90 ) { - $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style, - $this->yaxis->font_size); - $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle); - } - else { - $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style, - $this->xaxis->font_size); - $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle); - } - - $btotrequired += $lh + 5; - } - - if( $this->img->a == 90 ) { - // DO Nothing. It gets too messy to do this properly for 90 deg... - } - else{ - if( $this->img->top_margin < $totrequired ) { - $this->SetMargin($this->img->left_margin,$this->img->right_margin, - $totrequired,$this->img->bottom_margin); - } - if( $this->img->bottom_margin < $btotrequired ) { - $this->SetMargin($this->img->left_margin,$this->img->right_margin, - $this->img->top_margin,$btotrequired); - } - } - } - - // Stroke the graph - // $aStrokeFileName If != "" the image will be written to this file and NOT - // streamed back to the browser - function Stroke($aStrokeFileName="") { - - // Fist make a sanity check that user has specified a scale - if( empty($this->yscale) ) { - JpGraphError::RaiseL(25031);//('You must specify what scale to use with a call to Graph::SetScale().'); - } - - // Start by adjusting the margin so that potential titles will fit. - $this->AdjustMarginsForTitles(); - - // Setup scale constants - if( $this->yscale ) $this->yscale->InitConstants($this->img); - if( $this->xscale ) $this->xscale->InitConstants($this->img); - if( $this->y2scale ) $this->y2scale->InitConstants($this->img); - - $n=count($this->ynscale); - for($i=0; $i < $n; ++$i) { - if( $this->ynscale[$i] ) $this->ynscale[$i]->InitConstants($this->img); - } - - // If the filename is the predefined value = '_csim_special_' - // we assume that the call to stroke only needs to do enough - // to correctly generate the CSIM maps. - // We use this variable to skip things we don't strictly need - // to do to generate the image map to improve performance - // a best we can. Therefor you will see a lot of tests !$_csim in the - // code below. - $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); - - // We need to know if we have stroked the plot in the - // GetCSIMareas. Otherwise the CSIM hasn't been generated - // and in the case of GetCSIM called before stroke to generate - // CSIM without storing an image to disk GetCSIM must call Stroke. - $this->iHasStroked = true; - - // Do any pre-stroke adjustment that is needed by the different plot types - // (i.e bar plots want's to add an offset to the x-labels etc) - for($i=0; $i < count($this->plots) ; ++$i ) { - $this->plots[$i]->PreStrokeAdjust($this); - $this->plots[$i]->DoLegend($this); - } - - // Any plots on the second Y scale? - if( $this->y2scale != null ) { - for($i=0; $iy2plots) ; ++$i ) { - $this->y2plots[$i]->PreStrokeAdjust($this); - $this->y2plots[$i]->DoLegend($this); - } - } - - // Any plots on the extra Y axises? - $n = count($this->ynaxis); - for($i=0; $i<$n ; ++$i ) { - if( $this->ynplots == null || $this->ynplots[$i] == null) { - JpGraphError::RaiseL(25032,$i);//("No plots for Y-axis nbr:$i"); - } - $m = count($this->ynplots[$i]); - for($j=0; $j < $m; ++$j ) { - $this->ynplots[$i][$j]->PreStrokeAdjust($this); - $this->ynplots[$i][$j]->DoLegend($this); - } - } - - - // Bail out if any of the Y-axis not been specified and - // has no plots. (This means it is impossible to do autoscaling and - // no other scale was given so we can't possible draw anything). If you use manual - // scaling you also have to supply the tick steps as well. - if( (!$this->yscale->IsSpecified() && count($this->plots)==0) || - ($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) { - //$e = "n=".count($this->y2plots)."\n"; - // $e = "Can't draw unspecified Y-scale.
\nYou have either:
\n"; - // $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots
\n"; - // $e .= "2. Specified a scale manually but have forgot to specify the tick steps"; - JpGraphError::RaiseL(25026); - } - - // Bail out if no plots and no specified X-scale - if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) ) - JpGraphError::RaiseL(25034);//("JpGraph: Can't draw unspecified X-scale.
No plots.
"); - - //Check if we should autoscale y-axis - if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) { - list($min,$max) = $this->GetPlotsYMinMax($this->plots); - $lres = $this->GetLinesYMinMax($this->lines); - if( is_array($lres) ) { - list($linmin,$linmax) = $lres ; - $min = min($min,$linmin); - $max = max($max,$linmax); - } - $tres = $this->GetTextsYMinMax(); - if( is_array($tres) ) { - list($tmin,$tmax) = $tres ; - $min = min($min,$tmin); - $max = max($max,$tmax); - } - $this->yscale->AutoScale($this->img,$min,$max, - $this->img->plotheight/$this->ytick_factor); - } - elseif( $this->yscale->IsSpecified() && - ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) { - // The tick calculation will use the user suplied min/max values to determine - // the ticks. If auto_ticks is false the exact user specifed min and max - // values will be used for the scale. - // If auto_ticks is true then the scale might be slightly adjusted - // so that the min and max values falls on an even major step. - $min = $this->yscale->scale[0]; - $max = $this->yscale->scale[1]; - $this->yscale->AutoScale($this->img,$min,$max, - $this->img->plotheight/$this->ytick_factor, - $this->yscale->auto_ticks); - } - - if( $this->y2scale != null) { - - if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) { - list($min,$max) = $this->GetPlotsYMinMax($this->y2plots); - $lres = $this->GetLinesYMinMax($this->y2lines); - if( is_array($lres) ) { - list($linmin,$linmax) = $lres ; - $min = min($min,$linmin); - $max = max($max,$linmax); - } - $tres = $this->GetTextsYMinMax(true); - if( is_array($tres) ) { - list($tmin,$tmax) = $tres ; - $min = min($min,$tmin); - $max = max($max,$tmax); - } - $this->y2scale->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor); - } - elseif( $this->y2scale->IsSpecified() && - ( $this->y2scale->auto_ticks || !$this->y2scale->ticks->IsSpecified()) ) { - // The tick calculation will use the user suplied min/max values to determine - // the ticks. If auto_ticks is false the exact user specifed min and max - // values will be used for the scale. - // If auto_ticks is true then the scale might be slightly adjusted - // so that the min and max values falls on an even major step. - $min = $this->y2scale->scale[0]; - $max = $this->y2scale->scale[1]; - $this->y2scale->AutoScale($this->img,$min,$max, - $this->img->plotheight/$this->ytick_factor, - $this->y2scale->auto_ticks); - } - } - - // - // Autoscale the multiple Y-axis - // - $n = count($this->ynaxis); - for( $i=0; $i < $n; ++$i ) { - if( $this->ynscale[$i] != null) { - if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) { - list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]); - $this->ynscale[$i]->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor); - } - elseif( $this->ynscale[$i]->IsSpecified() && - ( $this->ynscale[$i]->auto_ticks || !$this->ynscale[$i]->ticks->IsSpecified()) ) { - // The tick calculation will use the user suplied min/max values to determine - // the ticks. If auto_ticks is false the exact user specifed min and max - // values will be used for the scale. - // If auto_ticks is true then the scale might be slightly adjusted - // so that the min and max values falls on an even major step. - $min = $this->ynscale[$i]->scale[0]; - $max = $this->ynscale[$i]->scale[1]; - $this->ynscale[$i]->AutoScale($this->img,$min,$max, - $this->img->plotheight/$this->ytick_factor, - $this->ynscale[$i]->auto_ticks); - } - } - } - - - //Check if we should autoscale x-axis - if( !$this->xscale->IsSpecified() ) { - if( substr($this->axtype,0,4) == "text" ) { - $max=0; - $n = count($this->plots); - for($i=0; $i < $n; ++$i ) { - $p = $this->plots[$i]; - // We need some unfortunate sub class knowledge here in order - // to increase number of data points in case it is a line plot - // which has the barcenter set. If not it could mean that the - // last point of the data is outside the scale since the barcenter - // settings means that we will shift the entire plot half a tick step - // to the right in oder to align with the center of the bars. - if( is_a($p,'BarPlot') || empty($p->barcenter)) { - $max=max($max,$p->numpoints-1); - } - else { - $max=max($max,$p->numpoints); - } - } - $min=0; - if( $this->y2axis != null ) { - foreach( $this->y2plots as $p ) { - $max=max($max,$p->numpoints-1); - } - } - $n = count($this->ynaxis); - for( $i=0; $i < $n; ++$i ) { - if( $this->ynaxis[$i] != null) { - foreach( $this->ynplots[$i] as $p ) { - $max=max($max,$p->numpoints-1); - } - } - } - - $this->xscale->Update($this->img,$min,$max); - $this->xscale->ticks->Set($this->xaxis->tick_step,1); - $this->xscale->ticks->SupressMinorTickMarks(); - } - else { - list($min,$max) = $this->GetXMinMax(); - $lres = $this->GetLinesXMinMax($this->lines); - if( $lres ) { - list($linmin,$linmax) = $lres ; - $min = min($min,$linmin); - $max = max($max,$linmax); - } - $lres = $this->GetLinesXMinMax($this->y2lines); - if( $lres ) { - list($linmin,$linmax) = $lres ; - $min = min($min,$linmin); - $max = max($max,$linmax); - } - - $tres = $this->GetTextsXMinMax(); - if( $tres ) { - list($tmin,$tmax) = $tres ; - $min = min($min,$tmin); - $max = max($max,$tmax); - } - - $tres = $this->GetTextsXMinMax(true); - if( $tres ) { - list($tmin,$tmax) = $tres ; - $min = min($min,$tmin); - $max = max($max,$tmax); - } - - $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor)); - } - - //Adjust position of y-axis and y2-axis to minimum/maximum of x-scale - if( !is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos) ) - $this->yaxis->SetPos($this->xscale->GetMinVal()); - if( $this->y2axis != null ) { - if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) - $this->y2axis->SetPos($this->xscale->GetMaxVal()); - $this->y2axis->SetTitleSide(SIDE_RIGHT); - } - - $n = count($this->ynaxis); - $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0; - for( $i=0; $i < $n; ++$i ) { - if( $this->ynaxis[$i] != null ) { - if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) { - $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal()); - $this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj); - } - $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT); - } - } - } - elseif( $this->xscale->IsSpecified() && - ( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) { - // The tick calculation will use the user suplied min/max values to determine - // the ticks. If auto_ticks is false the exact user specifed min and max - // values will be used for the scale. - // If auto_ticks is true then the scale might be slightly adjusted - // so that the min and max values falls on an even major step. - $min = $this->xscale->scale[0]; - $max = $this->xscale->scale[1]; - - - $this->xscale->AutoScale($this->img,$min,$max, - $this->img->plotwidth/$this->xtick_factor, - false); - - if( $this->y2axis != null ) { - if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) - $this->y2axis->SetPos($this->xscale->GetMaxVal()); - $this->y2axis->SetTitleSide(SIDE_RIGHT); - } - - } - - // If we have a negative values and x-axis position is at 0 - // we need to supress the first and possible the last tick since - // they will be drawn on top of the y-axis (and possible y2 axis) - // The test below might seem strange the reasone being that if - // the user hasn't specified a value for position this will not - // be set until we do the stroke for the axis so as of now it - // is undefined. - // For X-text scale we ignore all this since the tick are usually - // much further in and not close to the Y-axis. Hence the test - // for 'text' - - if( ($this->yaxis->pos==$this->xscale->GetMinVal() || - (is_string($this->yaxis->pos) && $this->yaxis->pos=='min')) && - !is_numeric($this->xaxis->pos) && $this->yscale->GetMinVal() < 0 && - substr($this->axtype,0,4) != 'text' && $this->xaxis->pos!="min" ) { - - //$this->yscale->ticks->SupressZeroLabel(false); - $this->xscale->ticks->SupressFirst(); - if( $this->y2axis != null ) { - $this->xscale->ticks->SupressLast(); - } - } - elseif( !is_numeric($this->yaxis->pos) && $this->yaxis->pos=='max' ) { - $this->xscale->ticks->SupressLast(); - } - - - if( !$_csim ) { - $this->StrokePlotArea(); - if( $this->iIconDepth == DEPTH_BACK ) { - $this->StrokeIcons(); - } - } - $this->StrokeAxis(); - - // Stroke bands - if( $this->bands != null && !$_csim) - for($i=0; $i < count($this->bands); ++$i) { - // Stroke all bands that asks to be in the background - if( $this->bands[$i]->depth == DEPTH_BACK ) - $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale); - } - - if( $this->y2bands != null && $this->y2scale != null && !$_csim ) - for($i=0; $i < count($this->y2bands); ++$i) { - // Stroke all bands that asks to be in the foreground - if( $this->y2bands[$i]->depth == DEPTH_BACK ) - $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale); - } - - - if( $this->grid_depth == DEPTH_BACK && !$_csim) { - $this->ygrid->Stroke(); - $this->xgrid->Stroke(); - } - - // Stroke Y2-axis - if( $this->y2axis != null && !$_csim) { - $this->y2axis->Stroke($this->xscale); - $this->y2grid->Stroke(); - } - - // Stroke yn-axis - $n = count($this->ynaxis); - for( $i=0; $i < $n; ++$i ) { - $this->ynaxis[$i]->Stroke($this->xscale); - } - - $oldoff=$this->xscale->off; - if(substr($this->axtype,0,4)=="text") { - if( $this->text_scale_abscenteroff > -1 ) { - // For a text scale the scale factor is the number of pixel per step. - // Hence we can use the scale factor as a substitute for number of pixels - // per major scale step and use that in order to adjust the offset so that - // an object of width "abscenteroff" becomes centered. - $this->xscale->off += round($this->xscale->scale_factor/2)-round($this->text_scale_abscenteroff/2); - } - else { - $this->xscale->off += - ceil($this->xscale->scale_factor*$this->text_scale_off*$this->xscale->ticks->minor_step); - } - } - - if( $this->iDoClipping ) { - $oldimage = $this->img->CloneCanvasH(); - } - - if( ! $this->y2orderback ) { - // Stroke all plots for Y axis - for($i=0; $i < count($this->plots); ++$i) { - $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale); - $this->plots[$i]->StrokeMargin($this->img); - } - } - - // Stroke all plots for Y2 axis - if( $this->y2scale != null ) - for($i=0; $i< count($this->y2plots); ++$i ) { - $this->y2plots[$i]->Stroke($this->img,$this->xscale,$this->y2scale); - } - - if( $this->y2orderback ) { - // Stroke all plots for Y1 axis - for($i=0; $i < count($this->plots); ++$i) { - $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale); - $this->plots[$i]->StrokeMargin($this->img); - } - } - - $n = count($this->ynaxis); - for( $i=0; $i < $n; ++$i ) { - $m = count($this->ynplots[$i]); - for( $j=0; $j < $m; ++$j ) { - $this->ynplots[$i][$j]->Stroke($this->img,$this->xscale,$this->ynscale[$i]); - $this->ynplots[$i][$j]->StrokeMargin($this->img); - } - } - - if( $this->iIconDepth == DEPTH_FRONT) { - $this->StrokeIcons(); - } - - if( $this->iDoClipping ) { - // Clipping only supports graphs at 0 and 90 degrees - if( $this->img->a == 0 ) { - $this->img->CopyCanvasH($oldimage,$this->img->img, - $this->img->left_margin,$this->img->top_margin, - $this->img->left_margin,$this->img->top_margin, - $this->img->plotwidth+1,$this->img->plotheight); - } - elseif( $this->img->a == 90 ) { - $adj = ($this->img->height - $this->img->width)/2; - $this->img->CopyCanvasH($oldimage,$this->img->img, - $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, - $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, - $this->img->plotheight+1,$this->img->plotwidth); - } - else { - 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.'); - } - $this->img->Destroy(); - $this->img->SetCanvasH($oldimage); - } - - $this->xscale->off=$oldoff; - - if( $this->grid_depth == DEPTH_FRONT && !$_csim ) { - $this->ygrid->Stroke(); - $this->xgrid->Stroke(); - } - - // Stroke bands - if( $this->bands!= null ) - for($i=0; $i < count($this->bands); ++$i) { - // Stroke all bands that asks to be in the foreground - if( $this->bands[$i]->depth == DEPTH_FRONT ) - $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale); - } - - if( $this->y2bands!= null && $this->y2scale != null ) - for($i=0; $i < count($this->y2bands); ++$i) { - // Stroke all bands that asks to be in the foreground - if( $this->y2bands[$i]->depth == DEPTH_FRONT ) - $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale); - } - - - // Stroke any lines added - if( $this->lines != null ) { - for($i=0; $i < count($this->lines); ++$i) { - $this->lines[$i]->Stroke($this->img,$this->xscale,$this->yscale); - } - } - - if( $this->y2lines != null && $this->y2scale != null ) { - for($i=0; $i < count($this->y2lines); ++$i) { - $this->y2lines[$i]->Stroke($this->img,$this->xscale,$this->y2scale); - } - } - - // Finally draw the axis again since some plots may have nagged - // the axis in the edges.However we do no stroke the labels again - // since any user defined callback would be called twice. It also - // enhances performance. - - if( !$_csim ) - $this->StrokeAxis(false); - - if( $this->y2scale != null && !$_csim ) - $this->y2axis->Stroke($this->xscale,false); - - if( !$_csim ) { - $this->StrokePlotBox(); - } - - // The titles and legends never gets rotated so make sure - // that the angle is 0 before stroking them - $aa = $this->img->SetAngle(0); - $this->StrokeTitles(); - $this->footer->Stroke($this->img); - $this->legend->Stroke($this->img); - $this->img->SetAngle($aa); - $this->StrokeTexts(); - $this->StrokeTables(); - - if( !$_csim ) { - - $this->img->SetAngle($aa); - - // Draw an outline around the image map - if(_JPG_DEBUG) { - $this->DisplayClientSideaImageMapAreas(); - } - - // Adjust the appearance of the image - $this->AdjustSaturationBrightnessContrast(); - - // Should we do any final image transformation - if( $this->iImgTrans ) { - if( !class_exists('ImgTrans') ) { - require_once('jpgraph_imgtrans.php'); - //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.'); - } - - $tform = new ImgTrans($this->img->img); - $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, - $this->iImgTransDirection,$this->iImgTransHighQ, - $this->iImgTransMinSize,$this->iImgTransFillColor, - $this->iImgTransBorder); - } - - // If the filename is given as the special "__handle" - // then the image handler is returned and the image is NOT - // streamed back - if( $aStrokeFileName == _IMG_HANDLER ) { - return $this->img->img; - } - else { - // Finally stream the generated picture - $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); - } - } - } - - function SetAxisLabelBackground($aType,$aXFColor='lightgray',$aXColor='black',$aYFColor='lightgray',$aYColor='black') { - $this->iAxisLblBgType = $aType; - $this->iXAxisLblBgFillColor = $aXFColor; - $this->iXAxisLblBgColor = $aXColor; - $this->iYAxisLblBgFillColor = $aYFColor; - $this->iYAxisLblBgColor = $aYColor; - } - -//--------------- -// PRIVATE METHODS - - function StrokeAxisLabelBackground() { - // Types - // 0 = No background - // 1 = Only X-labels, length of axis - // 2 = Only Y-labels, length of axis - // 3 = As 1 but extends to width of graph - // 4 = As 2 but extends to height of graph - // 5 = Combination of 3 & 4 - // 6 = Combination of 1 & 2 - - $t = $this->iAxisLblBgType ; - if( $t < 1 ) return; - // Stroke optional X-axis label background color - if( $t == 1 || $t == 3 || $t == 5 || $t == 6 ) { - $this->img->PushColor($this->iXAxisLblBgFillColor); - if( $t == 1 || $t == 6 ) { - $xl = $this->img->left_margin; - $yu = $this->img->height - $this->img->bottom_margin + 1; - $xr = $this->img->width - $this->img->right_margin ; - $yl = $this->img->height-1-$this->frame_weight; - } - else { // t==3 || t==5 - $xl = $this->frame_weight; - $yu = $this->img->height - $this->img->bottom_margin + 1; - $xr = $this->img->width - 1 - $this->frame_weight; - $yl = $this->img->height-1-$this->frame_weight; - } - - $this->img->FilledRectangle($xl,$yu,$xr,$yl); - $this->img->PopColor(); - - // Check if we should add the vertical lines at left and right edge - if( $this->iXAxisLblBgColor !== '' ) { - $this->img->PushColor($this->iXAxisLblBgColor); - if( $t == 1 || $t == 6 ) { - $this->img->Line($xl,$yu,$xl,$yl); - $this->img->Line($xr,$yu,$xr,$yl); - } - else { - $xl = $this->img->width - $this->img->right_margin ; - $this->img->Line($xl,$yu-1,$xr,$yu-1); - } - $this->img->PopColor(); - } - } - - if( $t == 2 || $t == 4 || $t == 5 || $t == 6 ) { - $this->img->PushColor($this->iYAxisLblBgFillColor); - if( $t == 2 || $t == 6 ) { - $xl = $this->frame_weight; - $yu = $this->frame_weight+$this->img->top_margin; - $xr = $this->img->left_margin - 1; - $yl = $this->img->height - $this->img->bottom_margin + 1; - } - else { - $xl = $this->frame_weight; - $yu = $this->frame_weight; - $xr = $this->img->left_margin - 1; - $yl = $this->img->height-1-$this->frame_weight; - } - - $this->img->FilledRectangle($xl,$yu,$xr,$yl); - $this->img->PopColor(); - - // Check if we should add the vertical lines at left and right edge - if( $this->iXAxisLblBgColor !== '' ) { - $this->img->PushColor($this->iXAxisLblBgColor); - if( $t == 2 || $t == 6 ) { - $this->img->Line($xl,$yu-1,$xr,$yu-1); - $this->img->Line($xl,$yl-1,$xr,$yl-1); - } - else { - $this->img->Line($xr+1,$yu,$xr+1,$this->img->top_margin); - } - $this->img->PopColor(); - } - - } - } - - function StrokeAxis($aStrokeLabels=true) { - - if( $aStrokeLabels ) { - $this->StrokeAxisLabelBackground(); - } - - // Stroke axis - if( $this->iAxisStyle != AXSTYLE_SIMPLE ) { - switch( $this->iAxisStyle ) { - case AXSTYLE_BOXIN : - $toppos = SIDE_DOWN; - $bottompos = SIDE_UP; - $leftpos = SIDE_RIGHT; - $rightpos = SIDE_LEFT; - break; - case AXSTYLE_BOXOUT : - $toppos = SIDE_UP; - $bottompos = SIDE_DOWN; - $leftpos = SIDE_LEFT; - $rightpos = SIDE_RIGHT; - break; - case AXSTYLE_YBOXIN: - $toppos = -100; - $bottompos = SIDE_UP; - $leftpos = SIDE_RIGHT; - $rightpos = SIDE_LEFT; - break; - case AXSTYLE_YBOXOUT: - $toppos = -100; - $bottompos = SIDE_DOWN; - $leftpos = SIDE_LEFT; - $rightpos = SIDE_RIGHT; - break; - default: - JpGRaphError::RaiseL(25036,$this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle); - break; - } - $this->xaxis->SetPos('min'); - - // By default we hide the first label so it doesn't cross the - // Y-axis in case the positon hasn't been set by the user. - // However, if we use a box we always want the first value - // displayed so we make sure it will be displayed. - $this->xscale->ticks->SupressFirst(false); - - $this->xaxis->SetLabelSide(SIDE_DOWN); - $this->xaxis->scale->ticks->SetSide($bottompos); - $this->xaxis->Stroke($this->yscale); - - if( $toppos != -100 ) { - // To avoid side effects we work on a new copy - $maxis = $this->xaxis; - $maxis->SetPos('max'); - $maxis->SetLabelSide(SIDE_UP); - $maxis->SetLabelMargin(7); - $this->xaxis->scale->ticks->SetSide($toppos); - $maxis->Stroke($this->yscale); - } - - $this->yaxis->SetPos('min'); - $this->yaxis->SetLabelMargin(10); - $this->yaxis->SetLabelSide(SIDE_LEFT); - $this->yaxis->scale->ticks->SetSide($leftpos); - $this->yaxis->Stroke($this->xscale); - - $myaxis = $this->yaxis; - $myaxis->SetPos('max'); - $myaxis->SetLabelMargin(10); - $myaxis->SetLabelSide(SIDE_RIGHT); - $myaxis->title->Set(''); - $myaxis->scale->ticks->SetSide($rightpos); - $myaxis->Stroke($this->xscale); - - } - else { - $this->xaxis->Stroke($this->yscale,$aStrokeLabels); - $this->yaxis->Stroke($this->xscale,$aStrokeLabels); - } - } - - - // Private helper function for backgound image - function LoadBkgImage($aImgFormat='',$aFile='',$aImgStr='') { - if( $aImgStr != '' ) { - return Image::CreateFromString($aImgStr); - } - if( $aFile == '' ) - $aFile = $this->background_image; - // Remove case sensitivity and setup appropriate function to create image - // Get file extension. This should be the LAST '.' separated part of the filename - $e = explode('.',$aFile); - $ext = strtolower($e[count($e)-1]); - if ($ext == "jpeg") { - $ext = "jpg"; - } - - if( trim($ext) == '' ) - $ext = 'png'; // Assume PNG if no extension specified - - if( $aImgFormat == '' ) - $imgtag = $ext; - else - $imgtag = $aImgFormat; - - $supported = imagetypes(); - if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) || - ( $ext == 'gif' && !($supported & IMG_GIF) ) || - ( $ext == 'png' && !($supported & IMG_PNG) ) ) { - JpGraphError::RaiseL(25037,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. '); - } - - - if( $imgtag == "jpg" || $imgtag == "jpeg") - { - $f = "imagecreatefromjpeg"; - $imgtag = "jpg"; - } - else - { - $f = "imagecreatefrom".$imgtag; - } - - // Compare specified image type and file extension - if( $imgtag != $ext ) { - //$t = "Background image seems to be of different type (has different file extension) than specified imagetype. Specified: '".$aImgFormat."'File: '".$aFile."'"; - JpGraphError::RaiseL(25038, $aImgFormat, $aFile); - } - - $img = @$f($aFile); - if( !$img ) { - JpGraphError::RaiseL(25039,$aFile);//(" Can't read background image: '".$aFile."'"); - } - return $img; - } - - function StrokeBackgroundGrad() { - if( $this->bkg_gradtype < 0 ) - return; - $grad = new Gradient($this->img); - if( $this->bkg_gradstyle == BGRAD_PLOT ) { - $xl = $this->img->left_margin; - $yt = $this->img->top_margin; - $xr = $xl + $this->img->plotwidth+1 ; - $yb = $yt + $this->img->plotheight ; - $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype); - } - else { - $xl = 0; - $yt = 0; - $xr = $xl + $this->img->width - 1; - $yb = $yt + $this->img->height; - if( $this->doshadow ) { - $xr -= $this->shadow_width; - $yb -= $this->shadow_width; - } - if( $this->doframe ) { - $yt += $this->frame_weight; - $yb -= $this->frame_weight; - $xl += $this->frame_weight; - $xr -= $this->frame_weight; - } - $aa = $this->img->SetAngle(0); - $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype); - $aa = $this->img->SetAngle($aa); - } - } - - function StrokeFrameBackground() { - if( $this->background_image != "" && $this->background_cflag != "" ) { - JpGraphError::RaiseL(25040);//('It is not possible to specify both a background image and a background country flag.'); - } - if( $this->background_image != "" ) { - $bkgimg = $this->LoadBkgImage($this->background_image_format); - $this->img->_AdjBrightContrast($bkgimg,$this->background_image_bright, - $this->background_image_contr); - $this->img->_AdjSat($bkgimg,$this->background_image_sat); - } - elseif( $this->background_cflag != "" ) { - if( ! class_exists('FlagImages') ) { - JpGraphError::RaiseL(25041);//('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.'); - } - $fobj = new FlagImages(FLAGSIZE4); - $dummy=''; - $bkgimg = $fobj->GetImgByName($this->background_cflag,$dummy); - $this->background_image_mix = $this->background_cflag_mix; - $this->background_image_type = $this->background_cflag_type; - } - else { - return ; - } - - $bw = ImageSX($bkgimg); - $bh = ImageSY($bkgimg); - - // No matter what the angle is we always stroke the image and frame - // assuming it is 0 degree - $aa = $this->img->SetAngle(0); - - switch( $this->background_image_type ) { - case BGIMG_FILLPLOT: // Resize to just fill the plotarea - $this->FillMarginArea(); - $this->StrokeFrame(); - $this->FillPlotArea(); - $this->img->CopyMerge($bkgimg, - $this->img->left_margin,$this->img->top_margin, - 0,0,$this->img->plotwidth+1,$this->img->plotheight, - $bw,$bh,$this->background_image_mix); - break; - case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit - $hadj=0; $vadj=0; - if( $this->doshadow ) { - $hadj = $this->shadow_width; - $vadj = $this->shadow_width; - } - $this->FillMarginArea(); - $this->FillPlotArea(); - $this->img->CopyMerge($bkgimg,0,0,0,0,$this->img->width-$hadj,$this->img->height-$vadj, - $bw,$bh,$this->background_image_mix); - $this->StrokeFrame(); - break; - case BGIMG_COPY: // Just copy the image from left corner, no resizing - $this->FillMarginArea(); - $this->FillPlotArea(); - $this->img->CopyMerge($bkgimg,0,0,0,0,$bw,$bh, - $bw,$bh,$this->background_image_mix); - $this->StrokeFrame(); - break; - case BGIMG_CENTER: // Center original image in the plot area - $this->FillMarginArea(); - $this->FillPlotArea(); - $centerx = round($this->img->plotwidth/2+$this->img->left_margin-$bw/2); - $centery = round($this->img->plotheight/2+$this->img->top_margin-$bh/2); - $this->img->CopyMerge($bkgimg,$centerx,$centery,0,0,$bw,$bh, - $bw,$bh,$this->background_image_mix); - $this->StrokeFrame(); - break; - default: - JpGraphError::RaiseL(25042);//(" Unknown background image layout"); - } - $this->img->SetAngle($aa); - } - - // Private - // Draw a frame around the image - function StrokeFrame() { - if( !$this->doframe ) return; - - if( $this->background_image_type <= 1 && - ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_PLOT)) ) { - $c = $this->margin_color; - } - else { - $c = false; - } - - if( $this->doshadow ) { - $this->img->SetColor($this->frame_color); - $this->img->ShadowRectangle(0,0,$this->img->width,$this->img->height, - $c,$this->shadow_width,$this->shadow_color); - } - elseif( $this->framebevel ) { - if( $c ) { - $this->img->SetColor($this->margin_color); - $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1); - } - $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2, - $this->framebeveldepth, - $this->framebevelcolor1,$this->framebevelcolor2); - if( $this->framebevelborder ) { - $this->img->SetColor($this->framebevelbordercolor); - $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); - } - } - else { - $this->img->SetLineWeight($this->frame_weight); - if( $c ) { - $this->img->SetColor($this->margin_color); - $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1); - } - $this->img->SetColor($this->frame_color); - $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); - } - } - - function FillMarginArea() { - $hadj=0; $vadj=0; - if( $this->doshadow ) { - $hadj = $this->shadow_width; - $vadj = $this->shadow_width; - } - - $this->img->SetColor($this->margin_color); -// $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->height-1-$vadj); - - $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->top_margin); - $this->img->FilledRectangle(0,$this->img->top_margin,$this->img->left_margin,$this->img->height-1-$hadj); - $this->img->FilledRectangle($this->img->left_margin+1, - $this->img->height-$this->img->bottom_margin, - $this->img->width-1-$hadj, - $this->img->height-1-$hadj); - $this->img->FilledRectangle($this->img->width-$this->img->right_margin, - $this->img->top_margin+1, - $this->img->width-1-$hadj, - $this->img->height-$this->img->bottom_margin-1); - } - - function FillPlotArea() { - $this->img->PushColor($this->plotarea_color); - $this->img->FilledRectangle($this->img->left_margin, - $this->img->top_margin, - $this->img->width-$this->img->right_margin, - $this->img->height-$this->img->bottom_margin); - $this->img->PopColor(); - } - - // Stroke the plot area with either a solid color or a background image - function StrokePlotArea() { - // Note: To be consistent we really should take a possible shadow - // into account. However, that causes some problem for the LinearScale class - // since in the current design it does not have any links to class Graph which - // means it has no way of compensating for the adjusted plotarea in case of a - // shadow. So, until I redesign LinearScale we can't compensate for this. - // So just set the two adjustment parameters to zero for now. - $boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ; - $adj = 0; //$this->doshadow ? $this->shadow_width : 0 ; - - if( $this->background_image != "" || $this->background_cflag != "" ) { - $this->StrokeFrameBackground(); - } - else { - $aa = $this->img->SetAngle(0); - $this->StrokeFrame(); - $aa = $this->img->SetAngle($aa); - $this->StrokeBackgroundGrad(); - if( $this->bkg_gradtype < 0 || - ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_MARGIN) ) { - $this->FillPlotArea(); - } - } - } - - function StrokeIcons() { - $n = count($this->iIcons); - for( $i=0; $i < $n; ++$i ) { - $this->iIcons[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); - } - } - - function StrokePlotBox() { - // Should we draw a box around the plot area? - if( $this->boxed ) { - $this->img->SetLineWeight(1); - $this->img->SetLineStyle('solid'); - $this->img->SetColor($this->box_color); - for($i=0; $i < $this->box_weight; ++$i ) { - $this->img->Rectangle( - $this->img->left_margin-$i,$this->img->top_margin-$i, - $this->img->width-$this->img->right_margin+$i, - $this->img->height-$this->img->bottom_margin+$i); - } - } - } - - function SetTitleBackgroundFillStyle($aStyle,$aColor1='black',$aColor2='white') { - $this->titlebkg_fillstyle = $aStyle; - $this->titlebkg_scolor1 = $aColor1; - $this->titlebkg_scolor2 = $aColor2; - } - - function SetTitleBackground($aBackColor='gray', $aStyle=TITLEBKG_STYLE1, $aFrameStyle=TITLEBKG_FRAME_NONE, $aFrameColor='black', $aFrameWeight=1, $aBevelHeight=3, $aEnable=true) { - $this->titlebackground = $aEnable; - $this->titlebackground_color = $aBackColor; - $this->titlebackground_style = $aStyle; - $this->titlebackground_framecolor = $aFrameColor; - $this->titlebackground_framestyle = $aFrameStyle; - $this->titlebackground_frameweight = $aFrameWeight; - $this->titlebackground_bevelheight = $aBevelHeight ; - } - - - function StrokeTitles() { - - $margin=3; - - if( $this->titlebackground ) { - - // Find out height - $this->title->margin += 2 ; - $h = $this->title->GetTextHeight($this->img)+$this->title->margin+$margin; - if( $this->subtitle->t != "" && !$this->subtitle->hide ) { - $h += $this->subtitle->GetTextHeight($this->img)+$margin+ - $this->subtitle->margin; - $h += 2; - } - if( $this->subsubtitle->t != "" && !$this->subsubtitle->hide ) { - $h += $this->subsubtitle->GetTextHeight($this->img)+$margin+ - $this->subsubtitle->margin; - $h += 2; - } - $this->img->PushColor($this->titlebackground_color); - if( $this->titlebackground_style === TITLEBKG_STYLE1 ) { - // Inside the frame - if( $this->framebevel ) { - $x1 = $y1 = $this->framebeveldepth + 1 ; - $x2 = $this->img->width - $this->framebeveldepth - 2 ; - $this->title->margin += $this->framebeveldepth + 1 ; - $h += $y1 ; - $h += 2; - } - else { - $x1 = $y1 = $this->frame_weight; - $x2 = $this->img->width - 2*$x1; - } - } - elseif( $this->titlebackground_style === TITLEBKG_STYLE2 ) { - // Cover the frame as well - $x1 = $y1 = 0; - $x2 = $this->img->width - 1 ; - } - elseif( $this->titlebackground_style === TITLEBKG_STYLE3 ) { - // Cover the frame as well (the difference is that - // for style==3 a bevel frame border is on top - // of the title background) - $x1 = $y1 = 0; - $x2 = $this->img->width - 1 ; - $h += $this->framebeveldepth ; - $this->title->margin += $this->framebeveldepth ; - } - else { - JpGraphError::RaiseL(25043);//('Unknown title background style.'); - } - - if( $this->titlebackground_framestyle === 3 ) { - $h += $this->titlebackground_bevelheight*2 + 1 ; - $this->title->margin += $this->titlebackground_bevelheight ; - } - - if( $this->doshadow ) { - $x2 -= $this->shadow_width ; - } - - $indent=0; - if( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) { - $ind = $this->titlebackground_bevelheight; - } - - if( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_HSTRIPED ) { - $this->img->FilledRectangle2($x1+$ind,$y1+$ind,$x2-$ind,$h-$ind, - $this->titlebkg_scolor1, - $this->titlebkg_scolor2); - } - elseif( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_VSTRIPED ) { - $this->img->FilledRectangle2($x1+$ind,$y1+$ind,$x2-$ind,$h-$ind, - $this->titlebkg_scolor1, - $this->titlebkg_scolor2,2); - } - else { - // Solid fill - $this->img->FilledRectangle($x1,$y1,$x2,$h); - } - $this->img->PopColor(); - - $this->img->PushColor($this->titlebackground_framecolor); - $this->img->SetLineWeight($this->titlebackground_frameweight); - if( $this->titlebackground_framestyle == TITLEBKG_FRAME_FULL ) { - // Frame background - $this->img->Rectangle($x1,$y1,$x2,$h); - } - elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM ) { - // Bottom line only - $this->img->Line($x1,$h,$x2,$h); - } - elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) { - $this->img->Bevel($x1,$y1,$x2,$h,$this->titlebackground_bevelheight); - } - $this->img->PopColor(); - - // This is clumsy. But we neeed to stroke the whole graph frame if it is - // set to bevel to get the bevel shading on top of the text background - if( $this->framebevel && $this->doframe && - $this->titlebackground_style === 3 ) { - $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2, - $this->framebeveldepth, - $this->framebevelcolor1,$this->framebevelcolor2); - if( $this->framebevelborder ) { - $this->img->SetColor($this->framebevelbordercolor); - $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); - } - } - } - - // Stroke title - $y = $this->title->margin; - if( $this->title->halign == 'center' ) - $this->title->Center(0,$this->img->width,$y); - elseif( $this->title->halign == 'left' ) { - $this->title->SetPos($this->title->margin+2,$y); - } - elseif( $this->title->halign == 'right' ) { - $indent = 0; - if( $this->doshadow ) - $indent = $this->shadow_width+2; - $this->title->SetPos($this->img->width-$this->title->margin-$indent,$y,'right'); - } - $this->title->Stroke($this->img); - - // ... and subtitle - $y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin; - if( $this->subtitle->halign == 'center' ) - $this->subtitle->Center(0,$this->img->width,$y); - elseif( $this->subtitle->halign == 'left' ) { - $this->subtitle->SetPos($this->subtitle->margin+2,$y); - } - elseif( $this->subtitle->halign == 'right' ) { - $indent = 0; - if( $this->doshadow ) - $indent = $this->shadow_width+2; - $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right'); - } - $this->subtitle->Stroke($this->img); - - // ... and subsubtitle - $y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin; - if( $this->subsubtitle->halign == 'center' ) - $this->subsubtitle->Center(0,$this->img->width,$y); - elseif( $this->subsubtitle->halign == 'left' ) { - $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y); - } - elseif( $this->subsubtitle->halign == 'right' ) { - $indent = 0; - if( $this->doshadow ) - $indent = $this->shadow_width+2; - $this->subsubtitle->SetPos($this->img->width-$this->subsubtitle->margin-$indent,$y,'right'); - } - $this->subsubtitle->Stroke($this->img); - - // ... and fancy title - $this->tabtitle->Stroke($this->img); - - } - - function StrokeTexts() { - // Stroke any user added text objects - if( $this->texts != null ) { - for($i=0; $i < count($this->texts); ++$i) { - $this->texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); - } - } - - if( $this->y2texts != null && $this->y2scale != null ) { - for($i=0; $i < count($this->y2texts); ++$i) { - $this->y2texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->y2scale); - } - } - - } - - function StrokeTables() { - if( $this->iTables != null ) { - $n = count($this->iTables); - for( $i=0; $i < $n; ++$i ) { - $this->iTables[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); - } - } - } - - function DisplayClientSideaImageMapAreas() { - // Debug stuff - display the outline of the image map areas - $csim=''; - foreach ($this->plots as $p) { - $csim.= $p->GetCSIMareas(); - } - $csim .= $this->legend->GetCSIMareas(); - if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) { - $this->img->SetColor($this->csimcolor); - $n = count($coords[0]); - for ($i=0; $i < $n; $i++) { - if ($coords[1][$i]=="poly") { - preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts); - $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]); - $m = count($pts[0]); - for ($j=0; $j < $m; $j++) { - $this->img->LineTo($pts[1][$j],$pts[2][$j]); - } - } else if ($coords[1][$i]=="rect") { - $pts = preg_split('/,/', $coords[2][$i]); - $this->img->SetStartPoint($pts[0],$pts[1]); - $this->img->LineTo($pts[2],$pts[1]); - $this->img->LineTo($pts[2],$pts[3]); - $this->img->LineTo($pts[0],$pts[3]); - $this->img->LineTo($pts[0],$pts[1]); - } - } - } - } - - function AdjustSaturationBrightnessContrast() { - // Adjust the brightness and contrast of the image - if( $this->image_contr || $this->image_bright ) - $this->img->AdjBrightContrast($this->image_bright,$this->image_contr); - if( $this->image_sat ) - $this->img->AdjSat($this->image_sat); - } - - // Text scale offset in fractions of a major scale step - function SetTextScaleOff($aOff) { - $this->text_scale_off = $aOff; - $this->xscale->text_scale_off = $aOff; - } - - // Text width of bar to be centered in absolute pixels - function SetTextScaleAbsCenterOff($aOff) { - $this->text_scale_abscenteroff = $aOff; - } - - // Get Y min and max values for added lines - function GetLinesYMinMax( $aLines ) { - $n = count($aLines); - if( $n == 0 ) return false; - $min = $aLines[0]->scaleposition ; - $max = $min ; - $flg = false; - for( $i=0; $i < $n; ++$i ) { - if( $aLines[$i]->direction == HORIZONTAL ) { - $flg = true ; - $v = $aLines[$i]->scaleposition ; - if( $min > $v ) $min = $v ; - if( $max < $v ) $max = $v ; - } - } - return $flg ? array($min,$max) : false ; - } - - // Get X min and max values for added lines - function GetLinesXMinMax( $aLines ) { - $n = count($aLines); - if( $n == 0 ) return false ; - $min = $aLines[0]->scaleposition ; - $max = $min ; - $flg = false; - for( $i=0; $i < $n; ++$i ) { - if( $aLines[$i]->direction == VERTICAL ) { - $flg = true ; - $v = $aLines[$i]->scaleposition ; - if( $min > $v ) $min = $v ; - if( $max < $v ) $max = $v ; - } - } - return $flg ? array($min,$max) : false ; - } - - // Get min and max values for all included plots - function GetPlotsYMinMax(&$aPlots) { - $n = count($aPlots); - $i=0; - do { - list($xmax,$max) = $aPlots[$i]->Max(); - } while( ++$i < $n && !is_numeric($max) ); - - $i=0; - do { - list($xmin,$min) = $aPlots[$i]->Min(); - } while( ++$i < $n && !is_numeric($min) ); - - if( !is_numeric($min) || !is_numeric($max) ) { - JpGraphError::RaiseL(25044);//('Cannot use autoscaling since it is impossible to determine a valid min/max value of the Y-axis (only null values).'); - } - - list($xmax,$max) = $aPlots[0]->Max(); - list($xmin,$min) = $aPlots[0]->Min(); - for($i=0; $i < count($aPlots); ++$i ) { - list($xmax,$ymax)=$aPlots[$i]->Max(); - list($xmin,$ymin)=$aPlots[$i]->Min(); - if (is_numeric($ymax)) $max=max($max,$ymax); - if (is_numeric($ymin)) $min=min($min,$ymin); - } - if( $min == '' ) $min = 0; - if( $max == '' ) $max = 0; - if( $min == 0 && $max == 0 ) { - // Special case if all values are 0 - $min=0;$max=1; - } - return array($min,$max); - } - -} // Class - - -//=================================================== -// CLASS TTF -// Description: Handle TTF font names -//=================================================== -class TTF { - var $font_files,$style_names; -//--------------- -// CONSTRUCTOR - function __construct() { - $this->style_names=array(FS_NORMAL=>'normal',FS_BOLD=>'bold',FS_ITALIC=>'italic',FS_BOLDITALIC=>'bolditalic'); - // File names for available fonts - $this->font_files=array( - FF_COURIER => array(FS_NORMAL=>'cour.ttf', FS_BOLD=>'courbd.ttf', FS_ITALIC=>'couri.ttf', FS_BOLDITALIC=>'courbi.ttf' ), - FF_GEORGIA => array(FS_NORMAL=>'georgia.ttf', FS_BOLD=>'georgiab.ttf', FS_ITALIC=>'georgiai.ttf', FS_BOLDITALIC=>'' ), - FF_TREBUCHE =>array(FS_NORMAL=>'trebuc.ttf', FS_BOLD=>'trebucbd.ttf', FS_ITALIC=>'trebucit.ttf', FS_BOLDITALIC=>'trebucbi.ttf' ), - FF_VERDANA => array(FS_NORMAL=>'verdana.ttf', FS_BOLD=>'verdanab.ttf', FS_ITALIC=>'verdanai.ttf', FS_BOLDITALIC=>'' ), - FF_TIMES => array(FS_NORMAL=>'times.ttf', FS_BOLD=>'timesbd.ttf', FS_ITALIC=>'timesi.ttf', FS_BOLDITALIC=>'timesbi.ttf' ), - FF_COMIC => array(FS_NORMAL=>'comic.ttf', FS_BOLD=>'comicbd.ttf', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_ARIAL => array(FS_NORMAL=>'arial.ttf', FS_BOLD=>'arialbd.ttf', FS_ITALIC=>'ariali.ttf', FS_BOLDITALIC=>'arialbi.ttf' ) , - FF_VERA => array(FS_NORMAL=>'Vera.ttf', FS_BOLD=>'VeraBd.ttf', FS_ITALIC=>'VeraIt.ttf', FS_BOLDITALIC=>'VeraBI.ttf' ), - FF_VERAMONO => array(FS_NORMAL=>'VeraMono.ttf', FS_BOLD=>'VeraMoBd.ttf', FS_ITALIC=>'VeraMoIt.ttf', FS_BOLDITALIC=>'VeraMoBI.ttf' ), - FF_VERASERIF => array(FS_NORMAL=>'VeraSe.ttf', FS_BOLD=>'VeraSeBd.ttf', FS_ITALIC=>'', FS_BOLDITALIC=>'' ) , - FF_SIMSUN => array(FS_NORMAL=>'simsun.ttc', FS_BOLD=>'simhei.ttf', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_CHINESE => array(FS_NORMAL=>CHINESE_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_MINCHO => array(FS_NORMAL=>MINCHO_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_PMINCHO => array(FS_NORMAL=>PMINCHO_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_GOTHIC => array(FS_NORMAL=>GOTHIC_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_PGOTHIC => array(FS_NORMAL=>PGOTHIC_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ), - FF_MINCHO => array(FS_NORMAL=>PMINCHO_TTF_FONT, FS_BOLD=>'', FS_ITALIC=>'', FS_BOLDITALIC=>'' ) -); - } - -//--------------- -// PUBLIC METHODS - // Create the TTF file from the font specification - function File($family,$style=FS_NORMAL) { - - if( $family == FF_HANDWRT || $family==FF_BOOK ) { - JpGraphError::RaiseL(25045);//('Font families FF_HANDWRT and FF_BOOK are no longer available due to copyright problem with these fonts. Fonts can no longer be distributed with JpGraph. Please download fonts from http://corefonts.sourceforge.net/'); - } - - $fam = @$this->font_files[$family]; - if( !$fam ) { - 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/"); - } - $f = @$fam[$style]; - - if( $f==='' ) - 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].'.'); - if( !$f ) { - JpGraphError::RaiseL(25048,$fam);//("Unknown font style specification [$fam]."); - } - - if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) { - $f = MBTTF_DIR.$f; - } else { - $f = TTF_DIR.$f; - } - - if( file_exists($f) === false || is_readable($f) === false ) { - JpGraphError::RaiseL(25049,$f);//("Font file \"$f\" is not readable or does not exist."); - } - return $f; - } -} // Class - -//=================================================== -// CLASS LineProperty -// Description: Holds properties for a line -//=================================================== -class LineProperty { - var $iWeight=1, $iColor="black",$iStyle="solid"; - var $iShow=true; - -//--------------- -// PUBLIC METHODS - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function SetWeight($aWeight) { - $this->iWeight = $aWeight; - } - - function SetStyle($aStyle) { - $this->iStyle = $aStyle; - } - - function Show($aShow=true) { - $this->iShow=$aShow; - } - - function Stroke(&$aImg,$aX1,$aY1,$aX2,$aY2) { - if( $this->iShow ) { - $aImg->PushColor($this->iColor); - $oldls = $aImg->line_style; - $oldlw = $aImg->line_weight; - $aImg->SetLineWeight($this->iWeight); - $aImg->SetLineStyle($this->iStyle); - $aImg->StyleLine($aX1,$aY1,$aX2,$aY2); - $aImg->PopColor($this->iColor); - $aImg->line_style = $oldls; - $aImg->line_weight = $oldlw; - - } - } -} - - -//=================================================== -// CLASS Text -// Description: Arbitrary text object that can be added to the graph -//=================================================== -class Text { - var $t,$x=0,$y=0,$halign="left",$valign="top",$color=array(0,0,0); - var $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12; - var $hide=false, $dir=0; - var $boxed=false; // Should the text be boxed - var $paragraph_align="left"; - var $margin=0; - var $icornerradius=0,$ishadowwidth=3; - var $iScalePosY=null,$iScalePosX=null; - var $iWordwrap=0; - var $fcolor='white',$bcolor='black',$shadow=false; - var $iCSIMarea='',$iCSIMalt='',$iCSIMtarget=''; - -//--------------- -// CONSTRUCTOR - - // Create new text at absolute pixel coordinates - function __construct($aTxt="",$aXAbsPos=0,$aYAbsPos=0) { - if( ! is_string($aTxt) ) { - JpGraphError::RaiseL(25050);//('First argument to Text::Text() must be s atring.'); - } - $this->t = $aTxt; - $this->x = round($aXAbsPos); - $this->y = round($aYAbsPos); - $this->margin = 0; - } -//--------------- -// PUBLIC METHODS - // Set the string in the text object - function Set($aTxt) { - $this->t = $aTxt; - } - - // Alias for Pos() - function SetPos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") { - $this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign); - } - - // Specify the position and alignment for the text object - function Pos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") { - $this->x = $aXAbsPos; - $this->y = $aYAbsPos; - $this->halign = $aHAlign; - $this->valign = $aVAlign; - } - - function SetScalePos($aX,$aY) { - $this->iScalePosX = $aX; - $this->iScalePosY = $aY; - } - - // Specify alignment for the text - function Align($aHAlign,$aVAlign="top",$aParagraphAlign="") { - $this->halign = $aHAlign; - $this->valign = $aVAlign; - if( $aParagraphAlign != "" ) - $this->paragraph_align = $aParagraphAlign; - } - - // Alias - function SetAlign($aHAlign,$aVAlign="top",$aParagraphAlign="") { - $this->Align($aHAlign,$aVAlign,$aParagraphAlign); - } - - // Specifies the alignment for a multi line text - function ParagraphAlign($aAlign) { - $this->paragraph_align = $aAlign; - } - - // Specifies the alignment for a multi line text - function SetParagraphAlign($aAlign) { - $this->paragraph_align = $aAlign; - } - - function SetShadow($aShadowColor='gray',$aShadowWidth=3) { - $this->ishadowwidth=$aShadowWidth; - $this->shadow=$aShadowColor; - $this->boxed=true; - } - - function SetWordWrap($aCol) { - $this->iWordwrap = $aCol ; - } - - // Specify that the text should be boxed. fcolor=frame color, bcolor=border color, - // $shadow=drop shadow should be added around the text. - function SetBox($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) { - if( $aFrameColor==false ) - $this->boxed=false; - else - $this->boxed=true; - $this->fcolor=$aFrameColor; - $this->bcolor=$aBorderColor; - // For backwards compatibility when shadow was just true or false - if( $aShadowColor === true ) - $aShadowColor = 'gray'; - $this->shadow=$aShadowColor; - $this->icornerradius=$aCornerRadius; - $this->ishadowwidth=$aShadowWidth; - } - - // Hide the text - function Hide($aHide=true) { - $this->hide=$aHide; - } - - // This looks ugly since it's not a very orthogonal design - // but I added this "inverse" of Hide() to harmonize - // with some classes which I designed more recently (especially) - // jpgraph_gantt - function Show($aShow=true) { - $this->hide=!$aShow; - } - - // Specify font - function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { - $this->font_family=$aFamily; - $this->font_style=$aStyle; - $this->font_size=$aSize; - } - - // Center the text between $left and $right coordinates - function Center($aLeft,$aRight,$aYAbsPos=false) { - $this->x = $aLeft + ($aRight-$aLeft )/2; - $this->halign = "center"; - if( is_numeric($aYAbsPos) ) - $this->y = $aYAbsPos; - } - - // Set text color - function SetColor($aColor) { - $this->color = $aColor; - } - - function SetAngle($aAngle) { - $this->SetOrientation($aAngle); - } - - // Orientation of text. Note only TTF fonts can have an arbitrary angle - function SetOrientation($aDirection=0) { - if( is_numeric($aDirection) ) - $this->dir=$aDirection; - elseif( $aDirection=="h" ) - $this->dir = 0; - elseif( $aDirection=="v" ) - $this->dir = 90; - else JpGraphError::RaiseL(25051);//(" Invalid direction specified for text."); - } - - // Total width of text - function GetWidth(&$aImg) { - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $w = $aImg->GetTextWidth($this->t,$this->dir); - return $w; - } - - // Hight of font - function GetFontHeight(&$aImg) { - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $h = $aImg->GetFontHeight(); - return $h; - - } - - function GetTextHeight(&$aImg) { - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $h = $aImg->GetTextHeight($this->t,$this->dir); - return $h; - } - - function GetHeight(&$aImg) { - // Synonym for GetTextHeight() - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $h = $aImg->GetTextHeight($this->t,$this->dir); - return $h; - } - - // Set the margin which will be interpretated differently depending - // on the context. - function SetMargin($aMarg) { - $this->margin = $aMarg; - } - - function StrokeWithScale(&$aImg,$axscale,$ayscale) { - if( $this->iScalePosX === null || - $this->iScalePosY === null ) { - $this->Stroke($aImg); - } - else { - $this->Stroke($aImg, - round($axscale->Translate($this->iScalePosX)), - round($ayscale->Translate($this->iScalePosY))); - } - } - - function SetCSIMTarget($aTarget,$aAlt=null) { - $this->iCSIMtarget = $aTarget; - $this->iCSIMalt = $aAlt; - } - - function GetCSIMareas() { - if( $this->iCSIMtarget !== '' ) - return $this->iCSIMarea; - else - return ''; - } - - // Display text in image - function Stroke(&$aImg,$x=null,$y=null) { - - if( !empty($x) ) $this->x = round($x); - if( !empty($y) ) $this->y = round($y); - - // Insert newlines - if( $this->iWordwrap > 0 ) { - $this->t = wordwrap($this->t,$this->iWordwrap,"\n"); - } - - // If position been given as a fraction of the image size - // calculate the absolute position - if( $this->x < 1 && $this->x > 0 ) $this->x *= $aImg->width; - if( $this->y < 1 && $this->y > 0 ) $this->y *= $aImg->height; - - $aImg->PushColor($this->color); - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $aImg->SetTextAlign($this->halign,$this->valign); - if( $this->boxed ) { - if( $this->fcolor=="nofill" ) - $this->fcolor=false; - $aImg->SetLineWeight(1); - $bbox = $aImg->StrokeBoxedText($this->x,$this->y,$this->t, - $this->dir,$this->fcolor,$this->bcolor,$this->shadow, - $this->paragraph_align,5,5,$this->icornerradius, - $this->ishadowwidth); - } - else { - $bbox = $aImg->StrokeText($this->x,$this->y,$this->t,$this->dir,$this->paragraph_align); - } - - // Create CSIM targets - $coords = $bbox[0].','.$bbox[1].','.$bbox[2].','.$bbox[3].','.$bbox[4].','.$bbox[5].','.$bbox[6].','.$bbox[7]; - $this->iCSIMarea = "iCSIMtarget."\""; - $this->iCSIMarea .= " alt=\"".$this->iCSIMalt."\" title=\"".$this->iCSIMalt."\" />\n"; - - $aImg->PopColor($this->color); - - } -} // Class - -class GraphTabTitle extends Text{ - var $corner = 6 , $posx = 7, $posy = 4; - var $color='darkred',$fillcolor='lightyellow',$bordercolor='black'; - var $align = 'left', $width=TABTITLE_WIDTHFIT; - function __construct() { - parent::__construct(); - $this->t = ''; - $this->font_style = FS_BOLD; - $this->hide = true; - } - - function SetColor($aTxtColor,$aFillColor='lightyellow',$aBorderColor='black') { - $this->color = $aTxtColor; - $this->fillcolor = $aFillColor; - $this->bordercolor = $aBorderColor; - } - - function SetFillColor($aFillColor) { - $this->fillcolor = $aFillColor; - } - - function SetTabAlign($aAlign) { - // Synonym for SetPos - $this->align = $aAlign; - } - - function SetPos($aXAbsPos = 0, $aYAbsPos = 0, $aHAlign = 'left', $aVAlign = 'top') { - //$this->align = $aXAbsPos; - throw new \Exception('Invalid function call. should use SetTabAlign()'); - } - - function SetWidth($aWidth) { - $this->width = $aWidth ; - } - - function Set($t) { - $this->t = $t; - $this->hide = false; - } - - function SetCorner($aD) { - $this->corner = $aD ; - } - - // parent class compat function - function Stroke(&$aImg, $x = NULL, $y = NULL) { - if( $this->hide ) - return; - $this->boxed = false; - $w = $this->GetWidth($aImg) + 2*$this->posx; - $h = $this->GetTextHeight($aImg) + 2*$this->posy; - - $x = $aImg->left_margin; - $y = $aImg->top_margin; - - if( $this->width === TABTITLE_WIDTHFIT ) { - if( $this->align == 'left' ) { - $p = array($x, $y, - $x, $y-$h+$this->corner, - $x + $this->corner,$y-$h, - $x + $w - $this->corner, $y-$h, - $x + $w, $y-$h+$this->corner, - $x + $w, $y); - } - elseif( $this->align == 'center' ) { - $x += round($aImg->plotwidth/2) - round($w/2); - $p = array($x, $y, - $x, $y-$h+$this->corner, - $x + $this->corner, $y-$h, - $x + $w - $this->corner, $y-$h, - $x + $w, $y-$h+$this->corner, - $x + $w, $y); - } - else { - $x += $aImg->plotwidth -$w; - $p = array($x, $y, - $x, $y-$h+$this->corner, - $x + $this->corner,$y-$h, - $x + $w - $this->corner, $y-$h, - $x + $w, $y-$h+$this->corner, - $x + $w, $y); - } - } - else { - if( $this->width === TABTITLE_WIDTHFULL ) - $w = $aImg->plotwidth ; - else - $w = $this->width ; - - // Make the tab fit the width of the plot area - $p = array($x, $y, - $x, $y-$h+$this->corner, - $x + $this->corner,$y-$h, - $x + $w - $this->corner, $y-$h, - $x + $w, $y-$h+$this->corner, - $x + $w, $y); - - } - if( $this->halign == 'left' ) { - $aImg->SetTextAlign('left','bottom'); - $x += $this->posx; - $y -= $this->posy; - } - elseif( $this->halign == 'center' ) { - $aImg->SetTextAlign('center','bottom'); - $x += $w/2; - $y -= $this->posy; - } - else { - $aImg->SetTextAlign('right','bottom'); - $x += $w - $this->posx; - $y -= $this->posy; - } - - $aImg->SetColor($this->fillcolor); - $aImg->FilledPolygon($p); - - $aImg->SetColor($this->bordercolor); - $aImg->Polygon($p,true); - - $aImg->SetColor($this->color); - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $aImg->StrokeText($x,$y,$this->t,0,'center'); - } - -} - -//=================================================== -// CLASS SuperScriptText -// Description: Format a superscript text -//=================================================== -class SuperScriptText extends Text { - var $iSuper=""; - var $sfont_family="",$sfont_style="",$sfont_size=8; - var $iSuperMargin=2,$iVertOverlap=4,$iSuperScale=0.65; - var $iSDir=0; - var $iSimple=false; - - function __construct($aTxt="",$aSuper="",$aXAbsPos=0,$aYAbsPos=0) { - parent::__construct($aTxt,$aXAbsPos,$aYAbsPos); - $this->iSuper = $aSuper; - } - - function FromReal($aVal,$aPrecision=2) { - // Convert a floating point number to scientific notation - $neg=1.0; - if( $aVal < 0 ) { - $neg = -1.0; - $aVal = -$aVal; - } - - $l = floor(log10($aVal)); - $a = sprintf("%0.".$aPrecision."f",round($aVal / pow(10,$l),$aPrecision)); - $a *= $neg; - if( $this->iSimple && ($a == 1 || $a==-1) ) $a = ''; - - if( $a != '' ) - $this->t = $a.' * 10'; - else { - if( $neg == 1 ) - $this->t = '10'; - else - $this->t = '-10'; - } - $this->iSuper = $l; - } - - function Set($aTxt,$aSuper="") { - $this->t = $aTxt; - $this->iSuper = $aSuper; - } - - function SetSuperFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=8) { - $this->sfont_family = $aFontFam; - $this->sfont_style = $aFontStyle; - $this->sfont_size = $aFontSize; - } - - // Total width of text - function GetWidth(&$aImg) { - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $w = $aImg->GetTextWidth($this->t); - $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); - $w += $aImg->GetTextWidth($this->iSuper); - $w += $this->iSuperMargin; - return $w; - } - - // Hight of font (approximate the height of the text) - function GetFontHeight(&$aImg) { - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $h = $aImg->GetFontHeight(); - $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); - $h += $aImg->GetFontHeight(); - return $h; - } - - // Hight of text - function GetTextHeight(&$aImg) { - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $h = $aImg->GetTextHeight($this->t); - $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); - $h += $aImg->GetTextHeight($this->iSuper); - return $h; - } - - function Stroke(&$aImg,$ax=-1,$ay=-1) { - - // To position the super script correctly we need different - // cases to handle the alignmewnt specified since that will - // determine how we can interpret the x,y coordinates - - $w = parent::GetWidth($aImg); - $h = parent::GetTextHeight($aImg); - switch( $this->valign ) { - case 'top': - $sy = $this->y; - break; - case 'center': - $sy = $this->y - $h/2; - break; - case 'bottom': - $sy = $this->y - $h; - break; - default: - JpGraphError::RaiseL(25052);//('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text'); - exit(); - } - - switch( $this->halign ) { - case 'left': - $sx = $this->x + $w; - break; - case 'center': - $sx = $this->x + $w/2; - break; - case 'right': - $sx = $this->x; - break; - default: - JpGraphError::RaiseL(25053);//('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text'); - exit(); - } - - $sx += $this->iSuperMargin; - $sy += $this->iVertOverlap; - - // Should we automatically determine the font or - // has the user specified it explicetly? - if( $this->sfont_family == "" ) { - if( $this->font_family <= FF_FONT2 ) { - if( $this->font_family == FF_FONT0 ) { - $sff = FF_FONT0; - } - elseif( $this->font_family == FF_FONT1 ) { - if( $this->font_style == FS_NORMAL ) - $sff = FF_FONT0; - else - $sff = FF_FONT1; - } - else { - $sff = FF_FONT1; - } - $sfs = $this->font_style; - $sfz = $this->font_size; - } - else { - // TTF fonts - $sff = $this->font_family; - $sfs = $this->font_style; - $sfz = floor($this->font_size*$this->iSuperScale); - if( $sfz < 8 ) $sfz = 8; - } - $this->sfont_family = $sff; - $this->sfont_style = $sfs; - $this->sfont_size = $sfz; - } - else { - $sff = $this->sfont_family; - $sfs = $this->sfont_style; - $sfz = $this->sfont_size; - } - - parent::Stroke($aImg,$ax,$ay); - - - // For the builtin fonts we need to reduce the margins - // since the bounding bx reported for the builtin fonts - // are much larger than for the TTF fonts. - if( $sff <= FF_FONT2 ) { - $sx -= 2; - $sy += 3; - } - - $aImg->SetTextAlign('left','bottom'); - $aImg->SetFont($sff,$sfs,$sfz); - $aImg->PushColor($this->color); - $aImg->StrokeText($sx,$sy,$this->iSuper,$this->iSDir,'left'); - $aImg->PopColor(); - } -} - - -//=================================================== -// CLASS Grid -// Description: responsible for drawing grid lines in graph -//=================================================== -class Grid { - var $img; - var $scale; - var $grid_color='#DDDDDD',$grid_mincolor='#DDDDDD'; - var $type="solid"; - var $show=false, $showMinor=false,$weight=1; - var $fill=false,$fillcolor=array('#EFEFEF','#BBCCFF'); -//--------------- -// CONSTRUCTOR - function __construct(&$aAxis) { - $this->scale = &$aAxis->scale; - $this->img = &$aAxis->img; - } -//--------------- -// PUBLIC METHODS - function SetColor($aMajColor,$aMinColor=false) { - $this->grid_color=$aMajColor; - if( $aMinColor === false ) - $aMinColor = $aMajColor ; - $this->grid_mincolor = $aMinColor; - } - - function SetWeight($aWeight) { - $this->weight=$aWeight; - } - - // Specify if grid should be dashed, dotted or solid - function SetLineStyle($aType) { - $this->type = $aType; - } - - // Decide if both major and minor grid should be displayed - function Show($aShowMajor=true,$aShowMinor=false) { - $this->show=$aShowMajor; - $this->showMinor=$aShowMinor; - } - - function SetFill($aFlg=true,$aColor1='lightgray',$aColor2='lightblue') { - $this->fill = $aFlg; - $this->fillcolor = array( $aColor1, $aColor2 ); - } - - // Display the grid - function Stroke() { - if( $this->showMinor ) { - $tmp = $this->grid_color; - $this->grid_color = $this->grid_mincolor; - $this->DoStroke($this->scale->ticks->ticks_pos); - - $this->grid_color = $tmp; - $this->DoStroke($this->scale->ticks->maj_ticks_pos); - } - else { - $this->DoStroke($this->scale->ticks->maj_ticks_pos); - } - } - -//-------------- -// Private methods - // Draw the grid - function DoStroke(&$aTicksPos) { - if( !$this->show ) - return; - $nbrgrids = count($aTicksPos); - - if( $this->scale->type=="y" ) { - $xl=$this->img->left_margin; - $xr=$this->img->width-$this->img->right_margin; - - if( $this->fill ) { - // Draw filled areas - $y2 = $aTicksPos[0]; - $i=1; - while( $i < $nbrgrids ) { - $y1 = $y2; - $y2 = $aTicksPos[$i++]; - $this->img->SetColor($this->fillcolor[$i & 1]); - $this->img->FilledRectangle($xl,$y1,$xr,$y2); - } - } - - $this->img->SetColor($this->grid_color); - $this->img->SetLineWeight($this->weight); - - // Draw grid lines - for($i=0; $i<$nbrgrids; ++$i) { - $y=$aTicksPos[$i]; - if( $this->type == "solid" ) - $this->img->Line($xl,$y,$xr,$y); - elseif( $this->type == "dotted" ) - $this->img->DashedLine($xl,$y,$xr,$y,1,6); - elseif( $this->type == "dashed" ) - $this->img->DashedLine($xl,$y,$xr,$y,2,4); - elseif( $this->type == "longdashed" ) - $this->img->DashedLine($xl,$y,$xr,$y,8,6); - } - } - elseif( $this->scale->type=="x" ) { - $yu=$this->img->top_margin; - $yl=$this->img->height-$this->img->bottom_margin; - $limit=$this->img->width-$this->img->right_margin; - - if( $this->fill ) { - // Draw filled areas - $x2 = $aTicksPos[0]; - $i=1; - while( $i < $nbrgrids ) { - $x1 = $x2; - $x2 = min($aTicksPos[$i++],$limit) ; - $this->img->SetColor($this->fillcolor[$i & 1]); - $this->img->FilledRectangle($x1,$yu,$x2,$yl); - } - } - - $this->img->SetColor($this->grid_color); - $this->img->SetLineWeight($this->weight); - - // We must also test for limit since we might have - // an offset and the number of ticks is calculated with - // assumption offset==0 so we might end up drawing one - // to many gridlines - $i=0; - $x=$aTicksPos[$i]; - while( $itype == "solid" ) - $this->img->Line($x,$yl,$x,$yu); - elseif( $this->type == "dotted" ) - $this->img->DashedLine($x,$yl,$x,$yu,1,6); - elseif( $this->type == "dashed" ) - $this->img->DashedLine($x,$yl,$x,$yu,2,4); - elseif( $this->type == "longdashed" ) - $this->img->DashedLine($x,$yl,$x,$yu,8,6); - ++$i; - } - } - else { - JpGraphError::RaiseL(25054,$this->scale->type);//('Internal error: Unknown grid axis ['.$this->scale->type.']'); - } - return true; - } -} // Class - -//=================================================== -// CLASS Axis -// Description: Defines X and Y axis. Notes that at the -// moment the code is not really good since the axis on -// several occasion must know wheter it's an X or Y axis. -// This was a design decision to make the code easier to -// follow. -//=================================================== -class Axis { - var $pos = false; - var $weight=1; - var $color=array(0,0,0),$label_color=array(0,0,0); - var $img=null,$scale=null; - var $hide=false; - var $ticks_label=false, $ticks_label_colors=null; - var $show_first_label=true,$show_last_label=true; - var $label_step=1; // Used by a text axis to specify what multiple of major steps - // should be labeled. - var $tick_step=1; - var $labelPos=0; // Which side of the axis should the labels be? - var $title=null,$title_adjust,$title_margin,$title_side=SIDE_LEFT; - var $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12,$label_angle=0; - var $tick_label_margin=5; - var $label_halign = '',$label_valign = '', $label_para_align='left'; - var $hide_line=false,$hide_labels=false; - var $iDeltaAbsPos=0; - //var $hide_zero_label=false; - -//--------------- -// CONSTRUCTOR - function __construct(&$img,&$aScale,$color=array(0,0,0)) { - $this->img = &$img; - $this->scale = &$aScale; - $this->color = $color; - $this->title=new Text(""); - - if( $aScale->type=="y" ) { - $this->title_margin = 25; - $this->title_adjust="middle"; - $this->title->SetOrientation(90); - $this->tick_label_margin=7; - $this->labelPos=SIDE_LEFT; - //$this->SetLabelFormat('%.1f'); - } - else { - $this->title_margin = 5; - $this->title_adjust="high"; - $this->title->SetOrientation(0); - $this->tick_label_margin=5; - $this->labelPos=SIDE_DOWN; - $this->title_side=SIDE_DOWN; - //$this->SetLabelFormat('%.0f'); - } - } -//--------------- -// PUBLIC METHODS - - function SetLabelFormat($aFormStr) { - $this->scale->ticks->SetLabelFormat($aFormStr); - } - - function SetLabelFormatString($aFormStr,$aDate=false) { - $this->scale->ticks->SetLabelFormat($aFormStr,$aDate); - } - - function SetLabelFormatCallback($aFuncName) { - $this->scale->ticks->SetFormatCallback($aFuncName); - } - - function SetLabelAlign($aHAlign,$aVAlign="top",$aParagraphAlign='left') { - $this->label_halign = $aHAlign; - $this->label_valign = $aVAlign; - $this->label_para_align = $aParagraphAlign; - } - - // Don't display the first label - function HideFirstTickLabel($aShow=false) { - $this->show_first_label=$aShow; - } - - function HideLastTickLabel($aShow=false) { - $this->show_last_label=$aShow; - } - - // Manually specify the major and (optional) minor tick position and labels - function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) { - $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels); - } - - // Manually specify major tick positions and optional labels - function SetMajTickPositions($aMajPos,$aLabels=NULL) { - $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels); - } - - // Hide minor or major tick marks - function HideTicks($aHideMinor=true,$aHideMajor=true) { - $this->scale->ticks->SupressMinorTickMarks($aHideMinor); - $this->scale->ticks->SupressTickMarks($aHideMajor); - } - - // Hide zero label - function HideZeroLabel($aFlag=true) { - $this->scale->ticks->SupressZeroLabel(); - //$this->hide_zero_label = $aFlag; - } - - function HideFirstLastLabel() { - // The two first calls to ticks method will supress - // automatically generated scale values. However, that - // will not affect manually specified value, e.g text-scales. - // therefor we also make a kludge here to supress manually - // specified scale labels. - $this->scale->ticks->SupressLast(); - $this->scale->ticks->SupressFirst(); - $this->show_first_label = false; - $this->show_last_label = false; - } - - // Hide the axis - function Hide($aHide=true) { - $this->hide=$aHide; - } - - // Hide the actual axis-line, but still print the labels - function HideLine($aHide=true) { - $this->hide_line = $aHide; - } - - function HideLabels($aHide=true) { - $this->hide_labels = $aHide; - } - - - // Weight of axis - function SetWeight($aWeight) { - $this->weight = $aWeight; - } - - // Axis color - function SetColor($aColor,$aLabelColor=false) { - $this->color = $aColor; - if( !$aLabelColor ) $this->label_color = $aColor; - else $this->label_color = $aLabelColor; - } - - // Title on axis - function SetTitle($aTitle,$aAdjustAlign="high") { - $this->title->Set($aTitle); - $this->title_adjust=$aAdjustAlign; - } - - // Specify distance from the axis - function SetTitleMargin($aMargin) { - $this->title_margin=$aMargin; - } - - // Which side of the axis should the axis title be? - function SetTitleSide($aSideOfAxis) { - $this->title_side = $aSideOfAxis; - } - - // Utility function to set the direction for tick marks - function SetTickDirection($aDir) { - // Will be deprecated from 1.7 - if( ERR_DEPRECATED ) - JpGraphError::RaiseL(25055);//('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead'); - $this->scale->ticks->SetSide($aDir); - } - - function SetTickSide($aDir) { - $this->scale->ticks->SetSide($aDir); - } - - // Specify text labels for the ticks. One label for each data point - function SetTickLabels($aLabelArray,$aLabelColorArray=null) { - $this->ticks_label = $aLabelArray; - $this->ticks_label_colors = $aLabelColorArray; - } - - // How far from the axis should the labels be drawn - function SetTickLabelMargin($aMargin) { - if( ERR_DEPRECATED ) - JpGraphError::RaiseL(25056);//('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.'); - $this->tick_label_margin=$aMargin; - } - - function SetLabelMargin($aMargin) { - $this->tick_label_margin=$aMargin; - } - - // Specify that every $step of the ticks should be displayed starting - // at $start - // DEPRECATED FUNCTION: USE SetTextTickInterval() INSTEAD - function SetTextTicks($step,$start=0) { - JpGraphError::RaiseL(25057);//(" SetTextTicks() is deprecated. Use SetTextTickInterval() instead."); - } - - // Specify that every $step of the ticks should be displayed starting - // at $start - function SetTextTickInterval($aStep,$aStart=0) { - $this->scale->ticks->SetTextLabelStart($aStart); - $this->tick_step=$aStep; - } - - // Specify that every $step tick mark should have a label - // should be displayed starting - function SetTextLabelInterval($aStep,$aStart=0) { - if( $aStep < 1 ) - JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1."); - $this->scale->ticks->SetTextLabelStart($aStart); - $this->label_step=$aStep; - } - - // Which side of the axis should the labels be on? - function SetLabelPos($aSidePos) { - // This will be deprecated from 1.7 - if( ERR_DEPRECATED ) - JpGraphError::RaiseL(25059);//('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.'); - $this->labelPos=$aSidePos; - } - - function SetLabelSide($aSidePos) { - $this->labelPos=$aSidePos; - } - - // Set the font - function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { - $this->font_family = $aFamily; - $this->font_style = $aStyle; - $this->font_size = $aSize; - } - - // Position for axis line on the "other" scale - function SetPos($aPosOnOtherScale) { - $this->pos=$aPosOnOtherScale; - } - - // Set the position of the axis to be X-pixels delta to the right - // of the max X-position (used to position the multiple Y-axis) - function SetPosAbsDelta($aDelta) { - $this->iDeltaAbsPos=$aDelta; - } - - // Specify the angle for the tick labels - function SetLabelAngle($aAngle) { - $this->label_angle = $aAngle; - } - - // Stroke the axis. - function Stroke($aOtherAxisScale,$aStrokeLabels=true) { - if( $this->hide ) return; - if( is_numeric($this->pos) ) { - $pos=$aOtherAxisScale->Translate($this->pos); - } - else { // Default to minimum of other scale if pos not set - if( ($aOtherAxisScale->GetMinVal() >= 0 && $this->pos==false) || $this->pos=="min" ) { - $pos = $aOtherAxisScale->scale_abs[0]; - } - elseif($this->pos == "max") { - $pos = $aOtherAxisScale->scale_abs[1]; - } - else { // If negative set x-axis at 0 - $this->pos=0; - $pos=$aOtherAxisScale->Translate(0); - } - } - $pos += $this->iDeltaAbsPos; - $this->img->SetLineWeight($this->weight); - $this->img->SetColor($this->color); - $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); - if( $this->scale->type == "x" ) { - if( !$this->hide_line ) - $this->img->FilledRectangle($this->img->left_margin,$pos, - $this->img->width-$this->img->right_margin,$pos+$this->weight-1); - if( $this->title_side == SIDE_DOWN ) { - $y = $pos + $this->img->GetFontHeight() + $this->title_margin + $this->title->margin; - $yalign = 'top'; - } - else { - $y = $pos - $this->img->GetFontHeight() - $this->title_margin - $this->title->margin; - $yalign = 'bottom'; - } - - if( $this->title_adjust=="high" ) - $this->title->Pos($this->img->width-$this->img->right_margin,$y,"right",$yalign); - elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" ) - $this->title->Pos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin,$y,"center",$yalign); - elseif($this->title_adjust=="low") - $this->title->Pos($this->img->left_margin,$y,"left",$yalign); - else { - JpGraphError::RaiseL(25060,$this->title_adjust);//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')'); - } - } - elseif( $this->scale->type == "y" ) { - // Add line weight to the height of the axis since - // the x-axis could have a width>1 and we want the axis to fit nicely together. - if( !$this->hide_line ) - $this->img->FilledRectangle($pos-$this->weight+1,$this->img->top_margin, - $pos,$this->img->height-$this->img->bottom_margin+$this->weight-1); - $x=$pos ; - if( $this->title_side == SIDE_LEFT ) { - $x -= $this->title_margin; - $x -= $this->title->margin; - $halign="right"; - } - else { - $x += $this->title_margin; - $x += $this->title->margin; - $halign="left"; - } - // If the user has manually specified an hor. align - // then we override the automatic settings with this - // specifed setting. Since default is 'left' we compare - // with that. (This means a manually set 'left' align - // will have no effect.) - if( $this->title->halign != 'left' ) - $halign = $this->title->halign; - if( $this->title_adjust=="high" ) - $this->title->Pos($x,$this->img->top_margin,$halign,"top"); - elseif($this->title_adjust=="middle" || $this->title_adjust=="center") - $this->title->Pos($x,($this->img->height-$this->img->top_margin-$this->img->bottom_margin)/2+$this->img->top_margin,$halign,"center"); - elseif($this->title_adjust=="low") - $this->title->Pos($x,$this->img->height-$this->img->bottom_margin,$halign,"bottom"); - else - JpGraphError::RaiseL(25061,$this->title_adjust);//('Unknown alignment specified for Y-axis title. ('.$this->title_adjust.')'); - - } - $this->scale->ticks->Stroke($this->img,$this->scale,$pos); - if( $aStrokeLabels ) { - if( !$this->hide_labels ) - $this->StrokeLabels($pos); - $this->title->Stroke($this->img); - } - } - -//--------------- -// PRIVATE METHODS - // Draw all the tick labels on major tick marks - function StrokeLabels($aPos,$aMinor=false,$aAbsLabel=false) { - - $this->img->SetColor($this->label_color); - $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); - $yoff=$this->img->GetFontHeight()/2; - - // Only draw labels at major tick marks - $nbr = count($this->scale->ticks->maj_ticks_label); - - // We have the option to not-display the very first mark - // (Usefull when the first label might interfere with another - // axis.) - $i = $this->show_first_label ? 0 : 1 ; - if( !$this->show_last_label ) --$nbr; - // Now run through all labels making sure we don't overshoot the end - // of the scale. - $ncolor=0; - if( isset($this->ticks_label_colors) ) - $ncolor=count($this->ticks_label_colors); - - while( $i<$nbr ) { - // $tpos holds the absolute text position for the label - $tpos=$this->scale->ticks->maj_ticklabels_pos[$i]; - - // Note. the $limit is only used for the x axis since we - // might otherwise overshoot if the scale has been centered - // This is due to us "loosing" the last tick mark if we center. - if( $this->scale->type=="x" && $tpos > $this->img->width-$this->img->right_margin+1 ) { - return; - } - // we only draw every $label_step label - if( ($i % $this->label_step)==0 ) { - - // Set specific label color if specified - if( $ncolor > 0 ) - $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]); - - // If the label has been specified use that and in other case - // just label the mark with the actual scale value - $m=$this->scale->ticks->GetMajor(); - - // ticks_label has an entry for each data point and is the array - // that holds the labels set by the user. If the user hasn't - // specified any values we use whats in the automatically asigned - // labels in the maj_ticks_label - if( isset($this->ticks_label[$i*$m]) ) - $label=$this->ticks_label[$i*$m]; - else { - if( $aAbsLabel ) - $label=abs($this->scale->ticks->maj_ticks_label[$i]); - else - $label=$this->scale->ticks->maj_ticks_label[$i]; - if( $this->scale->textscale && $this->scale->ticks->label_formfunc == '' ) { - ++$label; - } - } - - //if( $this->hide_zero_label && $label==0.0 ) { - // ++$i; - // continue; - //} - - if( $this->scale->type == "x" ) { - if( $this->labelPos == SIDE_DOWN ) { - if( $this->label_angle==0 || $this->label_angle==90 ) { - if( $this->label_halign=='' && $this->label_valign=='') - $this->img->SetTextAlign('center','top'); - else - $this->img->SetTextAlign($this->label_halign,$this->label_valign); - - } - else { - if( $this->label_halign=='' && $this->label_valign=='') - $this->img->SetTextAlign("right","top"); - else - $this->img->SetTextAlign($this->label_halign,$this->label_valign); - } - - $this->img->StrokeText($tpos,$aPos+$this->tick_label_margin,$label, - $this->label_angle,$this->label_para_align); - } - else { - if( $this->label_angle==0 || $this->label_angle==90 ) { - if( $this->label_halign=='' && $this->label_valign=='') - $this->img->SetTextAlign("center","bottom"); - else - $this->img->SetTextAlign($this->label_halign,$this->label_valign); - } - else { - if( $this->label_halign=='' && $this->label_valign=='') - $this->img->SetTextAlign("right","bottom"); - else - $this->img->SetTextAlign($this->label_halign,$this->label_valign); - } - $this->img->StrokeText($tpos,$aPos-$this->tick_label_margin,$label, - $this->label_angle,$this->label_para_align); - } - } - else { - // scale->type == "y" - //if( $this->label_angle!=0 ) - //JpGraphError::Raise(" Labels at an angle are not supported on Y-axis"); - if( $this->labelPos == SIDE_LEFT ) { // To the left of y-axis - if( $this->label_halign=='' && $this->label_valign=='') - $this->img->SetTextAlign("right","center"); - else - $this->img->SetTextAlign($this->label_halign,$this->label_valign); - $this->img->StrokeText($aPos-$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align); - } - else { // To the right of the y-axis - if( $this->label_halign=='' && $this->label_valign=='') - $this->img->SetTextAlign("left","center"); - else - $this->img->SetTextAlign($this->label_halign,$this->label_valign); - $this->img->StrokeText($aPos+$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align); - } - } - } - ++$i; - } - } - -} // Class - -//=================================================== -// CLASS Ticks -// Description: Abstract base class for drawing linear and logarithmic -// tick marks on axis -//=================================================== -class Ticks { - var $minor_abs_size=3, $major_abs_size=5; - var $direction=1; // Should ticks be in(=1) the plot area or outside (=-1)? - var $scale; - var $is_set=false; - var $precision; - var $supress_zerolabel=false,$supress_first=false; - var $supress_last=false,$supress_tickmarks=false,$supress_minor_tickmarks=false; - var $mincolor="",$majcolor=""; - var $weight=1; - var $label_formatstr=''; // C-style format string to use for labels - var $label_formfunc=''; - var $label_dateformatstr=''; - var $label_usedateformat=FALSE; - - -//--------------- -// CONSTRUCTOR - function __construct(&$aScale) { - $this->scale=&$aScale; - $this->precision = -1; - } - -//--------------- -// PUBLIC METHODS - // Set format string for automatic labels - function SetLabelFormat($aFormatString,$aDate=FALSE) { - $this->label_formatstr=$aFormatString; - $this->label_usedateformat=$aDate; - } - - function SetLabelDateFormat($aFormatString) { - $this->label_dateformatstr=$aFormatString; - } - - function SetFormatCallback($aCallbackFuncName) { - $this->label_formfunc = $aCallbackFuncName; - } - - // Don't display the first zero label - function SupressZeroLabel($aFlag=true) { - $this->supress_zerolabel=$aFlag; - } - - // Don't display minor tick marks - function SupressMinorTickMarks($aHide=true) { - $this->supress_minor_tickmarks=$aHide; - } - - // Don't display major tick marks - function SupressTickMarks($aHide=true) { - $this->supress_tickmarks=$aHide; - } - - // Hide the first tick mark - function SupressFirst($aHide=true) { - $this->supress_first=$aHide; - } - - // Hide the last tick mark - function SupressLast($aHide=true) { - $this->supress_last=$aHide; - } - - // Size (in pixels) of minor tick marks - function GetMinTickAbsSize() { - return $this->minor_abs_size; - } - - // Size (in pixels) of major tick marks - function GetMajTickAbsSize() { - return $this->major_abs_size; - } - - function SetSize($aMajSize,$aMinSize=3) { - $this->major_abs_size = $aMajSize; - $this->minor_abs_size = $aMinSize; - } - - // Have the ticks been specified - function IsSpecified() { - return $this->is_set; - } - - // Set the distance between major and minor tick marks - function Set($aMaj,$aMin) { - // "Virtual method" - // Should be implemented by the concrete subclass - // if any action is wanted. - } - - // Specify number of decimals in automatic labels - // Deprecated from 1.4. Use SetFormatString() instead - function SetPrecision($aPrecision) { - if( ERR_DEPRECATED ) - JpGraphError::RaiseL(25063);//('Ticks::SetPrecision() is deprecated. Use Ticks::SetLabelFormat() (or Ticks::SetFormatCallback()) instead'); - $this->precision=$aPrecision; - } - - function SetSide($aSide) { - $this->direction=$aSide; - } - - // Which side of the axis should the ticks be on - function SetDirection($aSide=SIDE_RIGHT) { - $this->direction=$aSide; - } - - // Set colors for major and minor tick marks - function SetMarkColor($aMajorColor,$aMinorColor="") { - $this->SetColor($aMajorColor,$aMinorColor); - } - - function SetColor($aMajorColor,$aMinorColor="") { - $this->majcolor=$aMajorColor; - - // If not specified use same as major - if( $aMinorColor=="" ) - $this->mincolor=$aMajorColor; - else - $this->mincolor=$aMinorColor; - } - - function SetWeight($aWeight) { - $this->weight=$aWeight; - } - -} // Class - -//=================================================== -// CLASS LinearTicks -// Description: Draw linear ticks on axis -//=================================================== -class LinearTicks extends Ticks { - var $minor_step=1, $major_step=2; - var $xlabel_offset=0,$xtick_offset=0; - var $label_offset=0; // What offset should the displayed label have - // i.e should we display 0,1,2 or 1,2,3,4 or 2,3,4 etc - var $text_label_start=0; - var $iManualTickPos = NULL, $iManualMinTickPos = NULL, $iManualTickLabels = NULL; - var $maj_ticks_pos = array(), $maj_ticklabels_pos = array(), - $ticks_pos = array(), $maj_ticks_label = array(); - -//--------------- -// CONSTRUCTOR - function __construct() { - parent::__construct(); - $this->precision = -1; - } - -//--------------- -// PUBLIC METHODS - - - // Return major step size in world coordinates - function GetMajor() { - return $this->major_step; - } - - // Return minor step size in world coordinates - function GetMinor() { - return $this->minor_step; - } - - // Set Minor and Major ticks (in world coordinates) - function Set($aMajStep,$aMinStep=false) { - if( $aMinStep==false ) - $aMinStep=$aMajStep; - - if( $aMajStep <= 0 || $aMinStep <= 0 ) { - JpGraphError::RaiseL(25064); -//(" 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."); - } - - $this->major_step=$aMajStep; - $this->minor_step=$aMinStep; - $this->is_set = true; - } - - function SetMajTickPositions($aMajPos,$aLabels=NULL) { - $this->SetTickPositions($aMajPos,NULL,$aLabels); - } - - function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) { - if( !is_array($aMajPos) || ($aMinPos!==NULL && !is_array($aMinPos)) ) { - JpGraphError::RaiseL(25065);//('Tick positions must be specifued as an array()'); - return; - } - $n=count($aMajPos); - if( is_array($aLabels) && (count($aLabels) != $n) ) { - JpGraphError::RaiseL(25066);//('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.'); - return; - } - $this->iManualTickPos = $aMajPos; - $this->iManualMinTickPos = $aMinPos; - $this->iManualTickLabels = $aLabels; - } - - // Specify all the tick positions manually and possible also the exact labels - function _doManualTickPos($aScale) { - $n=count($this->iManualTickPos); - $m=count($this->iManualMinTickPos); - $doLbl=count($this->iManualTickLabels) > 0; - $this->use_manualtickpos=true; - - $this->maj_ticks_pos = array(); - $this->maj_ticklabels_pos = array(); - $this->ticks_pos = array(); - - // Now loop through the supplied positions and translate them to screen coordinates - // and store them in the maj_label_positions - $minScale = $aScale->scale[0]; - $maxScale = $aScale->scale[1]; - $j=0; - for($i=0; $i < $n ; ++$i ) { - // First make sure that the first tick is not lower than the lower scale value - if( !isset($this->iManualTickPos[$i]) || - $this->iManualTickPos[$i] < $minScale || $this->iManualTickPos[$i] > $maxScale) { - continue; - } - - - $this->maj_ticks_pos[$j] = $aScale->Translate($this->iManualTickPos[$i]); - $this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j]; - - // Set the minor tick marks the same as major if not specified - if( $m <= 0 ) { - $this->ticks_pos[$j] = $this->maj_ticks_pos[$j]; - } - - if( $doLbl ) { - $this->maj_ticks_label[$j] = $this->iManualTickLabels[$i]; - } - else { - $this->maj_ticks_label[$j]=$this->_doLabelFormat($this->iManualTickPos[$i],$i,$n); - } - ++$j; - } - - // Some sanity check - if( count($this->maj_ticks_pos) < 2 ) { - 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.'); - } - - // Setup the minor tick marks - $j=0; - for($i=0; $i < $m; ++$i ) { - if( empty($this->iManualMinTickPos[$i]) || - $this->iManualMinTickPos[$i] < $minScale || $this->iManualMinTickPos[$i] > $maxScale) - continue; - $this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]); - ++$j; - } - } - - function _doAutoTickPos($aScale) { - $maj_step_abs = $aScale->scale_factor*$this->major_step; - $min_step_abs = $aScale->scale_factor*$this->minor_step; - - if( $min_step_abs==0 || $maj_step_abs==0 ) { - 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')"); - } - // We need to make this an int since comparing it below - // with the result from round() can give wrong result, such that - // (40 < 40) == TRUE !!! - $limit = (int)$aScale->scale_abs[1]; - - if( $aScale->textscale ) { - // This can only be true for a X-scale (horizontal) - // Define ticks for a text scale. This is slightly different from a - // normal linear type of scale since the position might be adjusted - // and the labels start at on - $label = (float)$aScale->GetMinVal()+$this->text_label_start+$this->label_offset; - $start_abs=$aScale->scale_factor*$this->text_label_start; - $nbrmajticks=ceil(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; - $x = $aScale->scale_abs[0]+$start_abs+$this->xlabel_offset*$min_step_abs; - for( $i=0; $label <= $aScale->GetMaxVal()+$this->label_offset; ++$i ) { - // Apply format to label - $this->maj_ticks_label[$i]=$this->_doLabelFormat($label,$i,$nbrmajticks); - $label+=$this->major_step; - - // The x-position of the tick marks can be different from the labels. - // Note that we record the tick position (not the label) so that the grid - // happen upon tick marks and not labels. - $xtick=$aScale->scale_abs[0]+$start_abs+$this->xtick_offset*$min_step_abs+$i*$maj_step_abs; - $this->maj_ticks_pos[$i]=$xtick; - $this->maj_ticklabels_pos[$i] = round($x); - $x += $maj_step_abs; - } - } - else { - $label = $aScale->GetMinVal(); - $abs_pos = $aScale->scale_abs[0]; - $j=0; $i=0; - $step = round($maj_step_abs/$min_step_abs); - if( $aScale->type == "x" ) { - // For a normal linear type of scale the major ticks will always be multiples - // of the minor ticks. In order to avoid any rounding issues the major ticks are - // defined as every "step" minor ticks and not calculated separately - $nbrmajticks=ceil(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; - while( round($abs_pos) <= $limit ) { - $this->ticks_pos[] = round($abs_pos); - $this->ticks_label[] = $label; - if( $i % $step == 0 && $j < $nbrmajticks ) { - $this->maj_ticks_pos[$j] = round($abs_pos); - $this->maj_ticklabels_pos[$j] = round($abs_pos); - $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks); - ++$j; - } - ++$i; - $abs_pos += $min_step_abs; - $label+=$this->minor_step; - } - } - elseif( $aScale->type == "y" ) { - $nbrmajticks=floor(($aScale->GetMaxVal()-$aScale->GetMinVal())/$this->major_step)+1; - while( round($abs_pos) >= $limit ) { - $this->ticks_pos[$i] = round($abs_pos); - $this->ticks_label[$i]=$label; - if( $i % $step == 0 && $j < $nbrmajticks) { - $this->maj_ticks_pos[$j] = round($abs_pos); - $this->maj_ticklabels_pos[$j] = round($abs_pos); - $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks); - ++$j; - } - ++$i; - $abs_pos += $min_step_abs; - $label += $this->minor_step; - } - } - } - } - - function _doLabelFormat($aVal,$aIdx,$aNbrTicks) { - - // If precision hasn't been specified set it to a sensible value - if( $this->precision==-1 ) { - $t = log10($this->minor_step); - if( $t > 0 ) - $precision = 0; - else - $precision = -floor($t); - } - else - $precision = $this->precision; - - if( $this->label_formfunc != '' ) { - $f=$this->label_formfunc; - $l = call_user_func($f,$aVal); - } - elseif( $this->label_formatstr != '' || $this->label_dateformatstr != '' ) { - if( $this->label_usedateformat ) { - $l = date($this->label_formatstr,$aVal); - } - else { - if( $this->label_dateformatstr !== '' ) - $l = date($this->label_dateformatstr,$aVal); - else - $l = sprintf($this->label_formatstr,$aVal); - } - } - else { - $l = sprintf('%01.'.$precision.'f',round($aVal,$precision)); - } - - if( ($this->supress_zerolabel && $l==0) || ($this->supress_first && $aIdx==0) || - ($this->supress_last && $aIdx==$aNbrTicks-1) ) { - $l=''; - } - return $l; - } - - // Stroke ticks on either X or Y axis - function _StrokeTicks(&$aImg,$aScale,$aPos) { - $hor = $aScale->type == 'x'; - $aImg->SetLineWeight($this->weight); - - // We need to make this an int since comparing it below - // with the result from round() can give wrong result, such that - // (40 < 40) == TRUE !!! - $limit = (int)$aScale->scale_abs[1]; - - // A text scale doesn't have any minor ticks - if( !$aScale->textscale ) { - // Stroke minor ticks - $yu = $aPos - $this->direction*$this->GetMinTickAbsSize(); - $xr = $aPos + $this->direction*$this->GetMinTickAbsSize(); - $n = count($this->ticks_pos); - for($i=0; $i < $n; ++$i ) { - if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { - if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor); - if( $hor ) { - //if( $this->ticks_pos[$i] <= $limit ) - $aImg->Line($this->ticks_pos[$i],$aPos,$this->ticks_pos[$i],$yu); - } - else { - //if( $this->ticks_pos[$i] >= $limit ) - $aImg->Line($aPos,$this->ticks_pos[$i],$xr,$this->ticks_pos[$i]); - } - if( $this->mincolor!="" ) $aImg->PopColor(); - } - } - } - - // Stroke major ticks - $yu = $aPos - $this->direction*$this->GetMajTickAbsSize(); - $xr = $aPos + $this->direction*$this->GetMajTickAbsSize(); - $nbrmajticks=ceil(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; - $n = count($this->maj_ticks_pos); - for($i=0; $i < $n ; ++$i ) { - if(!($this->xtick_offset > 0 && $i==$nbrmajticks-1) && !$this->supress_tickmarks) { - if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor); - if( $hor ) { - //if( $this->maj_ticks_pos[$i] <= $limit ) - $aImg->Line($this->maj_ticks_pos[$i],$aPos,$this->maj_ticks_pos[$i],$yu); - } - else { - //if( $this->maj_ticks_pos[$i] >= $limit ) - $aImg->Line($aPos,$this->maj_ticks_pos[$i],$xr,$this->maj_ticks_pos[$i]); - } - if( $this->majcolor!="" ) $aImg->PopColor(); - } - } - - } - - // Draw linear ticks - function Stroke(&$aImg,$aScale,$aPos) { - if( $this->iManualTickPos != NULL ) - $this->_doManualTickPos($aScale); - else - $this->_doAutoTickPos($aScale); - $this->_StrokeTicks($aImg,$aScale,$aPos, $aScale->type == 'x' ); - } - -//--------------- -// PRIVATE METHODS - // Spoecify the offset of the displayed tick mark with the tick "space" - // Legal values for $o is [0,1] used to adjust where the tick marks and label - // should be positioned within the major tick-size - // $lo specifies the label offset and $to specifies the tick offset - // this comes in handy for example in bar graphs where we wont no offset for the - // tick but have the labels displayed halfway under the bars. - function SetXLabelOffset($aLabelOff,$aTickOff=-1) { - $this->xlabel_offset=$aLabelOff; - if( $aTickOff==-1 ) // Same as label offset - $this->xtick_offset=$aLabelOff; - else - $this->xtick_offset=$aTickOff; - if( $aLabelOff>0 ) - $this->SupressLast(); // The last tick wont fit - } - - // Which tick label should we start with? - function SetTextLabelStart($aTextLabelOff) { - $this->text_label_start=$aTextLabelOff; - } - -} // Class - -//=================================================== -// CLASS LinearScale -// Description: Handle linear scaling between screen and world -//=================================================== -class LinearScale { - var $scale=array(0,0); - var $scale_abs=array(0,0); - var $scale_factor; // Scale factor between world and screen - var $world_size; // Plot area size in world coordinates - var $world_abs_size; // Plot area size in pixels - var $off; // Offset between image edge and plot area - var $type; // is this x or y scale ? - var $ticks=null; // Store ticks - var $text_scale_off = 0; - var $autoscale_min=false; // Forced minimum value, auto determine max - var $autoscale_max=false; // Forced maximum value, auto determine min - var $gracetop=0,$gracebottom=0; - var $intscale=false; // Restrict autoscale to integers - var $textscale=false; // Just a flag to let the Plot class find out if - // we are a textscale or not. This is a cludge since - // this ionformatyion is availabale in Graph::axtype but - // we don't have access to the graph object in the Plots - // stroke method. So we let graph store the status here - // when the linear scale is created. A real cludge... - var $auto_ticks=false; // When using manual scale should the ticks be automatically set? - var $name = 'lin'; -//--------------- -// CONSTRUCTOR - function __construct($aMin=0,$aMax=0,$aType="y") { - assert($aType=="x" || $aType=="y" ); - assert($aMin<=$aMax); - - $this->type=$aType; - $this->scale=array($aMin,$aMax); - $this->world_size=$aMax-$aMin; - $this->ticks = new LinearTicks(); - } - -//--------------- -// PUBLIC METHODS - // Check if scale is set or if we should autoscale - // We should do this is either scale or ticks has not been set - function IsSpecified() { - if( $this->GetMinVal()==$this->GetMaxVal() ) { // Scale not set - return false; - } - return true; - } - - // Set the minimum data value when the autoscaling is used. - // Usefull if you want a fix minimum (like 0) but have an - // automatic maximum - function SetAutoMin($aMin) { - $this->autoscale_min=$aMin; - } - - // Set the minimum data value when the autoscaling is used. - // Usefull if you want a fix minimum (like 0) but have an - // automatic maximum - function SetAutoMax($aMax) { - $this->autoscale_max=$aMax; - } - - // If the user manually specifies a scale should the ticks - // still be set automatically? - function SetAutoTicks($aFlag=true) { - $this->auto_ticks = $aFlag; - } - - // Specify scale "grace" value (top and bottom) - function SetGrace($aGraceTop,$aGraceBottom=0) { - if( $aGraceTop<0 || $aGraceBottom < 0 ) - JpGraphError::RaiseL(25069);//(" Grace must be larger then 0"); - $this->gracetop=$aGraceTop; - $this->gracebottom=$aGraceBottom; - } - - // Get the minimum value in the scale - function GetMinVal() { - return $this->scale[0]; - } - - // get maximum value for scale - function GetMaxVal() { - return $this->scale[1]; - } - - // Specify a new min/max value for sclae - function Update(&$aImg,$aMin,$aMax) { - $this->scale=array($aMin,$aMax); - $this->world_size=$aMax-$aMin; - $this->InitConstants($aImg); - } - - // Translate between world and screen - function Translate($aCoord) { - if( !is_numeric($aCoord) ) { - if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) - JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.'); - return 0; - } - else { - return $this->off + ($aCoord - $this->scale[0])*$this->scale_factor; - } - } - - // Relative translate (don't include offset) usefull when we just want - // to know the relative position (in pixels) on the axis - function RelTranslate($aCoord) { - if( !is_numeric($aCoord) ) { - if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) - JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.'); - return 0; - } - else { - return ($aCoord - $this->scale[0]) * $this->scale_factor; - } - } - - // Restrict autoscaling to only use integers - function SetIntScale($aIntScale=true) { - $this->intscale=$aIntScale; - } - - // Calculate an integer autoscale - function IntAutoScale(&$img,$min,$max,$maxsteps,$majend=true) { - // Make sure limits are integers - $min=floor($min); - $max=ceil($max); - if( abs($min-$max)==0 ) { - --$min; ++$max; - } - $maxsteps = floor($maxsteps); - - $gracetop=round(($this->gracetop/100.0)*abs($max-$min)); - $gracebottom=round(($this->gracebottom/100.0)*abs($max-$min)); - if( is_numeric($this->autoscale_min) ) { - $min = ceil($this->autoscale_min); - if( $min >= $max ) { - 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.'); - } - } - - if( is_numeric($this->autoscale_max) ) { - $max = ceil($this->autoscale_max); - if( $min >= $max ) { - 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.'); - } - } - - if( abs($min-$max ) == 0 ) { - ++$max; - --$min; - } - - $min -= $gracebottom; - $max += $gracetop; - - // First get tickmarks as multiples of 1, 10, ... - if( $majend ) { - list($num1steps,$adj1min,$adj1max,$maj1step) = - $this->IntCalcTicks($maxsteps,$min,$max,1); - } - else { - $adj1min = $min; - $adj1max = $max; - list($num1steps,$maj1step) = - $this->IntCalcTicksFreeze($maxsteps,$min,$max,1); - } - - if( abs($min-$max) > 2 ) { - // Then get tick marks as 2:s 2, 20, ... - if( $majend ) { - list($num2steps,$adj2min,$adj2max,$maj2step) = - $this->IntCalcTicks($maxsteps,$min,$max,5); - } - else { - $adj2min = $min; - $adj2max = $max; - list($num2steps,$maj2step) = - $this->IntCalcTicksFreeze($maxsteps,$min,$max,5); - } - } - else { - $num2steps = 10000; // Dummy high value so we don't choose this - } - - if( abs($min-$max) > 5 ) { - // Then get tickmarks as 5:s 5, 50, 500, ... - if( $majend ) { - list($num5steps,$adj5min,$adj5max,$maj5step) = - $this->IntCalcTicks($maxsteps,$min,$max,2); - } - else { - $adj5min = $min; - $adj5max = $max; - list($num5steps,$maj5step) = - $this->IntCalcTicksFreeze($maxsteps,$min,$max,2); - } - } - else { - $num5steps = 10000; // Dummy high value so we don't choose this - } - - // Check to see whichof 1:s, 2:s or 5:s fit better with - // the requested number of major ticks - $match1=abs($num1steps-$maxsteps); - $match2=abs($num2steps-$maxsteps); - if( !empty($maj5step) && $maj5step > 1 ) - $match5=abs($num5steps-$maxsteps); - else - $match5=10000; // Dummy high value - - // Compare these three values and see which is the closest match - // We use a 0.6 weight to gravitate towards multiple of 5:s - if( $match1 < $match2 ) { - if( $match1 < $match5 ) - $r=1; - else - $r=3; - } - else { - if( $match2 < $match5 ) - $r=2; - else - $r=3; - } - // Minsteps are always the same as maxsteps for integer scale - switch( $r ) { - case 1: - $this->ticks->Set($maj1step,$maj1step); - $this->Update($img,$adj1min,$adj1max); - break; - case 2: - $this->ticks->Set($maj2step,$maj2step); - $this->Update($img,$adj2min,$adj2max); - break; - case 3: - $this->ticks->Set($maj5step,$maj5step); - $this->Update($img,$adj5min,$adj5max); - break; - default: - JpGraphError::RaiseL(25073,$r);//('Internal error. Integer scale algorithm comparison out of bound (r=$r)'); - } - } - - - // Calculate autoscale. Used if user hasn't given a scale and ticks - // $maxsteps is the maximum number of major tickmarks allowed. - function AutoScale(&$img,$min,$max,$maxsteps,$majend=true) { - if( $this->intscale ) { - $this->IntAutoScale($img,$min,$max,$maxsteps,$majend); - return; - } - if( abs($min-$max) < 0.00001 ) { - // We need some difference to be able to autoscale - // make it 5% above and 5% below value - if( $min==0 && $max==0 ) { // Special case - $min=-1; $max=1; - } - else { - $delta = (abs($max)+abs($min))*0.005; - $min -= $delta; - $max += $delta; - } - } - - $gracetop=($this->gracetop/100.0)*abs($max-$min); - $gracebottom=($this->gracebottom/100.0)*abs($max-$min); - if( is_numeric($this->autoscale_min) ) { - $min = $this->autoscale_min; - if( $min >= $max ) { - 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.'); - } - if( abs($min-$max ) < 0.00001 ) - $max *= 1.2; - } - - if( is_numeric($this->autoscale_max) ) { - $max = $this->autoscale_max; - if( $min >= $max ) { - 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.'); - } - if( abs($min-$max ) < 0.00001 ) - $min *= 0.8; - } - - - $min -= $gracebottom; - $max += $gracetop; - - // First get tickmarks as multiples of 0.1, 1, 10, ... - if( $majend ) { - list($num1steps,$adj1min,$adj1max,$min1step,$maj1step) = - $this->CalcTicks($maxsteps,$min,$max,1,2); - } - else { - $adj1min=$min; - $adj1max=$max; - list($num1steps,$min1step,$maj1step) = - $this->CalcTicksFreeze($maxsteps,$min,$max,1,2,false); - } - - // Then get tick marks as 2:s 0.2, 2, 20, ... - if( $majend ) { - list($num2steps,$adj2min,$adj2max,$min2step,$maj2step) = - $this->CalcTicks($maxsteps,$min,$max,5,2); - } - else { - $adj2min=$min; - $adj2max=$max; - list($num2steps,$min2step,$maj2step) = - $this->CalcTicksFreeze($maxsteps,$min,$max,5,2,false); - } - - // Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ... - if( $majend ) { - list($num5steps,$adj5min,$adj5max,$min5step,$maj5step) = - $this->CalcTicks($maxsteps,$min,$max,2,5); - } - else { - $adj5min=$min; - $adj5max=$max; - list($num5steps,$min5step,$maj5step) = - $this->CalcTicksFreeze($maxsteps,$min,$max,2,5,false); - } - - // Check to see whichof 1:s, 2:s or 5:s fit better with - // the requested number of major ticks - $match1=abs($num1steps-$maxsteps); - $match2=abs($num2steps-$maxsteps); - $match5=abs($num5steps-$maxsteps); - // Compare these three values and see which is the closest match - // We use a 0.8 weight to gravitate towards multiple of 5:s - $r=$this->MatchMin3($match1,$match2,$match5,0.8); - switch( $r ) { - case 1: - $this->Update($img,$adj1min,$adj1max); - $this->ticks->Set($maj1step,$min1step); - break; - case 2: - $this->Update($img,$adj2min,$adj2max); - $this->ticks->Set($maj2step,$min2step); - break; - case 3: - $this->Update($img,$adj5min,$adj5max); - $this->ticks->Set($maj5step,$min5step); - break; - } - } - -//--------------- -// PRIVATE METHODS - - // This method recalculates all constants that are depending on the - // margins in the image. If the margins in the image are changed - // this method should be called for every scale that is registred with - // that image. Should really be installed as an observer of that image. - function InitConstants(&$img) { - if( $this->type=="x" ) { - $this->world_abs_size=$img->width - $img->left_margin - $img->right_margin; - $this->off=$img->left_margin; - $this->scale_factor = 0; - if( $this->world_size > 0 ) - $this->scale_factor=$this->world_abs_size/($this->world_size*1.0); - } - else { // y scale - $this->world_abs_size=$img->height - $img->top_margin - $img->bottom_margin; - $this->off=$img->top_margin+$this->world_abs_size; - $this->scale_factor = 0; - if( $this->world_size > 0 ) { - $this->scale_factor=-$this->world_abs_size/($this->world_size*1.0); - } - } - $size = $this->world_size * $this->scale_factor; - $this->scale_abs=array($this->off,$this->off + $size); - } - - // Initialize the conversion constants for this scale - // This tries to pre-calculate as much as possible to speed up the - // actual conversion (with Translate()) later on - // $start =scale start in absolute pixels (for x-scale this is an y-position - // and for an y-scale this is an x-position - // $len =absolute length in pixels of scale - function SetConstants($aStart,$aLen) { - $this->world_abs_size=$aLen; - $this->off=$aStart; - - if( $this->world_size<=0 ) { - // This should never ever happen !! - JpGraphError::RaiseL(25074); -//("You have unfortunately stumbled upon a bug in JpGraph. It seems like the scale range is ".$this->world_size." [for ".$this->type." scale]
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."); - - } - - // scale_factor = number of pixels per world unit - $this->scale_factor=$this->world_abs_size/($this->world_size*1.0); - - // scale_abs = start and end points of scale in absolute pixels - $this->scale_abs=array($this->off,$this->off+$this->world_size*$this->scale_factor); - } - - - // Calculate number of ticks steps with a specific division - // $a is the divisor of 10**x to generate the first maj tick intervall - // $a=1, $b=2 give major ticks with multiple of 10, ...,0.1,1,10,... - // $a=5, $b=2 give major ticks with multiple of 2:s ...,0.2,2,20,... - // $a=2, $b=5 give major ticks with multiple of 5:s ...,0.5,5,50,... - // We return a vector of - // [$numsteps,$adjmin,$adjmax,$minstep,$majstep] - // If $majend==true then the first and last marks on the axis will be major - // labeled tick marks otherwise it will be adjusted to the closest min tick mark - function CalcTicks($maxsteps,$min,$max,$a,$b,$majend=true) { - $diff=$max-$min; - if( $diff==0 ) - $ld=0; - else - $ld=floor(log10($diff)); - - // Gravitate min towards zero if we are close - if( $min>0 && $min < pow(10,$ld) ) $min=0; - - //$majstep=pow(10,$ld-1)/$a; - $majstep=pow(10,$ld)/$a; - $minstep=$majstep/$b; - - $adjmax=ceil($max/$minstep)*$minstep; - $adjmin=floor($min/$minstep)*$minstep; - $adjdiff = $adjmax-$adjmin; - $numsteps=$adjdiff/$majstep; - - while( $numsteps>$maxsteps ) { - $majstep=pow(10,$ld)/$a; - $numsteps=$adjdiff/$majstep; - ++$ld; - } - - $minstep=$majstep/$b; - $adjmin=floor($min/$minstep)*$minstep; - $adjdiff = $adjmax-$adjmin; - if( $majend ) { - $adjmin = floor($min/$majstep)*$majstep; - $adjdiff = $adjmax-$adjmin; - $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin; - } - else - $adjmax=ceil($max/$minstep)*$minstep; - - return array($numsteps,$adjmin,$adjmax,$minstep,$majstep); - } - - function CalcTicksFreeze($maxsteps,$min,$max,$a,$b) { - // Same as CalcTicks but don't adjust min/max values - $diff=$max-$min; - if( $diff==0 ) - $ld=0; - else - $ld=floor(log10($diff)); - - //$majstep=pow(10,$ld-1)/$a; - $majstep=pow(10,$ld)/$a; - $minstep=$majstep/$b; - $numsteps=floor($diff/$majstep); - - while( $numsteps > $maxsteps ) { - $majstep=pow(10,$ld)/$a; - $numsteps=floor($diff/$majstep); - ++$ld; - } - $minstep=$majstep/$b; - return array($numsteps,$minstep,$majstep); - } - - - function IntCalcTicks($maxsteps,$min,$max,$a,$majend=true) { - $diff=$max-$min; - if( $diff==0 ) - JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.'); - else - $ld=floor(log10($diff)); - - // Gravitate min towards zero if we are close - if( $min>0 && $min < pow(10,$ld) ) $min=0; - - if( $ld == 0 ) $ld=1; - - if( $a == 1 ) - $majstep = 1; - else - $majstep=pow(10,$ld)/$a; - $adjmax=ceil($max/$majstep)*$majstep; - - $adjmin=floor($min/$majstep)*$majstep; - $adjdiff = $adjmax-$adjmin; - $numsteps=$adjdiff/$majstep; - while( $numsteps>$maxsteps ) { - $majstep=pow(10,$ld)/$a; - $numsteps=$adjdiff/$majstep; - ++$ld; - } - - $adjmin=floor($min/$majstep)*$majstep; - $adjdiff = $adjmax-$adjmin; - if( $majend ) { - $adjmin = floor($min/$majstep)*$majstep; - $adjdiff = $adjmax-$adjmin; - $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin; - } - else - $adjmax=ceil($max/$majstep)*$majstep; - - return array($numsteps,$adjmin,$adjmax,$majstep); - } - - - function IntCalcTicksFreeze($maxsteps,$min,$max,$a) { - // Same as IntCalcTick but don't change min/max values - $diff=$max-$min; - if( $diff==0 ) - JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.'); - else - $ld=floor(log10($diff)); - - if( $ld == 0 ) $ld=1; - - if( $a == 1 ) - $majstep = 1; - else - $majstep=pow(10,$ld)/$a; - - $numsteps=floor($diff/$majstep); - while( $numsteps > $maxsteps ) { - $majstep=pow(10,$ld)/$a; - $numsteps=floor($diff/$majstep); - ++$ld; - } - - return array($numsteps,$majstep); - } - - - - // Determine the minimum of three values witha weight for last value - function MatchMin3($a,$b,$c,$weight) { - if( $a < $b ) { - if( $a < ($c*$weight) ) - return 1; // $a smallest - else - return 3; // $c smallest - } - elseif( $b < ($c*$weight) ) - return 2; // $b smallest - return 3; // $c smallest - } -} // Class - -//=================================================== -// CLASS RGB -// Description: Color definitions as RGB triples -//=================================================== -class RGB { - var $rgb_table; - var $img; - function __construct(&$aImg) { - $this->img = &$aImg; - - // Conversion array between color names and RGB - $this->rgb_table = array( - "aqua"=> array(0,255,255), - "lime"=> array(0,255,0), - "teal"=> array(0,128,128), - "whitesmoke"=>array(245,245,245), - "gainsboro"=>array(220,220,220), - "oldlace"=>array(253,245,230), - "linen"=>array(250,240,230), - "antiquewhite"=>array(250,235,215), - "papayawhip"=>array(255,239,213), - "blanchedalmond"=>array(255,235,205), - "bisque"=>array(255,228,196), - "peachpuff"=>array(255,218,185), - "navajowhite"=>array(255,222,173), - "moccasin"=>array(255,228,181), - "cornsilk"=>array(255,248,220), - "ivory"=>array(255,255,240), - "lemonchiffon"=>array(255,250,205), - "seashell"=>array(255,245,238), - "mintcream"=>array(245,255,250), - "azure"=>array(240,255,255), - "aliceblue"=>array(240,248,255), - "lavender"=>array(230,230,250), - "lavenderblush"=>array(255,240,245), - "mistyrose"=>array(255,228,225), - "white"=>array(255,255,255), - "black"=>array(0,0,0), - "darkslategray"=>array(47,79,79), - "dimgray"=>array(105,105,105), - "slategray"=>array(112,128,144), - "lightslategray"=>array(119,136,153), - "gray"=>array(190,190,190), - "lightgray"=>array(211,211,211), - "midnightblue"=>array(25,25,112), - "navy"=>array(0,0,128), - "cornflowerblue"=>array(100,149,237), - "darkslateblue"=>array(72,61,139), - "slateblue"=>array(106,90,205), - "mediumslateblue"=>array(123,104,238), - "lightslateblue"=>array(132,112,255), - "mediumblue"=>array(0,0,205), - "royalblue"=>array(65,105,225), - "blue"=>array(0,0,255), - "dodgerblue"=>array(30,144,255), - "deepskyblue"=>array(0,191,255), - "skyblue"=>array(135,206,235), - "lightskyblue"=>array(135,206,250), - "steelblue"=>array(70,130,180), - "lightred"=>array(211,167,168), - "lightsteelblue"=>array(176,196,222), - "lightblue"=>array(173,216,230), - "powderblue"=>array(176,224,230), - "paleturquoise"=>array(175,238,238), - "darkturquoise"=>array(0,206,209), - "mediumturquoise"=>array(72,209,204), - "turquoise"=>array(64,224,208), - "cyan"=>array(0,255,255), - "lightcyan"=>array(224,255,255), - "cadetblue"=>array(95,158,160), - "mediumaquamarine"=>array(102,205,170), - "aquamarine"=>array(127,255,212), - "darkgreen"=>array(0,100,0), - "darkolivegreen"=>array(85,107,47), - "darkseagreen"=>array(143,188,143), - "seagreen"=>array(46,139,87), - "mediumseagreen"=>array(60,179,113), - "lightseagreen"=>array(32,178,170), - "palegreen"=>array(152,251,152), - "springgreen"=>array(0,255,127), - "lawngreen"=>array(124,252,0), - "green"=>array(0,255,0), - "chartreuse"=>array(127,255,0), - "mediumspringgreen"=>array(0,250,154), - "greenyellow"=>array(173,255,47), - "limegreen"=>array(50,205,50), - "yellowgreen"=>array(154,205,50), - "forestgreen"=>array(34,139,34), - "olivedrab"=>array(107,142,35), - "darkkhaki"=>array(189,183,107), - "khaki"=>array(240,230,140), - "palegoldenrod"=>array(238,232,170), - "lightgoldenrodyellow"=>array(250,250,210), - "lightyellow"=>array(255,255,200), - "yellow"=>array(255,255,0), - "gold"=>array(255,215,0), - "lightgoldenrod"=>array(238,221,130), - "goldenrod"=>array(218,165,32), - "darkgoldenrod"=>array(184,134,11), - "rosybrown"=>array(188,143,143), - "indianred"=>array(205,92,92), - "saddlebrown"=>array(139,69,19), - "sienna"=>array(160,82,45), - "peru"=>array(205,133,63), - "burlywood"=>array(222,184,135), - "beige"=>array(245,245,220), - "wheat"=>array(245,222,179), - "sandybrown"=>array(244,164,96), - "tan"=>array(210,180,140), - "chocolate"=>array(210,105,30), - "firebrick"=>array(178,34,34), - "brown"=>array(165,42,42), - "darksalmon"=>array(233,150,122), - "salmon"=>array(250,128,114), - "lightsalmon"=>array(255,160,122), - "orange"=>array(255,165,0), - "darkorange"=>array(255,140,0), - "coral"=>array(255,127,80), - "lightcoral"=>array(240,128,128), - "tomato"=>array(255,99,71), - "orangered"=>array(255,69,0), - "red"=>array(255,0,0), - "hotpink"=>array(255,105,180), - "deeppink"=>array(255,20,147), - "pink"=>array(255,192,203), - "lightpink"=>array(255,182,193), - "palevioletred"=>array(219,112,147), - "maroon"=>array(176,48,96), - "mediumvioletred"=>array(199,21,133), - "violetred"=>array(208,32,144), - "magenta"=>array(255,0,255), - "violet"=>array(238,130,238), - "plum"=>array(221,160,221), - "orchid"=>array(218,112,214), - "mediumorchid"=>array(186,85,211), - "darkorchid"=>array(153,50,204), - "darkviolet"=>array(148,0,211), - "blueviolet"=>array(138,43,226), - "purple"=>array(160,32,240), - "mediumpurple"=>array(147,112,219), - "thistle"=>array(216,191,216), - "snow1"=>array(255,250,250), - "snow2"=>array(238,233,233), - "snow3"=>array(205,201,201), - "snow4"=>array(139,137,137), - "seashell1"=>array(255,245,238), - "seashell2"=>array(238,229,222), - "seashell3"=>array(205,197,191), - "seashell4"=>array(139,134,130), - "AntiqueWhite1"=>array(255,239,219), - "AntiqueWhite2"=>array(238,223,204), - "AntiqueWhite3"=>array(205,192,176), - "AntiqueWhite4"=>array(139,131,120), - "bisque1"=>array(255,228,196), - "bisque2"=>array(238,213,183), - "bisque3"=>array(205,183,158), - "bisque4"=>array(139,125,107), - "peachPuff1"=>array(255,218,185), - "peachpuff2"=>array(238,203,173), - "peachpuff3"=>array(205,175,149), - "peachpuff4"=>array(139,119,101), - "navajowhite1"=>array(255,222,173), - "navajowhite2"=>array(238,207,161), - "navajowhite3"=>array(205,179,139), - "navajowhite4"=>array(139,121,94), - "lemonchiffon1"=>array(255,250,205), - "lemonchiffon2"=>array(238,233,191), - "lemonchiffon3"=>array(205,201,165), - "lemonchiffon4"=>array(139,137,112), - "ivory1"=>array(255,255,240), - "ivory2"=>array(238,238,224), - "ivory3"=>array(205,205,193), - "ivory4"=>array(139,139,131), - "honeydew"=>array(193,205,193), - "lavenderblush1"=>array(255,240,245), - "lavenderblush2"=>array(238,224,229), - "lavenderblush3"=>array(205,193,197), - "lavenderblush4"=>array(139,131,134), - "mistyrose1"=>array(255,228,225), - "mistyrose2"=>array(238,213,210), - "mistyrose3"=>array(205,183,181), - "mistyrose4"=>array(139,125,123), - "azure1"=>array(240,255,255), - "azure2"=>array(224,238,238), - "azure3"=>array(193,205,205), - "azure4"=>array(131,139,139), - "slateblue1"=>array(131,111,255), - "slateblue2"=>array(122,103,238), - "slateblue3"=>array(105,89,205), - "slateblue4"=>array(71,60,139), - "royalblue1"=>array(72,118,255), - "royalblue2"=>array(67,110,238), - "royalblue3"=>array(58,95,205), - "royalblue4"=>array(39,64,139), - "dodgerblue1"=>array(30,144,255), - "dodgerblue2"=>array(28,134,238), - "dodgerblue3"=>array(24,116,205), - "dodgerblue4"=>array(16,78,139), - "steelblue1"=>array(99,184,255), - "steelblue2"=>array(92,172,238), - "steelblue3"=>array(79,148,205), - "steelblue4"=>array(54,100,139), - "deepskyblue1"=>array(0,191,255), - "deepskyblue2"=>array(0,178,238), - "deepskyblue3"=>array(0,154,205), - "deepskyblue4"=>array(0,104,139), - "skyblue1"=>array(135,206,255), - "skyblue2"=>array(126,192,238), - "skyblue3"=>array(108,166,205), - "skyblue4"=>array(74,112,139), - "lightskyblue1"=>array(176,226,255), - "lightskyblue2"=>array(164,211,238), - "lightskyblue3"=>array(141,182,205), - "lightskyblue4"=>array(96,123,139), - "slategray1"=>array(198,226,255), - "slategray2"=>array(185,211,238), - "slategray3"=>array(159,182,205), - "slategray4"=>array(108,123,139), - "lightsteelblue1"=>array(202,225,255), - "lightsteelblue2"=>array(188,210,238), - "lightsteelblue3"=>array(162,181,205), - "lightsteelblue4"=>array(110,123,139), - "lightblue1"=>array(191,239,255), - "lightblue2"=>array(178,223,238), - "lightblue3"=>array(154,192,205), - "lightblue4"=>array(104,131,139), - "lightcyan1"=>array(224,255,255), - "lightcyan2"=>array(209,238,238), - "lightcyan3"=>array(180,205,205), - "lightcyan4"=>array(122,139,139), - "paleturquoise1"=>array(187,255,255), - "paleturquoise2"=>array(174,238,238), - "paleturquoise3"=>array(150,205,205), - "paleturquoise4"=>array(102,139,139), - "cadetblue1"=>array(152,245,255), - "cadetblue2"=>array(142,229,238), - "cadetblue3"=>array(122,197,205), - "cadetblue4"=>array(83,134,139), - "turquoise1"=>array(0,245,255), - "turquoise2"=>array(0,229,238), - "turquoise3"=>array(0,197,205), - "turquoise4"=>array(0,134,139), - "cyan1"=>array(0,255,255), - "cyan2"=>array(0,238,238), - "cyan3"=>array(0,205,205), - "cyan4"=>array(0,139,139), - "darkslategray1"=>array(151,255,255), - "darkslategray2"=>array(141,238,238), - "darkslategray3"=>array(121,205,205), - "darkslategray4"=>array(82,139,139), - "aquamarine1"=>array(127,255,212), - "aquamarine2"=>array(118,238,198), - "aquamarine3"=>array(102,205,170), - "aquamarine4"=>array(69,139,116), - "darkseagreen1"=>array(193,255,193), - "darkseagreen2"=>array(180,238,180), - "darkseagreen3"=>array(155,205,155), - "darkseagreen4"=>array(105,139,105), - "seagreen1"=>array(84,255,159), - "seagreen2"=>array(78,238,148), - "seagreen3"=>array(67,205,128), - "seagreen4"=>array(46,139,87), - "palegreen1"=>array(154,255,154), - "palegreen2"=>array(144,238,144), - "palegreen3"=>array(124,205,124), - "palegreen4"=>array(84,139,84), - "springgreen1"=>array(0,255,127), - "springgreen2"=>array(0,238,118), - "springgreen3"=>array(0,205,102), - "springgreen4"=>array(0,139,69), - "chartreuse1"=>array(127,255,0), - "chartreuse2"=>array(118,238,0), - "chartreuse3"=>array(102,205,0), - "chartreuse4"=>array(69,139,0), - "olivedrab1"=>array(192,255,62), - "olivedrab2"=>array(179,238,58), - "olivedrab3"=>array(154,205,50), - "olivedrab4"=>array(105,139,34), - "darkolivegreen1"=>array(202,255,112), - "darkolivegreen2"=>array(188,238,104), - "darkolivegreen3"=>array(162,205,90), - "darkolivegreen4"=>array(110,139,61), - "khaki1"=>array(255,246,143), - "khaki2"=>array(238,230,133), - "khaki3"=>array(205,198,115), - "khaki4"=>array(139,134,78), - "lightgoldenrod1"=>array(255,236,139), - "lightgoldenrod2"=>array(238,220,130), - "lightgoldenrod3"=>array(205,190,112), - "lightgoldenrod4"=>array(139,129,76), - "yellow1"=>array(255,255,0), - "yellow2"=>array(238,238,0), - "yellow3"=>array(205,205,0), - "yellow4"=>array(139,139,0), - "gold1"=>array(255,215,0), - "gold2"=>array(238,201,0), - "gold3"=>array(205,173,0), - "gold4"=>array(139,117,0), - "goldenrod1"=>array(255,193,37), - "goldenrod2"=>array(238,180,34), - "goldenrod3"=>array(205,155,29), - "goldenrod4"=>array(139,105,20), - "darkgoldenrod1"=>array(255,185,15), - "darkgoldenrod2"=>array(238,173,14), - "darkgoldenrod3"=>array(205,149,12), - "darkgoldenrod4"=>array(139,101,8), - "rosybrown1"=>array(255,193,193), - "rosybrown2"=>array(238,180,180), - "rosybrown3"=>array(205,155,155), - "rosybrown4"=>array(139,105,105), - "indianred1"=>array(255,106,106), - "indianred2"=>array(238,99,99), - "indianred3"=>array(205,85,85), - "indianred4"=>array(139,58,58), - "sienna1"=>array(255,130,71), - "sienna2"=>array(238,121,66), - "sienna3"=>array(205,104,57), - "sienna4"=>array(139,71,38), - "burlywood1"=>array(255,211,155), - "burlywood2"=>array(238,197,145), - "burlywood3"=>array(205,170,125), - "burlywood4"=>array(139,115,85), - "wheat1"=>array(255,231,186), - "wheat2"=>array(238,216,174), - "wheat3"=>array(205,186,150), - "wheat4"=>array(139,126,102), - "tan1"=>array(255,165,79), - "tan2"=>array(238,154,73), - "tan3"=>array(205,133,63), - "tan4"=>array(139,90,43), - "chocolate1"=>array(255,127,36), - "chocolate2"=>array(238,118,33), - "chocolate3"=>array(205,102,29), - "chocolate4"=>array(139,69,19), - "firebrick1"=>array(255,48,48), - "firebrick2"=>array(238,44,44), - "firebrick3"=>array(205,38,38), - "firebrick4"=>array(139,26,26), - "brown1"=>array(255,64,64), - "brown2"=>array(238,59,59), - "brown3"=>array(205,51,51), - "brown4"=>array(139,35,35), - "salmon1"=>array(255,140,105), - "salmon2"=>array(238,130,98), - "salmon3"=>array(205,112,84), - "salmon4"=>array(139,76,57), - "lightsalmon1"=>array(255,160,122), - "lightsalmon2"=>array(238,149,114), - "lightsalmon3"=>array(205,129,98), - "lightsalmon4"=>array(139,87,66), - "orange1"=>array(255,165,0), - "orange2"=>array(238,154,0), - "orange3"=>array(205,133,0), - "orange4"=>array(139,90,0), - "darkorange1"=>array(255,127,0), - "darkorange2"=>array(238,118,0), - "darkorange3"=>array(205,102,0), - "darkorange4"=>array(139,69,0), - "coral1"=>array(255,114,86), - "coral2"=>array(238,106,80), - "coral3"=>array(205,91,69), - "coral4"=>array(139,62,47), - "tomato1"=>array(255,99,71), - "tomato2"=>array(238,92,66), - "tomato3"=>array(205,79,57), - "tomato4"=>array(139,54,38), - "orangered1"=>array(255,69,0), - "orangered2"=>array(238,64,0), - "orangered3"=>array(205,55,0), - "orangered4"=>array(139,37,0), - "deeppink1"=>array(255,20,147), - "deeppink2"=>array(238,18,137), - "deeppink3"=>array(205,16,118), - "deeppink4"=>array(139,10,80), - "hotpink1"=>array(255,110,180), - "hotpink2"=>array(238,106,167), - "hotpink3"=>array(205,96,144), - "hotpink4"=>array(139,58,98), - "pink1"=>array(255,181,197), - "pink2"=>array(238,169,184), - "pink3"=>array(205,145,158), - "pink4"=>array(139,99,108), - "lightpink1"=>array(255,174,185), - "lightpink2"=>array(238,162,173), - "lightpink3"=>array(205,140,149), - "lightpink4"=>array(139,95,101), - "palevioletred1"=>array(255,130,171), - "palevioletred2"=>array(238,121,159), - "palevioletred3"=>array(205,104,137), - "palevioletred4"=>array(139,71,93), - "maroon1"=>array(255,52,179), - "maroon2"=>array(238,48,167), - "maroon3"=>array(205,41,144), - "maroon4"=>array(139,28,98), - "violetred1"=>array(255,62,150), - "violetred2"=>array(238,58,140), - "violetred3"=>array(205,50,120), - "violetred4"=>array(139,34,82), - "magenta1"=>array(255,0,255), - "magenta2"=>array(238,0,238), - "magenta3"=>array(205,0,205), - "magenta4"=>array(139,0,139), - "mediumred"=>array(140,34,34), - "orchid1"=>array(255,131,250), - "orchid2"=>array(238,122,233), - "orchid3"=>array(205,105,201), - "orchid4"=>array(139,71,137), - "plum1"=>array(255,187,255), - "plum2"=>array(238,174,238), - "plum3"=>array(205,150,205), - "plum4"=>array(139,102,139), - "mediumorchid1"=>array(224,102,255), - "mediumorchid2"=>array(209,95,238), - "mediumorchid3"=>array(180,82,205), - "mediumorchid4"=>array(122,55,139), - "darkorchid1"=>array(191,62,255), - "darkorchid2"=>array(178,58,238), - "darkorchid3"=>array(154,50,205), - "darkorchid4"=>array(104,34,139), - "purple1"=>array(155,48,255), - "purple2"=>array(145,44,238), - "purple3"=>array(125,38,205), - "purple4"=>array(85,26,139), - "mediumpurple1"=>array(171,130,255), - "mediumpurple2"=>array(159,121,238), - "mediumpurple3"=>array(137,104,205), - "mediumpurple4"=>array(93,71,139), - "thistle1"=>array(255,225,255), - "thistle2"=>array(238,210,238), - "thistle3"=>array(205,181,205), - "thistle4"=>array(139,123,139), - "gray1"=>array(10,10,10), - "gray2"=>array(40,40,30), - "gray3"=>array(70,70,70), - "gray4"=>array(100,100,100), - "gray5"=>array(130,130,130), - "gray6"=>array(160,160,160), - "gray7"=>array(190,190,190), - "gray8"=>array(210,210,210), - "gray9"=>array(240,240,240), - "darkgray"=>array(100,100,100), - "darkblue"=>array(0,0,139), - "darkcyan"=>array(0,139,139), - "darkmagenta"=>array(139,0,139), - "darkred"=>array(139,0,0), - "silver"=>array(192, 192, 192), - "eggplant"=>array(144,176,168), - "lightgreen"=>array(144,238,144)); - } -//---------------- -// PUBLIC METHODS - // Colors can be specified as either - // 1. #xxxxxx HTML style - // 2. "colorname" as a named color - // 3. array(r,g,b) RGB triple - // This function translates this to a native RGB format and returns an - // RGB triple. - function Color($aColor) { - if (is_string($aColor)) { - // Strip of any alpha factor - $pos = strpos($aColor,'@'); - if( $pos === false ) { - $alpha = 0; - } - else { - $pos2 = strpos($aColor,':'); - if( $pos2===false ) - $pos2 = $pos-1; // Sentinel - if( $pos > $pos2 ) { - $alpha = substr($aColor,$pos+1); - $aColor = substr($aColor,0,$pos); - } - else { - $alpha = substr($aColor,$pos+1,$pos2-$pos-1); - $aColor = substr($aColor,0,$pos).substr($aColor,$pos2); - } - } - - // Extract potential adjustment figure at end of color - // specification - $pos = strpos($aColor,":"); - if( $pos === false ) { - $adj = 1.0; - } - else { - $adj = 0.0 + substr($aColor,$pos+1); - $aColor = substr($aColor,0,$pos); - } - if( $adj < 0 ) - JpGraphError::RaiseL(25077);//('Adjustment factor for color must be > 0'); - - if (substr($aColor, 0, 1) == "#") { - $r = hexdec(substr($aColor, 1, 2)); - $g = hexdec(substr($aColor, 3, 2)); - $b = hexdec(substr($aColor, 5, 2)); - } else { - if(!isset($this->rgb_table[$aColor]) ) - JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor"); - $tmp=$this->rgb_table[$aColor]; - $r = $tmp[0]; - $g = $tmp[1]; - $b = $tmp[2]; - } - // Scale adj so that an adj=2 always - // makes the color 100% white (i.e. 255,255,255. - // and adj=1 neutral and adj=0 black. - if( $adj > 1 ) { - $m = ($adj-1.0)*(255-min(255,min($r,min($g,$b)))); - return array(min(255,$r+$m), min(255,$g+$m), min(255,$b+$m),$alpha); - } - elseif( $adj < 1 ) { - $m = ($adj-1.0)*max(255,max($r,max($g,$b))); - return array(max(0,$r+$m), max(0,$g+$m), max(0,$b+$m),$alpha); - } - else { - return array($r,$g,$b,$alpha); - } - - } elseif( is_array($aColor) ) { - if( count($aColor)==3 ) { - $aColor[3]=0; - return $aColor; - } - else - return $aColor; - } - else - JpGraphError::RaiseL(25079,$aColor,count($aColor));//(" Unknown color specification: $aColor , size=".count($aColor)); - } - - // Compare two colors - // return true if equal - function Equal($aCol1,$aCol2) { - $c1 = $this->Color($aCol1); - $c2 = $this->Color($aCol2); - if( $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] ) - return true; - else - return false; - } - - // Allocate a new color in the current image - // Return new color index, -1 if no more colors could be allocated - function Allocate($aColor,$aAlpha=0.0) { - list ($r, $g, $b, $a) = $this->color($aColor); - // If alpha is specified in the color string then this - // takes precedence over the second argument - if( $a > 0 ) - $aAlpha = $a; - if( $GLOBALS['gd2'] ) { - if( $aAlpha < 0 || $aAlpha > 1 ) { - JpGraphError::RaiseL(25080);//('Alpha parameter for color must be between 0.0 and 1.0'); - } - return imagecolorresolvealpha($this->img, $r, $g, $b, round($aAlpha * 127)); - } else { - $index = imagecolorexact($this->img, $r, $g, $b); - if ($index == -1) { - $index = imagecolorallocate($this->img, $r, $g, $b); - if( USE_APPROX_COLORS && $index == -1 ) - $index = imagecolorresolve($this->img, $r, $g, $b); - } - return $index; - } - } -} // Class - - -//=================================================== -// CLASS Image -// Description: Wrapper class with some goodies to form the -// Interface to low level image drawing routines. -//=================================================== -class Image { - var $img_format; - var $expired=true; - var $img=null; - var $left_margin=30,$right_margin=20,$top_margin=20,$bottom_margin=30; - var $plotwidth=0,$plotheight=0; - var $rgb=null; - var $current_color,$current_color_name; - var $lastx=0, $lasty=0; - var $width=0, $height=0; - var $line_weight=1; - var $line_style=1; // Default line style is solid - var $obs_list=array(); - var $font_size=12,$font_family=FF_FONT1, $font_style=FS_NORMAL; - var $font_file=''; - var $text_halign="left",$text_valign="bottom"; - var $ttf=null; - var $use_anti_aliasing=false; - var $quality=null; - var $colorstack=array(),$colorstackidx=0; - var $canvascolor = 'white' ; - var $langconv = null ; - - //--------------- - // CONSTRUCTOR - function __construct($aWidth,$aHeight,$aFormat=DEFAULT_GFORMAT) { - $this->CreateImgCanvas($aWidth,$aHeight); - $this->SetAutoMargin(); - - if( !$this->SetImgFormat($aFormat) ) { - JpGraphError::RaiseL(25081,$aFormat);//("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]"); - } - $this->ttf = new TTF(); - $this->langconv = new LanguageConv(); - } - - // Should we use anti-aliasing. Note: This really slows down graphics! - function SetAntiAliasing() { - $this->use_anti_aliasing=true; - } - - function CreateRawCanvas($aWidth=0,$aHeight=0) { - if( $aWidth <= 1 || $aHeight <= 1 ) { - JpGraphError::RaiseL(25082,$aWidth,$aHeight);//("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)"); - } - if( @$GLOBALS['gd2']==true && USE_TRUECOLOR ) { - $this->img = @imagecreatetruecolor($aWidth, $aHeight); - if( $this->img < 1 ) { - JpGraphError::RaiseL(25126); - //die("Can't create truecolor image. Check that you really have GD2 library installed."); - } - $this->SetAlphaBlending(); - } else { - $this->img = @imagecreate($aWidth, $aHeight); - if( $this->img < 1 ) { - JpGraphError::RaiseL(25126); - //die("JpGraph Error: Can't create image. Check that you really have the GD library installed."); - } - } - if( $this->rgb != null ) - $this->rgb->img = $this->img ; - else - $this->rgb = new RGB($this->img); - } - - function CloneCanvasH() { - $oldimage = $this->img; - $this->CreateRawCanvas($this->width,$this->height); - imagecopy($this->img,$oldimage,0,0,0,0,$this->width,$this->height); - return $oldimage; - } - - function CreateImgCanvas($aWidth=0,$aHeight=0) { - - $old = array($this->img,$this->width,$this->height); - - $aWidth = round($aWidth); - $aHeight = round($aHeight); - - $this->width=$aWidth; - $this->height=$aHeight; - - - if( $aWidth==0 || $aHeight==0 ) { - // We will set the final size later. - // Note: The size must be specified before any other - // img routines that stroke anything are called. - $this->img = null; - $this->rgb = null; - return $old; - } - - $this->CreateRawCanvas($aWidth,$aHeight); - - // Set canvas color (will also be the background color for a - // a pallett image - $this->SetColor($this->canvascolor); - $this->FilledRectangle(0,0,$aWidth,$aHeight); - - return $old ; - } - - function CopyCanvasH($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY,$aWidth,$aHeight,$aw=-1,$ah=-1) { - if( $aw === -1 ) { - $aw = $aWidth; - $ah = $aHeight; - $f = 'imagecopyresized'; - } - else { - $f = $GLOBALS['copyfunc'] ; - } - $f($aToHdl,$aFromHdl, - $aToX,$aToY,$aFromX,$aFromY, $aWidth,$aHeight,$aw,$ah); - } - - function Copy($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1) { - $this->CopyCanvasH($this->img,$fromImg,$toX,$toY,$fromX,$fromY, - $toWidth,$toHeight,$fromWidth,$fromHeight); - } - - function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) { - if( $aMix == 100 ) { - $this->CopyCanvasH($this->img,$fromImg, - $toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight); - } - else { - if( ($fromWidth != -1 && ($fromWidth != $toWidth)) || - ($fromHeight != -1 && ($fromHeight != $fromHeight)) ) { - // Create a new canvas that will hold the re-scaled original from image - if( $toWidth <= 1 || $toHeight <= 1 ) { - JpGraphError::RaiseL(25083);//('Illegal image size when copying image. Size for copied to image is 1 pixel or less.'); - } - if( @$GLOBALS['gd2']==true && USE_TRUECOLOR ) { - $tmpimg = @imagecreatetruecolor($toWidth, $toHeight); - } else { - $tmpimg = @imagecreate($toWidth, $toHeight); - } - if( $tmpimg < 1 ) { - JpGraphError::RaiseL(25084);//('Failed to create temporary GD canvas. Out of memory ?'); - } - $this->CopyCanvasH($tmpimg,$fromImg,0,0,0,0, - $toWidth,$toHeight,$fromWidth,$fromHeight); - $fromImg = $tmpimg; - } - imagecopymerge($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$aMix); - } - } - - function GetWidth($aImg=null) { - if( $aImg === null ) - $aImg = $this->img; - return imagesx($aImg); - } - - function GetHeight($aImg=null) { - if( $aImg === null ) - $aImg = $this->img; - return imagesy($aImg); - } - - function CreateFromString($aStr) { - $img = imagecreatefromstring($aStr); - if( $img === false ) { - 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.'); - } - return $img; - } - - function SetCanvasH($aHdl) { - $this->img = $aHdl; - $this->rgb->img = $aHdl; - } - - function SetCanvasColor($aColor) { - $this->canvascolor = $aColor ; - } - - function SetAlphaBlending($aFlg=true) { - if( $GLOBALS['gd2'] ) - ImageAlphaBlending($this->img,$aFlg); - else - JpGraphError::RaiseL(25086);//('You only seem to have GD 1.x installed. To enable Alphablending requires GD 2.x or higher. Please install GD or make sure the constant USE_GD2 is specified correctly to reflect your installation. By default it tries to autodetect what version of GD you have installed. On some very rare occasions it may falsely detect GD2 where only GD1 is installed. You must then set USE_GD2 to false.'); - } - - - function SetAutoMargin() { - GLOBAL $gJpgBrandTiming; - $min_bm=10; - /* - if( $gJpgBrandTiming ) - $min_bm=15; - */ - $lm = min(40,$this->width/7); - $rm = min(20,$this->width/10); - $tm = max(20,$this->height/7); - $bm = max($min_bm,$this->height/7); - $this->SetMargin($lm,$rm,$tm,$bm); - } - - - //--------------- - // PUBLIC METHODS - - function SetFont($family,$style=FS_NORMAL,$size=10) { - $this->font_family=$family; - $this->font_style=$style; - $this->font_size=$size; - $this->font_file=''; - if( ($this->font_family==FF_FONT1 || $this->font_family==FF_FONT2) && $this->font_style==FS_BOLD ){ - ++$this->font_family; - } - if( $this->font_family > FF_FONT2+1 ) { // A TTF font so get the font file - - // Check that this PHP has support for TTF fonts - if( !function_exists('imagettfbbox') ) { - JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.'); - exit(); - } - $this->font_file = $this->ttf->File($this->font_family,$this->font_style); - } - } - - // Get the specific height for a text string - function GetTextHeight($txt="",$angle=0) { - $tmp = split("\n",$txt); - $n = count($tmp); - $m=0; - for($i=0; $i< $n; ++$i) - $m = max($m,strlen($tmp[$i])); - - if( $this->font_family <= FF_FONT2+1 ) { - if( $angle==0 ) { - $h = imagefontheight($this->font_family); - if( $h === false ) { - JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); - } - - return $n*$h; - } - else { - $w = @imagefontwidth($this->font_family); - if( $w === false ) { - JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); - } - - return $m*$w; - } - } - else { - $bbox = $this->GetTTFBBox($txt,$angle); - return $bbox[1]-$bbox[5]; - } - } - - // Estimate font height - function GetFontHeight($angle=0) { - $txt = "XOMg"; - return $this->GetTextHeight($txt,$angle); - } - - // Approximate font width with width of letter "O" - function GetFontWidth($angle=0) { - $txt = 'O'; - return $this->GetTextWidth($txt,$angle); - } - - // Get actual width of text in absolute pixels - function GetTextWidth($txt,$angle=0) { - - $tmp = split("\n",$txt); - $n = count($tmp); - if( $this->font_family <= FF_FONT2+1 ) { - - $m=0; - for($i=0; $i < $n; ++$i) { - $l=strlen($tmp[$i]); - if( $l > $m ) { - $m = $l; - } - } - - if( $angle==0 ) { - $w = @imagefontwidth($this->font_family); - if( $w === false ) { - JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); - } - return $m*$w; - } - else { - // 90 degrees internal so height becomes width - $h = @imagefontheight($this->font_family); - if( $h === false ) { - JpGraphError::RaiseL(25089);//('You have a misconfigured GD font support. The call to imagefontheight() fails.'); - } - return $n*$h; - } - } - else { - // For TTF fonts we must walk through a lines and find the - // widest one which we use as the width of the multi-line - // paragraph - $m=0; - for( $i=0; $i < $n; ++$i ) { - $bbox = $this->GetTTFBBox($tmp[$i],$angle); - $mm = $bbox[2] - $bbox[0]; - if( $mm > $m ) - $m = $mm; - } - return $m; - } - } - - // Draw text with a box around it - function StrokeBoxedText($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black", - $shadowcolor=false,$paragraph_align="left", - $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) { - - if( !is_numeric($dir) ) { - if( $dir=="h" ) $dir=0; - elseif( $dir=="v" ) $dir=90; - else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]"); - } - - if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) { - $width=$this->GetTextWidth($txt,$dir) ; - $height=$this->GetTextHeight($txt,$dir) ; - } - else { - $width=$this->GetBBoxWidth($txt,$dir) ; - $height=$this->GetBBoxHeight($txt,$dir) ; - } - - $height += 2*$ymarg; - $width += 2*$xmarg; - - if( $this->text_halign=="right" ) $x -= $width; - elseif( $this->text_halign=="center" ) $x -= $width/2; - if( $this->text_valign=="bottom" ) $y -= $height; - elseif( $this->text_valign=="center" ) $y -= $height/2; - - if( $shadowcolor ) { - $this->PushColor($shadowcolor); - $this->FilledRoundedRectangle($x-$xmarg+$dropwidth,$y-$ymarg+$dropwidth, - $x+$width+$dropwidth,$y+$height-$ymarg+$dropwidth, - $cornerradius); - $this->PopColor(); - $this->PushColor($fcolor); - $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg, - $x+$width,$y+$height-$ymarg, - $cornerradius); - $this->PopColor(); - $this->PushColor($bcolor); - $this->RoundedRectangle($x-$xmarg,$y-$ymarg, - $x+$width,$y+$height-$ymarg,$cornerradius); - $this->PopColor(); - } - else { - if( $fcolor ) { - $oc=$this->current_color; - $this->SetColor($fcolor); - $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius); - $this->current_color=$oc; - } - if( $bcolor ) { - $oc=$this->current_color; - $this->SetColor($bcolor); - $this->RoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius); - $this->current_color=$oc; - } - } - - $h=$this->text_halign; - $v=$this->text_valign; - $this->SetTextAlign("left","top"); - $this->StrokeText($x, $y, $txt, $dir, $paragraph_align); - $bb = array($x-$xmarg,$y+$height-$ymarg,$x+$width,$y+$height-$ymarg, - $x+$width,$y-$ymarg,$x-$xmarg,$y-$ymarg); - $this->SetTextAlign($h,$v); - return $bb; - } - - // Set text alignment - function SetTextAlign($halign,$valign="bottom") { - $this->text_halign=$halign; - $this->text_valign=$valign; - } - - - function _StrokeBuiltinFont($x,$y,$txt,$dir=0,$paragraph_align="left",&$aBoundingBox,$aDebug=false) { - - if( is_numeric($dir) && $dir!=90 && $dir!=0) - JpGraphError::RaiseL(25091);//(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead."); - - $h=$this->GetTextHeight($txt); - $fh=$this->GetFontHeight(); - $w=$this->GetTextWidth($txt); - - if( $this->text_halign=="right") - $x -= $dir==0 ? $w : $h; - elseif( $this->text_halign=="center" ) { - // For center we subtract 1 pixel since this makes the middle - // be prefectly in the middle - $x -= $dir==0 ? $w/2-1 : $h/2; - } - if( $this->text_valign=="top" ) - $y += $dir==0 ? $h : $w; - elseif( $this->text_valign=="center" ) - $y += $dir==0 ? $h/2 : $w/2; - - if( $dir==90 ) { - imagestringup($this->img,$this->font_family,$x,$y,$txt,$this->current_color); - $aBoundingBox = array(round($x),round($y),round($x),round($y-$w),round($x+$h),round($y-$w),round($x+$h),round($y)); - if( $aDebug ) { - // Draw bounding box - $this->PushColor('green'); - $this->Polygon($aBoundingBox,true); - $this->PopColor(); - } - } - else { - if( ereg("\n",$txt) ) { - $tmp = split("\n",$txt); - for($i=0; $i < count($tmp); ++$i) { - $w1 = $this->GetTextWidth($tmp[$i]); - if( $paragraph_align=="left" ) { - imagestring($this->img,$this->font_family,$x,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); - } - elseif( $paragraph_align=="right" ) { - imagestring($this->img,$this->font_family,$x+($w-$w1), - $y-$h+1+$i*$fh,$tmp[$i],$this->current_color); - } - else { - imagestring($this->img,$this->font_family,$x+$w/2-$w1/2, - $y-$h+1+$i*$fh,$tmp[$i],$this->current_color); - } - } - } - else { - //Put the text - imagestring($this->img,$this->font_family,$x,$y-$h+1,$txt,$this->current_color); - } - if( $aDebug ) { - // Draw the bounding rectangle and the bounding box - $p1 = array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y)); - - // Draw bounding box - $this->PushColor('green'); - $this->Polygon($p1,true); - $this->PopColor(); - - } - $aBoundingBox=array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y)); - } - } - - function AddTxtCR($aTxt) { - // If the user has just specified a '\n' - // instead of '\n\t' we have to add '\r' since - // the width will be too muchy otherwise since when - // we print we stroke the individually lines by hand. - $e = explode("\n",$aTxt); - $n = count($e); - for($i=0; $i<$n; ++$i) { - $e[$i]=str_replace("\r","",$e[$i]); - } - return implode("\n\r",$e); - } - - function GetTTFBBox($aTxt,$aAngle=0) { - $bbox = @ImageTTFBBox($this->font_size,$aAngle,$this->font_file,$aTxt); - if( $bbox === false ) { - JpGraphError::RaiseL(25092,$this->font_file); -//("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."); - } - return $bbox; - } - - function GetBBoxTTF($aTxt,$aAngle=0) { - // Normalize the bounding box to become a minimum - // enscribing rectangle - - $aTxt = $this->AddTxtCR($aTxt); - - if( !is_readable($this->font_file) ) { - JpGraphError::RaiseL(25093,$this->font_file); -//('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.'); - } - $bbox = $this->GetTTFBBox($aTxt,$aAngle); - - if( $aAngle==0 ) - return $bbox; - if( $aAngle >= 0 ) { - if( $aAngle <= 90 ) { //<=0 - $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1], - $bbox[2],$bbox[5],$bbox[6],$bbox[5]); - } - elseif( $aAngle <= 180 ) { //<= 2 - $bbox = array($bbox[4],$bbox[7],$bbox[0],$bbox[7], - $bbox[0],$bbox[3],$bbox[4],$bbox[3]); - } - elseif( $aAngle <= 270 ) { //<= 3 - $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5], - $bbox[6],$bbox[1],$bbox[2],$bbox[1]); - } - else { - $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], - $bbox[4],$bbox[7],$bbox[0],$bbox[7]); - } - } - elseif( $aAngle < 0 ) { - if( $aAngle <= -270 ) { // <= -3 - $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1], - $bbox[2],$bbox[5],$bbox[6],$bbox[5]); - } - elseif( $aAngle <= -180 ) { // <= -2 - $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], - $bbox[4],$bbox[7],$bbox[0],$bbox[7]); - } - elseif( $aAngle <= -90 ) { // <= -1 - $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5], - $bbox[6],$bbox[1],$bbox[2],$bbox[1]); - } - else { - $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], - $bbox[4],$bbox[7],$bbox[0],$bbox[7]); - } - } - return $bbox; - } - - function GetBBoxHeight($aTxt,$aAngle=0) { - $box = $this->GetBBoxTTF($aTxt,$aAngle); - return $box[1]-$box[7]+1; - } - - function GetBBoxWidth($aTxt,$aAngle=0) { - $box = $this->GetBBoxTTF($aTxt,$aAngle); - return $box[2]-$box[0]+1; - } - - function _StrokeTTF($x,$y,$txt,$dir=0,$paragraph_align="left",&$aBoundingBox,$debug=false) { - - // Setupo default inter line margin for paragraphs to - // 25% of the font height. - $ConstLineSpacing = 0.25 ; - - // Remember the anchor point before adjustment - if( $debug ) { - $ox=$x; - $oy=$y; - } - - if( !ereg("\n",$txt) || ($dir>0 && ereg("\n",$txt)) ) { - // Format a single line - - $txt = $this->AddTxtCR($txt); - - $bbox=$this->GetBBoxTTF($txt,$dir); - - // Align x,y ot lower left corner of bbox - $x -= $bbox[0]; - $y -= $bbox[1]; - - // Note to self: "topanchor" is deprecated after we changed the - // bopunding box stuff. - if( $this->text_halign=="right" || $this->text_halign=="topanchor" ) - $x -= $bbox[2]-$bbox[0]; - elseif( $this->text_halign=="center" ) $x -= ($bbox[2]-$bbox[0])/2; - - if( $this->text_valign=="top" ) $y += abs($bbox[5])+$bbox[1]; - elseif( $this->text_valign=="center" ) $y -= ($bbox[5]-$bbox[1])/2; - - ImageTTFText ($this->img, $this->font_size, $dir, $x, $y, - $this->current_color,$this->font_file,$txt); - - // Calculate and return the co-ordinates for the bounding box - $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$txt); - $p1 = array(); - - - for($i=0; $i < 4; ++$i) { - $p1[] = round($box[$i*2]+$x); - $p1[] = round($box[$i*2+1]+$y); - } - $aBoundingBox = $p1; - - // Debugging code to highlight the bonding box and bounding rectangle - // For text at 0 degrees the bounding box and bounding rectangle are the - // same - if( $debug ) { - // Draw the bounding rectangle and the bounding box - $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$txt); - $p = array(); - $p1 = array(); - for($i=0; $i < 4; ++$i) { - $p[] = $bbox[$i*2]+$x; - $p[] = $bbox[$i*2+1]+$y; - $p1[] = $box[$i*2]+$x; - $p1[] = $box[$i*2+1]+$y; - } - - // Draw bounding box - $this->PushColor('green'); - $this->Polygon($p1,true); - $this->PopColor(); - - // Draw bounding rectangle - $this->PushColor('darkgreen'); - $this->Polygon($p,true); - $this->PopColor(); - - // Draw a cross at the anchor point - $this->PushColor('red'); - $this->Line($ox-15,$oy,$ox+15,$oy); - $this->Line($ox,$oy-15,$ox,$oy+15); - $this->PopColor(); - } - } - else { - // Format a text paragraph - $fh=$this->GetFontHeight(); - - // Line margin is 25% of font height - $linemargin=round($fh*$ConstLineSpacing); - $fh += $linemargin; - $w=$this->GetTextWidth($txt); - - $y -= $linemargin/2; - $tmp = split("\n",$txt); - $nl = count($tmp); - $h = $nl * $fh; - - if( $this->text_halign=="right") - $x -= $dir==0 ? $w : $h; - elseif( $this->text_halign=="center" ) { - $x -= $dir==0 ? $w/2 : $h/2; - } - - if( $this->text_valign=="top" ) - $y += $dir==0 ? $h : $w; - elseif( $this->text_valign=="center" ) - $y += $dir==0 ? $h/2 : $w/2; - - // Here comes a tricky bit. - // Since we have to give the position for the string at the - // baseline this means thaht text will move slightly up - // and down depending on any of it's character descend below - // the baseline, for example a 'g'. To adjust the Y-position - // we therefore adjust the text with the baseline Y-offset - // as used for the current font and size. This will keep the - // baseline at a fixed positoned disregarding the actual - // characters in the string. - $standardbox = $this->GetTTFBBox('Gg',$dir); - $yadj = $standardbox[1]; - $xadj = $standardbox[0]; - $aBoundingBox = array(); - for($i=0; $i < $nl; ++$i) { - $wl = $this->GetTextWidth($tmp[$i]); - $bbox = $this->GetTTFBBox($tmp[$i],$dir); - if( $paragraph_align=="left" ) { - $xl = $x; - } - elseif( $paragraph_align=="right" ) { - $xl = $x + ($w-$wl); - } - else { - // Center - $xl = $x + $w/2 - $wl/2 ; - } - - $xl -= $bbox[0]; - $yl = $y - $yadj; - $xl = $xl - $xadj; - ImageTTFText ($this->img, $this->font_size, $dir, - $xl, $yl-($h-$fh)+$fh*$i, - $this->current_color,$this->font_file,$tmp[$i]); - - if( $debug ) { - // Draw the bounding rectangle around each line - $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$tmp[$i]); - $p = array(); - for($j=0; $j < 4; ++$j) { - $p[] = $bbox[$j*2]+$xl; - $p[] = $bbox[$j*2+1]+$yl-($h-$fh)+$fh*$i; - } - - // Draw bounding rectangle - $this->PushColor('darkgreen'); - $this->Polygon($p,true); - $this->PopColor(); - } - } - - // Get the bounding box - $bbox = $this->GetBBoxTTF($txt,$dir); - for($j=0; $j < 4; ++$j) { - $bbox[$j*2]+= round($x); - $bbox[$j*2+1]+= round($y - ($h-$fh) - $yadj); - } - $aBoundingBox = $bbox; - - if( $debug ) { - // Draw a cross at the anchor point - $this->PushColor('red'); - $this->Line($ox-25,$oy,$ox+25,$oy); - $this->Line($ox,$oy-25,$ox,$oy+25); - $this->PopColor(); - } - - } - } - - function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) { - - $x = round($x); - $y = round($y); - - // Do special language encoding - $txt = $this->langconv->Convert($txt,$this->font_family); - - if( !is_numeric($dir) ) - JpGraphError::RaiseL(25094);//(" Direction for text most be given as an angle between 0 and 90."); - - if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) { - $this->_StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug); - } - elseif($this->font_family >= _FF_FIRST && $this->font_family <= _FF_LAST) { - $this->_StrokeTTF($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug); - } - else - JpGraphError::RaiseL(25095);//(" Unknown font font family specification. "); - return $boundingbox; - } - - function SetMargin($lm,$rm,$tm,$bm) { - $this->left_margin=$lm; - $this->right_margin=$rm; - $this->top_margin=$tm; - $this->bottom_margin=$bm; - $this->plotwidth=$this->width - $this->left_margin-$this->right_margin ; - $this->plotheight=$this->height - $this->top_margin-$this->bottom_margin ; - if( $this->width > 0 && $this->height > 0 ) { - if( $this->plotwidth < 0 || $this->plotheight < 0 ) - JpGraphError::raise("Too 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."); - } - } - - function SetTransparent($color) { - imagecolortransparent ($this->img,$this->rgb->allocate($color)); - } - - function SetColor($color,$aAlpha=0) { - $this->current_color_name = $color; - $this->current_color=$this->rgb->allocate($color,$aAlpha); - if( $this->current_color == -1 ) { - $tc=imagecolorstotal($this->img); - JpGraphError::RaiseL(25096); -//("Can't allocate any more colors. Image has already allocated maximum of $tc colors. 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."); - } - return $this->current_color; - } - - function PushColor($color) { - if( $color != "" ) { - $this->colorstack[$this->colorstackidx]=$this->current_color_name; - $this->colorstack[$this->colorstackidx+1]=$this->current_color; - $this->colorstackidx+=2; - $this->SetColor($color); - } - else { - JpGraphError::RaiseL(25097);//("Color specified as empty string in PushColor()."); - } - } - - function PopColor() { - if($this->colorstackidx<1) - JpGraphError::RaiseL(25098);//(" Negative Color stack index. Unmatched call to PopColor()"); - $this->current_color=$this->colorstack[--$this->colorstackidx]; - $this->current_color_name=$this->colorstack[--$this->colorstackidx]; - } - - - // Why this duplication? Because this way we can call this method - // for any image and not only the current objsct - function AdjSat($sat) { - if( $GLOBALS['gd2'] && USE_TRUECOLOR ) - return; - $this->_AdjSat($this->img,$sat); - } - - function _AdjSat($img,$sat) { - $nbr = imagecolorstotal ($img); - for( $i=0; $i<$nbr; ++$i ) { - $colarr = imagecolorsforindex ($img,$i); - $rgb[0]=$colarr["red"]; - $rgb[1]=$colarr["green"]; - $rgb[2]=$colarr["blue"]; - $rgb = $this->AdjRGBSat($rgb,$sat); - imagecolorset ($img, $i, $rgb[0], $rgb[1], $rgb[2]); - } - } - - function AdjBrightContrast($bright,$contr=0) { - if( $GLOBALS['gd2'] && USE_TRUECOLOR ) - return; - $this->_AdjBrightContrast($this->img,$bright,$contr); - } - - function _AdjBrightContrast($img,$bright,$contr=0) { - if( $bright < -1 || $bright > 1 || $contr < -1 || $contr > 1 ) - JpGraphError::RaiseL(25099);//(" Parameters for brightness and Contrast out of range [-1,1]"); - $nbr = imagecolorstotal ($img); - for( $i=0; $i<$nbr; ++$i ) { - $colarr = imagecolorsforindex ($img,$i); - $r = $this->AdjRGBBrightContrast($colarr["red"],$bright,$contr); - $g = $this->AdjRGBBrightContrast($colarr["green"],$bright,$contr); - $b = $this->AdjRGBBrightContrast($colarr["blue"],$bright,$contr); - imagecolorset ($img, $i, $r, $g, $b); - } - } - - // Private helper function for adj sat - // Adjust saturation for RGB array $u. $sat is a value between -1 and 1 - // Note: Due to GD inability to handle true color the RGB values are only between - // 8 bit. This makes saturation quite sensitive for small increases in parameter sat. - // - // Tip: To get a grayscale picture set sat=-100, values <-100 changes the colors - // to it's complement. - // - // Implementation note: The saturation is implemented directly in the RGB space - // by adjusting the perpendicular distance between the RGB point and the "grey" - // line (1,1,1). Setting $sat>0 moves the point away from the line along the perp. - // distance and a negative value moves the point closer to the line. - // The values are truncated when the color point hits the bounding box along the - // RGB axis. - // DISCLAIMER: I'm not 100% sure this is he correct way to implement a color - // saturation function in RGB space. However, it looks ok and has the expected effect. - function AdjRGBSat($rgb,$sat) { - // TODO: Should be moved to the RGB class - // Grey vector - $v=array(1,1,1); - - // Dot product - $dot = $rgb[0]*$v[0]+$rgb[1]*$v[1]+$rgb[2]*$v[2]; - - // Normalize dot product - $normdot = $dot/3; // dot/|v|^2 - - // Direction vector between $u and its projection onto $v - for($i=0; $i<3; ++$i) - $r[$i] = $rgb[$i] - $normdot*$v[$i]; - - // Adjustment factor so that sat==1 sets the highest RGB value to 255 - if( $sat > 0 ) { - $m=0; - for( $i=0; $i<3; ++$i) { - if( sign($r[$i]) == 1 && $r[$i]>0) - $m=max($m,(255-$rgb[$i])/$r[$i]); - } - $tadj=$m; - } - else - $tadj=1; - - $tadj = $tadj*$sat; - for($i=0; $i<3; ++$i) { - $un[$i] = round($rgb[$i] + $tadj*$r[$i]); - if( $un[$i]<0 ) $un[$i]=0; // Truncate color when they reach 0 - if( $un[$i]>255 ) $un[$i]=255;// Avoid potential rounding error - } - return $un; - } - - // Private helper function for AdjBrightContrast - function AdjRGBBrightContrast($rgb,$bright,$contr) { - // TODO: Should be moved to the RGB class - // First handle contrast, i.e change the dynamic range around grey - if( $contr <= 0 ) { - // Decrease contrast - $adj = abs($rgb-128) * (-$contr); - if( $rgb < 128 ) $rgb += $adj; - else $rgb -= $adj; - } - else { // $contr > 0 - // Increase contrast - if( $rgb < 128 ) $rgb = $rgb - ($rgb * $contr); - else $rgb = $rgb + ((255-$rgb) * $contr); - } - - // Add (or remove) various amount of white - $rgb += $bright*255; - $rgb=min($rgb,255); - $rgb=max($rgb,0); - return $rgb; - } - - function SetLineWeight($weight) { - $this->line_weight = $weight; - } - - function SetStartPoint($x,$y) { - $this->lastx=round($x); - $this->lasty=round($y); - } - - function Arc($cx,$cy,$w,$h,$s,$e) { - // GD Arc doesn't like negative angles - while( $s < 0) $s += 360; - while( $e < 0) $e += 360; - - imagearc($this->img,round($cx),round($cy),round($w),round($h), - $s,$e,$this->current_color); - } - - function FilledArc($xc,$yc,$w,$h,$s,$e,$style="") { - - if( $GLOBALS['gd2'] ) { - while( $s < 0 ) $s += 360; - while( $e < 0 ) $e += 360; - if( $style=="" ) - $style=IMG_ARC_PIE; - imagefilledarc($this->img,round($xc),round($yc),round($w),round($h), - round($s),round($e),$this->current_color,$style); - return; - } - - - // In GD 1.x we have to do it ourself interesting enough there is surprisingly - // little difference in time between doing it PHP and using the optimised GD - // library (roughly ~20%) I had expected it to be at least 100% slower doing it - // manually with a polygon approximation in PHP..... - $fillcolor = $this->current_color_name; - - $w /= 2; // We use radius in our calculations instead - $h /= 2; - - // Setup the angles so we have the same conventions as the builtin - // FilledArc() which is a little bit strange if you ask me.... - - $s = 360-$s; - $e = 360-$e; - - if( $e > $s ) { - $e = $e - 360; - $da = $s - $e; - } - $da = $s-$e; - - // We use radians - $s *= M_PI/180; - $e *= M_PI/180; - $da *= M_PI/180; - - // Calculate a polygon approximation - $p[0] = $xc; - $p[1] = $yc; - - // Heuristic on how many polygons we need to make the - // arc look good - $numsteps = round(8 * abs($da) * ($w+$h)*($w+$h)/1500); - - if( $numsteps == 0 ) return; - if( $numsteps < 7 ) $numsteps=7; - $delta = abs($da)/$numsteps; - - $pa=array(); - $a = $s; - for($i=1; $i<=$numsteps; ++$i ) { - $p[2*$i] = round($xc + $w*cos($a)); - $p[2*$i+1] = round($yc - $h*sin($a)); - //$a = $s + $i*$delta; - $a -= $delta; - $pa[2*($i-1)] = $p[2*$i]; - $pa[2*($i-1)+1] = $p[2*$i+1]; - } - - // Get the last point at the exact ending angle to avoid - // any rounding errors. - $p[2*$i] = round($xc + $w*cos($e)); - $p[2*$i+1] = round($yc - $h*sin($e)); - $pa[2*($i-1)] = $p[2*$i]; - $pa[2*($i-1)+1] = $p[2*$i+1]; - $i++; - - $p[2*$i] = $xc; - $p[2*$i+1] = $yc; - if( $fillcolor != "" ) { - $this->PushColor($fillcolor); - imagefilledpolygon($this->img,$p,count($p)/2,$this->current_color); - $this->PopColor(); - } - } - - function FilledCakeSlice($cx,$cy,$w,$h,$s,$e) { - $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name); - } - - function CakeSlice($xc,$yc,$w,$h,$s,$e,$fillcolor="",$arccolor="") { - $s = round($s); $e = round($e); - $w = round($w); $h = round($h); - $xc = round($xc); $yc = round($yc); - $this->PushColor($fillcolor); - $this->FilledArc($xc,$yc,2*$w,2*$h,$s,$e); - $this->PopColor(); - if( $arccolor != "" ) { - $this->PushColor($arccolor); - // We add 2 pixels to make the Arc() better aligned with the filled arc. - if( $GLOBALS['gd2'] ) { - imagefilledarc($this->img,$xc,$yc,2*$w,2*$h,$s,$e,$this->current_color,IMG_ARC_NOFILL | IMG_ARC_EDGED ) ; - } - else { - $this->Arc($xc,$yc,2*$w+2,2*$h+2,$s,$e); - $xx = $w * cos(2*M_PI - $s*M_PI/180) + $xc; - $yy = $yc - $h * sin(2*M_PI - $s*M_PI/180); - $this->Line($xc,$yc,$xx,$yy); - $xx = $w * cos(2*M_PI - $e*M_PI/180) + $xc; - $yy = $yc - $h * sin(2*M_PI - $e*M_PI/180); - $this->Line($xc,$yc,$xx,$yy); - } - $this->PopColor(); - } - } - - function Ellipse($xc,$yc,$w,$h) { - $this->Arc($xc,$yc,$w,$h,0,360); - } - - // Breseham circle gives visually better result then using GD - // built in arc(). It takes some more time but gives better - // accuracy. - function BresenhamCircle($xc,$yc,$r) { - $d = 3-2*$r; - $x = 0; - $y = $r; - while($x<=$y) { - $this->Point($xc+$x,$yc+$y); - $this->Point($xc+$x,$yc-$y); - $this->Point($xc-$x,$yc+$y); - $this->Point($xc-$x,$yc-$y); - - $this->Point($xc+$y,$yc+$x); - $this->Point($xc+$y,$yc-$x); - $this->Point($xc-$y,$yc+$x); - $this->Point($xc-$y,$yc-$x); - - if( $d<0 ) $d += 4*$x+6; - else { - $d += 4*($x-$y)+10; - --$y; - } - ++$x; - } - } - - function Circle($xc,$yc,$r) { - if( USE_BRESENHAM ) - $this->BresenhamCircle($xc,$yc,$r); - else { - - /* - // Some experimental code snippet to see if we can get a decent - // result doing a trig-circle - // Create an approximated circle with 0.05 rad resolution - $end = 2*M_PI; - $l = $r/10; - if( $l < 3 ) $l=3; - $step_size = 2*M_PI/(2*$r*M_PI/$l); - $pts = array(); - $pts[] = $r + $xc; - $pts[] = $yc; - for( $a=$step_size; $a <= $end; $a += $step_size ) { - $pts[] = round($xc + $r*cos($a)); - $pts[] = round($yc - $r*sin($a)); - } - imagepolygon($this->img,$pts,count($pts)/2,$this->current_color); - */ - - $this->Arc($xc,$yc,$r*2,$r*2,0,360); - - // For some reason imageellipse() isn't in GD 2.0.1, PHP 4.1.1 - //imageellipse($this->img,$xc,$yc,$r,$r,$this->current_color); - } - } - - function FilledCircle($xc,$yc,$r) { - if( $GLOBALS['gd2'] ) { - imagefilledellipse($this->img,round($xc),round($yc), - 2*$r,2*$r,$this->current_color); - } - else { - for( $i=1; $i < 2*$r; $i += 2 ) { - // To avoid moire patterns we have to draw some - // 1 extra "skewed" filled circles - $this->Arc($xc,$yc,$i,$i,0,360); - $this->Arc($xc,$yc,$i+1,$i,0,360); - $this->Arc($xc,$yc,$i+1,$i+1,0,360); - } - } - } - - // Linear Color InterPolation - function lip($f,$t,$p) { - $p = round($p,1); - $r = $f[0] + ($t[0]-$f[0])*$p; - $g = $f[1] + ($t[1]-$f[1])*$p; - $b = $f[2] + ($t[2]-$f[2])*$p; - return array($r,$g,$b); - } - - // Anti-aliased line. - // Note that this is roughly 8 times slower then a normal line! - function WuLine($x1,$y1,$x2,$y2) { - // Get foreground line color - $lc = imagecolorsforindex($this->img,$this->current_color); - $lc = array($lc["red"],$lc["green"],$lc["blue"]); - - $dx = $x2-$x1; - $dy = $y2-$y1; - - if( abs($dx) > abs($dy) ) { - if( $dx<0 ) { - $dx = -$dx;$dy = -$dy; - $tmp=$x2;$x2=$x1;$x1=$tmp; - $tmp=$y2;$y2=$y1;$y1=$tmp; - } - $x=$x1<<16; $y=$y1<<16; - $yinc = ($dy*65535)/$dx; - while( ($x >> 16) < $x2 ) { - - $bc = @imagecolorsforindex($this->img,imagecolorat($this->img,$x>>16,$y>>16)); - if( $bc <= 0 ) { - JpGraphError::RaiseL(25100);//('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 that truecolor is enabled.'); - } - $bc=array($bc["red"],$bc["green"],$bc["blue"]); - - $this->SetColor($this->lip($lc,$bc,($y & 0xFFFF)/65535)); - imagesetpixel($this->img,$x>>16,$y>>16,$this->current_color); - $this->SetColor($this->lip($lc,$bc,(~$y & 0xFFFF)/65535)); - imagesetpixel($this->img,$x>>16,($y>>16)+1,$this->current_color); - $x += 65536; $y += $yinc; - } - } - else { - if( $dy<0 ) { - $dx = -$dx;$dy = -$dy; - $tmp=$x2;$x2=$x1;$x1=$tmp; - $tmp=$y2;$y2=$y1;$y1=$tmp; - } - $x=$x1<<16; $y=$y1<<16; - $xinc = ($dx*65535)/$dy; - while( ($y >> 16) < $y2 ) { - - $bc = @imagecolorsforindex($this->img,imagecolorat($this->img,$x>>16,$y>>16)); - if( $bc <= 0 ) { - JpGraphError::RaiseL(25100);//('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.'); - - } - - $bc=array($bc["red"],$bc["green"],$bc["blue"]); - - $this->SetColor($this->lip($lc,$bc,($x & 0xFFFF)/65535)); - imagesetpixel($this->img,$x>>16,$y>>16,$this->current_color); - $this->SetColor($this->lip($lc,$bc,(~$x & 0xFFFF)/65535)); - imagesetpixel($this->img,($x>>16)+1,$y>>16,$this->current_color); - $y += 65536; $x += $xinc; - } - } - $this->SetColor($lc); - imagesetpixel($this->img,$x2,$y2,$this->current_color); - imagesetpixel($this->img,$x1,$y1,$this->current_color); - } - - // Set line style dashed, dotted etc - function SetLineStyle($s) { - if( is_numeric($s) ) { - if( $s<1 || $s>4 ) - JpGraphError::RaiseL(25101,$s);//(" Illegal numeric argument to SetLineStyle(): ($s)"); - } - elseif( is_string($s) ) { - if( $s == "solid" ) $s=1; - elseif( $s == "dotted" ) $s=2; - elseif( $s == "dashed" ) $s=3; - elseif( $s == "longdashed" ) $s=4; - else JpGraphError::RaiseL(25102,$s);//(" Illegal string argument to SetLineStyle(): $s"); - } - else JpGraphError::RaiseL(25103,$s);//(" Illegal argument to SetLineStyle $s"); - $this->line_style=$s; - } - - // Same as Line but take the line_style into account - function StyleLine($x1,$y1,$x2,$y2) { - switch( $this->line_style ) { - case 1:// Solid - $this->Line($x1,$y1,$x2,$y2); - break; - case 2: // Dotted - $this->DashedLine($x1,$y1,$x2,$y2,1,6); - break; - case 3: // Dashed - $this->DashedLine($x1,$y1,$x2,$y2,2,4); - break; - case 4: // Longdashes - $this->DashedLine($x1,$y1,$x2,$y2,8,6); - break; - default: - JpGraphError::RaiseL(25104,$this->line_style);//(" Unknown line style: $this->line_style "); - break; - } - } - - function Line($x1,$y1,$x2,$y2) { - - $x1 = round($x1); - $x2 = round($x2); - $y1 = round($y1); - $y2 = round($y2); - - if( $this->line_weight==0 ) return; - if( $this->use_anti_aliasing ) { - $dx = $x2-$x1; - $dy = $y2-$y1; - // Vertical, Horizontal or 45 lines don't need anti-aliasing - if( $dx!=0 && $dy!=0 && $dx!=$dy ) { - $this->WuLine($x1,$y1,$x2,$y2); - return; - } - } - if( $this->line_weight==1 ) { - imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); - } - elseif( $x1==$x2 ) { // Special case for vertical lines - imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); - $w1=floor($this->line_weight/2); - $w2=floor(($this->line_weight-1)/2); - for($i=1; $i<=$w1; ++$i) - imageline($this->img,$x1+$i,$y1,$x2+$i,$y2,$this->current_color); - for($i=1; $i<=$w2; ++$i) - imageline($this->img,$x1-$i,$y1,$x2-$i,$y2,$this->current_color); - } - elseif( $y1==$y2 ) { // Special case for horizontal lines - imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); - $w1=floor($this->line_weight/2); - $w2=floor(($this->line_weight-1)/2); - for($i=1; $i<=$w1; ++$i) - imageline($this->img,$x1,$y1+$i,$x2,$y2+$i,$this->current_color); - for($i=1; $i<=$w2; ++$i) - imageline($this->img,$x1,$y1-$i,$x2,$y2-$i,$this->current_color); - } - else { // General case with a line at an angle - $a = atan2($y1-$y2,$x2-$x1); - // Now establish some offsets from the center. This gets a little - // bit involved since we are dealing with integer functions and we - // want the apperance to be as smooth as possible and never be thicker - // then the specified width. - - // We do the trig stuff to make sure that the endpoints of the line - // are perpendicular to the line itself. - $dx=(sin($a)*$this->line_weight/2); - $dy=(cos($a)*$this->line_weight/2); - - $pnts = array($x2+$dx,$y2+$dy,$x2-$dx,$y2-$dy,$x1-$dx,$y1-$dy,$x1+$dx,$y1+$dy); - imagefilledpolygon($this->img,$pnts,count($pnts)/2,$this->current_color); - } - $this->lastx=$x2; $this->lasty=$y2; - } - - function Polygon($p,$closed=FALSE,$fast=FALSE) { - if( $this->line_weight==0 ) return; - $n=count($p); - $oldx = $p[0]; - $oldy = $p[1]; - if( $fast ) { - for( $i=2; $i < $n; $i+=2 ) { - imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->current_color); - $oldx = $p[$i]; - $oldy = $p[$i+1]; - } - if( $closed ) { - imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->current_color); - } - } - else { - for( $i=2; $i < $n; $i+=2 ) { - $this->StyleLine($oldx,$oldy,$p[$i],$p[$i+1]); - $oldx = $p[$i]; - $oldy = $p[$i+1]; - } - } - if( $closed ) - $this->Line($oldx,$oldy,$p[0],$p[1]); - } - - function FilledPolygon($pts) { - $n=count($pts); - if( $n == 0 ) { - JpGraphError::RaiseL(25105);//('NULL data specified for a filled polygon. Check that your data is not NULL.'); - } - for($i=0; $i < $n; ++$i) - $pts[$i] = round($pts[$i]); - imagefilledpolygon($this->img,$pts,count($pts)/2,$this->current_color); - } - - function Rectangle($xl,$yu,$xr,$yl) { - $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu)); - } - - function FilledRectangle($xl,$yu,$xr,$yl) { - $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl)); - } - - function FilledRectangle2($xl,$yu,$xr,$yl,$color1,$color2,$style=1) { - // Fill a rectangle with lines of two colors - if( $style===1 ) { - // Horizontal stripe - if( $yl < $yu ) { - $t = $yl; $yl=$yu; $yu=$t; - } - for( $y=$yu; $y <= $yl; ++$y) { - $this->SetColor($color1); - $this->Line($xl,$y,$xr,$y); - ++$y; - $this->SetColor($color2); - $this->Line($xl,$y,$xr,$y); - } - } - else { - if( $xl < $xl ) { - $t = $xl; $xl=$xr; $xr=$t; - } - for( $x=$xl; $x <= $xr; ++$x) { - $this->SetColor($color1); - $this->Line($x,$yu,$x,$yl); - ++$x; - $this->SetColor($color2); - $this->Line($x,$yu,$x,$yl); - } - } - } - - function ShadowRectangle($xl,$yu,$xr,$yl,$fcolor=false,$shadow_width=3,$shadow_color=array(102,102,102)) { - // This is complicated by the fact that we must also handle the case where - // the reactangle has no fill color - $this->PushColor($shadow_color); - $this->FilledRectangle($xr-$shadow_width,$yu+$shadow_width,$xr,$yl-$shadow_width-1); - $this->FilledRectangle($xl+$shadow_width,$yl-$shadow_width,$xr,$yl); - //$this->FilledRectangle($xl+$shadow_width,$yu+$shadow_width,$xr,$yl); - $this->PopColor(); - if( $fcolor==false ) - $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); - else { - $this->PushColor($fcolor); - $this->FilledRectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); - $this->PopColor(); - $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); - } - } - - function FilledRoundedRectangle($xt,$yt,$xr,$yl,$r=5) { - if( $r==0 ) { - $this->FilledRectangle($xt,$yt,$xr,$yl); - return; - } - - // To avoid overlapping fillings (which will look strange - // when alphablending is enabled) we have no choice but - // to fill the five distinct areas one by one. - - // Center square - $this->FilledRectangle($xt+$r,$yt+$r,$xr-$r,$yl-$r); - // Top band - $this->FilledRectangle($xt+$r,$yt,$xr-$r,$yt+$r-1); - // Bottom band - $this->FilledRectangle($xt+$r,$yl-$r+1,$xr-$r,$yl); - // Left band - $this->FilledRectangle($xt,$yt+$r+1,$xt+$r-1,$yl-$r); - // Right band - $this->FilledRectangle($xr-$r+1,$yt+$r,$xr,$yl-$r); - - // Topleft & Topright arc - $this->FilledArc($xt+$r,$yt+$r,$r*2,$r*2,180,270); - $this->FilledArc($xr-$r,$yt+$r,$r*2,$r*2,270,360); - - // Bottomleft & Bottom right arc - $this->FilledArc($xt+$r,$yl-$r,$r*2,$r*2,90,180); - $this->FilledArc($xr-$r,$yl-$r,$r*2,$r*2,0,90); - - } - - function RoundedRectangle($xt,$yt,$xr,$yl,$r=5) { - - if( $r==0 ) { - $this->Rectangle($xt,$yt,$xr,$yl); - return; - } - - // Top & Bottom line - $this->Line($xt+$r,$yt,$xr-$r,$yt); - $this->Line($xt+$r,$yl,$xr-$r,$yl); - - // Left & Right line - $this->Line($xt,$yt+$r,$xt,$yl-$r); - $this->Line($xr,$yt+$r,$xr,$yl-$r); - - // Topleft & Topright arc - $this->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); - $this->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); - - // Bottomleft & Bottomright arc - $this->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); - $this->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); - } - - function FilledBevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='darkgray@0.4') { - $this->FilledRectangle($x1,$y1,$x2,$y2); - $this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2); - } - - function Bevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='black@0.5') { - $this->PushColor($color1); - for( $i=0; $i < $depth; ++$i ) { - $this->Line($x1+$i,$y1+$i,$x1+$i,$y2-$i); - $this->Line($x1+$i,$y1+$i,$x2-$i,$y1+$i); - } - $this->PopColor(); - - $this->PushColor($color2); - for( $i=0; $i < $depth; ++$i ) { - $this->Line($x1+$i,$y2-$i,$x2-$i,$y2-$i); - $this->Line($x2-$i,$y1+$i,$x2-$i,$y2-$i-1); - } - $this->PopColor(); - } - - function StyleLineTo($x,$y) { - $this->StyleLine($this->lastx,$this->lasty,$x,$y); - $this->lastx=$x; - $this->lasty=$y; - } - - function LineTo($x,$y) { - $this->Line($this->lastx,$this->lasty,$x,$y); - $this->lastx=$x; - $this->lasty=$y; - } - - function Point($x,$y) { - imagesetpixel($this->img,round($x),round($y),$this->current_color); - } - - function Fill($x,$y) { - imagefill($this->img,round($x),round($y),$this->current_color); - } - - function FillToBorder($x,$y,$aBordColor) { - $bc = $this->rgb->allocate($aBordColor); - if( $bc == -1 ) { - JpGraphError::RaiseL(25106);//('Image::FillToBorder : Can not allocate more colors'); - exit(); - } - imagefilltoborder($this->img,round($x),round($y),$bc,$this->current_color); - } - - function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) { - - $x1 = round($x1); - $x2 = round($x2); - $y1 = round($y1); - $y2 = round($y2); - - // Code based on, but not identical to, work by Ariel Garza and James Pine - $line_length = ceil (sqrt(pow(($x2 - $x1),2) + pow(($y2 - $y1),2)) ); - $dx = ($line_length) ? ($x2 - $x1) / $line_length : 0; - $dy = ($line_length) ? ($y2 - $y1) / $line_length : 0; - $lastx = $x1; $lasty = $y1; - $xmax = max($x1,$x2); - $xmin = min($x1,$x2); - $ymax = max($y1,$y2); - $ymin = min($y1,$y2); - for ($i = 0; $i < $line_length; $i += ($dash_length + $dash_space)) { - $x = ($dash_length * $dx) + $lastx; - $y = ($dash_length * $dy) + $lasty; - - // The last section might overshoot so we must take a computational hit - // and check this. - if( $x>$xmax ) $x=$xmax; - if( $y>$ymax ) $y=$ymax; - - if( $x<$xmin ) $x=$xmin; - if( $y<$ymin ) $y=$ymin; - - $this->Line($lastx,$lasty,$x,$y); - $lastx = $x + ($dash_space * $dx); - $lasty = $y + ($dash_space * $dy); - } - } - - function SetExpired($aFlg=true) { - $this->expired = $aFlg; - } - - // Generate image header - function Headers() { - - // In case we are running from the command line with the client version of - // PHP we can't send any headers. - $sapi = php_sapi_name(); - if( $sapi == 'cli' ) - return; - - if( headers_sent($file,$lineno) ) { - $file=basename($file); - $t = new ErrMsgText(); - $msg = $t->Get(10,$file,$lineno); - die($msg); - } - - if ($this->expired) { - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT"); - header("Cache-Control: no-cache, must-revalidate"); - header("Pragma: no-cache"); - } - header("Content-type: image/$this->img_format"); - } - - // Adjust image quality for formats that allow this - function SetQuality($q) { - $this->quality = $q; - } - - // Stream image to browser or to file - function Stream($aFile="") { - $func="image".$this->img_format; - if( $this->img_format=="jpeg" && $this->quality != null ) { - $res = @$func($this->img,$aFile,$this->quality); - } - else { - if( $aFile != "" ) { - $res = @$func($this->img,$aFile); - if( !$res ) - JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission."); - } - else { - $res = @$func($this->img); - if( !$res ) - 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."); - - } - } - } - - // Clear resource tide up by image - function Destroy() { - imagedestroy($this->img); - } - - // Specify image format. Note depending on your installation - // of PHP not all formats may be supported. - function SetImgFormat($aFormat,$aQuality=75) { - $this->quality = $aQuality; - $aFormat = strtolower($aFormat); - $tst = true; - $supported = imagetypes(); - if( $aFormat=="auto" ) { - if( $supported & IMG_PNG ) - $this->img_format="png"; - elseif( $supported & IMG_JPG ) - $this->img_format="jpeg"; - elseif( $supported & IMG_GIF ) - $this->img_format="gif"; - else - 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."); - - return true; - } - else { - if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) { - if( $aFormat=="jpeg" && !($supported & IMG_JPG) ) - $tst=false; - elseif( $aFormat=="png" && !($supported & IMG_PNG) ) - $tst=false; - elseif( $aFormat=="gif" && !($supported & IMG_GIF) ) - $tst=false; - else { - $this->img_format=$aFormat; - return true; - } - } - else - $tst=false; - if( !$tst ) - JpGraphError::RaiseL(25110,$aFormat);//(" Your PHP installation does not support the chosen graphic format: $aFormat"); - } - } -} // CLASS - -//=================================================== -// CLASS RotImage -// Description: Exactly as Image but draws the image at -// a specified angle around a specified rotation point. -//=================================================== -class RotImage extends Image { - var $m=array(); - var $a=0; - var $dx=0,$dy=0,$transx=0,$transy=0; - - function __construct($aWidth,$aHeight,$a=0,$aFormat=DEFAULT_GFORMAT) { - parent::__construct($aWidth,$aHeight,$aFormat); - $this->dx=$this->left_margin+$this->plotwidth/2; - $this->dy=$this->top_margin+$this->plotheight/2; - $this->SetAngle($a); - } - - function SetCenter($dx,$dy) { - $old_dx = $this->dx; - $old_dy = $this->dy; - $this->dx=$dx; - $this->dy=$dy; - $this->SetAngle($this->a); - return array($old_dx,$old_dy); - } - - function SetTranslation($dx,$dy) { - $old = array($this->transx,$this->transy); - $this->transx = $dx; - $this->transy = $dy; - return $old; - } - - function UpdateRotMatrice() { - $a = $this->a; - $a *= M_PI/180; - $sa=sin($a); $ca=cos($a); - // Create the rotation matrix - $this->m[0][0] = $ca; - $this->m[0][1] = -$sa; - $this->m[0][2] = $this->dx*(1-$ca) + $sa*$this->dy ; - $this->m[1][0] = $sa; - $this->m[1][1] = $ca; - $this->m[1][2] = $this->dy*(1-$ca) - $sa*$this->dx ; - } - - function SetAngle($a) { - $tmp = $this->a; - $this->a = $a; - $this->UpdateRotMatrice(); - return $tmp; - } - - function Circle($xc,$yc,$r) { - // Circle get's rotated through the Arc() call - // made in the parent class - parent::Circle($xc,$yc,$r); - } - - function FilledCircle($xc,$yc,$r) { - // If we use GD1 then Image::FilledCircle will use a - // call to Arc so it will get rotated through the Arc - // call. - if( $GLOBALS['gd2'] ) { - list($xc,$yc) = $this->Rotate($xc,$yc); - } - parent::FilledCircle($xc,$yc,$r); - } - - function Arc($xc,$yc,$w,$h,$s,$e) { - list($xc,$yc) = $this->Rotate($xc,$yc); - $s += $this->a; - $e += $this->a; - parent::Arc($xc,$yc,$w,$h,$s,$e); - } - - function FilledArc($xc,$yc,$w,$h,$s,$e, $style='') { - list($xc,$yc) = $this->Rotate($xc,$yc); - $s += $this->a; - $e += $this->a; - parent::FilledArc($xc,$yc,$w,$h,$s,$e); - } - - function SetMargin($lm,$rm,$tm,$bm) { - parent::SetMargin($lm,$rm,$tm,$bm); - $this->dx=$this->left_margin+$this->plotwidth/2; - $this->dy=$this->top_margin+$this->plotheight/2; - $this->UpdateRotMatrice(); - } - - function Rotate($x,$y) { - // Optimization. Ignore rotation if Angle==0 || ANgle==360 - if( $this->a == 0 || $this->a == 360 ) { - return array($x + $this->transx, $y + $this->transy ); - } - else { - $x1=round($this->m[0][0]*$x + $this->m[0][1]*$y,1) + $this->m[0][2] + $this->transx; - $y1=round($this->m[1][0]*$x + $this->m[1][1]*$y,1) + $this->m[1][2] + $this->transy; - return array($x1,$y1); - } - } - - function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) { - list($toX,$toY) = $this->Rotate($toX,$toY); - parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix); - - } - - function ArrRotate($pnts) { - $n = count($pnts)-1; - for($i=0; $i < $n; $i+=2) { - list ($x,$y) = $this->Rotate($pnts[$i],$pnts[$i+1]); - $pnts[$i] = $x; $pnts[$i+1] = $y; - } - return $pnts; - } - - function Line($x1,$y1,$x2,$y2) { - list($x1,$y1) = $this->Rotate($x1,$y1); - list($x2,$y2) = $this->Rotate($x2,$y2); - parent::Line($x1,$y1,$x2,$y2); - } - - function Rectangle($x1,$y1,$x2,$y2) { - // Rectangle uses Line() so it will be rotated through that call - parent::Rectangle($x1,$y1,$x2,$y2); - } - - function FilledRectangle($x1,$y1,$x2,$y2) { - if( $y1==$y2 || $x1==$x2 ) - $this->Line($x1,$y1,$x2,$y2); - else - $this->FilledPolygon(array($x1,$y1,$x2,$y1,$x2,$y2,$x1,$y2)); - } - - function Polygon($pnts,$closed=FALSE,$fast=false) { - //Polygon uses Line() so it will be rotated through that call - parent::Polygon($pnts,$closed,$fast); - } - - function FilledPolygon($pnts) { - parent::FilledPolygon($this->ArrRotate($pnts)); - } - - function Point($x,$y) { - list($xp,$yp) = $this->Rotate($x,$y); - parent::Point($xp,$yp); - } - - function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) { - list($xp,$yp) = $this->Rotate($x,$y); - return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug); - } -} - -//=================================================== -// CLASS ImgStreamCache -// Description: Handle caching of graphs to files -//=================================================== -class ImgStreamCache { - var $cache_dir; - var $img=null; - var $timeout=0; // Infinite timeout - //--------------- - // CONSTRUCTOR - function __construct(&$aImg, $aCacheDir=CACHE_DIR) { - $this->img = &$aImg; - $this->cache_dir = $aCacheDir; - } - -//--------------- -// PUBLIC METHODS - - // Specify a timeout (in minutes) for the file. If the file is older then the - // timeout value it will be overwritten with a newer version. - // If timeout is set to 0 this is the same as infinite large timeout and if - // timeout is set to -1 this is the same as infinite small timeout - function SetTimeout($aTimeout) { - $this->timeout=$aTimeout; - } - - // Output image to browser and also write it to the cache - function PutAndStream(&$aImage,$aCacheFileName,$aInline,$aStrokeFileName) { - // Some debugging code to brand the image with numbe of colors - // used - GLOBAL $gJpgBrandTiming; - - if( $gJpgBrandTiming ) { - global $tim; - $t=$tim->Pop()/1000.0; - $c=$aImage->SetColor("black"); - $t=sprintf(BRAND_TIME_FORMAT,round($t,3)); - imagestring($this->img->img,2,5,$this->img->height-20,$t,$c); - } - - // Check if we should stroke the image to an arbitrary file - if( _FORCE_IMGTOFILE ) { - $aStrokeFileName = _FORCE_IMGDIR.GenImgName(); - } - - if( $aStrokeFileName!="" ) { - if( $aStrokeFileName == "auto" ) - $aStrokeFileName = GenImgName(); - if( file_exists($aStrokeFileName) ) { - // Delete the old file - if( !@unlink($aStrokeFileName) ) - JpGraphError::RaiseL(25111,$aStrokeFileName);//(" Can't delete cached image $aStrokeFileName. Permission problem?"); - } - $aImage->Stream($aStrokeFileName); - return; - } - - if( $aCacheFileName != "" && USE_CACHE) { - - $aCacheFileName = $this->cache_dir . $aCacheFileName; - if( file_exists($aCacheFileName) ) { - if( !$aInline ) { - // If we are generating image off-line (just writing to the cache) - // and the file exists and is still valid (no timeout) - // then do nothing, just return. - $diff=time()-filemtime($aCacheFileName); - if( $diff < 0 ) - JpGraphError::RaiseL(25112,$aCacheFileName);//(" Cached imagefile ($aCacheFileName) has file date in the future!!"); - if( $this->timeout>0 && ($diff <= $this->timeout*60) ) - return; - } - if( !@unlink($aCacheFileName) ) - JpGraphError::RaiseL(25113,$aStrokeFileName);//(" Can't delete cached image $aStrokeFileName. Permission problem?"); - $aImage->Stream($aCacheFileName); - } - else { - $this->MakeDirs(dirname($aCacheFileName)); - if( !is_writeable(dirname($aCacheFileName)) ) { - 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.'); - } - $aImage->Stream($aCacheFileName); - } - - $res=true; - // Set group to specified - if( CACHE_FILE_GROUP != "" ) - $res = @chgrp($aCacheFileName,CACHE_FILE_GROUP); - if( CACHE_FILE_MOD != "" ) - $res = @chmod($aCacheFileName,CACHE_FILE_MOD); - if( !$res ) - JpGraphError::RaiseL(25115,$aStrokeFileName);//(" Can't set permission for cached image $aStrokeFileName. Permission problem?"); - - $aImage->Destroy(); - if( $aInline ) { - if ($fh = @fopen($aCacheFileName, "rb") ) { - $this->img->Headers(); - fpassthru($fh); - return; - } - else - JpGraphError::RaiseL(25116,$aFile);//(" Cant open file from cache [$aFile]"); - } - } - elseif( $aInline ) { - $this->img->Headers(); - $aImage->Stream(); - return; - } - } - - // Check if a given image is in cache and in that case - // pass it directly on to web browser. Return false if the - // image file doesn't exist or exists but is to old - function GetAndStream($aCacheFileName) { - $aCacheFileName = $this->cache_dir.$aCacheFileName; - if ( USE_CACHE && file_exists($aCacheFileName) && $this->timeout>=0 ) { - $diff=time()-filemtime($aCacheFileName); - if( $this->timeout>0 && ($diff > $this->timeout*60) ) { - return false; - } - else { - if ($fh = @fopen($aCacheFileName, "rb")) { - $this->img->Headers(); - fpassthru($fh); - return true; - } - else - JpGraphError::RaiseL(25117,$aCacheFileName);//(" Can't open cached image \"$aCacheFileName\" for reading."); - } - } - return false; - } - - //--------------- - // PRIVATE METHODS - // Create all necessary directories in a path - function MakeDirs($aFile) { - $dirs = array(); - while ( !(file_exists($aFile)) ) { - $dirs[] = $aFile; - $aFile = dirname($aFile); - } - for ($i = sizeof($dirs)-1; $i>=0; $i--) { - if(! @mkdir($dirs[$i],0777) ) - JpGraphError::RaiseL(25118,$aFile);//(" Can't create directory $aFile. Make sure PHP has write permission to this directory."); - // We also specify mode here after we have changed group. - // This is necessary if Apache user doesn't belong the - // default group and hence can't specify group permission - // in the previous mkdir() call - if( CACHE_FILE_GROUP != "" ) { - $res=true; - $res =@chgrp($dirs[$i],CACHE_FILE_GROUP); - $res &= @chmod($dirs[$i],0777); - if( !$res ) - JpGraphError::RaiseL(25119,$aFile);//(" Can't set permissions for $aFile. Permission problems?"); - } - } - return true; - } -} // CLASS Cache - -//=================================================== -// CLASS Legend -// Description: Responsible for drawing the box containing -// all the legend text for the graph -//=================================================== -DEFINE('_DEFAULT_LPM_SIZE',8); -class Legend { - var $color=array(0,0,0); // Default fram color - var $fill_color=array(235,235,235); // Default fill color - var $shadow=true; // Shadow around legend "box" - var $shadow_color='gray'; - var $txtcol=array(); - var $mark_abs_hsize=_DEFAULT_LPM_SIZE, $mark_abs_vsize=_DEFAULT_LPM_SIZE; - var $xmargin=5,$ymargin=3,$shadow_width=2; - var $xlmargin=2, $ylmargin=''; - var $xpos=0.05, $ypos=0.15, $xabspos=-1, $yabspos=-1; - var $halign="right", $valign="top"; - var $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12; - var $font_color='black'; - var $hide=false,$layout_n=1; - var $weight=1,$frameweight=1; - var $csimareas=''; - var $reverse = false ; -//--------------- -// CONSTRUCTOR - function __construct() { - // Empty - } -//--------------- -// PUBLIC METHODS - function Hide($aHide=true) { - $this->hide=$aHide; - } - - function SetHColMargin($aXMarg) { - $this->xmargin = $aXMarg; - } - - function SetVColMargin($aSpacing) { - $this->ymargin = $aSpacing ; - } - - function SetLeftMargin($aXMarg) { - $this->xlmargin = $aXMarg; - } - - // Synonym - function SetLineSpacing($aSpacing) { - $this->ymargin = $aSpacing ; - } - - function SetShadow($aShow='gray',$aWidth=2) { - if( is_string($aShow) ) { - $this->shadow_color = $aShow; - $this->shadow=true; - } - else - $this->shadow=$aShow; - $this->shadow_width=$aWidth; - } - - function SetMarkAbsSize($aSize) { - $this->mark_abs_vsize = $aSize ; - $this->mark_abs_hsize = $aSize ; - } - - function SetMarkAbsVSize($aSize) { - $this->mark_abs_vsize = $aSize ; - } - - function SetMarkAbsHSize($aSize) { - $this->mark_abs_hsize = $aSize ; - } - - function SetLineWeight($aWeight) { - $this->weight = $aWeight; - } - - function SetFrameWeight($aWeight) { - $this->frameweight = $aWeight; - } - - function SetLayout($aDirection=LEGEND_VERT) { - $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ; - } - - function SetColumns($aCols) { - $this->layout_n = $aCols ; - } - - function SetReverse($f=true) { - $this->reverse = $f ; - } - - // Set color on frame around box - function SetColor($aFontColor,$aColor='black') { - $this->font_color=$aFontColor; - $this->color=$aColor; - } - - function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { - $this->font_family = $aFamily; - $this->font_style = $aStyle; - $this->font_size = $aSize; - } - - function SetPos($aX,$aY,$aHAlign="right",$aVAlign="top") { - $this->Pos($aX,$aY,$aHAlign,$aVAlign); - } - - function SetAbsPos($aX,$aY,$aHAlign="right",$aVAlign="top") { - $this->xabspos=$aX; - $this->yabspos=$aY; - $this->halign=$aHAlign; - $this->valign=$aVAlign; - } - - - function Pos($aX,$aY,$aHAlign="right",$aVAlign="top") { - if( !($aX<1 && $aY<1) ) - JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1"); - $this->xpos=$aX; - $this->ypos=$aY; - $this->halign=$aHAlign; - $this->valign=$aVAlign; - } - - function SetFillColor($aColor) { - $this->fill_color=$aColor; - } - - function Add($aTxt,$aColor,$aPlotmark="",$aLinestyle=0,$csimtarget="",$csimalt="") { - $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt); - } - - function GetCSIMAreas() { - return $this->csimareas; - } - - function Stroke(&$aImg) { - // Constant - $fillBoxFrameWeight=1; - - if( $this->hide ) return; - - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - - if( $this->reverse ) { - $this->txtcol = array_reverse($this->txtcol); - } - - $n=count($this->txtcol); - if( $n == 0 ) return; - - // Find out the max width and height of each column to be able - // to size the legend box. - $numcolumns = ($n > $this->layout_n ? $this->layout_n : $n); - for( $i=0; $i < $numcolumns; ++$i ) { - $colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) + - 2*$this->xmargin + 2*$this->mark_abs_hsize; - $colheight[$i] = 0; - } - - // Find our maximum height in each row - $rows = 0 ; $rowheight[0] = 0; - for( $i=0; $i < $n; ++$i ) { - $h = max($this->mark_abs_vsize,$aImg->GetTextHeight($this->txtcol[$i][0]))+$this->ymargin; - if( $i % $numcolumns == 0 ) { - $rows++; - $rowheight[$rows-1] = 0; - } - $rowheight[$rows-1] = max($rowheight[$rows-1],$h); - } - - $abs_height = 0; - for( $i=0; $i < $rows; ++$i ) { - $abs_height += $rowheight[$i] ; - } - - // Make sure that the height is at least as high as mark size + ymargin - $abs_height = max($abs_height,$this->mark_abs_vsize); - - // We add 3 extra pixels height to compensate for the difficult in - // calculating font height - $abs_height += $this->ymargin+3; - - // Find out the maximum width in each column - for( $i=$numcolumns; $i < $n; ++$i ) { - $colwidth[$i % $numcolumns] = max( - $aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize,$colwidth[$i % $numcolumns]); - } - - // Get the total width - $mtw = 0; - for( $i=0; $i < $numcolumns; ++$i ) { - $mtw += $colwidth[$i] ; - } - - // Find out maximum width we need for legend box - $abs_width = $mtw+$this->xlmargin; - - if( $this->xabspos === -1 && $this->yabspos === -1 ) { - $this->xabspos = $this->xpos*$aImg->width ; - $this->yabspos = $this->ypos*$aImg->height ; - } - - // Positioning of the legend box - if( $this->halign=="left" ) - $xp = $this->xabspos; - elseif( $this->halign=="center" ) - $xp = $this->xabspos - $abs_width/2; - else - $xp = $aImg->width - $this->xabspos - $abs_width; - - $yp=$this->yabspos; - if( $this->valign=="center" ) - $yp-=$abs_height/2; - elseif( $this->valign=="bottom" ) - $yp-=$abs_height; - - // Stroke legend box - $aImg->SetColor($this->color); - $aImg->SetLineWeight($this->frameweight); - $aImg->SetLineStyle('solid'); - - if( $this->shadow ) - $aImg->ShadowRectangle($xp,$yp,$xp+$abs_width+$this->shadow_width, - $yp+$abs_height+$this->shadow_width, - $this->fill_color,$this->shadow_width,$this->shadow_color); - else { - $aImg->SetColor($this->fill_color); - $aImg->FilledRectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height); - $aImg->SetColor($this->color); - $aImg->Rectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height); - } - - // x1,y1 is the position for the legend mark - $x1=$xp+$this->mark_abs_hsize+$this->xlmargin; - $y1=$yp + $this->ymargin; - - $f2 = round($aImg->GetTextHeight('X')/2); - - $grad = new Gradient($aImg); - $patternFactory = null; - - // Now stroke each legend in turn - // Each plot has added the following information to the legend - // p[0] = Legend text - // p[1] = Color, - // p[2] = For markers a reference to the PlotMark object - // p[3] = For lines the line style, for gradient the negative gradient style - // p[4] = CSIM target - // p[5] = CSIM Alt text - $i = 1 ; $row = 0; - foreach($this->txtcol as $p) { - - // STROKE DEBUG BOX - if( _JPG_DEBUG ) { - $aImg->SetLineWeight(1); - $aImg->SetColor('red'); - $aImg->SetLineStyle('solid'); - $aImg->Rectangle($xp,$y1,$xp+$abs_width,$y1+$rowheight[$row]); - } - - $aImg->SetLineWeight($this->weight); - $x1 = round($x1); $y1=round($y1); - if ( $p[2] != "" && $p[2]->GetType() > -1 ) { - // Make a plot mark legend - $aImg->SetColor($p[1]); - if( is_string($p[3]) || $p[3]>0 ) { - $aImg->SetLineStyle($p[3]); - $aImg->StyleLine($x1-$this->mark_abs_hsize,$y1+$f2,$x1+$this->mark_abs_hsize,$y1+$f2); - } - // Stroke a mark with the standard size - // (As long as it is not an image mark ) - if( $p[2]->GetType() != MARK_IMG ) { - $p[2]->iFormatCallback = ''; - - // Since size for circles is specified as the radius - // this means that we must half the size to make the total - // width behave as the other marks - if( $p[2]->GetType() == MARK_FILLEDCIRCLE || $p[2]->GetType() == MARK_CIRCLE ) { - $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)/2); - $p[2]->Stroke($aImg,$x1,$y1+$f2); - } - else { - $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)); - $p[2]->Stroke($aImg,$x1,$y1+$f2); - } - } - } - elseif ( $p[2] != "" && (is_string($p[3]) || $p[3]>0 ) ) { - // Draw a styled line - $aImg->SetColor($p[1]); - $aImg->SetLineStyle($p[3]); - $aImg->StyleLine($x1-1,$y1+$f2,$x1+$this->mark_abs_hsize,$y1+$f2); - $aImg->StyleLine($x1-1,$y1+$f2+1,$x1+$this->mark_abs_hsize,$y1+$f2+1); - } - else { - // Draw a colored box - $color = $p[1] ; - // We make boxes slightly larger to better show - $boxsize = min($this->mark_abs_vsize,$this->mark_abs_hsize) + 2 ; - $ym = round($y1 + $f2 - $boxsize/2); - // We either need to plot a gradient or a - // pattern. To differentiate we use a kludge. - // Patterns have a p[3] value of < -100 - if( $p[3] < -100 ) { - // p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity - if( $patternFactory == null ) { - $patternFactory = new RectPatternFactory(); - } - $prect = $patternFactory->Create($p[1][0],$p[1][1],1); - $prect->SetBackground($p[1][3]); - $prect->SetDensity($p[1][2]+1); - $prect->SetPos(new Rectangle($x1,$ym,$boxsize,$boxsize)); - $prect->Stroke($aImg); - $prect=null; - } - else { - if( is_array($color) && count($color)==2 ) { - // The client want a gradient color - $grad->FilledRectangle($x1,$ym, - $x1+$boxsize,$ym+$boxsize, - $color[0],$color[1],-$p[3]); - } - else { - $aImg->SetColor($p[1]); - $aImg->FilledRectangle($x1,$ym,$x1+$boxsize,$ym+$boxsize); - } - $aImg->SetColor($this->color); - $aImg->SetLineWeight($fillBoxFrameWeight); - $aImg->Rectangle($x1,$ym,$x1+$boxsize,$ym+$boxsize); - } - } - $aImg->SetColor($this->font_color); - $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); - $aImg->SetTextAlign("left","top"); - $aImg->StrokeText(round($x1+$this->mark_abs_hsize+$this->xmargin),$y1,$p[0]); - - // Add CSIM for Legend if defined - if( $p[4] != "" ) { - $xe = $x1 + $this->xmargin+$this->mark_abs_hsize+$aImg->GetTextWidth($p[0]); - $ye = $y1 + max($this->mark_abs_vsize,$aImg->GetTextHeight($p[0])); - $coords = "$x1,$y1,$xe,$y1,$xe,$ye,$x1,$ye"; - if( ! empty($p[4]) ) { - $this->csimareas .= "csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"\" />\n"; - } - } - if( $i >= $this->layout_n ) { - $x1 = $xp+$this->mark_abs_hsize+$this->xlmargin; - $y1 += $rowheight[$row++]; - $i = 1; - } - else { - $x1 += $colwidth[($i-1) % $numcolumns] ; - ++$i; - } - } - } -} // Class - - -//=================================================== -// CLASS DisplayValue -// Description: Used to print data values at data points -//=================================================== -class DisplayValue { - var $show=false,$format="%.1f",$negformat=""; - var $iFormCallback=''; - var $angle=0; - var $ff=FF_FONT1,$fs=FS_NORMAL,$fsize=10; - var $color="navy",$negcolor=""; - var $margin=5,$valign="",$halign="center"; - var $iHideZero=false; - - function Show($aFlag=true) { - $this->show=$aFlag; - } - - function SetColor($aColor,$aNegcolor="") { - $this->color = $aColor; - $this->negcolor = $aNegcolor; - } - - function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { - $this->ff=$aFontFamily; - $this->fs=$aFontStyle; - $this->fsize=$aFontSize; - } - - function SetMargin($aMargin) { - $this->margin = $aMargin; - } - - function SetAngle($aAngle) { - $this->angle = $aAngle; - } - - function SetAlign($aHAlign,$aVAlign='') { - $this->halign = $aHAlign; - $this->valign = $aVAlign; - } - - function SetFormat($aFormat,$aNegFormat="") { - $this->format= $aFormat; - $this->negformat= $aNegFormat; - } - - function SetFormatCallback($aFunc) { - $this->iFormCallback = $aFunc; - } - - function HideZero($aFlag=true) { - $this->iHideZero=$aFlag; - } - - function Stroke($img,$aVal,$x,$y) { - - if( $this->show ) - { - if( $this->negformat=="" ) $this->negformat=$this->format; - if( $this->negcolor=="" ) $this->negcolor=$this->color; - - if( $aVal===NULL || (is_string($aVal) && ($aVal=="" || $aVal=="-" || $aVal=="x" ) ) ) - return; - - if( is_numeric($aVal) && $aVal==0 && $this->iHideZero ) { - return; - } - - // Since the value is used in different cirumstances we need to check what - // kind of formatting we shall use. For example, to display values in a line - // graph we simply display the formatted value, but in the case where the user - // has already specified a text string we don't fo anything. - if( $this->iFormCallback != '' ) { - $f = $this->iFormCallback; - $sval = call_user_func($f,$aVal); - } - elseif( is_numeric($aVal) ) { - if( $aVal >= 0 ) - $sval=sprintf($this->format,$aVal); - else - $sval=sprintf($this->negformat,$aVal); - } - else - $sval=$aVal; - - $y = $y-sign($aVal)*$this->margin; - - $txt = new Text($sval,$x,$y); - $txt->SetFont($this->ff,$this->fs,$this->fsize); - if( $this->valign == "" ) { - if( $aVal >= 0 ) - $valign = "bottom"; - else - $valign = "top"; - } - else - $valign = $this->valign; - $txt->Align($this->halign,$valign); - - $txt->SetOrientation($this->angle); - if( $aVal > 0 ) - $txt->SetColor($this->color); - else - $txt->SetColor($this->negcolor); - $txt->Stroke($img); - } - } -} - -//=================================================== -// CLASS Plot -// Description: Abstract base class for all concrete plot classes -//=================================================== -class Plot { - var $line_weight=1; - var $coords=array(); - var $legend='',$hidelegend=false; - var $csimtargets=array(); // Array of targets for CSIM - var $csimareas=""; // Resultant CSIM area tags - var $csimalts=null; // ALT:s for corresponding target - var $color="black"; - var $numpoints=0; - var $weight=1; - var $value; - var $center=false; - var $legendcsimtarget=''; - var $legendcsimalt=''; -//--------------- -// CONSTRUCTOR - function __construct(&$aDatay,$aDatax=false) { - $this->numpoints = count($aDatay); - if( $this->numpoints==0 ) - JpGraphError::RaiseL(25121);//("Empty input data array specified for plot. Must have at least one data point."); - $this->coords[0]=$aDatay; - if( is_array($aDatax) ) - $this->coords[1]=$aDatax; - $this->value = new DisplayValue(); - } - -//--------------- -// PUBLIC METHODS - - // Stroke the plot - // "virtual" function which must be implemented by - // the subclasses - function Stroke(&$aImg,&$aXScale,&$aYScale) { - JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot"); - } - - function HideLegend($f=true) { - $this->hidelegend = $f; - } - - function DoLegend(&$graph) { - if( !$this->hidelegend ) - $this->Legend($graph); - } - - function StrokeDataValue($img,$aVal,$x,$y) { - $this->value->Stroke($img,$aVal,$x,$y); - } - - // Set href targets for CSIM - function SetCSIMTargets($aTargets,$aAlts=null) { - $this->csimtargets=$aTargets; - $this->csimalts=$aAlts; - } - - // Get all created areas - function GetCSIMareas() { - return $this->csimareas; - } - - // "Virtual" function which gets called before any scale - // or axis are stroked used to do any plot specific adjustment - function PreStrokeAdjust(&$aGraph) { - if( substr($aGraph->axtype,0,4) == "text" && (isset($this->coords[1])) ) - JpGraphError::RaiseL(25123);//("JpGraph: You can't use a text X-scale with specified X-coords. Use a \"int\" or \"lin\" scale instead."); - return true; - } - - // Get minimum values in plot - function Min() { - if( isset($this->coords[1]) ) - $x=$this->coords[1]; - else - $x=""; - if( $x != "" && count($x) > 0 ) - $xm=min($x); - else - $xm=0; - $y=$this->coords[0]; - $cnt = count($y); - if( $cnt > 0 ) { - /* - if( ! isset($y[0]) ) { - JpGraphError('The input data array must have consecutive values from position 0 and forward. The given y-array starts with empty values (NULL)'); - } - */ - //$ym = $y[0]; - $i=0; - while( $i<$cnt && !is_numeric($ym=$y[$i]) ) - $i++; - while( $i < $cnt) { - if( is_numeric($y[$i]) ) - $ym=min($ym,$y[$i]); - ++$i; - } - } - else - $ym=""; - return array($xm,$ym); - } - - // Get maximum value in plot - function Max() { - if( isset($this->coords[1]) ) - $x=$this->coords[1]; - else - $x=""; - - if( $x!="" && count($x) > 0 ) - $xm=max($x); - else { - $xm = $this->numpoints-1; - } - $y=$this->coords[0]; - if( count($y) > 0 ) { - /* - if( !isset($y[0]) ) { - JpGraphError::Raise('The input data array must have consecutive values from position 0 and forward. The given y-array starts with empty values (NULL)'); - //$y[0] = 0; -// Change in 1.5.1 Don't treat this as an error any more. Just silently convert to 0 -// Change in 1.17 Treat his as an error again !! This is the right way to do !! - } - */ - $cnt = count($y); - $i=0; - while( $i<$cnt && !is_numeric($ym=$y[$i]) ) - $i++; - while( $i < $cnt ) { - if( is_numeric($y[$i]) ) - $ym=max($ym,$y[$i]); - ++$i; - } - - } - else - $ym=""; - return array($xm,$ym); - } - - function SetColor($aColor) { - $this->color=$aColor; - } - - function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") { - $this->legend = $aLegend; - $this->legendcsimtarget = $aCSIM; - $this->legendcsimalt = $aCSIMAlt; - } - - function SetWeight($aWeight) { - $this->weight=$aWeight; - } - - function SetLineWeight($aWeight=1) { - $this->line_weight=$aWeight; - } - - function SetCenter($aCenter=true) { - $this->center = $aCenter; - } - - // This method gets called by Graph class to plot anything that should go - // into the margin after the margin color has been set. - function StrokeMargin(&$aImg) { - return true; - } - - // Framework function the chance for each plot class to set a legend - function Legend(&$aGraph) { - if( $this->legend != "" ) - $aGraph->legend->Add($this->legend,$this->color,"",0,$this->legendcsimtarget,$this->legendcsimalt); - } - -} // Class - - -//=================================================== -// CLASS PlotLine -// Description: -// Data container class to hold properties for a static -// line that is drawn directly in the plot area. -// Usefull to add static borders inside a plot to show -// for example set-values -//=================================================== -class PlotLine { - var $weight=1; - var $color="black"; - var $direction=-1; - var $scaleposition; - -//--------------- -// CONSTRUCTOR - function __construct($aDir=HORIZONTAL,$aPos=0,$aColor="black",$aWeight=1) { - $this->direction = $aDir; - $this->color=$aColor; - $this->weight=$aWeight; - $this->scaleposition=$aPos; - } - -//--------------- -// PUBLIC METHODS - function SetPosition($aScalePosition) { - $this->scaleposition=$aScalePosition; - } - - function SetDirection($aDir) { - $this->direction = $aDir; - } - - function SetColor($aColor) { - $this->color=$aColor; - } - - function SetWeight($aWeight) { - $this->weight=$aWeight; - } - - function PreStrokeAdjust($aGraph) { - // Nothing to do - } - - function Stroke(&$aImg,&$aXScale,&$aYScale) { - $aImg->SetColor($this->color); - $aImg->SetLineWeight($this->weight); - if( $this->direction == VERTICAL ) { - $ymin_abs=$aYScale->Translate($aYScale->GetMinVal()); - $ymax_abs=$aYScale->Translate($aYScale->GetMaxVal()); - $xpos_abs=$aXScale->Translate($this->scaleposition); - $aImg->Line($xpos_abs, $ymin_abs, $xpos_abs, $ymax_abs); - } - elseif( $this->direction == HORIZONTAL ) { - $xmin_abs=$aXScale->Translate($aXScale->GetMinVal()); - $xmax_abs=$aXScale->Translate($aXScale->GetMaxVal()); - $ypos_abs=$aYScale->Translate($this->scaleposition); - $aImg->Line($xmin_abs, $ypos_abs, $xmax_abs, $ypos_abs); - } - else - JpGraphError::RaiseL(25125);//(" Illegal direction for static line"); - } -} - -// -?> +Get(11,$file,$lineno); + die($msg); + } + else { + define('CACHE_DIR', $_SERVER['TEMP'] . '/'); + } + } else { + define('CACHE_DIR','/tmp/jpgraph_cache/'); + } + } +} +elseif( !defined('CACHE_DIR') ) { + define('CACHE_DIR', ''); +} + +// +// Setup path for western/latin TTF fonts +// +if (!defined('TTF_DIR')) { + if (strstr( PHP_OS, 'WIN') ) { + $sroot = getenv('SystemRoot'); + if( empty($sroot) ) { + $t = new ErrMsgText(); + $msg = $t->Get(12,$file,$lineno); + die($msg); + } + else { + define('TTF_DIR', $sroot.'/fonts/'); + } + } else { + define('TTF_DIR','/usr/share/fonts/truetype/'); + } +} + +// +// Setup path for MultiByte TTF fonts (japanese, chinese etc.) +// +if (!defined('MBTTF_DIR')) { + if (strstr( PHP_OS, 'WIN') ) { + $sroot = getenv('SystemRoot'); + if( empty($sroot) ) { + $t = new ErrMsgText(); + $msg = $t->Get(12,$file,$lineno); + die($msg); + } + else { + define('MBTTF_DIR', $sroot.'/fonts/'); + } + } else { + define('MBTTF_DIR','/usr/share/fonts/truetype/'); + } +} + +// +// Check minimum PHP version +// +function CheckPHPVersion($aMinVersion) { + list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION); + list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion); + + if ($majorC < $majorR) return false; + + if ($majorC == $majorR) { + if($minorC < $minorR) return false; + + if($minorC == $minorR){ + if($editC < $editR) return false; + } + } + + return true; +} + +// +// Make sure PHP version is high enough +// +if( !CheckPHPVersion(MIN_PHPVERSION) ) { + JpGraphError::RaiseL(13,PHP_VERSION,MIN_PHPVERSION); + die(); +} + +// +// Make GD sanity check +// +if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) { + JpGraphError::RaiseL(25001); + //("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)"); +} + +// +// Setup PHP error handler +// +function _phpErrorHandler($errno,$errmsg,$filename, $linenum, $vars) { + // Respect current error level + if( $errno & error_reporting() ) { + JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg); + } +} + +if( INSTALL_PHP_ERR_HANDLER ) { + set_error_handler("_phpErrorHandler"); +} + +// +// Check if there were any warnings, perhaps some wrong includes by the user. In this +// case we raise it immediately since otherwise the image will not show and makes +// debugging difficult. This is controlled by the user setting CATCH_PHPERRMSG +// +if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) { + JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']); +} + +// Useful mathematical function +function sign($a) {return $a >= 0 ? 1 : -1;} + +// +// Utility function to generate an image name based on the filename we +// are running from and assuming we use auto detection of graphic format +// (top level), i.e it is safe to call this function +// from a script that uses JpGraph +// +function GenImgName() { + // Determine what format we should use when we save the images + $supported = imagetypes(); + if( $supported & IMG_PNG ) $img_format="png"; + elseif( $supported & IMG_GIF ) $img_format="gif"; + elseif( $supported & IMG_JPG ) $img_format="jpeg"; + elseif( $supported & IMG_WBMP ) $img_format="wbmp"; + elseif( $supported & IMG_XPM ) $img_format="xpm"; + + + if( !isset($_SERVER['PHP_SELF']) ) { + JpGraphError::RaiseL(25005); + //(" 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."); + } + $fname = basename($_SERVER['PHP_SELF']); + if( !empty($_SERVER['QUERY_STRING']) ) { + $q = @$_SERVER['QUERY_STRING']; + $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format; + } + else { + $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format; + } + return $fname; +} + +//=================================================== +// CLASS JpgTimer +// Description: General timing utility class to handle +// time measurement of generating graphs. Multiple +// timers can be started. +//=================================================== +class JpgTimer { + private $start, $idx; + + function __construct() { + $this->idx=0; + } + + // Push a new timer start on stack + function Push() { + list($ms,$s)=explode(" ",microtime()); + $this->start[$this->idx++]=floor($ms*1000) + 1000*$s; + } + + // Pop the latest timer start and return the diff with the + // current time + function Pop() { + assert($this->idx>0); + list($ms,$s)=explode(" ",microtime()); + $etime=floor($ms*1000) + (1000*$s); + $this->idx--; + return $etime-$this->start[$this->idx]; + } +} // Class + +//=================================================== +// CLASS DateLocale +// Description: Hold localized text used in dates +//=================================================== +class DateLocale { + + public $iLocale = 'C'; // environmental locale be used by default + private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null; + + function __construct() { + settype($this->iDayAbb, 'array'); + settype($this->iShortDay, 'array'); + settype($this->iShortMonth, 'array'); + settype($this->iMonthName, 'array'); + $this->Set('C'); + } + + function Set($aLocale) { + if ( in_array($aLocale, array_keys($this->iDayAbb)) ){ + $this->iLocale = $aLocale; + return TRUE; // already cached nothing else to do! + } + + $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME + + if (is_array($aLocale)) { + foreach ($aLocale as $loc) { + $res = @setlocale(LC_TIME, $loc); + if ( $res ) { + $aLocale = $loc; + break; + } + } + } + else { + $res = @setlocale(LC_TIME, $aLocale); + } + + if ( ! $res ) { + JpGraphError::RaiseL(25007,$aLocale); + //("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."); + return FALSE; + } + + $this->iLocale = $aLocale; + for( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ) { + $day = strftime('%a', strtotime("$ofs day")); + $day[0] = strtoupper($day[0]); + $this->iDayAbb[$aLocale][]= $day[0]; + $this->iShortDay[$aLocale][]= $day; + } + + for($i=1; $i<=12; ++$i) { + list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01"))); + $this->iShortMonth[$aLocale][] = ucfirst($short); + $this->iMonthName [$aLocale][] = ucfirst($full); + } + + setlocale(LC_TIME, $pLocale); + + return TRUE; + } + + + function GetDayAbb() { + return $this->iDayAbb[$this->iLocale]; + } + + function GetShortDay() { + return $this->iShortDay[$this->iLocale]; + } + + function GetShortMonth() { + return $this->iShortMonth[$this->iLocale]; + } + + function GetShortMonthName($aNbr) { + return $this->iShortMonth[$this->iLocale][$aNbr]; + } + + function GetLongMonthName($aNbr) { + return $this->iMonthName[$this->iLocale][$aNbr]; + } + + function GetMonth() { + return $this->iMonthName[$this->iLocale]; + } +} + +// Global object handlers +$gDateLocale = new DateLocale(); +$gJpgDateLocale = new DateLocale(); + +//======================================================= +// CLASS Footer +// Description: Encapsulates the footer line in the Graph +//======================================================= +class Footer { + public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ; + public $left,$center,$right; + private $iTimer=null, $itimerpoststring=''; + + function __construct() { + $this->left = new Text(); + $this->left->ParagraphAlign('left'); + $this->center = new Text(); + $this->center->ParagraphAlign('center'); + $this->right = new Text(); + $this->right->ParagraphAlign('right'); + } + + function SetTimer($aTimer,$aTimerPostString='') { + $this->iTimer = $aTimer; + $this->itimerpoststring = $aTimerPostString; + } + + function SetMargin($aLeft=3,$aRight=3,$aBottom=3) { + $this->iLeftMargin = $aLeft; + $this->iRightMargin = $aRight; + $this->iBottomMargin = $aBottom; + } + + function Stroke($aImg) { + $y = $aImg->height - $this->iBottomMargin; + $x = $this->iLeftMargin; + $this->left->Align('left','bottom'); + $this->left->Stroke($aImg,$x,$y); + + $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2; + $this->center->Align('center','bottom'); + $this->center->Stroke($aImg,$x,$y); + + $x = $aImg->width - $this->iRightMargin; + $this->right->Align('right','bottom'); + if( $this->iTimer != null ) { + $this->right->Set( $this->right->t . sprintf('%.3f',$this->iTimer->Pop()/1000.0) . $this->itimerpoststring ); + } + $this->right->Stroke($aImg,$x,$y); + } +} + + +//=================================================== +// CLASS Graph +// Description: Main class to handle graphs +//=================================================== +class Graph { + public $cache=null; // Cache object (singleton) + public $img=null; // Img object (singleton) + public $plots=array(); // Array of all plot object in the graph (for Y 1 axis) + public $y2plots=array(); // Array of all plot object in the graph (for Y 2 axis) + public $ynplots=array(); + public $xscale=null; // X Scale object (could be instance of LinearScale or LogScale + public $yscale=null,$y2scale=null, $ynscale=array(); + public $iIcons = array(); // Array of Icons to add to + public $cache_name; // File name to be used for the current graph in the cache directory + public $xgrid=null; // X Grid object (linear or logarithmic) + public $ygrid=null,$y2grid=null; //dito for Y + public $doframe,$frame_color, $frame_weight; // Frame around graph + public $boxed=false, $box_color='black', $box_weight=1; // Box around plot area + public $doshadow=false,$shadow_width=4,$shadow_color='gray@0.5'; // Shadow for graph + public $xaxis=null; // X-axis (instane of Axis class) + public $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class) + public $margin_color; // Margin color of graph + public $plotarea_color=array(255,255,255); // Plot area color + public $title,$subtitle,$subsubtitle; // Title and subtitle(s) text object + public $axtype="linlin"; // Type of axis + public $xtick_factor,$ytick_factor; // Factor to determine the maximum number of ticks depending on the plot width + public $texts=null, $y2texts=null; // Text object to ge shown in the graph + public $lines=null, $y2lines=null; + public $bands=null, $y2bands=null; + public $text_scale_off=0, $text_scale_abscenteroff=-1; // Text scale in fractions and for centering bars + public $background_image='',$background_image_type=-1,$background_image_format="png"; + public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0; + public $background_image_xpos=0,$background_image_ypos=0; + public $image_bright=0, $image_contr=0, $image_sat=0; + public $inline; + public $showcsim=0,$csimcolor="red";//debug stuff, draw the csim boundaris on the image if <>0 + public $grid_depth=DEPTH_BACK; // Draw grid under all plots as default + public $iAxisStyle = AXSTYLE_SIMPLE; + public $iCSIMdisplay=false,$iHasStroked = false; + public $footer; + public $csimcachename = '', $csimcachetimeout = 0, $iCSIMImgAlt=''; + public $iDoClipping = false; + public $y2orderback=true; + public $tabtitle; + public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN; + public $bkg_gradfrom='navy', $bkg_gradto='silver'; + public $plot_gradtype=-1,$plot_gradstyle=BGRAD_MARGIN; + public $plot_gradfrom='silver', $plot_gradto='navy'; + + public $titlebackground = false; + public $titlebackground_color = 'lightblue', + $titlebackground_style = 1, + $titlebackground_framecolor, + $titlebackground_framestyle, + $titlebackground_frameweight, + $titlebackground_bevelheight; + public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID; + public $titlebkg_scolor1='black',$titlebkg_scolor2='white'; + public $framebevel, $framebeveldepth; + public $framebevelborder, $framebevelbordercolor; + public $framebevelcolor1, $framebevelcolor2; + public $background_image_mix=100; + public $background_cflag = ''; + public $background_cflag_type = BGIMG_FILLPLOT; + public $background_cflag_mix = 100; + public $iImgTrans=false, + $iImgTransHorizon = 100,$iImgTransSkewDist=150, + $iImgTransDirection = 1, $iImgTransMinSize = true, + $iImgTransFillColor='white',$iImgTransHighQ=false, + $iImgTransBorder=false,$iImgTransHorizonPos=0.5; + public $legend; + public $graph_theme; + protected $iYAxisDeltaPos=50; + protected $iIconDepth=DEPTH_BACK; + protected $iAxisLblBgType = 0, + $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black', + $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black'; + protected $iTables=NULL; + + protected $isRunningClear = false; + protected $inputValues; + protected $isAfterSetScale = false; + + // aWIdth Width in pixels of image + // aHeight Height in pixels of image + // aCachedName Name for image file in cache directory + // aTimeOut Timeout in minutes for image in cache + // aInline If true the image is streamed back in the call to Stroke() + // If false the image is just created in the cache + function __construct($aWidth=300,$aHeight=200,$aCachedName='',$aTimeout=0,$aInline=true) { + + if( !is_numeric($aWidth) || !is_numeric($aHeight) ) { + JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric'); + } + + // Initialize frame and margin + $this->InitializeFrameAndMargin(); + + // Automatically generate the image file name based on the name of the script that + // generates the graph + if( $aCachedName == 'auto' ) { + $aCachedName=GenImgName(); + } + + // Should the image be streamed back to the browser or only to the cache? + $this->inline=$aInline; + + $this->img = new RotImage($aWidth,$aHeight); + $this->cache = new ImgStreamCache(); + + // Window doesn't like '?' in the file name so replace it with an '_' + $aCachedName = str_replace("?","_",$aCachedName); + $this->SetupCache($aCachedName, $aTimeout); + + $this->title = new Text(); + $this->title->ParagraphAlign('center'); + $this->title->SetFont(FF_DEFAULT,FS_NORMAL); //FF_FONT2, FS_BOLD + $this->title->SetMargin(5); + $this->title->SetAlign('center'); + + $this->subtitle = new Text(); + $this->subtitle->ParagraphAlign('center'); + $this->subtitle->SetMargin(3); + $this->subtitle->SetAlign('center'); + + $this->subsubtitle = new Text(); + $this->subsubtitle->ParagraphAlign('center'); + $this->subsubtitle->SetMargin(3); + $this->subsubtitle->SetAlign('center'); + + $this->legend = new Legend(); + $this->footer = new Footer(); + + // If the cached version exist just read it directly from the + // cache, stream it back to browser and exit + if( $aCachedName!='' && READ_CACHE && $aInline ) { + if( $this->cache->GetAndStream($this->img,$aCachedName) ) { + exit(); + } + } + + $this->SetTickDensity(); // Normal density + + $this->tabtitle = new GraphTabTitle(); + + if (!$this->isRunningClear) { + $this->inputValues = array(); + $this->inputValues['aWidth'] = $aWidth; + $this->inputValues['aHeight'] = $aHeight; + $this->inputValues['aCachedName'] = $aCachedName; + $this->inputValues['aTimeout'] = $aTimeout; + $this->inputValues['aInline'] = $aInline; + + $theme_class = DEFAULT_THEME_CLASS; + if (class_exists($theme_class)) { + $this->graph_theme = new $theme_class(); + } + } + } + + function InitializeFrameAndMargin() { + $this->doframe=true; + $this->frame_color='black'; + $this->frame_weight=1; + + $this->titlebackground_framecolor = 'blue'; + $this->titlebackground_framestyle = 2; + $this->titlebackground_frameweight = 1; + $this->titlebackground_bevelheight = 3; + $this->titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID; + $this->titlebkg_scolor1='black'; + $this->titlebkg_scolor2='white'; + $this->framebevel = false; + $this->framebeveldepth = 2; + $this->framebevelborder = false; + $this->framebevelbordercolor='black'; + $this->framebevelcolor1='white@0.4'; + $this->framebevelcolor2='black@0.4'; + + $this->margin_color = array(250,250,250); + } + + function SetupCache($aFilename,$aTimeout=60) { + $this->cache_name = $aFilename; + $this->cache->SetTimeOut($aTimeout); + } + + // Enable final image perspective transformation + function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) { + $this->iImgTrans = true; + $this->iImgTransHorizon = $aHorizon; + $this->iImgTransSkewDist= $aSkewDist; + $this->iImgTransDirection = $aDir; + $this->iImgTransMinSize = $aMinSize; + $this->iImgTransFillColor=$aFillColor; + $this->iImgTransHighQ=$aQuality; + $this->iImgTransBorder=$aBorder; + $this->iImgTransHorizonPos=$aHorizonPos; + } + + function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt); + } + + function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt); + } + + function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt); + } + + function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt); + } + + // Set Image format and optional quality + function SetImgFormat($aFormat,$aQuality=75) { + $this->img->SetImgFormat($aFormat,$aQuality); + } + + // Should the grid be in front or back of the plot? + function SetGridDepth($aDepth) { + $this->grid_depth=$aDepth; + } + + function SetIconDepth($aDepth) { + $this->iIconDepth=$aDepth; + } + + // Specify graph angle 0-360 degrees. + function SetAngle($aAngle) { + $this->img->SetAngle($aAngle); + } + + function SetAlphaBlending($aFlg=true) { + $this->img->SetAlphaBlending($aFlg); + } + + // Shortcut to image margin + function SetMargin($lm,$rm,$tm,$bm) { + $this->img->SetMargin($lm,$rm,$tm,$bm); + } + + function SetY2OrderBack($aBack=true) { + $this->y2orderback = $aBack; + } + + // Rotate the graph 90 degrees and set the margin + // when we have done a 90 degree rotation + function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) { + $adj = ($this->img->height - $this->img->width)/2; + $this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj); + $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2)); + $this->SetAngle(90); + if( empty($this->yaxis) || empty($this->xaxis) ) { + JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()'); + } + $this->xaxis->SetLabelAlign('right','center'); + $this->yaxis->SetLabelAlign('center','bottom'); + } + + function SetClipping($aFlg=true) { + $this->iDoClipping = $aFlg ; + } + + // Add a plot object to the graph + function Add($aPlot) { + if( $aPlot == null ) { + JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph."); + } + if( is_array($aPlot) && count($aPlot) > 0 ) { + $cl = $aPlot[0]; + } + else { + $cl = $aPlot; + } + + if( $cl instanceof Text ) $this->AddText($aPlot); + elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) $this->AddLine($aPlot); + elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) $this->AddBand($aPlot); + elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot); + elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) ) $this->AddTable($aPlot); + else { + if( is_array($aPlot) ) { + $this->plots = array_merge($this->plots,$aPlot); + } + else { + $this->plots[] = $aPlot; + } + } + + if ($this->graph_theme) { + $this->graph_theme->SetupPlot($aPlot); + } + } + + function AddTable($aTable) { + if( is_array($aTable) ) { + for($i=0; $i < count($aTable); ++$i ) { + $this->iTables[]=$aTable[$i]; + } + } + else { + $this->iTables[] = $aTable ; + } + } + + function AddIcon($aIcon) { + if( is_array($aIcon) ) { + for($i=0; $i < count($aIcon); ++$i ) { + $this->iIcons[]=$aIcon[$i]; + } + } + else { + $this->iIcons[] = $aIcon ; + } + } + + // Add plot to second Y-scale + function AddY2($aPlot) { + if( $aPlot == null ) { + JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph."); + } + + if( is_array($aPlot) && count($aPlot) > 0 ) { + $cl = $aPlot[0]; + } + else { + $cl = $aPlot; + } + + if( $cl instanceof Text ) { + $this->AddText($aPlot,true); + } + elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) { + $this->AddLine($aPlot,true); + } + elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) { + $this->AddBand($aPlot,true); + } + else { + $this->y2plots[] = $aPlot; + } + + if ($this->graph_theme) { + $this->graph_theme->SetupPlot($aPlot); + } + } + + // Add plot to the extra Y-axises + function AddY($aN,$aPlot) { + + if( $aPlot == null ) { + JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph."); + } + + if( is_array($aPlot) && count($aPlot) > 0 ) { + $cl = $aPlot[0]; + } + else { + $cl = $aPlot; + } + + if( ($cl instanceof Text) || + (class_exists('PlotLine',false) && ($cl instanceof PlotLine)) || + (class_exists('PlotBand',false) && ($cl instanceof PlotBand)) ) { + JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis'); + } + else { + $this->ynplots[$aN][] = $aPlot; + } + + if ($this->graph_theme) { + $this->graph_theme->SetupPlot($aPlot); + } + } + + // Add text object to the graph + function AddText($aTxt,$aToY2=false) { + if( $aTxt == null ) { + JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph."); + } + if( $aToY2 ) { + if( is_array($aTxt) ) { + for($i=0; $i < count($aTxt); ++$i ) { + $this->y2texts[]=$aTxt[$i]; + } + } + else { + $this->y2texts[] = $aTxt; + } + } + else { + if( is_array($aTxt) ) { + for($i=0; $i < count($aTxt); ++$i ) { + $this->texts[]=$aTxt[$i]; + } + } + else { + $this->texts[] = $aTxt; + } + } + } + + // Add a line object (class PlotLine) to the graph + function AddLine($aLine,$aToY2=false) { + if( $aLine == null ) { + JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph."); + } + + if( $aToY2 ) { + if( is_array($aLine) ) { + for($i=0; $i < count($aLine); ++$i ) { + //$this->y2lines[]=$aLine[$i]; + $this->y2plots[]=$aLine[$i]; + } + } + else { + //$this->y2lines[] = $aLine; + $this->y2plots[]=$aLine; + } + } + else { + if( is_array($aLine) ) { + for($i=0; $ilines[]=$aLine[$i]; + $this->plots[]=$aLine[$i]; + } + } + else { + //$this->lines[] = $aLine; + $this->plots[] = $aLine; + } + } + } + + // Add vertical or horizontal band + function AddBand($aBand,$aToY2=false) { + if( $aBand == null ) { + JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph."); + } + + if( $aToY2 ) { + if( is_array($aBand) ) { + for($i=0; $i < count($aBand); ++$i ) { + $this->y2bands[] = $aBand[$i]; + } + } + else { + $this->y2bands[] = $aBand; + } + } + else { + if( is_array($aBand) ) { + for($i=0; $i < count($aBand); ++$i ) { + $this->bands[] = $aBand[$i]; + } + } + else { + $this->bands[] = $aBand; + } + } + } + + function SetPlotGradient($aFrom='navy',$aTo='silver',$aGradType=2) { + $this->plot_gradtype=$aGradType; + $this->plot_gradfrom = $aFrom; + $this->plot_gradto = $aTo; + } + + function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) { + $this->bkg_gradtype=$aGradType; + $this->bkg_gradstyle=$aStyle; + $this->bkg_gradfrom = $aFrom; + $this->bkg_gradto = $aTo; + } + + // Set a country flag in the background + function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) { + $this->background_cflag = $aName; + $this->background_cflag_type = $aBgType; + $this->background_cflag_mix = $aMix; + } + + // Alias for the above method + function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) { + $this->background_cflag = $aName; + $this->background_cflag_type = $aBgType; + $this->background_cflag_mix = $aMix; + } + + + // Specify a background image + function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat='auto') { + + // Get extension to determine image type + if( $aImgFormat == 'auto' ) { + $e = explode('.',$aFileName); + if( !$e ) { + 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'); + } + + $valid_formats = array('png', 'jpg', 'gif'); + $aImgFormat = strtolower($e[count($e)-1]); + if ($aImgFormat == 'jpeg') { + $aImgFormat = 'jpg'; + } + elseif (!in_array($aImgFormat, $valid_formats) ) { + JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName); + } + } + + $this->background_image = $aFileName; + $this->background_image_type=$aBgType; + $this->background_image_format=$aImgFormat; + } + + function SetBackgroundImageMix($aMix) { + $this->background_image_mix = $aMix ; + } + + // Adjust background image position + function SetBackgroundImagePos($aXpos,$aYpos) { + $this->background_image_xpos = $aXpos ; + $this->background_image_ypos = $aYpos ; + } + + // Specify axis style (boxed or single) + function SetAxisStyle($aStyle) { + $this->iAxisStyle = $aStyle ; + } + + // Set a frame around the plot area + function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) { + $this->boxed = $aDrawPlotFrame; + $this->box_weight = $aPlotFrameWeight; + $this->box_color = $aPlotFrameColor; + } + + // Specify color for the plotarea (not the margins) + function SetColor($aColor) { + $this->plotarea_color=$aColor; + } + + // Specify color for the margins (all areas outside the plotarea) + function SetMarginColor($aColor) { + $this->margin_color=$aColor; + } + + // Set a frame around the entire image + function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) { + $this->doframe = $aDrawImgFrame; + $this->frame_color = $aImgFrameColor; + $this->frame_weight = $aImgFrameWeight; + } + + function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) { + $this->framebevel = $aFlg ; + $this->framebeveldepth = $aDepth ; + $this->framebevelborder = $aBorder ; + $this->framebevelbordercolor = $aBorderColor ; + $this->framebevelcolor1 = $aColor1 ; + $this->framebevelcolor2 = $aColor2 ; + + $this->doshadow = false ; + } + + // Set the shadow around the whole image + function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor='darkgray') { + $this->doshadow = $aShowShadow; + $this->shadow_color = $aShadowColor; + $this->shadow_width = $aShadowWidth; + $this->footer->iBottomMargin += $aShadowWidth; + $this->footer->iRightMargin += $aShadowWidth; + } + + // Specify x,y scale. Note that if you manually specify the scale + // you must also specify the tick distance with a call to Ticks::Set() + function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) { + $this->axtype = $aAxisType; + + if( $aYMax < $aYMin || $aXMax < $aXMin ) { + JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.'); + } + + $yt=substr($aAxisType,-3,3); + if( $yt == 'lin' ) { + $this->yscale = new LinearScale($aYMin,$aYMax); + } + elseif( $yt == 'int' ) { + $this->yscale = new LinearScale($aYMin,$aYMax); + $this->yscale->SetIntScale(); + } + elseif( $yt == 'log' ) { + $this->yscale = new LogScale($aYMin,$aYMax); + } + else { + JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)"); + } + + $xt=substr($aAxisType,0,3); + if( $xt == 'lin' || $xt == 'tex' ) { + $this->xscale = new LinearScale($aXMin,$aXMax,'x'); + $this->xscale->textscale = ($xt == 'tex'); + } + elseif( $xt == 'int' ) { + $this->xscale = new LinearScale($aXMin,$aXMax,'x'); + $this->xscale->SetIntScale(); + } + elseif( $xt == 'dat' ) { + $this->xscale = new DateScale($aXMin,$aXMax,'x'); + } + elseif( $xt == 'log' ) { + $this->xscale = new LogScale($aXMin,$aXMax,'x'); + } + else { + JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)"); + } + + $this->xaxis = new Axis($this->img,$this->xscale); + $this->yaxis = new Axis($this->img,$this->yscale); + $this->xgrid = new Grid($this->xaxis); + $this->ygrid = new Grid($this->yaxis); + $this->ygrid->Show(); + + + if (!$this->isRunningClear) { + $this->inputValues['aAxisType'] = $aAxisType; + $this->inputValues['aYMin'] = $aYMin; + $this->inputValues['aYMax'] = $aYMax; + $this->inputValues['aXMin'] = $aXMin; + $this->inputValues['aXMax'] = $aXMax; + + if ($this->graph_theme) { + $this->graph_theme->ApplyGraph($this); + } + } + + $this->isAfterSetScale = true; + } + + // Specify secondary Y scale + function SetY2Scale($aAxisType='lin',$aY2Min=1,$aY2Max=1) { + if( $aAxisType == 'lin' ) { + $this->y2scale = new LinearScale($aY2Min,$aY2Max); + } + elseif( $aAxisType == 'int' ) { + $this->y2scale = new LinearScale($aY2Min,$aY2Max); + $this->y2scale->SetIntScale(); + } + elseif( $aAxisType == 'log' ) { + $this->y2scale = new LogScale($aY2Min,$aY2Max); + } + else { + JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)"); + } + + $this->y2axis = new Axis($this->img,$this->y2scale); + $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT); + $this->y2axis->SetLabelSide(SIDE_RIGHT); + $this->y2axis->SetPos('max'); + $this->y2axis->SetTitleSide(SIDE_RIGHT); + + // Deafult position is the max x-value + $this->y2grid = new Grid($this->y2axis); + + if ($this->graph_theme) { + $this->graph_theme->ApplyGraph($this); + } + } + + // Set the delta position (in pixels) between the multiple Y-axis + function SetYDeltaDist($aDist) { + $this->iYAxisDeltaPos = $aDist; + } + + // Specify secondary Y scale + function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) { + + if( $aAxisType == 'lin' ) { + $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax); + } + elseif( $aAxisType == 'int' ) { + $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax); + $this->ynscale[$aN]->SetIntScale(); + } + elseif( $aAxisType == 'log' ) { + $this->ynscale[$aN] = new LogScale($aYMin,$aYMax); + } + else { + JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)"); + } + + $this->ynaxis[$aN] = new Axis($this->img,$this->ynscale[$aN]); + $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT); + $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT); + + if ($this->graph_theme) { + $this->graph_theme->ApplyGraph($this); + } + } + + // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse' + // The dividing factor have been determined heuristically according to my aesthetic + // sense (or lack off) y.m.m.v ! + function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) { + $this->xtick_factor=30; + $this->ytick_factor=25; + switch( $aYDensity ) { + case TICKD_DENSE: + $this->ytick_factor=12; + break; + case TICKD_NORMAL: + $this->ytick_factor=25; + break; + case TICKD_SPARSE: + $this->ytick_factor=40; + break; + case TICKD_VERYSPARSE: + $this->ytick_factor=100; + break; + default: + JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy"); + } + switch( $aXDensity ) { + case TICKD_DENSE: + $this->xtick_factor=15; + break; + case TICKD_NORMAL: + $this->xtick_factor=30; + break; + case TICKD_SPARSE: + $this->xtick_factor=45; + break; + case TICKD_VERYSPARSE: + $this->xtick_factor=60; + break; + default: + JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx"); + } + } + + + // Get a string of all image map areas + function GetCSIMareas() { + if( !$this->iHasStroked ) { + $this->Stroke(_CSIM_SPECIALFILE); + } + + $csim = $this->title->GetCSIMAreas(); + $csim .= $this->subtitle->GetCSIMAreas(); + $csim .= $this->subsubtitle->GetCSIMAreas(); + $csim .= $this->legend->GetCSIMAreas(); + + if( $this->y2axis != NULL ) { + $csim .= $this->y2axis->title->GetCSIMAreas(); + } + + if( $this->texts != null ) { + $n = count($this->texts); + for($i=0; $i < $n; ++$i ) { + $csim .= $this->texts[$i]->GetCSIMAreas(); + } + } + + if( $this->y2texts != null && $this->y2scale != null ) { + $n = count($this->y2texts); + for($i=0; $i < $n; ++$i ) { + $csim .= $this->y2texts[$i]->GetCSIMAreas(); + } + } + + if( $this->yaxis != null && $this->xaxis != null ) { + $csim .= $this->yaxis->title->GetCSIMAreas(); + $csim .= $this->xaxis->title->GetCSIMAreas(); + } + + $n = count($this->plots); + for( $i=0; $i < $n; ++$i ) { + $csim .= $this->plots[$i]->GetCSIMareas(); + } + + $n = count($this->y2plots); + for( $i=0; $i < $n; ++$i ) { + $csim .= $this->y2plots[$i]->GetCSIMareas(); + } + + $n = count($this->ynaxis); + for( $i=0; $i < $n; ++$i ) { + $m = count($this->ynplots[$i]); + for($j=0; $j < $m; ++$j ) { + $csim .= $this->ynplots[$i][$j]->GetCSIMareas(); + } + } + + if($this->iTables != null) { + $n = count($this->iTables); + for ($i = 0; $i < $n; ++$i) { + $csim .= $this->iTables[$i]->GetCSIMareas(); + } + } + + return $csim; + } + + // Get a complete .. tag for the final image map + function GetHTMLImageMap($aMapName) { + $im = "\n"; + $im .= $this->GetCSIMareas(); + $im .= ""; + return $im; + } + + function CheckCSIMCache($aCacheName,$aTimeOut=60) { + global $_SERVER; + + if( $aCacheName=='auto' ) { + $aCacheName=basename($_SERVER['PHP_SELF']); + } + + $urlarg = $this->GetURLArguments(); + $this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg; + $this->csimcachetimeout = $aTimeOut; + + // First determine if we need to check for a cached version + // This differs from the standard cache in the sense that the + // image and CSIM map HTML file is written relative to the directory + // the script executes in and not the specified cache directory. + // The reason for this is that the cache directory is not necessarily + // accessible from the HTTP server. + if( $this->csimcachename != '' ) { + $dir = dirname($this->csimcachename); + $base = basename($this->csimcachename); + $base = strtok($base,'.'); + $suffix = strtok('.'); + $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html'; + $baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format; + + $timedout=false; + // Does it exist at all ? + + if( file_exists($basecsim) && file_exists($baseimg) ) { + // Check that it hasn't timed out + $diff=time()-filemtime($basecsim); + if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) { + $timedout=true; + @unlink($basecsim); + @unlink($baseimg); + } + else { + if ($fh = @fopen($basecsim, "r")) { + fpassthru($fh); + return true; + } + else { + JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading."); + } + } + } + } + return false; + } + + // Build the argument string to be used with the csim images + static function GetURLArguments($aAddRecursiveBlocker=false) { + + if( $aAddRecursiveBlocker ) { + // This is a JPGRAPH internal defined that prevents + // us from recursively coming here again + $urlarg = _CSIM_DISPLAY.'=1'; + } + + // Now reconstruct any user URL argument + reset($_GET); + foreach ($_GET as $key => $value) { + if( is_array($value) ) { + foreach ( $value as $k => $v ) { + $urlarg .= '&'.$key.'%5B'.$k.'%5D='.urlencode($v); + } + } + else { + $urlarg .= '&'.$key.'='.urlencode($value); + } + } + + // It's not ideal to convert POST argument to GET arguments + // but there is little else we can do. One idea for the + // future might be recreate the POST header in case. + reset($_POST); + foreach ($_POST as $key => $value) { + if( is_array($value) ) { + foreach ( $value as $k => $v ) { + $urlarg .= '&'.$key.'%5B'.$k.'%5D='.urlencode($v); + } + } + else { + $urlarg .= '&'.$key.'='.urlencode($value); + } + } + + return $urlarg; + } + + function SetCSIMImgAlt($aAlt) { + $this->iCSIMImgAlt = $aAlt; + } + + function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) { + if( $aCSIMName=='' ) { + // create a random map name + srand ((double) microtime() * 1000000); + $r = rand(0,100000); + $aCSIMName='__mapname'.$r.'__'; + } + + if( $aScriptName=='auto' ) { + $aScriptName=basename($_SERVER['PHP_SELF']); + } + + $urlarg = $this->GetURLArguments(true); + + if( empty($_GET[_CSIM_DISPLAY]) ) { + // First determine if we need to check for a cached version + // This differs from the standard cache in the sense that the + // image and CSIM map HTML file is written relative to the directory + // the script executes in and not the specified cache directory. + // The reason for this is that the cache directory is not necessarily + // accessible from the HTTP server. + if( $this->csimcachename != '' ) { + $dir = dirname($this->csimcachename); + $base = basename($this->csimcachename); + $base = strtok($base,'.'); + $suffix = strtok('.'); + $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html'; + $baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format; + + // Check that apache can write to directory specified + + if( file_exists($dir) && !is_writeable($dir) ) { + JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.'); + } + + // Make sure directory exists + $this->cache->MakeDirs($dir); + + // Write the image file + $this->Stroke(CSIMCACHE_DIR.$baseimg); + + // Construct wrapper HTML and write to file and send it back to browser + + // In the src URL we must replace the '?' with its encoding to prevent the arguments + // to be converted to real arguments. + $tmp = str_replace('?','%3f',$baseimg); + $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n". + 'img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n"; + + if($fh = @fopen($basecsim,'w') ) { + fwrite($fh,$htmlwrap); + fclose($fh); + echo $htmlwrap; + } + else { + JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions."); + } + } + else { + + if( $aScriptName=='' ) { + 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().'); + } + echo $this->GetHTMLImageMap($aCSIMName) . $this->GetCSIMImgHTML($aCSIMName, $aScriptName, $aBorder); + } + } + else { + $this->Stroke(); + } + } + + function StrokeCSIMImage() { + if( @$_GET[_CSIM_DISPLAY] == 1 ) { + $this->Stroke(); + } + } + + function GetCSIMImgHTML($aCSIMName, $aScriptName='auto', $aBorder=0 ) { + if( $aScriptName=='auto' ) { + $aScriptName=basename($_SERVER['PHP_SELF']); + } + $urlarg = $this->GetURLArguments(true); + return "\"".$this-iCSIMImgAlt."\" />\n"; + } + + function GetTextsYMinMax($aY2=false) { + if( $aY2 ) { + $txts = $this->y2texts; + } + else { + $txts = $this->texts; + } + $n = is_array($txts) ? count($txts) : 0; + $min=null; + $max=null; + for( $i=0; $i < $n; ++$i ) { + if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) { + if( $min === null ) { + $min = $max = $txts[$i]->iScalePosY ; + } + else { + $min = min($min,$txts[$i]->iScalePosY); + $max = max($max,$txts[$i]->iScalePosY); + } + } + } + if( $min !== null ) { + return array($min,$max); + } + else { + return null; + } + } + + function GetTextsXMinMax($aY2=false) { + if( $aY2 ) { + $txts = $this->y2texts; + } + else { + $txts = $this->texts; + } + $n = is_array($txts) ? count($txts) : 0; + $min=null; + $max=null; + for( $i=0; $i < $n; ++$i ) { + if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) { + if( $min === null ) { + $min = $max = $txts[$i]->iScalePosX ; + } + else { + $min = min($min,$txts[$i]->iScalePosX); + $max = max($max,$txts[$i]->iScalePosX); + } + } + } + if( $min !== null ) { + return array($min,$max); + } + else { + return null; + } + } + + function GetXMinMax() { + + list($min,$ymin) = $this->plots[0]->Min(); + list($max,$ymax) = $this->plots[0]->Max(); + + $i=0; + // Some plots, e.g. PlotLine should not affect the scale + // and will return (null,null). We should ignore those + // values. + while( ($min===null || $max === null) && ($i < count($this->plots)-1) ) { + ++$i; + list($min,$ymin) = $this->plots[$i]->Min(); + list($max,$ymax) = $this->plots[$i]->Max(); + } + + foreach( $this->plots as $p ) { + list($xmin,$ymin) = $p->Min(); + list($xmax,$ymax) = $p->Max(); + + if( $xmin !== null && $xmax !== null ) { + $min = Min($xmin,$min); + $max = Max($xmax,$max); + } + } + + if( $this->y2axis != null ) { + foreach( $this->y2plots as $p ) { + list($xmin,$ymin) = $p->Min(); + list($xmax,$ymax) = $p->Max(); + if( $xmin !== null && $xmax !== null ) { + $min = Min($xmin, $min); + $max = Max($xmax, $max); + } + } + } + + $n = count($this->ynaxis); + for( $i=0; $i < $n; ++$i ) { + if( $this->ynaxis[$i] != null) { + foreach( $this->ynplots[$i] as $p ) { + list($xmin,$ymin) = $p->Min(); + list($xmax,$ymax) = $p->Max(); + if( $xmin !== null && $xmax !== null ) { + $min = Min($xmin, $min); + $max = Max($xmax, $max); + } + } + } + } + return array($min,$max); + } + + function AdjustMarginsForTitles() { + $totrequired = + ($this->title->t != '' + ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 * SUPERSAMPLING_SCALE + : 0 ) + + ($this->subtitle->t != '' + ? $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 * SUPERSAMPLING_SCALE + : 0 ) + + ($this->subsubtitle->t != '' + ? $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 * SUPERSAMPLING_SCALE + : 0 ) ; + + $btotrequired = 0; + if($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels ) { + // Minimum bottom margin + if( $this->xaxis->title->t != '' ) { + if( $this->img->a == 90 ) { + $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 7 ; + } + else { + $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 7 ; + } + } + else { + $btotrequired = 0; + } + + if( $this->img->a == 90 ) { + $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style, + $this->yaxis->font_size); + $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle); + } + else { + $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style, + $this->xaxis->font_size); + $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle); + } + + $btotrequired += $lh + 6; + } + + if( $this->img->a == 90 ) { + // DO Nothing. It gets too messy to do this properly for 90 deg... + } + else{ + // need more top margin + if( $this->img->top_margin < $totrequired ) { + $this->SetMargin( + $this->img->raw_left_margin, + $this->img->raw_right_margin, + $totrequired / SUPERSAMPLING_SCALE, + $this->img->raw_bottom_margin + ); + } + + // need more bottom margin + if( $this->img->bottom_margin < $btotrequired ) { + $this->SetMargin( + $this->img->raw_left_margin, + $this->img->raw_right_margin, + $this->img->raw_top_margin, + $btotrequired / SUPERSAMPLING_SCALE + ); + } + } + } + + function StrokeStore($aStrokeFileName) { + // Get the handler to prevent the library from sending the + // image to the browser + $ih = $this->Stroke(_IMG_HANDLER); + + // Stroke it to a file + $this->img->Stream($aStrokeFileName); + + // Send it back to browser + $this->img->Headers(); + $this->img->Stream(); + } + + function doAutoscaleXAxis() { + //Check if we should autoscale x-axis + if( !$this->xscale->IsSpecified() ) { + if( substr($this->axtype,0,4) == "text" ) { + $max=0; + $n = count($this->plots); + for($i=0; $i < $n; ++$i ) { + $p = $this->plots[$i]; + // We need some unfortunate sub class knowledge here in order + // to increase number of data points in case it is a line plot + // which has the barcenter set. If not it could mean that the + // last point of the data is outside the scale since the barcenter + // settings means that we will shift the entire plot half a tick step + // to the right in oder to align with the center of the bars. + if( class_exists('BarPlot',false) ) { + $cl = strtolower(get_class($p)); + if( (class_exists('BarPlot',false) && ($p instanceof BarPlot)) || empty($p->barcenter) ) { + $max=max($max,$p->numpoints-1); + } + else { + $max=max($max,$p->numpoints); + } + } + else { + if( empty($p->barcenter) ) { + $max=max($max,$p->numpoints-1); + } + else { + $max=max($max,$p->numpoints); + } + } + } + $min=0; + if( $this->y2axis != null ) { + foreach( $this->y2plots as $p ) { + $max=max($max,$p->numpoints-1); + } + } + $n = count($this->ynaxis); + for( $i=0; $i < $n; ++$i ) { + if( $this->ynaxis[$i] != null) { + foreach( $this->ynplots[$i] as $p ) { + $max=max($max,$p->numpoints-1); + } + } + } + + $this->xscale->Update($this->img,$min,$max); + $this->xscale->ticks->Set($this->xaxis->tick_step,1); + $this->xscale->ticks->SupressMinorTickMarks(); + } + else { + list($min,$max) = $this->GetXMinMax(); + + $lres = $this->GetLinesXMinMax($this->lines); + if( $lres ) { + list($linmin,$linmax) = $lres ; + $min = min($min,$linmin); + $max = max($max,$linmax); + } + + $lres = $this->GetLinesXMinMax($this->y2lines); + if( $lres ) { + list($linmin,$linmax) = $lres ; + $min = min($min,$linmin); + $max = max($max,$linmax); + } + + $tres = $this->GetTextsXMinMax(); + if( $tres ) { + list($tmin,$tmax) = $tres ; + $min = min($min,$tmin); + $max = max($max,$tmax); + } + + $tres = $this->GetTextsXMinMax(true); + if( $tres ) { + list($tmin,$tmax) = $tres ; + $min = min($min,$tmin); + $max = max($max,$tmax); + } + + $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor)); + } + + //Adjust position of y-axis and y2-axis to minimum/maximum of x-scale + if( !is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos) ) { + $this->yaxis->SetPos($this->xscale->GetMinVal()); + } + } + elseif( $this->xscale->IsSpecified() && + ( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) { + // The tick calculation will use the user suplied min/max values to determine + // the ticks. If auto_ticks is false the exact user specifed min and max + // values will be used for the scale. + // If auto_ticks is true then the scale might be slightly adjusted + // so that the min and max values falls on an even major step. + $min = $this->xscale->scale[0]; + $max = $this->xscale->scale[1]; + $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor),false); + + // Now make sure we show enough precision to accurate display the + // labels. If this is not done then the user might end up with + // a scale that might actually start with, say 13.5, butdue to rounding + // the scale label will ony show 14. + if( abs(floor($min)-$min) > 0 ) { + + // If the user has set a format then we bail out + if( $this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '' ) { + $this->xscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; + } + } + } + + // Position the optional Y2 and Yn axis to the rightmost position of the x-axis + if( $this->y2axis != null ) { + if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) { + $this->y2axis->SetPos($this->xscale->GetMaxVal()); + } + $this->y2axis->SetTitleSide(SIDE_RIGHT); + } + + $n = count($this->ynaxis); + $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0; + for( $i=0; $i < $n; ++$i ) { + if( $this->ynaxis[$i] != null ) { + if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) { + $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal()); + $this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj); + } + $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT); + } + } + } + + + function doAutoScaleYnAxis() { + + if( $this->y2scale != null) { + if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) { + list($min,$max) = $this->GetPlotsYMinMax($this->y2plots); + + $lres = $this->GetLinesYMinMax($this->y2lines); + if( is_array($lres) ) { + list($linmin,$linmax) = $lres ; + $min = min($min,$linmin); + $max = max($max,$linmax); + } + $tres = $this->GetTextsYMinMax(true); + if( is_array($tres) ) { + list($tmin,$tmax) = $tres ; + $min = min($min,$tmin); + $max = max($max,$tmax); + } + $this->y2scale->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor); + } + elseif( $this->y2scale->IsSpecified() && ( $this->y2scale->auto_ticks || !$this->y2scale->ticks->IsSpecified()) ) { + // The tick calculation will use the user suplied min/max values to determine + // the ticks. If auto_ticks is false the exact user specifed min and max + // values will be used for the scale. + // If auto_ticks is true then the scale might be slightly adjusted + // so that the min and max values falls on an even major step. + $min = $this->y2scale->scale[0]; + $max = $this->y2scale->scale[1]; + $this->y2scale->AutoScale($this->img,$min,$max, + $this->img->plotheight/$this->ytick_factor, + $this->y2scale->auto_ticks); + + // Now make sure we show enough precision to accurate display the + // labels. If this is not done then the user might end up with + // a scale that might actually start with, say 13.5, butdue to rounding + // the scale label will ony show 14. + if( abs(floor($min)-$min) > 0 ) { + // If the user has set a format then we bail out + if( $this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '' ) { + $this->y2scale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; + } + } + + } + } + + + // + // Autoscale the extra Y-axises + // + $n = count($this->ynaxis); + for( $i=0; $i < $n; ++$i ) { + if( $this->ynscale[$i] != null) { + if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) { + list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]); + $this->ynscale[$i]->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor); + } + elseif( $this->ynscale[$i]->IsSpecified() && ( $this->ynscale[$i]->auto_ticks || !$this->ynscale[$i]->ticks->IsSpecified()) ) { + // The tick calculation will use the user suplied min/max values to determine + // the ticks. If auto_ticks is false the exact user specifed min and max + // values will be used for the scale. + // If auto_ticks is true then the scale might be slightly adjusted + // so that the min and max values falls on an even major step. + $min = $this->ynscale[$i]->scale[0]; + $max = $this->ynscale[$i]->scale[1]; + $this->ynscale[$i]->AutoScale($this->img,$min,$max, + $this->img->plotheight/$this->ytick_factor, + $this->ynscale[$i]->auto_ticks); + + // Now make sure we show enough precision to accurate display the + // labels. If this is not done then the user might end up with + // a scale that might actually start with, say 13.5, butdue to rounding + // the scale label will ony show 14. + if( abs(floor($min)-$min) > 0 ) { + // If the user has set a format then we bail out + if( $this->ynscale[$i]->ticks->label_formatstr == '' && $this->ynscale[$i]->ticks->label_dateformatstr == '' ) { + $this->ynscale[$i]->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; + } + } + } + } + } + } + + function doAutoScaleYAxis() { + + //Check if we should autoscale y-axis + if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) { + list($min,$max) = $this->GetPlotsYMinMax($this->plots); + $lres = $this->GetLinesYMinMax($this->lines); + if( is_array($lres) ) { + list($linmin,$linmax) = $lres ; + $min = min($min,$linmin); + $max = max($max,$linmax); + } + $tres = $this->GetTextsYMinMax(); + if( is_array($tres) ) { + list($tmin,$tmax) = $tres ; + $min = min($min,$tmin); + $max = max($max,$tmax); + } + $this->yscale->AutoScale($this->img,$min,$max, + $this->img->plotheight/$this->ytick_factor); + } + elseif( $this->yscale->IsSpecified() && ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) { + // The tick calculation will use the user suplied min/max values to determine + // the ticks. If auto_ticks is false the exact user specifed min and max + // values will be used for the scale. + // If auto_ticks is true then the scale might be slightly adjusted + // so that the min and max values falls on an even major step. + $min = $this->yscale->scale[0]; + $max = $this->yscale->scale[1]; + $this->yscale->AutoScale($this->img,$min,$max, + $this->img->plotheight/$this->ytick_factor, + $this->yscale->auto_ticks); + + // Now make sure we show enough precision to accurate display the + // labels. If this is not done then the user might end up with + // a scale that might actually start with, say 13.5, butdue to rounding + // the scale label will ony show 14. + if( abs(floor($min)-$min) > 0 ) { + + // If the user has set a format then we bail out + if( $this->yscale->ticks->label_formatstr == '' && $this->yscale->ticks->label_dateformatstr == '' ) { + $this->yscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; + } + } + } + + } + + function InitScaleConstants() { + // Setup scale constants + if( $this->yscale ) $this->yscale->InitConstants($this->img); + if( $this->xscale ) $this->xscale->InitConstants($this->img); + if( $this->y2scale ) $this->y2scale->InitConstants($this->img); + + $n=count($this->ynscale); + for($i=0; $i < $n; ++$i) { + if( $this->ynscale[$i] ) { + $this->ynscale[$i]->InitConstants($this->img); + } + } + } + + function doPrestrokeAdjustments() { + + // Do any pre-stroke adjustment that is needed by the different plot types + // (i.e bar plots want's to add an offset to the x-labels etc) + for($i=0; $i < count($this->plots) ; ++$i ) { + $this->plots[$i]->PreStrokeAdjust($this); + $this->plots[$i]->DoLegend($this); + } + + // Any plots on the second Y scale? + if( $this->y2scale != null ) { + for($i=0; $iy2plots) ; ++$i ) { + $this->y2plots[$i]->PreStrokeAdjust($this); + $this->y2plots[$i]->DoLegend($this); + } + } + + // Any plots on the extra Y axises? + $n = count($this->ynaxis); + for($i=0; $i<$n ; ++$i ) { + if( $this->ynplots == null || $this->ynplots[$i] == null) { + JpGraphError::RaiseL(25032,$i);//("No plots for Y-axis nbr:$i"); + } + $m = count($this->ynplots[$i]); + for($j=0; $j < $m; ++$j ) { + $this->ynplots[$i][$j]->PreStrokeAdjust($this); + $this->ynplots[$i][$j]->DoLegend($this); + } + } + } + + function StrokeBands($aDepth,$aCSIM) { + // Stroke bands + if( $this->bands != null && !$aCSIM) { + for($i=0; $i < count($this->bands); ++$i) { + // Stroke all bands that asks to be in the background + if( $this->bands[$i]->depth == $aDepth ) { + $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale); + } + } + } + + if( $this->y2bands != null && $this->y2scale != null && !$aCSIM ) { + for($i=0; $i < count($this->y2bands); ++$i) { + // Stroke all bands that asks to be in the foreground + if( $this->y2bands[$i]->depth == $aDepth ) { + $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale); + } + } + } + } + + + // Stroke the graph + // $aStrokeFileName If != "" the image will be written to this file and NOT + // streamed back to the browser + function Stroke($aStrokeFileName='') { + // Fist make a sanity check that user has specified a scale + if( empty($this->yscale) ) { + JpGraphError::RaiseL(25031);//('You must specify what scale to use with a call to Graph::SetScale().'); + } + + // Start by adjusting the margin so that potential titles will fit. + $this->AdjustMarginsForTitles(); + + // Give the plot a chance to do any scale adjuments the individual plots + // wants to do. Right now this is only used by the contour plot to set scale + // limits + for($i=0; $i < count($this->plots) ; ++$i ) { + $this->plots[$i]->PreScaleSetup($this); + } + + // Init scale constants that are used to calculate the transformation from + // world to pixel coordinates + $this->InitScaleConstants(); + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // a best we can. Therefor you will see a lot of tests !$_csim in the + // code below. + $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); + + // If we are called the second time (perhaps the user has called GetHTMLImageMap() + // himself then the legends have alsready been populated once in order to get the + // CSIM coordinats. Since we do not want the legends to be populated a second time + // we clear the legends + $this->legend->Clear(); + + // We need to know if we have stroked the plot in the + // GetCSIMareas. Otherwise the CSIM hasn't been generated + // and in the case of GetCSIM called before stroke to generate + // CSIM without storing an image to disk GetCSIM must call Stroke. + $this->iHasStroked = true; + + // Setup pre-stroked adjustments and Legends + $this->doPrestrokeAdjustments(); + + if ($this->graph_theme) { + $this->graph_theme->PreStrokeApply($this); + } + + // Bail out if any of the Y-axis not been specified and + // has no plots. (This means it is impossible to do autoscaling and + // no other scale was given so we can't possible draw anything). If you use manual + // scaling you also have to supply the tick steps as well. + if( (!$this->yscale->IsSpecified() && count($this->plots)==0) || + ($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) { + //$e = "n=".count($this->y2plots)."\n"; + // $e = "Can't draw unspecified Y-scale.
\nYou have either:
\n"; + // $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots
\n"; + // $e .= "2. Specified a scale manually but have forgot to specify the tick steps"; + JpGraphError::RaiseL(25026); + } + + // Bail out if no plots and no specified X-scale + if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) ) { + JpGraphError::RaiseL(25034);//("JpGraph: Can't draw unspecified X-scale.
No plots.
"); + } + + // Autoscale the normal Y-axis + $this->doAutoScaleYAxis(); + + // Autoscale all additiopnal y-axis + $this->doAutoScaleYnAxis(); + + // Autoscale the regular x-axis and position the y-axis properly + $this->doAutoScaleXAxis(); + + // If we have a negative values and x-axis position is at 0 + // we need to supress the first and possible the last tick since + // they will be drawn on top of the y-axis (and possible y2 axis) + // The test below might seem strange the reasone being that if + // the user hasn't specified a value for position this will not + // be set until we do the stroke for the axis so as of now it + // is undefined. + // For X-text scale we ignore all this since the tick are usually + // much further in and not close to the Y-axis. Hence the test + // for 'text' + if( ($this->yaxis->pos==$this->xscale->GetMinVal() || (is_string($this->yaxis->pos) && $this->yaxis->pos=='min')) && + !is_numeric($this->xaxis->pos) && $this->yscale->GetMinVal() < 0 && + substr($this->axtype,0,4) != 'text' && $this->xaxis->pos != 'min' ) { + + //$this->yscale->ticks->SupressZeroLabel(false); + $this->xscale->ticks->SupressFirst(); + if( $this->y2axis != null ) { + $this->xscale->ticks->SupressLast(); + } + } + elseif( !is_numeric($this->yaxis->pos) && $this->yaxis->pos=='max' ) { + $this->xscale->ticks->SupressLast(); + } + + if( !$_csim ) { + $this->StrokePlotArea(); + if( $this->iIconDepth == DEPTH_BACK ) { + $this->StrokeIcons(); + } + } + $this->StrokeAxis(false); + + // Stroke colored bands + $this->StrokeBands(DEPTH_BACK,$_csim); + + if( $this->grid_depth == DEPTH_BACK && !$_csim) { + $this->ygrid->Stroke(); + $this->xgrid->Stroke(); + } + + // Stroke Y2-axis + if( $this->y2axis != null && !$_csim) { + $this->y2axis->Stroke($this->xscale); + $this->y2grid->Stroke(); + } + + // Stroke yn-axis + $n = count($this->ynaxis); + for( $i=0; $i < $n; ++$i ) { + $this->ynaxis[$i]->Stroke($this->xscale); + } + + $oldoff=$this->xscale->off; + if( substr($this->axtype,0,4) == 'text' ) { + if( $this->text_scale_abscenteroff > -1 ) { + // For a text scale the scale factor is the number of pixel per step. + // Hence we can use the scale factor as a substitute for number of pixels + // per major scale step and use that in order to adjust the offset so that + // an object of width "abscenteroff" becomes centered. + $this->xscale->off += round($this->xscale->scale_factor/2)-round($this->text_scale_abscenteroff/2); + } + else { + $this->xscale->off += ceil($this->xscale->scale_factor*$this->text_scale_off*$this->xscale->ticks->minor_step); + } + } + + if( $this->iDoClipping ) { + $oldimage = $this->img->CloneCanvasH(); + } + + if( ! $this->y2orderback ) { + // Stroke all plots for Y1 axis + for($i=0; $i < count($this->plots); ++$i) { + $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale); + $this->plots[$i]->StrokeMargin($this->img); + } + } + + // Stroke all plots for Y2 axis + if( $this->y2scale != null ) { + for($i=0; $i< count($this->y2plots); ++$i ) { + $this->y2plots[$i]->Stroke($this->img,$this->xscale,$this->y2scale); + } + } + + if( $this->y2orderback ) { + // Stroke all plots for Y1 axis + for($i=0; $i < count($this->plots); ++$i) { + $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale); + $this->plots[$i]->StrokeMargin($this->img); + } + } + + $n = count($this->ynaxis); + for( $i=0; $i < $n; ++$i ) { + $m = count($this->ynplots[$i]); + for( $j=0; $j < $m; ++$j ) { + $this->ynplots[$i][$j]->Stroke($this->img,$this->xscale,$this->ynscale[$i]); + $this->ynplots[$i][$j]->StrokeMargin($this->img); + } + } + + if( $this->iIconDepth == DEPTH_FRONT) { + $this->StrokeIcons(); + } + + if( $this->iDoClipping ) { + // Clipping only supports graphs at 0 and 90 degrees + if( $this->img->a == 0 ) { + $this->img->CopyCanvasH($oldimage,$this->img->img, + $this->img->left_margin,$this->img->top_margin, + $this->img->left_margin,$this->img->top_margin, + $this->img->plotwidth+1,$this->img->plotheight); + } + elseif( $this->img->a == 90 ) { + $adj = ($this->img->height - $this->img->width)/2; + $this->img->CopyCanvasH($oldimage,$this->img->img, + $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, + $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, + $this->img->plotheight+1,$this->img->plotwidth); + } + else { + 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.'); + } + $this->img->Destroy(); + $this->img->SetCanvasH($oldimage); + } + + $this->xscale->off=$oldoff; + + if( $this->grid_depth == DEPTH_FRONT && !$_csim ) { + $this->ygrid->Stroke(); + $this->xgrid->Stroke(); + } + + // Stroke colored bands + $this->StrokeBands(DEPTH_FRONT,$_csim); + + // Finally draw the axis again since some plots may have nagged + // the axis in the edges. + if( !$_csim ) { + $this->StrokeAxis(); + } + + if( $this->y2scale != null && !$_csim ) { + $this->y2axis->Stroke($this->xscale,false); + } + + if( !$_csim ) { + $this->StrokePlotBox(); + } + + // The titles and legends never gets rotated so make sure + // that the angle is 0 before stroking them + $aa = $this->img->SetAngle(0); + $this->StrokeTitles(); + $this->footer->Stroke($this->img); + $this->legend->Stroke($this->img); + $this->img->SetAngle($aa); + $this->StrokeTexts(); + $this->StrokeTables(); + + if( !$_csim ) { + + $this->img->SetAngle($aa); + + // Draw an outline around the image map + if(_JPG_DEBUG) { + $this->DisplayClientSideaImageMapAreas(); + } + + // Should we do any final image transformation + if( $this->iImgTrans ) { + if( !class_exists('ImgTrans',false) ) { + require_once('jpgraph_imgtrans.php'); + //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.'); + } + + $tform = new ImgTrans($this->img->img); + $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, + $this->iImgTransDirection,$this->iImgTransHighQ, + $this->iImgTransMinSize,$this->iImgTransFillColor, + $this->iImgTransBorder); + } + + // If the filename is given as the special "__handle" + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); + } + } + } + + function SetAxisLabelBackground($aType,$aXFColor='lightgray',$aXColor='black',$aYFColor='lightgray',$aYColor='black') { + $this->iAxisLblBgType = $aType; + $this->iXAxisLblBgFillColor = $aXFColor; + $this->iXAxisLblBgColor = $aXColor; + $this->iYAxisLblBgFillColor = $aYFColor; + $this->iYAxisLblBgColor = $aYColor; + } + + function StrokeAxisLabelBackground() { + // Types + // 0 = No background + // 1 = Only X-labels, length of axis + // 2 = Only Y-labels, length of axis + // 3 = As 1 but extends to width of graph + // 4 = As 2 but extends to height of graph + // 5 = Combination of 3 & 4 + // 6 = Combination of 1 & 2 + + $t = $this->iAxisLblBgType ; + if( $t < 1 ) return; + + // Stroke optional X-axis label background color + if( $t == 1 || $t == 3 || $t == 5 || $t == 6 ) { + $this->img->PushColor($this->iXAxisLblBgFillColor); + if( $t == 1 || $t == 6 ) { + $xl = $this->img->left_margin; + $yu = $this->img->height - $this->img->bottom_margin + 1; + $xr = $this->img->width - $this->img->right_margin ; + $yl = $this->img->height-1-$this->frame_weight; + } + else { // t==3 || t==5 + $xl = $this->frame_weight; + $yu = $this->img->height - $this->img->bottom_margin + 1; + $xr = $this->img->width - 1 - $this->frame_weight; + $yl = $this->img->height-1-$this->frame_weight; + } + + $this->img->FilledRectangle($xl,$yu,$xr,$yl); + $this->img->PopColor(); + + // Check if we should add the vertical lines at left and right edge + if( $this->iXAxisLblBgColor !== '' ) { + // Hardcode to one pixel wide + $this->img->SetLineWeight(1); + $this->img->PushColor($this->iXAxisLblBgColor); + if( $t == 1 || $t == 6 ) { + $this->img->Line($xl,$yu,$xl,$yl); + $this->img->Line($xr,$yu,$xr,$yl); + } + else { + $xl = $this->img->width - $this->img->right_margin ; + $this->img->Line($xl,$yu-1,$xr,$yu-1); + } + $this->img->PopColor(); + } + } + + if( $t == 2 || $t == 4 || $t == 5 || $t == 6 ) { + $this->img->PushColor($this->iYAxisLblBgFillColor); + if( $t == 2 || $t == 6 ) { + $xl = $this->frame_weight; + $yu = $this->frame_weight+$this->img->top_margin; + $xr = $this->img->left_margin - 1; + $yl = $this->img->height - $this->img->bottom_margin + 1; + } + else { + $xl = $this->frame_weight; + $yu = $this->frame_weight; + $xr = $this->img->left_margin - 1; + $yl = $this->img->height-1-$this->frame_weight; + } + + $this->img->FilledRectangle($xl,$yu,$xr,$yl); + $this->img->PopColor(); + + // Check if we should add the vertical lines at left and right edge + if( $this->iXAxisLblBgColor !== '' ) { + $this->img->PushColor($this->iXAxisLblBgColor); + if( $t == 2 || $t == 6 ) { + $this->img->Line($xl,$yu-1,$xr,$yu-1); + $this->img->Line($xl,$yl-1,$xr,$yl-1); + } + else { + $this->img->Line($xr+1,$yu,$xr+1,$this->img->top_margin); + } + $this->img->PopColor(); + } + + } + } + + function StrokeAxis($aStrokeLabels=true) { + + if( $aStrokeLabels ) { + $this->StrokeAxisLabelBackground(); + } + + // Stroke axis + if( $this->iAxisStyle != AXSTYLE_SIMPLE ) { + switch( $this->iAxisStyle ) { + case AXSTYLE_BOXIN : + $toppos = SIDE_DOWN; + $bottompos = SIDE_UP; + $leftpos = SIDE_RIGHT; + $rightpos = SIDE_LEFT; + break; + case AXSTYLE_BOXOUT : + $toppos = SIDE_UP; + $bottompos = SIDE_DOWN; + $leftpos = SIDE_LEFT; + $rightpos = SIDE_RIGHT; + break; + case AXSTYLE_YBOXIN: + $toppos = FALSE; + $bottompos = SIDE_UP; + $leftpos = SIDE_RIGHT; + $rightpos = SIDE_LEFT; + break; + case AXSTYLE_YBOXOUT: + $toppos = FALSE; + $bottompos = SIDE_DOWN; + $leftpos = SIDE_LEFT; + $rightpos = SIDE_RIGHT; + break; + default: + JpGRaphError::RaiseL(25036,$this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle); + break; + } + + // By default we hide the first label so it doesn't cross the + // Y-axis in case the positon hasn't been set by the user. + // However, if we use a box we always want the first value + // displayed so we make sure it will be displayed. + $this->xscale->ticks->SupressFirst(false); + + // Now draw the bottom X-axis + $this->xaxis->SetPos('min'); + $this->xaxis->SetLabelSide(SIDE_DOWN); + $this->xaxis->scale->ticks->SetSide($bottompos); + $this->xaxis->Stroke($this->yscale,$aStrokeLabels); + + if( $toppos !== FALSE ) { + // We also want a top X-axis + $this->xaxis = $this->xaxis; + $this->xaxis->SetPos('max'); + $this->xaxis->SetLabelSide(SIDE_UP); + // No title for the top X-axis + if( $aStrokeLabels ) { + $this->xaxis->title->Set(''); + } + $this->xaxis->scale->ticks->SetSide($toppos); + $this->xaxis->Stroke($this->yscale,$aStrokeLabels); + } + + // Stroke the left Y-axis + $this->yaxis->SetPos('min'); + $this->yaxis->SetLabelSide(SIDE_LEFT); + $this->yaxis->scale->ticks->SetSide($leftpos); + $this->yaxis->Stroke($this->xscale,$aStrokeLabels); + + // Stroke the right Y-axis + $this->yaxis->SetPos('max'); + // No title for the right side + if( $aStrokeLabels ) { + $this->yaxis->title->Set(''); + } + $this->yaxis->SetLabelSide(SIDE_RIGHT); + $this->yaxis->scale->ticks->SetSide($rightpos); + $this->yaxis->Stroke($this->xscale,$aStrokeLabels); + } + else { + $this->xaxis->Stroke($this->yscale,$aStrokeLabels); + $this->yaxis->Stroke($this->xscale,$aStrokeLabels); + } + } + + + // Private helper function for backgound image + static function LoadBkgImage($aImgFormat='',$aFile='',$aImgStr='') { + if( $aImgStr != '' ) { + return Image::CreateFromString($aImgStr); + } + + // Remove case sensitivity and setup appropriate function to create image + // Get file extension. This should be the LAST '.' separated part of the filename + $e = explode('.',$aFile); + $ext = strtolower($e[count($e)-1]); + if ($ext == "jpeg") { + $ext = "jpg"; + } + + if( trim($ext) == '' ) { + $ext = 'png'; // Assume PNG if no extension specified + } + + if( $aImgFormat == '' ) { + $imgtag = $ext; + } + else { + $imgtag = $aImgFormat; + } + + $supported = imagetypes(); + if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) || + ( $ext == 'gif' && !($supported & IMG_GIF) ) || + ( $ext == 'png' && !($supported & IMG_PNG) ) || + ( $ext == 'bmp' && !($supported & IMG_WBMP) ) || + ( $ext == 'xpm' && !($supported & IMG_XPM) ) ) { + + JpGraphError::RaiseL(25037,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. '); + } + + + if( $imgtag == "jpg" || $imgtag == "jpeg") { + $f = "imagecreatefromjpeg"; + $imgtag = "jpg"; + } + else { + $f = "imagecreatefrom".$imgtag; + } + + // Compare specified image type and file extension + if( $imgtag != $ext ) { + //$t = "Background image seems to be of different type (has different file extension) than specified imagetype. Specified: '".$aImgFormat."'File: '".$aFile."'"; + JpGraphError::RaiseL(25038, $aImgFormat, $aFile); + } + + $img = @$f($aFile); + if( !$img ) { + JpGraphError::RaiseL(25039,$aFile);//(" Can't read background image: '".$aFile."'"); + } + return $img; + } + + function StrokePlotGrad() { + if( $this->plot_gradtype < 0 ) + return; + + $grad = new Gradient($this->img); + $xl = $this->img->left_margin; + $yt = $this->img->top_margin; + $xr = $xl + $this->img->plotwidth+1 ; + $yb = $yt + $this->img->plotheight ; + $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->plot_gradfrom,$this->plot_gradto,$this->plot_gradtype); + + } + + function StrokeBackgroundGrad() { + if( $this->bkg_gradtype < 0 ) + return; + + $grad = new Gradient($this->img); + if( $this->bkg_gradstyle == BGRAD_PLOT ) { + $xl = $this->img->left_margin; + $yt = $this->img->top_margin; + $xr = $xl + $this->img->plotwidth+1 ; + $yb = $yt + $this->img->plotheight ; + $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype); + } + else { + $xl = 0; + $yt = 0; + $xr = $xl + $this->img->width - 1; + $yb = $yt + $this->img->height - 1 ; + if( $this->doshadow ) { + $xr -= $this->shadow_width; + $yb -= $this->shadow_width; + } + if( $this->doframe ) { + $yt += $this->frame_weight; + $yb -= $this->frame_weight; + $xl += $this->frame_weight; + $xr -= $this->frame_weight; + } + $aa = $this->img->SetAngle(0); + $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype); + $aa = $this->img->SetAngle($aa); + } + } + + function StrokeFrameBackground() { + if( $this->background_image != '' && $this->background_cflag != '' ) { + JpGraphError::RaiseL(25040);//('It is not possible to specify both a background image and a background country flag.'); + } + if( $this->background_image != '' ) { + $bkgimg = $this->LoadBkgImage($this->background_image_format,$this->background_image); + } + elseif( $this->background_cflag != '' ) { + if( ! class_exists('FlagImages',false) ) { + JpGraphError::RaiseL(25041);//('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.'); + } + $fobj = new FlagImages(FLAGSIZE4); + $dummy=''; + $bkgimg = $fobj->GetImgByName($this->background_cflag,$dummy); + $this->background_image_mix = $this->background_cflag_mix; + $this->background_image_type = $this->background_cflag_type; + } + else { + return ; + } + + $bw = ImageSX($bkgimg); + $bh = ImageSY($bkgimg); + + // No matter what the angle is we always stroke the image and frame + // assuming it is 0 degree + $aa = $this->img->SetAngle(0); + + switch( $this->background_image_type ) { + case BGIMG_FILLPLOT: // Resize to just fill the plotarea + $this->FillMarginArea(); + $this->StrokeFrame(); + // Special case to hande 90 degree rotated graph corectly + if( $aa == 90 ) { + $this->img->SetAngle(90); + $this->FillPlotArea(); + $aa = $this->img->SetAngle(0); + $adj = ($this->img->height - $this->img->width)/2; + $this->img->CopyMerge($bkgimg, + $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, + 0,0, + $this->img->plotheight+1,$this->img->plotwidth, + $bw,$bh,$this->background_image_mix); + } + else { + $this->FillPlotArea(); + $this->img->CopyMerge($bkgimg, + $this->img->left_margin,$this->img->top_margin+1, + 0,0,$this->img->plotwidth+1,$this->img->plotheight, + $bw,$bh,$this->background_image_mix); + } + break; + case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit + $hadj=0; $vadj=0; + if( $this->doshadow ) { + $hadj = $this->shadow_width; + $vadj = $this->shadow_width; + } + $this->FillMarginArea(); + $this->FillPlotArea(); + $this->img->CopyMerge($bkgimg,0,0,0,0,$this->img->width-$hadj,$this->img->height-$vadj, + $bw,$bh,$this->background_image_mix); + $this->StrokeFrame(); + break; + case BGIMG_COPY: // Just copy the image from left corner, no resizing + $this->FillMarginArea(); + $this->FillPlotArea(); + $this->img->CopyMerge($bkgimg,0,0,0,0,$bw,$bh, + $bw,$bh,$this->background_image_mix); + $this->StrokeFrame(); + break; + case BGIMG_CENTER: // Center original image in the plot area + $this->FillMarginArea(); + $this->FillPlotArea(); + $centerx = round($this->img->plotwidth/2+$this->img->left_margin-$bw/2); + $centery = round($this->img->plotheight/2+$this->img->top_margin-$bh/2); + $this->img->CopyMerge($bkgimg,$centerx,$centery,0,0,$bw,$bh, + $bw,$bh,$this->background_image_mix); + $this->StrokeFrame(); + break; + case BGIMG_FREE: // Just copy the image to the specified location + $this->img->CopyMerge($bkgimg, + $this->background_image_xpos,$this->background_image_ypos, + 0,0,$bw,$bh,$bw,$bh,$this->background_image_mix); + $this->StrokeFrame(); // New + break; + default: + JpGraphError::RaiseL(25042);//(" Unknown background image layout"); + } + $this->img->SetAngle($aa); + } + + // Private + // Draw a frame around the image + function StrokeFrame() { + if( !$this->doframe ) return; + + if( $this->background_image_type <= 1 && ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_PLOT)) ) { + $c = $this->margin_color; + } + else { + $c = false; + } + + if( $this->doshadow ) { + $this->img->SetColor($this->frame_color); + $this->img->ShadowRectangle(0,0,$this->img->width,$this->img->height, + $c,$this->shadow_width,$this->shadow_color); + } + elseif( $this->framebevel ) { + if( $c ) { + $this->img->SetColor($this->margin_color); + $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1); + } + $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2, + $this->framebeveldepth, + $this->framebevelcolor1,$this->framebevelcolor2); + if( $this->framebevelborder ) { + $this->img->SetColor($this->framebevelbordercolor); + $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); + } + } + else { + $this->img->SetLineWeight($this->frame_weight); + if( $c ) { + $this->img->SetColor($this->margin_color); + $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1); + } + $this->img->SetColor($this->frame_color); + $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); + } + } + + function FillMarginArea() { + $hadj=0; $vadj=0; + if( $this->doshadow ) { + $hadj = $this->shadow_width; + $vadj = $this->shadow_width; + } + + $this->img->SetColor($this->margin_color); + $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->height-1-$vadj); + + $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->top_margin); + $this->img->FilledRectangle(0,$this->img->top_margin,$this->img->left_margin,$this->img->height-1-$hadj); + $this->img->FilledRectangle($this->img->left_margin+1, + $this->img->height-$this->img->bottom_margin, + $this->img->width-1-$hadj, + $this->img->height-1-$hadj); + $this->img->FilledRectangle($this->img->width-$this->img->right_margin, + $this->img->top_margin+1, + $this->img->width-1-$hadj, + $this->img->height-$this->img->bottom_margin-1); + } + + function FillPlotArea() { + $this->img->PushColor($this->plotarea_color); + $this->img->FilledRectangle($this->img->left_margin, + $this->img->top_margin, + $this->img->width-$this->img->right_margin, + $this->img->height-$this->img->bottom_margin); + $this->img->PopColor(); + } + + // Stroke the plot area with either a solid color or a background image + function StrokePlotArea() { + // Note: To be consistent we really should take a possible shadow + // into account. However, that causes some problem for the LinearScale class + // since in the current design it does not have any links to class Graph which + // means it has no way of compensating for the adjusted plotarea in case of a + // shadow. So, until I redesign LinearScale we can't compensate for this. + // So just set the two adjustment parameters to zero for now. + $boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ; + $adj = 0; //$this->doshadow ? $this->shadow_width : 0 ; + + if( $this->background_image != '' || $this->background_cflag != '' ) { + $this->StrokeFrameBackground(); + } + else { + $aa = $this->img->SetAngle(0); + $this->StrokeFrame(); + $aa = $this->img->SetAngle($aa); + $this->StrokeBackgroundGrad(); + if( $this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_MARGIN) ) { + $this->FillPlotArea(); + } + $this->StrokePlotGrad(); + } + } + + function StrokeIcons() { + $n = count($this->iIcons); + for( $i=0; $i < $n; ++$i ) { + $this->iIcons[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); + } + } + + function StrokePlotBox() { + // Should we draw a box around the plot area? + if( $this->boxed ) { + $this->img->SetLineWeight(1); + $this->img->SetLineStyle('solid'); + $this->img->SetColor($this->box_color); + for($i=0; $i < $this->box_weight; ++$i ) { + $this->img->Rectangle( + $this->img->left_margin-$i,$this->img->top_margin-$i, + $this->img->width-$this->img->right_margin+$i, + $this->img->height-$this->img->bottom_margin+$i); + } + } + } + + function SetTitleBackgroundFillStyle($aStyle,$aColor1='black',$aColor2='white') { + $this->titlebkg_fillstyle = $aStyle; + $this->titlebkg_scolor1 = $aColor1; + $this->titlebkg_scolor2 = $aColor2; + } + + function SetTitleBackground($aBackColor='gray', $aStyle=TITLEBKG_STYLE1, $aFrameStyle=TITLEBKG_FRAME_NONE, $aFrameColor='black', $aFrameWeight=1, $aBevelHeight=3, $aEnable=true) { + $this->titlebackground = $aEnable; + $this->titlebackground_color = $aBackColor; + $this->titlebackground_style = $aStyle; + $this->titlebackground_framecolor = $aFrameColor; + $this->titlebackground_framestyle = $aFrameStyle; + $this->titlebackground_frameweight = $aFrameWeight; + $this->titlebackground_bevelheight = $aBevelHeight ; + } + + + function StrokeTitles() { + + $margin=3; + + if( $this->titlebackground ) { + // Find out height + $this->title->margin += 2 ; + $h = $this->title->GetTextHeight($this->img)+$this->title->margin+$margin; + if( $this->subtitle->t != '' && !$this->subtitle->hide ) { + $h += $this->subtitle->GetTextHeight($this->img)+$margin+ + $this->subtitle->margin; + $h += 2; + } + if( $this->subsubtitle->t != '' && !$this->subsubtitle->hide ) { + $h += $this->subsubtitle->GetTextHeight($this->img)+$margin+ + $this->subsubtitle->margin; + $h += 2; + } + $this->img->PushColor($this->titlebackground_color); + if( $this->titlebackground_style === TITLEBKG_STYLE1 ) { + // Inside the frame + if( $this->framebevel ) { + $x1 = $y1 = $this->framebeveldepth + 1 ; + $x2 = $this->img->width - $this->framebeveldepth - 2 ; + $this->title->margin += $this->framebeveldepth + 1 ; + $h += $y1 ; + $h += 2; + } + else { + $x1 = $y1 = $this->frame_weight; + $x2 = $this->img->width - $this->frame_weight-1; + } + } + elseif( $this->titlebackground_style === TITLEBKG_STYLE2 ) { + // Cover the frame as well + $x1 = $y1 = 0; + $x2 = $this->img->width - 1 ; + } + elseif( $this->titlebackground_style === TITLEBKG_STYLE3 ) { + // Cover the frame as well (the difference is that + // for style==3 a bevel frame border is on top + // of the title background) + $x1 = $y1 = 0; + $x2 = $this->img->width - 1 ; + $h += $this->framebeveldepth ; + $this->title->margin += $this->framebeveldepth ; + } + else { + JpGraphError::RaiseL(25043);//('Unknown title background style.'); + } + + if( $this->titlebackground_framestyle === 3 ) { + $h += $this->titlebackground_bevelheight*2 + 1 ; + $this->title->margin += $this->titlebackground_bevelheight ; + } + + if( $this->doshadow ) { + $x2 -= $this->shadow_width ; + } + + $indent=0; + if( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) { + $indent = $this->titlebackground_bevelheight; + } + + if( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_HSTRIPED ) { + $this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent, + $this->titlebkg_scolor1, + $this->titlebkg_scolor2); + } + elseif( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_VSTRIPED ) { + $this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent, + $this->titlebkg_scolor1, + $this->titlebkg_scolor2,2); + } + else { + // Solid fill + $this->img->FilledRectangle($x1,$y1,$x2,$h); + } + $this->img->PopColor(); + + $this->img->PushColor($this->titlebackground_framecolor); + $this->img->SetLineWeight($this->titlebackground_frameweight); + if( $this->titlebackground_framestyle == TITLEBKG_FRAME_FULL ) { + // Frame background + $this->img->Rectangle($x1,$y1,$x2,$h); + } + elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM ) { + // Bottom line only + $this->img->Line($x1,$h,$x2,$h); + } + elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) { + $this->img->Bevel($x1,$y1,$x2,$h,$this->titlebackground_bevelheight); + } + $this->img->PopColor(); + + // This is clumsy. But we neeed to stroke the whole graph frame if it is + // set to bevel to get the bevel shading on top of the text background + if( $this->framebevel && $this->doframe && $this->titlebackground_style === 3 ) { + $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2, + $this->framebeveldepth, + $this->framebevelcolor1,$this->framebevelcolor2); + if( $this->framebevelborder ) { + $this->img->SetColor($this->framebevelbordercolor); + $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); + } + } + } + + // Stroke title + $y = $this->title->margin; + if( $this->title->halign == 'center' ) { + $this->title->Center(0,$this->img->width,$y); + } + elseif( $this->title->halign == 'left' ) { + $this->title->SetPos($this->title->margin+2,$y); + } + elseif( $this->title->halign == 'right' ) { + $indent = 0; + if( $this->doshadow ) { + $indent = $this->shadow_width+2; + } + $this->title->SetPos($this->img->width-$this->title->margin-$indent,$y,'right'); + } + $this->title->Stroke($this->img); + + // ... and subtitle + $y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin; + if( $this->subtitle->halign == 'center' ) { + $this->subtitle->Center(0,$this->img->width,$y); + } + elseif( $this->subtitle->halign == 'left' ) { + $this->subtitle->SetPos($this->subtitle->margin+2,$y); + } + elseif( $this->subtitle->halign == 'right' ) { + $indent = 0; + if( $this->doshadow ) + $indent = $this->shadow_width+2; + $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right'); + } + $this->subtitle->Stroke($this->img); + + // ... and subsubtitle + $y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin; + if( $this->subsubtitle->halign == 'center' ) { + $this->subsubtitle->Center(0,$this->img->width,$y); + } + elseif( $this->subsubtitle->halign == 'left' ) { + $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y); + } + elseif( $this->subsubtitle->halign == 'right' ) { + $indent = 0; + if( $this->doshadow ) + $indent = $this->shadow_width+2; + $this->subsubtitle->SetPos($this->img->width-$this->subsubtitle->margin-$indent,$y,'right'); + } + $this->subsubtitle->Stroke($this->img); + + // ... and fancy title + $this->tabtitle->Stroke($this->img); + + } + + function StrokeTexts() { + // Stroke any user added text objects + if( $this->texts != null ) { + for($i=0; $i < count($this->texts); ++$i) { + $this->texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); + } + } + + if( $this->y2texts != null && $this->y2scale != null ) { + for($i=0; $i < count($this->y2texts); ++$i) { + $this->y2texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->y2scale); + } + } + + } + + function StrokeTables() { + if( $this->iTables != null ) { + $n = count($this->iTables); + for( $i=0; $i < $n; ++$i ) { + $this->iTables[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); + } + } + } + + function DisplayClientSideaImageMapAreas() { + // Debug stuff - display the outline of the image map areas + $csim=''; + foreach ($this->plots as $p) { + $csim.= $p->GetCSIMareas(); + } + $csim .= $this->legend->GetCSIMareas(); + if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) { + $this->img->SetColor($this->csimcolor); + $n = count($coords[0]); + for ($i=0; $i < $n; $i++) { + if ( $coords[1][$i] == 'poly' ) { + preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts); + $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]); + $m = count($pts[0]); + for ($j=0; $j < $m; $j++) { + $this->img->LineTo($pts[1][$j],$pts[2][$j]); + } + } elseif ( $coords[1][$i] == 'rect' ) { + $pts = preg_split('/,/', $coords[2][$i]); + $this->img->SetStartPoint($pts[0],$pts[1]); + $this->img->LineTo($pts[2],$pts[1]); + $this->img->LineTo($pts[2],$pts[3]); + $this->img->LineTo($pts[0],$pts[3]); + $this->img->LineTo($pts[0],$pts[1]); + } + } + } + } + + // Text scale offset in world coordinates + function SetTextScaleOff($aOff) { + $this->text_scale_off = $aOff; + $this->xscale->text_scale_off = $aOff; + } + + // Text width of bar to be centered in absolute pixels + function SetTextScaleAbsCenterOff($aOff) { + $this->text_scale_abscenteroff = $aOff; + } + + // Get Y min and max values for added lines + function GetLinesYMinMax( $aLines ) { + $n = is_array($aLines) ? count($aLines) : 0; + if( $n == 0 ) return false; + $min = $aLines[0]->scaleposition ; + $max = $min ; + $flg = false; + for( $i=0; $i < $n; ++$i ) { + if( $aLines[$i]->direction == HORIZONTAL ) { + $flg = true ; + $v = $aLines[$i]->scaleposition ; + if( $min > $v ) $min = $v ; + if( $max < $v ) $max = $v ; + } + } + return $flg ? array($min,$max) : false ; + } + + // Get X min and max values for added lines + function GetLinesXMinMax( $aLines ) { + $n = is_array($aLines) ? count($aLines) : 0; + if( $n == 0 ) return false ; + $min = $aLines[0]->scaleposition ; + $max = $min ; + $flg = false; + for( $i=0; $i < $n; ++$i ) { + if( $aLines[$i]->direction == VERTICAL ) { + $flg = true ; + $v = $aLines[$i]->scaleposition ; + if( $min > $v ) $min = $v ; + if( $max < $v ) $max = $v ; + } + } + return $flg ? array($min,$max) : false ; + } + + // Get min and max values for all included plots + function GetPlotsYMinMax($aPlots) { + $n = count($aPlots); + $i=0; + do { + list($xmax,$max) = $aPlots[$i]->Max(); + } while( ++$i < $n && !is_numeric($max) ); + + $i=0; + do { + list($xmin,$min) = $aPlots[$i]->Min(); + } while( ++$i < $n && !is_numeric($min) ); + + if( !is_numeric($min) || !is_numeric($max) ) { + JpGraphError::RaiseL(25044);//('Cannot use autoscaling since it is impossible to determine a valid min/max value of the Y-axis (only null values).'); + } + + for($i=0; $i < $n; ++$i ) { + list($xmax,$ymax)=$aPlots[$i]->Max(); + list($xmin,$ymin)=$aPlots[$i]->Min(); + if (is_numeric($ymax)) $max=max($max,$ymax); + if (is_numeric($ymin)) $min=min($min,$ymin); + } + if( $min == '' ) $min = 0; + if( $max == '' ) $max = 0; + if( $min == 0 && $max == 0 ) { + // Special case if all values are 0 + $min=0;$max=1; + } + return array($min,$max); + } + + function hasLinePlotAndBarPlot() { + $has_line = false; + $has_bar = false; + + foreach ($this->plots as $plot) { + if ($plot instanceof LinePlot) { + $has_line = true; + } + if ($plot instanceof BarPlot) { + $has_bar = true; + } + } + + if ($has_line && $has_bar) { + return true; + } + + return false; + } + + function SetTheme($graph_theme) { + + if (!($this instanceof PieGraph)) { + if (!$this->isAfterSetScale) { + JpGraphError::RaiseL(25133);//('Use Graph::SetTheme() after Graph::SetScale().'); + } + } + + if ($this->graph_theme) { + $this->ClearTheme(); + } + $this->graph_theme = $graph_theme; + $this->graph_theme->ApplyGraph($this); + } + + function ClearTheme() { + $this->graph_theme = null; + + $this->isRunningClear = true; + + $this->__construct( + $this->inputValues['aWidth'], + $this->inputValues['aHeight'], + $this->inputValues['aCachedName'], + $this->inputValues['aTimeout'], + $this->inputValues['aInline'] + ); + + if (!($this instanceof PieGraph)) { + if ($this->isAfterSetScale) { + $this->SetScale( + $this->inputValues['aAxisType'], + $this->inputValues['aYMin'], + $this->inputValues['aYMax'], + $this->inputValues['aXMin'], + $this->inputValues['aXMax'] + ); + } + } + + $this->isRunningClear = false; + } + + function SetSupersampling($do = false, $scale = 2) { + if ($do) { + define('SUPERSAMPLING_SCALE', $scale); + // $this->img->scale = $scale; + } else { + define('SUPERSAMPLING_SCALE', 1); + //$this->img->scale = 0; + } + } + +} // Class + +//=================================================== +// CLASS LineProperty +// Description: Holds properties for a line +//=================================================== +class LineProperty { + public $iWeight=1, $iColor='black', $iStyle='solid', $iShow=false; + + function __construct($aWeight=1,$aColor='black',$aStyle='solid') { + $this->iWeight = $aWeight; + $this->iColor = $aColor; + $this->iStyle = $aStyle; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function SetWeight($aWeight) { + $this->iWeight = $aWeight; + } + + function SetStyle($aStyle) { + $this->iStyle = $aStyle; + } + + function Show($aShow=true) { + $this->iShow=$aShow; + } + + function Stroke($aImg,$aX1,$aY1,$aX2,$aY2) { + if( $this->iShow ) { + $aImg->PushColor($this->iColor); + $oldls = $aImg->line_style; + $oldlw = $aImg->line_weight; + $aImg->SetLineWeight($this->iWeight); + $aImg->SetLineStyle($this->iStyle); + $aImg->StyleLine($aX1,$aY1,$aX2,$aY2); + $aImg->PopColor($this->iColor); + $aImg->line_style = $oldls; + $aImg->line_weight = $oldlw; + + } + } +} + +//=================================================== +// CLASS GraphTabTitle +// Description: Draw "tab" titles on top of graphs +//=================================================== +class GraphTabTitle extends Text{ + private $corner = 6 , $posx = 7, $posy = 4; + private $fillcolor='lightyellow',$bordercolor='black'; + private $align = 'left', $width=TABTITLE_WIDTHFIT; + function __construct() { + $this->t = ''; + $this->font_style = FS_BOLD; + $this->hide = true; + $this->color = 'darkred'; + } + + function SetColor($aTxtColor,$aFillColor='lightyellow',$aBorderColor='black') { + $this->color = $aTxtColor; + $this->fillcolor = $aFillColor; + $this->bordercolor = $aBorderColor; + } + + function SetFillColor($aFillColor) { + $this->fillcolor = $aFillColor; + } + + function SetTabAlign($aAlign) { + $this->align = $aAlign; + } + + function SetWidth($aWidth) { + $this->width = $aWidth ; + } + + function Set($t) { + $this->t = $t; + $this->hide = false; + } + + function SetCorner($aD) { + $this->corner = $aD ; + } + + function Stroke($aImg,$aDummy1=null,$aDummy2=null) { + if( $this->hide ) + return; + $this->boxed = false; + $w = $this->GetWidth($aImg) + 2*$this->posx; + $h = $this->GetTextHeight($aImg) + 2*$this->posy; + + $x = $aImg->left_margin; + $y = $aImg->top_margin; + + if( $this->width === TABTITLE_WIDTHFIT ) { + if( $this->align == 'left' ) { + $p = array($x, $y, + $x, $y-$h+$this->corner, + $x + $this->corner,$y-$h, + $x + $w - $this->corner, $y-$h, + $x + $w, $y-$h+$this->corner, + $x + $w, $y); + } + elseif( $this->align == 'center' ) { + $x += round($aImg->plotwidth/2) - round($w/2); + $p = array($x, $y, + $x, $y-$h+$this->corner, + $x + $this->corner, $y-$h, + $x + $w - $this->corner, $y-$h, + $x + $w, $y-$h+$this->corner, + $x + $w, $y); + } + else { + $x += $aImg->plotwidth -$w; + $p = array($x, $y, + $x, $y-$h+$this->corner, + $x + $this->corner,$y-$h, + $x + $w - $this->corner, $y-$h, + $x + $w, $y-$h+$this->corner, + $x + $w, $y); + } + } + else { + if( $this->width === TABTITLE_WIDTHFULL ) { + $w = $aImg->plotwidth ; + } + else { + $w = $this->width ; + } + + // Make the tab fit the width of the plot area + $p = array($x, $y, + $x, $y-$h+$this->corner, + $x + $this->corner,$y-$h, + $x + $w - $this->corner, $y-$h, + $x + $w, $y-$h+$this->corner, + $x + $w, $y); + + } + if( $this->halign == 'left' ) { + $aImg->SetTextAlign('left','bottom'); + $x += $this->posx; + $y -= $this->posy; + } + elseif( $this->halign == 'center' ) { + $aImg->SetTextAlign('center','bottom'); + $x += $w/2; + $y -= $this->posy; + } + else { + $aImg->SetTextAlign('right','bottom'); + $x += $w - $this->posx; + $y -= $this->posy; + } + + $aImg->SetColor($this->fillcolor); + $aImg->FilledPolygon($p); + + $aImg->SetColor($this->bordercolor); + $aImg->Polygon($p,true); + + $aImg->SetColor($this->color); + $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); + $aImg->StrokeText($x,$y,$this->t,0,'center'); + } + +} + +//=================================================== +// CLASS SuperScriptText +// Description: Format a superscript text +//=================================================== +class SuperScriptText extends Text { + private $iSuper=''; + private $sfont_family='',$sfont_style='',$sfont_size=8; + private $iSuperMargin=2,$iVertOverlap=4,$iSuperScale=0.65; + private $iSDir=0; + private $iSimple=false; + + function __construct($aTxt='',$aSuper='',$aXAbsPos=0,$aYAbsPos=0) { + parent::__construct($aTxt,$aXAbsPos,$aYAbsPos); + $this->iSuper = $aSuper; + } + + function FromReal($aVal,$aPrecision=2) { + // Convert a floating point number to scientific notation + $neg=1.0; + if( $aVal < 0 ) { + $neg = -1.0; + $aVal = -$aVal; + } + + $l = floor(log10($aVal)); + $a = sprintf("%0.".$aPrecision."f",round($aVal / pow(10,$l),$aPrecision)); + $a *= $neg; + if( $this->iSimple && ($a == 1 || $a==-1) ) $a = ''; + + if( $a != '' ) { + $this->t = $a.' * 10'; + } + else { + if( $neg == 1 ) { + $this->t = '10'; + } + else { + $this->t = '-10'; + } + } + $this->iSuper = $l; + } + + function Set($aTxt,$aSuper='') { + $this->t = $aTxt; + $this->iSuper = $aSuper; + } + + function SetSuperFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=8) { + $this->sfont_family = $aFontFam; + $this->sfont_style = $aFontStyle; + $this->sfont_size = $aFontSize; + } + + // Total width of text + function GetWidth($aImg) { + $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); + $w = $aImg->GetTextWidth($this->t); + $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); + $w += $aImg->GetTextWidth($this->iSuper); + $w += $this->iSuperMargin; + return $w; + } + + // Hight of font (approximate the height of the text) + function GetFontHeight($aImg) { + $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); + $h = $aImg->GetFontHeight(); + $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); + $h += $aImg->GetFontHeight(); + return $h; + } + + // Hight of text + function GetTextHeight($aImg) { + $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); + $h = $aImg->GetTextHeight($this->t); + $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); + $h += $aImg->GetTextHeight($this->iSuper); + return $h; + } + + function Stroke($aImg,$ax=-1,$ay=-1) { + + // To position the super script correctly we need different + // cases to handle the alignmewnt specified since that will + // determine how we can interpret the x,y coordinates + + $w = parent::GetWidth($aImg); + $h = parent::GetTextHeight($aImg); + switch( $this->valign ) { + case 'top': + $sy = $this->y; + break; + case 'center': + $sy = $this->y - $h/2; + break; + case 'bottom': + $sy = $this->y - $h; + break; + default: + JpGraphError::RaiseL(25052);//('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text'); + break; + } + + switch( $this->halign ) { + case 'left': + $sx = $this->x + $w; + break; + case 'center': + $sx = $this->x + $w/2; + break; + case 'right': + $sx = $this->x; + break; + default: + JpGraphError::RaiseL(25053);//('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text'); + break; + } + + $sx += $this->iSuperMargin; + $sy += $this->iVertOverlap; + + // Should we automatically determine the font or + // has the user specified it explicetly? + if( $this->sfont_family == '' ) { + if( $this->font_family <= FF_FONT2 ) { + if( $this->font_family == FF_FONT0 ) { + $sff = FF_FONT0; + } + elseif( $this->font_family == FF_FONT1 ) { + if( $this->font_style == FS_NORMAL ) { + $sff = FF_FONT0; + } + else { + $sff = FF_FONT1; + } + } + else { + $sff = FF_FONT1; + } + $sfs = $this->font_style; + $sfz = $this->font_size; + } + else { + // TTF fonts + $sff = $this->font_family; + $sfs = $this->font_style; + $sfz = floor($this->font_size*$this->iSuperScale); + if( $sfz < 8 ) $sfz = 8; + } + $this->sfont_family = $sff; + $this->sfont_style = $sfs; + $this->sfont_size = $sfz; + } + else { + $sff = $this->sfont_family; + $sfs = $this->sfont_style; + $sfz = $this->sfont_size; + } + + parent::Stroke($aImg,$ax,$ay); + + // For the builtin fonts we need to reduce the margins + // since the bounding bx reported for the builtin fonts + // are much larger than for the TTF fonts. + if( $sff <= FF_FONT2 ) { + $sx -= 2; + $sy += 3; + } + + $aImg->SetTextAlign('left','bottom'); + $aImg->SetFont($sff,$sfs,$sfz); + $aImg->PushColor($this->color); + $aImg->StrokeText($sx,$sy,$this->iSuper,$this->iSDir,'left'); + $aImg->PopColor(); + } +} + + +//=================================================== +// CLASS Grid +// Description: responsible for drawing grid lines in graph +//=================================================== +class Grid { + protected $img; + protected $scale; + protected $majorcolor='#CCCCCC',$minorcolor='#DDDDDD'; + protected $majortype='solid',$minortype='solid'; + protected $show=false, $showMinor=false,$majorweight=1,$minorweight=1; + protected $fill=false,$fillcolor=array('#EFEFEF','#BBCCFF'); + + function __construct($aAxis) { + $this->scale = $aAxis->scale; + $this->img = $aAxis->img; + } + + function SetColor($aMajColor,$aMinColor=false) { + $this->majorcolor=$aMajColor; + if( $aMinColor === false ) { + $aMinColor = $aMajColor ; + } + $this->minorcolor = $aMinColor; + } + + function SetWeight($aMajorWeight,$aMinorWeight=1) { + $this->majorweight=$aMajorWeight; + $this->minorweight=$aMinorWeight; + } + + // Specify if grid should be dashed, dotted or solid + function SetLineStyle($aMajorType,$aMinorType='solid') { + $this->majortype = $aMajorType; + $this->minortype = $aMinorType; + } + + function SetStyle($aMajorType,$aMinorType='solid') { + $this->SetLineStyle($aMajorType,$aMinorType); + } + + // Decide if both major and minor grid should be displayed + function Show($aShowMajor=true,$aShowMinor=false) { + $this->show=$aShowMajor; + $this->showMinor=$aShowMinor; + } + + function SetFill($aFlg=true,$aColor1='lightgray',$aColor2='lightblue') { + $this->fill = $aFlg; + $this->fillcolor = array( $aColor1, $aColor2 ); + } + + // Display the grid + function Stroke() { + if( $this->showMinor && !$this->scale->textscale ) { + $this->DoStroke($this->scale->ticks->ticks_pos,$this->minortype,$this->minorcolor,$this->minorweight); + $this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight); + } + else { + $this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight); + } + } + + //-------------- + // Private methods + // Draw the grid + function DoStroke($aTicksPos,$aType,$aColor,$aWeight) { + if( !$this->show ) return; + $nbrgrids = count($aTicksPos); + + if( $this->scale->type == 'y' ) { + $xl=$this->img->left_margin; + $xr=$this->img->width-$this->img->right_margin; + + if( $this->fill ) { + // Draw filled areas + $y2 = !empty($aTicksPos) ? $aTicksPos[0] : null; + $i=1; + while( $i < $nbrgrids ) { + $y1 = $y2; + $y2 = $aTicksPos[$i++]; + $this->img->SetColor($this->fillcolor[$i & 1]); + $this->img->FilledRectangle($xl,$y1,$xr,$y2); + } + } + + $this->img->SetColor($aColor); + $this->img->SetLineWeight($aWeight); + + // Draw grid lines + switch( $aType ) { + case 'solid': $style = LINESTYLE_SOLID; break; + case 'dotted': $style = LINESTYLE_DOTTED; break; + case 'dashed': $style = LINESTYLE_DASHED; break; + case 'longdashed': $style = LINESTYLE_LONGDASH; break; + default: + $style = LINESTYLE_SOLID; break; + } + + for($i=0; $i < $nbrgrids; ++$i) { + $y=$aTicksPos[$i]; + $this->img->StyleLine($xl,$y,$xr,$y,$style,true); + } + } + elseif( $this->scale->type == 'x' ) { + $yu=$this->img->top_margin; + $yl=$this->img->height-$this->img->bottom_margin; + $limit=$this->img->width-$this->img->right_margin; + + if( $this->fill ) { + // Draw filled areas + $x2 = $aTicksPos[0]; + $i=1; + while( $i < $nbrgrids ) { + $x1 = $x2; + $x2 = min($aTicksPos[$i++],$limit) ; + $this->img->SetColor($this->fillcolor[$i & 1]); + $this->img->FilledRectangle($x1,$yu,$x2,$yl); + } + } + + $this->img->SetColor($aColor); + $this->img->SetLineWeight($aWeight); + + // We must also test for limit since we might have + // an offset and the number of ticks is calculated with + // assumption offset==0 so we might end up drawing one + // to many gridlines + $i=0; + while( $iimg->Line($x,$yl,$x,$yu); + elseif( $aType == 'dotted' ) $this->img->DashedLineForGrid($x,$yl,$x,$yu,1,6); + elseif( $aType == 'dashed' ) $this->img->DashedLineForGrid($x,$yl,$x,$yu,2,4); + elseif( $aType == 'longdashed' ) $this->img->DashedLineForGrid($x,$yl,$x,$yu,8,6); + ++$i; + } + } + else { + JpGraphError::RaiseL(25054,$this->scale->type);//('Internal error: Unknown grid axis ['.$this->scale->type.']'); + } + return true; + } +} // Class + +//=================================================== +// CLASS Axis +// Description: Defines X and Y axis. Notes that at the +// moment the code is not really good since the axis on +// several occasion must know wheter it's an X or Y axis. +// This was a design decision to make the code easier to +// follow. +//=================================================== +class AxisPrototype { + public $scale=null; + public $img=null; + public $hide=false,$hide_labels=false; + public $title=null; + public $font_family=FF_DEFAULT,$font_style=FS_NORMAL,$font_size=8,$label_angle=0; + public $tick_step=1; + public $pos = false; + public $ticks_label = array(); + + protected $weight=1; + protected $color=array(0,0,0),$label_color=array(0,0,0); + protected $ticks_label_colors=null; + protected $show_first_label=true,$show_last_label=true; + protected $label_step=1; // Used by a text axis to specify what multiple of major steps + // should be labeled. + protected $labelPos=0; // Which side of the axis should the labels be? + protected $title_adjust,$title_margin,$title_side=SIDE_LEFT; + protected $tick_label_margin=5; + protected $label_halign = '',$label_valign = '', $label_para_align='left'; + protected $hide_line=false; + protected $iDeltaAbsPos=0; + + function __construct($img,$aScale,$color = array(0,0,0)) { + $this->img = $img; + $this->scale = $aScale; + $this->color = $color; + $this->title=new Text(''); + + if( $aScale->type == 'y' ) { + $this->title_margin = 25; + $this->title_adjust = 'middle'; + $this->title->SetOrientation(90); + $this->tick_label_margin=7; + $this->labelPos=SIDE_LEFT; + } + else { + $this->title_margin = 5; + $this->title_adjust = 'high'; + $this->title->SetOrientation(0); + $this->tick_label_margin=5; + $this->labelPos=SIDE_DOWN; + $this->title_side=SIDE_DOWN; + } + } + + function SetLabelFormat($aFormStr) { + $this->scale->ticks->SetLabelFormat($aFormStr); + } + + function SetLabelFormatString($aFormStr,$aDate=false) { + $this->scale->ticks->SetLabelFormat($aFormStr,$aDate); + } + + function SetLabelFormatCallback($aFuncName) { + $this->scale->ticks->SetFormatCallback($aFuncName); + } + + function SetLabelAlign($aHAlign,$aVAlign='top',$aParagraphAlign='left') { + $this->label_halign = $aHAlign; + $this->label_valign = $aVAlign; + $this->label_para_align = $aParagraphAlign; + } + + // Don't display the first label + function HideFirstTickLabel($aShow=false) { + $this->show_first_label=$aShow; + } + + function HideLastTickLabel($aShow=false) { + $this->show_last_label=$aShow; + } + + // Manually specify the major and (optional) minor tick position and labels + function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) { + $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels); + } + + // Manually specify major tick positions and optional labels + function SetMajTickPositions($aMajPos,$aLabels=NULL) { + $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels); + } + + // Hide minor or major tick marks + function HideTicks($aHideMinor=true,$aHideMajor=true) { + $this->scale->ticks->SupressMinorTickMarks($aHideMinor); + $this->scale->ticks->SupressTickMarks($aHideMajor); + } + + // Hide zero label + function HideZeroLabel($aFlag=true) { + $this->scale->ticks->SupressZeroLabel(); + } + + function HideFirstLastLabel() { + // The two first calls to ticks method will supress + // automatically generated scale values. However, that + // will not affect manually specified value, e.g text-scales. + // therefor we also make a kludge here to supress manually + // specified scale labels. + $this->scale->ticks->SupressLast(); + $this->scale->ticks->SupressFirst(); + $this->show_first_label = false; + $this->show_last_label = false; + } + + // Hide the axis + function Hide($aHide=true) { + $this->hide=$aHide; + } + + // Hide the actual axis-line, but still print the labels + function HideLine($aHide=true) { + $this->hide_line = $aHide; + } + + function HideLabels($aHide=true) { + $this->hide_labels = $aHide; + } + + // Weight of axis + function SetWeight($aWeight) { + $this->weight = $aWeight; + } + + // Axis color + function SetColor($aColor,$aLabelColor=false) { + $this->color = $aColor; + if( !$aLabelColor ) $this->label_color = $aColor; + else $this->label_color = $aLabelColor; + } + + // Title on axis + function SetTitle($aTitle,$aAdjustAlign='high') { + $this->title->Set($aTitle); + $this->title_adjust=$aAdjustAlign; + } + + // Specify distance from the axis + function SetTitleMargin($aMargin) { + $this->title_margin=$aMargin; + } + + // Which side of the axis should the axis title be? + function SetTitleSide($aSideOfAxis) { + $this->title_side = $aSideOfAxis; + } + + function SetTickSide($aDir) { + $this->scale->ticks->SetSide($aDir); + } + + function SetTickSize($aMajSize,$aMinSize=3) { + $this->scale->ticks->SetSize($aMajSize,$aMinSize=3); + } + + // Specify text labels for the ticks. One label for each data point + function SetTickLabels($aLabelArray,$aLabelColorArray=null) { + $this->ticks_label = $aLabelArray; + $this->ticks_label_colors = $aLabelColorArray; + } + + function SetLabelMargin($aMargin) { + $this->tick_label_margin=$aMargin; + } + + // Specify that every $step of the ticks should be displayed starting + // at $start + function SetTextTickInterval($aStep,$aStart=0) { + $this->scale->ticks->SetTextLabelStart($aStart); + $this->tick_step=$aStep; + } + + // Specify that every $step tick mark should have a label + // should be displayed starting + function SetTextLabelInterval($aStep) { + if( $aStep < 1 ) { + JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1."); + } + $this->label_step=$aStep; + } + + function SetLabelSide($aSidePos) { + $this->labelPos=$aSidePos; + } + + // Set the font + function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { + $this->font_family = $aFamily; + $this->font_style = $aStyle; + $this->font_size = $aSize; + } + + // Position for axis line on the "other" scale + function SetPos($aPosOnOtherScale) { + $this->pos=$aPosOnOtherScale; + } + + // Set the position of the axis to be X-pixels delta to the right + // of the max X-position (used to position the multiple Y-axis) + function SetPosAbsDelta($aDelta) { + $this->iDeltaAbsPos=$aDelta; + } + + // Specify the angle for the tick labels + function SetLabelAngle($aAngle) { + $this->label_angle = $aAngle; + } + +} // Class + + +//=================================================== +// CLASS Axis +// Description: Defines X and Y axis. Notes that at the +// moment the code is not really good since the axis on +// several occasion must know wheter it's an X or Y axis. +// This was a design decision to make the code easier to +// follow. +//=================================================== +class Axis extends AxisPrototype { + + function __construct($img,$aScale,$color='black') { + parent::__construct($img,$aScale,$color); + } + + // Stroke the axis. + function Stroke($aOtherAxisScale,$aStrokeLabels=true) { + if( $this->hide ) + return; + if( is_numeric($this->pos) ) { + $pos=$aOtherAxisScale->Translate($this->pos); + } + else { // Default to minimum of other scale if pos not set + if( ($aOtherAxisScale->GetMinVal() >= 0 && $this->pos==false) || $this->pos == 'min' ) { + $pos = $aOtherAxisScale->scale_abs[0]; + } + elseif($this->pos == "max") { + $pos = $aOtherAxisScale->scale_abs[1]; + } + else { // If negative set x-axis at 0 + $this->pos=0; + $pos=$aOtherAxisScale->Translate(0); + } + } + + $pos += $this->iDeltaAbsPos; + $this->img->SetLineWeight($this->weight); + $this->img->SetColor($this->color); + $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); + + if( $this->scale->type == "x" ) { + if( !$this->hide_line ) { + // Stroke X-axis + $this->img->FilledRectangle( + $this->img->left_margin, + $pos, + $this->img->width - $this->img->right_margin, + $pos + $this->weight-1 + ); + } + if( $this->title_side == SIDE_DOWN ) { + $y = $pos + $this->img->GetFontHeight() + $this->title_margin + $this->title->margin; + $yalign = 'top'; + } + else { + $y = $pos - $this->img->GetFontHeight() - $this->title_margin - $this->title->margin; + $yalign = 'bottom'; + } + + if( $this->title_adjust=='high' ) { + $this->title->SetPos($this->img->width-$this->img->right_margin,$y,'right',$yalign); + } + elseif( $this->title_adjust=='middle' || $this->title_adjust=='center' ) { + $this->title->SetPos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin,$y,'center',$yalign); + } + elseif($this->title_adjust=='low') { + $this->title->SetPos($this->img->left_margin,$y,'left',$yalign); + } + else { + JpGraphError::RaiseL(25060,$this->title_adjust);//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')'); + } + } + elseif( $this->scale->type == "y" ) { + // Add line weight to the height of the axis since + // the x-axis could have a width>1 and we want the axis to fit nicely together. + if( !$this->hide_line ) { + // Stroke Y-axis + $this->img->FilledRectangle( + $pos - $this->weight + 1, + $this->img->top_margin, + $pos, + $this->img->height - $this->img->bottom_margin + $this->weight - 1 + ); + } + + $x=$pos ; + if( $this->title_side == SIDE_LEFT ) { + $x -= $this->title_margin; + $x -= $this->title->margin; + $halign = 'right'; + } + else { + $x += $this->title_margin; + $x += $this->title->margin; + $halign = 'left'; + } + // If the user has manually specified an hor. align + // then we override the automatic settings with this + // specifed setting. Since default is 'left' we compare + // with that. (This means a manually set 'left' align + // will have no effect.) + if( $this->title->halign != 'left' ) { + $halign = $this->title->halign; + } + if( $this->title_adjust == 'high' ) { + $this->title->SetPos($x,$this->img->top_margin,$halign,'top'); + } + elseif($this->title_adjust=='middle' || $this->title_adjust=='center') { + $this->title->SetPos($x,($this->img->height-$this->img->top_margin-$this->img->bottom_margin)/2+$this->img->top_margin,$halign,"center"); + } + elseif($this->title_adjust=='low') { + $this->title->SetPos($x,$this->img->height-$this->img->bottom_margin,$halign,'bottom'); + } + else { + JpGraphError::RaiseL(25061,$this->title_adjust);//('Unknown alignment specified for Y-axis title. ('.$this->title_adjust.')'); + } + } + $this->scale->ticks->Stroke($this->img,$this->scale,$pos); + if( $aStrokeLabels ) { + if( !$this->hide_labels ) { + $this->StrokeLabels($pos); + } + $this->title->Stroke($this->img); + } + } + + //--------------- + // PRIVATE METHODS + // Draw all the tick labels on major tick marks + function StrokeLabels($aPos,$aMinor=false,$aAbsLabel=false) { + + if( is_array($this->label_color) && count($this->label_color) > 3 ) { + $this->ticks_label_colors = $this->label_color; + $this->img->SetColor($this->label_color[0]); + } + else { + $this->img->SetColor($this->label_color); + } + $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); + $yoff=$this->img->GetFontHeight()/2; + + // Only draw labels at major tick marks + $nbr = count($this->scale->ticks->maj_ticks_label); + + // We have the option to not-display the very first mark + // (Usefull when the first label might interfere with another + // axis.) + $i = $this->show_first_label ? 0 : 1 ; + if( !$this->show_last_label ) { + --$nbr; + } + // Now run through all labels making sure we don't overshoot the end + // of the scale. + $ncolor=0; + if( isset($this->ticks_label_colors) ) { + $ncolor=count($this->ticks_label_colors); + } + while( $i < $nbr ) { + // $tpos holds the absolute text position for the label + $tpos=$this->scale->ticks->maj_ticklabels_pos[$i]; + + // Note. the $limit is only used for the x axis since we + // might otherwise overshoot if the scale has been centered + // This is due to us "loosing" the last tick mark if we center. + if( $this->scale->type == 'x' && $tpos > $this->img->width-$this->img->right_margin+1 ) { + return; + } + // we only draw every $label_step label + if( ($i % $this->label_step)==0 ) { + + // Set specific label color if specified + if( $ncolor > 0 ) { + $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]); + } + + // If the label has been specified use that and in other case + // just label the mark with the actual scale value + $m=$this->scale->ticks->GetMajor(); + + // ticks_label has an entry for each data point and is the array + // that holds the labels set by the user. If the user hasn't + // specified any values we use whats in the automatically asigned + // labels in the maj_ticks_label + if( isset($this->ticks_label[$i*$m]) ) { + $label=$this->ticks_label[$i*$m]; + } + else { + if( $aAbsLabel ) { + $label=abs($this->scale->ticks->maj_ticks_label[$i]); + } + else { + $label=$this->scale->ticks->maj_ticks_label[$i]; + } + + // We number the scale from 1 and not from 0 so increase by one + if( $this->scale->textscale && + $this->scale->ticks->label_formfunc == '' && + ! $this->scale->ticks->HaveManualLabels() ) { + + ++$label; + + } + } + + if( $this->scale->type == "x" ) { + if( $this->labelPos == SIDE_DOWN ) { + if( $this->label_angle==0 || $this->label_angle==90 ) { + if( $this->label_halign=='' && $this->label_valign=='') { + $this->img->SetTextAlign('center','top'); + } + else { + $this->img->SetTextAlign($this->label_halign,$this->label_valign); + } + + } + else { + if( $this->label_halign=='' && $this->label_valign=='') { + $this->img->SetTextAlign("right","top"); + } + else { + $this->img->SetTextAlign($this->label_halign,$this->label_valign); + } + } + $this->img->StrokeText($tpos,$aPos+$this->tick_label_margin,$label, + $this->label_angle,$this->label_para_align); + } + else { + if( $this->label_angle==0 || $this->label_angle==90 ) { + if( $this->label_halign=='' && $this->label_valign=='') { + $this->img->SetTextAlign("center","bottom"); + } + else { + $this->img->SetTextAlign($this->label_halign,$this->label_valign); + } + } + else { + if( $this->label_halign=='' && $this->label_valign=='') { + $this->img->SetTextAlign("right","bottom"); + } + else { + $this->img->SetTextAlign($this->label_halign,$this->label_valign); + } + } + $this->img->StrokeText($tpos,$aPos-$this->tick_label_margin-1,$label, + $this->label_angle,$this->label_para_align); + } + } + else { + // scale->type == "y" + //if( $this->label_angle!=0 ) + //JpGraphError::Raise(" Labels at an angle are not supported on Y-axis"); + if( $this->labelPos == SIDE_LEFT ) { // To the left of y-axis + if( $this->label_halign=='' && $this->label_valign=='') { + $this->img->SetTextAlign("right","center"); + } + else { + $this->img->SetTextAlign($this->label_halign,$this->label_valign); + } + $this->img->StrokeText($aPos-$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align); + } + else { // To the right of the y-axis + if( $this->label_halign=='' && $this->label_valign=='') { + $this->img->SetTextAlign("left","center"); + } + else { + $this->img->SetTextAlign($this->label_halign,$this->label_valign); + } + $this->img->StrokeText($aPos+$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align); + } + } + } + ++$i; + } + } + +} + + +//=================================================== +// CLASS Ticks +// Description: Abstract base class for drawing linear and logarithmic +// tick marks on axis +//=================================================== +class Ticks { + public $label_formatstr=''; // C-style format string to use for labels + public $label_formfunc=''; + public $label_dateformatstr=''; + public $direction=1; // Should ticks be in(=1) the plot area or outside (=-1) + public $supress_last=false,$supress_tickmarks=false,$supress_minor_tickmarks=false; + public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(), + $ticks_pos = array(), $maj_ticks_label = array(); + public $precision; + + protected $minor_abs_size=3, $major_abs_size=5; + protected $scale; + protected $is_set=false; + protected $supress_zerolabel=false,$supress_first=false; + protected $mincolor='',$majcolor=''; + protected $weight=1; + protected $label_usedateformat=FALSE; + + function __construct($aScale) { + $this->scale=$aScale; + $this->precision = -1; + } + + // Set format string for automatic labels + function SetLabelFormat($aFormatString,$aDate=FALSE) { + $this->label_formatstr=$aFormatString; + $this->label_usedateformat=$aDate; + } + + function SetLabelDateFormat($aFormatString) { + $this->label_dateformatstr=$aFormatString; + } + + function SetFormatCallback($aCallbackFuncName) { + $this->label_formfunc = $aCallbackFuncName; + } + + // Don't display the first zero label + function SupressZeroLabel($aFlag=true) { + $this->supress_zerolabel=$aFlag; + } + + // Don't display minor tick marks + function SupressMinorTickMarks($aHide=true) { + $this->supress_minor_tickmarks=$aHide; + } + + // Don't display major tick marks + function SupressTickMarks($aHide=true) { + $this->supress_tickmarks=$aHide; + } + + // Hide the first tick mark + function SupressFirst($aHide=true) { + $this->supress_first=$aHide; + } + + // Hide the last tick mark + function SupressLast($aHide=true) { + $this->supress_last=$aHide; + } + + // Size (in pixels) of minor tick marks + function GetMinTickAbsSize() { + return $this->minor_abs_size; + } + + // Size (in pixels) of major tick marks + function GetMajTickAbsSize() { + return $this->major_abs_size; + } + + function SetSize($aMajSize,$aMinSize=3) { + $this->major_abs_size = $aMajSize; + $this->minor_abs_size = $aMinSize; + } + + // Have the ticks been specified + function IsSpecified() { + return $this->is_set; + } + + function SetSide($aSide) { + $this->direction=$aSide; + } + + // Which side of the axis should the ticks be on + function SetDirection($aSide=SIDE_RIGHT) { + $this->direction=$aSide; + } + + // Set colors for major and minor tick marks + function SetMarkColor($aMajorColor,$aMinorColor='') { + $this->SetColor($aMajorColor,$aMinorColor); + } + + function SetColor($aMajorColor,$aMinorColor='') { + $this->majcolor=$aMajorColor; + + // If not specified use same as major + if( $aMinorColor == '' ) { + $this->mincolor=$aMajorColor; + } + else { + $this->mincolor=$aMinorColor; + } + } + + function SetWeight($aWeight) { + $this->weight=$aWeight; + } + +} // Class + +//=================================================== +// CLASS LinearTicks +// Description: Draw linear ticks on axis +//=================================================== +class LinearTicks extends Ticks { + public $minor_step=1, $major_step=2; + public $xlabel_offset=0,$xtick_offset=0; + private $label_offset=0; // What offset should the displayed label have + // i.e should we display 0,1,2 or 1,2,3,4 or 2,3,4 etc + private $text_label_start=0; + private $iManualTickPos = NULL, $iManualMinTickPos = NULL, $iManualTickLabels = NULL; + private $iAdjustForDST = false; // If a date falls within the DST period add one hour to the diaplyed time + + function __construct() { + $this->precision = -1; + } + + // Return major step size in world coordinates + function GetMajor() { + return $this->major_step; + } + + // Return minor step size in world coordinates + function GetMinor() { + return $this->minor_step; + } + + // Set Minor and Major ticks (in world coordinates) + function Set($aMajStep,$aMinStep=false) { + if( $aMinStep==false ) { + $aMinStep=$aMajStep; + } + + if( $aMajStep <= 0 || $aMinStep <= 0 ) { + JpGraphError::RaiseL(25064); + //(" 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."); + } + + $this->major_step=$aMajStep; + $this->minor_step=$aMinStep; + $this->is_set = true; + } + + function SetMajTickPositions($aMajPos,$aLabels=NULL) { + $this->SetTickPositions($aMajPos,NULL,$aLabels); + } + + function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) { + if( !is_array($aMajPos) || ($aMinPos!==NULL && !is_array($aMinPos)) ) { + JpGraphError::RaiseL(25065);//('Tick positions must be specifued as an array()'); + return; + } + $n=count($aMajPos); + if( is_array($aLabels) && (count($aLabels) != $n) ) { + JpGraphError::RaiseL(25066);//('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.'); + } + $this->iManualTickPos = $aMajPos; + $this->iManualMinTickPos = $aMinPos; + $this->iManualTickLabels = $aLabels; + } + + function HaveManualLabels() { + return is_array($this->iManualTickLabels) ? count($this->iManualTickLabels) > 0 : false; + } + + // Specify all the tick positions manually and possible also the exact labels + function _doManualTickPos($aScale) { + $n=count($this->iManualTickPos); + $m= is_array($this->iManualMinTickPos) ? count($this->iManualMinTickPos) : 0; + $doLbl= is_array($this->iManualTickLabels) ? count($this->iManualTickLabels) > 0 : false; + + $this->maj_ticks_pos = array(); + $this->maj_ticklabels_pos = array(); + $this->ticks_pos = array(); + + // Now loop through the supplied positions and translate them to screen coordinates + // and store them in the maj_label_positions + $minScale = $aScale->scale[0]; + $maxScale = $aScale->scale[1]; + $j=0; + for($i=0; $i < $n ; ++$i ) { + // First make sure that the first tick is not lower than the lower scale value + if( !isset($this->iManualTickPos[$i]) || $this->iManualTickPos[$i] < $minScale || $this->iManualTickPos[$i] > $maxScale) { + continue; + } + + $this->maj_ticks_pos[$j] = $aScale->Translate($this->iManualTickPos[$i]); + $this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j]; + + // Set the minor tick marks the same as major if not specified + if( $m <= 0 ) { + $this->ticks_pos[$j] = $this->maj_ticks_pos[$j]; + } + if( $doLbl ) { + $this->maj_ticks_label[$j] = $this->iManualTickLabels[$i]; + } + else { + $this->maj_ticks_label[$j]=$this->_doLabelFormat($this->iManualTickPos[$i],$i,$n); + } + ++$j; + } + + // Some sanity check + if( count($this->maj_ticks_pos) < 2 ) { + 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.'); + } + + // Setup the minor tick marks + $j=0; + for($i=0; $i < $m; ++$i ) { + if( empty($this->iManualMinTickPos[$i]) || $this->iManualMinTickPos[$i] < $minScale || $this->iManualMinTickPos[$i] > $maxScale) { + continue; + } + $this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]); + ++$j; + } + } + + function _doAutoTickPos($aScale) { + $maj_step_abs = $aScale->scale_factor*$this->major_step; + $min_step_abs = $aScale->scale_factor*$this->minor_step; + + if( $min_step_abs==0 || $maj_step_abs==0 ) { + 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')"); + } + // We need to make this an int since comparing it below + // with the result from round() can give wrong result, such that + // (40 < 40) == TRUE !!! + $limit = (int)$aScale->scale_abs[1]; + + if( $aScale->textscale ) { + // This can only be true for a X-scale (horizontal) + // Define ticks for a text scale. This is slightly different from a + // normal linear type of scale since the position might be adjusted + // and the labels start at on + $label = (float)$aScale->GetMinVal()+$this->text_label_start+$this->label_offset; + $start_abs=$aScale->scale_factor*$this->text_label_start; + $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; + + $x = $aScale->scale_abs[0]+$start_abs+$this->xlabel_offset*$min_step_abs; + for( $i=0; $label <= $aScale->GetMaxVal()+$this->label_offset; ++$i ) { + // Apply format to label + $this->maj_ticks_label[$i]=$this->_doLabelFormat($label,$i,$nbrmajticks); + $label+=$this->major_step; + + // The x-position of the tick marks can be different from the labels. + // Note that we record the tick position (not the label) so that the grid + // happen upon tick marks and not labels. + $xtick=$aScale->scale_abs[0]+$start_abs+$this->xtick_offset*$min_step_abs+$i*$maj_step_abs; + $this->maj_ticks_pos[$i]=$xtick; + $this->maj_ticklabels_pos[$i] = round($x); + $x += $maj_step_abs; + } + } + else { + $label = $aScale->GetMinVal(); + $abs_pos = $aScale->scale_abs[0]; + $j=0; $i=0; + $step = round($maj_step_abs/$min_step_abs); + if( $aScale->type == "x" ) { + // For a normal linear type of scale the major ticks will always be multiples + // of the minor ticks. In order to avoid any rounding issues the major ticks are + // defined as every "step" minor ticks and not calculated separately + $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; + while( round($abs_pos) <= $limit ) { + $this->ticks_pos[] = round($abs_pos); + $this->ticks_label[] = $label; + if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks ) { + $this->maj_ticks_pos[$j] = round($abs_pos); + $this->maj_ticklabels_pos[$j] = round($abs_pos); + $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks); + ++$j; + } + ++$i; + $abs_pos += $min_step_abs; + $label+=$this->minor_step; + } + } + elseif( $aScale->type == "y" ) { + //@todo s=2:20,12 s=1:50,6 $this->major_step:$nbr + // abs_point,limit s=1:270,80 s=2:540,160 + // $this->major_step = 50; + $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal())/$this->major_step)+1; +// $step = 5; + while( round($abs_pos) >= $limit ) { + $this->ticks_pos[$i] = round($abs_pos); + $this->ticks_label[$i]=$label; + if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks) { + $this->maj_ticks_pos[$j] = round($abs_pos); + $this->maj_ticklabels_pos[$j] = round($abs_pos); + $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks); + ++$j; + } + ++$i; + $abs_pos += $min_step_abs; + $label += $this->minor_step; + } + } + } + } + + function AdjustForDST($aFlg=true) { + $this->iAdjustForDST = $aFlg; + } + + + function _doLabelFormat($aVal,$aIdx,$aNbrTicks) { + + // If precision hasn't been specified set it to a sensible value + if( $this->precision==-1 ) { + $t = log10($this->minor_step); + if( $t > 0 || $t === 0.0) { + $precision = 0; + } + else { + $precision = -floor($t); + } + } + else { + $precision = $this->precision; + } + + if( $this->label_formfunc != '' ) { + $f=$this->label_formfunc; + if( $this->label_formatstr == '' ) { + $l = call_user_func($f,$aVal); + } + else { + $l = sprintf($this->label_formatstr, call_user_func($f,$aVal)); + } + } + elseif( $this->label_formatstr != '' || $this->label_dateformatstr != '' ) { + if( $this->label_usedateformat ) { + // Adjust the value to take daylight savings into account + if (date("I",$aVal)==1 && $this->iAdjustForDST ) { + // DST + $aVal+=3600; + } + + $l = date($this->label_formatstr,$aVal); + if( $this->label_formatstr == 'W' ) { + // If we use week formatting then add a single 'w' in front of the + // week number to differentiate it from dates + $l = 'w'.$l; + } + } + else { + if( $this->label_dateformatstr !== '' ) { + // Adjust the value to take daylight savings into account + if (date("I",$aVal)==1 && $this->iAdjustForDST ) { + // DST + $aVal+=3600; + } + + $l = date($this->label_dateformatstr,$aVal); + if( $this->label_formatstr == 'W' ) { + // If we use week formatting then add a single 'w' in front of the + // week number to differentiate it from dates + $l = 'w'.$l; + } + } + else { + $l = sprintf($this->label_formatstr,$aVal); + } + } + } + else { + $l = sprintf('%01.'.$precision.'f',round($aVal,$precision)); + } + + if( ($this->supress_zerolabel && $l==0) || ($this->supress_first && $aIdx==0) || ($this->supress_last && $aIdx==$aNbrTicks-1) ) { + $l=''; + } + return $l; + } + + // Stroke ticks on either X or Y axis + function _StrokeTicks($aImg,$aScale,$aPos) { + $hor = $aScale->type == 'x'; + $aImg->SetLineWeight($this->weight); + + // We need to make this an int since comparing it below + // with the result from round() can give wrong result, such that + // (40 < 40) == TRUE !!! + $limit = (int)$aScale->scale_abs[1]; + + // A text scale doesn't have any minor ticks + if( !$aScale->textscale ) { + // Stroke minor ticks + $yu = $aPos - $this->direction*$this->GetMinTickAbsSize(); + $xr = $aPos + $this->direction*$this->GetMinTickAbsSize(); + $n = count($this->ticks_pos); + for($i=0; $i < $n; ++$i ) { + if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { + if( $this->mincolor != '') { + $aImg->PushColor($this->mincolor); + } + if( $hor ) { + //if( $this->ticks_pos[$i] <= $limit ) + $aImg->Line($this->ticks_pos[$i],$aPos,$this->ticks_pos[$i],$yu); + } + else { + //if( $this->ticks_pos[$i] >= $limit ) + $aImg->Line($aPos,$this->ticks_pos[$i],$xr,$this->ticks_pos[$i]); + } + if( $this->mincolor != '' ) { + $aImg->PopColor(); + } + } + } + } + + // Stroke major ticks + $yu = $aPos - $this->direction*$this->GetMajTickAbsSize(); + $xr = $aPos + $this->direction*$this->GetMajTickAbsSize(); + $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; + $n = count($this->maj_ticks_pos); + for($i=0; $i < $n ; ++$i ) { + if(!($this->xtick_offset > 0 && $i==$nbrmajticks-1) && !$this->supress_tickmarks) { + if( $this->majcolor != '') { + $aImg->PushColor($this->majcolor); + } + if( $hor ) { + //if( $this->maj_ticks_pos[$i] <= $limit ) + $aImg->Line($this->maj_ticks_pos[$i],$aPos,$this->maj_ticks_pos[$i],$yu); + } + else { + //if( $this->maj_ticks_pos[$i] >= $limit ) + $aImg->Line($aPos,$this->maj_ticks_pos[$i],$xr,$this->maj_ticks_pos[$i]); + } + if( $this->majcolor != '') { + $aImg->PopColor(); + } + } + } + + } + + // Draw linear ticks + function Stroke($aImg,$aScale,$aPos) { + if( $this->iManualTickPos != NULL ) { + $this->_doManualTickPos($aScale); + } + else { + $this->_doAutoTickPos($aScale); + } + $this->_StrokeTicks($aImg,$aScale,$aPos, $aScale->type == 'x' ); + } + + //--------------- + // PRIVATE METHODS + // Spoecify the offset of the displayed tick mark with the tick "space" + // Legal values for $o is [0,1] used to adjust where the tick marks and label + // should be positioned within the major tick-size + // $lo specifies the label offset and $to specifies the tick offset + // this comes in handy for example in bar graphs where we wont no offset for the + // tick but have the labels displayed halfway under the bars. + function SetXLabelOffset($aLabelOff,$aTickOff=-1) { + $this->xlabel_offset=$aLabelOff; + if( $aTickOff==-1 ) { + // Same as label offset + $this->xtick_offset=$aLabelOff; + } + else { + $this->xtick_offset=$aTickOff; + } + if( $aLabelOff>0 ) { + $this->SupressLast(); // The last tick wont fit + } + } + + // Which tick label should we start with? + function SetTextLabelStart($aTextLabelOff) { + $this->text_label_start=$aTextLabelOff; + } + +} // Class + +//=================================================== +// CLASS LinearScale +// Description: Handle linear scaling between screen and world +//=================================================== +class LinearScale { + public $textscale=false; // Just a flag to let the Plot class find out if + // we are a textscale or not. This is a cludge since + // this information is available in Graph::axtype but + // we don't have access to the graph object in the Plots + // stroke method. So we let graph store the status here + // when the linear scale is created. A real cludge... + public $type; // is this x or y scale ? + public $ticks=null; // Store ticks + public $text_scale_off = 0; + public $scale_abs=array(0,0); + public $scale_factor; // Scale factor between world and screen + public $off; // Offset between image edge and plot area + public $scale=array(0,0); + public $name = 'lin'; + public $auto_ticks=false; // When using manual scale should the ticks be automatically set? + public $world_abs_size; // Plot area size in pixels (Needed public in jpgraph_radar.php) + public $intscale=false; // Restrict autoscale to integers + protected $autoscale_min=false; // Forced minimum value, auto determine max + protected $autoscale_max=false; // Forced maximum value, auto determine min + private $gracetop=0,$gracebottom=0; + + private $_world_size; // Plot area size in world coordinates + + function __construct($aMin=0,$aMax=0,$aType='y') { + assert($aType=='x' || $aType=='y' ); + assert($aMin<=$aMax); + + $this->type=$aType; + $this->scale=array($aMin,$aMax); + $this->world_size=$aMax-$aMin; + $this->ticks = new LinearTicks(); + } + + // Check if scale is set or if we should autoscale + // We should do this is either scale or ticks has not been set + function IsSpecified() { + if( $this->GetMinVal()==$this->GetMaxVal() ) { // Scale not set + return false; + } + return true; + } + + // Set the minimum data value when the autoscaling is used. + // Usefull if you want a fix minimum (like 0) but have an + // automatic maximum + function SetAutoMin($aMin) { + $this->autoscale_min=$aMin; + } + + // Set the minimum data value when the autoscaling is used. + // Usefull if you want a fix minimum (like 0) but have an + // automatic maximum + function SetAutoMax($aMax) { + $this->autoscale_max=$aMax; + } + + // If the user manually specifies a scale should the ticks + // still be set automatically? + function SetAutoTicks($aFlag=true) { + $this->auto_ticks = $aFlag; + } + + // Specify scale "grace" value (top and bottom) + function SetGrace($aGraceTop,$aGraceBottom=0) { + if( $aGraceTop<0 || $aGraceBottom < 0 ) { + JpGraphError::RaiseL(25069);//(" Grace must be larger then 0"); + } + $this->gracetop=$aGraceTop; + $this->gracebottom=$aGraceBottom; + } + + // Get the minimum value in the scale + function GetMinVal() { + return $this->scale[0]; + } + + // get maximum value for scale + function GetMaxVal() { + return $this->scale[1]; + } + + // Specify a new min/max value for sclae + function Update($aImg,$aMin,$aMax) { + $this->scale=array($aMin,$aMax); + $this->world_size=$aMax-$aMin; + $this->InitConstants($aImg); + } + + // Translate between world and screen + function Translate($aCoord) { + if( !is_numeric($aCoord) ) { + if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) { + JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.'); + } + return 0; + } + else { + return round($this->off+($aCoord - $this->scale[0]) * $this->scale_factor); + } + } + + // Relative translate (don't include offset) usefull when we just want + // to know the relative position (in pixels) on the axis + function RelTranslate($aCoord) { + if( !is_numeric($aCoord) ) { + if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) { + JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.'); + } + return 0; + } + else { + return ($aCoord - $this->scale[0]) * $this->scale_factor; + } + } + + // Restrict autoscaling to only use integers + function SetIntScale($aIntScale=true) { + $this->intscale=$aIntScale; + } + + // Calculate an integer autoscale + function IntAutoScale($img,$min,$max,$maxsteps,$majend=true) { + // Make sure limits are integers + $min=floor($min); + $max=ceil($max); + if( abs($min-$max)==0 ) { + --$min; ++$max; + } + $maxsteps = floor($maxsteps); + + $gracetop=round(($this->gracetop/100.0)*abs($max-$min)); + $gracebottom=round(($this->gracebottom/100.0)*abs($max-$min)); + if( is_numeric($this->autoscale_min) ) { + $min = ceil($this->autoscale_min); + if( $min >= $max ) { + 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.'); + } + } + + if( is_numeric($this->autoscale_max) ) { + $max = ceil($this->autoscale_max); + if( $min >= $max ) { + 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.'); + } + } + + if( abs($min-$max ) == 0 ) { + ++$max; + --$min; + } + + $min -= $gracebottom; + $max += $gracetop; + + // First get tickmarks as multiples of 1, 10, ... + if( $majend ) { + list($num1steps,$adj1min,$adj1max,$maj1step) = $this->IntCalcTicks($maxsteps,$min,$max,1); + } + else { + $adj1min = $min; + $adj1max = $max; + list($num1steps,$maj1step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,1); + } + + if( abs($min-$max) > 2 ) { + // Then get tick marks as 2:s 2, 20, ... + if( $majend ) { + list($num2steps,$adj2min,$adj2max,$maj2step) = $this->IntCalcTicks($maxsteps,$min,$max,5); + } + else { + $adj2min = $min; + $adj2max = $max; + list($num2steps,$maj2step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,5); + } + } + else { + $num2steps = 10000; // Dummy high value so we don't choose this + } + + if( abs($min-$max) > 5 ) { + // Then get tickmarks as 5:s 5, 50, 500, ... + if( $majend ) { + list($num5steps,$adj5min,$adj5max,$maj5step) = $this->IntCalcTicks($maxsteps,$min,$max,2); + } + else { + $adj5min = $min; + $adj5max = $max; + list($num5steps,$maj5step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,2); + } + } + else { + $num5steps = 10000; // Dummy high value so we don't choose this + } + + // Check to see whichof 1:s, 2:s or 5:s fit better with + // the requested number of major ticks + $match1=abs($num1steps-$maxsteps); + $match2=abs($num2steps-$maxsteps); + if( !empty($maj5step) && $maj5step > 1 ) { + $match5=abs($num5steps-$maxsteps); + } + else { + $match5=10000; // Dummy high value + } + + // Compare these three values and see which is the closest match + // We use a 0.6 weight to gravitate towards multiple of 5:s + if( $match1 < $match2 ) { + if( $match1 < $match5 ) $r=1; + else $r=3; + } + else { + if( $match2 < $match5 ) $r=2; + else $r=3; + } + // Minsteps are always the same as maxsteps for integer scale + switch( $r ) { + case 1: + $this->ticks->Set($maj1step,$maj1step); + $this->Update($img,$adj1min,$adj1max); + break; + case 2: + $this->ticks->Set($maj2step,$maj2step); + $this->Update($img,$adj2min,$adj2max); + break; + case 3: + $this->ticks->Set($maj5step,$maj5step); + $this->Update($img,$adj5min,$adj5max); + break; + default: + JpGraphError::RaiseL(25073,$r);//('Internal error. Integer scale algorithm comparison out of bound (r=$r)'); + } + } + + + // Calculate autoscale. Used if user hasn't given a scale and ticks + // $maxsteps is the maximum number of major tickmarks allowed. + function AutoScale($img,$min,$max,$maxsteps,$majend=true) { + + if( !is_numeric($min) || !is_numeric($max) ) { + JpGraphError::Raise(25044); + } + + if( $this->intscale ) { + $this->IntAutoScale($img,$min,$max,$maxsteps,$majend); + return; + } + if( abs($min-$max) < 0.00001 ) { + // We need some difference to be able to autoscale + // make it 5% above and 5% below value + if( $min==0 && $max==0 ) { // Special case + $min=-1; $max=1; + } + else { + $delta = (abs($max)+abs($min))*0.005; + $min -= $delta; + $max += $delta; + } + } + + $gracetop=($this->gracetop/100.0)*abs($max-$min); + $gracebottom=($this->gracebottom/100.0)*abs($max-$min); + if( is_numeric($this->autoscale_min) ) { + $min = $this->autoscale_min; + if( $min >= $max ) { + 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.'); + } + if( abs($min-$max ) < 0.001 ) { + $max *= 1.2; + } + } + + if( is_numeric($this->autoscale_max) ) { + $max = $this->autoscale_max; + if( $min >= $max ) { + 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.'); + } + if( abs($min-$max ) < 0.001 ) { + $min *= 0.8; + } + } + + $min -= $gracebottom; + $max += $gracetop; + + // First get tickmarks as multiples of 0.1, 1, 10, ... + if( $majend ) { + list($num1steps,$adj1min,$adj1max,$min1step,$maj1step) = $this->CalcTicks($maxsteps,$min,$max,1,2); + } + else { + $adj1min=$min; + $adj1max=$max; + list($num1steps,$min1step,$maj1step) = $this->CalcTicksFreeze($maxsteps,$min,$max,1,2,false); + } + + // Then get tick marks as 2:s 0.2, 2, 20, ... + if( $majend ) { + list($num2steps,$adj2min,$adj2max,$min2step,$maj2step) = $this->CalcTicks($maxsteps,$min,$max,5,2); + } + else { + $adj2min=$min; + $adj2max=$max; + list($num2steps,$min2step,$maj2step) = $this->CalcTicksFreeze($maxsteps,$min,$max,5,2,false); + } + + // Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ... + if( $majend ) { + list($num5steps,$adj5min,$adj5max,$min5step,$maj5step) = $this->CalcTicks($maxsteps,$min,$max,2,5); + } + else { + $adj5min=$min; + $adj5max=$max; + list($num5steps,$min5step,$maj5step) = $this->CalcTicksFreeze($maxsteps,$min,$max,2,5,false); + } + + // Check to see whichof 1:s, 2:s or 5:s fit better with + // the requested number of major ticks + $match1=abs($num1steps-$maxsteps); + $match2=abs($num2steps-$maxsteps); + $match5=abs($num5steps-$maxsteps); + + // Compare these three values and see which is the closest match + // We use a 0.8 weight to gravitate towards multiple of 5:s + $r=$this->MatchMin3($match1,$match2,$match5,0.8); + switch( $r ) { + case 1: + $this->Update($img,$adj1min,$adj1max); + $this->ticks->Set($maj1step,$min1step); + break; + case 2: + $this->Update($img,$adj2min,$adj2max); + $this->ticks->Set($maj2step,$min2step); + break; + case 3: + $this->Update($img,$adj5min,$adj5max); + $this->ticks->Set($maj5step,$min5step); + break; + } + } + + //--------------- + // PRIVATE METHODS + + // This method recalculates all constants that are depending on the + // margins in the image. If the margins in the image are changed + // this method should be called for every scale that is registred with + // that image. Should really be installed as an observer of that image. + function InitConstants($img) { + if( $this->type=='x' ) { + $this->world_abs_size=$img->width - $img->left_margin - $img->right_margin; + $this->off=$img->left_margin; + $this->scale_factor = 0; + if( $this->world_size > 0 ) { + $this->scale_factor=$this->world_abs_size/($this->world_size*0.999999); + } + } + else { // y scale + $this->world_abs_size=$img->height - $img->top_margin - $img->bottom_margin; + $this->off=$img->top_margin+$this->world_abs_size; + $this->scale_factor = 0; + if( $this->world_size > 0 ) { + $this->scale_factor=-$this->world_abs_size/($this->world_size*0.999999); + } + } + $size = $this->world_size * $this->scale_factor; + $this->scale_abs=array($this->off,$this->off + $size); + } + + // Initialize the conversion constants for this scale + // This tries to pre-calculate as much as possible to speed up the + // actual conversion (with Translate()) later on + // $start =scale start in absolute pixels (for x-scale this is an y-position + // and for an y-scale this is an x-position + // $len =absolute length in pixels of scale + function SetConstants($aStart,$aLen) { + $this->world_abs_size=$aLen; + $this->off=$aStart; + + if( $this->world_size<=0 ) { + // This should never ever happen !! + JpGraphError::RaiseL(25074); + //("You have unfortunately stumbled upon a bug in JpGraph. It seems like the scale range is ".$this->world_size." [for ".$this->type." scale]
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."); + } + + // scale_factor = number of pixels per world unit + $this->scale_factor=$this->world_abs_size/($this->world_size*1.0); + + // scale_abs = start and end points of scale in absolute pixels + $this->scale_abs=array($this->off,$this->off+$this->world_size*$this->scale_factor); + } + + + // Calculate number of ticks steps with a specific division + // $a is the divisor of 10**x to generate the first maj tick intervall + // $a=1, $b=2 give major ticks with multiple of 10, ...,0.1,1,10,... + // $a=5, $b=2 give major ticks with multiple of 2:s ...,0.2,2,20,... + // $a=2, $b=5 give major ticks with multiple of 5:s ...,0.5,5,50,... + // We return a vector of + // [$numsteps,$adjmin,$adjmax,$minstep,$majstep] + // If $majend==true then the first and last marks on the axis will be major + // labeled tick marks otherwise it will be adjusted to the closest min tick mark + function CalcTicks($maxsteps,$min,$max,$a,$b,$majend=true) { + $diff=$max-$min; + if( $diff==0 ) { + $ld=0; + } + else { + $ld=floor(log10($diff)); + } + + // Gravitate min towards zero if we are close + if( $min>0 && $min < pow(10,$ld) ) $min=0; + + //$majstep=pow(10,$ld-1)/$a; + $majstep=pow(10,$ld)/$a; + $minstep=$majstep/$b; + + $adjmax=ceil($max/$minstep)*$minstep; + $adjmin=floor($min/$minstep)*$minstep; + $adjdiff = $adjmax-$adjmin; + $numsteps=$adjdiff/$majstep; + + while( $numsteps>$maxsteps ) { + $majstep=pow(10,$ld)/$a; + $numsteps=$adjdiff/$majstep; + ++$ld; + } + + $minstep=$majstep/$b; + $adjmin=floor($min/$minstep)*$minstep; + $adjdiff = $adjmax-$adjmin; + if( $majend ) { + $adjmin = floor($min/$majstep)*$majstep; + $adjdiff = $adjmax-$adjmin; + $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin; + } + else { + $adjmax=ceil($max/$minstep)*$minstep; + } + + return array($numsteps,$adjmin,$adjmax,$minstep,$majstep); + } + + function CalcTicksFreeze($maxsteps,$min,$max,$a,$b) { + // Same as CalcTicks but don't adjust min/max values + $diff=$max-$min; + if( $diff==0 ) { + $ld=0; + } + else { + $ld=floor(log10($diff)); + } + + //$majstep=pow(10,$ld-1)/$a; + $majstep=pow(10,$ld)/$a; + $minstep=$majstep/$b; + $numsteps=floor($diff/$majstep); + + while( $numsteps > $maxsteps ) { + $majstep=pow(10,$ld)/$a; + $numsteps=floor($diff/$majstep); + ++$ld; + } + $minstep=$majstep/$b; + return array($numsteps,$minstep,$majstep); + } + + + function IntCalcTicks($maxsteps,$min,$max,$a,$majend=true) { + $diff=$max-$min; + if( $diff==0 ) { + JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.'); + } + else { + $ld=floor(log10($diff)); + } + + // Gravitate min towards zero if we are close + if( $min>0 && $min < pow(10,$ld) ) { + $min=0; + } + if( $ld == 0 ) { + $ld=1; + } + if( $a == 1 ) { + $majstep = 1; + } + else { + $majstep=pow(10,$ld)/$a; + } + $adjmax=ceil($max/$majstep)*$majstep; + + $adjmin=floor($min/$majstep)*$majstep; + $adjdiff = $adjmax-$adjmin; + $numsteps=$adjdiff/$majstep; + while( $numsteps>$maxsteps ) { + $majstep=pow(10,$ld)/$a; + $numsteps=$adjdiff/$majstep; + ++$ld; + } + + $adjmin=floor($min/$majstep)*$majstep; + $adjdiff = $adjmax-$adjmin; + if( $majend ) { + $adjmin = floor($min/$majstep)*$majstep; + $adjdiff = $adjmax-$adjmin; + $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin; + } + else { + $adjmax=ceil($max/$majstep)*$majstep; + } + + return array($numsteps,$adjmin,$adjmax,$majstep); + } + + + function IntCalcTicksFreeze($maxsteps,$min,$max,$a) { + // Same as IntCalcTick but don't change min/max values + $diff=$max-$min; + if( $diff==0 ) { + JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.'); + } + else { + $ld=floor(log10($diff)); + } + if( $ld == 0 ) { + $ld=1; + } + if( $a == 1 ) { + $majstep = 1; + } + else { + $majstep=pow(10,$ld)/$a; + } + + $numsteps=floor($diff/$majstep); + while( $numsteps > $maxsteps ) { + $majstep=pow(10,$ld)/$a; + $numsteps=floor($diff/$majstep); + ++$ld; + } + + return array($numsteps,$majstep); + } + + // Determine the minimum of three values witha weight for last value + function MatchMin3($a,$b,$c,$weight) { + if( $a < $b ) { + if( $a < ($c*$weight) ) { + return 1; // $a smallest + } + else { + return 3; // $c smallest + } + } + elseif( $b < ($c*$weight) ) { + return 2; // $b smallest + } + return 3; // $c smallest + } + + function __get($name) { + $variable_name = '_' . $name; + + if (isset($this->$variable_name)) { + return $this->$variable_name * SUPERSAMPLING_SCALE; + } else { + JpGraphError::RaiseL('25132', $name); + } + } + + function __set($name, $value) { + $this->{'_'.$name} = $value; + } +} // Class + + +//=================================================== +// CLASS DisplayValue +// Description: Used to print data values at data points +//=================================================== +class DisplayValue { + public $margin=5; + public $show=false; + public $valign='',$halign='center'; + public $format='%.1f',$negformat=''; + private $ff=FF_DEFAULT,$fs=FS_NORMAL,$fsize=8; + private $iFormCallback=''; + private $angle=0; + private $color='navy',$negcolor=''; + private $iHideZero=false; + public $txt=null; + + function __construct() { + $this->txt = new Text(); + } + + function Show($aFlag=true) { + $this->show=$aFlag; + } + + function SetColor($aColor,$aNegcolor='') { + $this->color = $aColor; + $this->negcolor = $aNegcolor; + } + + function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=8) { + $this->ff=$aFontFamily; + $this->fs=$aFontStyle; + $this->fsize=$aFontSize; + } + + function ApplyFont($aImg) { + $aImg->SetFont($this->ff,$this->fs,$this->fsize); + } + + function SetMargin($aMargin) { + $this->margin = $aMargin; + } + + function SetAngle($aAngle) { + $this->angle = $aAngle; + } + + function SetAlign($aHAlign,$aVAlign='') { + $this->halign = $aHAlign; + $this->valign = $aVAlign; + } + + function SetFormat($aFormat,$aNegFormat='') { + $this->format= $aFormat; + $this->negformat= $aNegFormat; + } + + function SetFormatCallback($aFunc) { + $this->iFormCallback = $aFunc; + } + + function HideZero($aFlag=true) { + $this->iHideZero=$aFlag; + } + + function Stroke($img,$aVal,$x,$y) { + + if( $this->show ) + { + if( $this->negformat=='' ) { + $this->negformat=$this->format; + } + if( $this->negcolor=='' ) { + $this->negcolor=$this->color; + } + + if( $aVal===NULL || (is_string($aVal) && ($aVal=='' || $aVal=='-' || $aVal=='x' ) ) ) { + return; + } + + if( is_numeric($aVal) && $aVal==0 && $this->iHideZero ) { + return; + } + + // Since the value is used in different cirumstances we need to check what + // kind of formatting we shall use. For example, to display values in a line + // graph we simply display the formatted value, but in the case where the user + // has already specified a text string we don't fo anything. + if( $this->iFormCallback != '' ) { + $f = $this->iFormCallback; + $sval = call_user_func($f,$aVal); + } + elseif( is_numeric($aVal) ) { + if( $aVal >= 0 ) { + $sval=sprintf($this->format,$aVal); + } + else { + $sval=sprintf($this->negformat,$aVal); + } + } + else { + $sval=$aVal; + } + + $y = $y-sign($aVal)*$this->margin; + + $this->txt->Set($sval); + $this->txt->SetPos($x,$y); + $this->txt->SetFont($this->ff,$this->fs,$this->fsize); + if( $this->valign == '' ) { + if( $aVal >= 0 ) { + $valign = "bottom"; + } + else { + $valign = "top"; + } + } + else { + $valign = $this->valign; + } + $this->txt->Align($this->halign,$valign); + + $this->txt->SetOrientation($this->angle); + if( $aVal > 0 ) { + $this->txt->SetColor($this->color); + } + else { + $this->txt->SetColor($this->negcolor); + } + $this->txt->Stroke($img); + } + } +} + +//=================================================== +// CLASS Plot +// Description: Abstract base class for all concrete plot classes +//=================================================== +class Plot { + public $numpoints=0; + public $value; + public $legend=''; + public $coords=array(); + public $color='black'; + public $hidelegend=false; + public $line_weight=1; + public $csimtargets=array(),$csimwintargets=array(); // Array of targets for CSIM + public $csimareas=''; // Resultant CSIM area tags + public $csimalts=null; // ALT:s for corresponding target + public $legendcsimtarget='',$legendcsimwintarget=''; + public $legendcsimalt=''; + protected $weight=1; + protected $center=false; + + protected $inputValues; + protected $isRunningClear = false; + + function __construct($aDatay,$aDatax=false) { + $this->numpoints = count($aDatay); + if( $this->numpoints==0 ) { + JpGraphError::RaiseL(25121);//("Empty input data array specified for plot. Must have at least one data point."); + } + + if (!$this->isRunningClear) { + $this->inputValues = array(); + $this->inputValues['aDatay'] = $aDatay; + $this->inputValues['aDatax'] = $aDatax; + } + + $this->coords[0]=$aDatay; + if( is_array($aDatax) ) { + $this->coords[1]=$aDatax; + $n = count($aDatax); + for( $i=0; $i < $n; ++$i ) { + if( !is_numeric($aDatax[$i]) ) { + JpGraphError::RaiseL(25070); + } + } + } + $this->value = new DisplayValue(); + } + + // Stroke the plot + // "virtual" function which must be implemented by + // the subclasses + function Stroke($aImg,$aXScale,$aYScale) { + JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot"); + } + + function HideLegend($f=true) { + $this->hidelegend = $f; + } + + function DoLegend($graph) { + if( !$this->hidelegend ) + $this->Legend($graph); + } + + function StrokeDataValue($img,$aVal,$x,$y) { + $this->value->Stroke($img,$aVal,$x,$y); + } + + // Set href targets for CSIM + function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') { + $this->csimtargets=$aTargets; + $this->csimwintargets=$aWinTargets; + $this->csimalts=$aAlts; + } + + // Get all created areas + function GetCSIMareas() { + return $this->csimareas; + } + + // "Virtual" function which gets called before any scale + // or axis are stroked used to do any plot specific adjustment + function PreStrokeAdjust($aGraph) { + if( substr($aGraph->axtype,0,4) == "text" && (isset($this->coords[1])) ) { + JpGraphError::RaiseL(25123);//("JpGraph: You can't use a text X-scale with specified X-coords. Use a \"int\" or \"lin\" scale instead."); + } + return true; + } + + // Virtual function to the the concrete plot class to make any changes to the graph + // and scale before the stroke process begins + function PreScaleSetup($aGraph) { + // Empty + } + + // Get minimum values in plot + function Min() { + if( isset($this->coords[1]) ) { + $x=$this->coords[1]; + } + else { + $x=''; + } + if( $x != '' && count($x) > 0 ) { + $xm=min($x); + } + else { + $xm=0; + } + $y=$this->coords[0]; + $cnt = count($y); + if( $cnt > 0 ) { + $i=0; + while( $i<$cnt && !is_numeric($ym=$y[$i]) ) { + $i++; + } + while( $i < $cnt) { + if( is_numeric($y[$i]) ) { + $ym=min($ym,$y[$i]); + } + ++$i; + } + } + else { + $ym=''; + } + return array($xm,$ym); + } + + // Get maximum value in plot + function Max() { + if( isset($this->coords[1]) ) { + $x=$this->coords[1]; + } + else { + $x=''; + } + + if( $x!='' && count($x) > 0 ) { + $xm=max($x); + } + else { + $xm = $this->numpoints-1; + } + $y=$this->coords[0]; + if( count($y) > 0 ) { + $cnt = count($y); + $i=0; + while( $i<$cnt && !is_numeric($ym=$y[$i]) ) { + $i++; + } + while( $i < $cnt ) { + if( is_numeric($y[$i]) ) { + $ym=max($ym,$y[$i]); + } + ++$i; + } + } + else { + $ym=''; + } + return array($xm,$ym); + } + + function SetColor($aColor) { + $this->color=$aColor; + } + + function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') { + $this->legend = $aLegend; + $this->legendcsimtarget = $aCSIM; + $this->legendcsimwintarget = $aCSIMWinTarget; + $this->legendcsimalt = $aCSIMAlt; + } + + function SetWeight($aWeight) { + $this->weight=$aWeight; + } + + function SetLineWeight($aWeight=1) { + $this->line_weight=$aWeight; + } + + function SetCenter($aCenter=true) { + $this->center = $aCenter; + } + + // This method gets called by Graph class to plot anything that should go + // into the margin after the margin color has been set. + function StrokeMargin($aImg) { + return true; + } + + // Framework function the chance for each plot class to set a legend + function Legend($aGraph) { + if( $this->legend != '' ) { + $aGraph->legend->Add($this->legend,$this->color,'',0,$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } + + function Clear() { + $this->isRunningClear = true; + Plot::__construct($this->inputValues['aDatay'], $this->inputValues['aDatax']); + $this->isRunningClear = false; + } + +} // Class + + +// Provide a deterministic list of new colors whenever the getColor() method +// is called. Used to automatically set colors of plots. +class ColorFactory { + + static private $iIdx = 0; + static private $iColorList = array( + 'black', + 'blue', + 'orange', + 'darkgreen', + 'red', + 'AntiqueWhite3', + 'aquamarine3', + 'azure4', + 'brown', + 'cadetblue3', + 'chartreuse4', + 'chocolate', + 'darkblue', + 'darkgoldenrod3', + 'darkorchid3', + 'darksalmon', + 'darkseagreen4', + 'deepskyblue2', + 'dodgerblue4', + 'gold3', + 'hotpink', + 'lawngreen', + 'lightcoral', + 'lightpink3', + 'lightseagreen', + 'lightslateblue', + 'mediumpurple', + 'olivedrab', + 'orangered1', + 'peru', + 'slategray', + 'yellow4', + 'springgreen2'); + static private $iNum = 33; + + static function getColor() { + if( ColorFactory::$iIdx >= ColorFactory::$iNum ) + ColorFactory::$iIdx = 0; + return ColorFactory::$iColorList[ColorFactory::$iIdx++]; + } + +} + +// +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_antispam-digits.php b/web/public_php/admin/jpgraph/jpgraph_antispam-digits.php index 3015af0ce..d9d350ca4 100644 --- a/web/public_php/admin/jpgraph/jpgraph_antispam-digits.php +++ b/web/public_php/admin/jpgraph/jpgraph_antispam-digits.php @@ -1,205 +1,205 @@ -digits['6'][0]= 645 ; - $this->digits['6'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'. - 'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'. - 'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'. - 'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'. - 'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'. - 'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'. - 'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ; - -//========================================================== -// d2-small.jpg -//========================================================== - $this->digits['2'][0]= 606 ; - $this->digits['2'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'. - 'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'. - 'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'. - 'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'. - 'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'. - '7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'. - 'DLZ6f//Z' ; - -//========================================================== -// d9-small.jpg -//========================================================== - $this->digits['9'][0]= 680 ; - $this->digits['9'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'. - 'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'. - 'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'. - 'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'. - 'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'. - 'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'. - 'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'. - '1V1//9k=' ; - -//========================================================== -// d5-small.jpg -//========================================================== - $this->digits['5'][0]= 632 ; - $this->digits['5'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'. - 'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'. - 'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'. - 'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'. - 'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'. - 'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'. - '8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ; - -//========================================================== -// d1-small.jpg -//========================================================== - $this->digits['1'][0]= 646 ; - $this->digits['1'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'. - 'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'. - 'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'. - 'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'. - 'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'. - 'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'. - 'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ; - -//========================================================== -// d8-small.jpg -//========================================================== - $this->digits['8'][0]= 694 ; - $this->digits['8'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'. - 'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'. - 'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'. - 'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'. - '44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'. - 'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'. - 'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'. - 'EylmLHQltptPZKQOBo1FzH//2Q==' ; - -//========================================================== -// d4-small.jpg -//========================================================== - $this->digits['4'][0]= 643 ; - $this->digits['4'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'. - 'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'. - 'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'. - 'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'. - 'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'. - '27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'. - 'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ; - -//========================================================== -// d7-small.jpg -//========================================================== - $this->digits['7'][0]= 658 ; - $this->digits['7'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'. - 'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'. - 'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'. - '19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'. - 'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'. - '8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'. - 'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ; - -//========================================================== -// d3-small.jpg -//========================================================== - $this->digits['3'][0]= 662 ; - $this->digits['3'][1]= - '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. - 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. - 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'. - 'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'. - 'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'. - 'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'. - 'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'. - 'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'. - 'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ; - } -} - -class AntiSpam { - - var $iNumber=''; - - function AntiSpam($aNumber='') { - $this->iNumber = $aNumber; - } - - function Rand($aLen) { - $d=''; - for($i=0; $i < $aLen; ++$i) { - $d .= rand(1,9); - } - $this->iNumber = $d; - return $d; - } - - function Stroke() { - - $n=strlen($this->iNumber); - for($i=0; $i < $n; ++$i ) { - if( !is_numeric($this->iNumber[$i]) || $this->iNumber[$i]==0 ) { - return false; - } - } - - $dd = new HandDigits(); - $n = strlen($this->iNumber); - $img = @imagecreatetruecolor($n*$dd->iWidth, $dd->iHeight); - if( $img < 1 ) { - return false; - } - $start=0; - for($i=0; $i < $n; ++$i ) { - $size = $dd->digits[$this->iNumber[$i]][0]; - $dimg = imagecreatefromstring(base64_decode($dd->digits[$this->iNumber[$i]][1])); - imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $dd->iHeight); - $start += imagesx($dimg); - } - $resimg = @imagecreatetruecolor($start+4, $dd->iHeight+4); - if( $resimg < 1 ) { - return false; - } - imagecopy($resimg,$img,2,2,0,0,$start, $dd->iHeight); - header("Content-type: image/jpeg"); - imagejpeg($resimg); - return true; - } -} - -?> +digits['6'][0]= 645 ; + $this->digits['6'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'. + 'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'. + 'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'. + 'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'. + 'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'. + 'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'. + 'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ; + + //========================================================== + // d2-small.jpg + //========================================================== + $this->digits['2'][0]= 606 ; + $this->digits['2'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'. + 'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'. + 'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'. + 'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'. + 'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'. + '7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'. + 'DLZ6f//Z' ; + + //========================================================== + // d9-small.jpg + //========================================================== + $this->digits['9'][0]= 680 ; + $this->digits['9'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'. + 'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'. + 'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'. + 'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'. + 'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'. + 'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'. + 'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'. + '1V1//9k=' ; + + //========================================================== + // d5-small.jpg + //========================================================== + $this->digits['5'][0]= 632 ; + $this->digits['5'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'. + 'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'. + 'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'. + 'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'. + 'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'. + 'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'. + '8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ; + + //========================================================== + // d1-small.jpg + //========================================================== + $this->digits['1'][0]= 646 ; + $this->digits['1'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'. + 'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'. + 'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'. + 'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'. + 'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'. + 'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'. + 'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ; + + //========================================================== + // d8-small.jpg + //========================================================== + $this->digits['8'][0]= 694 ; + $this->digits['8'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'. + 'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'. + 'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'. + 'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'. + '44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'. + 'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'. + 'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'. + 'EylmLHQltptPZKQOBo1FzH//2Q==' ; + + //========================================================== + // d4-small.jpg + //========================================================== + $this->digits['4'][0]= 643 ; + $this->digits['4'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'. + 'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'. + 'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'. + 'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'. + 'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'. + '27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'. + 'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ; + + //========================================================== + // d7-small.jpg + //========================================================== + $this->digits['7'][0]= 658 ; + $this->digits['7'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'. + 'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'. + 'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'. + '19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'. + 'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'. + '8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'. + 'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ; + + //========================================================== + // d3-small.jpg + //========================================================== + $this->digits['3'][0]= 662 ; + $this->digits['3'][1]= + '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. + 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. + 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'. + 'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'. + 'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'. + 'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'. + 'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'. + 'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'. + 'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ; + } +} + +class AntiSpam { + + private $iNumber=''; + + function __construct($aNumber='') { + $this->iNumber = $aNumber; + } + + function Rand($aLen) { + $d=''; + for($i=0; $i < $aLen; ++$i) { + $d .= rand(1,9); + } + $this->iNumber = $d; + return $d; + } + + function Stroke() { + + $n=strlen($this->iNumber); + for($i=0; $i < $n; ++$i ) { + if( !is_numeric($this->iNumber[$i]) || $this->iNumber[$i]==0 ) { + return false; + } + } + + $dd = new HandDigits(); + $n = strlen($this->iNumber); + $img = @imagecreatetruecolor($n*$dd->iWidth, $dd->iHeight); + if( $img < 1 ) { + return false; + } + $start=0; + for($i=0; $i < $n; ++$i ) { + $size = $dd->digits[$this->iNumber[$i]][0]; + $dimg = imagecreatefromstring(base64_decode($dd->digits[$this->iNumber[$i]][1])); + imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $dd->iHeight); + $start += imagesx($dimg); + } + $resimg = @imagecreatetruecolor($start+4, $dd->iHeight+4); + if( $resimg < 1 ) { + return false; + } + imagecopy($resimg,$img,2,2,0,0,$start, $dd->iHeight); + header("Content-type: image/jpeg"); + imagejpeg($resimg); + return true; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_antispam.php b/web/public_php/admin/jpgraph/jpgraph_antispam.php index 9876fc5fe..7998df28f 100644 --- a/web/public_php/admin/jpgraph/jpgraph_antispam.php +++ b/web/public_php/admin/jpgraph/jpgraph_antispam.php @@ -1,625 +1,615 @@ -chars['j'][0]= 658 ; -$this->chars['j'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUGBAf/xAAsEAACAQMDAwMBCQAAAAAAAAAB'. -'AgMEBREAEjEGIUEUUXGBBxMVIiNSYWKC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/8QAGhEAAwADAQAAAAAAAAAAAAAAAAECERIh'. -'Mv/aAAwDAQACEQMRAD8A6veK2st8zRWSyV1dUBfvHaGVI4hknsS7AFv4AyM57ayWbqeS+11xtT2etttwo4YqhEqnQs5bcAfyk4AZ'. -'SOeD441TKRTyingUBG4/ah8j684+dSFzh/BvtaslejMUu9DPQTDnLx4lQ/ONw1TGBm0jdRWqguEMghEisWilgDmNs4Ze+MEEEH40'. -'aUVFTa7JeLjRXu4GjhmnNbSfqFQVlA3rkckOjH/Q99Glmkl0C/Q06pvsvT9vttXHDF6T1KrWbs5gRgQJM+FDlQxPhjpF1XcVq+qe'. -'jEoKiOecXBqh2TDDYIXLKuP6549xk8auI6aJqV45oknWdNswkAIkGMYIxjGO2NR1F0LZY5qkWqkS1xrM0M8lMSJpY+TGrnJiQ577'. -'cEgeNHhi7D3qC3UN69M8tIakRhgrh9o748+eNGtcCiKjjpkQKlMTEg3ZwoxtHHtgfTRpYXArvp//2Q==' ; - -//========================================================== -// lf-small.jpg -//========================================================== -$this->chars['f'][0]= 633 ; -$this->chars['f'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQFBgcC/8QAKxAAAgEDAwMCBQUAAAAAAAAA'. -'AQIDBBEhAAUGEjFBEyIHFFFhoRUzYnGS/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQP/xAAaEQACAwEBAAAAAAAAAAAAAAAAAQIRMRIh'. -'/9oADAMBAAIRAxEAPwDcnmLoIkiSYsouC3tA++O2lU9WkqVjJ+YdhZLsQI/4/YfQm50kZP0vbmaCSU0SRNIH6sghb9INs3t38dvp'. -'akUuz8x5DwdN5peS1jV1dSipSiVUigIcdQjQ26lIB/c6r3F86SZpE/zCFJaqsihQNhRgdj3Jyfxo0jDSbXHt9Oph9RAoV3qJGltY'. -'HDOxyb/nRpV0D3RXle21m48XraOk3IUSemUaV4g4Zc9ShcDtgff+tQfwvjq34Dtku7buamFqeJKemCCMxKFsEJU+/FrX8d76sEHG'. -'aNItzr4usVNdG3S0rmRYAVwEUmyjyQLZ11x7aF4zs9DQOyzml29I2cLa/pixIHi99DFCtU9dFuLIaijo9qiYPmR2mZmB9thgAHOD'. -'4+mjUrURyrUNMZFEkkIOFuFAbsP9d/OjVIQ6Vh4tP//Z' ; - -//========================================================== -// lb-small.jpg -//========================================================== -$this->chars['b'][0]= 645 ; -$this->chars['b'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYCAwUH/8QAKxAAAQMDAwMDAwUAAAAAAAAA'. -'AQIDBAAFEQYSIRMxUSJBYQcVI2JxgqHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQL/xAAYEQEBAQEBAAAAAAAAAAAAAAAAATERYf/a'. -'AAwDAQACEQMRAD8A6H95mxNYwLXcX+pCuilSLXJ6YSplaUELjqxwe4IJ5PIPamJ2V0bPcS7+NxCX1cHggAnIP+xSd9RyzHh2m7FQ'. -'Q1CvMNQWTjCt+HFD+PB/Y1fI1PL1HFFt0zaGblFdJQ9cJjpZiqPJUlBAKnPcEpGB5NNRKdrOl1NlgiQol4R2w4Sc5VtGf7opZteo'. -'LhdorjUSM5FnQnlR50NeHQysYxtVxlJHIPgjtRRD3xkaghs6juumdHz4+Y7RVPnt59K2mk7W+fcKWsZ7djTXMkW+xMP3GRJjwIEN'. -'HTG/CWx5wPY8AADx2NYk3SL9wukvUjGobnBkORksIbjdMANozgEqSo8qJPGO/wAVO36IsjUmBIfZfuM7epZk3F9UhSSk5O0K9Kcq'. -'8AcU3UzFuhUSBFud6nRXoz96mqmJZWg7m2dqUNhWBwdqQSP1UU5c/FFCn//Z' ; - -//========================================================== -// d6-small.jpg -//========================================================== -$this->chars['6'][0]= 645 ; -$this->chars['6'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'. -'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'. -'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'. -'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'. -'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'. -'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'. -'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ; - -//========================================================== -// lx-small.jpg -//========================================================== -$this->chars['x'][0]= 650 ; -$this->chars['x'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABMDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUHBgj/xAApEAABAwMDAwQCAwAAAAAAAAAB'. -'AgMEBQYRACFBBxIxFCJRgRNxkcHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEQH/2gAMAwEA'. -'AhEDEQA/AH9t3pKvO14UykVARa/HfAlxlDKXR24V2p3z7RlPwdtMep91uWdRGHWELjuTFFtLvcC4SNznnH+21O7ttiodOq1BvC0E'. -'p9I0lSX2kgqCSklK+5PKCMAng6zV2XRO6u3lSIURtbDRShltlZHa0tW7q/0MeTwnjxq1Jiw2xc9xTLbhSVU5iaXUFfqFFILgJOCd'. -'9Gt3SXabR6REpkL8yo0RpLCFNx1qBCRjOQMHxo0pEr6o3um2LVYpMEpTVqg25lHn08dfcB9kEgfZ1LIFDuawqZRb7aQlLTzqglsg'. -'9wQdveOEqBIB425xqhQuk8qo9UKlPrlRblw2ZBeCSVKW6CcoSrI2AGOT41SKzT4dYtmdS5bIXDZhNoWgbZJ94x8AYT/GkM03oNUc'. -'uKgwqtTZDTMOU0FttqRkoHggnPkEEHRrkJ6t1SlSHYUOc6zHaWrsbQrATk5/vRqK/9k=' ; - -//========================================================== -// d2-small.jpg -//========================================================== -$this->chars['2'][0]= 606 ; -$this->chars['2'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'. -'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'. -'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'. -'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'. -'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'. -'7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'. -'DLZ6f//Z' ; - -//========================================================== -// lm-small.jpg -//========================================================== -$this->chars['m'][0]= 649 ; -$this->chars['m'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAcDBAUCBv/EAC0QAAICAQMCBAMJAAAAAAAA'. -'AAECAwQRAAUSBiETMVFhB2KhFSIyQVJxgZHB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREBAQEAAwAAAAAAAAAAAAAAAQAR'. -'EiEx/9oADAMBAAIRAxEAPwB0MI2lIdgI0Cly3kFXLEn2zx1FDdp7rbpbjUtRWKio3hyxOGQllJzkegX66rQ2qW87Zuk9S5FNVmru'. -'iywyBhjDKTkeXfSr+GRfYtq2KAO32b1BGxAZu0dyJ2DKPTxY1wPddVszycUq2Golq8jRWbcnJWwCVGMjz+VQP50atxMtm2ZUOY4l'. -'4qfUnBP0x/Z0amy4jJm10Tt2yddWasFmfaRfdrlG3UcgArnxKzJ+Fu4DqCMkcgNem2DoWav8PLfTm+FPEkuSNTnqueS5bnHIv6CG'. -'LNjJwM99bm67NB1Ht89KSxNXnr2hNDbiUc47K4KyD2GQMfmMjUnS+7vuIktTqPCaaWCqAMMojPFyw8hyYMQBnAwNJHYGXPTsW9VN'. -'jg2zf50W9zk524GAEihuz+xbIOD82jW5TkjtRPZkTkJ+4VgDhQfuj/f3OjUxl1f/2Q==' ; - -//========================================================== -// lt-small.jpg -//========================================================== -$this->chars['t'][0]= 648 ; -$this->chars['t'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAJxAAAQMDAgYDAQEAAAAAAAAA'. -'AQIDBAUGEQASEyExQVFhIjJxFSP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAP/xAAZEQADAQEBAAAAAAAAAAAAAAAAAREhMUH/2gAM'. -'AwEAAhEDEQA/AO4BLEiEy7uG4IGxxs5IOOx76wd2XYidSp1HoD70240gcNNPbDyI6wQQpaz8E9MczkdhqtbsKYLieDk6WLKmZmmL'. -'Hk7AHVkbkLI+RQc7uRxgkfr1tx2rGu6VbToLVKkhU+kbugGf9WfaknCk5ycaX0zmaa+3JkqvW/CmzojsB9xoF6OoFK0r6HOcEDI0'. -'aefTuKX5ScMdC14HYq8n12zo1DEUcKTGg1Z+hyBwoPBVIiA/VQyOIgedhUCB4WMfXSV3UufVLcTUIqVf26K6mXDbPVRRzKT54iMg'. -'+zjtq6mtsyJjclxpKlUhSXEbkgkqWnBx4+J5e/zU0pZemPvJJQzEPDfQOrwwFY9AZ5eeYPLV6FwhoFYZuigxpkJeIjqAeIoAk9wA'. -'D46EnuD+6Nc1smDNrTlRkxqtMo1vzKhIdYgU9YDqVpISrLhHxSSd21I0aYyqP//Z' ; - -//========================================================== -// li-small.jpg -//========================================================== -$this->chars['i'][0]= 639 ; -$this->chars['i'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABwAGBP/EACcQAAEEAQMEAgIDAAAAAAAAAAEC'. -'AwQRBQAGEiExQVEHExSBFWFx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgMB/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECMRH/2gAMAwEA'. -'AhEDEQA/AE7c+5M9BeRG29t1WUfKFFYW+GvrI7WD3B9g140YD5T36rcErDjbUR6dCBdejsKUpxITXI2FUrooCh70yvxzHyIlMvuK'. -'eVSH7IKEpJoKqu/ahddLryR/aMiO187bsmrWShhp1AZS2XHHrWhNJrzdf7f7GiVcHk3sptmHkJcJ2DIftS2FrKlJPXudWuLGYeQp'. -'t2fmEIckqIZaaKuSGG0lQ4gduRoFRHQ9AOgs2lOJbk9aSUlpjGvAWeSVH2VKq/2dFPw3IjyJe8s281ct3I9UoHJXGiQkD2STrSZ7'. -'Yf8AOl7JTdw5eOCz0jw3+LbYCfA9nz71msb8KMxoTGTw+5srjsipAdDqFBQBIuiOl6KrdYyJMyTCshlw2G3Fr/HiNqNNAqJJUoGl'. -'KND+h47km1bZwsvCbYYjycxIyK1qDv2yEi0hQviK8atKDcy9j//Z' ; - - -//========================================================== -// lp-small.jpg -//========================================================== -$this->chars['p'][0]= 700 ; -$this->chars['p'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAECBAUGB//EAC8QAAEDAwMCBAMJAAAAAAAA'. -'AAECAwQFESEABhIiMRMVUWEHFEEWIzIzcYGRocH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAcEQACAgIDAAAAAAAAAAAAAAAA'. -'AQIxAxESIUH/2gAMAwEAAhEDEQA/AOh703xG21DMeOyqoVNDjSzERiwU6Ep5qtZNycA97HTF13d33KWtmlt9xwkLl1NkXVxIuQgK'. -'wLj+hqBvel0qmbR8GnR22nJNZiLeeKr8nDIT1OLJucX+uPbWom7iocRpafOac5MX1ALltp/Cbi+cJH++utdh+WVNL3PNdNYpdWgx'. -'Y0qmLZSrwJJcQoOJ5XKlJFu4HbJOjVbt+V5nu7eopNRivqcdhK+bFnWwA1Y2AOcgjvj9dGlxy0g5y0xd+hNXoG24C4obizq3HZUh'. -'YHqtRHD06bG/8a0MbbG1mqekxaBSGmgkrcdcitlLfrckZIz7DUatbeFak0tyRLUwzT5vmiGm0cufEkFBJItfkD+59tKmiO12atFa'. -'eQukO3ejUxgENqTcfnE5WbkHiOnJ76N2IqI1DibabptS+zkZhtp90F2Y0S026EkAFK/qL46cXv65NVZDfxHmVCK4DE2/RX/lRFbA'. -'C5LwAyq2EtpHZI7mxPYDRqoctdESimz/2Q==' ; - -//========================================================== -// le-small.jpg -//========================================================== -$this->chars['e'][0]= 700 ; -$this->chars['e'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABgDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYEBQcB/8QAKhAAAQMCBAUEAwEAAAAAAAAA'. -'AgEDBAURAAYSIQciMTJBE0JRYRQVFoH/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREAAwEBAQAAAAAAAAAAAAAAAAERAjFB'. -'/9oADAMBAAIRAxEAPwDTszvhEYCoS80BTm2bCjQRwdAzVe2yopkpJtpRUVfjEIc4V2oMerByg5Ji30oMyS3GeMunK0upfnu09MdJ'. -'p2scTmWnnGfx6HThktgLfKj7xEOqyr7QBbL41LhBzpxbcOru0LKDLdSnOHoaltNqSC4qWL0x9xbJYum69caczSaHmGmTmpDUYn4l'. -'UiqjkynzAVtwV23Ud+X4Ibpa2DCPkjhfUaRO/p8yzpb+YHhUmhbev6ZEll1lvqK3jt2XrbBgp6HVwsK3THpfEubGSoOUyFMpbJmL'. -'Deh6SgOGKti57EuY6l62JMWdJy7k3hg1LkOozEbVm7suQSkTiKtkEfP1pH664Za/QItccgI4bseTHdNxiXHLQ8yVl7V32XyioqL5'. -'TGc1ng6eYs0idczXUZscBBABWgEhEtfKNuUezwPnBhEuj8X2M21z9BR6NUX211Kk/UKKAjuhkPhL7XVf8vtgw7UPJlEyrDWFSYLb'. -'LBNF6qrzG6t0spEu6+fpL7YMXhUndp//2Q==' ; - -//========================================================== -// la-small.jpg -//========================================================== -$this->chars['a'][0]= 730 ; -$this->chars['a'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABoDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwIFAQcCBwAAAAAAAAAB'. -'AgMEBREAEiExQQYHFBUiUXGBE2EyQkNSgpHh/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAMBAv/EABkRAAMBAQEAAAAAAAAAAAAAAAAB'. -'IQIRMf/aAAwDAQACEQMRAD8AfdQ1pxjqZMSn0mRUZRYDaklJCE3OawO2ttTxY4hl07qFMVs1Ku02kpPnRGhsAqz8W9T9wDjozq6o'. -'Q1lDrcZLGVcmUoZg0obpufxK3Ftt9ccqB1GgBcmLSqtVEqOZcr6ARm/kbXHt7DEtc7WTJKTJqEWvRKfLqL9QplSjuPtGVYOJKBrm'. -'t+U+n94WGStZzNypmRWqckUKTbixy6jAfxPxHtCgKqFNlU5huK6pLMndSlegG4J45N8aKmTMKQRBsCNMzwB+RbHWHGEAZlPZX2hx'. -'qZIC34ygZoYUbB50JSkFXFhZR9BrpheR4fIbQ6gvurJ7q02bIQTuAOAN8x40HAxRr3TrNRpBmSHVt1KMlTyJTCsqkKAPlSf28W+c'. -'UGaD1c9HSR1HFUh9tJU45EBcAtcC9+P9wqbg8IAto9o81yputrVGpiUkgHKkqUTZI32+cKm1z1tIUgPBBAKQ4UBQH3uL3xmXSXep'. -'HVDtXStE5K5jlPU7PF3Q41+okJFkjgC+3OuNSYiSzHaLtRcW4UDMpLYSCbakDW3thhum5p//2Q==' ; - -//========================================================== -// d9-small.jpg -//========================================================== -$this->chars['9'][0]= 680 ; -$this->chars['9'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'. -'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'. -'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'. -'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'. -'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'. -'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'. -'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'. -'1V1//9k=' ; - -//========================================================== -// d5-small.jpg -//========================================================== -$this->chars['5'][0]= 632 ; -$this->chars['5'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'. -'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'. -'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'. -'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'. -'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'. -'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'. -'8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ; - -//========================================================== -// d1-small.jpg -//========================================================== -$this->chars['1'][0]= 646 ; -$this->chars['1'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'. -'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'. -'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'. -'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'. -'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'. -'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'. -'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ; - -//========================================================== -// ll-small.jpg -//========================================================== -$this->chars['l'][0]= 626 ; -$this->chars['l'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYEBQf/xAArEAACAQIFAwIGAwAAAAAAAAAB'. -'AgMEEQAFBhIhFEFREzEHFSIyYcFxgZH/xAAXAQEAAwAAAAAAAAAAAAAAAAACAAED/8QAGhEAAwEAAwAAAAAAAAAAAAAAAAECMREh'. -'Qf/aAAwDAQACEQMRAD8A15Zfm1VURj1Fp5AqLKv3OARcL4W5Nzx+MLWjdRz5hqXU6TSb6OCr6WghiQbrJ91gOTy1yT5xZ55myZFk'. -'Gb5ozX6Ondm28XYqpQDwu7jEH4c5S2UaDy4xxrLmlUDWzk8XaQ3O49hbj+RiB85HNg8Ee3aqwIqhDuux7G/HHbvzgxEqaWOvy09R'. -'O0o3hjdQoUji20g+fY3wYSM6pJ4Ylr7V+Zz5PSaezHTlTRNWzxySSxt6q1MSkH6AOT2Fu3Aw7RfF/T9DEkLUeawuF2mKSgdWQj2/'. -'q3+fnDZDlqRZzQGaOGcpTOaeR1u8R+ncN3gj94so2jNWHeMNNKzorEX2qp9v3imNPoRE1zpjUtZ09HJmYq5lury0benZeTww23t3'. -'Ivgw+T0yRRyyxIqNfkLcA8jt7YMKcBWn/9k=' ; - - -//========================================================== -// ls-small.jpg -//========================================================== -$this->chars['s'][0]= 701 ; -$this->chars['s'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAMCBAUGB//EACwQAAEEAQIFAgUFAAAAAAAA'. -'AAECAwQFEQAGEhMUITEiYQcjQVFxFRZCUoH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAZEQADAQEBAAAAAAAAAAAAAAAAAQIR'. -'EiH/2gAMAwEAAhEDEQA/APWZMhmFXSJU+SGmWFiQtAWMJQAnJUr8Z+w/OuQk71uZnMsqnbjy9s8st9UMCQ6kZJdZaIHEkZ/JHceN'. -'N3HtizuY1JLrG48yLBSC9UTFKQiY4nACir+wAOOMEe2rm2bTbzlqtE1MyBuZAPybpw85KSfDRJ4Cg+Pl/wC61hJeGjV31VuuKqwr'. -'LGU+whZZK+Rw+oYJAyj3GjS4dZFpZVkqPLktdfMXNcaU2kBC1BIITkdx6c599GlnvPAa3TL2vNvU76n0063acr3YSLCEjpUpUQtW'. -'Dhf14SMEnOc57aZ8Tegm7dbrEQGZt1PeTDgc1PEW3FeXAvyAkZVkeMDOm2G3f3O7Cl/qEuqkQg4lp6CRxraWfUlRUD24kZA741Ko'. -'2k1HvlT3ri2sLOCgtsyJz6XEtBwZPAgJAGQMHUNPWKqWItsqh0UCFVyLeKhyLHQ2TMdHNVj+RKlAnJyfto1FW2ahgjrq6LYTFjjf'. -'lymUOLdWfJyoHA+gA7AAAaNPE3ysJdLT/9k=' ; - -//========================================================== -// lh-small.jpg -//========================================================== -$this->chars['h'][0]= 677 ; -$this->chars['h'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAIDBAUGB//EACwQAAIBAwMCBQIHAAAAAAAA'. -'AAECAwQFEQAGEiExExQiQVEVggcyU2GRocH/xAAXAQADAQAAAAAAAAAAAAAAAAAAAwQB/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQAC'. -'AyEyMf/aAAwDAQACEQMRAD8A6DZb95q9bmpK6ieOCzNHJTxmE+NMhQ5fr1fLq3Ejvkak2e7ipiFsqb3R0m4qkPPJRiRXenU9VjKE'. -'5JVcA9R7nWc3/BUbfoKTdO3VRXhpjbZ2D8Rwk6RyZH6chB+46m7i2hDYtgA2ePlV2VkuKysoLzzRnlIScZJZeeevvjtrX7LK2rp7'. -'tTwwJ9WjhILDrTKnIdMEDl2+P80aVdJZb1QW+vgqENLPH4sBCDLIwUgnOf4GjVvDnLgUk79T81voqjb8NnuUx8pVRCiEaYUSuynl'. -'jHU9mOfnOoOx6hqz8PrbNdfEkMUXg1LSM3rKOUywJ7YAJ1ZTWmSpvdvlaVTDSUzJAhH5ZJBgv0x2RSAPlz21WXqoet3ba9nuW8n4'. -'Jr6qTPqnUNxSM/f6mPvxA9zqJnExTbR+h0nkhVu1uE8j0UBRQ9PGxBKFjnkAScdsDp10a0lc7z0tI7Y5YYN+5GAf7GjVXF4Icj3f'. -'/9k=' ; - - -//========================================================== -// ld-small.jpg -//========================================================== -$this->chars['d'][0]= 681 ; -$this->chars['d'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFBgH/xAAsEAABAwMEAAQFBQAAAAAAAAAB'. -'AgMEBQYRABIhMQcTI0EUMlFhkRgicaGx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgEA/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECETH/'. -'2gAMAwEAAhEDEQA/ALUhp6h3W/X63UlypbhCY0WMjLqGzwDtPCfv/WtealNpVInuVBBqCogcdbU36YUkAkJWVHG8YPXBxxzxqPcN'. -'YtWyWnIlUeW05VEOAvrCnnSkftK1H5lKJPHsMDoDUWq+KdrSbIqsalVsImiEtLUZ2MU71bcYJWkhZ/36ayLHhi/IXZVOmzKqp5uU'. -'688hTyjuGVEFJKvoQesD86NL2jGZp1EoLDSmk+ZAQ8d7oPzp3YGesFWMfxo1YGvSzLsT9QExVX8phTlMaFOExAJIBGQjJwCcL+/e'. -'rd+W7GuO0Kw05CQ6+ww69Gfdb2kFIKk7DgEkjgnr86rXRa9HuyP8LV4SH0sIBbWFFDiFEgDaocgdkjo8ccay0qw7ut5nyrcviQqC'. -'slsRKo0HwlODkBRzxj2AGoXTtpzIdQ8MbffUChz4NCPRaClAo9Mn6c7T3o13wytmo0K05VIqkiPJbizFiMWs4CTgnIIHOST796NL'. -'Ia1JX//Z' ; - -//========================================================== -// d8-small.jpg -//========================================================== -$this->chars['8'][0]= 694 ; -$this->chars['8'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'. -'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'. -'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'. -'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'. -'44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'. -'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'. -'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'. -'EylmLHQltptPZKQOBo1FzH//2Q==' ; - -//========================================================== -// lz-small.jpg -//========================================================== -$this->chars['z'][0]= 690 ; -$this->chars['z'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgAHA//EACsQAAEDAwQBAwIHAAAAAAAAAAEC'. -'AwQFESEABhIxBxMiQVFxCCM0UmGRof/EABYBAQEBAAAAAAAAAAAAAAAAAAECAP/EABgRAAMBAQAAAAAAAAAAAAAAAAABEVEC/9oA'. -'DAMBAAIRAxEAPwBTWfLu1KXXZDbM4uewNvLajlwhaCbBAwDe5uehYd3xm6t6bi3jvulwqc7KgxXZZeYQLNLeF73WRg4HEdgfzrSa'. -'P45pNEkznITDc9ypLShtyWhJDJyXC2qxJHZvjoZOjyVv1v8AESt6FFS4ijxvTLbawEApSccrYHJf0+OtJMQ2rNXk7GZMufJgJjTH'. -'Un9M4qzxT7hyCiThIyRnPXWrRvyLElVBUF6vlhl0lwRYCFKcQhAtyWpVhyWTx+w++rUvp4EWjOvbniUOnVatcS43BYDbJSPZyIBw'. -'ejclIx+3Wa+J63T6DQanuGszI0eZVJJV60p0Jum5GEi6le7l0PjvSjyRsaTvJqI1BqhhR46ksuMrQVJcUSEoUbHNr/7o7C8L7eiz'. -'4lLlyJk2cEqW+6V+m0AE9ISLnsj5+O9UhsFK92bZZqb9SRu9p2c4A0OCEqDbYAJSlJwAVZv3fBvbFrg/462btlhuS1RG5nL8pYkq'. -'KrnsKH06I/rVrQKkf//Z' ; - -//========================================================== -// d4-small.jpg -//========================================================== -$this->chars['4'][0]= 643 ; -$this->chars['4'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'. -'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'. -'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'. -'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'. -'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'. -'27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'. -'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ; - -//========================================================== -// lv-small.jpg -//========================================================== -$this->chars['v'][0]= 648 ; -$this->chars['v'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAKBAAAQQBAwMEAgMAAAAAAAAA'. -'AQIDBBEFAAYhEzFBEhQiYQdRFTKB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAERIf/aAAwD'. -'AQACEQMRAD8A6Ngt1SZ4yrYgrecgTFsFJA9aGwAUrUaF2D2Avjzq6CIjiBPkB9bwQVIkIYIDae/wq+P9N+dY4SGMf+Txlev7KBmY'. -'PoadKRy4zxSgRxaTwO/x09u7KPYnasmHjlsyFZZXt4K23ezjvBpNGgLUrvXfVZyLLbWambiwEbKvvxYAkeotNlIJW2FEJWb7WBda'. -'NSQI0fHYyJjkrjKRDZQwnpQ1vgBIr+w8+a+9GocZr8iKkuY1eXhsKH8U8iZE9BHz6ZHUc48UfSPqzqH3kfeO9kTTDQYGGietpTaO'. -'shyW6AocpHNIrv8AvWzk9BUSdPdYS4BcRlomkhIV6KP0VE39V+tU2wdlRMHtZUB8NuTQ+51X27+Kr46ZPIAFV540D8zeLsJ5LMHa'. -'ubmMBCVJdjx0pRyLoWR4I8aNIQ8BvZMNtMTeUcsptKfc4tC1gAkCyFC+K0aJtf/Z' ; - -//========================================================== -// lk-small.jpg -//========================================================== -$this->chars['k'][0]= 680 ; -$this->chars['k'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBAMH/8QALhAAAQMDAwIEBAcAAAAAAAAA'. -'AQIDBAUREgAGITFBEyIyYQcVUYEUIzNicZHx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEE/8QAGxEAAwACAwAAAAAAAAAAAAAAAAEC'. -'AxESMeH/2gAMAwEAAhEDEQA/APVK/V36dU6NSJDTT8esPLiqfK8S2cCoeTkKvZQ6jm2ldSqKqbu+OgMOvSX3m4UBrLnDlbqiefKl'. -'Nzz2x1m+IwNP27CkJQ7JkR6rCkMJbP5jp8S2CPfkgD6H+dJ6Ca0nerr+64rTNSqMYrg+C9mmOwhVpDfsuxSbi97DmybaoZeQ5jTl'. -'PEp18JTIfeW3kq3ly4H26aNZqvTWZsjFcZTsVtSg0G8Rio+vr2vb7g6NLPRnuXy8F+8kl+obUh4KXJdqSJJQnohlkZqJPYBXh3P+'. -'a4b5Hyp6k1bO7sOotPyXkj9NlwFl0ewstJA9ifrqkVSmET4csoS7UTHXFQ+6SQlskKUMb/tH9ddLVUmS7DqdBqD7U6OsqfS46jzl'. -'hQ5bXb1K9Scuybdxo2OTu92dwSZkWn0Sb8viQWyn8Qq5D6ifSLd0BIv7q0arTBRSKPToMZbi2GWylsvLK148Wue/XRrRjxOpT2R2'. -'k9aP/9k=' ; - -//========================================================== -// lr-small.jpg -//========================================================== -$this->chars['r'][0]= 681 ; -$this->chars['r'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAGgAAAgIDAAAAAAAAAAAAAAAAAAYCBQMEB//EAC4QAAICAQIFAgMJAQAAAAAA'. -'AAECAwQRBQYAEiExQQdRFGFxEyIyM0JSYoGC8P/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/EABcRAQEBAQAAAAAAAAAAAAAAAAAB'. -'EUH/2gAMAwEAAhEDEQA/AOs0ZdETU54Gt1INSmlPJEsyo7J+jlXPUYBPY9c+eE/dO9tY0a7ren6BVrW7VJTZtW5kZkjXkBSIKveQ'. -'gHp0AAJ4w+q2hVdT2Md0h46+saS4mr3EUK0gWTAB+vQj2PboeL/ZVOqmhaZVjkFmxdC6tctt3tM2G5/7bAx4C4+qxiWwd3prWzKe'. -'r3IBAth5OYxozKsgc8y4GTgnJB9uncdTi6tXq2140rRVM13JMEMAVAg7sMdBjJB/18uDgRO9R2Oo6FX2vShkFzURFUq1whIj+8DI'. -'7EdAFjXv7MeNb0kuStsFEmIaajZaos2fy2Q4VGH7SGxn+Rzw9yMLOm/FzRhZazmOTkP4grYyD3B8j2PTyeFfZ+z7G3BeSS8lmprl'. -'2K2qcnK0Z5S8gPjrgAY8cNEWmq7u23pEos6/Zji+Kd0rLLGWwseA3joeZj/w4OET1g0vlmrWV+ydFnkUxSgsvM4V+YYIwfHz6cHB'. -'ZeKZ1//Z' ; - -//========================================================== -// lg-small.jpg -//========================================================== -$this->chars['g'][0]= 655 ; -$this->chars['g'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQCBQYH/8QAJxAAAQQBAwQCAgMAAAAAAAAA'. -'AQIDBBEFAAYhBxIxQRNhcYEiQlH/xAAYAQACAwAAAAAAAAAAAAAAAAACAwABBP/EABkRAAMBAQEAAAAAAAAAAAAAAAABAhEhIv/a'. -'AAwDAQACEQMRAD8AayO4t6bq3hmMHtxyLi4OKeKH5jyASiiQCCQeTRNAeB61FrBb+jTGpLO+BMW24EFMhkhpQru8m7B/H70x09Yi'. -'q3nv/vLfwpnJ7UNkqSRbngf2ofWkpXV7brymC2malLfagurjW0aHk89xPJ9cX9aprURHWbYEaMHHEBfwpv8AnXPk+/8AdGqGJOxO'. -'4YbOSxK4y4boIStUWysgkEmxY54r60aOI8oTV9MHtjJwunPUbO46WWo0HLlD8KY4goboFVoquOVEVwLT963WdnxYfT6ZJyz0JvHm'. -'KvtaSkW4tYNVSqKiTwB+fw5n9sY/cuOXCzDDcluyW3Ckd7V+0n0eNZTH9DdouFalHIOJBUhtDki0pNV3UALo81ehG6IdKjPZ6d47'. -'4ywltanVJvuJI+RQs/sHRqy2r003JhsImEc/CUyhxRZBjKV2oJ8eRXNmufPnRo1WIz3DdNn/2Q==' ; - -//========================================================== -// lc-small.jpg -//========================================================== -$this->chars['c'][0]= 629 ; -$this->chars['c'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBwID/8QALRAAAgICAQIEBAYDAAAAAAAA'. -'AQIDBAURACExBhIiQRMVUWEHMkJScYFykaH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/xAAXEQEBAQEAAAAAAAAAAAAAAAAAATER'. -'/9oADAMBAAIRAxEAPwDcoGkmiT4Q8kWvzuPU38D2/v8A1zwrCFayq1qTaFk2H7aJHt05MeMvENzC4upDWkjW9kJXiricAJCigvJN'. -'IB1IVQT5frrv24twPgunk6a288crbklUSJNNdnSTZ2STHHqOP/Eb17njdZtAoqwEvrEiGVyG117/AG6HhyV8H1sljMldoxXTksGC'. -'zV7M0oaWGQOVeGQ92I6EMR22D11w4LmEPjaOL51iL8ssc9Z69zHtZkYCGGeQK0ez2UEoU39wCeX1S/LLiEt+mPSbMLxsGVv2kEjR'. -'305xkaEV/GTULMUT1LD/AAGh8gIZS2jv+vpybb8NMIb0dVLWYWgiiU0vmMphOj6V0TvQI3rfsON1E6dYjGtisa0F1mAWR2NhG0WZ'. -'3Ls3TqNs5Hc9h23w49NWL9K+Q/VD5T/zhwPH/9k=' ; - -//========================================================== -// d7-small.jpg -//========================================================== -$this->chars['7'][0]= 658 ; -$this->chars['7'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'. -'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'. -'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'. -'19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'. -'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'. -'8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'. -'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ; - -//========================================================== -// ly-small.jpg -//========================================================== -$this->chars['y'][0]= 672 ; -$this->chars['y'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQGBQf/xAArEAABAwMEAQIFBQAAAAAAAAAB'. -'AgMEBREhAAYSEzEHIhQkQVGxQmFxgaH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAQL/xAAeEQEAAgEEAwAAAAAAAAAAAAABABECAxIh'. -'MUGR8P/aAAwDAQACEQMRAD8Ar3tys07dVHohemz5dWQ7fk91MsA3IIRY8rkKFySceTqw3JVV0KhyKw+0C1CQp9aUOFSiAk4AIAvn'. -'76xtz0ioVvbcJ6msx2JtOfZmw1PKI5LQcJNh7UqBKcn6+NRfqPu6s1fYc6GxSJsRfWDUVSGA22ygEckJWSexRNgOP0udXzDKOJ0I'. -'yo62mHm25Sy80l1Z4lSgpQvZRGLgWwPGjTjbchyLH+Ejx22EtJSgO8kki3kADA/nOjWjGzv73CyQZjUWNVp7bNSrj7qJDqflqUlQ'. -'DMds24l3HvcNr3Pi9gME6T9WWVsemdYWswwC2lPta4m5WMA3OdUExCmozUJD6g84ntMjrHIFBTdQz5yLDx/WDNytpwW6nAkViqVe'. -'uvmXdlme6n4dCwlRBKEgA2tj99QG7Ilncp5QqpU31PMsJ6x7A32f6SPxo0hPVCD45oVyKf0MtgeT97/nRrO7UOCFla3tn//Z' ; - -//========================================================== -// d3-small.jpg -//========================================================== -$this->chars['3'][0]= 662 ; -$this->chars['3'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. -'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'. -'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'. -'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'. -'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'. -'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'. -'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'. -'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ; - -//========================================================== -// ln-small.jpg -//========================================================== -$this->chars['n'][0]= 643 ; -$this->chars['n'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGwAAAgEFAAAAAAAAAAAAAAAAAAYCAQMEBQf/xAAtEAACAQMCBAUCBwAAAAAA'. -'AAABAgMEBREAIQYSE0EHIjFRcWGRIzIzQoGCwf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAP/EABkRAQEBAQEBAAAAAAAAAAAAAAEA'. -'AhEhUf/aAAwDAQACEQMRAD8A6FR3p7v4oV9rlkMQsjL00RyOss0KkFxnDcrc2PbI1NOJKyTjW+W5OmKeA0UEJx5meRZS2/8AUfbS'. -'LVGS1+K16vCzfiR3GmoqqXGyxz06hWPsFlVMfOmq1iNvE69KjBYo3oJMZ3GKeYYPxg/fW+xzZX1FLQyxwSTcpWNceu4G3+aNSmpY'. -'qmQzzwh2k8yhv2r2H23/AJ0aoy+EWh7I1ntacR3PxDtEzhjWy0wkkIwYmanU5GO6sNh7rrU8AVdTceNbhDXxNHUQvS0tZ3DzwxVA'. -'fB7hj59/XJ08cPWaKj4gvlwSQiG7dCboqvLy9NOmQT9SM7ayJrBa6K5V91hjlWorp4JGUOAglRSiMMDb82/vgaBGTpVvtNUVtyJg'. -'5+WNAh5ZCu/r2+dGrgq0pi0DhmlRsSSAfqMd+b6ZyNu3po1Rk1yNBe3/2Q==' ; - -//========================================================== -// lu-small.jpg -//========================================================== -$this->chars['u'][0]= 671 ; -$this->chars['u'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYDBAUH/8QAJRAAAQQBAwQDAQEAAAAAAAAA'. -'AQIDBBEFAAYhBxMxYRJBURSB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAD/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQARITFBAv/aAAwD'. -'AQACEQMRAD8A6dLkQmJzu3WVtHIqjf0duKFNuBr5UTQ45F1R8/XI1PMmsYoJyjhS9iI7BKHeKjkXZVXqhyLHP+rrHeR1pZlx1W1M'. -'wTiW0ukkrS28nn5fV2SPPFfurHUKQhzYG7pLYKEfyBhaSOS7dG/YCki/uvWn3LPDOJrwa4kyEzOYeakqkpC3Hk0bNePQHgDRpchY'. -'leIZwzUWauKtuPctTSUlCAUmrBHIKuAPV/ujQsmHdm7hya43UbbD3ZVElOQJsdTS6IQaQUqBHCk8E2Pocgam6oYwObHy0Zm0oi45'. -'T1KBPdpV2f0pom/1Ws7cmPazu98Ltvcq3VzRHfehz8a4pirFEKRZo8eQT+eCdWYfS/b+WYnxpbuVcDRMdHcyTqg2fiAfiLoi+Rf+'. -'jT7Xc74HtOYnHyUOh8yWUvKeHhy0CiPVUAPoDRrm+OeznTva6lzsyMjCYbbaiNJjJSWElagD5tRpNUSALFeNGoOCH7Bv/9k=' ; - -//========================================================== -// lw-small.jpg -//========================================================== -$this->chars['w'][0]= 673 ; -$this->chars['w'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYDBAX/xAAtEAACAQMDAgMHBQAAAAAAAAAB'. -'AgMEBREABhIhMRMUQRUiIzJRYZEWNIGx0f/EABYBAQEBAAAAAAAAAAAAAAAAAAABA//EABoRAAICAwAAAAAAAAAAAAAAAAABERIh'. -'MVH/2gAMAwEAAhEDEQA/AHXbV13ZLu6t2/uaa1JijWopVp4XUTKSAXRyc+6ehBGeoPbTSlwpql0K3GneqpZViqUhI5JzGMEZJGeh'. -'GlXfaFILDf7FQzXC426rDLTojs8sLqVkXBGcfKf40twWbdWzZY75R0s90ul3jPtKjVMJDNn4DDp8iEhW+wJ1WZG2KWt3Lv26U1tv'. -'92o7PaYkgYUbqVepYlmUBlIwqnB++O2jTDt/bBtth9jcpvEWNGqalZQryTlmeR8jPct6+mNGmRC4a1U13htzVFItB5nA/cyOUVfp'. -'7oz/ALqitJulYJKuqvFsppHALLFb3cp9FBaXr+O51bq0q6i38KK5PDVAAxSzU6SIpz3Kjjn8jUFoS7uFmut1gq17xLFQ+DxOccj8'. -'Rsn+tVpiyJnqv09YfOXu5AycgZZQEhBZjgDBOOgwO/po0sttWHdNzqLruioa4UwmdaC3kYp4IwSvJlBHKQ4OSe3po0qxM6P/2Q==' ; - -//========================================================== -// lq-small.jpg -//========================================================== -$this->chars['q'][0]= 671 ; -$this->chars['q'][1]= -'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. -'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. -'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAcDBAUG/8QAKRAAAQQBBAICAQQDAAAAAAAA'. -'AQIDBBEFAAYSIQcxIlETCBQVgSNBYf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oADAMB'. -'AAIRAxEAPwDT3H5Qz+O3LN2vtrF/y86NYLzzVlAABJITQPv2a/17vXMboz3lDEYWPuafNx7CFrS03+2jpK2bs0CUkUa7pRvrUu63'. -'sr438yv7pLEo4XIK5Kcji0uJUkckm+uQUOVH6GsnyJv7A5vaJwuFdkONLmolgONFH4vioKRXYqyCADXvRMh0yspmZ4jyIEtDTK47'. -'aiA0lQUopBJBI/7X9aNT7amRo228e3a31iO3yUzCcdSPiKAIFdCho0TIswZ7GQlO/hlRxBooih1YXzAoKUkX0LPEBX110dJ7zbuv'. -'AORpO04cIpmxH23FSEIRwKuNnsdk0o31702XhFMKbuRUZJWP8LTQ6HBCuIB+iVWSR2BXuqK93/hDlvGzEphmG3Ml5JpDi1I7TzNA'. -'BYFlPafY+/7LBiv1CYDH4iFDOGySlMR22lFP4wCUpANfL11o1r4bxXlWMNEaE/bqlIbCFl/ANPK5Do/M0VDr2Rf3o0TX/9k=' ; - - - - } -} - -class AntiSpam { - - var $iData=''; - var $iDD=null; - - function AntiSpam($aData='') { - $this->iData = $aData; - $this->iDD = new HandDigits(); - } - - function Set($aData) { - $this->iData = $aData; - } - - function Rand($aLen) { - $d=''; - for($i=0; $i < $aLen; ++$i) { - if( rand(0,9) < 6 ) { - // Digits - $d .= chr( ord('1') + rand(0,8) ); - } - else { - // Letters - do { - $offset = rand(0,25); - } while ( $offset==14 ); - $d .= chr( ord('a') + $offset ); - } - } - $this->iData = $d; - return $d; - } - - function Stroke($aStrokeFileName="") { - - $n=strlen($this->iData); - if( $n==0 ) { - return false; - } - - for($i=0; $i < $n; ++$i ) { - if( $this->iData[$i]==='0' || strtolower($this->iData[$i])==='o') { - return false; - } - } - - $img = @imagecreatetruecolor($n*$this->iDD->iWidth, $this->iDD->iHeight); - if( $img < 1 ) { - return false; - } - - $start=0; - for($i=0; $i < $n; ++$i ) { - $dimg = imagecreatefromstring(base64_decode($this->iDD->chars[strtolower($this->iData[$i])][1])); - imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $this->iDD->iHeight); - $start += imagesx($dimg); - } - $resimg = @imagecreatetruecolor($start+4, $this->iDD->iHeight+4); - if( $resimg < 1 ) { - return false; - } - - imagecopy($resimg,$img,2,2,0,0,$start, $this->iDD->iHeight); - - if( $aStrokeFileName!="" ) { - if( file_exists($aStrokeFileName) ) { - if( !@unlink($aStrokeFileName) ) - return false; - } - imagejpeg($resimg,$aStrokeFileName); - return; - } - - header("Content-type: image/jpeg"); - $res=imagejpeg($resimg); - return $res; - } -} - -?> +chars['j'][0]= 658 ; + $this->chars['j'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUGBAf/xAAsEAACAQMDAwMBCQAAAAAAAAAB'. +'AgMEBREAEjEGIUEUUXGBBxMVIiNSYWKC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/8QAGhEAAwADAQAAAAAAAAAAAAAAAAECERIh'. +'Mv/aAAwDAQACEQMRAD8A6veK2st8zRWSyV1dUBfvHaGVI4hknsS7AFv4AyM57ayWbqeS+11xtT2etttwo4YqhEqnQs5bcAfyk4AZ'. +'SOeD441TKRTyingUBG4/ah8j684+dSFzh/BvtaslejMUu9DPQTDnLx4lQ/ONw1TGBm0jdRWqguEMghEisWilgDmNs4Ze+MEEEH40'. +'aUVFTa7JeLjRXu4GjhmnNbSfqFQVlA3rkckOjH/Q99Glmkl0C/Q06pvsvT9vttXHDF6T1KrWbs5gRgQJM+FDlQxPhjpF1XcVq+qe'. +'jEoKiOecXBqh2TDDYIXLKuP6549xk8auI6aJqV45oknWdNswkAIkGMYIxjGO2NR1F0LZY5qkWqkS1xrM0M8lMSJpY+TGrnJiQ577'. +'cEgeNHhi7D3qC3UN69M8tIakRhgrh9o748+eNGtcCiKjjpkQKlMTEg3ZwoxtHHtgfTRpYXArvp//2Q==' ; + + //========================================================== + // lf-small.jpg + //========================================================== + $this->chars['f'][0]= 633 ; + $this->chars['f'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQFBgcC/8QAKxAAAgEDAwMCBQUAAAAAAAAA'. +'AQIDBBEhAAUGEjFBEyIHFFFhoRUzYnGS/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQP/xAAaEQACAwEBAAAAAAAAAAAAAAAAAQIRMRIh'. +'/9oADAMBAAIRAxEAPwDcnmLoIkiSYsouC3tA++O2lU9WkqVjJ+YdhZLsQI/4/YfQm50kZP0vbmaCSU0SRNIH6sghb9INs3t38dvp'. +'akUuz8x5DwdN5peS1jV1dSipSiVUigIcdQjQ26lIB/c6r3F86SZpE/zCFJaqsihQNhRgdj3Jyfxo0jDSbXHt9Oph9RAoV3qJGltY'. +'HDOxyb/nRpV0D3RXle21m48XraOk3IUSemUaV4g4Zc9ShcDtgff+tQfwvjq34Dtku7buamFqeJKemCCMxKFsEJU+/FrX8d76sEHG'. +'aNItzr4usVNdG3S0rmRYAVwEUmyjyQLZ11x7aF4zs9DQOyzml29I2cLa/pixIHi99DFCtU9dFuLIaijo9qiYPmR2mZmB9thgAHOD'. +'4+mjUrURyrUNMZFEkkIOFuFAbsP9d/OjVIQ6Vh4tP//Z' ; + + //========================================================== + // lb-small.jpg + //========================================================== + $this->chars['b'][0]= 645 ; + $this->chars['b'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYCAwUH/8QAKxAAAQMDAwMDAwUAAAAAAAAA'. +'AQIDBAAFEQYSIRMxUSJBYQcVI2JxgqHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQL/xAAYEQEBAQEBAAAAAAAAAAAAAAAAATERYf/a'. +'AAwDAQACEQMRAD8A6H95mxNYwLXcX+pCuilSLXJ6YSplaUELjqxwe4IJ5PIPamJ2V0bPcS7+NxCX1cHggAnIP+xSd9RyzHh2m7FQ'. +'Q1CvMNQWTjCt+HFD+PB/Y1fI1PL1HFFt0zaGblFdJQ9cJjpZiqPJUlBAKnPcEpGB5NNRKdrOl1NlgiQol4R2w4Sc5VtGf7opZteo'. +'LhdorjUSM5FnQnlR50NeHQysYxtVxlJHIPgjtRRD3xkaghs6juumdHz4+Y7RVPnt59K2mk7W+fcKWsZ7djTXMkW+xMP3GRJjwIEN'. +'HTG/CWx5wPY8AADx2NYk3SL9wukvUjGobnBkORksIbjdMANozgEqSo8qJPGO/wAVO36IsjUmBIfZfuM7epZk3F9UhSSk5O0K9Kcq'. +'8AcU3UzFuhUSBFud6nRXoz96mqmJZWg7m2dqUNhWBwdqQSP1UU5c/FFCn//Z' ; + + //========================================================== + // d6-small.jpg + //========================================================== + $this->chars['6'][0]= 645 ; + $this->chars['6'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'. +'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'. +'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'. +'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'. +'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'. +'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'. +'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ; + + //========================================================== + // lx-small.jpg + //========================================================== + $this->chars['x'][0]= 650 ; + $this->chars['x'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABMDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUHBgj/xAApEAABAwMDAwQCAwAAAAAAAAAB'. +'AgMEBQYRACFBBxIxFCJRgRNxkcHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEQH/2gAMAwEA'. +'AhEDEQA/AH9t3pKvO14UykVARa/HfAlxlDKXR24V2p3z7RlPwdtMep91uWdRGHWELjuTFFtLvcC4SNznnH+21O7ttiodOq1BvC0E'. +'p9I0lSX2kgqCSklK+5PKCMAng6zV2XRO6u3lSIURtbDRShltlZHa0tW7q/0MeTwnjxq1Jiw2xc9xTLbhSVU5iaXUFfqFFILgJOCd'. +'9Gt3SXabR6REpkL8yo0RpLCFNx1qBCRjOQMHxo0pEr6o3um2LVYpMEpTVqg25lHn08dfcB9kEgfZ1LIFDuawqZRb7aQlLTzqglsg'. +'9wQdveOEqBIB425xqhQuk8qo9UKlPrlRblw2ZBeCSVKW6CcoSrI2AGOT41SKzT4dYtmdS5bIXDZhNoWgbZJ94x8AYT/GkM03oNUc'. +'uKgwqtTZDTMOU0FttqRkoHggnPkEEHRrkJ6t1SlSHYUOc6zHaWrsbQrATk5/vRqK/9k=' ; + + //========================================================== + // d2-small.jpg + //========================================================== + $this->chars['2'][0]= 606 ; + $this->chars['2'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'. +'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'. +'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'. +'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'. +'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'. +'7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'. +'DLZ6f//Z' ; + + //========================================================== + // lm-small.jpg + //========================================================== + $this->chars['m'][0]= 649 ; + $this->chars['m'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAcDBAUCBv/EAC0QAAICAQMCBAMJAAAAAAAA'. +'AAECAwQRAAUSBiETMVFhB2KhFSIyQVJxgZHB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREBAQEAAwAAAAAAAAAAAAAAAQAR'. +'EiEx/9oADAMBAAIRAxEAPwB0MI2lIdgI0Cly3kFXLEn2zx1FDdp7rbpbjUtRWKio3hyxOGQllJzkegX66rQ2qW87Zuk9S5FNVmru'. +'iywyBhjDKTkeXfSr+GRfYtq2KAO32b1BGxAZu0dyJ2DKPTxY1wPddVszycUq2Golq8jRWbcnJWwCVGMjz+VQP50atxMtm2ZUOY4l'. +'4qfUnBP0x/Z0amy4jJm10Tt2yddWasFmfaRfdrlG3UcgArnxKzJ+Fu4DqCMkcgNem2DoWav8PLfTm+FPEkuSNTnqueS5bnHIv6CG'. +'LNjJwM99bm67NB1Ht89KSxNXnr2hNDbiUc47K4KyD2GQMfmMjUnS+7vuIktTqPCaaWCqAMMojPFyw8hyYMQBnAwNJHYGXPTsW9VN'. +'jg2zf50W9zk524GAEihuz+xbIOD82jW5TkjtRPZkTkJ+4VgDhQfuj/f3OjUxl1f/2Q==' ; + + //========================================================== + // lt-small.jpg + //========================================================== + $this->chars['t'][0]= 648 ; + $this->chars['t'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAJxAAAQMDAgYDAQEAAAAAAAAA'. +'AQIDBAUGEQASEyExQVFhIjJxFSP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAP/xAAZEQADAQEBAAAAAAAAAAAAAAAAAREhMUH/2gAM'. +'AwEAAhEDEQA/AO4BLEiEy7uG4IGxxs5IOOx76wd2XYidSp1HoD70240gcNNPbDyI6wQQpaz8E9MczkdhqtbsKYLieDk6WLKmZmmL'. +'Hk7AHVkbkLI+RQc7uRxgkfr1tx2rGu6VbToLVKkhU+kbugGf9WfaknCk5ycaX0zmaa+3JkqvW/CmzojsB9xoF6OoFK0r6HOcEDI0'. +'aefTuKX5ScMdC14HYq8n12zo1DEUcKTGg1Z+hyBwoPBVIiA/VQyOIgedhUCB4WMfXSV3UufVLcTUIqVf26K6mXDbPVRRzKT54iMg'. +'+zjtq6mtsyJjclxpKlUhSXEbkgkqWnBx4+J5e/zU0pZemPvJJQzEPDfQOrwwFY9AZ5eeYPLV6FwhoFYZuigxpkJeIjqAeIoAk9wA'. +'D46EnuD+6Nc1smDNrTlRkxqtMo1vzKhIdYgU9YDqVpISrLhHxSSd21I0aYyqP//Z' ; + + //========================================================== + // li-small.jpg + //========================================================== + $this->chars['i'][0]= 639 ; + $this->chars['i'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABwAGBP/EACcQAAEEAQMEAgIDAAAAAAAAAAEC'. +'AwQRBQAGEiExQVEHExSBFWFx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgMB/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECMRH/2gAMAwEA'. +'AhEDEQA/AE7c+5M9BeRG29t1WUfKFFYW+GvrI7WD3B9g140YD5T36rcErDjbUR6dCBdejsKUpxITXI2FUrooCh70yvxzHyIlMvuK'. +'eVSH7IKEpJoKqu/ahddLryR/aMiO187bsmrWShhp1AZS2XHHrWhNJrzdf7f7GiVcHk3sptmHkJcJ2DIftS2FrKlJPXudWuLGYeQp'. +'t2fmEIckqIZaaKuSGG0lQ4gduRoFRHQ9AOgs2lOJbk9aSUlpjGvAWeSVH2VKq/2dFPw3IjyJe8s281ct3I9UoHJXGiQkD2STrSZ7'. +'Yf8AOl7JTdw5eOCz0jw3+LbYCfA9nz71msb8KMxoTGTw+5srjsipAdDqFBQBIuiOl6KrdYyJMyTCshlw2G3Fr/HiNqNNAqJJUoGl'. +'KND+h47km1bZwsvCbYYjycxIyK1qDv2yEi0hQviK8atKDcy9j//Z' ; + + + //========================================================== + // lp-small.jpg + //========================================================== + $this->chars['p'][0]= 700 ; + $this->chars['p'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAECBAUGB//EAC8QAAEDAwMCBAMJAAAAAAAA'. +'AAECAwQFESEABhIiMRMVUWEHFEEWIzIzcYGRocH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAcEQACAgIDAAAAAAAAAAAAAAAA'. +'AQIxAxESIUH/2gAMAwEAAhEDEQA/AOh703xG21DMeOyqoVNDjSzERiwU6Ep5qtZNycA97HTF13d33KWtmlt9xwkLl1NkXVxIuQgK'. +'wLj+hqBvel0qmbR8GnR22nJNZiLeeKr8nDIT1OLJucX+uPbWom7iocRpafOac5MX1ALltp/Cbi+cJH++utdh+WVNL3PNdNYpdWgx'. +'Y0qmLZSrwJJcQoOJ5XKlJFu4HbJOjVbt+V5nu7eopNRivqcdhK+bFnWwA1Y2AOcgjvj9dGlxy0g5y0xd+hNXoG24C4obizq3HZUh'. +'YHqtRHD06bG/8a0MbbG1mqekxaBSGmgkrcdcitlLfrckZIz7DUatbeFak0tyRLUwzT5vmiGm0cufEkFBJItfkD+59tKmiO12atFa'. +'eQukO3ejUxgENqTcfnE5WbkHiOnJ76N2IqI1DibabptS+zkZhtp90F2Y0S026EkAFK/qL46cXv65NVZDfxHmVCK4DE2/RX/lRFbA'. +'C5LwAyq2EtpHZI7mxPYDRqoctdESimz/2Q==' ; + + //========================================================== + // le-small.jpg + //========================================================== + $this->chars['e'][0]= 700 ; + $this->chars['e'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABgDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYEBQcB/8QAKhAAAQMCBAUEAwEAAAAAAAAA'. +'AgEDBAURAAYSIQciMTJBE0JRYRQVFoH/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREAAwEBAQAAAAAAAAAAAAAAAAERAjFB'. +'/9oADAMBAAIRAxEAPwDTszvhEYCoS80BTm2bCjQRwdAzVe2yopkpJtpRUVfjEIc4V2oMerByg5Ji30oMyS3GeMunK0upfnu09MdJ'. +'p2scTmWnnGfx6HThktgLfKj7xEOqyr7QBbL41LhBzpxbcOru0LKDLdSnOHoaltNqSC4qWL0x9xbJYum69caczSaHmGmTmpDUYn4l'. +'UiqjkynzAVtwV23Ud+X4Ibpa2DCPkjhfUaRO/p8yzpb+YHhUmhbev6ZEll1lvqK3jt2XrbBgp6HVwsK3THpfEubGSoOUyFMpbJmL'. +'Deh6SgOGKti57EuY6l62JMWdJy7k3hg1LkOozEbVm7suQSkTiKtkEfP1pH664Za/QItccgI4bseTHdNxiXHLQ8yVl7V32XyioqL5'. +'TGc1ng6eYs0idczXUZscBBABWgEhEtfKNuUezwPnBhEuj8X2M21z9BR6NUX211Kk/UKKAjuhkPhL7XVf8vtgw7UPJlEyrDWFSYLb'. +'LBNF6qrzG6t0spEu6+fpL7YMXhUndp//2Q==' ; + + //========================================================== + // la-small.jpg + //========================================================== + $this->chars['a'][0]= 730 ; + $this->chars['a'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABoDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwIFAQcCBwAAAAAAAAAB'. +'AgMEBREAEiExQQYHFBUiUXGBE2EyQkNSgpHh/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAMBAv/EABkRAAMBAQEAAAAAAAAAAAAAAAAB'. +'IQIRMf/aAAwDAQACEQMRAD8AfdQ1pxjqZMSn0mRUZRYDaklJCE3OawO2ttTxY4hl07qFMVs1Ku02kpPnRGhsAqz8W9T9wDjozq6o'. +'Q1lDrcZLGVcmUoZg0obpufxK3Ftt9ccqB1GgBcmLSqtVEqOZcr6ARm/kbXHt7DEtc7WTJKTJqEWvRKfLqL9QplSjuPtGVYOJKBrm'. +'t+U+n94WGStZzNypmRWqckUKTbixy6jAfxPxHtCgKqFNlU5huK6pLMndSlegG4J45N8aKmTMKQRBsCNMzwB+RbHWHGEAZlPZX2hx'. +'qZIC34ygZoYUbB50JSkFXFhZR9BrpheR4fIbQ6gvurJ7q02bIQTuAOAN8x40HAxRr3TrNRpBmSHVt1KMlTyJTCsqkKAPlSf28W+c'. +'UGaD1c9HSR1HFUh9tJU45EBcAtcC9+P9wqbg8IAto9o81yputrVGpiUkgHKkqUTZI32+cKm1z1tIUgPBBAKQ4UBQH3uL3xmXSXep'. +'HVDtXStE5K5jlPU7PF3Q41+okJFkjgC+3OuNSYiSzHaLtRcW4UDMpLYSCbakDW3thhum5p//2Q==' ; + + //========================================================== + // d9-small.jpg + //========================================================== + $this->chars['9'][0]= 680 ; + $this->chars['9'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'. +'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'. +'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'. +'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'. +'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'. +'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'. +'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'. +'1V1//9k=' ; + + //========================================================== + // d5-small.jpg + //========================================================== + $this->chars['5'][0]= 632 ; + $this->chars['5'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'. +'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'. +'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'. +'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'. +'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'. +'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'. +'8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ; + + //========================================================== + // d1-small.jpg + //========================================================== + $this->chars['1'][0]= 646 ; + $this->chars['1'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'. +'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'. +'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'. +'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'. +'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'. +'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'. +'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ; + + //========================================================== + // ll-small.jpg + //========================================================== + $this->chars['l'][0]= 626 ; + $this->chars['l'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYEBQf/xAArEAACAQIFAwIGAwAAAAAAAAAB'. +'AgMEEQAFBhIhFEFREzEHFSIyYcFxgZH/xAAXAQEAAwAAAAAAAAAAAAAAAAACAAED/8QAGhEAAwEAAwAAAAAAAAAAAAAAAAECMREh'. +'Qf/aAAwDAQACEQMRAD8A15Zfm1VURj1Fp5AqLKv3OARcL4W5Nzx+MLWjdRz5hqXU6TSb6OCr6WghiQbrJ91gOTy1yT5xZ55myZFk'. +'Gb5ozX6Ondm28XYqpQDwu7jEH4c5S2UaDy4xxrLmlUDWzk8XaQ3O49hbj+RiB85HNg8Ee3aqwIqhDuux7G/HHbvzgxEqaWOvy09R'. +'O0o3hjdQoUji20g+fY3wYSM6pJ4Ylr7V+Zz5PSaezHTlTRNWzxySSxt6q1MSkH6AOT2Fu3Aw7RfF/T9DEkLUeawuF2mKSgdWQj2/'. +'q3+fnDZDlqRZzQGaOGcpTOaeR1u8R+ncN3gj94so2jNWHeMNNKzorEX2qp9v3imNPoRE1zpjUtZ09HJmYq5lury0benZeTww23t3'. +'Ivgw+T0yRRyyxIqNfkLcA8jt7YMKcBWn/9k=' ; + + + //========================================================== + // ls-small.jpg + //========================================================== + $this->chars['s'][0]= 701 ; + $this->chars['s'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAMCBAUGB//EACwQAAEEAQIFAgUFAAAAAAAA'. +'AAECAwQFEQAGEhMUITEiYQcjQVFxFRZCUoH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAZEQADAQEBAAAAAAAAAAAAAAAAAQIR'. +'EiH/2gAMAwEAAhEDEQA/APWZMhmFXSJU+SGmWFiQtAWMJQAnJUr8Z+w/OuQk71uZnMsqnbjy9s8st9UMCQ6kZJdZaIHEkZ/JHceN'. +'N3HtizuY1JLrG48yLBSC9UTFKQiY4nACir+wAOOMEe2rm2bTbzlqtE1MyBuZAPybpw85KSfDRJ4Cg+Pl/wC61hJeGjV31VuuKqwr'. +'LGU+whZZK+Rw+oYJAyj3GjS4dZFpZVkqPLktdfMXNcaU2kBC1BIITkdx6c599GlnvPAa3TL2vNvU76n0063acr3YSLCEjpUpUQtW'. +'Dhf14SMEnOc57aZ8Tegm7dbrEQGZt1PeTDgc1PEW3FeXAvyAkZVkeMDOm2G3f3O7Cl/qEuqkQg4lp6CRxraWfUlRUD24kZA741Ko'. +'2k1HvlT3ri2sLOCgtsyJz6XEtBwZPAgJAGQMHUNPWKqWItsqh0UCFVyLeKhyLHQ2TMdHNVj+RKlAnJyfto1FW2ahgjrq6LYTFjjf'. +'lymUOLdWfJyoHA+gA7AAAaNPE3ysJdLT/9k=' ; + + //========================================================== + // lh-small.jpg + //========================================================== + $this->chars['h'][0]= 677 ; + $this->chars['h'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAIDBAUGB//EACwQAAIBAwMCBQIHAAAAAAAA'. +'AAECAwQFEQAGEiExExQiQVEVggcyU2GRocH/xAAXAQADAQAAAAAAAAAAAAAAAAAAAwQB/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQAC'. +'AyEyMf/aAAwDAQACEQMRAD8A6DZb95q9bmpK6ieOCzNHJTxmE+NMhQ5fr1fLq3Ejvkak2e7ipiFsqb3R0m4qkPPJRiRXenU9VjKE'. +'5JVcA9R7nWc3/BUbfoKTdO3VRXhpjbZ2D8Rwk6RyZH6chB+46m7i2hDYtgA2ePlV2VkuKysoLzzRnlIScZJZeeevvjtrX7LK2rp7'. +'tTwwJ9WjhILDrTKnIdMEDl2+P80aVdJZb1QW+vgqENLPH4sBCDLIwUgnOf4GjVvDnLgUk79T81voqjb8NnuUx8pVRCiEaYUSuynl'. +'jHU9mOfnOoOx6hqz8PrbNdfEkMUXg1LSM3rKOUywJ7YAJ1ZTWmSpvdvlaVTDSUzJAhH5ZJBgv0x2RSAPlz21WXqoet3ba9nuW8n4'. +'Jr6qTPqnUNxSM/f6mPvxA9zqJnExTbR+h0nkhVu1uE8j0UBRQ9PGxBKFjnkAScdsDp10a0lc7z0tI7Y5YYN+5GAf7GjVXF4Icj3f'. +'/9k=' ; + + + //========================================================== + // ld-small.jpg + //========================================================== + $this->chars['d'][0]= 681 ; + $this->chars['d'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFBgH/xAAsEAABAwMEAAQFBQAAAAAAAAAB'. +'AgMEBQYRABIhMQcTI0EUMlFhkRgicaGx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgEA/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECETH/'. +'2gAMAwEAAhEDEQA/ALUhp6h3W/X63UlypbhCY0WMjLqGzwDtPCfv/WtealNpVInuVBBqCogcdbU36YUkAkJWVHG8YPXBxxzxqPcN'. +'YtWyWnIlUeW05VEOAvrCnnSkftK1H5lKJPHsMDoDUWq+KdrSbIqsalVsImiEtLUZ2MU71bcYJWkhZ/36ayLHhi/IXZVOmzKqp5uU'. +'688hTyjuGVEFJKvoQesD86NL2jGZp1EoLDSmk+ZAQ8d7oPzp3YGesFWMfxo1YGvSzLsT9QExVX8phTlMaFOExAJIBGQjJwCcL+/e'. +'rd+W7GuO0Kw05CQ6+ww69Gfdb2kFIKk7DgEkjgnr86rXRa9HuyP8LV4SH0sIBbWFFDiFEgDaocgdkjo8ccay0qw7ut5nyrcviQqC'. +'slsRKo0HwlODkBRzxj2AGoXTtpzIdQ8MbffUChz4NCPRaClAo9Mn6c7T3o13wytmo0K05VIqkiPJbizFiMWs4CTgnIIHOST796NL'. +'Ia1JX//Z' ; + + //========================================================== + // d8-small.jpg + //========================================================== + $this->chars['8'][0]= 694 ; + $this->chars['8'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'. +'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'. +'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'. +'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'. +'44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'. +'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'. +'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'. +'EylmLHQltptPZKQOBo1FzH//2Q==' ; + + //========================================================== + // lz-small.jpg + //========================================================== + $this->chars['z'][0]= 690 ; + $this->chars['z'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgAHA//EACsQAAEDAwQBAwIHAAAAAAAAAAEC'. +'AwQFESEABhIxBxMiQVFxCCM0UmGRof/EABYBAQEBAAAAAAAAAAAAAAAAAAECAP/EABgRAAMBAQAAAAAAAAAAAAAAAAABEVEC/9oA'. +'DAMBAAIRAxEAPwBTWfLu1KXXZDbM4uewNvLajlwhaCbBAwDe5uehYd3xm6t6bi3jvulwqc7KgxXZZeYQLNLeF73WRg4HEdgfzrSa'. +'P45pNEkznITDc9ypLShtyWhJDJyXC2qxJHZvjoZOjyVv1v8AESt6FFS4ijxvTLbawEApSccrYHJf0+OtJMQ2rNXk7GZMufJgJjTH'. +'Un9M4qzxT7hyCiThIyRnPXWrRvyLElVBUF6vlhl0lwRYCFKcQhAtyWpVhyWTx+w++rUvp4EWjOvbniUOnVatcS43BYDbJSPZyIBw'. +'ejclIx+3Wa+J63T6DQanuGszI0eZVJJV60p0Jum5GEi6le7l0PjvSjyRsaTvJqI1BqhhR46ksuMrQVJcUSEoUbHNr/7o7C8L7eiz'. +'4lLlyJk2cEqW+6V+m0AE9ISLnsj5+O9UhsFK92bZZqb9SRu9p2c4A0OCEqDbYAJSlJwAVZv3fBvbFrg/462btlhuS1RG5nL8pYkq'. +'KrnsKH06I/rVrQKkf//Z' ; + + //========================================================== + // d4-small.jpg + //========================================================== + $this->chars['4'][0]= 643 ; + $this->chars['4'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'. +'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'. +'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'. +'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'. +'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'. +'27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'. +'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ; + + //========================================================== + // lv-small.jpg + //========================================================== + $this->chars['v'][0]= 648 ; + $this->chars['v'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAKBAAAQQBAwMEAgMAAAAAAAAA'. +'AQIDBBEFAAYhEzFBEhQiYQdRFTKB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAERIf/aAAwD'. +'AQACEQMRAD8A6Ngt1SZ4yrYgrecgTFsFJA9aGwAUrUaF2D2Avjzq6CIjiBPkB9bwQVIkIYIDae/wq+P9N+dY4SGMf+Txlev7KBmY'. +'PoadKRy4zxSgRxaTwO/x09u7KPYnasmHjlsyFZZXt4K23ezjvBpNGgLUrvXfVZyLLbWambiwEbKvvxYAkeotNlIJW2FEJWb7WBda'. +'NSQI0fHYyJjkrjKRDZQwnpQ1vgBIr+w8+a+9GocZr8iKkuY1eXhsKH8U8iZE9BHz6ZHUc48UfSPqzqH3kfeO9kTTDQYGGietpTaO'. +'shyW6AocpHNIrv8AvWzk9BUSdPdYS4BcRlomkhIV6KP0VE39V+tU2wdlRMHtZUB8NuTQ+51X27+Kr46ZPIAFV540D8zeLsJ5LMHa'. +'ubmMBCVJdjx0pRyLoWR4I8aNIQ8BvZMNtMTeUcsptKfc4tC1gAkCyFC+K0aJtf/Z' ; + + //========================================================== + // lk-small.jpg + //========================================================== + $this->chars['k'][0]= 680 ; + $this->chars['k'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBAMH/8QALhAAAQMDAwIEBAcAAAAAAAAA'. +'AQIDBAUREgAGITFBEyIyYQcVUYEUIzNicZHx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEE/8QAGxEAAwACAwAAAAAAAAAAAAAAAAEC'. +'AxESMeH/2gAMAwEAAhEDEQA/APVK/V36dU6NSJDTT8esPLiqfK8S2cCoeTkKvZQ6jm2ldSqKqbu+OgMOvSX3m4UBrLnDlbqiefKl'. +'Nzz2x1m+IwNP27CkJQ7JkR6rCkMJbP5jp8S2CPfkgD6H+dJ6Ca0nerr+64rTNSqMYrg+C9mmOwhVpDfsuxSbi97DmybaoZeQ5jTl'. +'PEp18JTIfeW3kq3ly4H26aNZqvTWZsjFcZTsVtSg0G8Rio+vr2vb7g6NLPRnuXy8F+8kl+obUh4KXJdqSJJQnohlkZqJPYBXh3P+'. +'a4b5Hyp6k1bO7sOotPyXkj9NlwFl0ewstJA9ifrqkVSmET4csoS7UTHXFQ+6SQlskKUMb/tH9ddLVUmS7DqdBqD7U6OsqfS46jzl'. +'hQ5bXb1K9Scuybdxo2OTu92dwSZkWn0Sb8viQWyn8Qq5D6ifSLd0BIv7q0arTBRSKPToMZbi2GWylsvLK148Wue/XRrRjxOpT2R2'. +'k9aP/9k=' ; + + //========================================================== + // lr-small.jpg + //========================================================== + $this->chars['r'][0]= 681 ; + $this->chars['r'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAGgAAAgIDAAAAAAAAAAAAAAAAAAYCBQMEB//EAC4QAAICAQIFAgMJAQAAAAAA'. +'AAECAwQRBQYAEiExQQdRFGFxEyIyM0JSYoGC8P/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/EABcRAQEBAQAAAAAAAAAAAAAAAAAB'. +'EUH/2gAMAwEAAhEDEQA/AOs0ZdETU54Gt1INSmlPJEsyo7J+jlXPUYBPY9c+eE/dO9tY0a7ren6BVrW7VJTZtW5kZkjXkBSIKveQ'. +'gHp0AAJ4w+q2hVdT2Md0h46+saS4mr3EUK0gWTAB+vQj2PboeL/ZVOqmhaZVjkFmxdC6tctt3tM2G5/7bAx4C4+qxiWwd3prWzKe'. +'r3IBAth5OYxozKsgc8y4GTgnJB9uncdTi6tXq2140rRVM13JMEMAVAg7sMdBjJB/18uDgRO9R2Oo6FX2vShkFzURFUq1whIj+8DI'. +'7EdAFjXv7MeNb0kuStsFEmIaajZaos2fy2Q4VGH7SGxn+Rzw9yMLOm/FzRhZazmOTkP4grYyD3B8j2PTyeFfZ+z7G3BeSS8lmprl'. +'2K2qcnK0Z5S8gPjrgAY8cNEWmq7u23pEos6/Zji+Kd0rLLGWwseA3joeZj/w4OET1g0vlmrWV+ydFnkUxSgsvM4V+YYIwfHz6cHB'. +'ZeKZ1//Z' ; + + //========================================================== + // lg-small.jpg + //========================================================== + $this->chars['g'][0]= 655 ; + $this->chars['g'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQCBQYH/8QAJxAAAQQBAwQCAgMAAAAAAAAA'. +'AQIDBBEFAAYhBxIxQRNhcYEiQlH/xAAYAQACAwAAAAAAAAAAAAAAAAACAwABBP/EABkRAAMBAQEAAAAAAAAAAAAAAAABAhEhIv/a'. +'AAwDAQACEQMRAD8AayO4t6bq3hmMHtxyLi4OKeKH5jyASiiQCCQeTRNAeB61FrBb+jTGpLO+BMW24EFMhkhpQru8m7B/H70x09Yi'. +'q3nv/vLfwpnJ7UNkqSRbngf2ofWkpXV7brymC2malLfagurjW0aHk89xPJ9cX9aprURHWbYEaMHHEBfwpv8AnXPk+/8AdGqGJOxO'. +'4YbOSxK4y4boIStUWysgkEmxY54r60aOI8oTV9MHtjJwunPUbO46WWo0HLlD8KY4goboFVoquOVEVwLT963WdnxYfT6ZJyz0JvHm'. +'KvtaSkW4tYNVSqKiTwB+fw5n9sY/cuOXCzDDcluyW3Ckd7V+0n0eNZTH9DdouFalHIOJBUhtDki0pNV3UALo81ehG6IdKjPZ6d47'. +'4ywltanVJvuJI+RQs/sHRqy2r003JhsImEc/CUyhxRZBjKV2oJ8eRXNmufPnRo1WIz3DdNn/2Q==' ; + + //========================================================== + // lc-small.jpg + //========================================================== + $this->chars['c'][0]= 629 ; + $this->chars['c'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBwID/8QALRAAAgICAQIEBAYDAAAAAAAA'. +'AQIDBAURACExBhIiQRMVUWEHMkJScYFykaH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/xAAXEQEBAQEAAAAAAAAAAAAAAAAAATER'. +'/9oADAMBAAIRAxEAPwDcoGkmiT4Q8kWvzuPU38D2/v8A1zwrCFayq1qTaFk2H7aJHt05MeMvENzC4upDWkjW9kJXiricAJCigvJN'. +'IB1IVQT5frrv24twPgunk6a288crbklUSJNNdnSTZ2STHHqOP/Eb17njdZtAoqwEvrEiGVyG117/AG6HhyV8H1sljMldoxXTksGC'. +'zV7M0oaWGQOVeGQ92I6EMR22D11w4LmEPjaOL51iL8ssc9Z69zHtZkYCGGeQK0ez2UEoU39wCeX1S/LLiEt+mPSbMLxsGVv2kEjR'. +'305xkaEV/GTULMUT1LD/AAGh8gIZS2jv+vpybb8NMIb0dVLWYWgiiU0vmMphOj6V0TvQI3rfsON1E6dYjGtisa0F1mAWR2NhG0WZ'. +'3Ls3TqNs5Hc9h23w49NWL9K+Q/VD5T/zhwPH/9k=' ; + + //========================================================== + // d7-small.jpg + //========================================================== + $this->chars['7'][0]= 658 ; + $this->chars['7'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'. +'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'. +'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'. +'19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'. +'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'. +'8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'. +'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ; + + //========================================================== + // ly-small.jpg + //========================================================== + $this->chars['y'][0]= 672 ; + $this->chars['y'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQGBQf/xAArEAABAwMEAQIFBQAAAAAAAAAB'. +'AgMEBREhAAYSEzEHIhQkQVGxQmFxgaH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAQL/xAAeEQEAAgEEAwAAAAAAAAAAAAABABECAxIh'. +'MUGR8P/aAAwDAQACEQMRAD8Ar3tys07dVHohemz5dWQ7fk91MsA3IIRY8rkKFySceTqw3JVV0KhyKw+0C1CQp9aUOFSiAk4AIAvn'. +'76xtz0ioVvbcJ6msx2JtOfZmw1PKI5LQcJNh7UqBKcn6+NRfqPu6s1fYc6GxSJsRfWDUVSGA22ygEckJWSexRNgOP0udXzDKOJ0I'. +'yo62mHm25Sy80l1Z4lSgpQvZRGLgWwPGjTjbchyLH+Ejx22EtJSgO8kki3kADA/nOjWjGzv73CyQZjUWNVp7bNSrj7qJDqflqUlQ'. +'DMds24l3HvcNr3Pi9gME6T9WWVsemdYWswwC2lPta4m5WMA3OdUExCmozUJD6g84ntMjrHIFBTdQz5yLDx/WDNytpwW6nAkViqVe'. +'uvmXdlme6n4dCwlRBKEgA2tj99QG7Ilncp5QqpU31PMsJ6x7A32f6SPxo0hPVCD45oVyKf0MtgeT97/nRrO7UOCFla3tn//Z' ; + + //========================================================== + // d3-small.jpg + //========================================================== + $this->chars['3'][0]= 662 ; + $this->chars['3'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. +'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'. +'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'. +'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'. +'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'. +'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'. +'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'. +'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ; + + //========================================================== + // ln-small.jpg + //========================================================== + $this->chars['n'][0]= 643 ; + $this->chars['n'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGwAAAgEFAAAAAAAAAAAAAAAAAAYCAQMEBQf/xAAtEAACAQMCBAUCBwAAAAAA'. +'AAABAgMEBREAIQYSE0EHIjFRcWGRIzIzQoGCwf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAP/EABkRAQEBAQEBAAAAAAAAAAAAAAEA'. +'AhEhUf/aAAwDAQACEQMRAD8A6FR3p7v4oV9rlkMQsjL00RyOss0KkFxnDcrc2PbI1NOJKyTjW+W5OmKeA0UEJx5meRZS2/8AUfbS'. +'LVGS1+K16vCzfiR3GmoqqXGyxz06hWPsFlVMfOmq1iNvE69KjBYo3oJMZ3GKeYYPxg/fW+xzZX1FLQyxwSTcpWNceu4G3+aNSmpY'. +'qmQzzwh2k8yhv2r2H23/AJ0aoy+EWh7I1ntacR3PxDtEzhjWy0wkkIwYmanU5GO6sNh7rrU8AVdTceNbhDXxNHUQvS0tZ3DzwxVA'. +'fB7hj59/XJ08cPWaKj4gvlwSQiG7dCboqvLy9NOmQT9SM7ayJrBa6K5V91hjlWorp4JGUOAglRSiMMDb82/vgaBGTpVvtNUVtyJg'. +'5+WNAh5ZCu/r2+dGrgq0pi0DhmlRsSSAfqMd+b6ZyNu3po1Rk1yNBe3/2Q==' ; + + //========================================================== + // lu-small.jpg + //========================================================== + $this->chars['u'][0]= 671 ; + $this->chars['u'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYDBAUH/8QAJRAAAQQBAwQDAQEAAAAAAAAA'. +'AQIDBBEFAAYhBxMxYRJBURSB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAD/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQARITFBAv/aAAwD'. +'AQACEQMRAD8A6dLkQmJzu3WVtHIqjf0duKFNuBr5UTQ45F1R8/XI1PMmsYoJyjhS9iI7BKHeKjkXZVXqhyLHP+rrHeR1pZlx1W1M'. +'wTiW0ukkrS28nn5fV2SPPFfurHUKQhzYG7pLYKEfyBhaSOS7dG/YCki/uvWn3LPDOJrwa4kyEzOYeakqkpC3Hk0bNePQHgDRpchY'. +'leIZwzUWauKtuPctTSUlCAUmrBHIKuAPV/ujQsmHdm7hya43UbbD3ZVElOQJsdTS6IQaQUqBHCk8E2Pocgam6oYwObHy0Zm0oi45'. +'T1KBPdpV2f0pom/1Ws7cmPazu98Ltvcq3VzRHfehz8a4pirFEKRZo8eQT+eCdWYfS/b+WYnxpbuVcDRMdHcyTqg2fiAfiLoi+Rf+'. +'jT7Xc74HtOYnHyUOh8yWUvKeHhy0CiPVUAPoDRrm+OeznTva6lzsyMjCYbbaiNJjJSWElagD5tRpNUSALFeNGoOCH7Bv/9k=' ; + + //========================================================== + // lw-small.jpg + //========================================================== + $this->chars['w'][0]= 673 ; + $this->chars['w'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYDBAX/xAAtEAACAQMDAgMHBQAAAAAAAAAB'. +'AgMEBREABhIhMRMUQRUiIzJRYZEWNIGx0f/EABYBAQEBAAAAAAAAAAAAAAAAAAABA//EABoRAAICAwAAAAAAAAAAAAAAAAABERIh'. +'MVH/2gAMAwEAAhEDEQA/AHXbV13ZLu6t2/uaa1JijWopVp4XUTKSAXRyc+6ehBGeoPbTSlwpql0K3GneqpZViqUhI5JzGMEZJGeh'. +'GlXfaFILDf7FQzXC426rDLTojs8sLqVkXBGcfKf40twWbdWzZY75R0s90ul3jPtKjVMJDNn4DDp8iEhW+wJ1WZG2KWt3Lv26U1tv'. +'92o7PaYkgYUbqVepYlmUBlIwqnB++O2jTDt/bBtth9jcpvEWNGqalZQryTlmeR8jPct6+mNGmRC4a1U13htzVFItB5nA/cyOUVfp'. +'7oz/ALqitJulYJKuqvFsppHALLFb3cp9FBaXr+O51bq0q6i38KK5PDVAAxSzU6SIpz3Kjjn8jUFoS7uFmut1gq17xLFQ+DxOccj8'. +'Rsn+tVpiyJnqv09YfOXu5AycgZZQEhBZjgDBOOgwO/po0sttWHdNzqLruioa4UwmdaC3kYp4IwSvJlBHKQ4OSe3po0qxM6P/2Q==' ; + + //========================================================== + // lq-small.jpg + //========================================================== + $this->chars['q'][0]= 671 ; + $this->chars['q'][1]= +'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. +'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. +'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAcDBAUG/8QAKRAAAQQBBAICAQQDAAAAAAAA'. +'AQIDBBEFAAYSIQcxIlETCBQVgSNBYf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oADAMB'. +'AAIRAxEAPwDT3H5Qz+O3LN2vtrF/y86NYLzzVlAABJITQPv2a/17vXMboz3lDEYWPuafNx7CFrS03+2jpK2bs0CUkUa7pRvrUu63'. +'sr438yv7pLEo4XIK5Kcji0uJUkckm+uQUOVH6GsnyJv7A5vaJwuFdkONLmolgONFH4vioKRXYqyCADXvRMh0yspmZ4jyIEtDTK47'. +'aiA0lQUopBJBI/7X9aNT7amRo228e3a31iO3yUzCcdSPiKAIFdCho0TIswZ7GQlO/hlRxBooih1YXzAoKUkX0LPEBX110dJ7zbuv'. +'AORpO04cIpmxH23FSEIRwKuNnsdk0o31702XhFMKbuRUZJWP8LTQ6HBCuIB+iVWSR2BXuqK93/hDlvGzEphmG3Ml5JpDi1I7TzNA'. +'BYFlPafY+/7LBiv1CYDH4iFDOGySlMR22lFP4wCUpANfL11o1r4bxXlWMNEaE/bqlIbCFl/ANPK5Do/M0VDr2Rf3o0TX/9k=' ; + + + + } +} + +class AntiSpam { + + private $iData=''; + private $iDD=null; + + function __construct($aData='') { + $this->iData = $aData; + $this->iDD = new HandDigits(); + } + + function Set($aData) { + $this->iData = $aData; + } + + function Rand($aLen) { + $d=''; + for($i=0; $i < $aLen; ++$i) { + if( rand(0,9) < 6 ) { + // Digits + $d .= chr( ord('1') + rand(0,8) ); + } + else { + // Letters + do { + $offset = rand(0,25); + } while ( $offset==14 ); + $d .= chr( ord('a') + $offset ); + } + } + $this->iData = $d; + return $d; + } + + function Stroke() { + + $n=strlen($this->iData); + if( $n==0 ) { + return false; + } + + for($i=0; $i < $n; ++$i ) { + if( $this->iData[$i]==='0' || strtolower($this->iData[$i])==='o') { + return false; + } + } + + $img = @imagecreatetruecolor($n*$this->iDD->iWidth, $this->iDD->iHeight); + if( $img < 1 ) { + return false; + } + + $start=0; + for($i=0; $i < $n; ++$i ) { + $dimg = imagecreatefromstring(base64_decode($this->iDD->chars[strtolower($this->iData[$i])][1])); + imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $this->iDD->iHeight); + $start += imagesx($dimg); + } + $resimg = @imagecreatetruecolor($start+4, $this->iDD->iHeight+4); + if( $resimg < 1 ) { + return false; + } + + imagecopy($resimg,$img,2,2,0,0,$start, $this->iDD->iHeight); + header("Content-type: image/jpeg"); + imagejpeg($resimg); + return true; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_bar.php b/web/public_php/admin/jpgraph/jpgraph_bar.php index a7ba46ed5..ec9da456a 100644 --- a/web/public_php/admin/jpgraph/jpgraph_bar.php +++ b/web/public_php/admin/jpgraph/jpgraph_bar.php @@ -1,964 +1,1200 @@ -Plot($datay,$datax); - ++$this->numpoints; - } - -//--------------- -// PUBLIC METHODS - - // Set a drop shadow for the bar (or rather an "up-right" shadow) - function SetShadow($color="black",$hsize=3,$vsize=3,$show=true) { - $this->bar_shadow=$show; - $this->bar_shadow_color=$color; - $this->bar_shadow_vsize=$vsize; - $this->bar_shadow_hsize=$hsize; - - // Adjust the value margin to compensate for shadow - $this->value->margin += $vsize; - } - - // DEPRECATED use SetYBase instead - function SetYMin($aYStartValue) { - //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead."); - $this->ybase=$aYStartValue; - } - - // Specify the base value for the bars - function SetYBase($aYStartValue) { - $this->ybase=$aYStartValue; - } - - function Legend(&$graph) { - if( $this->grad && $this->legend!="" && !$this->fill ) { - $color=array($this->grad_fromcolor,$this->grad_tocolor); - // In order to differentiate between gradients and cooors specified as an RGB triple - $graph->legend->Add($this->legend,$color,"",-$this->grad_style, - $this->legendcsimtarget,$this->legendcsimalt); - } - elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) { - if( is_array($this->iPattern) ) { - $p1 = $this->iPattern[0]; - $p2 = $this->iPatternColor[0]; - $p3 = $this->iPatternDensity[0]; - } - else { - $p1 = $this->iPattern; - $p2 = $this->iPatternColor; - $p3 = $this->iPatternDensity; - } - $color = array($p1,$p2,$p3,$this->fill_color); - // A kludge: Too mark that we add a pattern we use a type value of < 100 - $graph->legend->Add($this->legend,$color,"",-101, - $this->legendcsimtarget,$this->legendcsimalt); - } - elseif( $this->fill_color && $this->legend!="" ) { - if( is_array($this->fill_color) ) { - $graph->legend->Add($this->legend,$this->fill_color[0],"",0, - $this->legendcsimtarget,$this->legendcsimalt); - } - else { - $graph->legend->Add($this->legend,$this->fill_color,"",0, - $this->legendcsimtarget,$this->legendcsimalt); - } - } - } - - // Gets called before any axis are stroked - function PreStrokeAdjust(&$graph) { - parent::PreStrokeAdjust($graph); - - // If we are using a log Y-scale we want the base to be at the - // minimum Y-value unless the user have specifically set some other - // value than the default. - if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 ) - $this->ybase = $graph->yaxis->scale->GetMinVal(); - - // For a "text" X-axis scale we will adjust the - // display of the bars a little bit. - if( substr($graph->axtype,0,3)=="tex" ) { - // Position the ticks between the bars - $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0); - - // Center the bars - if( $this->abswidth > -1 ) { - $graph->SetTextScaleAbsCenterOff($this->abswidth); - } - else { - if( $this->align == "center" ) - $graph->SetTextScaleOff(0.5-$this->width/2); - elseif( $this->align == "right" ) - $graph->SetTextScaleOff(1-$this->width); - } - - } - elseif( is_a($this,'AccBarPlot') || is_a($this,'GroupBarPlot') ) { - // We only set an absolute width for linear and int scale - // for text scale the width will be set to a fraction of - // the majstep width. - if( $this->abswidth == -1 ) { - // Not set - // set width to a visuable sensible default - $this->abswidth = $graph->img->plotwidth/(2*count($this->coords[0])); - } - } - } - - function Min() { - $m = parent::Min(); - if( $m[1] >= $this->ybase ) - $m[1] = $this->ybase; - return $m; - } - - function Max() { - $m = parent::Max(); - if( $m[1] <= $this->ybase ) - $m[1] = $this->ybase; - return $m; - } - - // Specify width as fractions of the major stepo size - function SetWidth($aFractionWidth) { - $this->width=$aFractionWidth; - } - - // Specify width in absolute pixels. If specified this - // overrides SetWidth() - function SetAbsWidth($aWidth) { - $this->abswidth=$aWidth; - } - - function SetAlign($aAlign) { - $this->align=$aAlign; - } - - function SetNoFill() { - $this->grad = false; - $this->fill_color=false; - $this->fill=false; - } - - function SetFillColor($aColor) { - $this->fill = true ; - $this->fill_color=$aColor; - } - - function SetFillGradient($from_color,$to_color,$style) { - $this->grad=true; - $this->grad_fromcolor=$from_color; - $this->grad_tocolor=$to_color; - $this->grad_style=$style; - } - - function SetValuePos($aPos) { - $this->valuepos = $aPos; - } - - function SetPattern($aPattern, $aColor='black'){ - if( is_array($aPattern) ) { - $n = count($aPattern); - $this->iPattern = array(); - $this->iPatternDensity = array(); - if( is_array($aColor) ) { - $this->iPatternColor = array(); - if( count($aColor) != $n ) { - JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()'); - } - } - else - $this->iPatternColor = $aColor; - for( $i=0; $i < $n; ++$i ) { - $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]); - if( is_array($aColor) ) { - $this->iPatternColor[$i] = $aColor[$i]; - } - } - } - else { - $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity); - $this->iPatternColor = $aColor; - } - } - - function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){ - switch( $aPattern ) { - case PATTERN_DIAG1: - $aPatternValue= 1; - $aDensity = 90; - break; - case PATTERN_DIAG2: - $aPatternValue= 1; - $aDensity = 75; - break; - case PATTERN_DIAG3: - $aPatternValue= 2; - $aDensity = 90; - break; - case PATTERN_DIAG4: - $aPatternValue= 2; - $aDensity = 75; - break; - case PATTERN_CROSS1: - $aPatternValue= 8; - $aDensity = 90; - break; - case PATTERN_CROSS2: - $aPatternValue= 8; - $aDensity = 78; - break; - case PATTERN_CROSS3: - $aPatternValue= 8; - $aDensity = 65; - break; - case PATTERN_CROSS4: - $aPatternValue= 7; - $aDensity = 90; - break; - case PATTERN_STRIPE1: - $aPatternValue= 5; - $aDensity = 95; - break; - case PATTERN_STRIPE2: - $aPatternValue= 5; - $aDensity = 85; - break; - default: - JpGraphError::RaiseL(2002);//('Unknown pattern specified in call to BarPlot::SetPattern()'); - } - } - - function Stroke(&$img,&$xscale,&$yscale) { - - $numpoints = count($this->coords[0]); - if( isset($this->coords[1]) ) { - if( count($this->coords[1])!=$numpoints ) - JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); -//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints"); - else - $exist_x = true; - } - else - $exist_x = false; - - - $numbars=count($this->coords[0]); - - // Use GetMinVal() instead of scale[0] directly since in the case - // of log scale we get a correct value. Log scales will have negative - // values for values < 1 while still not representing negative numbers. - if( $yscale->GetMinVal() >= 0 ) - $zp=$yscale->scale_abs[0]; - else { - $zp=$yscale->Translate(0); - } - - if( $this->abswidth > -1 ) { - $abswidth=$this->abswidth; - } - else - $abswidth=round($this->width*$xscale->scale_factor,0); - - // Count potential pattern array to avoid doing the count for each iteration - if( is_array($this->iPattern) ) { - $np = count($this->iPattern); - } - - for($i=0; $i < $numbars; ++$i) { - - // If value is NULL, or 0 then don't draw a bar at all - if ($this->coords[0][$i] === null || - $this->coords[0][$i] === '' || - $this->coords[0][$i] === 0 ) continue; - - if( $exist_x ) $x=$this->coords[1][$i]; - else $x=$i; - - $x=$xscale->Translate($x); - -// Comment Note: This confuses the positioning when using acc together with -// grouped bars. Workaround for fixing #191 -/* - if( !$xscale->textscale ) { - if($this->align=="center") - $x -= $abswidth/2; - elseif($this->align=="right") - $x -= $abswidth; - } - -*/ - // Stroke fill color and fill gradient - $pts=array( - $x,$zp, - $x,$yscale->Translate($this->coords[0][$i]), - $x+$abswidth,$yscale->Translate($this->coords[0][$i]), - $x+$abswidth,$zp); - if( $this->grad ) { - $grad = new Gradient($img); - $grad->FilledRectangle($pts[2],$pts[3], - $pts[6],$pts[7], - $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); - } - elseif( !empty($this->fill_color) ) { - if(is_array($this->fill_color)) { - $img->PushColor($this->fill_color[$i % count($this->fill_color)]); - } else { - $img->PushColor($this->fill_color); - } - $img->FilledPolygon($pts); - $img->PopColor(); - } - - - // Remember value of this bar - $val=$this->coords[0][$i]; - - if( !empty($val) && !is_numeric($val) ) { - JpGraphError::RaiseL(2004,$i,$val); -//('All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\''); - } - - // Determine the shadow - if( $this->bar_shadow && $val != 0) { - - $ssh = $this->bar_shadow_hsize; - $ssv = $this->bar_shadow_vsize; - // Create points to create a "upper-right" shadow - if( $val > 0 ) { - $sp[0]=$pts[6]; $sp[1]=$pts[7]; - $sp[2]=$pts[4]; $sp[3]=$pts[5]; - $sp[4]=$pts[2]; $sp[5]=$pts[3]; - $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; - $sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv; - $sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv; - } - elseif( $val < 0 ) { - $sp[0]=$pts[4]; $sp[1]=$pts[5]; - $sp[2]=$pts[6]; $sp[3]=$pts[7]; - $sp[4]=$pts[0]; $sp[5]=$pts[1]; - $sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv; - $sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv; - $sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv; - } - if( is_array($this->bar_shadow_color) ) { - $numcolors = count($this->bar_shadow_color); - if( $numcolors == 0 ) { - JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.'); - } - $img->PushColor($this->bar_shadow_color[$i % $numcolors]); - } - else { - $img->PushColor($this->bar_shadow_color); - } - $img->FilledPolygon($sp); - $img->PopColor(); - } - - // Stroke the pattern - if( is_array($this->iPattern) ) { - $f = new RectPatternFactory(); - if( is_array($this->iPatternColor) ) { - $pcolor = $this->iPatternColor[$i % $np]; - } - else - $pcolor = $this->iPatternColor; - $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1); - $prect->SetDensity($this->iPatternDensity[$i % $np]); - - if( $val < 0 ) { - $rx = $pts[0]; - $ry = $pts[1]; - } - else { - $rx = $pts[2]; - $ry = $pts[3]; - } - $width = abs($pts[4]-$pts[0])+1; - $height = abs($pts[1]-$pts[3])+1; - $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); - $prect->Stroke($img); - } - else { - if( $this->iPattern > -1 ) { - $f = new RectPatternFactory(); - $prect = $f->Create($this->iPattern,$this->iPatternColor,1); - $prect->SetDensity($this->iPatternDensity); - if( $val < 0 ) { - $rx = $pts[0]; - $ry = $pts[1]; - } - else { - $rx = $pts[2]; - $ry = $pts[3]; - } - $width = abs($pts[4]-$pts[0])+1; - $height = abs($pts[1]-$pts[3])+1; - $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); - $prect->Stroke($img); - } - } - // Stroke the outline of the bar - if( is_array($this->color) ) - $img->SetColor($this->color[$i % count($this->color)]); - else - $img->SetColor($this->color); - - $pts[] = $pts[0]; - $pts[] = $pts[1]; - - if( $this->weight > 0 ) { - $img->SetLineWeight($this->weight); - $img->Polygon($pts); - } - - // Determine how to best position the values of the individual bars - $x=$pts[2]+($pts[4]-$pts[2])/2; - if( $this->valuepos=='top' ) { - $y=$pts[3]; - if( $img->a === 90 ) { - if( $val < 0 ) - $this->value->SetAlign('right','center'); - else - $this->value->SetAlign('left','center'); - - } - $this->value->Stroke($img,$val,$x,$y); - } - elseif( $this->valuepos=='max' ) { - $y=$pts[3]; - if( $img->a === 90 ) { - if( $val < 0 ) - $this->value->SetAlign('left','center'); - else - $this->value->SetAlign('right','center'); - } - else { - $this->value->SetAlign('center','top'); - } - $this->value->SetMargin(-3); - $this->value->Stroke($img,$val,$x,$y); - } - elseif( $this->valuepos=='center' ) { - $y = ($pts[3] + $pts[1])/2; - $this->value->SetAlign('center','center'); - $this->value->SetMargin(0); - $this->value->Stroke($img,$val,$x,$y); - } - elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) { - $y=$pts[1]; - if( $img->a === 90 ) { - if( $val < 0 ) - $this->value->SetAlign('right','center'); - else - $this->value->SetAlign('left','center'); - } - $this->value->SetMargin(3); - $this->value->Stroke($img,$val,$x,$y); - } - else { - JpGraphError::RaiseL(2006,$this->valuepos); -//('Unknown position for values on bars :'.$this->valuepos); - } - // Create the client side image map - $rpts = $img->ArrRotate($pts); - $csimcoord=round($rpts[0]).", ".round($rpts[1]); - for( $j=1; $j < 4; ++$j){ - $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]); - } - if( !empty($this->csimtargets[$i]) ) { - $this->csimareas .= 'csimareas .= " href=\"".$this->csimtargets[$i]."\""; - $sval=''; - if( !empty($this->csimalts[$i]) ) { - $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]); - $this->csimareas .= " title=\"$sval\" "; - } - $this->csimareas .= " alt=\"$sval\" />\n"; - } - } - return true; - } -} // Class - -//=================================================== -// CLASS GroupBarPlot -// Description: Produce grouped bar plots -//=================================================== -class GroupBarPlot extends BarPlot { - var $plots; - var $width=0.7; - var $nbrplots=0; - var $numpoints; -//--------------- -// CONSTRUCTOR - function GroupBarPlot($plots) { - $this->plots = $plots; - $this->nbrplots = count($plots); - if( $this->nbrplots < 1 ) { - JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.'); - } - for($i=0; $i < $this->nbrplots; ++$i ) { - if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { - JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty."); - } - } - $this->numpoints = $plots[0]->numpoints; - } - -//--------------- -// PUBLIC METHODS - function Legend(&$graph) { - $n = count($this->plots); - for($i=0; $i < $n; ++$i) { - $c = get_class($this->plots[$i]); - if( !is_a($this->plots[$i],'BarPlot') ) { - JpGraphError::RaiseL(2009,$c);//('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.')'); - } - $this->plots[$i]->DoLegend($graph); - } - } - - function Min() { - list($xmin,$ymin) = $this->plots[0]->Min(); - $n = count($this->plots); - for($i=0; $i < $n; ++$i) { - list($xm,$ym) = $this->plots[$i]->Min(); - $xmin = max($xmin,$xm); - $ymin = min($ymin,$ym); - } - return array($xmin,$ymin); - } - - function Max() { - list($xmax,$ymax) = $this->plots[0]->Max(); - $n = count($this->plots); - for($i=0; $i < $n; ++$i) { - list($xm,$ym) = $this->plots[$i]->Max(); - $xmax = max($xmax,$xm); - $ymax = max($ymax,$ym); - } - return array($xmax,$ymax); - } - - function GetCSIMareas() { - $n = count($this->plots); - $csimareas=''; - for($i=0; $i < $n; ++$i) { - $csimareas .= $this->plots[$i]->csimareas; - } - return $csimareas; - } - - // Stroke all the bars next to each other - function Stroke(&$img,&$xscale,&$yscale) { - $tmp=$xscale->off; - $n = count($this->plots); - $subwidth = $this->width/$this->nbrplots ; - for( $i=0; $i < $n; ++$i ) { - $this->plots[$i]->ymin=$this->ybase; - $this->plots[$i]->SetWidth($subwidth); - - // If the client have used SetTextTickInterval() then - // major_step will be > 1 and the positioning will fail. - // If we assume it is always one the positioning will work - // fine with a text scale but this will not work with - // arbitrary linear scale - $xscale->off = $tmp+$i*round(/*$xscale->ticks->major_step* */ - $xscale->scale_factor* $subwidth); - $this->plots[$i]->Stroke($img,$xscale,$yscale); - } - $xscale->off=$tmp; - } -} // Class - -//=================================================== -// CLASS AccBarPlot -// Description: Produce accumulated bar plots -//=================================================== -class AccBarPlot extends BarPlot { - var $plots=null,$nbrplots=0,$numpoints=0; -//--------------- -// CONSTRUCTOR - function AccBarPlot($plots) { - $this->plots = $plots; - $this->nbrplots = count($plots); - if( $this->nbrplots < 1 ) { - JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.'); - } - for($i=0; $i < $this->nbrplots; ++$i ) { - if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { - JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty."); - } - } - $this->numpoints = $plots[0]->numpoints; - $this->value = new DisplayValue(); - } - -//--------------- -// PUBLIC METHODS - function Legend(&$graph) { - $n = count($this->plots); - for( $i=$n-1; $i >= 0; --$i ) { - $c = get_class($this->plots[$i]); - if( !is_a($this->plots[$i],'BarPlot') ) { - JpGraphError::RaiseL(2012,$c);//('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.')'); - } - $this->plots[$i]->DoLegend($graph); - } - } - - function Max() { - list($xmax) = $this->plots[0]->Max(); - $nmax=0; - for($i=0; $i < count($this->plots); ++$i) { - $n = count($this->plots[$i]->coords[0]); - $nmax = max($nmax,$n); - list($x) = $this->plots[$i]->Max(); - $xmax = max($xmax,$x); - } - for( $i = 0; $i < $nmax; $i++ ) { - // Get y-value for bar $i by adding the - // individual bars from all the plots added. - // It would be wrong to just add the - // individual plots max y-value since that - // would in most cases give to large y-value. - $y=0; - if( !isset($this->plots[0]->coords[0][$i]) ) { - JpGraphError::RaiseL(2014); - } - if( $this->plots[0]->coords[0][$i] > 0 ) - $y=$this->plots[0]->coords[0][$i]; - for( $j = 1; $j < $this->nbrplots; $j++ ) { - if( !isset($this->plots[$j]->coords[0][$i]) ) { - JpGraphError::RaiseL(2014); - } - if( $this->plots[$j]->coords[0][$i] > 0 ) - $y += $this->plots[$j]->coords[0][$i]; - } - $ymax[$i] = $y; - } - $ymax = max($ymax); - - // Bar always start at baseline - if( $ymax <= $this->ybase ) - $ymax = $this->ybase; - return array($xmax,$ymax); - } - - function Min() { - $nmax=0; - list($xmin,$ysetmin) = $this->plots[0]->Min(); - for($i=0; $i < count($this->plots); ++$i) { - $n = count($this->plots[$i]->coords[0]); - $nmax = max($nmax,$n); - list($x,$y) = $this->plots[$i]->Min(); - $xmin = Min($xmin,$x); - $ysetmin = Min($y,$ysetmin); - } - for( $i = 0; $i < $nmax; $i++ ) { - // Get y-value for bar $i by adding the - // individual bars from all the plots added. - // It would be wrong to just add the - // individual plots max y-value since that - // would in most cases give to large y-value. - $y=0; - if( $this->plots[0]->coords[0][$i] < 0 ) - $y=$this->plots[0]->coords[0][$i]; - for( $j = 1; $j < $this->nbrplots; $j++ ) { - if( $this->plots[$j]->coords[0][$i] < 0 ) - $y += $this->plots[ $j ]->coords[0][$i]; - } - $ymin[$i] = $y; - } - $ymin = Min($ysetmin,Min($ymin)); - // Bar always start at baseline - if( $ymin >= $this->ybase ) - $ymin = $this->ybase; - return array($xmin,$ymin); - } - - // Stroke acc bar plot - function Stroke(&$img,&$xscale,&$yscale) { - $pattern=NULL; - $img->SetLineWeight($this->weight); - for($i=0; $i < $this->numpoints-1; $i++) { - $accy = 0; - $accy_neg = 0; - for($j=0; $j < $this->nbrplots; ++$j ) { - $img->SetColor($this->plots[$j]->color); - - if ( $this->plots[$j]->coords[0][$i] >= 0) { - $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); - $accyt=$yscale->Translate($accy); - $accy+=$this->plots[$j]->coords[0][$i]; - } - else { - //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) { - $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); - $accyt=$yscale->Translate($accy_neg); - $accy_neg+=$this->plots[$j]->coords[0][$i]; - } - - $xt=$xscale->Translate($i); - - if( $this->abswidth > -1 ) - $abswidth=$this->abswidth; - else - $abswidth=round($this->width*$xscale->scale_factor,0); - - $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt); - - if( $this->bar_shadow ) { - $ssh = $this->bar_shadow_hsize; - $ssv = $this->bar_shadow_vsize; - - // We must also differ if we are a positive or negative bar. - if( $j === 0 ) { - // This gets extra complicated since we have to - // see all plots to see if we are negative. It could - // for example be that all plots are 0 until the very - // last one. We therefore need to save the initial setup - // for both the negative and positive case - - // In case the final bar is positive - $sp[0]=$pts[6]+1; $sp[1]=$pts[7]; - $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv; - - // In case the final bar is negative - $nsp[0]=$pts[0]; $nsp[1]=$pts[1]; - $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv; - $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv; - $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7]; - } - - if( $j === $this->nbrplots-1 ) { - // If this is the last plot of the bar and - // the total value is larger than 0 then we - // add the shadow. - if( is_array($this->bar_shadow_color) ) { - $numcolors = count($this->bar_shadow_color); - if( $numcolors == 0 ) { - JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.'); - } - $img->PushColor($this->bar_shadow_color[$i % $numcolors]); - } - else { - $img->PushColor($this->bar_shadow_color); - } - - if( $accy > 0 ) { - $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv; - $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; - $sp[8]=$pts[2]; $sp[9]=$pts[3]-1; - $sp[10]=$pts[4]+1; $sp[11]=$pts[5]; - $img->FilledPolygon($sp,4); - } - elseif( $accy_neg < 0 ) { - $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv; - $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5]; - $img->FilledPolygon($nsp,4); - } - $img->PopColor(); - } - } - - - // If value is NULL or 0, then don't draw a bar at all - if ($this->plots[$j]->coords[0][$i] == 0 ) continue; - - if( $this->plots[$j]->grad ) { - $grad = new Gradient($img); - $grad->FilledRectangle( - $pts[2],$pts[3], - $pts[6],$pts[7], - $this->plots[$j]->grad_fromcolor, - $this->plots[$j]->grad_tocolor, - $this->plots[$j]->grad_style); - } else { - if (is_array($this->plots[$j]->fill_color) ) { - $numcolors = count($this->plots[$j]->fill_color); - $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]); - } - else { - $img->SetColor($this->plots[$j]->fill_color); - } - $img->FilledPolygon($pts); - $img->SetColor($this->plots[$j]->color); - } - - // Stroke the pattern - if( $this->plots[$j]->iPattern > -1 ) { - if( $pattern===NULL ) - $pattern = new RectPatternFactory(); - - $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1); - $prect->SetDensity($this->plots[$j]->iPatternDensity); - if( $this->plots[$j]->coords[0][$i] < 0 ) { - $rx = $pts[0]; - $ry = $pts[1]; - } - else { - $rx = $pts[2]; - $ry = $pts[3]; - } - $width = abs($pts[4]-$pts[0])+1; - $height = abs($pts[1]-$pts[3])+1; - $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); - $prect->Stroke($img); - } - - - // CSIM array - - if( $i < count($this->plots[$j]->csimtargets) ) { - // Create the client side image map - $rpts = $img->ArrRotate($pts); - $csimcoord=round($rpts[0]).", ".round($rpts[1]); - for( $k=1; $k < 4; ++$k){ - $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]); - } - if( ! empty($this->plots[$j]->csimtargets[$i]) ) { - $this->csimareas.= 'csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\""; - if( !empty($this->plots[$j]->csimalts[$i]) ) { - $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]); - $this->csimareas .= " title=\"$sval\" "; - } - $this->csimareas .= " alt=\"$sval\" />\n"; - } - } - - $pts[] = $pts[0]; - $pts[] = $pts[1]; - $img->Polygon($pts); - } - - // Draw labels for each acc.bar - - $x=$pts[2]+($pts[4]-$pts[2])/2; - if($this->bar_shadow) $x += $ssh; - - // First stroke the accumulated value for the entire bar - // This value is always placed at the top/bottom of the bars - if( $accy_neg < 0 ) { - $y=$yscale->Translate($accy_neg); - $this->value->Stroke($img,$accy_neg,$x,$y); - } - else { - $y=$yscale->Translate($accy); - $this->value->Stroke($img,$accy,$x,$y); - } - - $accy = 0; - $accy_neg = 0; - for($j=0; $j < $this->nbrplots; ++$j ) { - - // We don't print 0 values in an accumulated bar plot - if( $this->plots[$j]->coords[0][$i] == 0 ) continue; - - if ($this->plots[$j]->coords[0][$i] > 0) { - $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); - $accyt=$yscale->Translate($accy); - if( $this->plots[$j]->valuepos=='center' ) { - $y = $accyt-($accyt-$yt)/2; - } - elseif( $this->plots[$j]->valuepos=='bottom' ) { - $y = $accyt; - } - else { // top or max - $y = $accyt-($accyt-$yt); - } - $accy+=$this->plots[$j]->coords[0][$i]; - if( $this->plots[$j]->valuepos=='center' ) { - $this->plots[$j]->value->SetAlign("center","center"); - $this->plots[$j]->value->SetMargin(0); - } - elseif( $this->plots[$j]->valuepos=='bottom' ) { - $this->plots[$j]->value->SetAlign('center','bottom'); - $this->plots[$j]->value->SetMargin(2); - } - else { - $this->plots[$j]->value->SetAlign('center','top'); - $this->plots[$j]->value->SetMargin(1); - } - } else { - $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); - $accyt=$yscale->Translate($accy_neg); - $accy_neg+=$this->plots[$j]->coords[0][$i]; - if( $this->plots[$j]->valuepos=='center' ) { - $y = $accyt-($accyt-$yt)/2; - } - elseif( $this->plots[$j]->valuepos=='bottom' ) { - $y = $accyt; - } - else { - $y = $accyt-($accyt-$yt); - } - if( $this->plots[$j]->valuepos=='center' ) { - $this->plots[$j]->value->SetAlign("center","center"); - $this->plots[$j]->value->SetMargin(0); - } - elseif( $this->plots[$j]->valuepos=='bottom' ) { - $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top'); - $this->plots[$j]->value->SetMargin(-2); - } - else { - $this->plots[$j]->value->SetAlign('center','bottom'); - $this->plots[$j]->value->SetMargin(-1); - } - } - $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y); - } - - } - return true; - } -} // Class - -/* EOF */ -?> +numpoints; + } + + //--------------- + // PUBLIC METHODS + + // Set a drop shadow for the bar (or rather an "up-right" shadow) + function SetShadow($aColor="black",$aHSize=3,$aVSize=3,$aShow=true) { + $this->bar_shadow=$aShow; + $this->bar_shadow_color=$aColor; + $this->bar_shadow_vsize=$aVSize; + $this->bar_shadow_hsize=$aHSize; + + // Adjust the value margin to compensate for shadow + $this->value->margin += $aVSize; + } + + function Set3D($aHSize=3,$aVSize=3,$aShow=true) { + $this->bar_3d=$aShow; + $this->bar_3d_vsize=$aVSize; + $this->bar_3d_hsize=$aHSize; + + $this->value->margin += $aVSize; + } + + // DEPRECATED use SetYBase instead + function SetYMin($aYStartValue) { + //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead."); + $this->ybase=$aYStartValue; + } + + // Specify the base value for the bars + function SetYBase($aYStartValue) { + $this->ybase=$aYStartValue; + } + + // The method will take the specified pattern anre + // return a pattern index that corresponds to the original + // patterm being rotated 90 degreees. This is needed when plottin + // Horizontal bars + function RotatePattern($aPat,$aRotate=true) { + $rotate = array(1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8); + if( $aRotate ) { + return $rotate[$aPat]; + } + else { + return $aPat; + } + } + + function Legend($graph) { + if( $this->grad && $this->legend!="" && !$this->fill ) { + $color=array($this->grad_fromcolor,$this->grad_tocolor); + // In order to differentiate between gradients and cooors specified as an RGB triple + $graph->legend->Add($this->legend,$color,"",-$this->grad_style, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) { + if( is_array($this->iPattern) ) { + $p1 = $this->RotatePattern( $this->iPattern[0], $graph->img->a == 90 ); + $p2 = $this->iPatternColor[0]; + $p3 = $this->iPatternDensity[0]; + } + else { + $p1 = $this->RotatePattern( $this->iPattern, $graph->img->a == 90 ); + $p2 = $this->iPatternColor; + $p3 = $this->iPatternDensity; + } + if( $p3 < 90 ) $p3 += 5; + $color = array($p1,$p2,$p3,$this->fill_color); + // A kludge: Too mark that we add a pattern we use a type value of < 100 + $graph->legend->Add($this->legend,$color,"",-101, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + elseif( $this->fill_color && $this->legend!="" ) { + if( is_array($this->fill_color) ) { + $graph->legend->Add($this->legend,$this->fill_color[0],"",0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + else { + $graph->legend->Add($this->legend,$this->fill_color,"",0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } + } + + // Gets called before any axis are stroked + function PreStrokeAdjust($graph) { + parent::PreStrokeAdjust($graph); + + // If we are using a log Y-scale we want the base to be at the + // minimum Y-value unless the user have specifically set some other + // value than the default. + if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 ) + $this->ybase = $graph->yaxis->scale->GetMinVal(); + + // For a "text" X-axis scale we will adjust the + // display of the bars a little bit. + if( substr($graph->axtype,0,3)=="tex" ) { + // Position the ticks between the bars + $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0); + + // Center the bars + if( $this->abswidth > -1 ) { + $graph->SetTextScaleAbsCenterOff($this->abswidth); + } + else { + if( $this->align == "center" ) + $graph->SetTextScaleOff(0.5-$this->width/2); + elseif( $this->align == "right" ) + $graph->SetTextScaleOff(1-$this->width); + } + } + elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) { + // We only set an absolute width for linear and int scale + // for text scale the width will be set to a fraction of + // the majstep width. + if( $this->abswidth == -1 ) { + // Not set + // set width to a visuable sensible default + $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints); + } + } + } + + function Min() { + $m = parent::Min(); + if( $m[1] >= $this->ybase ) $m[1] = $this->ybase; + return $m; + } + + function Max() { + $m = parent::Max(); + if( $m[1] <= $this->ybase ) $m[1] = $this->ybase; + return $m; + } + + // Specify width as fractions of the major stepo size + function SetWidth($aWidth) { + if( $aWidth > 1 ) { + // Interpret this as absolute width + $this->abswidth=$aWidth; + } + else { + $this->width=$aWidth; + } + } + + // Specify width in absolute pixels. If specified this + // overrides SetWidth() + function SetAbsWidth($aWidth) { + $this->abswidth=$aWidth; + } + + function SetAlign($aAlign) { + $this->align=$aAlign; + } + + function SetNoFill() { + $this->grad = false; + $this->fill_color=false; + $this->fill=false; + } + + function SetFillColor($aColor) { + // Do an extra error check if the color is specified as an RGB array triple + // In that case convert it to a hex string since it will otherwise be + // interpretated as an array of colors for each individual bar. + + $aColor = RGB::tryHexConversion($aColor); + $this->fill = true ; + $this->fill_color=$aColor; + + } + + function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) { + $this->grad = true; + $this->grad_fromcolor = $aFromColor; + $this->grad_tocolor = $aToColor; + $this->grad_style = $aStyle; + } + + function SetValuePos($aPos) { + $this->valuepos = $aPos; + } + + function SetPattern($aPattern, $aColor='black'){ + if( is_array($aPattern) ) { + $n = count($aPattern); + $this->iPattern = array(); + $this->iPatternDensity = array(); + if( is_array($aColor) ) { + $this->iPatternColor = array(); + if( count($aColor) != $n ) { + JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()'); + } + } + else { + $this->iPatternColor = $aColor; + } + for( $i=0; $i < $n; ++$i ) { + $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]); + if( is_array($aColor) ) { + $this->iPatternColor[$i] = $aColor[$i]; + } + } + } + else { + $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity); + $this->iPatternColor = $aColor; + } + } + + function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){ + switch( $aPattern ) { + case PATTERN_DIAG1: + $aPatternValue= 1; + $aDensity = 92; + break; + case PATTERN_DIAG2: + $aPatternValue= 1; + $aDensity = 78; + break; + case PATTERN_DIAG3: + $aPatternValue= 2; + $aDensity = 92; + break; + case PATTERN_DIAG4: + $aPatternValue= 2; + $aDensity = 78; + break; + case PATTERN_CROSS1: + $aPatternValue= 8; + $aDensity = 90; + break; + case PATTERN_CROSS2: + $aPatternValue= 8; + $aDensity = 78; + break; + case PATTERN_CROSS3: + $aPatternValue= 8; + $aDensity = 65; + break; + case PATTERN_CROSS4: + $aPatternValue= 7; + $aDensity = 90; + break; + case PATTERN_STRIPE1: + $aPatternValue= 5; + $aDensity = 94; + break; + case PATTERN_STRIPE2: + $aPatternValue= 5; + $aDensity = 85; + break; + default: + JpGraphError::RaiseL(2002); + //('Unknown pattern specified in call to BarPlot::SetPattern()'); + } + } + + + /** + * @override + * Without overriding this method, $this->numpoints does not updated correctly. + */ + function Clear() { + $this->isRunningClear = true; + $this->__construct($this->inputValues['aDatay'], $this->inputValues['aDatax']); + $this->isRunningClear = false; + } + + function Stroke($img,$xscale,$yscale) { + + $numpoints = count($this->coords[0]); + if( isset($this->coords[1]) ) { + if( count($this->coords[1])!=$numpoints ) { + JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); + //"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints"); + } + else { + $exist_x = true; + } + } + else { + $exist_x = false; + } + + + $numbars=count($this->coords[0]); + + // Use GetMinVal() instead of scale[0] directly since in the case + // of log scale we get a correct value. Log scales will have negative + // values for values < 1 while still not representing negative numbers. + if( $yscale->GetMinVal() >= 0 ) + $zp=$yscale->scale_abs[0]; + else { + $zp=$yscale->Translate(0); + } + + if( $this->abswidth > -1 ) { + $abswidth=$this->abswidth; + } + else { + $abswidth=round($this->width*$xscale->scale_factor,0); + } + + // Count pontetial pattern array to avoid doing the count for each iteration + if( is_array($this->iPattern) ) { + $np = count($this->iPattern); + } + + $grad = null; + for($i=0; $i < $numbars; ++$i) { + + // If value is NULL, or 0 then don't draw a bar at all + if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' ) + continue; + + if( $exist_x ) { + $x=$this->coords[1][$i]; + } + else { + $x=$i; + } + + $x=$xscale->Translate($x); + + // Comment Note: This confuses the positioning when using acc together with + // grouped bars. Workaround for fixing #191 + /* + if( !$xscale->textscale ) { + if($this->align=="center") + $x -= $abswidth/2; + elseif($this->align=="right") + $x -= $abswidth; + } + */ + // Stroke fill color and fill gradient + $pts=array( + $x,$zp, + $x,$yscale->Translate($this->coords[0][$i]), + $x+$abswidth,$yscale->Translate($this->coords[0][$i]), + $x+$abswidth,$zp); + if( $this->grad ) { + if( $grad === null ) { + $grad = new Gradient($img); + } + if( is_array($this->grad_fromcolor) ) { + // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array + // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be + // an array to specify both (from, to style) for each individual bar. The way to know the difference is + // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB + // triple. + $ng = count($this->grad_fromcolor); + if( $ng === 3 ) { + if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) { + // RGB Triple + $fromcolor = $this->grad_fromcolor; + $tocolor = $this->grad_tocolor; + $style = $this->grad_style; + } + else { + $fromcolor = $this->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->grad_fromcolor[$i % $ng][1]; + $style = $this->grad_fromcolor[$i % $ng][2]; + } + } + else { + $fromcolor = $this->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->grad_fromcolor[$i % $ng][1]; + $style = $this->grad_fromcolor[$i % $ng][2]; + } + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $fromcolor,$tocolor,$style); + } + else { + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); + } + } + elseif( !empty($this->fill_color) ) { + if(is_array($this->fill_color)) { + $img->PushColor($this->fill_color[$i % count($this->fill_color)]); + } else { + $img->PushColor($this->fill_color); + } + $img->FilledPolygon($pts); + $img->PopColor(); + } + +/////////////////////////kokorahen rectangle polygon////////////////////// + + // Remember value of this bar + $val=$this->coords[0][$i]; + + if( !empty($val) && !is_numeric($val) ) { + JpGraphError::RaiseL(2004,$i,$val); + //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\''); + } + + // Determine the shadow + if( $this->bar_shadow && $val != 0) { + + $ssh = $this->bar_shadow_hsize; + $ssv = $this->bar_shadow_vsize; + // Create points to create a "upper-right" shadow + if( $val > 0 ) { + $sp[0]=$pts[6]; $sp[1]=$pts[7]; + $sp[2]=$pts[4]; $sp[3]=$pts[5]; + $sp[4]=$pts[2]; $sp[5]=$pts[3]; + $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; + $sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv; + $sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv; + } + elseif( $val < 0 ) { + $sp[0]=$pts[4]; $sp[1]=$pts[5]; + $sp[2]=$pts[6]; $sp[3]=$pts[7]; + $sp[4]=$pts[0]; $sp[5]=$pts[1]; + $sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv; + $sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv; + $sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv; + } + if( is_array($this->bar_shadow_color) ) { + $numcolors = count($this->bar_shadow_color); + if( $numcolors == 0 ) { + JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.'); + } + $img->PushColor($this->bar_shadow_color[$i % $numcolors]); + } + else { + $img->PushColor($this->bar_shadow_color); + } + $img->FilledPolygon($sp); + $img->PopColor(); + + } elseif( $this->bar_3d && $val != 0) { + // Determine the 3D + + $ssh = $this->bar_3d_hsize; + $ssv = $this->bar_3d_vsize; + + // Create points to create a "upper-right" shadow + if( $val > 0 ) { + $sp1[0]=$pts[6]; $sp1[1]=$pts[7]; + $sp1[2]=$pts[4]; $sp1[3]=$pts[5]; + $sp1[4]=$pts[4]+$ssh; $sp1[5]=$pts[5]-$ssv; + $sp1[6]=$pts[6]+$ssh; $sp1[7]=$pts[7]-$ssv; + + $sp2[0]=$pts[4]; $sp2[1]=$pts[5]; + $sp2[2]=$pts[2]; $sp2[3]=$pts[3]; + $sp2[4]=$pts[2]+$ssh; $sp2[5]=$pts[3]-$ssv; + $sp2[6]=$pts[4]+$ssh; $sp2[7]=$pts[5]-$ssv; + + } + elseif( $val < 0 ) { + $sp1[0]=$pts[4]; $sp1[1]=$pts[5]; + $sp1[2]=$pts[6]; $sp1[3]=$pts[7]; + $sp1[4]=$pts[6]+$ssh; $sp1[5]=$pts[7]-$ssv; + $sp1[6]=$pts[4]+$ssh; $sp1[7]=$pts[5]-$ssv; + + $sp2[0]=$pts[6]; $sp2[1]=$pts[7]; + $sp2[2]=$pts[0]; $sp2[3]=$pts[1]; + $sp2[4]=$pts[0]+$ssh; $sp2[5]=$pts[1]-$ssv; + $sp2[6]=$pts[6]+$ssh; $sp2[7]=$pts[7]-$ssv; + } + + $base_color = $this->fill_color; + + $img->PushColor($base_color . ':0.7'); + $img->FilledPolygon($sp1); + $img->PopColor(); + + $img->PushColor($base_color . ':1.1'); + $img->FilledPolygon($sp2); + $img->PopColor(); + } + + // Stroke the pattern + if( is_array($this->iPattern) ) { + $f = new RectPatternFactory(); + if( is_array($this->iPatternColor) ) { + $pcolor = $this->iPatternColor[$i % $np]; + } + else { + $pcolor = $this->iPatternColor; + } + $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1); + $prect->SetDensity($this->iPatternDensity[$i % $np]); + + if( $val < 0 ) { + $rx = $pts[0]; + $ry = $pts[1]; + } + else { + $rx = $pts[2]; + $ry = $pts[3]; + } + $width = abs($pts[4]-$pts[0])+1; + $height = abs($pts[1]-$pts[3])+1; + $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); + $prect->Stroke($img); + } + else { + if( $this->iPattern > -1 ) { + $f = new RectPatternFactory(); + $prect = $f->Create($this->iPattern,$this->iPatternColor,1); + $prect->SetDensity($this->iPatternDensity); + if( $val < 0 ) { + $rx = $pts[0]; + $ry = $pts[1]; + } + else { + $rx = $pts[2]; + $ry = $pts[3]; + } + $width = abs($pts[4]-$pts[0])+1; + $height = abs($pts[1]-$pts[3])+1; + $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); + $prect->Stroke($img); + } + } + + // Stroke the outline of the bar + if( is_array($this->color) ) { + $img->SetColor($this->color[$i % count($this->color)]); + } + else { + $img->SetColor($this->color); + } + + $pts[] = $pts[0]; + $pts[] = $pts[1]; + + if( $this->weight > 0 ) { + $img->SetLineWeight($this->weight); + $img->Polygon($pts); + } + + // Determine how to best position the values of the individual bars + $x=$pts[2]+($pts[4]-$pts[2])/2; + $this->value->SetMargin(5); + + if( $this->valuepos=='top' ) { + $y=$pts[3]; + if( $img->a === 90 ) { + if( $val < 0 ) { + $this->value->SetAlign('right','center'); + } + else { + $this->value->SetAlign('left','center'); + } + + } + else { + if( $val < 0 ) { + $this->value->SetMargin(-5); + $y=$pts[1]; + $this->value->SetAlign('center','bottom'); + } + else { + $this->value->SetAlign('center','bottom'); + } + + } + $this->value->Stroke($img,$val,$x,$y); + } + elseif( $this->valuepos=='max' ) { + $y=$pts[3]; + if( $img->a === 90 ) { + if( $val < 0 ) + $this->value->SetAlign('left','center'); + else + $this->value->SetAlign('right','center'); + } + else { + if( $val < 0 ) { + $this->value->SetAlign('center','bottom'); + } + else { + $this->value->SetAlign('center','top'); + } + } + $this->value->SetMargin(-5); + $this->value->Stroke($img,$val,$x,$y); + } + elseif( $this->valuepos=='center' ) { + $y = ($pts[3] + $pts[1])/2; + $this->value->SetAlign('center','center'); + $this->value->SetMargin(0); + $this->value->Stroke($img,$val,$x,$y); + } + elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) { + $y=$pts[1]; + if( $img->a === 90 ) { + if( $val < 0 ) + $this->value->SetAlign('right','center'); + else + $this->value->SetAlign('left','center'); + } + $this->value->SetMargin(3); + $this->value->Stroke($img,$val,$x,$y); + } + else { + JpGraphError::RaiseL(2006,$this->valuepos); + //'Unknown position for values on bars :'.$this->valuepos); + } + // Create the client side image map + $rpts = $img->ArrRotate($pts); + $csimcoord=round($rpts[0]).", ".round($rpts[1]); + for( $j=1; $j < 4; ++$j){ + $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]); + } + if( !empty($this->csimtargets[$i]) ) { + $this->csimareas .= 'csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\""; + + if( !empty($this->csimwintargets[$i]) ) { + $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; + } + + $sval=''; + if( !empty($this->csimalts[$i]) ) { + $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]); + $this->csimareas .= " title=\"$sval\" alt=\"$sval\" "; + } + $this->csimareas .= " />\n"; + } + } + return true; + } +} // Class + +//=================================================== +// CLASS GroupBarPlot +// Description: Produce grouped bar plots +//=================================================== +class GroupBarPlot extends BarPlot { + public $plots; + private $nbrplots=0; + //--------------- + // CONSTRUCTOR + function __construct($plots) { + $this->width=0.7; + $this->plots = $plots; + $this->nbrplots = count($plots); + if( $this->nbrplots < 1 ) { + JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.'); + } + for($i=0; $i < $this->nbrplots; ++$i ) { + if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { + JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty."); + } + } + $this->numpoints = $plots[0]->numpoints; + $this->width=0.7; + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + $c = get_class($this->plots[$i]); + if( !($this->plots[$i] instanceof BarPlot) ) { + JpGraphError::RaiseL(2009,$c); + //('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.')'); + } + $this->plots[$i]->DoLegend($graph); + } + } + + function Min() { + list($xmin,$ymin) = $this->plots[0]->Min(); + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + list($xm,$ym) = $this->plots[$i]->Min(); + $xmin = min($xmin,$xm); + $ymin = min($ymin,$ym); + } + return array($xmin,$ymin); + } + + function Max() { + list($xmax,$ymax) = $this->plots[0]->Max(); + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + list($xm,$ym) = $this->plots[$i]->Max(); + $xmax = max($xmax,$xm); + $ymax = max($ymax,$ym); + } + return array($xmax,$ymax); + } + + function GetCSIMareas() { + $n = count($this->plots); + $csimareas=''; + for($i=0; $i < $n; ++$i) { + $csimareas .= $this->plots[$i]->csimareas; + } + return $csimareas; + } + + // Stroke all the bars next to each other + function Stroke($img,$xscale,$yscale) { + $tmp=$xscale->off; + $n = count($this->plots); + $subwidth = $this->width/$this->nbrplots ; + + for( $i=0; $i < $n; ++$i ) { + $this->plots[$i]->ymin=$this->ybase; + $this->plots[$i]->SetWidth($subwidth); + + // If the client have used SetTextTickInterval() then + // major_step will be > 1 and the positioning will fail. + // If we assume it is always one the positioning will work + // fine with a text scale but this will not work with + // arbitrary linear scale + $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth); + $this->plots[$i]->Stroke($img,$xscale,$yscale); + } + $xscale->off=$tmp; + } +} // Class + +//=================================================== +// CLASS AccBarPlot +// Description: Produce accumulated bar plots +//=================================================== +class AccBarPlot extends BarPlot { + public $plots=null; + private $nbrplots=0; + //--------------- + // CONSTRUCTOR + function __construct($plots) { + $this->plots = $plots; + $this->nbrplots = count($plots); + if( $this->nbrplots < 1 ) { + JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.'); + } + for($i=0; $i < $this->nbrplots; ++$i ) { + if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { + JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty."); + } + } + + // We can only allow individual plost which do not have specified X-positions + for($i=0; $i < $this->nbrplots; ++$i ) { + if( !empty($this->plots[$i]->coords[1]) ) { + JpGraphError::RaiseL(2015); + //'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.'); + } + } + + // Use 0 weight by default which means that the individual bar + // weights will be used per part n the accumulated bar + $this->SetWeight(0); + + $this->numpoints = $plots[0]->numpoints; + $this->value = new DisplayValue(); + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + $n = count($this->plots); + for( $i=$n-1; $i >= 0; --$i ) { + $c = get_class($this->plots[$i]); + if( !($this->plots[$i] instanceof BarPlot) ) { + JpGraphError::RaiseL(2012,$c); + //('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.')'); + } + $this->plots[$i]->DoLegend($graph); + } + } + + function Max() { + list($xmax) = $this->plots[0]->Max(); + $nmax=0; + for($i=0; $i < count($this->plots); ++$i) { + $n = count($this->plots[$i]->coords[0]); + $nmax = max($nmax,$n); + list($x) = $this->plots[$i]->Max(); + $xmax = max($xmax,$x); + } + for( $i = 0; $i < $nmax; $i++ ) { + // Get y-value for bar $i by adding the + // individual bars from all the plots added. + // It would be wrong to just add the + // individual plots max y-value since that + // would in most cases give to large y-value. + $y=0; + if( !isset($this->plots[0]->coords[0][$i]) ) { + JpGraphError::RaiseL(2014); + } + if( $this->plots[0]->coords[0][$i] > 0 ) + $y=$this->plots[0]->coords[0][$i]; + for( $j = 1; $j < $this->nbrplots; $j++ ) { + if( !isset($this->plots[$j]->coords[0][$i]) ) { + JpGraphError::RaiseL(2014); + } + if( $this->plots[$j]->coords[0][$i] > 0 ) + $y += $this->plots[$j]->coords[0][$i]; + } + $ymax[$i] = $y; + } + $ymax = max($ymax); + + // Bar always start at baseline + if( $ymax <= $this->ybase ) + $ymax = $this->ybase; + return array($xmax,$ymax); + } + + function Min() { + $nmax=0; + list($xmin,$ysetmin) = $this->plots[0]->Min(); + for($i=0; $i < count($this->plots); ++$i) { + $n = count($this->plots[$i]->coords[0]); + $nmax = max($nmax,$n); + list($x,$y) = $this->plots[$i]->Min(); + $xmin = Min($xmin,$x); + $ysetmin = Min($y,$ysetmin); + } + for( $i = 0; $i < $nmax; $i++ ) { + // Get y-value for bar $i by adding the + // individual bars from all the plots added. + // It would be wrong to just add the + // individual plots max y-value since that + // would in most cases give to large y-value. + $y=0; + if( $this->plots[0]->coords[0][$i] < 0 ) + $y=$this->plots[0]->coords[0][$i]; + for( $j = 1; $j < $this->nbrplots; $j++ ) { + if( $this->plots[$j]->coords[0][$i] < 0 ) + $y += $this->plots[ $j ]->coords[0][$i]; + } + $ymin[$i] = $y; + } + $ymin = Min($ysetmin,Min($ymin)); + // Bar always start at baseline + if( $ymin >= $this->ybase ) + $ymin = $this->ybase; + return array($xmin,$ymin); + } + + // Stroke acc bar plot + function Stroke($img,$xscale,$yscale) { + $pattern=NULL; + $img->SetLineWeight($this->weight); + $grad=null; + for($i=0; $i < $this->numpoints-1; $i++) { + $accy = 0; + $accy_neg = 0; + for($j=0; $j < $this->nbrplots; ++$j ) { + $img->SetColor($this->plots[$j]->color); + + if ( $this->plots[$j]->coords[0][$i] >= 0) { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); + $accyt=$yscale->Translate($accy); + $accy+=$this->plots[$j]->coords[0][$i]; + } + else { + //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); + $accyt=$yscale->Translate($accy_neg); + $accy_neg+=$this->plots[$j]->coords[0][$i]; + } + + $xt=$xscale->Translate($i); + + if( $this->abswidth > -1 ) { + $abswidth=$this->abswidth; + } + else { + $abswidth=round($this->width*$xscale->scale_factor,0); + } + + $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt); + + if( $this->bar_shadow ) { + $ssh = $this->bar_shadow_hsize; + $ssv = $this->bar_shadow_vsize; + + // We must also differ if we are a positive or negative bar. + if( $j === 0 ) { + // This gets extra complicated since we have to + // see all plots to see if we are negative. It could + // for example be that all plots are 0 until the very + // last one. We therefore need to save the initial setup + // for both the negative and positive case + + // In case the final bar is positive + $sp[0]=$pts[6]+1; $sp[1]=$pts[7]; + $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv; + + // In case the final bar is negative + $nsp[0]=$pts[0]; $nsp[1]=$pts[1]; + $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv; + $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv; + $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7]; + } + + if( $j === $this->nbrplots-1 ) { + // If this is the last plot of the bar and + // the total value is larger than 0 then we + // add the shadow. + if( is_array($this->bar_shadow_color) ) { + $numcolors = count($this->bar_shadow_color); + if( $numcolors == 0 ) { + JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.'); + } + $img->PushColor($this->bar_shadow_color[$i % $numcolors]); + } + else { + $img->PushColor($this->bar_shadow_color); + } + + if( $accy > 0 ) { + $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv; + $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; + $sp[8]=$pts[2]; $sp[9]=$pts[3]-1; + $sp[10]=$pts[4]+1; $sp[11]=$pts[5]; + $img->FilledPolygon($sp,4); + } + elseif( $accy_neg < 0 ) { + $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv; + $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5]; + $img->FilledPolygon($nsp,4); + } + $img->PopColor(); + } + } + + + // If value is NULL or 0, then don't draw a bar at all + if ($this->plots[$j]->coords[0][$i] == 0 ) continue; + + if( $this->plots[$j]->grad ) { + if( $grad === null ) { + $grad = new Gradient($img); + } + if( is_array($this->plots[$j]->grad_fromcolor) ) { + // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array + // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be + // an array to specify both (from, to style) for each individual bar. The way to know the difference is + // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB + // triple. + $ng = count($this->plots[$j]->grad_fromcolor); + if( $ng === 3 ) { + if( is_numeric($this->plots[$j]->grad_fromcolor[0]) && $this->plots[$j]->grad_fromcolor[0] > 0 && + $this->plots[$j]->grad_fromcolor[0] < 256 ) { + // RGB Triple + $fromcolor = $this->plots[$j]->grad_fromcolor; + $tocolor = $this->plots[$j]->grad_tocolor; + $style = $this->plots[$j]->grad_style; + } + else { + $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1]; + $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2]; + } + } + else { + $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1]; + $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2]; + } + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $fromcolor,$tocolor,$style); + } + else { + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $this->plots[$j]->grad_fromcolor, + $this->plots[$j]->grad_tocolor, + $this->plots[$j]->grad_style); + } + } else { + if (is_array($this->plots[$j]->fill_color) ) { + $numcolors = count($this->plots[$j]->fill_color); + $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors]; + // If the bar is specified to be non filled then the fill color is false + if( $fillcolor !== false ) { + $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]); + } + } + else { + $fillcolor = $this->plots[$j]->fill_color; + if( $fillcolor !== false ) { + $img->SetColor($this->plots[$j]->fill_color); + } + } + if( $fillcolor !== false ) { + $img->FilledPolygon($pts); + } + } + + $img->SetColor($this->plots[$j]->color); + + // Stroke the pattern + if( $this->plots[$j]->iPattern > -1 ) { + if( $pattern===NULL ) { + $pattern = new RectPatternFactory(); + } + + $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1); + $prect->SetDensity($this->plots[$j]->iPatternDensity); + if( $this->plots[$j]->coords[0][$i] < 0 ) { + $rx = $pts[0]; + $ry = $pts[1]; + } + else { + $rx = $pts[2]; + $ry = $pts[3]; + } + $width = abs($pts[4]-$pts[0])+1; + $height = abs($pts[1]-$pts[3])+1; + $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); + $prect->Stroke($img); + } + + + // CSIM array + + if( $i < count($this->plots[$j]->csimtargets) ) { + // Create the client side image map + $rpts = $img->ArrRotate($pts); + $csimcoord=round($rpts[0]).", ".round($rpts[1]); + for( $k=1; $k < 4; ++$k){ + $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]); + } + if( ! empty($this->plots[$j]->csimtargets[$i]) ) { + $this->csimareas.= 'csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" "; + + if( ! empty($this->plots[$j]->csimwintargets[$i]) ) { + $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" "; + } + + $sval=''; + if( !empty($this->plots[$j]->csimalts[$i]) ) { + $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]); + $this->csimareas .= " title=\"$sval\" "; + } + $this->csimareas .= " alt=\"$sval\" />\n"; + } + } + + $pts[] = $pts[0]; + $pts[] = $pts[1]; + $img->SetLineWeight($this->plots[$j]->weight); + $img->Polygon($pts); + $img->SetLineWeight(1); + } + + // Daw potential bar around the entire accbar bar + if( $this->weight > 0 ) { + $y=$yscale->Translate(0); + $img->SetColor($this->color); + $img->SetLineWeight($this->weight); + $img->Rectangle($pts[0],$y,$pts[6],$pts[5]); + } + + // Draw labels for each acc.bar + + $x=$pts[2]+($pts[4]-$pts[2])/2; + if($this->bar_shadow) $x += $ssh; + + // First stroke the accumulated value for the entire bar + // This value is always placed at the top/bottom of the bars + if( $accy + $accy_neg < 0 ) { + $y=$yscale->Translate($accy_neg); + } + else { + $y=$yscale->Translate($accy); + } + $this->value->Stroke($img,$accy + $accy_neg,$x,$y); + + $accy = 0; + $accy_neg = 0; + for($j=0; $j < $this->nbrplots; ++$j ) { + + // We don't print 0 values in an accumulated bar plot + if( $this->plots[$j]->coords[0][$i] == 0 ) continue; + + if ($this->plots[$j]->coords[0][$i] > 0) { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); + $accyt=$yscale->Translate($accy); + if( $this->plots[$j]->valuepos=='center' ) { + $y = $accyt-($accyt-$yt)/2; + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $y = $accyt; + } + else { // top or max + $y = $accyt-($accyt-$yt); + } + $accy+=$this->plots[$j]->coords[0][$i]; + if( $this->plots[$j]->valuepos=='center' ) { + $this->plots[$j]->value->SetAlign("center","center"); + $this->plots[$j]->value->SetMargin(0); + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $this->plots[$j]->value->SetAlign('center','bottom'); + $this->plots[$j]->value->SetMargin(2); + } + else { + $this->plots[$j]->value->SetAlign('center','top'); + $this->plots[$j]->value->SetMargin(1); + } + } else { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); + $accyt=$yscale->Translate($accy_neg); + $accy_neg+=$this->plots[$j]->coords[0][$i]; + if( $this->plots[$j]->valuepos=='center' ) { + $y = $accyt-($accyt-$yt)/2; + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $y = $accyt; + } + else { + $y = $accyt-($accyt-$yt); + } + if( $this->plots[$j]->valuepos=='center' ) { + $this->plots[$j]->value->SetAlign("center","center"); + $this->plots[$j]->value->SetMargin(0); + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top'); + $this->plots[$j]->value->SetMargin(-2); + } + else { + $this->plots[$j]->value->SetAlign('center','bottom'); + $this->plots[$j]->value->SetMargin(-1); + } + } + $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],round($x),round($y)); + } + + } + return true; + } +} // Class + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_canvas.php b/web/public_php/admin/jpgraph/jpgraph_canvas.php index 054417106..f94295132 100644 --- a/web/public_php/admin/jpgraph/jpgraph_canvas.php +++ b/web/public_php/admin/jpgraph/jpgraph_canvas.php @@ -1,77 +1,95 @@ -Graph($aWidth,$aHeight,$aCachedName,$timeout,$inline); - } - -//--------------- -// PUBLIC METHODS - - function InitFrame() { - $this->StrokePlotArea(); - } - - // Method description - function Stroke($aStrokeFileName="") { - if( $this->texts != null ) { - for($i=0; $i < count($this->texts); ++$i) { - $this->texts[$i]->Stroke($this->img); - } - } - if( $this->iTables !== null ) { - for($i=0; $i < count($this->iTables); ++$i) { - $this->iTables[$i]->Stroke($this->img); - } - } - $this->StrokeTitles(); - - // Should we do any final image transformation - if( $this->iImgTrans ) { - if( !class_exists('ImgTrans') ) { - require_once('jpgraph_imgtrans.php'); - } - - $tform = new ImgTrans($this->img->img); - $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, - $this->iImgTransDirection,$this->iImgTransHighQ, - $this->iImgTransMinSize,$this->iImgTransFillColor, - $this->iImgTransBorder); - } - - - // If the filename is given as the special _IMG_HANDLER - // then the image handler is returned and the image is NOT - // streamed back - if( $aStrokeFileName == _IMG_HANDLER ) { - return $this->img->img; - } - else { - // Finally stream the generated picture - $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); - return true; - } - } -} // Class -/* EOF */ -?> \ No newline at end of file +StrokePlotArea(); + } + + // Method description + function Stroke($aStrokeFileName="") { + if( $this->texts != null ) { + for($i=0; $i < count($this->texts); ++$i) { + $this->texts[$i]->Stroke($this->img); + } + } + if( $this->iTables !== null ) { + for($i=0; $i < count($this->iTables); ++$i) { + $this->iTables[$i]->Stroke($this->img); + } + } + $this->StrokeTitles(); + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // a best we can. Therefor you will see a lot of tests !$_csim in the + // code below. + $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); + + // We need to know if we have stroked the plot in the + // GetCSIMareas. Otherwise the CSIM hasn't been generated + // and in the case of GetCSIM called before stroke to generate + // CSIM without storing an image to disk GetCSIM must call Stroke. + $this->iHasStroked = true; + + if( !$_csim ) { + + // Should we do any final image transformation + if( $this->iImgTrans ) { + if( !class_exists('ImgTrans',false) ) { + require_once('jpgraph_imgtrans.php'); + } + + $tform = new ImgTrans($this->img->img); + $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, + $this->iImgTransDirection,$this->iImgTransHighQ, + $this->iImgTransMinSize,$this->iImgTransFillColor, + $this->iImgTransBorder); + } + + + // If the filename is given as the special _IMG_HANDLER + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); + return true; + } + } + } +} // Class + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_canvtools.php b/web/public_php/admin/jpgraph/jpgraph_canvtools.php index f43ee5669..2290a5bcd 100644 --- a/web/public_php/admin/jpgraph/jpgraph_canvtools.php +++ b/web/public_php/admin/jpgraph/jpgraph_canvtools.php @@ -1,516 +1,523 @@ -g = &$graph; - $this->w = $graph->img->width; - $this->h = $graph->img->height; - $this->ixmin = $xmin; - $this->ixmax = $xmax; - $this->iymin = $ymin; - $this->iymax = $ymax; - } - - function Set($xmin=0,$xmax=10,$ymin=0,$ymax=10) { - $this->ixmin = $xmin; - $this->ixmax = $xmax; - $this->iymin = $ymin; - $this->iymax = $ymax; - } - - function Translate($x,$y) { - $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w); - $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h); - return array($xp,$yp); - } - - function TranslateX($x) { - $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w); - return $xp; - } - - function TranslateY($y) { - $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h); - return $yp; - } - -} - - -//=================================================== -// CLASS Shape -// Description: Methods to draw shapes on canvas -//=================================================== -class Shape { - var $img,$scale; - - function Shape(&$aGraph,&$scale) { - $this->img = &$aGraph->img; - $this->img->SetColor('black'); - $this->scale = &$scale; - } - - function SetColor($aColor) { - $this->img->SetColor($aColor); - } - - function Line($x1,$y1,$x2,$y2) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - list($x2,$y2) = $this->scale->Translate($x2,$y2); - $this->img->Line($x1,$y1,$x2,$y2); - } - - function Polygon($p,$aClosed=false) { - $n=count($p); - for($i=0; $i < $n; $i+=2 ) { - $p[$i] = $this->scale->TranslateX($p[$i]); - $p[$i+1] = $this->scale->TranslateY($p[$i+1]); - } - $this->img->Polygon($p,$aClosed); - } - - function FilledPolygon($p) { - $n=count($p); - for($i=0; $i < $n; $i+=2 ) { - $p[$i] = $this->scale->TranslateX($p[$i]); - $p[$i+1] = $this->scale->TranslateY($p[$i+1]); - } - $this->img->FilledPolygon($p); - } - - - // Draw a bezier curve with defining points in the $aPnts array - // using $aSteps steps. - // 0=x0, 1=y0 - // 2=x1, 3=y1 - // 4=x2, 5=y2 - // 6=x3, 7=y3 - function Bezier($p,$aSteps=40) { - $x0 = $p[0]; - $y0 = $p[1]; - // Calculate coefficients - $cx = 3*($p[2]-$p[0]); - $bx = 3*($p[4]-$p[2])-$cx; - $ax = $p[6]-$p[0]-$cx-$bx; - $cy = 3*($p[3]-$p[1]); - $by = 3*($p[5]-$p[3])-$cy; - $ay = $p[7]-$p[1]-$cy-$by; - - // Step size - $delta = 1.0/$aSteps; - - $x_old = $x0; - $y_old = $y0; - for($t=$delta; $t<=1.0; $t+=$delta) { - $tt = $t*$t; $ttt=$tt*$t; - $x = $ax*$ttt + $bx*$tt + $cx*$t + $x0; - $y = $ay*$ttt + $by*$tt + $cy*$t + $y0; - $this->Line($x_old,$y_old,$x,$y); - $x_old = $x; - $y_old = $y; - } - $this->Line($x_old,$y_old,$p[6],$p[7]); - } - - function Rectangle($x1,$y1,$x2,$y2) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - list($x2,$y2) = $this->scale->Translate($x2,$y2); - $this->img->Rectangle($x1,$y1,$x2,$y2); - } - - function FilledRectangle($x1,$y1,$x2,$y2) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - list($x2,$y2) = $this->scale->Translate($x2,$y2); - $this->img->FilledRectangle($x1,$y1,$x2,$y2); - } - - function Circle($x1,$y1,$r) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - if( $r >= 0 ) - $r = $this->scale->TranslateX($r); - else - $r = -$r; - $this->img->Circle($x1,$y1,$r); - } - - function FilledCircle($x1,$y1,$r) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - if( $r >= 0 ) - $r = $this->scale->TranslateX($r); - else - $r = -$r; - $this->img->FilledCircle($x1,$y1,$r); - } - - function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - list($x2,$y2) = $this->scale->Translate($x2,$y2); - - if( $r == null ) - $r = 5; - elseif( $r >= 0 ) - $r = $this->scale->TranslateX($r); - else - $r = -$r; - $this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r); - } - - function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - list($x2,$y2) = $this->scale->Translate($x2,$y2); - - if( $r == null ) - $r = 5; - elseif( $r > 0 ) - $r = $this->scale->TranslateX($r); - else - $r = -$r; - $this->img->FilledRoundedRectangle($x1,$y1,$x2,$y2,$r); - } - - function ShadowRectangle($x1,$y1,$x2,$y2,$fcolor=false,$shadow_width=null,$shadow_color=array(102,102,102)) { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - list($x2,$y2) = $this->scale->Translate($x2,$y2); - if( $shadow_width == null ) - $shadow_width=4; - else - $shadow_width=$this->scale->TranslateX($shadow_width); - $this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color); - } - - function SetTextAlign($halign,$valign="bottom") { - $this->img->SetTextAlign($halign,$valign="bottom"); - } - - function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") { - list($x1,$y1) = $this->scale->Translate($x1,$y1); - $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align); - } - - // A rounded rectangle where one of the corner has been moved "into" the - // rectangle 'iw' width and 'ih' height. Corners: - // 0=Top left, 1=top right, 2=bottom right, 3=bottom left - function IndentedRectangle($xt,$yt,$w,$h,$iw=0,$ih=0,$aCorner=3,$aFillColor="",$r=4) { - - list($xt,$yt) = $this->scale->Translate($xt,$yt); - list($w,$h) = $this->scale->Translate($w,$h); - list($iw,$ih) = $this->scale->Translate($iw,$ih); - - $xr = $xt + $w - 0; - $yl = $yt + $h - 0; - - switch( $aCorner ) { - case 0: // Upper left - - // Bottom line, left & right arc - $this->img->Line($xt+$r,$yl,$xr-$r,$yl); - $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); - $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); - - // Right line, Top right arc - $this->img->Line($xr,$yt+$r,$xr,$yl-$r); - $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); - - // Top line, Top left arc - $this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt); - $this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270); - - // Left line - $this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r); - - // Indent horizontal, Lower left arc - $this->img->Line($xt+$r,$yt+$ih,$xt+$iw-$r,$yt+$ih); - $this->img->Arc($xt+$r,$yt+$ih+$r,$r*2,$r*2,180,270); - - // Indent vertical, Indent arc - $this->img->Line($xt+$iw,$yt+$r,$xt+$iw,$yt+$ih-$r); - $this->img->Arc($xt+$iw-$r,$yt+$ih-$r,$r*2,$r*2,0,90); - - if( $aFillColor != '' ) { - $bc = $this->img->current_color_name; - $this->img->PushColor($aFillColor); - $this->img->FillToBorder($xr-$r,$yl-$r,$bc); - $this->img->PopColor(); - } - - break; - - case 1: // Upper right - - // Bottom line, left & right arc - $this->img->Line($xt+$r,$yl,$xr-$r,$yl); - $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); - $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); - - // Left line, Top left arc - $this->img->Line($xt,$yt+$r,$xt,$yl-$r); - $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); - - // Top line, Top right arc - $this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt); - $this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360); - - // Right line - $this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r); - - // Indent horizontal, Lower right arc - $this->img->Line($xr-$iw+$r,$yt+$ih,$xr-$r,$yt+$ih); - $this->img->Arc($xr-$r,$yt+$ih+$r,$r*2,$r*2,270,360); - - // Indent vertical, Indent arc - $this->img->Line($xr-$iw,$yt+$r,$xr-$iw,$yt+$ih-$r); - $this->img->Arc($xr-$iw+$r,$yt+$ih-$r,$r*2,$r*2,90,180); - - if( $aFillColor != '' ) { - $bc = $this->img->current_color_name; - $this->img->PushColor($aFillColor); - $this->img->FillToBorder($xt+$r,$yl-$r,$bc); - $this->img->PopColor(); - } - - break; - - case 2: // Lower right - // Top line, Top left & Top right arc - $this->img->Line($xt+$r,$yt,$xr-$r,$yt); - $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); - $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); - - // Left line, Bottom left arc - $this->img->Line($xt,$yt+$r,$xt,$yl-$r); - $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); - - // Bottom line, Bottom right arc - $this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl); - $this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90); - - // Right line - $this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r); - - // Indent horizontal, Lower right arc - $this->img->Line($xr-$r,$yl-$ih,$xr-$iw+$r,$yl-$ih); - $this->img->Arc($xr-$r,$yl-$ih-$r,$r*2,$r*2,0,90); - - // Indent vertical, Indent arc - $this->img->Line($xr-$iw,$yl-$r,$xr-$iw,$yl-$ih+$r); - $this->img->Arc($xr-$iw+$r,$yl-$ih+$r,$r*2,$r*2,180,270); - - if( $aFillColor != '' ) { - $bc = $this->img->current_color_name; - $this->img->PushColor($aFillColor); - $this->img->FillToBorder($xt+$r,$yt+$r,$bc); - $this->img->PopColor(); - } - - break; - - case 3: // Lower left - // Top line, Top left & Top right arc - $this->img->Line($xt+$r,$yt,$xr-$r,$yt); - $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); - $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); - - // Right line, Bottom right arc - $this->img->Line($xr,$yt+$r,$xr,$yl-$r); - $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); - - // Bottom line, Bottom left arc - $this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl); - $this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180); - - // Left line - $this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r); - - // Indent horizontal, Lower left arc - $this->img->Line($xt+$r,$yl-$ih,$xt+$iw-$r,$yl-$ih); - $this->img->Arc($xt+$r,$yl-$ih-$r,$r*2,$r*2,90,180); - - // Indent vertical, Indent arc - $this->img->Line($xt+$iw,$yl-$ih+$r,$xt+$iw,$yl-$r); - $this->img->Arc($xt+$iw-$r,$yl-$ih+$r,$r*2,$r*2,270,360); - - if( $aFillColor != '' ) { - $bc = $this->img->current_color_name; - $this->img->PushColor($aFillColor); - $this->img->FillToBorder($xr-$r,$yt+$r,$bc); - $this->img->PopColor(); - } - - break; - } - } -} - - -//=================================================== -// CLASS RectangleText -// Description: Draws a text paragraph inside a -// rounded, possible filled, rectangle. -//=================================================== -class CanvasRectangleText { - var $ix,$iy,$iw,$ih,$ir=4; - var $iTxt,$iColor='black',$iFillColor='',$iFontColor='black'; - var $iParaAlign='center'; - var $iAutoBoxMargin=5; - var $iShadowWidth=3,$iShadowColor=''; - - function CanvasRectangleText($aTxt='',$xl=0,$yt=0,$w=0,$h=0) { - $this->iTxt = new Text($aTxt); - $this->ix = $xl; - $this->iy = $yt; - $this->iw = $w; - $this->ih = $h; - } - - function SetShadow($aColor='gray',$aWidth=3) { - $this->iShadowColor = $aColor; - $this->iShadowWidth = $aWidth; - } - - function SetFont($FontFam,$aFontStyle,$aFontSize=12) { - $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize); - } - - function SetTxt($aTxt) { - $this->iTxt->Set($aTxt); - } - - function ParagraphAlign($aParaAlign) { - $this->iParaAlign = $aParaAlign; - } - - function SetFillColor($aFillColor) { - $this->iFillColor = $aFillColor; - } - - function SetAutoMargin($aMargin) { - $this->iAutoBoxMargin=$aMargin; - } - - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function SetFontColor($aColor) { - $this->iFontColor = $aColor; - } - - function SetPos($xl=0,$yt=0,$w=0,$h=0) { - $this->ix = $xl; - $this->iy = $yt; - $this->iw = $w; - $this->ih = $h; - } - - function Pos($xl=0,$yt=0,$w=0,$h=0) { - $this->ix = $xl; - $this->iy = $yt; - $this->iw = $w; - $this->ih = $h; - } - - function Set($aTxt,$xl,$yt,$w=0,$h=0) { - $this->iTxt->Set($aTxt); - $this->ix = $xl; - $this->iy = $yt; - $this->iw = $w; - $this->ih = $h; - } - - function SetCornerRadius($aRad=5) { - $this->ir = $aRad; - } - - function Stroke($aImg,$scale) { - - // If coordinates are specifed as negative this means we should - // treat them as abolsute (pixels) coordinates - if( $this->ix > 0 ) { - $this->ix = $scale->TranslateX($this->ix) ; - } - else { - $this->ix = -$this->ix; - } - - if( $this->iy > 0 ) { - $this->iy = $scale->TranslateY($this->iy) ; - } - else { - $this->iy = -$this->iy; - } - - list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ; - - if( $this->iw == 0 ) - $this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin); - if( $this->ih == 0 ) { - $this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin); - } - - if( $this->iShadowColor != '' ) { - $aImg->PushColor($this->iShadowColor); - $aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth, - $this->iy+$this->iShadowWidth, - $this->ix+$this->iw-1+$this->iShadowWidth, - $this->iy+$this->ih-1+$this->iShadowWidth, - $this->ir); - $aImg->PopColor(); - } - - if( $this->iFillColor != '' ) { - $aImg->PushColor($this->iFillColor); - $aImg->FilledRoundedRectangle($this->ix,$this->iy, - $this->ix+$this->iw-1, - $this->iy+$this->ih-1, - $this->ir); - $aImg->PopColor(); - } - - if( $this->iColor != '' ) { - $aImg->PushColor($this->iColor); - $aImg->RoundedRectangle($this->ix,$this->iy, - $this->ix+$this->iw-1, - $this->iy+$this->ih-1, - $this->ir); - $aImg->PopColor(); - } - - $this->iTxt->Align('center','center'); - $this->iTxt->ParagraphAlign($this->iParaAlign); - $this->iTxt->SetColor($this->iFontColor); - $this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2); - - return array($this->iw, $this->ih); - - } - -} - - -?> \ No newline at end of file +g = $graph; + $this->w = $graph->img->width; + $this->h = $graph->img->height; + $this->ixmin = $xmin; + $this->ixmax = $xmax; + $this->iymin = $ymin; + $this->iymax = $ymax; + } + + function Set($xmin=0,$xmax=10,$ymin=0,$ymax=10) { + $this->ixmin = $xmin; + $this->ixmax = $xmax; + $this->iymin = $ymin; + $this->iymax = $ymax; + } + + function Get() { + return array($this->ixmin,$this->ixmax,$this->iymin,$this->iymax); + } + + function Translate($x,$y) { + $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w); + $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h); + return array($xp,$yp); + } + + function TranslateX($x) { + $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w); + return $xp; + } + + function TranslateY($y) { + $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h); + return $yp; + } + +} + + +//=================================================== +// CLASS Shape +// Description: Methods to draw shapes on canvas +//=================================================== +class Shape { + private $img,$scale; + + function __construct($aGraph,$scale) { + $this->img = $aGraph->img; + $this->img->SetColor('black'); + $this->scale = $scale; + } + + function SetColor($aColor) { + $this->img->SetColor($aColor); + } + + function Line($x1,$y1,$x2,$y2) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + list($x2,$y2) = $this->scale->Translate($x2,$y2); + $this->img->Line($x1,$y1,$x2,$y2); + } + + function SetLineWeight($aWeight) { + $this->img->SetLineWeight($aWeight); + } + + function Polygon($p,$aClosed=false) { + $n=count($p); + for($i=0; $i < $n; $i+=2 ) { + $p[$i] = $this->scale->TranslateX($p[$i]); + $p[$i+1] = $this->scale->TranslateY($p[$i+1]); + } + $this->img->Polygon($p,$aClosed); + } + + function FilledPolygon($p) { + $n=count($p); + for($i=0; $i < $n; $i+=2 ) { + $p[$i] = $this->scale->TranslateX($p[$i]); + $p[$i+1] = $this->scale->TranslateY($p[$i+1]); + } + $this->img->FilledPolygon($p); + } + + + // Draw a bezier curve with defining points in the $aPnts array + // using $aSteps steps. + // 0=x0, 1=y0 + // 2=x1, 3=y1 + // 4=x2, 5=y2 + // 6=x3, 7=y3 + function Bezier($p,$aSteps=40) { + $x0 = $p[0]; + $y0 = $p[1]; + // Calculate coefficients + $cx = 3*($p[2]-$p[0]); + $bx = 3*($p[4]-$p[2])-$cx; + $ax = $p[6]-$p[0]-$cx-$bx; + $cy = 3*($p[3]-$p[1]); + $by = 3*($p[5]-$p[3])-$cy; + $ay = $p[7]-$p[1]-$cy-$by; + + // Step size + $delta = 1.0/$aSteps; + + $x_old = $x0; + $y_old = $y0; + for($t=$delta; $t<=1.0; $t+=$delta) { + $tt = $t*$t; $ttt=$tt*$t; + $x = $ax*$ttt + $bx*$tt + $cx*$t + $x0; + $y = $ay*$ttt + $by*$tt + $cy*$t + $y0; + $this->Line($x_old,$y_old,$x,$y); + $x_old = $x; + $y_old = $y; + } + $this->Line($x_old,$y_old,$p[6],$p[7]); + } + + function Rectangle($x1,$y1,$x2,$y2) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + list($x2,$y2) = $this->scale->Translate($x2,$y2); + $this->img->Rectangle($x1,$y1,$x2,$y2); + } + + function FilledRectangle($x1,$y1,$x2,$y2) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + list($x2,$y2) = $this->scale->Translate($x2,$y2); + $this->img->FilledRectangle($x1,$y1,$x2,$y2); + } + + function Circle($x1,$y1,$r) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + if( $r >= 0 ) + $r = $this->scale->TranslateX($r); + else + $r = -$r; + $this->img->Circle($x1,$y1,$r); + } + + function FilledCircle($x1,$y1,$r) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + if( $r >= 0 ) + $r = $this->scale->TranslateX($r); + else + $r = -$r; + $this->img->FilledCircle($x1,$y1,$r); + } + + function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + list($x2,$y2) = $this->scale->Translate($x2,$y2); + + if( $r == null ) + $r = 5; + elseif( $r >= 0 ) + $r = $this->scale->TranslateX($r); + else + $r = -$r; + $this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r); + } + + function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + list($x2,$y2) = $this->scale->Translate($x2,$y2); + + if( $r == null ) + $r = 5; + elseif( $r > 0 ) + $r = $this->scale->TranslateX($r); + else + $r = -$r; + $this->img->FilledRoundedRectangle($x1,$y1,$x2,$y2,$r); + } + + function ShadowRectangle($x1,$y1,$x2,$y2,$fcolor=false,$shadow_width=null,$shadow_color=array(102,102,102)) { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + list($x2,$y2) = $this->scale->Translate($x2,$y2); + if( $shadow_width == null ) + $shadow_width=4; + else + $shadow_width=$this->scale->TranslateX($shadow_width); + $this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color); + } + + function SetTextAlign($halign,$valign="bottom") { + $this->img->SetTextAlign($halign,$valign="bottom"); + } + + function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") { + list($x1,$y1) = $this->scale->Translate($x1,$y1); + $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align); + } + + // A rounded rectangle where one of the corner has been moved "into" the + // rectangle 'iw' width and 'ih' height. Corners: + // 0=Top left, 1=top right, 2=bottom right, 3=bottom left + function IndentedRectangle($xt,$yt,$w,$h,$iw=0,$ih=0,$aCorner=3,$aFillColor="",$r=4) { + + list($xt,$yt) = $this->scale->Translate($xt,$yt); + list($w,$h) = $this->scale->Translate($w,$h); + list($iw,$ih) = $this->scale->Translate($iw,$ih); + + $xr = $xt + $w - 0; + $yl = $yt + $h - 0; + + switch( $aCorner ) { + case 0: // Upper left + + // Bottom line, left & right arc + $this->img->Line($xt+$r,$yl,$xr-$r,$yl); + $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); + $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); + + // Right line, Top right arc + $this->img->Line($xr,$yt+$r,$xr,$yl-$r); + $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); + + // Top line, Top left arc + $this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt); + $this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270); + + // Left line + $this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r); + + // Indent horizontal, Lower left arc + $this->img->Line($xt+$r,$yt+$ih,$xt+$iw-$r,$yt+$ih); + $this->img->Arc($xt+$r,$yt+$ih+$r,$r*2,$r*2,180,270); + + // Indent vertical, Indent arc + $this->img->Line($xt+$iw,$yt+$r,$xt+$iw,$yt+$ih-$r); + $this->img->Arc($xt+$iw-$r,$yt+$ih-$r,$r*2,$r*2,0,90); + + if( $aFillColor != '' ) { + $bc = $this->img->current_color_name; + $this->img->PushColor($aFillColor); + $this->img->FillToBorder($xr-$r,$yl-$r,$bc); + $this->img->PopColor(); + } + + break; + + case 1: // Upper right + + // Bottom line, left & right arc + $this->img->Line($xt+$r,$yl,$xr-$r,$yl); + $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); + $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); + + // Left line, Top left arc + $this->img->Line($xt,$yt+$r,$xt,$yl-$r); + $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); + + // Top line, Top right arc + $this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt); + $this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360); + + // Right line + $this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r); + + // Indent horizontal, Lower right arc + $this->img->Line($xr-$iw+$r,$yt+$ih,$xr-$r,$yt+$ih); + $this->img->Arc($xr-$r,$yt+$ih+$r,$r*2,$r*2,270,360); + + // Indent vertical, Indent arc + $this->img->Line($xr-$iw,$yt+$r,$xr-$iw,$yt+$ih-$r); + $this->img->Arc($xr-$iw+$r,$yt+$ih-$r,$r*2,$r*2,90,180); + + if( $aFillColor != '' ) { + $bc = $this->img->current_color_name; + $this->img->PushColor($aFillColor); + $this->img->FillToBorder($xt+$r,$yl-$r,$bc); + $this->img->PopColor(); + } + + break; + + case 2: // Lower right + // Top line, Top left & Top right arc + $this->img->Line($xt+$r,$yt,$xr-$r,$yt); + $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); + $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); + + // Left line, Bottom left arc + $this->img->Line($xt,$yt+$r,$xt,$yl-$r); + $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); + + // Bottom line, Bottom right arc + $this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl); + $this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90); + + // Right line + $this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r); + + // Indent horizontal, Lower right arc + $this->img->Line($xr-$r,$yl-$ih,$xr-$iw+$r,$yl-$ih); + $this->img->Arc($xr-$r,$yl-$ih-$r,$r*2,$r*2,0,90); + + // Indent vertical, Indent arc + $this->img->Line($xr-$iw,$yl-$r,$xr-$iw,$yl-$ih+$r); + $this->img->Arc($xr-$iw+$r,$yl-$ih+$r,$r*2,$r*2,180,270); + + if( $aFillColor != '' ) { + $bc = $this->img->current_color_name; + $this->img->PushColor($aFillColor); + $this->img->FillToBorder($xt+$r,$yt+$r,$bc); + $this->img->PopColor(); + } + + break; + + case 3: // Lower left + // Top line, Top left & Top right arc + $this->img->Line($xt+$r,$yt,$xr-$r,$yt); + $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); + $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); + + // Right line, Bottom right arc + $this->img->Line($xr,$yt+$r,$xr,$yl-$r); + $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); + + // Bottom line, Bottom left arc + $this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl); + $this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180); + + // Left line + $this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r); + + // Indent horizontal, Lower left arc + $this->img->Line($xt+$r,$yl-$ih,$xt+$iw-$r,$yl-$ih); + $this->img->Arc($xt+$r,$yl-$ih-$r,$r*2,$r*2,90,180); + + // Indent vertical, Indent arc + $this->img->Line($xt+$iw,$yl-$ih+$r,$xt+$iw,$yl-$r); + $this->img->Arc($xt+$iw-$r,$yl-$ih+$r,$r*2,$r*2,270,360); + + if( $aFillColor != '' ) { + $bc = $this->img->current_color_name; + $this->img->PushColor($aFillColor); + $this->img->FillToBorder($xr-$r,$yt+$r,$bc); + $this->img->PopColor(); + } + + break; + } + } +} + + +//=================================================== +// CLASS RectangleText +// Description: Draws a text paragraph inside a +// rounded, possible filled, rectangle. +//=================================================== +class CanvasRectangleText { + private $ix,$iy,$iw,$ih,$ir=4; + private $iTxt,$iColor='black',$iFillColor='',$iFontColor='black'; + private $iParaAlign='center'; + private $iAutoBoxMargin=5; + private $iShadowWidth=3,$iShadowColor=''; + + function __construct($aTxt='',$xl=0,$yt=0,$w=0,$h=0) { + $this->iTxt = new Text($aTxt); + $this->ix = $xl; + $this->iy = $yt; + $this->iw = $w; + $this->ih = $h; + } + + function SetShadow($aColor='gray',$aWidth=3) { + $this->iShadowColor = $aColor; + $this->iShadowWidth = $aWidth; + } + + function SetFont($FontFam,$aFontStyle,$aFontSize=12) { + $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize); + } + + function SetTxt($aTxt) { + $this->iTxt->Set($aTxt); + } + + function ParagraphAlign($aParaAlign) { + $this->iParaAlign = $aParaAlign; + } + + function SetFillColor($aFillColor) { + $this->iFillColor = $aFillColor; + } + + function SetAutoMargin($aMargin) { + $this->iAutoBoxMargin=$aMargin; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function SetFontColor($aColor) { + $this->iFontColor = $aColor; + } + + function SetPos($xl=0,$yt=0,$w=0,$h=0) { + $this->ix = $xl; + $this->iy = $yt; + $this->iw = $w; + $this->ih = $h; + } + + function Pos($xl=0,$yt=0,$w=0,$h=0) { + $this->ix = $xl; + $this->iy = $yt; + $this->iw = $w; + $this->ih = $h; + } + + function Set($aTxt,$xl,$yt,$w=0,$h=0) { + $this->iTxt->Set($aTxt); + $this->ix = $xl; + $this->iy = $yt; + $this->iw = $w; + $this->ih = $h; + } + + function SetCornerRadius($aRad=5) { + $this->ir = $aRad; + } + + function Stroke($aImg,$scale) { + + // If coordinates are specifed as negative this means we should + // treat them as abolsute (pixels) coordinates + if( $this->ix > 0 ) { + $this->ix = $scale->TranslateX($this->ix) ; + } + else { + $this->ix = -$this->ix; + } + + if( $this->iy > 0 ) { + $this->iy = $scale->TranslateY($this->iy) ; + } + else { + $this->iy = -$this->iy; + } + + list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ; + + if( $this->iw == 0 ) + $this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin); + if( $this->ih == 0 ) { + $this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin); + } + + if( $this->iShadowColor != '' ) { + $aImg->PushColor($this->iShadowColor); + $aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth, + $this->iy+$this->iShadowWidth, + $this->ix+$this->iw-1+$this->iShadowWidth, + $this->iy+$this->ih-1+$this->iShadowWidth, + $this->ir); + $aImg->PopColor(); + } + + if( $this->iFillColor != '' ) { + $aImg->PushColor($this->iFillColor); + $aImg->FilledRoundedRectangle($this->ix,$this->iy, + $this->ix+$this->iw-1, + $this->iy+$this->ih-1, + $this->ir); + $aImg->PopColor(); + } + + if( $this->iColor != '' ) { + $aImg->PushColor($this->iColor); + $aImg->RoundedRectangle($this->ix,$this->iy, + $this->ix+$this->iw-1, + $this->iy+$this->ih-1, + $this->ir); + $aImg->PopColor(); + } + + $this->iTxt->Align('center','center'); + $this->iTxt->ParagraphAlign($this->iParaAlign); + $this->iTxt->SetColor($this->iFontColor); + $this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2); + + return array($this->iw, $this->ih); + + } + +} + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_contour.php b/web/public_php/admin/jpgraph/jpgraph_contour.php new file mode 100644 index 000000000..760989e5f --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_contour.php @@ -0,0 +1,587 @@ +nbrRows = count($aMatrix); + $this->nbrCols = count($aMatrix[0]); + $this->dataPoints = $aMatrix; + + if( is_array($aIsobars) ) { + // use the isobar values supplied + $this->nbrIsobars = count($aIsobars); + $this->isobarValues = $aIsobars; + } + else { + // Determine the isobar values automatically + $this->nbrIsobars = $aIsobars; + list($min,$max) = $this->getMinMaxVal(); + $stepSize = ($max-$min) / $aIsobars ; + $isobar = $min+$stepSize/2; + for ($i = 0; $i < $aIsobars; $i++) { + $this->isobarValues[$i] = $isobar; + $isobar += $stepSize; + } + } + + if( $aColors !== null && count($aColors) > 0 ) { + + if( !is_array($aColors) ) { + JpGraphError::RaiseL(28001); + //'Third argument to Contour must be an array of colors.' + } + + if( count($aColors) != count($this->isobarValues) ) { + JpGraphError::RaiseL(28002); + //'Number of colors must equal the number of isobar lines specified'; + } + + $this->isobarColors = $aColors; + } + } + + /** + * Flip the plot around the Y-coordinate. This has the same affect as flipping the input + * data matrice + * + * @param $aFlg If true the the vertice in input data matrice position (0,0) corresponds to the top left + * corner of teh plot otherwise it will correspond to the bottom left corner (a horizontal flip) + */ + function SetInvert($aFlg=true) { + $this->invert = $aFlg; + } + + /** + * Find the min and max values in the data matrice + * + * @return array(min_value,max_value) + */ + function getMinMaxVal() { + $min = $this->dataPoints[0][0]; + $max = $this->dataPoints[0][0]; + for ($i = 0; $i < $this->nbrRows; $i++) { + if( ($mi=min($this->dataPoints[$i])) < $min ) $min = $mi; + if( ($ma=max($this->dataPoints[$i])) > $max ) $max = $ma; + } + return array($min,$max); + } + + /** + * Reset the two matrices that keeps track on where the isobars crosses the + * horizontal and vertical edges + */ + function resetEdgeMatrices() { + for ($k = 0; $k < 2; $k++) { + for ($i = 0; $i <= $this->nbrRows; $i++) { + for ($j = 0; $j <= $this->nbrCols; $j++) { + $this->edges[$k][$i][$j] = false; + } + } + } + } + + /** + * Determine if the specified isobar crosses the horizontal edge specified by its row and column + * + * @param $aRow Row index of edge to be checked + * @param $aCol Col index of edge to be checked + * @param $aIsobar Isobar value + * @return true if the isobar is crossing this edge + */ + function isobarHCrossing($aRow,$aCol,$aIsobar) { + + if( $aCol >= $this->nbrCols-1 ) { + JpGraphError::RaiseL(28003,$aCol); + //'ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)' + } + if( $aRow >= $this->nbrRows ) { + JpGraphError::RaiseL(28004,$aRow); + //'ContourPlot Internal Error: isobarHCrossing: Row index too large (%d)' + } + + $v1 = $this->dataPoints[$aRow][$aCol]; + $v2 = $this->dataPoints[$aRow][$aCol+1]; + + return ($aIsobar-$v1)*($aIsobar-$v2) < 0 ; + + } + + /** + * Determine if the specified isobar crosses the vertical edge specified by its row and column + * + * @param $aRow Row index of edge to be checked + * @param $aCol Col index of edge to be checked + * @param $aIsobar Isobar value + * @return true if the isobar is crossing this edge + */ + function isobarVCrossing($aRow,$aCol,$aIsobar) { + + if( $aRow >= $this->nbrRows-1) { + JpGraphError::RaiseL(28005,$aRow); + //'isobarVCrossing: Row index too large + } + if( $aCol >= $this->nbrCols ) { + JpGraphError::RaiseL(28006,$aCol); + //'isobarVCrossing: Col index too large + } + + $v1 = $this->dataPoints[$aRow][$aCol]; + $v2 = $this->dataPoints[$aRow+1][$aCol]; + + return ($aIsobar-$v1)*($aIsobar-$v2) < 0 ; + + } + + /** + * Determine all edges, horizontal and vertical that the specified isobar crosses. The crossings + * are recorded in the two edge matrices. + * + * @param $aIsobar The value of the isobar to be checked + */ + function determineIsobarEdgeCrossings($aIsobar) { + + $ib = $this->isobarValues[$aIsobar]; + + for ($i = 0; $i < $this->nbrRows-1; $i++) { + for ($j = 0; $j < $this->nbrCols-1; $j++) { + $this->edges[HORIZ_EDGE][$i][$j] = $this->isobarHCrossing($i,$j,$ib); + $this->edges[VERT_EDGE][$i][$j] = $this->isobarVCrossing($i,$j,$ib); + } + } + + // We now have the bottom and rightmost edges unsearched + for ($i = 0; $i < $this->nbrRows-1; $i++) { + $this->edges[VERT_EDGE][$i][$j] = $this->isobarVCrossing($i,$this->nbrCols-1,$ib); + } + for ($j = 0; $j < $this->nbrCols-1; $j++) { + $this->edges[HORIZ_EDGE][$i][$j] = $this->isobarHCrossing($this->nbrRows-1,$j,$ib); + } + + } + + /** + * Return the normalized coordinates for the crossing of the specified edge with the specified + * isobar- The crossing is simpy detrmined with a linear interpolation between the two vertices + * on each side of the edge and the value of the isobar + * + * @param $aRow Row of edge + * @param $aCol Column of edge + * @param $aEdgeDir Determine if this is a horizontal or vertical edge + * @param $ib The isobar value + * @return unknown_type + */ + function getCrossingCoord($aRow,$aCol,$aEdgeDir,$aIsobarVal) { + + // In order to avoid numerical problem when two vertices are very close + // we have to check and avoid dividing by close to zero denumerator. + if( $aEdgeDir == HORIZ_EDGE ) { + $d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow][$aCol+1]); + if( $d > 0.001 ) { + $xcoord = $aCol + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d; + } + else { + $xcoord = $aCol; + } + $ycoord = $aRow; + } + else { + $d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow+1][$aCol]); + if( $d > 0.001 ) { + $ycoord = $aRow + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d; + } + else { + $ycoord = $aRow; + } + $xcoord = $aCol; + } + if( $this->invert ) { + $ycoord = $this->nbrRows-1 - $ycoord; + } + return array($xcoord,$ycoord); + + } + + /** + * In order to avoid all kinds of unpleasent extra checks and complex boundary + * controls for the degenerated case where the contour levels exactly crosses + * one of the vertices we add a very small delta (0.1%) to the data point value. + * This has no visible affect but it makes the code sooooo much cleaner. + * + */ + function adjustDataPointValues() { + + $ni = count($this->isobarValues); + for ($k = 0; $k < $ni; $k++) { + $ib = $this->isobarValues[$k]; + for ($row = 0 ; $row < $this->nbrRows-1; ++$row) { + for ($col = 0 ; $col < $this->nbrCols-1; ++$col ) { + if( abs($this->dataPoints[$row][$col] - $ib) < 0.0001 ) { + $this->dataPoints[$row][$col] += $this->dataPoints[$row][$col]*0.001; + } + } + } + } + + } + + /** + * @param $aFlg + * @param $aBW + * @return unknown_type + */ + function UseHighContrastColor($aFlg=true,$aBW=false) { + $this->highcontrast = $aFlg; + $this->highcontrastbw = $aBW; + } + + /** + * Calculate suitable colors for each defined isobar + * + */ + function CalculateColors() { + if ( $this->highcontrast ) { + if ( $this->highcontrastbw ) { + for ($ib = 0; $ib < $this->nbrIsobars; $ib++) { + $this->isobarColors[$ib] = 'black'; + } + } + else { + // Use only blue/red scale + $step = round(255/($this->nbrIsobars-1)); + for ($ib = 0; $ib < $this->nbrIsobars; $ib++) { + $this->isobarColors[$ib] = array($ib*$step, 50, 255-$ib*$step); + } + } + } + else { + $n = $this->nbrIsobars; + $v = 0; $step = 1 / ($this->nbrIsobars-1); + for ($ib = 0; $ib < $this->nbrIsobars; $ib++) { + $this->isobarColors[$ib] = RGB::GetSpectrum($v); + $v += $step; + } + } + } + + /** + * This is where the main work is done. For each isobar the crossing of the edges are determined + * and then each cell is analyzed to find the 0, 2 or 4 crossings. Then the normalized coordinate + * for the crossings are determined and pushed on to the isobar stack. When the method is finished + * the $isobarCoord will hold one arrayfor each isobar where all the line segments that makes + * up the contour plot are stored. + * + * @return array( $isobarCoord, $isobarValues, $isobarColors ) + */ + function getIsobars() { + + $this->adjustDataPointValues(); + + for ($isobar = 0; $isobar < $this->nbrIsobars; $isobar++) { + + $ib = $this->isobarValues[$isobar]; + $this->resetEdgeMatrices(); + $this->determineIsobarEdgeCrossings($isobar); + $this->isobarCoord[$isobar] = array(); + + $ncoord = 0; + + for ($row = 0 ; $row < $this->nbrRows-1; ++$row) { + for ($col = 0 ; $col < $this->nbrCols-1; ++$col ) { + + // Find out how many crossings around the edges + $n = 0; + if ( $this->edges[HORIZ_EDGE][$row][$col] ) $neigh[$n++] = array($row, $col, HORIZ_EDGE); + if ( $this->edges[HORIZ_EDGE][$row+1][$col] ) $neigh[$n++] = array($row+1,$col, HORIZ_EDGE); + if ( $this->edges[VERT_EDGE][$row][$col] ) $neigh[$n++] = array($row, $col, VERT_EDGE); + if ( $this->edges[VERT_EDGE][$row][$col+1] ) $neigh[$n++] = array($row, $col+1,VERT_EDGE); + + if ( $n == 2 ) { + $n1=0; $n2=1; + $this->isobarCoord[$isobar][$ncoord++] = array( + $this->getCrossingCoord($neigh[$n1][0],$neigh[$n1][1],$neigh[$n1][2],$ib), + $this->getCrossingCoord($neigh[$n2][0],$neigh[$n2][1],$neigh[$n2][2],$ib) ); + } + elseif ( $n == 4 ) { + // We must determine how to connect the edges either northwest->southeast or + // northeast->southwest. We do that by calculating the imaginary middle value of + // the cell by averaging the for corners. This will compared with the value of the + // top left corner will help determine the orientation of the ridge/creek + $midval = ($this->dataPoints[$row][$col]+$this->dataPoints[$row][$col+1]+$this->dataPoints[$row+1][$col]+$this->dataPoints[$row+1][$col+1])/4; + $v = $this->dataPoints[$row][$col]; + if( $midval == $ib ) { + // Orientation "+" + $n1=0; $n2=1; $n3=2; $n4=3; + } elseif ( ($midval > $ib && $v > $ib) || ($midval < $ib && $v < $ib) ) { + // Orientation of ridge/valley = "\" + $n1=0; $n2=3; $n3=2; $n4=1; + } elseif ( ($midval > $ib && $v < $ib) || ($midval < $ib && $v > $ib) ) { + // Orientation of ridge/valley = "/" + $n1=0; $n2=2; $n3=3; $n4=1; + } + + $this->isobarCoord[$isobar][$ncoord++] = array( + $this->getCrossingCoord($neigh[$n1][0],$neigh[$n1][1],$neigh[$n1][2],$ib), + $this->getCrossingCoord($neigh[$n2][0],$neigh[$n2][1],$neigh[$n2][2],$ib) ); + + $this->isobarCoord[$isobar][$ncoord++] = array( + $this->getCrossingCoord($neigh[$n3][0],$neigh[$n3][1],$neigh[$n3][2],$ib), + $this->getCrossingCoord($neigh[$n4][0],$neigh[$n4][1],$neigh[$n4][2],$ib) ); + + } + } + } + } + + if( count($this->isobarColors) == 0 ) { + // No manually specified colors. Calculate them automatically. + $this->CalculateColors(); + } + return array( $this->isobarCoord, $this->isobarValues, $this->isobarColors ); + } +} + + +/** + * This class represent a plotting of a contour outline of data given as a X-Y matrice + * + */ +class ContourPlot extends Plot { + + private $contour, $contourCoord, $contourVal, $contourColor; + private $nbrCountours = 0 ; + private $dataMatrix = array(); + private $invertLegend = false; + private $interpFactor = 1; + private $flipData = false; + private $isobar = 10; + private $showLegend = false; + private $highcontrast = false, $highcontrastbw = false; + private $manualIsobarColors = array(); + + /** + * Construct a contour plotting algorithm. The end result of the algorithm is a sequence of + * line segments for each isobar given as two vertices. + * + * @param $aDataMatrix The Z-data to be used + * @param $aIsobar A mixed variable, if it is an integer then this specified the number of isobars to use. + * The values of the isobars are automatically detrmined to be equ-spaced between the min/max value of the + * data. If it is an array then it explicetely gives the isobar values + * @param $aInvert By default the matrice with row index 0 corresponds to Y-value 0, i.e. in the bottom of + * the plot. If this argument is true then the row with the highest index in the matrice corresponds to + * Y-value 0. In affect flipping the matrice around an imaginary horizontal axis. + * @param $aHighContrast Use high contrast colors (blue/red:ish) + * @param $aHighContrastBW Use only black colors for contours + * @return an instance of the contour plot algorithm + */ + function __construct($aDataMatrix, $aIsobar=10, $aFactor=1, $aInvert=false, $aIsobarColors=array()) { + + $this->dataMatrix = $aDataMatrix; + $this->flipData = $aInvert; + $this->isobar = $aIsobar; + $this->interpFactor = $aFactor; + + if ( $this->interpFactor > 1 ) { + + if( $this->interpFactor > 5 ) { + JpGraphError::RaiseL(28007);// ContourPlot interpolation factor is too large (>5) + } + + $ip = new MeshInterpolate(); + $this->dataMatrix = $ip->Linear($this->dataMatrix, $this->interpFactor); + } + + $this->contour = new Contour($this->dataMatrix,$this->isobar,$aIsobarColors); + + if( is_array($aIsobar) ) + $this->nbrContours = count($aIsobar); + else + $this->nbrContours = $aIsobar; + } + + + /** + * Flipe the data around the center + * + * @param $aFlg + * + */ + function SetInvert($aFlg=true) { + $this->flipData = $aFlg; + } + + /** + * Set the colors for the isobar lines + * + * @param $aColorArray + * + */ + function SetIsobarColors($aColorArray) { + $this->manualIsobarColors = $aColorArray; + } + + /** + * Show the legend + * + * @param $aFlg true if the legend should be shown + * + */ + function ShowLegend($aFlg=true) { + $this->showLegend = $aFlg; + } + + + /** + * @param $aFlg true if the legend should start with the lowest isobar on top + * @return unknown_type + */ + function Invertlegend($aFlg=true) { + $this->invertLegend = $aFlg; + } + + /* Internal method. Give the min value to be used for the scaling + * + */ + function Min() { + return array(0,0); + } + + /* Internal method. Give the max value to be used for the scaling + * + */ + function Max() { + return array(count($this->dataMatrix[0])-1,count($this->dataMatrix)-1); + } + + /** + * Internal ramewrok method to setup the legend to be used for this plot. + * @param $aGraph The parent graph class + */ + function Legend($aGraph) { + + if( ! $this->showLegend ) + return; + + if( $this->invertLegend ) { + for ($i = 0; $i < $this->nbrContours; $i++) { + $aGraph->legend->Add(sprintf('%.1f',$this->contourVal[$i]), $this->contourColor[$i]); + } + } + else { + for ($i = $this->nbrContours-1; $i >= 0 ; $i--) { + $aGraph->legend->Add(sprintf('%.1f',$this->contourVal[$i]), $this->contourColor[$i]); + } + } + } + + + /** + * Framework function which gets called before the Stroke() method is called + * + * @see Plot#PreScaleSetup($aGraph) + * + */ + function PreScaleSetup($aGraph) { + $xn = count($this->dataMatrix[0])-1; + $yn = count($this->dataMatrix)-1; + + $aGraph->xaxis->scale->Update($aGraph->img,0,$xn); + $aGraph->yaxis->scale->Update($aGraph->img,0,$yn); + + $this->contour->SetInvert($this->flipData); + list($this->contourCoord,$this->contourVal,$this->contourColor) = $this->contour->getIsobars(); + } + + /** + * Use high contrast color schema + * + * @param $aFlg True, to use high contrast color + * @param $aBW True, Use only black and white color schema + */ + function UseHighContrastColor($aFlg=true,$aBW=false) { + $this->highcontrast = $aFlg; + $this->highcontrastbw = $aBW; + $this->contour->UseHighContrastColor($this->highcontrast,$this->highcontrastbw); + } + + /** + * Internal method. Stroke the contour plot to the graph + * + * @param $img Image handler + * @param $xscale Instance of the xscale to use + * @param $yscale Instance of the yscale to use + */ + function Stroke($img,$xscale,$yscale) { + + if( count($this->manualIsobarColors) > 0 ) { + $this->contourColor = $this->manualIsobarColors; + if( count($this->manualIsobarColors) != $this->nbrContours ) { + JpGraphError::RaiseL(28002); + } + } + + $img->SetLineWeight($this->line_weight); + + for ($c = 0; $c < $this->nbrContours; $c++) { + + $img->SetColor( $this->contourColor[$c] ); + + $n = count($this->contourCoord[$c]); + $i = 0; + while ( $i < $n ) { + list($x1,$y1) = $this->contourCoord[$c][$i][0]; + $x1t = $xscale->Translate($x1); + $y1t = $yscale->Translate($y1); + + list($x2,$y2) = $this->contourCoord[$c][$i++][1]; + $x2t = $xscale->Translate($x2); + $y2t = $yscale->Translate($y2); + + $img->Line($x1t,$y1t,$x2t,$y2t); + } + + } + } + +} + +// EOF +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_date.php b/web/public_php/admin/jpgraph/jpgraph_date.php index 21a0b8ebb..bfb5ddb6a 100644 --- a/web/public_php/admin/jpgraph/jpgraph_date.php +++ b/web/public_php/admin/jpgraph/jpgraph_date.php @@ -1,492 +1,505 @@ -type=$aType; - $this->scale=array($aMin,$aMax); - $this->world_size=$aMax-$aMin; - $this->ticks = new LinearTicks(); - $this->intscale=true; - } - - -//------------------------------------------------------------------------------------------ -// Utility Function AdjDate() -// Description: Will round a given time stamp to an even year, month or day -// argument. -//------------------------------------------------------------------------------------------ - - function AdjDate($aTime,$aRound=0,$aYearType=false,$aMonthType=false,$aDayType=false) { - $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); - $h=0;$i=0;$s=0; - if( $aYearType !== false ) { - $yearAdj = array(0=>1, 1=>2, 2=>5); - if( $aRound == 0 ) { - $y = floor($y/$yearAdj[$aYearType])*$yearAdj[$aYearType]; - } - else { - ++$y; - $y = ceil($y/$yearAdj[$aYearType])*$yearAdj[$aYearType]; - } - $m=1;$d=1; - } - elseif( $aMonthType !== false ) { - $monthAdj = array(0=>1, 1=>6); - if( $aRound == 0 ) { - $m = floor($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType]; - $d=1; - } - else { - ++$m; - $m = ceil($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType]; - $d=1; - } - } - elseif( $aDayType !== false ) { - if( $aDayType == 0 ) { - if( $aRound == 1 ) { - //++$d; - $h=23;$i=59;$s=59; - } - } - else { - // Adjust to an even week boundary. - $w = (int)date('w',$aTime); // Day of week 0=Sun, 6=Sat - if( true ) { // Adjust to start on Mon - if( $w==0 ) $w=6; - else --$w; - } - if( $aRound == 0 ) { - $d -= $w; - } - else { - $d += (7-$w); - $h=23;$i=59;$s=59; - } - } - } - return mktime($h,$i,$s,$m,$d,$y); - - } - -//------------------------------------------------------------------------------------------ -// Wrapper for AdjDate that will round a timestamp to an even date rounding -// it downwards. -//------------------------------------------------------------------------------------------ - function AdjStartDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) { - return $this->AdjDate($aTime,0,$aYearType,$aMonthType,$aDayType); - } - -//------------------------------------------------------------------------------------------ -// Wrapper for AdjDate that will round a timestamp to an even date rounding -// it upwards -//------------------------------------------------------------------------------------------ - function AdjEndDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) { - return $this->AdjDate($aTime,1,$aYearType,$aMonthType,$aDayType); - } - -//------------------------------------------------------------------------------------------ -// Utility Function AdjTime() -// Description: Will round a given time stamp to an even time according to -// argument. -//------------------------------------------------------------------------------------------ - - function AdjTime($aTime,$aRound=0,$aHourType=false,$aMinType=false,$aSecType=false) { - $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); - $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); $s = (int)date('s',$aTime); - if( $aHourType !== false ) { - $aHourType %= 6; - $hourAdj = array(0=>1, 1=>2, 2=>3, 3=>4, 4=>6, 5=>12); - if( $aRound == 0 ) - $h = floor($h/$hourAdj[$aHourType])*$hourAdj[$aHourType]; - else { - if( ($h % $hourAdj[$aHourType]==0) && ($i > 0 || $s > 0) ) { - $h++; - } - $h = ceil($h/$hourAdj[$aHourType])*$hourAdj[$aHourType]; - if( $h >= 24 ) { - $aTime += 86400; - $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); - $h -= 24; - } - } - $i=0;$s=0; - } - elseif( $aMinType !== false ) { - $aMinType %= 5; - $minAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30); - if( $aRound == 0 ) { - $i = floor($i/$minAdj[$aMinType])*$minAdj[$aMinType]; - } - else { - if( ($i % $minAdj[$aMinType]==0) && $s > 0 ) { - $i++; - } - $i = ceil($i/$minAdj[$aMinType])*$minAdj[$aMinType]; - if( $i >= 60) { - $aTime += 3600; - $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); - $h = (int)date('H',$aTime); $i = 0; - } - } - $s=0; - } - elseif( $aSecType !== false ) { - $aSecType %= 5; - $secAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30); - if( $aRound == 0 ) { - $s = floor($s/$secAdj[$aSecType])*$secAdj[$aSecType]; - } - else { - $s = ceil($s/$secAdj[$aSecType]*1.0)*$secAdj[$aSecType]; - if( $s >= 60) { - $s=0; - $aTime += 60; - $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); - $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); - } - } - } - return mktime($h,$i,$s,$m,$d,$y); - } - -//------------------------------------------------------------------------------------------ -// Wrapper for AdjTime that will round a timestamp to an even time rounding -// it downwards. -// Example: AdjStartTime(mktime(18,27,13,2,22,2005),false,2) => 18:20 -//------------------------------------------------------------------------------------------ - function AdjStartTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) { - return $this->AdjTime($aTime,0,$aHourType,$aMinType,$aSecType); - } - -//------------------------------------------------------------------------------------------ -// Wrapper for AdjTime that will round a timestamp to an even time rounding -// it upwards -// Example: AdjEndTime(mktime(18,27,13,2,22,2005),false,2) => 18:30 -//------------------------------------------------------------------------------------------ - function AdjEndTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) { - return $this->AdjTime($aTime,1,$aHourType,$aMinType,$aSecType); - } - -//------------------------------------------------------------------------------------------ -// DateAutoScale -// Autoscale a date axis given start and end time -// Returns an array ($start,$end,$major,$minor,$format) -//------------------------------------------------------------------------------------------ - function DoDateAutoScale($aStartTime,$aEndTime,$aDensity=0,$aAdjust=true) { - // Format of array - // array ( Decision point, array( array( Major-scale-step-array ), - // array( Minor-scale-step-array ), - // array( 0=date-adjust, 1=time-adjust, adjustment-alignment) ) - // - $scalePoints = - array( - /* Intervall larger than 10 years */ - SECPERYEAR*10,array(array(SECPERYEAR*5,SECPERYEAR*2), - array(SECPERYEAR), - array(0,YEARADJ_1, 0,YEARADJ_1) ), - - /* Intervall larger than 2 years */ - SECPERYEAR*2,array(array(SECPERYEAR),array(SECPERYEAR), - array(0,YEARADJ_1) ), - - /* Intervall larger than 90 days (approx 3 month) */ - SECPERDAY*90,array(array(SECPERDAY*30,SECPERDAY*14,SECPERDAY*7,SECPERDAY), - array(SECPERDAY*5,SECPERDAY*7,SECPERDAY,SECPERDAY), - array(0,MONTHADJ_1, 0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1)), - - /* Intervall larger than 30 days (approx 1 month) */ - SECPERDAY*30,array(array(SECPERDAY*14,SECPERDAY*7,SECPERDAY*2, SECPERDAY), - array(SECPERDAY,SECPERDAY.SECPERDAY,SECPERDAY), - array(0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1, 0,DAYADJ_1)), - - /* Intervall larger than 7 days */ - SECPERDAY*7,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2), - array(SECPERHOUR*6,SECPERHOUR*3,SECPERHOUR,SECPERHOUR), - array(0,DAYADJ_1, 1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1)), - - /* Intervall larger than 1 day */ - SECPERDAY,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR), - array(SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR,SECPERHOUR,SECPERHOUR), - array(1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1, 1,HOURADJ_1)), - - /* Intervall larger than 12 hours */ - SECPERHOUR*12,array(array(SECPERHOUR*2,SECPERHOUR,SECPERMIN*30,900,600), - array(1800,1800,900,300,300), - array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), - - /* Intervall larger than 2 hours */ - SECPERHOUR*2,array(array(SECPERHOUR,SECPERMIN*30,900,600,300), - array(1800,900,300,120,60), - array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), - - /* Intervall larger than 1 hours */ - SECPERHOUR,array(array(SECPERMIN*30,900,600,300),array(900,300,120,60), - array(1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), - - /* Intervall larger than 30 min */ - SECPERMIN*30,array(array(SECPERMIN*15,SECPERMIN*10,SECPERMIN*5,SECPERMIN), - array(300,300,60,10), - array(1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5, 1,MINADJ_1)), - - /* Intervall larger than 1 min */ - SECPERMIN,array(array(SECPERMIN,15,10,5), - array(15,5,2,1), - array(1,MINADJ_1, 1,SECADJ_15, 1,SECADJ_10, 1,SECADJ_5)), - - /* Intervall larger than 10 sec */ - 10,array(array(5,2), - array(1,1), - array(1,SECADJ_5, 1,SECADJ_1)), - - /* Intervall larger than 1 sec */ - 1,array(array(1), - array(1), - array(1,SECADJ_1)), - ); - - $ns = count($scalePoints); - // Establish major and minor scale units for the date scale - $diff = $aEndTime - $aStartTime; - if( $diff < 1 ) return false; - $done=false; - $i=0; - while( ! $done ) { - if( $diff > $scalePoints[2*$i] ) { - // Get major and minor scale for this intervall - $scaleSteps = $scalePoints[2*$i+1]; - $major = $scaleSteps[0][min($aDensity,count($scaleSteps[0])-1)]; - // Try to find out which minor step looks best - $minor = $scaleSteps[1][min($aDensity,count($scaleSteps[1])-1)]; - if( $aAdjust ) { - // Find out how we should align the start and end timestamps - $idx = 2*min($aDensity,floor(count($scaleSteps[2])/2)-1); - if( $scaleSteps[2][$idx] === 0 ) { - // Use date adjustment - $adj = $scaleSteps[2][$idx+1]; - if( $adj >= 30 ) { - $start = $this->AdjStartDate($aStartTime,$adj-30); - $end = $this->AdjEndDate($aEndTime,$adj-30); - } - elseif( $adj >= 20 ) { - $start = $this->AdjStartDate($aStartTime,false,$adj-20); - $end = $this->AdjEndDate($aEndTime,false,$adj-20); - } - else { - $start = $this->AdjStartDate($aStartTime,false,false,$adj); - $end = $this->AdjEndDate($aEndTime,false,false,$adj); - // We add 1 second for date adjustment to make sure we end on 00:00 the following day - // This makes the final major tick be srawn when we step day-by-day instead of ending - // on xx:59:59 which would not draw the final major tick - $end++; - } - } - else { - // Use time adjustment - $adj = $scaleSteps[2][$idx+1]; - if( $adj >= 30 ) { - $start = $this->AdjStartTime($aStartTime,$adj-30); - $end = $this->AdjEndTime($aEndTime,$adj-30); - } - elseif( $adj >= 20 ) { - $start = $this->AdjStartTime($aStartTime,false,$adj-20); - $end = $this->AdjEndTime($aEndTime,false,$adj-20); - } - else { - $start = $this->AdjStartTime($aStartTime,false,false,$adj); - $end = $this->AdjEndTime($aEndTime,false,false,$adj); - } - } - } - // If the overall date span is larger than 1 day ten we show date - $format = ''; - if( ($end-$start) > SECPERDAY ) { - $format = 'Y-m-d '; - } - // If the major step is less than 1 day we need to whow hours + min - if( $major < SECPERDAY ) { - $format .= 'H:i'; - } - // If the major step is less than 1 min we need to show sec - if( $major < 60 ) { - $format .= ':s'; - } - $done=true; - } - ++$i; - } - return array($start,$end,$major,$minor,$format); - } - - // Overrides the automatic determined date format. Must be a valid date() format string - function SetDateFormat($aFormat) { - $this->date_format = $aFormat; - } - - function SetDateAlign($aStartAlign,$aEndAlign=false) { - if( $aEndAlign === false ) { - $aEndAlign=$aStartAlign; - } - $this->iStartAlign = $aStartAlign; - $this->iEndAlign = $aEndAlign; - } - - function SetTimeAlign($aStartAlign,$aEndAlign=false) { - if( $aEndAlign === false ) { - $aEndAlign=$aStartAlign; - } - $this->iStartTimeAlign = $aStartAlign; - $this->iEndTimeAlign = $aEndAlign; - } - - - function AutoScale(&$img,$aStartTime,$aEndTime,$aNumSteps) { - if( $aStartTime == $aEndTime ) { - // Special case when we only have one data point. - // Create a small artifical intervall to do the autoscaling - $aStartTime -= 10; - $aEndTime += 10; - } - $done=false; - $i=0; - while( ! $done && $i < 5) { - list($adjstart,$adjend,$maj,$min,$format) = $this->DoDateAutoScale($aStartTime,$aEndTime,$i); - $n = floor(($adjend-$adjstart)/$maj); - if( $n * 1.7 > $aNumSteps ) { - $done=true; - } - $i++; - } - - /* - if( 0 ) { // DEBUG - echo " Start =".date("Y-m-d H:i:s",$aStartTime)."
"; - echo " End =".date("Y-m-d H:i:s",$aEndTime)."
"; - echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."
"; - echo "Adj End =".date("Y-m-d H:i:s",$adjend)."

"; - echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day
"; - echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day
"; - echo "Format=$format

"; - } - */ - - if( $this->iStartTimeAlign !== false && $this->iStartAlign !== false ) { - JpGraphError::RaiseL(3001); -//('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both'); - } - - if( $this->iStartTimeAlign !== false ) { - if( $this->iStartTimeAlign >= 30 ) { - $adjstart = $this->AdjStartTime($aStartTime,$this->iStartTimeAlign-30); - } - elseif( $this->iStartTimeAlign >= 20 ) { - $adjstart = $this->AdjStartTime($aStartTime,false,$this->iStartTimeAlign-20); - } - else { - $adjstart = $this->AdjStartTime($aStartTime,false,false,$this->iStartTimeAlign); - } - } - if( $this->iEndTimeAlign !== false ) { - if( $this->iEndTimeAlign >= 30 ) { - $adjend = $this->AdjEndTime($aEndTime,$this->iEndTimeAlign-30); - } - elseif( $this->iEndTimeAlign >= 20 ) { - $adjend = $this->AdjEndTime($aEndTime,false,$this->iEndTimeAlign-20); - } - else { - $adjend = $this->AdjEndTime($aEndTime,false,false,$this->iEndTimeAlign); - } - } - - - - if( $this->iStartAlign !== false ) { - if( $this->iStartAlign >= 30 ) { - $adjstart = $this->AdjStartDate($aStartTime,$this->iStartAlign-30); - } - elseif( $this->iStartAlign >= 20 ) { - $adjstart = $this->AdjStartDate($aStartTime,false,$this->iStartAlign-20); - } - else { - $adjstart = $this->AdjStartDate($aStartTime,false,false,$this->iStartAlign); - } - } - if( $this->iEndAlign !== false ) { - if( $this->iEndAlign >= 30 ) { - $adjend = $this->AdjEndDate($aEndTime,$this->iEndAlign-30); - } - elseif( $this->iEndAlign >= 20 ) { - $adjend = $this->AdjEndDate($aEndTime,false,$this->iEndAlign-20); - } - else { - $adjend = $this->AdjEndDate($aEndTime,false,false,$this->iEndAlign); - } - } - $this->Update($img,$adjstart,$adjend); - if( ! $this->ticks->IsSpecified() ) - $this->ticks->Set($maj,$min); - if( $this->date_format == '' ) - $this->ticks->SetLabelDateFormat($format); - else - $this->ticks->SetLabelDateFormat($this->date_format); - } -} - - -?> +type=$aType; + $this->scale=array($aMin,$aMax); + $this->world_size=$aMax-$aMin; + $this->ticks = new LinearTicks(); + $this->intscale=true; + } + + + //------------------------------------------------------------------------------------------ + // Utility Function AdjDate() + // Description: Will round a given time stamp to an even year, month or day + // argument. + //------------------------------------------------------------------------------------------ + + function AdjDate($aTime,$aRound=0,$aYearType=false,$aMonthType=false,$aDayType=false) { + $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); + $h=0;$i=0;$s=0; + if( $aYearType !== false ) { + $yearAdj = array(0=>1, 1=>2, 2=>5); + if( $aRound == 0 ) { + $y = floor($y/$yearAdj[$aYearType])*$yearAdj[$aYearType]; + } + else { + ++$y; + $y = ceil($y/$yearAdj[$aYearType])*$yearAdj[$aYearType]; + } + $m=1;$d=1; + } + elseif( $aMonthType !== false ) { + $monthAdj = array(0=>1, 1=>6); + if( $aRound == 0 ) { + $m = floor($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType]; + $d=1; + } + else { + ++$m; + $m = ceil($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType]; + $d=1; + } + } + elseif( $aDayType !== false ) { + if( $aDayType == 0 ) { + if( $aRound == 1 ) { + //++$d; + $h=23;$i=59;$s=59; + } + } + else { + // Adjust to an even week boundary. + $w = (int)date('w',$aTime); // Day of week 0=Sun, 6=Sat + if( true ) { // Adjust to start on Mon + if( $w==0 ) $w=6; + else --$w; + } + if( $aRound == 0 ) { + $d -= $w; + } + else { + $d += (7-$w); + $h=23;$i=59;$s=59; + } + } + } + return mktime($h,$i,$s,$m,$d,$y); + + } + + //------------------------------------------------------------------------------------------ + // Wrapper for AdjDate that will round a timestamp to an even date rounding + // it downwards. + //------------------------------------------------------------------------------------------ + function AdjStartDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) { + return $this->AdjDate($aTime,0,$aYearType,$aMonthType,$aDayType); + } + + //------------------------------------------------------------------------------------------ + // Wrapper for AdjDate that will round a timestamp to an even date rounding + // it upwards + //------------------------------------------------------------------------------------------ + function AdjEndDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) { + return $this->AdjDate($aTime,1,$aYearType,$aMonthType,$aDayType); + } + + //------------------------------------------------------------------------------------------ + // Utility Function AdjTime() + // Description: Will round a given time stamp to an even time according to + // argument. + //------------------------------------------------------------------------------------------ + + function AdjTime($aTime,$aRound=0,$aHourType=false,$aMinType=false,$aSecType=false) { + $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); + $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); $s = (int)date('s',$aTime); + if( $aHourType !== false ) { + $aHourType %= 6; + $hourAdj = array(0=>1, 1=>2, 2=>3, 3=>4, 4=>6, 5=>12); + if( $aRound == 0 ) + $h = floor($h/$hourAdj[$aHourType])*$hourAdj[$aHourType]; + else { + if( ($h % $hourAdj[$aHourType]==0) && ($i > 0 || $s > 0) ) { + $h++; + } + $h = ceil($h/$hourAdj[$aHourType])*$hourAdj[$aHourType]; + if( $h >= 24 ) { + $aTime += 86400; + $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); + $h -= 24; + } + } + $i=0;$s=0; + } + elseif( $aMinType !== false ) { + $aMinType %= 5; + $minAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30); + if( $aRound == 0 ) { + $i = floor($i/$minAdj[$aMinType])*$minAdj[$aMinType]; + } + else { + if( ($i % $minAdj[$aMinType]==0) && $s > 0 ) { + $i++; + } + $i = ceil($i/$minAdj[$aMinType])*$minAdj[$aMinType]; + if( $i >= 60) { + $aTime += 3600; + $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); + $h = (int)date('H',$aTime); $i = 0; + } + } + $s=0; + } + elseif( $aSecType !== false ) { + $aSecType %= 5; + $secAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30); + if( $aRound == 0 ) { + $s = floor($s/$secAdj[$aSecType])*$secAdj[$aSecType]; + } + else { + $s = ceil($s/$secAdj[$aSecType]*1.0)*$secAdj[$aSecType]; + if( $s >= 60) { + $s=0; + $aTime += 60; + $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); + $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); + } + } + } + return mktime($h,$i,$s,$m,$d,$y); + } + + //------------------------------------------------------------------------------------------ + // Wrapper for AdjTime that will round a timestamp to an even time rounding + // it downwards. + // Example: AdjStartTime(mktime(18,27,13,2,22,2005),false,2) => 18:20 + //------------------------------------------------------------------------------------------ + function AdjStartTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) { + return $this->AdjTime($aTime,0,$aHourType,$aMinType,$aSecType); + } + + //------------------------------------------------------------------------------------------ + // Wrapper for AdjTime that will round a timestamp to an even time rounding + // it upwards + // Example: AdjEndTime(mktime(18,27,13,2,22,2005),false,2) => 18:30 + //------------------------------------------------------------------------------------------ + function AdjEndTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) { + return $this->AdjTime($aTime,1,$aHourType,$aMinType,$aSecType); + } + + //------------------------------------------------------------------------------------------ + // DateAutoScale + // Autoscale a date axis given start and end time + // Returns an array ($start,$end,$major,$minor,$format) + //------------------------------------------------------------------------------------------ + function DoDateAutoScale($aStartTime,$aEndTime,$aDensity=0,$aAdjust=true) { + // Format of array + // array ( Decision point, array( array( Major-scale-step-array ), + // array( Minor-scale-step-array ), + // array( 0=date-adjust, 1=time-adjust, adjustment-alignment) ) + // + $scalePoints = + array( + /* Intervall larger than 10 years */ + SECPERYEAR*10,array(array(SECPERYEAR*5,SECPERYEAR*2), + array(SECPERYEAR), + array(0,YEARADJ_1, 0,YEARADJ_1) ), + + /* Intervall larger than 2 years */ + SECPERYEAR*2,array(array(SECPERYEAR),array(SECPERYEAR), + array(0,YEARADJ_1) ), + + /* Intervall larger than 90 days (approx 3 month) */ + SECPERDAY*90,array(array(SECPERDAY*30,SECPERDAY*14,SECPERDAY*7,SECPERDAY), + array(SECPERDAY*5,SECPERDAY*7,SECPERDAY,SECPERDAY), + array(0,MONTHADJ_1, 0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1)), + + /* Intervall larger than 30 days (approx 1 month) */ + SECPERDAY*30,array(array(SECPERDAY*14,SECPERDAY*7,SECPERDAY*2, SECPERDAY), + array(SECPERDAY,SECPERDAY,SECPERDAY,SECPERDAY), + array(0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1, 0,DAYADJ_1)), + + /* Intervall larger than 7 days */ + SECPERDAY*7,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2), + array(SECPERHOUR*6,SECPERHOUR*3,SECPERHOUR,SECPERHOUR), + array(0,DAYADJ_1, 1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1)), + + /* Intervall larger than 1 day */ + SECPERDAY,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR), + array(SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR,SECPERHOUR,SECPERHOUR), + array(1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1, 1,HOURADJ_1)), + + /* Intervall larger than 12 hours */ + SECPERHOUR*12,array(array(SECPERHOUR*2,SECPERHOUR,SECPERMIN*30,900,600), + array(1800,1800,900,300,300), + array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), + + /* Intervall larger than 2 hours */ + SECPERHOUR*2,array(array(SECPERHOUR,SECPERMIN*30,900,600,300), + array(1800,900,300,120,60), + array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), + + /* Intervall larger than 1 hours */ + SECPERHOUR,array(array(SECPERMIN*30,900,600,300),array(900,300,120,60), + array(1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), + + /* Intervall larger than 30 min */ + SECPERMIN*30,array(array(SECPERMIN*15,SECPERMIN*10,SECPERMIN*5,SECPERMIN), + array(300,300,60,10), + array(1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5, 1,MINADJ_1)), + + /* Intervall larger than 1 min */ + SECPERMIN,array(array(SECPERMIN,15,10,5), + array(15,5,2,1), + array(1,MINADJ_1, 1,SECADJ_15, 1,SECADJ_10, 1,SECADJ_5)), + + /* Intervall larger than 10 sec */ + 10,array(array(5,2), + array(1,1), + array(1,SECADJ_5, 1,SECADJ_1)), + + /* Intervall larger than 1 sec */ + 1,array(array(1), + array(1), + array(1,SECADJ_1)), + ); + + $ns = count($scalePoints); + // Establish major and minor scale units for the date scale + $diff = $aEndTime - $aStartTime; + if( $diff < 1 ) return false; + $done=false; + $i=0; + while( ! $done ) { + if( $diff > $scalePoints[2*$i] ) { + // Get major and minor scale for this intervall + $scaleSteps = $scalePoints[2*$i+1]; + $major = $scaleSteps[0][min($aDensity,count($scaleSteps[0])-1)]; + // Try to find out which minor step looks best + $minor = $scaleSteps[1][min($aDensity,count($scaleSteps[1])-1)]; + if( $aAdjust ) { + // Find out how we should align the start and end timestamps + $idx = 2*min($aDensity,floor(count($scaleSteps[2])/2)-1); + if( $scaleSteps[2][$idx] === 0 ) { + // Use date adjustment + $adj = $scaleSteps[2][$idx+1]; + if( $adj >= 30 ) { + $start = $this->AdjStartDate($aStartTime,$adj-30); + $end = $this->AdjEndDate($aEndTime,$adj-30); + } + elseif( $adj >= 20 ) { + $start = $this->AdjStartDate($aStartTime,false,$adj-20); + $end = $this->AdjEndDate($aEndTime,false,$adj-20); + } + else { + $start = $this->AdjStartDate($aStartTime,false,false,$adj); + $end = $this->AdjEndDate($aEndTime,false,false,$adj); + // We add 1 second for date adjustment to make sure we end on 00:00 the following day + // This makes the final major tick be srawn when we step day-by-day instead of ending + // on xx:59:59 which would not draw the final major tick + $end++; + } + } + else { + // Use time adjustment + $adj = $scaleSteps[2][$idx+1]; + if( $adj >= 30 ) { + $start = $this->AdjStartTime($aStartTime,$adj-30); + $end = $this->AdjEndTime($aEndTime,$adj-30); + } + elseif( $adj >= 20 ) { + $start = $this->AdjStartTime($aStartTime,false,$adj-20); + $end = $this->AdjEndTime($aEndTime,false,$adj-20); + } + else { + $start = $this->AdjStartTime($aStartTime,false,false,$adj); + $end = $this->AdjEndTime($aEndTime,false,false,$adj); + } + } + } + // If the overall date span is larger than 1 day ten we show date + $format = ''; + if( ($end-$start) > SECPERDAY ) { + $format = 'Y-m-d '; + } + // If the major step is less than 1 day we need to whow hours + min + if( $major < SECPERDAY ) { + $format .= 'H:i'; + } + // If the major step is less than 1 min we need to show sec + if( $major < 60 ) { + $format .= ':s'; + } + $done=true; + } + ++$i; + } + return array($start,$end,$major,$minor,$format); + } + + // Overrides the automatic determined date format. Must be a valid date() format string + function SetDateFormat($aFormat) { + $this->date_format = $aFormat; + $this->ticks->SetLabelDateFormat($this->date_format); + } + + function AdjustForDST($aFlg=true) { + $this->ticks->AdjustForDST($aFlg); + } + + + function SetDateAlign($aStartAlign,$aEndAlign=false) { + if( $aEndAlign === false ) { + $aEndAlign=$aStartAlign; + } + $this->iStartAlign = $aStartAlign; + $this->iEndAlign = $aEndAlign; + } + + function SetTimeAlign($aStartAlign,$aEndAlign=false) { + if( $aEndAlign === false ) { + $aEndAlign=$aStartAlign; + } + $this->iStartTimeAlign = $aStartAlign; + $this->iEndTimeAlign = $aEndAlign; + } + + + function AutoScale($img,$aStartTime,$aEndTime,$aNumSteps,$_adummy=false) { + // We need to have one dummy argument to make the signature of AutoScale() + // identical to LinearScale::AutoScale + if( $aStartTime == $aEndTime ) { + // Special case when we only have one data point. + // Create a small artificial interval to do the autoscaling + $aStartTime -= 10; + $aEndTime += 10; + } + if( abs($aEndTime - $aStartTime) <= 1 ) { + // Special case when we only have one second. + // Create a small artificial interval to do the autoscaling + $aStartTime -= 1; + $aEndTime += 1; + } + $done=false; + $i=0; + while( ! $done && $i < 5) { + list($adjstart,$adjend,$maj,$min,$format) = $this->DoDateAutoScale($aStartTime,$aEndTime,$i); + $n = floor(($adjend-$adjstart)/$maj); + if( $n * 1.7 > $aNumSteps ) { + $done=true; + } + $i++; + } + + /* + if( 0 ) { // DEBUG + echo " Start =".date("Y-m-d H:i:s",$aStartTime)."
"; + echo " End =".date("Y-m-d H:i:s",$aEndTime)."
"; + echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."
"; + echo "Adj End =".date("Y-m-d H:i:s",$adjend)."

"; + echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day
"; + echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day
"; + echo "Format=$format

"; + } + */ + + if( $this->iStartTimeAlign !== false && $this->iStartAlign !== false ) { + JpGraphError::RaiseL(3001); + //('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both'); + } + + if( $this->iStartTimeAlign !== false ) { + if( $this->iStartTimeAlign >= 30 ) { + $adjstart = $this->AdjStartTime($aStartTime,$this->iStartTimeAlign-30); + } + elseif( $this->iStartTimeAlign >= 20 ) { + $adjstart = $this->AdjStartTime($aStartTime,false,$this->iStartTimeAlign-20); + } + else { + $adjstart = $this->AdjStartTime($aStartTime,false,false,$this->iStartTimeAlign); + } + } + if( $this->iEndTimeAlign !== false ) { + if( $this->iEndTimeAlign >= 30 ) { + $adjend = $this->AdjEndTime($aEndTime,$this->iEndTimeAlign-30); + } + elseif( $this->iEndTimeAlign >= 20 ) { + $adjend = $this->AdjEndTime($aEndTime,false,$this->iEndTimeAlign-20); + } + else { + $adjend = $this->AdjEndTime($aEndTime,false,false,$this->iEndTimeAlign); + } + } + + + + if( $this->iStartAlign !== false ) { + if( $this->iStartAlign >= 30 ) { + $adjstart = $this->AdjStartDate($aStartTime,$this->iStartAlign-30); + } + elseif( $this->iStartAlign >= 20 ) { + $adjstart = $this->AdjStartDate($aStartTime,false,$this->iStartAlign-20); + } + else { + $adjstart = $this->AdjStartDate($aStartTime,false,false,$this->iStartAlign); + } + } + if( $this->iEndAlign !== false ) { + if( $this->iEndAlign >= 30 ) { + $adjend = $this->AdjEndDate($aEndTime,$this->iEndAlign-30); + } + elseif( $this->iEndAlign >= 20 ) { + $adjend = $this->AdjEndDate($aEndTime,false,$this->iEndAlign-20); + } + else { + $adjend = $this->AdjEndDate($aEndTime,false,false,$this->iEndAlign); + } + } + $this->Update($img,$adjstart,$adjend); + if( ! $this->ticks->IsSpecified() ) + $this->ticks->Set($maj,$min); + if( $this->date_format == '' ) + $this->ticks->SetLabelDateFormat($format); + else + $this->ticks->SetLabelDateFormat($this->date_format); + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_errhandler.inc.php b/web/public_php/admin/jpgraph/jpgraph_errhandler.inc.php new file mode 100644 index 000000000..3dff8ebee --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_errhandler.inc.php @@ -0,0 +1,369 @@ +lt = $_jpg_messages; + } + + function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { + GLOBAL $__jpg_err_locale; + if( !isset($this->lt[$errnbr]) ) { + return 'Internal error: The specified error message ('.$errnbr.') does not exist in the chosen locale ('.$__jpg_err_locale.')'; + } + $ea = $this->lt[$errnbr]; + $j=0; + if( $a1 !== null ) { + $argv[$j++] = $a1; + if( $a2 !== null ) { + $argv[$j++] = $a2; + if( $a3 !== null ) { + $argv[$j++] = $a3; + if( $a4 !== null ) { + $argv[$j++] = $a4; + if( $a5 !== null ) { + $argv[$j++] = $a5; + } + } + } + } + } + $numargs = $j; + if( $ea[1] != $numargs ) { + // Error message argument count do not match. + // Just return the error message without arguments. + return $ea[0]; + } + switch( $numargs ) { + case 1: + $msg = sprintf($ea[0],$argv[0]); + break; + case 2: + $msg = sprintf($ea[0],$argv[0],$argv[1]); + break; + case 3: + $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]); + break; + case 4: + $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]); + break; + case 5: + $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]); + break; + case 0: + default: + $msg = sprintf($ea[0]); + break; + } + return $msg; + } +} + +// +// A wrapper class that is used to access the specified error object +// (to hide the global error parameter and avoid having a GLOBAL directive +// in all methods. +// +class JpGraphError { + private static $__iImgFlg = true; + private static $__iLogFile = ''; + private static $__iTitle = 'JpGraph Error: '; + public static function Raise($aMsg,$aHalt=true){ + throw new JpGraphException($aMsg); + } + public static function SetErrLocale($aLoc) { + GLOBAL $__jpg_err_locale ; + $__jpg_err_locale = $aLoc; + } + public static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { + throw new JpGraphExceptionL($errnbr,$a1,$a2,$a3,$a4,$a5); + } + public static function SetImageFlag($aFlg=true) { + self::$__iImgFlg = $aFlg; + } + public static function GetImageFlag() { + return self::$__iImgFlg; + } + public static function SetLogFile($aFile) { + self::$__iLogFile = $aFile; + } + public static function GetLogFile() { + return self::$__iLogFile; + } + public static function SetTitle($aTitle) { + self::$__iTitle = $aTitle; + } + public static function GetTitle() { + return self::$__iTitle; + } +} + +class JpGraphException extends Exception { + // Redefine the exception so message isn't optional + public function __construct($message, $code = 0) { + // make sure everything is assigned properly + parent::__construct($message, $code); + } + // custom string representation of object + public function _toString() { + return __CLASS__ . ": [{$this->code}]: {$this->message} at " . basename($this->getFile()) . ":" . $this->getLine() . "\n" . $this->getTraceAsString() . "\n"; + } + // custom representation of error as an image + public function Stroke() { + if( JpGraphError::GetImageFlag() ) { + $errobj = new JpGraphErrObjectImg(); + $errobj->SetTitle(JpGraphError::GetTitle()); + } + else { + $errobj = new JpGraphErrObject(); + $errobj->SetTitle(JpGraphError::GetTitle()); + $errobj->SetStrokeDest(JpGraphError::GetLogFile()); + } + $errobj->Raise($this->getMessage()); + } + static public function defaultHandler(Throwable $exception) { + global $__jpg_OldHandler; + if( $exception instanceof JpGraphException ) { + $exception->Stroke(); + } + else { + // Restore old handler + if( $__jpg_OldHandler !== NULL ) { + set_exception_handler($__jpg_OldHandler); + } + throw $exception; + } + } +} + +class JpGraphExceptionL extends JpGraphException { + // Redefine the exception so message isn't optional + public function __construct($errcode,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { + // make sure everything is assigned properly + $errtxt = new ErrMsgText(); + JpGraphError::SetTitle('JpGraph Error: '.$errcode); + parent::__construct($errtxt->Get($errcode,$a1,$a2,$a3,$a4,$a5), 0); + } +} + +// Setup the default handler +global $__jpg_OldHandler; +$__jpg_OldHandler = set_exception_handler(array('JpGraphException','defaultHandler')); + +// +// First of all set up a default error handler +// + +//============================================================= +// The default trivial text error handler. +//============================================================= +class JpGraphErrObject { + + protected $iTitle = "JpGraph error: "; + protected $iDest = false; + + + function __construct() { + // Empty. Reserved for future use + } + + function SetTitle($aTitle) { + $this->iTitle = $aTitle; + } + + function SetStrokeDest($aDest) { + $this->iDest = $aDest; + } + + // If aHalt is true then execution can't continue. Typical used for fatal errors + function Raise($aMsg,$aHalt=false) { + if( $this->iDest != '' ) { + if( $this->iDest == 'syslog' ) { + error_log($this->iTitle.$aMsg); + } + else { + $str = '['.date('r').'] '.$this->iTitle.$aMsg."\n"; + $f = @fopen($this->iDest,'a'); + if( $f ) { + @fwrite($f,$str); + @fclose($f); + } + } + } + else { + $aMsg = $this->iTitle.$aMsg; + // Check SAPI and if we are called from the command line + // send the error to STDERR instead + if( PHP_SAPI == 'cli' ) { + fwrite(STDERR,$aMsg); + } + else { + echo $aMsg; + } + } + if( $aHalt ) + exit(1); + } +} + +//============================================================== +// An image based error handler +//============================================================== +class JpGraphErrObjectImg extends JpGraphErrObject { + + function __construct() { + parent::__construct(); + // Empty. Reserved for future use + } + + function Raise($aMsg,$aHalt=true) { + $img_iconerror = + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'. + 'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. + 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'. + 'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. + 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. + 'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'. + '2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'. + 'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'. + 'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'. + 'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'. + '6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'. + 'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'. + 'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'. + 'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'. + 'qL72fwAAAABJRU5ErkJggg==' ; + + + if( function_exists("imagetypes") ) { + $supported = imagetypes(); + } else { + $supported = 0; + } + + if( !function_exists('imagecreatefromstring') ) { + $supported = 0; + } + + if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) { + // Special case for headers already sent or that the installation doesn't support + // the PNG format (which the error icon is encoded in). + // Dont return an image since it can't be displayed + die($this->iTitle.' '.$aMsg); + } + + $aMsg = wordwrap($aMsg,55); + $lines = substr_count($aMsg,"\n"); + + // Create the error icon GD + $erricon = Image::CreateFromString(base64_decode($img_iconerror)); + + // Create an image that contains the error text. + $w=400; + $h=100 + 15*max(0,$lines-3); + + $img = new Image($w,$h); + + + // Drop shadow + $img->SetColor("gray"); + $img->FilledRectangle(5,5,$w-1,$h-1,10); + $img->SetColor("gray:0.7"); + $img->FilledRectangle(5,5,$w-3,$h-3,10); + + // Window background + $img->SetColor("lightblue"); + $img->FilledRectangle(1,1,$w-5,$h-5); + $img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40); + + // Window border + $img->SetColor("black"); + $img->Rectangle(1,1,$w-5,$h-5); + $img->Rectangle(0,0,$w-4,$h-4); + + // Window top row + $img->SetColor("darkred"); + for($y=3; $y < 18; $y += 2 ) + $img->Line(1,$y,$w-6,$y); + + // "White shadow" + $img->SetColor("white"); + + // Left window edge + $img->Line(2,2,2,$h-5); + $img->Line(2,2,$w-6,2); + + // "Gray button shadow" + $img->SetColor("darkgray"); + + // Gray window shadow + $img->Line(2,$h-6,$w-5,$h-6); + $img->Line(3,$h-7,$w-5,$h-7); + + // Window title + $m = floor($w/2-5); + $l = 110; + $img->SetColor("lightgray:1.3"); + $img->FilledRectangle($m-$l,2,$m+$l,16); + + // Stroke text + $img->SetColor("darkred"); + $img->SetFont(FF_FONT2,FS_BOLD); + $img->StrokeText($m-90,15,$this->iTitle); + $img->SetColor("black"); + $img->SetFont(FF_FONT1,FS_NORMAL); + $txt = new Text($aMsg,52,25); + $txt->SetFont(FF_FONT1); + $txt->Align("left","top"); + $txt->Stroke($img); + if ($this->iDest) { + $img->Stream($this->iDest); + } else { + $img->Headers(); + $img->Stream(); + } + if( $aHalt ) + die(); + } +} + + + +if( ! USE_IMAGE_ERROR_HANDLER ) { + JpGraphError::SetImageFlag(false); +} +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_error.php b/web/public_php/admin/jpgraph/jpgraph_error.php index 635b38911..3ef3ca5b7 100644 --- a/web/public_php/admin/jpgraph/jpgraph_error.php +++ b/web/public_php/admin/jpgraph/jpgraph_error.php @@ -1,157 +1,157 @@ -Plot($datay,$datax); - $this->numpoints /= 2; - } -//--------------- -// PUBLIC METHODS - - // Gets called before any axis are stroked - function PreStrokeAdjust(&$graph) { - if( $this->center ) { - $a=0.5; $b=0.5; - ++$this->numpoints; - } else { - $a=0; $b=0; - } - $graph->xaxis->scale->ticks->SetXLabelOffset($a); - $graph->SetTextScaleOff($b); - //$graph->xaxis->scale->ticks->SupressMinorTickMarks(); - } - - // Method description - function Stroke(&$img,&$xscale,&$yscale) { - $numpoints=count($this->coords[0])/2; - $img->SetColor($this->color); - $img->SetLineWeight($this->weight); - - if( isset($this->coords[1]) ) { - if( count($this->coords[1])!=$numpoints ) - JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); -//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints"); - else - $exist_x = true; - } - else - $exist_x = false; - - for( $i=0; $i<$numpoints; ++$i) { - if( $exist_x ) - $x=$this->coords[1][$i]; - else - $x=$i; - - if( !is_numeric($x) || - !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) { - continue; - } - - $xt = $xscale->Translate($x); - $yt1 = $yscale->Translate($this->coords[0][$i*2]); - $yt2 = $yscale->Translate($this->coords[0][$i*2+1]); - $img->Line($xt,$yt1,$xt,$yt2); - $img->Line($xt-$this->errwidth,$yt1,$xt+$this->errwidth,$yt1); - $img->Line($xt-$this->errwidth,$yt2,$xt+$this->errwidth,$yt2); - } - return true; - } -} // Class - - -//=================================================== -// CLASS ErrorLinePlot -// Description: Combine a line and error plot -// THIS IS A DEPRECATED PLOT TYPE JUST KEPT FOR -// BACKWARD COMPATIBILITY -//=================================================== -class ErrorLinePlot extends ErrorPlot { - var $line=null; -//--------------- -// CONSTRUCTOR - function ErrorLinePlot(&$datay,$datax=false) { - $this->ErrorPlot($datay,$datax); - // Calculate line coordinates as the average of the error limits - $n = count($datay); - for($i=0; $i < $n; $i+=2 ) { - $ly[]=($datay[$i]+$datay[$i+1])/2; - } - $this->line=new LinePlot($ly,$datax); - } - -//--------------- -// PUBLIC METHODS - function Legend(&$graph) { - if( $this->legend != "" ) - $graph->legend->Add($this->legend,$this->color); - $this->line->Legend($graph); - } - - function Stroke(&$img,&$xscale,&$yscale) { - parent::Stroke($img,$xscale,$yscale); - $this->line->Stroke($img,$xscale,$yscale); - } -} // Class - - -//=================================================== -// CLASS LineErrorPlot -// Description: Combine a line and error plot -//=================================================== -class LineErrorPlot extends ErrorPlot { - var $line=null; -//--------------- -// CONSTRUCTOR - // Data is (val, errdeltamin, errdeltamax) - function LineErrorPlot(&$datay,$datax=false) { - $ly=array(); $ey=array(); - $n = count($datay); - if( $n % 3 != 0 ) { - JpGraphError::RaiseL(4002); -//('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3'); - } - for($i=0; $i < $n; $i+=3 ) { - $ly[]=$datay[$i]; - $ey[]=$datay[$i]+$datay[$i+1]; - $ey[]=$datay[$i]+$datay[$i+2]; - } - $this->ErrorPlot($ey,$datax); - $this->line=new LinePlot($ly,$datax); - } - -//--------------- -// PUBLIC METHODS - function Legend(&$graph) { - if( $this->legend != "" ) - $graph->legend->Add($this->legend,$this->color); - $this->line->Legend($graph); - } - - function Stroke(&$img,&$xscale,&$yscale) { - parent::Stroke($img,$xscale,$yscale); - $this->line->Stroke($img,$xscale,$yscale); - } -} // Class - - -/* EOF */ -?> \ No newline at end of file +numpoints /= 2; + } + //--------------- + // PUBLIC METHODS + + // Gets called before any axis are stroked + function PreStrokeAdjust($graph) { + if( $this->center ) { + $a=0.5; $b=0.5; + ++$this->numpoints; + } else { + $a=0; $b=0; + } + $graph->xaxis->scale->ticks->SetXLabelOffset($a); + $graph->SetTextScaleOff($b); + //$graph->xaxis->scale->ticks->SupressMinorTickMarks(); + } + + // Method description + function Stroke($img,$xscale,$yscale) { + $numpoints=count($this->coords[0])/2; + $img->SetColor($this->color); + $img->SetLineWeight($this->weight); + + if( isset($this->coords[1]) ) { + if( count($this->coords[1])!=$numpoints ) + JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); + //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints"); + else + $exist_x = true; + } + else + $exist_x = false; + + for( $i=0; $i<$numpoints; ++$i) { + if( $exist_x ) + $x=$this->coords[1][$i]; + else + $x=$i; + + if( !is_numeric($x) || + !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) { + continue; + } + + $xt = $xscale->Translate($x); + $yt1 = $yscale->Translate($this->coords[0][$i*2]); + $yt2 = $yscale->Translate($this->coords[0][$i*2+1]); + $img->Line($xt,$yt1,$xt,$yt2); + $img->Line($xt-$this->errwidth,$yt1,$xt+$this->errwidth,$yt1); + $img->Line($xt-$this->errwidth,$yt2,$xt+$this->errwidth,$yt2); + } + return true; + } +} // Class + + +//=================================================== +// CLASS ErrorLinePlot +// Description: Combine a line and error plot +// THIS IS A DEPRECATED PLOT TYPE JUST KEPT FOR +// BACKWARD COMPATIBILITY +//=================================================== +class ErrorLinePlot extends ErrorPlot { + public $line=null; + //--------------- + // CONSTRUCTOR + function __construct($datay,$datax=false) { + parent::__construct($datay,$datax); + // Calculate line coordinates as the average of the error limits + $n = count($datay); + for($i=0; $i < $n; $i+=2 ) { + $ly[]=($datay[$i]+$datay[$i+1])/2; + } + $this->line=new LinePlot($ly,$datax); + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + if( $this->legend != "" ) + $graph->legend->Add($this->legend,$this->color); + $this->line->Legend($graph); + } + + function Stroke($img,$xscale,$yscale) { + parent::Stroke($img,$xscale,$yscale); + $this->line->Stroke($img,$xscale,$yscale); + } +} // Class + + +//=================================================== +// CLASS LineErrorPlot +// Description: Combine a line and error plot +//=================================================== +class LineErrorPlot extends ErrorPlot { + public $line=null; + //--------------- + // CONSTRUCTOR + // Data is (val, errdeltamin, errdeltamax) + function __construct($datay,$datax=false) { + $ly=array(); $ey=array(); + $n = count($datay); + if( $n % 3 != 0 ) { + JpGraphError::RaiseL(4002); + //('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3'); + } + for($i=0; $i < $n; $i+=3 ) { + $ly[]=$datay[$i]; + $ey[]=$datay[$i]+$datay[$i+1]; + $ey[]=$datay[$i]+$datay[$i+2]; + } + parent::__construct($ey,$datax); + $this->line=new LinePlot($ly,$datax); + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + if( $this->legend != "" ) + $graph->legend->Add($this->legend,$this->color); + $this->line->Legend($graph); + } + + function Stroke($img,$xscale,$yscale) { + parent::Stroke($img,$xscale,$yscale); + $this->line->Stroke($img,$xscale,$yscale); + } +} // Class + + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_flags.php b/web/public_php/admin/jpgraph/jpgraph_flags.php index b53efd54d..f062eb622 100644 --- a/web/public_php/admin/jpgraph/jpgraph_flags.php +++ b/web/public_php/admin/jpgraph/jpgraph_flags.php @@ -1,374 +1,373 @@ - 'afgh', - 'Republic of Angola' => 'agla', - 'Republic of Albania' => 'alba', - 'Alderney' => 'alde', - 'Democratic and Popular Republic of Algeria' => 'alge', - 'Territory of American Samoa' => 'amsa', - 'Principality of Andorra' => 'andr', - 'British Overseas Territory of Anguilla' => 'angu', - 'Antarctica' => 'anta', - 'Argentine Republic' => 'arge', - 'League of Arab States' => 'arle', - 'Republic of Armenia' => 'arme', - 'Aruba' => 'arub', - 'Commonwealth of Australia' => 'astl', - 'Republic of Austria' => 'aust', - 'Azerbaijani Republic' => 'azer', - 'British Antarctic Territory' => 'bant', - 'Kingdom of Belgium' => 'belg', - 'British Overseas Territory of Bermuda' => 'berm', - 'Commonwealth of the Bahamas' => 'bhms', - 'Kingdom of Bahrain' => 'bhrn', - 'Republic of Belarus' => 'blru', - 'Republic of Bolivia' => 'blva', - 'Belize' => 'blze', - 'Republic of Benin' => 'bnin', - 'Republic of Botswana' => 'bots', - 'Federative Republic of Brazil' => 'braz', - 'Barbados' => 'brbd', - 'British Indian Ocean Territory' => 'brin', - 'Brunei Darussalam' => 'brun', - 'Republic of Burkina' => 'bufa', - 'Republic of Bulgaria' => 'bulg', - 'Republic of Burundi' => 'buru', - 'Overseas Territory of the British Virgin Islands' => 'bvis', - 'Central African Republic' => 'cafr', - 'Kingdom of Cambodia' => 'camb', - 'Republic of Cameroon' => 'came', - 'Dominion of Canada' => 'cana', - 'Caribbean Community' => 'cari', - 'Republic of Cape Verde' => 'cave', - 'Republic of Chad' => 'chad', - 'Republic of Chile' => 'chil', - 'Peoples Republic of China' => 'chin', - 'Territory of Christmas Island' => 'chms', - 'Commonwealth of Independent States' => 'cins', - 'Cook Islands' => 'ckis', - 'Republic of Colombia' => 'clmb', - 'Territory of Cocos Islands' => 'cois', - 'Commonwealth' => 'comn', - 'Union of the Comoros' => 'como', - 'Republic of the Congo' => 'cong', - 'Republic of Costa Rica' => 'corc', - 'Republic of Croatia' => 'croa', - 'Republic of Cuba' => 'cuba', - 'British Overseas Territory of the Cayman Islands' => 'cyis', - 'Republic of Cyprus' => 'cypr', - 'The Czech Republic' => 'czec', - 'Kingdom of Denmark' => 'denm', - 'Republic of Djibouti' => 'djib', - 'Commonwealth of Dominica' => 'domn', - 'Dominican Republic' => 'dore', - 'Republic of Ecuador' => 'ecua', - 'Arab Republic of Egypt' => 'egyp', - 'Republic of El Salvador' => 'elsa', - 'England' => 'engl', - 'Republic of Equatorial Guinea' => 'eqgu', - 'State of Eritrea' => 'erit', - 'Republic of Estonia' => 'estn', - 'Ethiopia' => 'ethp', - 'European Union' => 'euun', - 'British Overseas Territory of the Falkland Islands' => 'fais', - 'International Federation of Vexillological Associations' => 'fiav', - 'Republic of Fiji' => 'fiji', - 'Republic of Finland' => 'finl', - 'Territory of French Polynesia' => 'fpol', - 'French Republic' => 'fran', - 'Overseas Department of French Guiana' => 'frgu', - 'Gabonese Republic' => 'gabn', - 'Republic of the Gambia' => 'gamb', - 'Republic of Georgia' => 'geor', - 'Federal Republic of Germany' => 'germ', - 'Republic of Ghana' => 'ghan', - 'Gibraltar' => 'gibr', - 'Hellenic Republic' => 'grec', - 'State of Grenada' => 'gren', - 'Overseas Department of Guadeloupe' => 'guad', - 'Territory of Guam' => 'guam', - 'Republic of Guatemala' => 'guat', - 'The Bailiwick of Guernsey' => 'guer', - 'Republic of Guinea' => 'guin', - 'Republic of Haiti' => 'hait', - 'Hong Kong Special Administrative Region' => 'hokn', - 'Republic of Honduras' => 'hond', - 'Republic of Hungary' => 'hung', - 'Republic of Iceland' => 'icel', - 'International Committee of the Red Cross' => 'icrc', - 'Republic of India' => 'inda', - 'Republic of Indonesia' => 'indn', - 'Republic of Iraq' => 'iraq', - 'Republic of Ireland' => 'irel', - 'Organization of the Islamic Conference' => 'isco', - 'Isle of Man' => 'isma', - 'State of Israel' => 'isra', - 'Italian Republic' => 'ital', - 'Jamaica' => 'jama', - 'Japan' => 'japa', - 'The Bailiwick of Jersey' => 'jers', - 'Hashemite Kingdom of Jordan' => 'jord', - 'Republic of Kazakhstan' => 'kazk', - 'Republic of Kenya' => 'keny', - 'Republic of Kiribati' => 'kirb', - 'State of Kuwait' => 'kuwa', - 'Kyrgyz Republic' => 'kyrg', - 'Republic of Latvia' => 'latv', - 'Lebanese Republic' => 'leba', - 'Kingdom of Lesotho' => 'lest', - 'Republic of Liberia' => 'libe', - 'Principality of Liechtenstein' => 'liec', - 'Republic of Lithuania' => 'lith', - 'Grand Duchy of Luxembourg' => 'luxe', - 'Macao Special Administrative Region' => 'maca', - 'Republic of Macedonia' => 'mace', - 'Republic of Madagascar' => 'mada', - 'Republic of the Marshall Islands' => 'mais', - 'Republic of Mali' => 'mali', - 'Federation of Malaysia' => 'mals', - 'Republic of Malta' => 'malt', - 'Republic of Malawi' => 'malw', - 'Overseas Department of Martinique' => 'mart', - 'Islamic Republic of Mauritania' => 'maur', - 'Territorial Collectivity of Mayotte' => 'mayt', - 'United Mexican States' => 'mexc', - 'Federated States of Micronesia' => 'micr', - 'Midway Islands' => 'miis', - 'Republic of Moldova' => 'mold', - 'Principality of Monaco' => 'mona', - 'Republic of Mongolia' => 'mong', - 'British Overseas Territory of Montserrat' => 'mont', - 'Kingdom of Morocco' => 'morc', - 'Republic of Mozambique' => 'moza', - 'Republic of Mauritius' => 'mrts', - 'Union of Myanmar' => 'myan', - 'Republic of Namibia' => 'namb', - 'North Atlantic Treaty Organization' => 'nato', - 'Republic of Nauru' => 'naur', - 'Turkish Republic of Northern Cyprus' => 'ncyp', - 'Netherlands Antilles' => 'nean', - 'Kingdom of Nepal' => 'nepa', - 'Kingdom of the Netherlands' => 'neth', - 'Territory of Norfolk Island' => 'nfis', - 'Federal Republic of Nigeria' => 'ngra', - 'Republic of Nicaragua' => 'nica', - 'Republic of Niger' => 'nigr', - 'Niue' => 'niue', - 'Commonwealth of the Northern Mariana Islands' => 'nmar', - 'Province of Northern Ireland' => 'noir', - 'Nordic Council' => 'nord', - 'Kingdom of Norway' => 'norw', - 'Territory of New Caledonia and Dependencies' => 'nwca', - 'New Zealand' => 'nwze', - 'Organization of American States' => 'oast', - 'Organization of African Unity' => 'oaun', - 'International Olympic Committee' => 'olym', - 'Sultanate of Oman' => 'oman', - 'Islamic Republic of Pakistan' => 'paks', - 'Republic of Palau' => 'pala', - 'Independent State of Papua New Guinea' => 'pang', - 'Republic of Paraguay' => 'para', - 'Republic of Peru' => 'peru', - 'Republic of the Philippines' => 'phil', - 'British Overseas Territory of the Pitcairn Islands' => 'piis', - 'Republic of Poland' => 'pola', - 'Republic of Portugal' => 'port', - 'Commonwealth of Puerto Rico' => 'purc', - 'State of Qatar' => 'qata', - 'Russian Federation' => 'russ', - 'Republic of Rwanda' => 'rwan', - 'Kingdom of Saudi Arabia' => 'saar', - 'Republic of San Marino' => 'sama', - 'Nordic Sami Conference' => 'sami', - 'Sark' => 'sark', - 'Scotland' => 'scot', - 'Principality of Seborga' => 'sebo', - 'Republic of Sierra Leone' => 'sile', - 'Republic of Singapore' => 'sing', - 'Republic of Korea' => 'skor', - 'Republic of Slovenia' => 'slva', - 'Somali Republic' => 'smla', - 'Republic of Somaliland' => 'smld', - 'Republic of South Africa' => 'soaf', - 'Solomon Islands' => 'sois', - 'Kingdom of Spain' => 'span', - 'Secretariat of the Pacific Community' => 'spco', - 'Democratic Socialist Republic of Sri Lanka' => 'srla', - 'Saint Lucia' => 'stlu', - 'Republic of the Sudan' => 'suda', - 'Republic of Suriname' => 'surn', - 'Slovak Republic' => 'svka', - 'Kingdom of Sweden' => 'swdn', - 'Swiss Confederation' => 'swit', - 'Syrian Arab Republic' => 'syra', - 'Kingdom of Swaziland' => 'szld', - 'Republic of China' => 'taiw', - 'Taiwan' => 'taiw', - 'Republic of Tajikistan' => 'tajk', - 'United Republic of Tanzania' => 'tanz', - 'Kingdom of Thailand' => 'thal', - 'Autonomous Region of Tibet' => 'tibe', - 'Turkmenistan' => 'tkst', - 'Togolese Republic' => 'togo', - 'Tokelau' => 'toke', - 'Kingdom of Tonga' => 'tong', - 'Tristan da Cunha' => 'trdc', - 'Tromelin' => 'tris', - 'Republic of Tunisia' => 'tuns', - 'Republic of Turkey' => 'turk', - 'Tuvalu' => 'tuva', - 'United Arab Emirates' => 'uaem', - 'Republic of Uganda' => 'ugan', - 'Ukraine' => 'ukrn', - 'United Kingdom of Great Britain' => 'unkg', - 'United Nations' => 'unna', - 'United States of America' => 'unst', - 'Oriental Republic of Uruguay' => 'urgy', - 'Virgin Islands of the United States' => 'usvs', - 'Republic of Uzbekistan' => 'uzbk', - 'State of the Vatican City' => 'vacy', - 'Republic of Vanuatu' => 'vant', - 'Bolivarian Republic of Venezuela' => 'venz', - 'Republic of Yemen' => 'yemn', - 'Democratic Republic of Congo' => 'zare', - 'Republic of Zimbabwe' => 'zbwe' ) ; - - - var $iFlagCount = -1; - var $iFlagSetMap = array( - FLAGSIZE1 => 'flags_thumb35x35', - FLAGSIZE2 => 'flags_thumb60x60', - FLAGSIZE3 => 'flags_thumb100x100', - FLAGSIZE4 => 'flags' - ); - - var $iFlagData ; - var $iOrdIdx=array(); - - function FlagImages($aSize=FLAGSIZE1) { - switch($aSize) { - case FLAGSIZE1 : - case FLAGSIZE2 : - case FLAGSIZE3 : - case FLAGSIZE4 : - $file = dirname(__FILE__).'/'.$this->iFlagSetMap[$aSize].'.dat'; - $fp = fopen($file,'rb'); - $rawdata = fread($fp,filesize($file)); - $this->iFlagData = unserialize($rawdata); - break; - default: - JpGraphError::RaiseL(5001,$aSize); -//('Unknown flag size. ('.$aSize.')'); - } - $this->iFlagCount = count($this->iCountryNameMap); - } - - function GetNum() { - return $this->iFlagCount; - } - - function GetImgByName($aName,&$outFullName) { - $idx = $this->GetIdxByName($aName,$outFullName); - return $this->GetImgByIdx($idx); - } - - function GetImgByIdx($aIdx) { - if( array_key_exists($aIdx,$this->iFlagData) ) { - $d = $this->iFlagData[$aIdx][1]; - return Image::CreateFromString($d); - } - else { - JpGraphError::RaiseL(5002,$aIdx); -//("Flag index \" $aIdx\" does not exist."); - } - } - - function GetIdxByOrdinal($aOrd,&$outFullName) { - $aOrd--; - $n = count($this->iOrdIdx); - if( $n == 0 ) { - reset($this->iCountryNameMap); - $this->iOrdIdx=array(); - $i=0; - while( list($key,$val) = each($this->iCountryNameMap) ) { - $this->iOrdIdx[$i++] = array($val,$key); - } - $tmp=$this->iOrdIdx[$aOrd]; - $outFullName = $tmp[1]; - return $tmp[0]; - - } - elseif( $aOrd >= 0 && $aOrd < $n ) { - $tmp=$this->iOrdIdx[$aOrd]; - $outFullName = $tmp[1]; - return $tmp[0]; - } - else { - JpGraphError::RaiseL(5003,$aOrd); -//('Invalid ordinal number specified for flag index.'); - } - } - - function GetIdxByName($aName,&$outFullName) { - - if( is_integer($aName) ) { - $idx = $this->GetIdxByOrdinal($aName,$outFullName); - return $idx; - } - - $found=false; - $aName = strtolower($aName); - $nlen = strlen($aName); - reset($this->iCountryNameMap); - // Start by trying to match exact index name - while( list($key,$val) = each($this->iCountryNameMap) ) { - if( $nlen == strlen($val) && $val == $aName ) { - $found=true; - break; - } - } - if( !$found ) { - reset($this->iCountryNameMap); - // If the exact index doesn't work try a (partial) full name - while( list($key,$val) = each($this->iCountryNameMap) ) { - if( strpos(strtolower($key), $aName) !== false ) { - $found=true; - break; - } - } - } - if( $found ) { - $outFullName = $key; - return $val; - } - else { - JpGraphError::RaiseL(5004,$aName); -//("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\"."); - } - } -} - - - - -?> \ No newline at end of file + 'afgh', + 'Republic of Angola' => 'agla', + 'Republic of Albania' => 'alba', + 'Alderney' => 'alde', + 'Democratic and Popular Republic of Algeria' => 'alge', + 'Territory of American Samoa' => 'amsa', + 'Principality of Andorra' => 'andr', + 'British Overseas Territory of Anguilla' => 'angu', + 'Antarctica' => 'anta', + 'Argentine Republic' => 'arge', + 'League of Arab States' => 'arle', + 'Republic of Armenia' => 'arme', + 'Aruba' => 'arub', + 'Commonwealth of Australia' => 'astl', + 'Republic of Austria' => 'aust', + 'Azerbaijani Republic' => 'azer', + 'Bangladesh' => 'bngl', + 'British Antarctic Territory' => 'bant', + 'Kingdom of Belgium' => 'belg', + 'British Overseas Territory of Bermuda' => 'berm', + 'Commonwealth of the Bahamas' => 'bhms', + 'Kingdom of Bahrain' => 'bhrn', + 'Republic of Belarus' => 'blru', + 'Republic of Bolivia' => 'blva', + 'Belize' => 'blze', + 'Republic of Benin' => 'bnin', + 'Republic of Botswana' => 'bots', + 'Federative Republic of Brazil' => 'braz', + 'Barbados' => 'brbd', + 'British Indian Ocean Territory' => 'brin', + 'Brunei Darussalam' => 'brun', + 'Republic of Burkina' => 'bufa', + 'Republic of Bulgaria' => 'bulg', + 'Republic of Burundi' => 'buru', + 'Overseas Territory of the British Virgin Islands' => 'bvis', + 'Central African Republic' => 'cafr', + 'Kingdom of Cambodia' => 'camb', + 'Republic of Cameroon' => 'came', + 'Dominion of Canada' => 'cana', + 'Caribbean Community' => 'cari', + 'Republic of Cape Verde' => 'cave', + 'Republic of Chad' => 'chad', + 'Republic of Chile' => 'chil', + 'Peoples Republic of China' => 'chin', + 'Territory of Christmas Island' => 'chms', + 'Commonwealth of Independent States' => 'cins', + 'Cook Islands' => 'ckis', + 'Republic of Colombia' => 'clmb', + 'Territory of Cocos Islands' => 'cois', + 'Commonwealth' => 'comn', + 'Union of the Comoros' => 'como', + 'Republic of the Congo' => 'cong', + 'Republic of Costa Rica' => 'corc', + 'Republic of Croatia' => 'croa', + 'Republic of Cuba' => 'cuba', + 'British Overseas Territory of the Cayman Islands' => 'cyis', + 'Republic of Cyprus' => 'cypr', + 'The Czech Republic' => 'czec', + 'Kingdom of Denmark' => 'denm', + 'Republic of Djibouti' => 'djib', + 'Commonwealth of Dominica' => 'domn', + 'Dominican Republic' => 'dore', + 'Republic of Ecuador' => 'ecua', + 'Arab Republic of Egypt' => 'egyp', + 'Republic of El Salvador' => 'elsa', + 'England' => 'engl', + 'Republic of Equatorial Guinea' => 'eqgu', + 'State of Eritrea' => 'erit', + 'Republic of Estonia' => 'estn', + 'Ethiopia' => 'ethp', + 'European Union' => 'euun', + 'British Overseas Territory of the Falkland Islands' => 'fais', + 'International Federation of Vexillological Associations' => 'fiav', + 'Republic of Fiji' => 'fiji', + 'Republic of Finland' => 'finl', + 'Territory of French Polynesia' => 'fpol', + 'French Republic' => 'fran', + 'Overseas Department of French Guiana' => 'frgu', + 'Gabonese Republic' => 'gabn', + 'Republic of the Gambia' => 'gamb', + 'Republic of Georgia' => 'geor', + 'Federal Republic of Germany' => 'germ', + 'Republic of Ghana' => 'ghan', + 'Gibraltar' => 'gibr', + 'Hellenic Republic' => 'grec', + 'State of Grenada' => 'gren', + 'Overseas Department of Guadeloupe' => 'guad', + 'Territory of Guam' => 'guam', + 'Republic of Guatemala' => 'guat', + 'The Bailiwick of Guernsey' => 'guer', + 'Republic of Guinea' => 'guin', + 'Republic of Haiti' => 'hait', + 'Hong Kong Special Administrative Region' => 'hokn', + 'Republic of Honduras' => 'hond', + 'Republic of Hungary' => 'hung', + 'Republic of Iceland' => 'icel', + 'International Committee of the Red Cross' => 'icrc', + 'Republic of India' => 'inda', + 'Republic of Indonesia' => 'indn', + 'Republic of Iraq' => 'iraq', + 'Republic of Ireland' => 'irel', + 'Organization of the Islamic Conference' => 'isco', + 'Isle of Man' => 'isma', + 'State of Israel' => 'isra', + 'Italian Republic' => 'ital', + 'Jamaica' => 'jama', + 'Japan' => 'japa', + 'The Bailiwick of Jersey' => 'jers', + 'Hashemite Kingdom of Jordan' => 'jord', + 'Republic of Kazakhstan' => 'kazk', + 'Republic of Kenya' => 'keny', + 'Republic of Kiribati' => 'kirb', + 'State of Kuwait' => 'kuwa', + 'Kyrgyz Republic' => 'kyrg', + 'Republic of Latvia' => 'latv', + 'Lebanese Republic' => 'leba', + 'Kingdom of Lesotho' => 'lest', + 'Republic of Liberia' => 'libe', + 'Principality of Liechtenstein' => 'liec', + 'Republic of Lithuania' => 'lith', + 'Grand Duchy of Luxembourg' => 'luxe', + 'Macao Special Administrative Region' => 'maca', + 'Republic of Macedonia' => 'mace', + 'Republic of Madagascar' => 'mada', + 'Republic of the Marshall Islands' => 'mais', + 'Republic of Mali' => 'mali', + 'Federation of Malaysia' => 'mals', + 'Republic of Malta' => 'malt', + 'Republic of Malawi' => 'malw', + 'Overseas Department of Martinique' => 'mart', + 'Islamic Republic of Mauritania' => 'maur', + 'Territorial Collectivity of Mayotte' => 'mayt', + 'United Mexican States' => 'mexc', + 'Federated States of Micronesia' => 'micr', + 'Midway Islands' => 'miis', + 'Republic of Moldova' => 'mold', + 'Principality of Monaco' => 'mona', + 'Republic of Mongolia' => 'mong', + 'British Overseas Territory of Montserrat' => 'mont', + 'Kingdom of Morocco' => 'morc', + 'Republic of Mozambique' => 'moza', + 'Republic of Mauritius' => 'mrts', + 'Union of Myanmar' => 'myan', + 'Republic of Namibia' => 'namb', + 'North Atlantic Treaty Organization' => 'nato', + 'Republic of Nauru' => 'naur', + 'Turkish Republic of Northern Cyprus' => 'ncyp', + 'Netherlands Antilles' => 'nean', + 'Kingdom of Nepal' => 'nepa', + 'Kingdom of the Netherlands' => 'neth', + 'Territory of Norfolk Island' => 'nfis', + 'Federal Republic of Nigeria' => 'ngra', + 'Republic of Nicaragua' => 'nica', + 'Republic of Niger' => 'nigr', + 'Niue' => 'niue', + 'Commonwealth of the Northern Mariana Islands' => 'nmar', + 'Province of Northern Ireland' => 'noir', + 'Nordic Council' => 'nord', + 'Kingdom of Norway' => 'norw', + 'Territory of New Caledonia and Dependencies' => 'nwca', + 'New Zealand' => 'nwze', + 'Organization of American States' => 'oast', + 'Organization of African Unity' => 'oaun', + 'International Olympic Committee' => 'olym', + 'Sultanate of Oman' => 'oman', + 'Islamic Republic of Pakistan' => 'paks', + 'Republic of Palau' => 'pala', + 'Independent State of Papua New Guinea' => 'pang', + 'Republic of Paraguay' => 'para', + 'Republic of Peru' => 'peru', + 'Republic of the Philippines' => 'phil', + 'British Overseas Territory of the Pitcairn Islands' => 'piis', + 'Republic of Poland' => 'pola', + 'Republic of Portugal' => 'port', + 'Commonwealth of Puerto Rico' => 'purc', + 'State of Qatar' => 'qata', + 'Russian Federation' => 'russ', + 'Romania' => 'rmna', + 'Republic of Rwanda' => 'rwan', + 'Kingdom of Saudi Arabia' => 'saar', + 'Republic of San Marino' => 'sama', + 'Nordic Sami Conference' => 'sami', + 'Sark' => 'sark', + 'Scotland' => 'scot', + 'Principality of Seborga' => 'sebo', + 'Republic of Serbia' => 'serb', + 'Republic of Sierra Leone' => 'sile', + 'Republic of Singapore' => 'sing', + 'Republic of Korea' => 'skor', + 'Republic of Slovenia' => 'slva', + 'Somali Republic' => 'smla', + 'Republic of Somaliland' => 'smld', + 'Republic of South Africa' => 'soaf', + 'Solomon Islands' => 'sois', + 'Kingdom of Spain' => 'span', + 'Secretariat of the Pacific Community' => 'spco', + 'Democratic Socialist Republic of Sri Lanka' => 'srla', + 'Saint Lucia' => 'stlu', + 'Republic of the Sudan' => 'suda', + 'Republic of Suriname' => 'surn', + 'Slovak Republic' => 'svka', + 'Kingdom of Sweden' => 'swdn', + 'Swiss Confederation' => 'swit', + 'Syrian Arab Republic' => 'syra', + 'Kingdom of Swaziland' => 'szld', + 'Republic of China' => 'taiw', + 'Taiwan' => 'taiw', + 'Republic of Tajikistan' => 'tajk', + 'United Republic of Tanzania' => 'tanz', + 'Kingdom of Thailand' => 'thal', + 'Autonomous Region of Tibet' => 'tibe', + 'Turkmenistan' => 'tkst', + 'Togolese Republic' => 'togo', + 'Tokelau' => 'toke', + 'Kingdom of Tonga' => 'tong', + 'Tristan da Cunha' => 'trdc', + 'Tromelin' => 'tris', + 'Republic of Tunisia' => 'tuns', + 'Republic of Turkey' => 'turk', + 'Tuvalu' => 'tuva', + 'United Arab Emirates' => 'uaem', + 'Republic of Uganda' => 'ugan', + 'Ukraine' => 'ukrn', + 'United Kingdom of Great Britain' => 'unkg', + 'United Nations' => 'unna', + 'United States of America' => 'unst', + 'Oriental Republic of Uruguay' => 'urgy', + 'Virgin Islands of the United States' => 'usvs', + 'Republic of Uzbekistan' => 'uzbk', + 'State of the Vatican City' => 'vacy', + 'Republic of Vanuatu' => 'vant', + 'Bolivarian Republic of Venezuela' => 'venz', + 'Republic of Yemen' => 'yemn', + 'Democratic Republic of Congo' => 'zare', + 'Republic of Zimbabwe' => 'zbwe' ) ; + + + private $iFlagCount = -1; + private $iFlagSetMap = array( + FLAGSIZE1 => 'flags_thumb35x35', + FLAGSIZE2 => 'flags_thumb60x60', + FLAGSIZE3 => 'flags_thumb100x100', + FLAGSIZE4 => 'flags' + ); + + private $iFlagData ; + private $iOrdIdx=array(); + + function __construct($aSize=FLAGSIZE1) { + switch($aSize) { + case FLAGSIZE1 : + case FLAGSIZE2 : + case FLAGSIZE3 : + case FLAGSIZE4 : + $file = dirname(__FILE__).'/'.$this->iFlagSetMap[$aSize].'.dat'; + $fp = fopen($file,'rb'); + $rawdata = fread($fp,filesize($file)); + $this->iFlagData = unserialize($rawdata); + break; + default: + JpGraphError::RaiseL(5001,$aSize); + //('Unknown flag size. ('.$aSize.')'); + } + $this->iFlagCount = count($this->iCountryNameMap); + } + + function GetNum() { + return $this->iFlagCount; + } + + function GetImgByName($aName,&$outFullName) { + $idx = $this->GetIdxByName($aName,$outFullName); + return $this->GetImgByIdx($idx); + } + + function GetImgByIdx($aIdx) { + if( array_key_exists($aIdx,$this->iFlagData) ) { + $d = $this->iFlagData[$aIdx][1]; + return Image::CreateFromString($d); + } + else { + JpGraphError::RaiseL(5002,$aIdx); + //("Flag index \"�$aIdx\" does not exist."); + } + } + + function GetIdxByOrdinal($aOrd,&$outFullName) { + $aOrd--; + $n = count($this->iOrdIdx); + if( $n == 0 ) { + $this->iOrdIdx=array(); + $i=0; + foreach( $this->iCountryNameMap as $key => $val ) { + $this->iOrdIdx[$i++] = array($val,$key); + } + $tmp=$this->iOrdIdx[$aOrd]; + $outFullName = $tmp[1]; + return $tmp[0]; + + } + elseif( $aOrd >= 0 && $aOrd < $n ) { + $tmp=$this->iOrdIdx[$aOrd]; + $outFullName = $tmp[1]; + return $tmp[0]; + } + else { + JpGraphError::RaiseL(5003,$aOrd); + //('Invalid ordinal number specified for flag index.'); + } + } + + function GetIdxByName($aName,&$outFullName) { + + if( is_integer($aName) ) { + $idx = $this->GetIdxByOrdinal($aName,$outFullName); + return $idx; + } + + $found=false; + $aName = strtolower($aName); + $nlen = strlen($aName); + // Start by trying to match exact index name + foreach( $this->iCountryNameMap as $key => $val ) { + if( $nlen == strlen($val) && $val == $aName ) { + $found=true; + break; + } + } + if( !$found ) { + // If the exact index doesn't work try a (partial) full name + foreach( $this->iCountryNameMap as $key => $val ) { + if( strpos(strtolower($key), $aName) !== false ) { + $found=true; + break; + } + } + } + if( $found ) { + $outFullName = $key; + return $val; + } + else { + JpGraphError::RaiseL(5004,$aName); + //("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\"."); + } + } +} + + + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_gantt.php b/web/public_php/admin/jpgraph/jpgraph_gantt.php index b45cbe26a..d5afa6548 100644 --- a/web/public_php/admin/jpgraph/jpgraph_gantt.php +++ b/web/public_php/admin/jpgraph/jpgraph_gantt.php @@ -1,3776 +1,3955 @@ -vgrid = new LineProperty(); - } - - function Hide($aF=true) { - $this->iShow=!$aF; - } - - function Show($aF=true) { - $this->iShow=$aF; - } - - // Specify font - function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { - $this->iFFamily = $aFFamily; - $this->iFStyle = $aFStyle; - $this->iFSize = $aFSize; - } - - function SetStyle($aStyle) { - $this->iStyle = $aStyle; - } - - function SetColumnMargin($aLeft,$aRight) { - $this->iLeftColMargin = $aLeft; - $this->iRightColMargin = $aRight; - } - - function SetFontColor($aFontColor) { - $this->iFontColor = $aFontColor; - } - - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function SetBackgroundColor($aColor) { - $this->iBackgroundColor = $aColor; - } - - function SetColTitles($aTitles,$aWidth=null) { - $this->iTitles = $aTitles; - $this->iWidth = $aWidth; - } - - function SetMinColWidth($aWidths) { - $n = min(count($this->iTitles),count($aWidths)); - for($i=0; $i < $n; ++$i ) { - if( !empty($aWidths[$i]) ) { - if( empty($this->iWidth[$i]) ) { - $this->iWidth[$i] = $aWidths[$i]; - } - else { - $this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]); - } - } - } - } - - function GetWidth(&$aImg) { - $txt = new TextProperty(); - $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - $n = count($this->iTitles) ; - $rm=$this->iRightColMargin; - $w = 0; - for($h=0, $i=0; $i < $n; ++$i ) { - $w += $this->iLeftColMargin; - $txt->Set($this->iTitles[$i]); - if( !empty($this->iWidth[$i]) ) { - $w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]); - } - else { - $w1 = $txt->GetWidth($aImg)+$rm; - } - $this->iWidth[$i] = $w1; - $w += $w1; - $h = max($h,$txt->GetHeight($aImg)); - } - $this->iHeight = $h+$this->iTopHeaderMargin; - $txt=''; - return $w; - } - - function GetColStart(&$aImg,&$ioStart,$aAddLeftMargin=false) { - $n = count($this->iTitles) ; - $adj = $aAddLeftMargin ? $this->iLeftColMargin : 0; - $ioStart=array($aImg->left_margin+$adj); - for( $i=1; $i < $n; ++$i ) { - $ioStart[$i] = $ioStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1]; - } - } - - // Adjust headers left, right or centered - function SetHeaderAlign($aAlign) { - $this->iHeaderAlign=$aAlign; - } - - function Stroke(&$aImg,$aXLeft,$aYTop,$aXRight,$aYBottom,$aUseTextHeight=false) { - - if( !$this->iShow ) return; - - $txt = new TextProperty(); - $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - $txt->SetColor($this->iFontColor); - $txt->SetAlign($this->iHeaderAlign,'top'); - $n=count($this->iTitles); - - if( $n == 0 ) - return; - - $x = $aXLeft; - $h = $this->iHeight; - $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ; - - if( $h < 0 ) { - JpGraphError::RaiseL(6001); -//('Internal error. Height for ActivityTitles is < 0'); - } - - $aImg->SetLineWeight(1); - // Set background color - $aImg->SetColor($this->iBackgroundColor); - $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1); - - if( $this->iStyle == 1 ) { - // Make a 3D effect - $aImg->SetColor('white'); - $aImg->Line($aXLeft,$yTop+1, - $aXRight,$yTop+1); - } - - for($i=0; $i < $n; ++$i ) { - if( $this->iStyle == 1 ) { - // Make a 3D effect - $aImg->SetColor('white'); - $aImg->Line($x+1,$yTop,$x+1,$aYBottom); - } - $x += $this->iLeftColMargin; - $txt->Set($this->iTitles[$i]); - - // Adjust the text anchor position according to the choosen alignment - $xp = $x; - if( $this->iHeaderAlign == 'center' ) { - $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2; - } - elseif( $this->iHeaderAlign == 'right' ) { - $xp = $x +$this->iWidth[$i]-$this->iRightColMargin; - } - - $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin); - $x += $this->iWidth[$i]; - if( $i < $n-1 ) { - $aImg->SetColor($this->iColor); - $aImg->Line($x,$yTop,$x,$aYBottom); - } - } - - $aImg->SetColor($this->iColor); - $aImg->Line($aXLeft,$yTop, $aXRight,$yTop); - - // Stroke vertical column dividers - $cols=array(); - $this->GetColStart($aImg,$cols); - $n=count($cols); - for( $i=1; $i < $n; ++$i ) { - $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i], - $aImg->height - $aImg->bottom_margin); - } - } -} - - -//=================================================== -// CLASS GanttGraph -// Description: Main class to handle gantt graphs -//=================================================== -class GanttGraph extends Graph { - var $scale; // Public accessible - var $iObj=array(); // Gantt objects - var $iLabelHMarginFactor=0.2; // 10% margin on each side of the labels - var $iLabelVMarginFactor=0.4; // 40% margin on top and bottom of label - var $iLayout=GANTT_FROMTOP; // Could also be GANTT_EVEN - var $iSimpleFont = FF_FONT1,$iSimpleFontSize=11; - var $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red'; - var $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen'; - var $iSimpleProgressStyle=GANTT_SOLID; - var $hgrid=null; -//--------------- -// CONSTRUCTOR - // Create a new gantt graph - function GanttGraph($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) { - - // Backward compatibility - if( $aWidth == -1 ) $aWidth=0; - if( $aHeight == -1 ) $aHeight=0; - - if( $aWidth< 0 || $aHeight < 0 ) { - JpgraphError::RaiseL(6002); -//("You can't specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension."); - } - Graph::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline); - $this->scale = new GanttScale($this->img); - - // Default margins - $this->img->SetMargin(15,17,25,15); - - $this->hgrid = new HorizontalGridLine(); - - $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY); - $this->SetBox(); - } - -//--------------- -// PUBLIC METHODS - - // - - function SetSimpleFont($aFont,$aSize) { - $this->iSimpleFont = $aFont; - $this->iSimpleFontSize = $aSize; - } - - function SetSimpleStyle($aBand,$aColor,$aBkgColor) { - $this->iSimpleStyle = $aBand; - $this->iSimpleColor = $aColor; - $this->iSimpleBkgColor = $aBkgColor; - } - - // A utility function to help create basic Gantt charts - function CreateSimple($data,$constrains=array(),$progress=array()) { - $num = count($data); - for( $i=0; $i < $num; ++$i) { - switch( $data[$i][1] ) { - case ACTYPE_GROUP: - // Create a slightly smaller height bar since the - // "wings" at the end will make it look taller - $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',8); - $a->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize); - $a->rightMark->Show(); - $a->rightMark->SetType(MARK_RIGHTTRIANGLE); - $a->rightMark->SetWidth(8); - $a->rightMark->SetColor('black'); - $a->rightMark->SetFillColor('black'); - - $a->leftMark->Show(); - $a->leftMark->SetType(MARK_LEFTTRIANGLE); - $a->leftMark->SetWidth(8); - $a->leftMark->SetColor('black'); - $a->leftMark->SetFillColor('black'); - - $a->SetPattern(BAND_SOLID,'black'); - $csimpos = 6; - break; - - case ACTYPE_NORMAL: - $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10); - $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); - $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor); - $a->SetFillColor($this->iSimpleBkgColor); - // Check if this activity should have a constrain line - $n = count($constrains); - for( $j=0; $j < $n; ++$j ) { - if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) { - JpGraphError::RaiseL(6003,$j); -//("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)"); - } - if( $constrains[$j][0]==$data[$i][0] ) { - $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID); - } - } - - // Check if this activity have a progress bar - $n = count($progress); - for( $j=0; $j < $n; ++$j ) { - - if( empty($progress[$j]) || (count($progress[$j]) != 2) ) { - JpGraphError::RaiseL(6004,$j); -//("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)"); - } - if( $progress[$j][0]==$data[$i][0] ) { - $a->progress->Set($progress[$j][1]); - $a->progress->SetHeight(0.5); - $a->progress->SetPattern($this->iSimpleProgressStyle, - $this->iSimpleProgressColor); - $a->progress->SetFillColor($this->iSimpleProgressBkgColor); - //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]); - break; - } - } - $csimpos = 6; - break; - - case ACTYPE_MILESTONE: - $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]); - $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); - $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); - $csimpos = 5; - break; - default: - die('Unknown activity type'); - break; - } - - // Setup caption - $a->caption->Set($data[$i][$csimpos-1]); - - // Check if this activity should have a CSIM target ? - if( !empty($data[$i][$csimpos]) ) { - $a->SetCSIMTarget($data[$i][$csimpos]); - $a->SetCSIMAlt($data[$i][$csimpos+1]); - } - if( !empty($data[$i][$csimpos+2]) ) { - $a->title->SetCSIMTarget($data[$i][$csimpos+2]); - $a->title->SetCSIMAlt($data[$i][$csimpos+3]); - } - - $this->Add($a); - } - } - - - // Set what headers should be shown - function ShowHeaders($aFlg) { - $this->scale->ShowHeaders($aFlg); - } - - // Specify the fraction of the font height that should be added - // as vertical margin - function SetLabelVMarginFactor($aVal) { - $this->iLabelVMarginFactor = $aVal; - } - - // Synonym to the method above - function SetVMarginFactor($aVal) { - $this->iLabelVMarginFactor = $aVal; - } - - - // Add a new Gantt object - function Add($aObject) { - if( is_array($aObject) && count($aObject) > 0 ) { - $cl = $aObject[0]; - if( is_a($cl,'IconPlot') ) { - $this->AddIcon($aObject); - } - else { - $n = count($aObject); - for($i=0; $i < $n; ++$i) - $this->iObj[] = $aObject[$i]; - } - } - else { - if( is_a($aObject,'IconPlot') ) { - $this->AddIcon($aObject); - } - else { - $this->iObj[] = $aObject; - } - } - } - - // Override inherit method from Graph and give a warning message - function SetScale() { - JpGraphError::RaiseL(6005); -//("SetScale() is not meaningfull with Gantt charts."); - } - - // Specify the date range for Gantt graphs (if this is not set it will be - // automtically determined from the input data) - function SetDateRange($aStart,$aEnd) { - // Adjust the start and end so that the indicate the - // beginning and end of respective start and end days - if( strpos($aStart,':') === false ) - $aStart = date('Y-m-d 00:00',strtotime($aStart)); - if( strpos($aEnd,':') === false ) - $aEnd = date('Y-m-d 23:59',strtotime($aEnd)); - $this->scale->SetRange($aStart,$aEnd); - } - - // Get the maximum width of the activity titles columns for the bars - // The name is lightly misleading since we from now on can have - // multiple columns in the label section. When this was first written - // it only supported a single label, hence the name. - function GetMaxLabelWidth() { - $m=50; - if( $this->iObj != null ) { - $marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin; - $m = $this->iObj[0]->title->GetWidth($this->img)+$marg; - $n = count($this->iObj); - for($i=1; $i < $n; ++$i) { - if( !empty($this->iObj[$i]->title) ) { - if( $this->iObj[$i]->title->HasTabs() ) { - list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true); - $m=max($m,$tot); - } - else - $m=max($m,$this->iObj[$i]->title->GetWidth($this->img)); - } - } - } - return $m; - } - - // Get the maximum height of the titles for the bars - function GetMaxLabelHeight() { - $m=0; - if( $this->iObj != null ) { - $m = $this->iObj[0]->title->GetHeight($this->img); - $n = count($this->iObj); - for($i=1; $i < $n; ++$i) { - if( !empty($this->iObj[$i]->title) ) { - $m=max($m,$this->iObj[$i]->title->GetHeight($this->img)); - } - } - } - return $m; - } - - function GetMaxBarAbsHeight() { - $m=0; - if( $this->iObj != null ) { - $m = $this->iObj[0]->GetAbsHeight($this->img); - $n = count($this->iObj); - for($i=1; $i < $n; ++$i) { - $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img)); - } - } - return $m; - } - - // Get the maximum used line number (vertical position) for bars - function GetBarMaxLineNumber() { - $m=0; - if( $this->iObj != null ) { - $m = $this->iObj[0]->GetLineNbr(); - $n = count($this->iObj); - for($i=1; $i < $n; ++$i) { - $m=max($m,$this->iObj[$i]->GetLineNbr()); - } - } - return $m; - } - - // Get the minumum and maximum used dates for all bars - function GetBarMinMax() { - $start = 0 ; - $n = count($this->iObj); - - while( $start < $n && $this->iObj[$start]->GetMaxDate() === false ) - ++$start; - if( $start >= $n ) { - JpgraphError::RaiseL(6006); -//('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]'); - } - - $max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate()); - $min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate()); - - for($i=$start+1; $i < $n; ++$i) { - $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate()); - if( $rmax != false ) - $max=Max($max,$rmax); - $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate()); - if( $rmin != false ) - $min=Min($min,$rmin); - } - $minDate = date("Y-m-d",$min); - $min = strtotime($minDate); - $maxDate = date("Y-m-d 23:59",$max); - $max = strtotime($maxDate); - return array($min,$max); - } - - // Create a new auto sized canvas if the user hasn't specified a size - // The size is determined by what scale the user has choosen and hence - // the minimum width needed to display the headers. Some margins are - // also added to make it better looking. - function AutoSize() { - if( $this->img->img == null ) { - // The predefined left, right, top, bottom margins. - // Note that the top margin might incease depending on - // the title. - $lm = $this->img->left_margin; - $rm = $this->img->right_margin; - $rm += 2 ; - $tm = $this->img->top_margin; - $bm = $this->img->bottom_margin; - $bm += 1; - if( BRAND_TIMING ) $bm += 10; - - // First find out the height - $n=$this->GetBarMaxLineNumber()+1; - $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); - $height=$n*((1+$this->iLabelVMarginFactor)*$m); - - // Add the height of the scale titles - $h=$this->scale->GetHeaderHeight(); - $height += $h; - - // Calculate the top margin needed for title and subtitle - if( $this->title->t != "" ) { - $tm += $this->title->GetFontHeight($this->img); - } - if( $this->subtitle->t != "" ) { - $tm += $this->subtitle->GetFontHeight($this->img); - } - - // ...and then take the bottom and top plot margins into account - $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin; - // Now find the minimum width for the chart required - - // If day scale or smaller is shown then we use the day font width - // as the base size unit. - // If only weeks or above is displayed we use a modified unit to - // get a smaller image. - if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) { - // Add 2 pixel margin on each side - $fw=$this->scale->day->GetFontWidth($this->img)+4; - } - elseif( $this->scale->IsDisplayWeek() ) { - $fw = 8; - } - elseif( $this->scale->IsDisplayMonth() ) { - $fw = 4; - } - else { - $fw = 2; - } - - $nd=$this->scale->GetNumberOfDays(); - - if( $this->scale->IsDisplayDay() ) { - // If the days are displayed we also need to figure out - // how much space each day's title will require. - switch( $this->scale->day->iStyle ) { - case DAYSTYLE_LONG : - $txt = "Monday"; - break; - case DAYSTYLE_LONGDAYDATE1 : - $txt = "Monday 23 Jun"; - break; - case DAYSTYLE_LONGDAYDATE2 : - $txt = "Monday 23 Jun 2003"; - break; - case DAYSTYLE_SHORT : - $txt = "Mon"; - break; - case DAYSTYLE_SHORTDAYDATE1 : - $txt = "Mon 23/6"; - break; - case DAYSTYLE_SHORTDAYDATE2 : - $txt = "Mon 23 Jun"; - break; - case DAYSTYLE_SHORTDAYDATE3 : - $txt = "Mon 23"; - break; - case DAYSTYLE_SHORTDATE1 : - $txt = "23/6"; - break; - case DAYSTYLE_SHORTDATE2 : - $txt = "23 Jun"; - break; - case DAYSTYLE_SHORTDATE3 : - $txt = "Mon 23"; - break; - case DAYSTYLE_SHORTDATE4 : - $txt = "88"; - break; - case DAYSTYLE_CUSTOM : - $txt = date($this->scale->day->iLabelFormStr, - strtotime('2003-12-20 18:00')); - break; - case DAYSTYLE_ONELETTER : - default: - $txt = "M"; - break; - } - $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6; - } - - // If we have hours enabled we must make sure that each day has enough - // space to fit the number of hours to be displayed. - if( $this->scale->IsDisplayHour() ) { - // Depending on what format the user has choose we need different amount - // of space. We therefore create a typical string for the choosen format - // and determine the length of that string. - switch( $this->scale->hour->iStyle ) { - case HOURSTYLE_HMAMPM: - $txt = '12:00pm'; - break; - case HOURSTYLE_H24: - // 13 - $txt = '24'; - break; - case HOURSTYLE_HAMPM: - $txt = '12pm'; - break; - case HOURSTYLE_CUSTOM: - $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00')); - break; - case HOURSTYLE_HM24: - default: - $txt = '24:00'; - break; - } - - $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6; - $mw = $hfw; - if( $this->scale->IsDisplayMinute() ) { - // Depending on what format the user has choose we need different amount - // of space. We therefore create a typical string for the choosen format - // and determine the length of that string. - switch( $this->scale->minute->iStyle ) { - case HOURSTYLE_CUSTOM: - $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); - break; - case MINUTESTYLE_MM: - default: - $txt2 = '15'; - break; - } - - $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6; - $n2 = ceil(60 / $this->scale->minute->GetIntervall() ); - $mw = $n2 * $mfw; - } - $hfw = $hfw < $mw ? $mw : $hfw ; - $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) ); - $hw = $n * $hfw; - $fw = $fw < $hw ? $hw : $fw ; - } - - // We need to repeat this code block here as well. - // THIS iS NOT A MISTAKE ! - // We really need it since we need to adjust for minutes both in the case - // where hour scale is shown and when it is not shown. - - if( $this->scale->IsDisplayMinute() ) { - // Depending on what format the user has choose we need different amount - // of space. We therefore create a typical string for the choosen format - // and determine the length of that string. - switch( $this->scale->minute->iStyle ) { - case HOURSTYLE_CUSTOM: - $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); - break; - case MINUTESTYLE_MM: - default: - $txt = '15'; - break; - } - - $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6; - $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) ); - $mw = $n * $mfw; - $fw = $fw < $mw ? $mw : $fw ; - } - - // If we display week we must make sure that 7*$fw is enough - // to fit up to 10 characters of the week font (if the week is enabled) - if( $this->scale->IsDisplayWeek() ) { - // Depending on what format the user has choose we need different amount - // of space - $fsw = strlen($this->scale->week->iLabelFormStr); - if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { - $fsw += 8; - } - elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) { - $fsw += 7; - } - else { - $fsw += 4; - } - - $ww = $fsw*$this->scale->week->GetFontWidth($this->img); - if( 7*$fw < $ww ) { - $fw = ceil($ww/7); - } - } - - if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() && - !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || - $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) { - // If we don't display the individual days we can shrink the - // scale a little bit. This is a little bit pragmatic at the - // moment and should be re-written to take into account - // a) What scales exactly are shown and - // b) what format do they use so we know how wide we need to - // make each scale text space at minimum. - $fw /= 2; - if( !$this->scale->IsDisplayWeek() ) { - $fw /= 1.8; - } - } - - // Has the user specified a width or do we need to - // determine it? - if( $this->img->width <= 0 ) { - // Now determine the width for the activity titles column - - // Firdst find out the maximum width of each object column - $cw = $this->GetMaxActInfoColWidth() ; - $this->scale->actinfo->SetMinColWidth($cw); - $titlewidth = max(max($this->GetMaxLabelWidth(), - $this->scale->tableTitle->GetWidth($this->img)), - $this->scale->actinfo->GetWidth($this->img)); - - // Add the width of the vertivcal divider line - $titlewidth += $this->scale->divider->iWeight*2; - - - // Now get the total width taking - // titlewidth, left and rigt margin, dayfont size - // into account - $width = $titlewidth + $nd*$fw + $lm+$rm; - } - else - $width = $this->img->width; - - $width = round($width); - $height = round($height); - if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) { - JpgraphError::RaiseL(6007,$width,$height); -//("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."); - } - - $this->img->CreateImgCanvas($width,$height); - $this->img->SetMargin($lm,$rm,$tm,$bm); - } - } - - // Return an array width the maximum width for each activity - // column. This is used when we autosize the columns where we need - // to find out the maximum width of each column. In order to do that we - // must walk through all the objects, sigh... - function GetMaxActInfoColWidth() { - $n = count($this->iObj); - if( $n == 0 ) return; - $w = array(); - $m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin; - - for( $i=0; $i < $n; ++$i ) { - $tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m); - $nn = count($tmp); - for( $j=0; $j < $nn; ++$j ) { - if( empty($w[$j]) ) - $w[$j] = $tmp[$j]; - else - $w[$j] = max($w[$j],$tmp[$j]); - } - } - return $w; - } - - // Stroke the gantt chart - function Stroke($aStrokeFileName="") { - - - // If the filename is the predefined value = '_csim_special_' - // we assume that the call to stroke only needs to do enough - // to correctly generate the CSIM maps. - // We use this variable to skip things we don't strictly need - // to do to generate the image map to improve performance - // a best we can. Therefor you will see a lot of tests !$_csim in the - // code below. - $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); - - // Should we autoscale dates? - if( !$this->scale->IsRangeSet() ) { - list($min,$max) = $this->GetBarMinMax(); - $this->scale->SetRange($min,$max); - } - - $this->scale->AdjustStartEndDay(); - - // Check if we should autoscale the image - $this->AutoSize(); - - // Should we start from the top or just spread the bars out even over the - // available height - $this->scale->SetVertLayout($this->iLayout); - if( $this->iLayout == GANTT_FROMTOP ) { - $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); - $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor)); - } - // If it hasn't been set find out the maximum line number - if( $this->scale->iVertLines == -1 ) - $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1; - - $maxwidth=max($this->scale->actinfo->GetWidth($this->img), - max($this->GetMaxLabelWidth(), - $this->scale->tableTitle->GetWidth($this->img))); - - $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor)); - - if( !$_csim ) { - $this->StrokePlotArea(); - if( $this->iIconDepth == DEPTH_BACK ) { - $this->StrokeIcons(); - } - } - - $this->scale->Stroke(); - - if( !$_csim ) { - // Due to a minor off by 1 bug we need to temporarily adjust the margin - $this->img->right_margin--; - $this->StrokePlotBox(); - $this->img->right_margin++; - } - - // Stroke Grid line - $this->hgrid->Stroke($this->img,$this->scale); - - $n = count($this->iObj); - for($i=0; $i < $n; ++$i) { - //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2)); - $this->iObj[$i]->Stroke($this->img,$this->scale); - } - - $this->StrokeTitles(); - - if( !$_csim ) { - $this->StrokeConstrains(); - $this->footer->Stroke($this->img); - - if( $this->iIconDepth == DEPTH_FRONT) { - $this->StrokeIcons(); - } - - // Should we do any final image transformation - if( $this->iImgTrans ) { - if( !class_exists('ImgTrans') ) { - require_once('jpgraph_imgtrans.php'); - } - - $tform = new ImgTrans($this->img->img); - $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, - $this->iImgTransDirection,$this->iImgTransHighQ, - $this->iImgTransMinSize,$this->iImgTransFillColor, - $this->iImgTransBorder); - } - - - // If the filename is given as the special "__handle" - // then the image handler is returned and the image is NOT - // streamed back - if( $aStrokeFileName == _IMG_HANDLER ) { - return $this->img->img; - } - else { - // Finally stream the generated picture - $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, - $aStrokeFileName); - } - } - } - - function StrokeConstrains() { - $n = count($this->iObj); - - // Stroke all constrains - for($i=0; $i < $n; ++$i) { - - // Some gantt objects may not have constraints associated with them - // for example we can add IconPlots which doesn't have this property. - if( empty($this->iObj[$i]->constraints) ) continue; - - $numConstrains = count($this->iObj[$i]->constraints); - - for( $k = 0; $k < $numConstrains; $k++ ) { - $vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow; - if( $vpos >= 0 ) { - $c1 = $this->iObj[$i]->iConstrainPos; - - // Find out which object is on the target row - $targetobj = -1; - for( $j=0; $j < $n && $targetobj == -1; ++$j ) { - if( $this->iObj[$j]->iVPos == $vpos ) { - $targetobj = $j; - } - } - if( $targetobj == -1 ) { - JpGraphError::RaiseL(6008,$this->iObj[$i]->iVPos,$vpos); -//('You have specifed a constrain from row='.$this->iObj[$i]->iVPos.' to row='.$vpos.' which does not have any activity.'); - } - $c2 = $this->iObj[$targetobj]->iConstrainPos; - if( count($c1) == 4 && count($c2 ) == 4) { - switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) { - case CONSTRAIN_ENDSTART: - if( $c1[1] < $c2[1] ) { - $link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]); - } - else { - $link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]); - } - $link->SetPath(3); - break; - case CONSTRAIN_STARTEND: - if( $c1[1] < $c2[1] ) { - $link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]); - } - else { - $link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]); - } - $link->SetPath(0); - break; - case CONSTRAIN_ENDEND: - if( $c1[1] < $c2[1] ) { - $link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]); - } - else { - $link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]); - } - $link->SetPath(1); - break; - case CONSTRAIN_STARTSTART: - if( $c1[1] < $c2[1] ) { - $link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]); - } - else { - $link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]); - } - $link->SetPath(3); - break; - default: - JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos); -//('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos); - break; - } - - $link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor); - $link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize, - $this->iObj[$i]->constraints[$k]->iConstrainArrowType); - - $link->Stroke($this->img); - } - } - } - } - } - - function GetCSIMAreas() { - if( !$this->iHasStroked ) - $this->Stroke(_CSIM_SPECIALFILE); - - $csim = $this->title->GetCSIMAreas(); - $csim .= $this->subtitle->GetCSIMAreas(); - $csim .= $this->subsubtitle->GetCSIMAreas(); - - $n = count($this->iObj); - for( $i=$n-1; $i >= 0; --$i ) - $csim .= $this->iObj[$i]->GetCSIMArea(); - return $csim; - } -} - -//=================================================== -// CLASS PredefIcons -// Description: Predefined icons for use with Gantt charts -//=================================================== -DEFINE('GICON_WARNINGRED',0); -DEFINE('GICON_TEXT',1); -DEFINE('GICON_ENDCONS',2); -DEFINE('GICON_MAIL',3); -DEFINE('GICON_STARTCONS',4); -DEFINE('GICON_CALC',5); -DEFINE('GICON_MAGNIFIER',6); -DEFINE('GICON_LOCK',7); -DEFINE('GICON_STOP',8); -DEFINE('GICON_WARNINGYELLOW',9); -DEFINE('GICON_FOLDEROPEN',10); -DEFINE('GICON_FOLDER',11); -DEFINE('GICON_TEXTIMPORTANT',12); - -class PredefIcons { - var $iBuiltinIcon = null; - var $iLen = -1 ; - - function GetLen() { - return $this->iLen ; - } - - function GetImg($aIdx) { - if( $aIdx < 0 || $aIdx >= $this->iLen ) { - JpGraphError::RaiseL(6010,$aIdx); -//('Illegal icon index for Gantt builtin icon ['.$aIdx.']'); - } - return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1])); - } - - function PredefIcons() { - //========================================================== - // warning.png - //========================================================== - $this->iBuiltinIcon[0][0]= 1043 ; - $this->iBuiltinIcon[0][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. - 'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'. - '0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'. - '5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'. - 'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'. - 'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'. - '/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'. - 'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'. - 'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'. - 'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'. - 'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'. - 'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'. - 'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'. - 'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ; - - //========================================================== - // edit.png - //========================================================== - $this->iBuiltinIcon[1][0]= 959 ; - $this->iBuiltinIcon[1][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'. - 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'. - 'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'. - 'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'. - 'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'. - 'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'. - 'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'. - 'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'. - 'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'. - 'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'. - 'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'. - 'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'. - 'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ; - - //========================================================== - // endconstrain.png - //========================================================== - $this->iBuiltinIcon[2][0]= 666 ; - $this->iBuiltinIcon[2][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. - 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'. - 'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'. - 'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'. - 'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'. - '7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'. - '7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'. - 'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'. - 'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ; - - //========================================================== - // mail.png - //========================================================== - $this->iBuiltinIcon[3][0]= 1122 ; - $this->iBuiltinIcon[3][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. - 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'. - 'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'. - 'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'. - 'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'. - '3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'. - '7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'. - 'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'. - 'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'. - '6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'. - 'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'. - 'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'. - 'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'. - 'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'. - 'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ; - - //========================================================== - // startconstrain.png - //========================================================== - $this->iBuiltinIcon[4][0]= 725 ; - $this->iBuiltinIcon[4][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. - 'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'. - 'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'. - 'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'. - 'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'. - '5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'. - 'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'. - 'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'. - '5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'. - 'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ; - - //========================================================== - // calc.png - //========================================================== - $this->iBuiltinIcon[5][0]= 589 ; - $this->iBuiltinIcon[5][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'. - 'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'. - 'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'. - '3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'. - 'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'. - 'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'. - 'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'. - 'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ; - - //========================================================== - // mag.png - //========================================================== - $this->iBuiltinIcon[6][0]= 1415 ; - $this->iBuiltinIcon[6][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. - 'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'. - '0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'. - 'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'. - 'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'. - 'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'. - '8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'. - 'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'. - '/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'. - 'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'. - 'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'. - 'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'. - 'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'. - 'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'. - 'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'. - 'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'. - 'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'. - 'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'. - 'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ; - - //========================================================== - // lock.png - //========================================================== - $this->iBuiltinIcon[7][0]= 963 ; - $this->iBuiltinIcon[7][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. - 'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'. - 'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'. - 'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'. - 'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'. - 'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'. - 'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'. - 'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'. - 'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'. - 'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'. - 'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'. - '2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'. - 'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ; - - //========================================================== - // stop.png - //========================================================== - $this->iBuiltinIcon[8][0]= 889 ; - $this->iBuiltinIcon[8][1]= - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. - 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'. - 'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'. - 'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'. - 'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'. - 'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'. - 'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'. - 'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'. - 'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'. - 'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'. - 'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'. - 'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ; - - //========================================================== - // error.png - //========================================================== - $this->iBuiltinIcon[9][0]= 541 ; - $this->iBuiltinIcon[9][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. - 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. - 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'. - '2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'. - 'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'. - 'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'. - 'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'. - 'iOsCHgAAAABJRU5ErkJggg==' ; - - //========================================================== - // openfolder.png - //========================================================== - $this->iBuiltinIcon[10][0]= 2040 ; - $this->iBuiltinIcon[10][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'. - 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'. - 'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'. - 'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'. - 'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'. - 'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'. - '9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'. - 'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'. - '4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'. - 'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'. - 'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'. - 'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'. - 'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'. - 'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'. - 'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'. - 'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'. - 'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'. - 'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'. - 'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'. - 'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'. - 'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'. - 'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'. - 'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'. - 'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'. - '+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'. - '4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'. - 'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'. - 'dBntAAAAAElFTkSuQmCC' ; - - //========================================================== - // folder.png - //========================================================== - $this->iBuiltinIcon[11][0]= 1824 ; - $this->iBuiltinIcon[11][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. - 'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'. - '6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'. - 'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'. - '309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'. - 'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'. - 'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'. - '3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'. - 'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'. - 'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'. - '/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'. - '4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'. - 'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'. - 'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'. - 'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'. - 'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'. - 'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'. - 'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'. - 'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'. - 'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'. - 'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'. - 'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'. - 'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'. - 'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'. - 'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ; - - //========================================================== - // file_important.png - //========================================================== - $this->iBuiltinIcon[12][0]= 1785 ; - $this->iBuiltinIcon[12][1]= - 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. - 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'. - 'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'. - 'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'. - '1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'. - 's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'. - 'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'. - 'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'. - 'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'. - '73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'. - '4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'. - 'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'. - 'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'. - 'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'. - 'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'. - 't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'. - '9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'. - 'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'. - 'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'. - 'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'. - '8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'. - 'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'. - 'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'. - '7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ; - - $this->iLen = count($this->iBuiltinIcon); - } -} - -//=================================================== -// Global cache for builtin images -//=================================================== -$_gPredefIcons = new PredefIcons(); - -//=================================================== -// CLASS IconImage -// Description: Holds properties for an icon image -//=================================================== -class IconImage { - var $iGDImage=null; - var $iWidth,$iHeight; - var $ixalign='left',$iyalign='center'; - var $iScale=1.0; - - function IconImage($aIcon,$aScale=1) { - GLOBAL $_gPredefIcons ; - if( is_string($aIcon) ) { - $this->iGDImage = Graph::LoadBkgImage('',$aIcon); - } - elseif( is_integer($aIcon) ) { - // Builtin image - $this->iGDImage = $_gPredefIcons->GetImg($aIcon); - } - else { - JpGraphError::RaiseL(6011); -//('Argument to IconImage must be string or integer'); - } - $this->iScale = $aScale; - $this->iWidth = Image::GetWidth($this->iGDImage); - $this->iHeight = Image::GetHeight($this->iGDImage); - } - - function GetWidth() { - return round($this->iScale*$this->iWidth); - } - - function GetHeight() { - return round($this->iScale*$this->iHeight); - } - - function SetAlign($aX='left',$aY='center') { - - $this->ixalign = $aX; - $this->iyalign = $aY; - - } - - function Stroke(&$aImg,$x,$y) { - - if( $this->ixalign == 'right' ) { - $x -= $this->iWidth; - } - elseif( $this->ixalign == 'center' ) { - $x -= round($this->iWidth/2*$this->iScale); - } - - if( $this->iyalign == 'bottom' ) { - $y -= $this->iHeight; - } - elseif( $this->iyalign == 'center' ) { - $y -= round($this->iHeight/2*$this->iScale); - } - - $aImg->Copy($this->iGDImage, - $x,$y,0,0, - round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale), - $this->iWidth,$this->iHeight); - } -} - - -//=================================================== -// CLASS TextProperty -// Description: Holds properties for a text -//=================================================== -class TextProperty { - var $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10; - var $iColor="black"; - var $iShow=true; - var $iText=""; - var $iHAlign="left",$iVAlign="bottom"; - var $csimtarget='',$csimalt=''; - -//--------------- -// CONSTRUCTOR - function TextProperty($aTxt='') { - $this->iText = $aTxt; - } - -//--------------- -// PUBLIC METHODS - function Set($aTxt) { - $this->iText = $aTxt; - } - - function SetCSIMTarget($aTarget,$aAltText='') { - if( is_string($aTarget) ) - $aTarget = array($aTarget); - $this->csimtarget=$aTarget; - if( is_string($aAltText) ) - $aAltText = array($aAltText); - $this->csimalt=$aAltText; - } - - function SetCSIMAlt($aAltText) { - if( is_string($aAltText) ) - $aAltText = array($aAltText); - $this->csimalt=$aAltText; - } - - // Set text color - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function HasTabs() { - if( is_string($this->iText) ) { - return substr_count($this->iText,"\t") > 0; - } - elseif( is_array($this->iText) ) { - return false; - } - } - - // Get number of tabs in string - function GetNbrTabs() { - if( is_string($this->iText) ) { - return substr_count($this->iText,"\t") ; - } - else{ - return 0; - } - } - - // Set alignment - function Align($aHAlign,$aVAlign="bottom") { - $this->iHAlign=$aHAlign; - $this->iVAlign=$aVAlign; - } - - // Synonym - function SetAlign($aHAlign,$aVAlign="bottom") { - $this->iHAlign=$aHAlign; - $this->iVAlign=$aVAlign; - } - - // Specify font - function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { - $this->iFFamily = $aFFamily; - $this->iFStyle = $aFStyle; - $this->iFSize = $aFSize; - } - - function IsColumns() { - return is_array($this->iText) ; - } - - // Get width of text. If text contains several columns separated by - // tabs then return both the total width as well as an array with a - // width for each column. - function GetWidth(&$aImg,$aUseTabs=false,$aTabExtraMargin=1.1) { - $extra_margin=4; - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - if( is_string($this->iText) ) { - if( strlen($this->iText) == 0 ) return 0; - $tmp = split("\t",$this->iText); - if( count($tmp) <= 1 || !$aUseTabs ) { - return $aImg->GetTextWidth($this->iText)+2*$extra_margin; - } - else { - $tot=0; - $n = count($tmp); - for($i=0; $i < $n; ++$i) { - $res[$i] = $aImg->GetTextWidth($tmp[$i]); - $tot += $res[$i]*$aTabExtraMargin; - } - return array(round($tot),$res); - } - } - elseif( is_object($this->iText) ) { - // A single icon - return $this->iText->GetWidth()+2*$extra_margin; - } - elseif( is_array($this->iText) ) { - // Must be an array of texts. In this case we return the sum of the - // length + a fixed margin of 4 pixels on each text string - $n = count($this->iText); - for( $i=0, $w=0; $i < $n; ++$i ) { - $tmp = $this->iText[$i]; - if( is_string($tmp) ) { - $w += $aImg->GetTextWidth($tmp)+$extra_margin; - } - else { - if( is_object($tmp) === false ) { - JpGraphError::RaiseL(6012); - } - $w += $tmp->GetWidth()+$extra_margin; - } - } - return $w; - } - else { - JpGraphError::RaiseL(6012); - } - } - - // for the case where we have multiple columns this function returns the width of each - // column individually. If there is no columns just return the width of the single - // column as an array of one - function GetColWidth(&$aImg,$aMargin=0) { - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - if( is_array($this->iText) ) { - $n = count($this->iText); - for( $i=0, $w=array(); $i < $n; ++$i ) { - $tmp = $this->iText[$i]; - if( is_string($tmp) ) { - $w[$i] = $aImg->GetTextWidth($this->iText[$i])+$aMargin; - } - else { - if( is_object($tmp) === false ) { - JpGraphError::RaiseL(6012); - } - $w[$i] = $tmp->GetWidth()+$aMargin; - } - } - return $w; - } - else { - return array($this->GetWidth($aImg)); - } - } - - // Get total height of text - function GetHeight(&$aImg) { - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - return $aImg->GetFontHeight(); - } - - // Unhide/hide the text - function Show($aShow=true) { - $this->iShow=$aShow; - } - - // Stroke text at (x,y) coordinates. If the text contains tabs then the - // x parameter should be an array of positions to be used for each successive - // tab mark. If no array is supplied then the tabs will be ignored. - function Stroke(&$aImg,$aX,$aY) { - if( $this->iShow ) { - $aImg->SetColor($this->iColor); - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - $aImg->SetTextAlign($this->iHAlign,$this->iVAlign); - if( $this->GetNbrTabs() <= 1 ) { - if( is_string($this->iText) ) { - // Get rid of any "\t" characters and stroke string - if( is_array($aX) ) $aX=$aX[0]; - if( is_array($aY) ) $aY=$aY[0]; - $aImg->StrokeText($aX,$aY,str_replace("\t"," ",$this->iText)); - } - else { - $n = count($this->iText); - $ax = is_array($aX) ; - $ay = is_array($aY) ; - if( $ax && $ay ) { - // Nothing; both are already arrays - } - elseif( $ax ) { - $aY = array_fill(0,$n,$aY); - } - elseif( $ay ) { - $aX = array_fill(0,$n,$aX); - } - else { - $aX = array_fill(0,$n,$aX); - $aY = array_fill(0,$n,$aY); - } - $n = min($n, count($aX) ) ; - $n = min($n, count($aY) ) ; - for($i=0; $i < $n; ++$i ) { - $tmp = $this->iText[$i]; - if( is_object($tmp) ) { - $tmp->Stroke($aImg,$aX[$i],$aY[$i]); - } - else - $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp)); - } - } - } - else { - $tmp = split("\t",$this->iText); - $n = min(count($tmp),count($aX)); - for($i=0; $i < $n; ++$i) { - $aImg->StrokeText($aX[$i],$aY,$tmp[$i]); - } - } - } - } -} - -//=================================================== -// CLASS HeaderProperty -// Description: Data encapsulating class to hold property -// for each type of the scale headers -//=================================================== -class HeaderProperty { - var $iTitleVertMargin=3,$iFFamily=FF_FONT0,$iFStyle=FS_NORMAL,$iFSize=8; - var $iFrameColor="black",$iFrameWeight=1; - var $iShowLabels=true,$iShowGrid=true; - var $iBackgroundColor="white"; - var $iWeekendBackgroundColor="lightgray",$iSundayTextColor="red"; // these are only used with day scale - var $iTextColor="black"; - var $iLabelFormStr="%d"; - var $grid,$iStyle=0; - var $iIntervall = 1; - -//--------------- -// CONSTRUCTOR - function HeaderProperty() { - $this->grid = new LineProperty(); - } - -//--------------- -// PUBLIC METHODS - function Show($aShow=true) { - $this->iShowLabels = $aShow; - } - - function SetIntervall($aInt) { - $this->iIntervall = $aInt; - } - - function GetIntervall() { - return $this->iIntervall ; - } - - function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { - $this->iFFamily = $aFFamily; - $this->iFStyle = $aFStyle; - $this->iFSize = $aFSize; - } - - function SetFontColor($aColor) { - $this->iTextColor = $aColor; - } - - function GetFontHeight(&$aImg) { - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - return $aImg->GetFontHeight(); - } - - function GetFontWidth(&$aImg) { - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - return $aImg->GetFontWidth(); - } - - function GetStrWidth(&$aImg,$aStr) { - $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); - return $aImg->GetTextWidth($aStr); - } - - function SetStyle($aStyle) { - $this->iStyle = $aStyle; - } - - function SetBackgroundColor($aColor) { - $this->iBackgroundColor=$aColor; - } - - function SetFrameWeight($aWeight) { - $this->iFrameWeight=$aWeight; - } - - function SetFrameColor($aColor) { - $this->iFrameColor=$aColor; - } - - // Only used by day scale - function SetWeekendColor($aColor) { - $this->iWeekendBackgroundColor=$aColor; - } - - // Only used by day scale - function SetSundayFontColor($aColor) { - $this->iSundayTextColor=$aColor; - } - - function SetTitleVertMargin($aMargin) { - $this->iTitleVertMargin=$aMargin; - } - - function SetLabelFormatString($aStr) { - $this->iLabelFormStr=$aStr; - } - - function SetFormatString($aStr) { - $this->SetLabelFormatString($aStr); - } - - -} - -//=================================================== -// CLASS GanttScale -// Description: Responsible for calculating and showing -// the scale in a gantt chart. This includes providing methods for -// converting dates to position in the chart as well as stroking the -// date headers (days, week, etc). -//=================================================== -class GanttScale { - var $minute,$hour,$day,$week,$month,$year; - var $divider,$dividerh,$tableTitle; - var $iStartDate=-1,$iEndDate=-1; - // Number of gantt bar position (n.b not necessariliy the same as the number of bars) - // we could have on bar in position 1, and one bar in position 5 then there are two - // bars but the number of bar positions is 5 - var $iVertLines=-1; - // The width of the labels (defaults to the widest of all labels) - var $iLabelWidth; - // Out image to stroke the scale to - var $iImg; - var $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black"; - var $iTableHeaderFrameWeight=1; - var $iAvailableHeight=-1,$iVertSpacing=-1,$iVertHeaderSize=-1; - var $iDateLocale; - var $iVertLayout=GANTT_EVEN; - var $iTopPlotMargin=10,$iBottomPlotMargin=15; - var $iUsePlotWeekendBackground=true; - var $iWeekStart = 1; // Default to have weekends start on Monday - var $actinfo; - -//--------------- -// CONSTRUCTOR - function GanttScale(&$aImg) { - $this->iImg = &$aImg; - $this->iDateLocale = new DateLocale(); - - $this->minute = new HeaderProperty(); - $this->minute->SetIntervall(15); - $this->minute->SetLabelFormatString('i'); - $this->minute->SetFont(FF_FONT0); - $this->minute->grid->SetColor("gray"); - - $this->hour = new HeaderProperty(); - $this->hour->SetFont(FF_FONT0); - $this->hour->SetIntervall(6); - $this->hour->SetStyle(HOURSTYLE_HM24); - $this->hour->SetLabelFormatString('H:i'); - $this->hour->grid->SetColor("gray"); - - $this->day = new HeaderProperty(); - $this->day->grid->SetColor("gray"); - $this->day->SetLabelFormatString('l'); - - $this->week = new HeaderProperty(); - $this->week->SetLabelFormatString("w%d"); - $this->week->SetFont(FF_FONT1); - - $this->month = new HeaderProperty(); - $this->month->SetFont(FF_FONT1,FS_BOLD); - - $this->year = new HeaderProperty(); - $this->year->SetFont(FF_FONT1,FS_BOLD); - - $this->divider=new LineProperty(); - $this->dividerh=new LineProperty(); - $this->dividerh->SetWeight(2); - $this->divider->SetWeight(6); - $this->divider->SetColor('gray'); - $this->divider->SetStyle('fancy'); - - $this->tableTitle=new TextProperty(); - $this->tableTitle->Show(false); - $this->actinfo = new GanttActivityInfo(); - } - -//--------------- -// PUBLIC METHODS - // Specify what headers should be visible - function ShowHeaders($aFlg) { - $this->day->Show($aFlg & GANTT_HDAY); - $this->week->Show($aFlg & GANTT_HWEEK); - $this->month->Show($aFlg & GANTT_HMONTH); - $this->year->Show($aFlg & GANTT_HYEAR); - $this->hour->Show($aFlg & GANTT_HHOUR); - $this->minute->Show($aFlg & GANTT_HMIN); - - // Make some default settings of gridlines whihc makes sense - if( $aFlg & GANTT_HWEEK ) { - $this->month->grid->Show(false); - $this->year->grid->Show(false); - } - if( $aFlg & GANTT_HHOUR ) { - $this->day->grid->SetColor("black"); - } - } - - // Should the weekend background stretch all the way down in the plotarea - function UseWeekendBackground($aShow) { - $this->iUsePlotWeekendBackground = $aShow; - } - - // Have a range been specified? - function IsRangeSet() { - return $this->iStartDate!=-1 && $this->iEndDate!=-1; - } - - // Should the layout be from top or even? - function SetVertLayout($aLayout) { - $this->iVertLayout = $aLayout; - } - - // Which locale should be used? - function SetDateLocale($aLocale) { - $this->iDateLocale->Set($aLocale); - } - - // Number of days we are showing - function GetNumberOfDays() { - return round(($this->iEndDate-$this->iStartDate)/SECPERDAY); - } - - // The width of the actual plot area - function GetPlotWidth() { - $img=$this->iImg; - return $img->width - $img->left_margin - $img->right_margin; - } - - // Specify the width of the titles(labels) for the activities - // (This is by default set to the minimum width enought for the - // widest title) - function SetLabelWidth($aLabelWidth) { - $this->iLabelWidth=$aLabelWidth; - } - - // Which day should the week start? - // 0==Sun, 1==Monday, 2==Tuesday etc - function SetWeekStart($aStartDay) { - $this->iWeekStart = $aStartDay % 7; - - //Recalculate the startday since this will change the week start - $this->SetRange($this->iStartDate,$this->iEndDate); - } - - // Do we show min scale? - function IsDisplayMinute() { - return $this->minute->iShowLabels; - } - - // Do we show day scale? - function IsDisplayHour() { - return $this->hour->iShowLabels; - } - - - // Do we show day scale? - function IsDisplayDay() { - return $this->day->iShowLabels; - } - - // Do we show week scale? - function IsDisplayWeek() { - return $this->week->iShowLabels; - } - - // Do we show month scale? - function IsDisplayMonth() { - return $this->month->iShowLabels; - } - - // Do we show year scale? - function IsDisplayYear() { - return $this->year->iShowLabels; - } - - // Specify spacing (in percent of bar height) between activity bars - function SetVertSpacing($aSpacing) { - $this->iVertSpacing = $aSpacing; - } - - // Specify scale min and max date either as timestamp or as date strings - // Always round to the nearest week boundary - function SetRange($aMin,$aMax) { - $this->iStartDate = $this->NormalizeDate($aMin); - $this->iEndDate = $this->NormalizeDate($aMax); - } - - - // Adjust the start and end date so they fit to beginning/ending - // of the week taking the specified week start day into account. - function AdjustStartEndDay() { - - if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) { - // Don't adjust - return; - } - - // Get day in week for start and ending date (Sun==0) - $ds=strftime("%w",$this->iStartDate); - $de=strftime("%w",$this->iEndDate); - - // We want to start on iWeekStart day. But first we subtract a week - // if the startdate is "behind" the day the week start at. - // This way we ensure that the given start date is always included - // in the range. If we don't do this the nearest correct weekday in the week - // to start at might be later than the start date. - if( $ds < $this->iWeekStart ) - $d = strtotime('-7 day',$this->iStartDate); - else - $d = $this->iStartDate; - $adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ ); - $this->iStartDate = $adjdate; - - // We want to end on the last day of the week - $preferredEndDay = ($this->iWeekStart+6)%7; - if( $preferredEndDay != $de ) { - // Solve equivalence eq: $de + x ~ $preferredDay (mod 7) - $adj = (7+($preferredEndDay - $de)) % 7; - $adjdate = strtotime("+$adj day",$this->iEndDate); - $this->iEndDate = $adjdate; - } - } - - // Specify background for the table title area (upper left corner of the table) - function SetTableTitleBackground($aColor) { - $this->iTableHeaderBackgroundColor = $aColor; - } - -/////////////////////////////////////// -// PRIVATE Methods - - // Determine the height of all the scale headers combined - function GetHeaderHeight() { - $img=$this->iImg; - $height=1; - if( $this->minute->iShowLabels ) { - $height += $this->minute->GetFontHeight($img); - $height += $this->minute->iTitleVertMargin; - } - if( $this->hour->iShowLabels ) { - $height += $this->hour->GetFontHeight($img); - $height += $this->hour->iTitleVertMargin; - } - if( $this->day->iShowLabels ) { - $height += $this->day->GetFontHeight($img); - $height += $this->day->iTitleVertMargin; - } - if( $this->week->iShowLabels ) { - $height += $this->week->GetFontHeight($img); - $height += $this->week->iTitleVertMargin; - } - if( $this->month->iShowLabels ) { - $height += $this->month->GetFontHeight($img); - $height += $this->month->iTitleVertMargin; - } - if( $this->year->iShowLabels ) { - $height += $this->year->GetFontHeight($img); - $height += $this->year->iTitleVertMargin; - } - return $height; - } - - // Get width (in pixels) for a single day - function GetDayWidth() { - return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays(); - } - - // Get width (in pixels) for a single hour - function GetHourWidth() { - return $this->GetDayWidth() / 24 ; - } - - function GetMinuteWidth() { - return $this->GetHourWidth() / 60 ; - } - - // Nuber of days in a year - function GetNumDaysInYear($aYear) { - if( $this->IsLeap($aYear) ) - return 366; - else - return 365; - } - - // Get week number - function GetWeekNbr($aDate,$aSunStart=true) { - // We can't use the internal strftime() since it gets the weeknumber - // wrong since it doesn't follow ISO on all systems since this is - // system linrary dependent. - // Even worse is that this works differently if we are on a Windows - // or UNIX box (it even differs between UNIX boxes how strftime() - // is natively implemented) - // - // Credit to Nicolas Hoizey for this elegant - // version of Week Nbr calculation. - - $day = $this->NormalizeDate($aDate) ; - if( $aSunStart ) - $day += 60*60*24; - - /*------------------------------------------------------------------------- - According to ISO-8601 : - "Week 01 of a year is per definition the first week that has the Thursday in this year, - which is equivalent to the week that contains the fourth day of January. - In other words, the first week of a new year is the week that has the majority of its - days in the new year." - - Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!! - - day of year = date("z", $day) + 1 - offset to thursday = 3 - (date("w", $day) + 6) % 7 - first thursday of year = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7 - week number = (thursday's day of year - first thursday's day of year) / 7 + 1 - ---------------------------------------------------------------------------*/ - - $thursday = $day + 60 * 60 * 24 * (3 - (date("w", $day) + 6) % 7); // take week's thursday - $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7; - - return $week; - } - - // Is year a leap year? - function IsLeap($aYear) { - // Is the year a leap year? - //$year = 0+date("Y",$aDate); - if( $aYear % 4 == 0) - if( !($aYear % 100 == 0) || ($aYear % 400 == 0) ) - return true; - return false; - } - - // Get current year - function GetYear($aDate) { - return 0+Date("Y",$aDate); - } - - // Return number of days in a year - function GetNumDaysInMonth($aMonth,$aYear) { - $days=array(31,28,31,30,31,30,31,31,30,31,30,31); - $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31); - if( $this->IsLeap($aYear)) - return $daysl[$aMonth]; - else - return $days[$aMonth]; - } - - // Get day in month - function GetMonthDayNbr($aDate) { - return 0+strftime("%d",$aDate); - } - - // Get day in year - function GetYearDayNbr($aDate) { - return 0+strftime("%j",$aDate); - } - - // Get month number - function GetMonthNbr($aDate) { - return 0+strftime("%m",$aDate); - } - - // Translate a date to screen coordinates (horizontal scale) - function TranslateDate($aDate) { - // - // In order to handle the problem with Daylight savings time - // the scale written with equal number of seconds per day beginning - // with the start date. This means that we "cement" the state of - // DST as it is in the start date. If later the scale includes the - // switchover date (depends on the locale) we need to adjust back - // if the date we try to translate has a different DST status since - // we would otherwise be off by one hour. - $aDate = $this->NormalizeDate($aDate); - $tmp = localtime($aDate); - $cloc = $tmp[8]; - $tmp = localtime($this->iStartDate); - $sloc = $tmp[8]; - $offset = 0; - if( $sloc != $cloc) { - if( $sloc ) - $offset = 3600; - else - $offset = -3600; - } - $img=$this->iImg; - return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;; - } - - // Get screen coordinatesz for the vertical position for a bar - function TranslateVertPos($aPos) { - $img=$this->iImg; - $ph=$this->iAvailableHeight; - if( $aPos > $this->iVertLines ) - JpGraphError::RaiseL(6015,$aPos); -// 'Illegal vertical position %d' - if( $this->iVertLayout == GANTT_EVEN ) { - // Position the top bar at 1 vert spacing from the scale - return round($img->top_margin + $this->iVertHeaderSize + ($aPos+1)*$this->iVertSpacing); - } - else { - // position the top bar at 1/2 a vert spacing from the scale - return round($img->top_margin + $this->iVertHeaderSize + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing); - } - } - - // What is the vertical spacing? - function GetVertSpacing() { - return $this->iVertSpacing; - } - - // Convert a date to timestamp - function NormalizeDate($aDate) { - if( $aDate === false ) return false; - if( is_string($aDate) ) { - $t = strtotime($aDate); - if( $t === FALSE || $t === -1 ) { - JpGraphError::RaiseL(6016,$aDate); -//("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"); - } - return $t; - } - elseif( is_int($aDate) || is_float($aDate) ) - return $aDate; - else - JpGraphError::RaiseL(6017,$aDate); -//Unknown date format in GanttScale ($aDate)."); - } - - - // Convert a time string to minutes - - function TimeToMinutes($aTimeString) { - // Split in hours and minutes - $pos=strpos($aTimeString,':'); - $minint=60; - if( $pos === false ) { - $hourint = $aTimeString; - $minint = 0; - } - else { - $hourint = floor(substr($aTimeString,0,$pos)); - $minint = floor(substr($aTimeString,$pos+1)); - } - $minint += 60 * $hourint; - return $minint; - } - - // Stroke the day scale (including gridlines) - function StrokeMinutes($aYCoord,$getHeight=false) { - $img=$this->iImg; - $xt=$img->left_margin+$this->iLabelWidth; - $yt=$aYCoord+$img->top_margin; - if( $this->minute->iShowLabels ) { - $img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize); - $yb = $yt + $img->GetFontHeight() + - $this->minute->iTitleVertMargin + $this->minute->iFrameWeight; - if( $getHeight ) { - return $yb - $img->top_margin; - } - $xb = $img->width-$img->right_margin+1; - $img->SetColor($this->minute->iBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - - $x = $xt; - $img->SetTextAlign("center"); - $day = date('w',$this->iStartDate); - $minint = $this->minute->GetIntervall() ; - - if( 60 % $minint !== 0 ) { - JpGraphError::RaiseL(6018,$minint); -//'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.'); - } - - - $n = 60 / $minint; - $datestamp = $this->iStartDate; - $width = $this->GetHourWidth() / $n ; - if( $width < 8 ) { - // TO small width to draw minute scale - JpGraphError::RaiseL(6019,$width); -//('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.'); - } - - $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) ); - $nd = $this->GetNumberOfDays(); - // Convert to intervall to seconds - $minint *= 60; - for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) { - for( $k=0; $k < $nh; ++$k ) { - for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) { - if( $day==6 || $day==0 ) { - - $img->PushColor($this->day->iWeekendBackgroundColor); - if( $this->iUsePlotWeekendBackground ) - $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); - else - $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); - $img->PopColor(); - - } - - if( $day==0 ) - $img->SetColor($this->day->iSundayTextColor); - else - $img->SetColor($this->day->iTextColor); - - switch( $this->minute->iStyle ) { - case MINUTESTYLE_CUSTOM: - $txt = date($this->minute->iLabelFormStr,$datestamp); - break; - case MINUTESTYLE_MM: - default: - // 15 - $txt = date('i',$datestamp); - break; - } - $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt); - - // FIXME: The rounding problem needs to be solved properly ... - // - // Fix a rounding problem the wrong way .. - // If we also have hour scale then don't draw the firsta or last - // gridline since that will be overwritten by the hour scale gridline if such exists. - // However, due to the propagation of rounding of the 'x+=width' term in the loop - // this might sometimes be one pixel of so we fix this by not drawing it. - // The proper way to fix it would be to re-calculate the scale for each step and - // not using the additive term. - if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) { - $img->SetColor($this->minute->grid->iColor); - $img->SetLineWeight($this->minute->grid->iWeight); - $img->Line($x,$yt,$x,$yb); - $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); - } - } - } - } - $img->SetColor($this->minute->iFrameColor); - $img->SetLineWeight($this->minute->iFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - return $yb - $img->top_margin; - } - return $aYCoord; - } - - // Stroke the day scale (including gridlines) - function StrokeHours($aYCoord,$getHeight=false) { - $img=$this->iImg; - $xt=$img->left_margin+$this->iLabelWidth; - $yt=$aYCoord+$img->top_margin; - if( $this->hour->iShowLabels ) { - $img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize); - $yb = $yt + $img->GetFontHeight() + - $this->hour->iTitleVertMargin + $this->hour->iFrameWeight; - if( $getHeight ) { - return $yb - $img->top_margin; - } - $xb = $img->width-$img->right_margin+1; - $img->SetColor($this->hour->iBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - - $x = $xt; - $img->SetTextAlign("center"); - $tmp = $this->hour->GetIntervall() ; - $minint = $this->TimeToMinutes($tmp); - if( 1440 % $minint !== 0 ) { - JpGraphError::RaiseL(6020,$tmp); -//('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); - } - - $n = ceil(24*60 / $minint ); - $datestamp = $this->iStartDate; - $day = date('w',$this->iStartDate); - $doback = !$this->minute->iShowLabels; - $width = $this->GetDayWidth() / $n ; - for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) { - for($i=0; $i < $n ;++$i, $x+=$width) { - if( $day==6 || $day==0 ) { - - $img->PushColor($this->day->iWeekendBackgroundColor); - if( $this->iUsePlotWeekendBackground && $doback ) - $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); - else - $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); - $img->PopColor(); - - } - - if( $day==0 ) - $img->SetColor($this->day->iSundayTextColor); - else - $img->SetColor($this->day->iTextColor); - - switch( $this->hour->iStyle ) { - case HOURSTYLE_HMAMPM: - // 1:35pm - $txt = date('g:ia',$datestamp); - break; - case HOURSTYLE_H24: - // 13 - $txt = date('H',$datestamp); - break; - case HOURSTYLE_HAMPM: - $txt = date('ga',$datestamp); - break; - case HOURSTYLE_CUSTOM: - $txt = date($this->hour->iLabelFormStr,$datestamp); - break; - case HOURSTYLE_HM24: - default: - $txt = date('H:i',$datestamp); - break; - } - $img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt); - $img->SetColor($this->hour->grid->iColor); - $img->SetLineWeight($this->hour->grid->iWeight); - $img->Line($x,$yt,$x,$yb); - $this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); - //$datestamp += $minint*60 - $datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0, - date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); - - } - } - $img->SetColor($this->hour->iFrameColor); - $img->SetLineWeight($this->hour->iFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - return $yb - $img->top_margin; - } - return $aYCoord; - } - - - // Stroke the day scale (including gridlines) - function StrokeDays($aYCoord,$getHeight=false) { - $img=$this->iImg; - $daywidth=$this->GetDayWidth(); - $xt=$img->left_margin+$this->iLabelWidth; - $yt=$aYCoord+$img->top_margin; - if( $this->day->iShowLabels ) { - $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize); - $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight; - if( $getHeight ) { - return $yb - $img->top_margin; - } - $xb=$img->width-$img->right_margin+1; - $img->SetColor($this->day->iBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - - $x = $xt; - $img->SetTextAlign("center"); - $day = date('w',$this->iStartDate); - $datestamp = $this->iStartDate; - - $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels); - - setlocale(LC_TIME,$this->iDateLocale->iLocale); - - for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) { - if( $day==6 || $day==0 ) { - $img->SetColor($this->day->iWeekendBackgroundColor); - if( $this->iUsePlotWeekendBackground && $doback) - $img->FilledRectangle($x,$yt+$this->day->iFrameWeight, - $x+$daywidth,$img->height-$img->bottom_margin); - else - $img->FilledRectangle($x,$yt+$this->day->iFrameWeight, - $x+$daywidth,$yb-$this->day->iFrameWeight); - } - - $mn = strftime('%m',$datestamp); - if( $mn[0]=='0' ) - $mn = $mn[1]; - - switch( $this->day->iStyle ) { - case DAYSTYLE_LONG: - // "Monday" - $txt = strftime('%A',$datestamp); - break; - case DAYSTYLE_SHORT: - // "Mon" - $txt = strftime('%a',$datestamp); - break; - case DAYSTYLE_SHORTDAYDATE1: - // "Mon 23/6" - $txt = strftime('%a %d/'.$mn,$datestamp); - break; - case DAYSTYLE_SHORTDAYDATE2: - // "Mon 23 Jun" - $txt = strftime('%a %d %b',$datestamp); - break; - case DAYSTYLE_SHORTDAYDATE3: - // "Mon 23 Jun 2003" - $txt = strftime('%a %d %b %Y',$datestamp); - break; - case DAYSTYLE_LONGDAYDATE1: - // "Monday 23 Jun" - $txt = strftime('%A %d %b',$datestamp); - break; - case DAYSTYLE_LONGDAYDATE2: - // "Monday 23 Jun 2003" - $txt = strftime('%A %d %b %Y',$datestamp); - break; - case DAYSTYLE_SHORTDATE1: - // "23/6" - $txt = strftime('%d/'.$mn,$datestamp); - break; - case DAYSTYLE_SHORTDATE2: - // "23 Jun" - $txt = strftime('%d %b',$datestamp); - break; - case DAYSTYLE_SHORTDATE3: - // "Mon 23" - $txt = strftime('%a %d',$datestamp); - break; - case DAYSTYLE_SHORTDATE4: - // "23" - $txt = strftime('%d',$datestamp); - break; - case DAYSTYLE_CUSTOM: - // Custom format - $txt = strftime($this->day->iLabelFormStr,$datestamp); - break; - case DAYSTYLE_ONELETTER: - default: - // "M" - $txt = strftime('%A',$datestamp); - $txt = strtoupper($txt[0]); - break; - } - - if( $day==0 ) - $img->SetColor($this->day->iSundayTextColor); - else - $img->SetColor($this->day->iTextColor); - $img->StrokeText(round($x+$daywidth/2+1), - round($yb-$this->day->iTitleVertMargin),$txt); - $img->SetColor($this->day->grid->iColor); - $img->SetLineWeight($this->day->grid->iWeight); - $img->Line($x,$yt,$x,$yb); - $this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); - $datestamp = mktime(0,0,0,date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); - //$datestamp += SECPERDAY; - - } - $img->SetColor($this->day->iFrameColor); - $img->SetLineWeight($this->day->iFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - return $yb - $img->top_margin; - } - return $aYCoord; - } - - // Stroke week header and grid - function StrokeWeeks($aYCoord,$getHeight=false) { - if( $this->week->iShowLabels ) { - $img=$this->iImg; - $yt=$aYCoord+$img->top_margin; - $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize); - $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight; - - if( $getHeight ) { - return $yb - $img->top_margin; - } - - $xt=$img->left_margin+$this->iLabelWidth; - $weekwidth=$this->GetDayWidth()*7; - $wdays=$this->iDateLocale->GetDayAbb(); - $xb=$img->width-$img->right_margin+1; - $week = $this->iStartDate; - $weeknbr=$this->GetWeekNbr($week); - $img->SetColor($this->week->iBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - $img->SetColor($this->week->grid->iColor); - $x = $xt; - if( $this->week->iStyle==WEEKSTYLE_WNBR ) { - $img->SetTextAlign("center"); - $txtOffset = $weekwidth/2+1; - } - elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || - $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || - $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || - $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { - $img->SetTextAlign("left"); - $txtOffset = 3; - } - else - JpGraphError::RaiseL(6021); -//("Unknown formatting style for week."); - - for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) { - $img->PushColor($this->week->iTextColor); - - if( $this->week->iStyle==WEEKSTYLE_WNBR ) - $txt = sprintf($this->week->iLabelFormStr,$weeknbr); - elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || - $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) - $txt = date("j/n",$week); - elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || - $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { - $monthnbr = date("n",$week)-1; - $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr); - $txt = Date("j",$week)." ".$shortmonth; - } - - if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || - $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { - $w = sprintf($this->week->iLabelFormStr,$weeknbr); - $txt .= ' '.$w; - } - - $img->StrokeText(round($x+$txtOffset), - round($yb-$this->week->iTitleVertMargin),$txt); - - $week = strtotime('+7 day',$week); - $weeknbr = $this->GetWeekNbr($week); - $img->PopColor(); - $img->SetLineWeight($this->week->grid->iWeight); - $img->Line($x,$yt,$x,$yb); - $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); - } - $img->SetColor($this->week->iFrameColor); - $img->SetLineWeight($this->week->iFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - return $yb-$img->top_margin; - } - return $aYCoord; - } - - // Format the mont scale header string - function GetMonthLabel($aMonthNbr,$year) { - $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr); - $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr); - switch($this->month->iStyle) { - case MONTHSTYLE_SHORTNAME: - $m=$sn; - break; - case MONTHSTYLE_LONGNAME: - $m=$ln; - break; - case MONTHSTYLE_SHORTNAMEYEAR2: - $m=$sn." '".substr("".$year,2); - break; - case MONTHSTYLE_SHORTNAMEYEAR4: - $m=$sn." ".$year; - break; - case MONTHSTYLE_LONGNAMEYEAR2: - $m=$ln." '".substr("".$year,2); - break; - case MONTHSTYLE_LONGNAMEYEAR4: - $m=$ln." ".$year; - break; - case MONTHSTYLE_FIRSTLETTER: - $m=$sn[0]; - break; - } - return $m; - } - - // Stroke month scale and gridlines - function StrokeMonths($aYCoord,$getHeight=false) { - if( $this->month->iShowLabels ) { - $img=$this->iImg; - $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize); - $yt=$aYCoord+$img->top_margin; - $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight; - if( $getHeight ) { - return $yb - $img->top_margin; - } - $monthnbr = $this->GetMonthNbr($this->iStartDate)-1; - $xt=$img->left_margin+$this->iLabelWidth; - $xb=$img->width-$img->right_margin+1; - - $img->SetColor($this->month->iBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - - $img->SetLineWeight($this->month->grid->iWeight); - $img->SetColor($this->month->iTextColor); - $year = 0+strftime("%Y",$this->iStartDate); - $img->SetTextAlign("center"); - if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) - && $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) { - $monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1); - } - else { - $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1); - } - // Is it enough space to stroke the first month? - $monthName = $this->GetMonthLabel($monthnbr,$year); - if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) { - $img->SetColor($this->month->iTextColor); - $img->StrokeText(round($xt+$monthwidth/2+1), - round($yb-$this->month->iTitleVertMargin), - $monthName); - } - $x = $xt + $monthwidth; - while( $x < $xb ) { - $img->SetColor($this->month->grid->iColor); - $img->Line($x,$yt,$x,$yb); - $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); - $monthnbr++; - if( $monthnbr==12 ) { - $monthnbr=0; - $year++; - } - $monthName = $this->GetMonthLabel($monthnbr,$year); - $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year); - if( $x + $monthwidth < $xb ) - $w = $monthwidth; - else - $w = $xb-$x; - if( $w >= 1.2*$img->GetTextWidth($monthName) ) { - $img->SetColor($this->month->iTextColor); - $img->StrokeText(round($x+$w/2+1), - round($yb-$this->month->iTitleVertMargin),$monthName); - } - $x += $monthwidth; - } - $img->SetColor($this->month->iFrameColor); - $img->SetLineWeight($this->month->iFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - return $yb-$img->top_margin; - } - return $aYCoord; - } - - // Stroke year scale and gridlines - function StrokeYears($aYCoord,$getHeight=false) { - if( $this->year->iShowLabels ) { - $img=$this->iImg; - $yt=$aYCoord+$img->top_margin; - $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize); - $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight; - - if( $getHeight ) { - return $yb - $img->top_margin; - } - - $xb=$img->width-$img->right_margin+1; - $xt=$img->left_margin+$this->iLabelWidth; - $year = $this->GetYear($this->iStartDate); - $img->SetColor($this->year->iBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - $img->SetLineWeight($this->year->grid->iWeight); - $img->SetTextAlign("center"); - if( $year == $this->GetYear($this->iEndDate) ) - $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1); - else - $yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1); - - // The space for a year must be at least 20% bigger than the actual text - // so we allow 10% margin on each side - if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) { - $img->SetColor($this->year->iTextColor); - $img->StrokeText(round($xt+$yearwidth/2+1), - round($yb-$this->year->iTitleVertMargin), - $year); - } - $x = $xt + $yearwidth; - while( $x < $xb ) { - $img->SetColor($this->year->grid->iColor); - $img->Line($x,$yt,$x,$yb); - $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); - $year += 1; - $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year); - if( $x + $yearwidth < $xb ) - $w = $yearwidth; - else - $w = $xb-$x; - if( $w >= 1.2*$img->GetTextWidth("".$year) ) { - $img->SetColor($this->year->iTextColor); - $img->StrokeText(round($x+$w/2+1), - round($yb-$this->year->iTitleVertMargin), - $year); - } - $x += $yearwidth; - } - $img->SetColor($this->year->iFrameColor); - $img->SetLineWeight($this->year->iFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - return $yb-$img->top_margin; - } - return $aYCoord; - } - - // Stroke table title (upper left corner) - function StrokeTableHeaders($aYBottom) { - $img=$this->iImg; - $xt=$img->left_margin; - $yt=$img->top_margin; - $xb=$xt+$this->iLabelWidth; - $yb=$aYBottom+$img->top_margin; - - if( $this->tableTitle->iShow ) { - $img->SetColor($this->iTableHeaderBackgroundColor); - $img->FilledRectangle($xt,$yt,$xb,$yb); - $this->tableTitle->Align("center","top"); - $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2); - $img->SetColor($this->iTableHeaderFrameColor); - $img->SetLineWeight($this->iTableHeaderFrameWeight); - $img->Rectangle($xt,$yt,$xb,$yb); - } - - $this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow); - - - // Draw the horizontal dividing line - $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb); - - // Draw the vertical dividing line - // We do the width "manually" since we want the line only to grow - // to the left - $fancy = $this->divider->iStyle == 'fancy' ; - if( $fancy ) { - $this->divider->iStyle = 'solid'; - } - - $tmp = $this->divider->iWeight; - $this->divider->iWeight=1; - $y = $img->height-$img->bottom_margin; - for($i=0; $i < $tmp; ++$i ) { - $this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y); - } - - // Should we draw "fancy" divider - if( $fancy ) { - $img->SetLineWeight(1); - $img->SetColor($this->iTableHeaderFrameColor); - $img->Line($xb,$yt,$xb,$y); - $img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y); - $img->SetColor('white'); - $img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y); - } - } - - // Main entry point to stroke scale - function Stroke() { - if( !$this->IsRangeSet() ) - JpGraphError::RaiseL(6022); -//("Gantt scale has not been specified."); - $img=$this->iImg; - - // If minutes are displayed then hour interval must be 1 - if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) { - JpGraphError::RaiseL(6023); -//('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).'); - } - - // Stroke all headers. As argument we supply the offset from the - // top which depends on any previous headers - - // First find out the height of each header - $offy=$this->StrokeYears(0,true); - $offm=$this->StrokeMonths($offy,true); - $offw=$this->StrokeWeeks($offm,true); - $offd=$this->StrokeDays($offw,true); - $offh=$this->StrokeHours($offd,true); - $offmin=$this->StrokeMinutes($offh,true); - - - // ... then we can stroke them in the "backwards order to ensure that - // the larger scale gridlines is stroked over the smaller scale gridline - $this->StrokeMinutes($offh); - $this->StrokeHours($offd); - $this->StrokeDays($offw); - $this->StrokeWeeks($offm); - $this->StrokeMonths($offy); - $this->StrokeYears(0); - - // Now when we now the oaverall size of the scale headers - // we can stroke the overall table headers - $this->StrokeTableHeaders($offmin); - - // Now we can calculate the correct scaling factor for each vertical position - $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd; - $this->iVertHeaderSize = $offmin; - if( $this->iVertSpacing == -1 ) - $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines; - } -} - - -//=================================================== -// CLASS GanttConstraint -// Just a structure to store all the values for a constraint -//=================================================== -class GanttConstraint { - var $iConstrainType; - var $iConstrainRow; - var $iConstrainColor; - var $iConstrainArrowSize; - var $iConstrainArrowType; - -//--------------- -// CONSTRUCTOR - function GanttConstraint($aRow,$aType,$aColor,$aArrowSize,$aArrowType){ - $this->iConstrainType = $aType; - $this->iConstrainRow = $aRow; - $this->iConstrainColor=$aColor; - $this->iConstrainArrowSize=$aArrowSize; - $this->iConstrainArrowType=$aArrowType; - } -} - - -//=================================================== -// CLASS GanttPlotObject -// The common signature for a Gantt object -//=================================================== -class GanttPlotObject { - var $iVPos=0; // Vertical position - var $iLabelLeftMargin=2; // Title margin - var $iStart=""; // Start date - var $title,$caption; - var $iCaptionMargin=5; - var $csimarea='',$csimtarget='',$csimalt=''; - - var $constraints = array(); - var $iConstrainPos=array(); - - function GanttPlotObject() { - $this->title = new TextProperty(); - $this->title->Align("left","center"); - $this->caption = new TextProperty(); - } - - function GetCSIMArea() { - return $this->csimarea; - } - - function SetCSIMTarget($aTarget,$aAlt='') { - if( !is_string($aTarget) ) { - $tv = substr(var_export($aTarget,true),0,40); - JpGraphError::RaiseL(6024,$tv); -//('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv"); - } - if( !is_string($aAlt) ) { - $tv = substr(var_export($aAlt,true),0,40); - JpGraphError::RaiseL(6025,$tv); -//('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); - } - - $this->csimtarget=$aTarget; - $this->csimalt=$aAlt; - } - - function SetCSIMAlt($aAlt) { - if( !is_string($aAlt) ) { - $tv = substr(var_export($aAlt,true),0,40); - JpGraphError::RaiseL(6025,$tv); -//('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); - } - $this->csimalt=$aAlt; - } - - function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) { - $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType); - } - - function SetConstrainPos($xt,$yt,$xb,$yb) { - $this->iConstrainPos = array($xt,$yt,$xb,$yb); - } - - /* - function GetConstrain() { - return array($this->iConstrainRow,$this->iConstrainType); - } - */ - - function GetMinDate() { - return $this->iStart; - } - - function GetMaxDate() { - return $this->iStart; - } - - function SetCaptionMargin($aMarg) { - $this->iCaptionMargin=$aMarg; - } - - function GetAbsHeight(&$aImg) { - return 0; - } - - function GetLineNbr() { - return $this->iVPos; - } - - function SetLabelLeftMargin($aOff) { - $this->iLabelLeftMargin=$aOff; - } - - function StrokeActInfo(&$aImg,$aScale,$aYPos) { - $cols=array(); - $aScale->actinfo->GetColStart($aImg,$cols,true); - $this->title->Stroke($aImg,$cols,$aYPos); - } -} - -//=================================================== -// CLASS Progress -// Holds parameters for the progress indicator -// displyed within a bar -//=================================================== -class Progress { - var $iProgress=-1, $iColor="black", $iFillColor='black'; - var $iPattern=GANTT_SOLID; - var $iDensity=98, $iHeight=0.65; - - function Set($aProg) { - if( $aProg < 0.0 || $aProg > 1.0 ) - JpGraphError::RaiseL(6027); -//("Progress value must in range [0, 1]"); - $this->iProgress = $aProg; - } - - function SetPattern($aPattern,$aColor="blue",$aDensity=98) { - $this->iPattern = $aPattern; - $this->iColor = $aColor; - $this->iDensity = $aDensity; - } - - function SetFillColor($aColor) { - $this->iFillColor = $aColor; - } - - function SetHeight($aHeight) { - $this->iHeight = $aHeight; - } -} - -DEFINE('GANTT_HGRID1',0); -DEFINE('GANTT_HGRID2',1); - -//=================================================== -// CLASS HorizontalGridLine -// Responsible for drawinf horizontal gridlines and filled alternatibg rows -//=================================================== -class HorizontalGridLine { - var $iGraph=NULL; - var $iRowColor1 = '', $iRowColor2 = ''; - var $iShow=false; - var $line=null; - var $iStart=0; // 0=from left margin, 1=just along header - - function HorizontalGridLine() { - $this->line = new LineProperty(); - $this->line->SetColor('gray@0.4'); - $this->line->SetStyle('dashed'); - } - - function Show($aShow=true) { - $this->iShow = $aShow; - } - - function SetRowFillColor($aColor1,$aColor2='') { - $this->iRowColor1 = $aColor1; - $this->iRowColor2 = $aColor2; - } - - function SetStart($aStart) { - $this->iStart = $aStart; - } - - function Stroke(&$aImg,$aScale) { - - if( ! $this->iShow ) return; - - // Get horizontal width of line - /* - $limst = $aScale->iStartDate; - $limen = $aScale->iEndDate; - $xt = round($aScale->TranslateDate($aScale->iStartDate)); - $xb = round($aScale->TranslateDate($limen)); - */ - - if( $this->iStart === 0 ) { - $xt = $aImg->left_margin-1; - } - else { - $xt = round($aScale->TranslateDate($aScale->iStartDate))+1; - } - - $xb = $aImg->width-$aImg->right_margin; - - $yt = round($aScale->TranslateVertPos(0)); - $yb = round($aScale->TranslateVertPos(1)); - $height = $yb - $yt; - - // Loop around for all lines in the chart - for($i=0; $i < $aScale->iVertLines; ++$i ) { - $yb = $yt - $height; - $this->line->Stroke($aImg,$xt,$yb,$xb,$yb); - if( $this->iRowColor1 !== '' ) { - if( $i % 2 == 0 ) { - $aImg->PushColor($this->iRowColor1); - $aImg->FilledRectangle($xt,$yt,$xb,$yb); - $aImg->PopColor(); - } - elseif( $this->iRowColor2 !== '' ) { - $aImg->PushColor($this->iRowColor2); - $aImg->FilledRectangle($xt,$yt,$xb,$yb); - $aImg->PopColor(); - } - } - $yt = round($aScale->TranslateVertPos($i+1)); - } - $yb = $yt - $height; - $this->line->Stroke($aImg,$xt,$yb,$xb,$yb); - } -} - - -//=================================================== -// CLASS GanttBar -// Responsible for formatting individual gantt bars -//=================================================== -class GanttBar extends GanttPlotObject { - var $iEnd; - var $iHeightFactor=0.5; - var $iFillColor="white",$iFrameColor="black"; - var $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black"; - var $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95; - var $leftMark,$rightMark; - var $progress; -//--------------- -// CONSTRUCTOR - function GanttBar($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) { - parent::GanttPlotObject(); - $this->iStart = $aStart; - // Is the end date given as a date or as number of days added to start date? - if( is_string($aEnd) ) { - // If end date has been specified without a time we will asssume - // end date is at the end of that date - if( strpos($aEnd,':') === false ) - $this->iEnd = strtotime($aEnd)+SECPERDAY-1; - else - $this->iEnd = $aEnd; - } - elseif(is_int($aEnd) || is_float($aEnd) ) - $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY); - $this->iVPos = $aPos; - $this->iHeightFactor = $aHeightFactor; - $this->title->Set($aLabel); - $this->caption = new TextProperty($aCaption); - $this->caption->Align("left","center"); - $this->leftMark =new PlotMark(); - $this->leftMark->Hide(); - $this->rightMark=new PlotMark(); - $this->rightMark->Hide(); - $this->progress = new Progress(); - } - -//--------------- -// PUBLIC METHODS - function SetShadow($aShadow=true,$aColor="gray") { - $this->iShadow=$aShadow; - $this->iShadowColor=$aColor; - } - - function GetMaxDate() { - return $this->iEnd; - } - - function SetHeight($aHeight) { - $this->iHeightFactor = $aHeight; - } - - function SetColor($aColor) { - $this->iFrameColor = $aColor; - } - - function SetFillColor($aColor) { - $this->iFillColor = $aColor; - } - - function GetAbsHeight(&$aImg) { - if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) { - $m=-1; - if( is_int($this->iHeightFactor) ) - $m = $this->iHeightFactor; - if( $this->leftMark->show ) - $m = max($m,$this->leftMark->width*2); - if( $this->rightMark->show ) - $m = max($m,$this->rightMark->width*2); - return $m; - } - else - return -1; - } - - function SetPattern($aPattern,$aColor="blue",$aDensity=95) { - $this->iPattern = $aPattern; - $this->iPatternColor = $aColor; - $this->iPatternDensity = $aDensity; - } - - function Stroke(&$aImg,$aScale) { - $factory = new RectPatternFactory(); - $prect = $factory->Create($this->iPattern,$this->iPatternColor); - $prect->SetDensity($this->iPatternDensity); - - // If height factor is specified as a float between 0,1 then we take it as meaning - // percetage of the scale width between horizontal line. - // If it is an integer > 1 we take it to mean the absolute height in pixels - if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1) - $vs = $aScale->GetVertSpacing()*$this->iHeightFactor; - elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 ) - $vs = $this->iHeightFactor; - else - JpGraphError::RaiseL(6028,$this->iHeightFactor); -//("Specified height (".$this->iHeightFactor.") for gantt bar is out of range."); - - // Clip date to min max dates to show - $st = $aScale->NormalizeDate($this->iStart); - $en = $aScale->NormalizeDate($this->iEnd); - - - $limst = max($st,$aScale->iStartDate); - $limen = min($en,$aScale->iEndDate); - - $xt = round($aScale->TranslateDate($limst)); - $xb = round($aScale->TranslateDate($limen)); - $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2)); - $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2)); - $middle = round($yt+($yb-$yt)/2); - $this->StrokeActInfo($aImg,$aScale,$middle); - - // CSIM for title - if( ! empty($this->title->csimtarget) ) { - $colwidth = $this->title->GetColWidth($aImg); - $colstarts=array(); - $aScale->actinfo->GetColStart($aImg,$colstarts,true); - $n = min(count($colwidth),count($this->title->csimtarget)); - for( $i=0; $i < $n; ++$i ) { - $title_xt = $colstarts[$i]; - $title_xb = $title_xt + $colwidth[$i]; - $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; - $this->csimarea .= "title->csimtarget[$i]."\""; - if( ! empty($this->title->csimalt[$i]) ) { - $tmp = $this->title->csimalt[$i]; - $this->csimarea .= " title=\"$tmp\""; - } - $this->csimarea .= " alt=\"$tmp\" />\n"; - } - } - - // Check if the bar is totally outside the current scale range - if( $en < $aScale->iStartDate || $st > $aScale->iEndDate ) - return; - - - // Remember the positions for the bar - $this->SetConstrainPos($xt,$yt,$xb,$yb); - - $prect->ShowFrame(false); - $prect->SetBackground($this->iFillColor); - if( $this->iShadow ) { - $aImg->SetColor($this->iFrameColor); - $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor); - $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2)); - $prect->Stroke($aImg); - } - else { - $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1)); - $prect->Stroke($aImg); - $aImg->SetColor($this->iFrameColor); - $aImg->Rectangle($xt,$yt,$xb,$yb); - } - - // CSIM for bar - if( $this->csimtarget != '' ) { - - $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb"; - $this->csimarea .= "csimtarget."\""; - if( $this->csimalt != '' ) { - $tmp = $this->csimalt; - $this->csimarea .= " title=\"$tmp\""; - } - $this->csimarea .= " alt=\"$tmp\" />\n"; - } - - // Draw progress bar inside activity bar - if( $this->progress->iProgress > 0 ) { - - $xtp = $aScale->TranslateDate($st); - $xbp = $aScale->TranslateDate($en); - $len = ($xbp-$xtp)*$this->progress->iProgress; - - $endpos = $xtp+$len; - if( $endpos > $xt ) { - $len -= ($xt-$xtp); - - // Make sure that the progess bar doesn't extend over the end date - if( $xtp+$len-1 > $xb ) - $len = $xb - $xtp + 1; - - if( $xtp < $xt ) - $xtp = $xt; - - $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor); - $prog->SetDensity($this->progress->iDensity); - $prog->SetBackground($this->progress->iFillColor); - $barheight = ($yb-$yt+1); - if( $this->iShadow ) - $barheight -= $this->iShadowWidth; - $progressheight = floor($barheight*$this->progress->iHeight); - $marg = ceil(($barheight-$progressheight)/2); - $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg); - $prog->SetPos($pos); - $prog->Stroke($aImg); - } - } - - // We don't plot the end mark if the bar has been capped - if( $limst == $st ) { - $y = $middle; - // We treat the RIGHT and LEFT triangle mark a little bi - // special so that these marks are placed right under the - // bar. - if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) { - $y = $yb ; - } - $this->leftMark->Stroke($aImg,$xt,$y); - } - if( $limen == $en ) { - $y = $middle; - // We treat the RIGHT and LEFT triangle mark a little bi - // special so that these marks are placed right under the - // bar. - if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) { - $y = $yb ; - } - $this->rightMark->Stroke($aImg,$xb,$y); - - $margin = $this->iCaptionMargin; - if( $this->rightMark->show ) - $margin += $this->rightMark->GetWidth(); - $this->caption->Stroke($aImg,$xb+$margin,$middle); - } - } -} - -//=================================================== -// CLASS MileStone -// Responsible for formatting individual milestones -//=================================================== -class MileStone extends GanttPlotObject { - var $mark; - -//--------------- -// CONSTRUCTOR - function MileStone($aVPos,$aLabel,$aDate,$aCaption="") { - GanttPlotObject::GanttPlotObject(); - $this->caption->Set($aCaption); - $this->caption->Align("left","center"); - $this->caption->SetFont(FF_FONT1,FS_BOLD); - $this->title->Set($aLabel); - $this->title->SetColor("darkred"); - $this->mark = new PlotMark(); - $this->mark->SetWidth(10); - $this->mark->SetType(MARK_DIAMOND); - $this->mark->SetColor("darkred"); - $this->mark->SetFillColor("darkred"); - $this->iVPos = $aVPos; - $this->iStart = $aDate; - } - -//--------------- -// PUBLIC METHODS - - function GetAbsHeight(&$aImg) { - return max($this->title->GetHeight($aImg),$this->mark->GetWidth()); - } - - function Stroke(&$aImg,$aScale) { - // Put the mark in the middle at the middle of the day - $d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2; - $x = $aScale->TranslateDate($d); - $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2); - - $this->StrokeActInfo($aImg,$aScale,$y); - - // CSIM for title - if( ! empty($this->title->csimtarget) ) { - - $yt = round($y - $this->title->GetHeight($aImg)/2); - $yb = round($y + $this->title->GetHeight($aImg)/2); - - $colwidth = $this->title->GetColWidth($aImg); - $colstarts=array(); - $aScale->actinfo->GetColStart($aImg,$colstarts,true); - $n = min(count($colwidth),count($this->title->csimtarget)); - for( $i=0; $i < $n; ++$i ) { - $title_xt = $colstarts[$i]; - $title_xb = $title_xt + $colwidth[$i]; - $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; - $this->csimarea .= "title->csimtarget[$i]."\""; - if( ! empty($this->title->csimalt[$i]) ) { - $tmp = $this->title->csimalt[$i]; - $this->csimarea .= " title=\"$tmp\""; - } - $this->csimarea .= " alt=\"$tmp\" />\n"; - } - } - - if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) - return; - - // Remember the coordinates for any constrains linking to - // this milestone - $w = $this->mark->GetWidth()/2; - $this->SetConstrainPos($x,round($y-$w),$x,round($y+$w)); - - // Setup CSIM - if( $this->csimtarget != '' ) { - $this->mark->SetCSIMTarget( $this->csimtarget ); - $this->mark->SetCSIMAlt( $this->csimalt ); - } - - $this->mark->Stroke($aImg,$x,$y); - $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y); - - $this->csimarea .= $this->mark->GetCSIMAreas(); - } -} - - -//=================================================== -// CLASS GanttVLine -// Responsible for formatting individual milestones -//=================================================== - -class TextPropertyBelow extends TextProperty { - function TextPropertyBelow($aTxt='') { - parent::TextProperty($aTxt); - } - - function GetColWidth(&$aImg,$margin) { - // Since we are not stroking the title in the columns - // but rather under the graph we want this to return 0. - return array(0); - } -} - -class GanttVLine extends GanttPlotObject { - - var $iLine,$title_margin=3; - var $iDayOffset=1; // Defult to right edge of day - -//--------------- -// CONSTRUCTOR - function GanttVLine($aDate,$aTitle="",$aColor="black",$aWeight=3,$aStyle="dashed") { - GanttPlotObject::GanttPlotObject(); - $this->iLine = new LineProperty(); - $this->iLine->SetColor($aColor); - $this->iLine->SetWeight($aWeight); - $this->iLine->SetStyle($aStyle); - $this->iStart = $aDate; - $this->title = new TextPropertyBelow(); - $this->title->Set($aTitle); - } - -//--------------- -// PUBLIC METHODS - - function SetDayOffset($aOff=0.5) { - if( $aOff < 0.0 || $aOff > 1.0 ) - JpGraphError::RaiseL(6029); -//("Offset for vertical line must be in range [0,1]"); - $this->iDayOffset = $aOff; - } - - function SetTitleMargin($aMarg) { - $this->title_margin = $aMarg; - } - - function Stroke(&$aImg,$aScale) { - $d = $aScale->NormalizeDate($this->iStart); - if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) - return; - if($this->iDayOffset != 0.0) - $d += 24*60*60*$this->iDayOffset; - $x = $aScale->TranslateDate($d); - $y1 = $aScale->iVertHeaderSize+$aImg->top_margin; - $y2 = $aImg->height - $aImg->bottom_margin; - $this->iLine->Stroke($aImg,$x,$y1,$x,$y2); - $this->title->Align("center","top"); - $this->title->Stroke($aImg,$x,$y2+$this->title_margin); - } -} - -//=================================================== -// CLASS LinkArrow -// Handles the drawing of a an arrow -//=================================================== -class LinkArrow { - var $ix,$iy; - var $isizespec = array( - array(2,3),array(3,5),array(3,8),array(6,15),array(8,22)); - var $iDirection=ARROW_DOWN,$iType=ARROWT_SOLID,$iSize=ARROW_S2; - var $iColor='black'; - - function LinkArrow($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) { - $this->iDirection = $aDirection; - $this->iType = $aType; - $this->iSize = $aSize; - $this->ix = $x; - $this->iy = $y; - } - - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function SetSize($aSize) { - $this->iSize = $aSize; - } - - function SetType($aType) { - $this->iType = $aType; - } - - function Stroke(&$aImg) { - list($dx,$dy) = $this->isizespec[$this->iSize]; - $x = $this->ix; - $y = $this->iy; - switch ( $this->iDirection ) { - case ARROW_DOWN: - $c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y); - break; - case ARROW_UP: - $c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y); - break; - case ARROW_LEFT: - $c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y); - break; - case ARROW_RIGHT: - $c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y); - break; - default: - JpGraphError::RaiseL(6030); -//('Unknown arrow direction for link.'); - die(); - break; - } - $aImg->SetColor($this->iColor); - switch( $this->iType ) { - case ARROWT_SOLID: - $aImg->FilledPolygon($c); - break; - case ARROWT_OPEN: - $aImg->Polygon($c); - break; - default: - JpGraphError::RaiseL(6031); -//('Unknown arrow type for link.'); - die(); - break; - } - } -} - -//=================================================== -// CLASS GanttLink -// Handles the drawing of a link line between 2 points -//=================================================== - -class GanttLink { - var $ix1,$ix2,$iy1,$iy2; - var $iPathType=2,$iPathExtend=15; - var $iColor='black',$iWeight=1; - var $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID; - - function GanttLink($x1=0,$y1=0,$x2=0,$y2=0) { - $this->ix1 = $x1; - $this->ix2 = $x2; - $this->iy1 = $y1; - $this->iy2 = $y2; - } - - function SetPos($x1,$y1,$x2,$y2) { - $this->ix1 = $x1; - $this->ix2 = $x2; - $this->iy1 = $y1; - $this->iy2 = $y2; - } - - function SetPath($aPath) { - $this->iPathType = $aPath; - } - - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function SetArrow($aSize,$aType=ARROWT_SOLID) { - $this->iArrowSize = $aSize; - $this->iArrowType = $aType; - } - - function SetWeight($aWeight) { - $this->iWeight = $aWeight; - } - - function Stroke(&$aImg) { - // The way the path for the arrow is constructed is partly based - // on some heuristics. This is not an exact science but draws the - // path in a way that, for me, makes esthetic sence. For example - // if the start and end activities are very close we make a small - // detour to endter the target horixontally. If there are more - // space between axctivities then no suh detour is made and the - // target is "hit" directly vertical. I have tried to keep this - // simple. no doubt this could become almost infinitive complex - // and have some real AI. Feel free to modify this. - // This will no-doubt be tweaked as times go by. One design aim - // is to avoid having the user choose what types of arrow - // he wants. - - // The arrow is drawn between (x1,y1) to (x2,y2) - $x1 = $this->ix1 ; - $x2 = $this->ix2 ; - $y1 = $this->iy1 ; - $y2 = $this->iy2 ; - - // Depending on if the target is below or above we have to - // handle thi different. - if( $y2 > $y1 ) { - $arrowtype = ARROW_DOWN; - $midy = round(($y2-$y1)/2+$y1); - if( $x2 > $x1 ) { - switch ( $this->iPathType ) { - case 0: - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - break; - case 1: - case 2: - case 3: - $c = array($x1,$y1,$x2,$y1,$x2,$y2); - break; - default: - JpGraphError::RaiseL(6032,$this->iPathType); -//('Internal error: Unknown path type (='.$this->iPathType .') specified for link.'); - exit(1); - break; - } - } - else { - switch ( $this->iPathType ) { - case 0: - case 1: - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - break; - case 2: - // Always extend out horizontally a bit from the first point - // If we draw a link back in time (end to start) and the bars - // are very close we also change the path so it comes in from - // the left on the activity - $c = array($x1,$y1,$x1+$this->iPathExtend,$y1, - $x1+$this->iPathExtend,$midy, - $x2,$midy,$x2,$y2); - break; - case 3: - if( $y2-$midy < 6 ) { - $c = array($x1,$y1,$x1,$midy, - $x2-$this->iPathExtend,$midy, - $x2-$this->iPathExtend,$y2, - $x2,$y2); - $arrowtype = ARROW_RIGHT; - } - else { - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - } - break; - default: - JpGraphError::RaiseL(6032,$this->iPathType); -//('Internal error: Unknown path type specified for link.'); - exit(1); - break; - } - } - $arrow = new LinkArrow($x2,$y2,$arrowtype); - } - else { - // Y2 < Y1 - $arrowtype = ARROW_UP; - $midy = round(($y1-$y2)/2+$y2); - if( $x2 > $x1 ) { - switch ( $this->iPathType ) { - case 0: - case 1: - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - break; - case 3: - if( $midy-$y2 < 8 ) { - $arrowtype = ARROW_RIGHT; - $c = array($x1,$y1,$x1,$y2,$x2,$y2); - } - else { - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - } - break; - default: - JpGraphError::RaiseL(6032,$this->iPathType); -//('Internal error: Unknown path type specified for link.'); - break; - } - } - else { - switch ( $this->iPathType ) { - case 0: - case 1: - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - break; - case 2: - // Always extend out horizontally a bit from the first point - $c = array($x1,$y1,$x1+$this->iPathExtend,$y1, - $x1+$this->iPathExtend,$midy, - $x2,$midy,$x2,$y2); - break; - case 3: - if( $midy-$y2 < 16 ) { - $arrowtype = ARROW_RIGHT; - $c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy, - $x2-$this->iPathExtend,$y2, - $x2,$y2); - } - else { - $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); - } - break; - default: - JpGraphError::RaiseL(6032,$this->iPathType); -//('Internal error: Unknown path type specified for link.'); - break; - } - } - $arrow = new LinkArrow($x2,$y2,$arrowtype); - } - $aImg->SetColor($this->iColor); - $aImg->SetLineWeight($this->iWeight); - $aImg->Polygon($c); - $aImg->SetLineWeight(1); - $arrow->SetColor($this->iColor); - $arrow->SetSize($this->iArrowSize); - $arrow->SetType($this->iArrowType); - $arrow->Stroke($aImg); - } -} - -// -?> +vgrid = new LineProperty(); + } + + function Hide($aF=true) { + $this->iShow=!$aF; + } + + function Show($aF=true) { + $this->iShow=$aF; + } + + // Specify font + function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { + $this->iFFamily = $aFFamily; + $this->iFStyle = $aFStyle; + $this->iFSize = $aFSize; + } + + function SetStyle($aStyle) { + $this->iStyle = $aStyle; + } + + function SetColumnMargin($aLeft,$aRight) { + $this->iLeftColMargin = $aLeft; + $this->iRightColMargin = $aRight; + } + + function SetFontColor($aFontColor) { + $this->iFontColor = $aFontColor; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function SetBackgroundColor($aColor) { + $this->iBackgroundColor = $aColor; + } + + function SetColTitles($aTitles,$aWidth=null) { + $this->iTitles = $aTitles; + $this->iWidth = $aWidth; + } + + function SetMinColWidth($aWidths) { + $n = min(count($this->iTitles),count($aWidths)); + for($i=0; $i < $n; ++$i ) { + if( !empty($aWidths[$i]) ) { + if( empty($this->iWidth[$i]) ) { + $this->iWidth[$i] = $aWidths[$i]; + } + else { + $this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]); + } + } + } + } + + function GetWidth($aImg) { + $txt = new TextProperty(); + $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + $n = count($this->iTitles) ; + $rm=$this->iRightColMargin; + $w = 0; + for($h=0, $i=0; $i < $n; ++$i ) { + $w += $this->iLeftColMargin; + $txt->Set($this->iTitles[$i]); + if( !empty($this->iWidth[$i]) ) { + $w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]); + } + else { + $w1 = $txt->GetWidth($aImg)+$rm; + } + $this->iWidth[$i] = $w1; + $w += $w1; + $h = max($h,$txt->GetHeight($aImg)); + } + $this->iHeight = $h+$this->iTopHeaderMargin; + $txt=''; + return $w; + } + + function GetColStart($aImg,&$aStart,$aAddLeftMargin=false) { + $n = count($this->iTitles) ; + $adj = $aAddLeftMargin ? $this->iLeftColMargin : 0; + $aStart=array($aImg->left_margin+$adj); + for( $i=1; $i < $n; ++$i ) { + $aStart[$i] = $aStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1]; + } + } + + // Adjust headers left, right or centered + function SetHeaderAlign($aAlign) { + $this->iHeaderAlign=$aAlign; + } + + function Stroke($aImg,$aXLeft,$aYTop,$aXRight,$aYBottom,$aUseTextHeight=false) { + + if( !$this->iShow ) return; + + $txt = new TextProperty(); + $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + $txt->SetColor($this->iFontColor); + $txt->SetAlign($this->iHeaderAlign,'top'); + $n=count($this->iTitles); + + if( $n == 0 ) + return; + + $x = $aXLeft; + $h = $this->iHeight; + $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ; + + if( $h < 0 ) { + JpGraphError::RaiseL(6001); + //('Internal error. Height for ActivityTitles is < 0'); + } + + $aImg->SetLineWeight(1); + // Set background color + $aImg->SetColor($this->iBackgroundColor); + $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1); + + if( $this->iStyle == 1 ) { + // Make a 3D effect + $aImg->SetColor('white'); + $aImg->Line($aXLeft,$yTop+1,$aXRight,$yTop+1); + } + + for($i=0; $i < $n; ++$i ) { + if( $this->iStyle == 1 ) { + // Make a 3D effect + $aImg->SetColor('white'); + $aImg->Line($x+1,$yTop,$x+1,$aYBottom); + } + $x += $this->iLeftColMargin; + $txt->Set($this->iTitles[$i]); + + // Adjust the text anchor position according to the choosen alignment + $xp = $x; + if( $this->iHeaderAlign == 'center' ) { + $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2; + } + elseif( $this->iHeaderAlign == 'right' ) { + $xp = $x +$this->iWidth[$i]-$this->iRightColMargin; + } + + $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin); + $x += $this->iWidth[$i]; + if( $i < $n-1 ) { + $aImg->SetColor($this->iColor); + $aImg->Line($x,$yTop,$x,$aYBottom); + } + } + + $aImg->SetColor($this->iColor); + $aImg->Line($aXLeft,$yTop, $aXRight,$yTop); + + // Stroke vertical column dividers + $cols=array(); + $this->GetColStart($aImg,$cols); + $n=count($cols); + for( $i=1; $i < $n; ++$i ) { + $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i], + $aImg->height - $aImg->bottom_margin); + } + } +} + + +//=================================================== +// CLASS GanttGraph +// Description: Main class to handle gantt graphs +//=================================================== +class GanttGraph extends Graph { + public $scale; // Public accessible + public $hgrid=null; + private $iObj=array(); // Gantt objects + private $iLabelHMarginFactor=0.2; // 10% margin on each side of the labels + private $iLabelVMarginFactor=0.4; // 40% margin on top and bottom of label + private $iLayout=GANTT_FROMTOP; // Could also be GANTT_EVEN + private $iSimpleFont = FF_FONT1,$iSimpleFontSize=11; + private $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red'; + private $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen'; + private $iSimpleProgressStyle=GANTT_SOLID; + private $iZoomFactor = 1.0; + //--------------- + // CONSTRUCTOR + // Create a new gantt graph + function __construct($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) { + + // Backward compatibility + if( $aWidth == -1 ) $aWidth=0; + if( $aHeight == -1 ) $aHeight=0; + + if( $aWidth< 0 || $aHeight < 0 ) { + JpgraphError::RaiseL(6002); + //("You can't specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension."); + } + parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline); + $this->scale = new GanttScale($this->img); + + // Default margins + $this->img->SetMargin(15,17,25,15); + + $this->hgrid = new HorizontalGridLine(); + + $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY); + $this->SetBox(); + } + + //--------------- + // PUBLIC METHODS + + // + + function SetSimpleFont($aFont,$aSize) { + $this->iSimpleFont = $aFont; + $this->iSimpleFontSize = $aSize; + } + + function SetSimpleStyle($aBand,$aColor,$aBkgColor) { + $this->iSimpleStyle = $aBand; + $this->iSimpleColor = $aColor; + $this->iSimpleBkgColor = $aBkgColor; + } + + // A utility function to help create basic Gantt charts + function CreateSimple($data,$constrains=array(),$progress=array()) { + $num = count($data); + for( $i=0; $i < $num; ++$i) { + switch( $data[$i][1] ) { + case ACTYPE_GROUP: + // Create a slightly smaller height bar since the + // "wings" at the end will make it look taller + $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',8); + $a->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize); + $a->rightMark->Show(); + $a->rightMark->SetType(MARK_RIGHTTRIANGLE); + $a->rightMark->SetWidth(8); + $a->rightMark->SetColor('black'); + $a->rightMark->SetFillColor('black'); + + $a->leftMark->Show(); + $a->leftMark->SetType(MARK_LEFTTRIANGLE); + $a->leftMark->SetWidth(8); + $a->leftMark->SetColor('black'); + $a->leftMark->SetFillColor('black'); + + $a->SetPattern(BAND_SOLID,'black'); + $csimpos = 6; + break; + + case ACTYPE_NORMAL: + $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10); + $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); + $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor); + $a->SetFillColor($this->iSimpleBkgColor); + // Check if this activity should have a constrain line + $n = count($constrains); + for( $j=0; $j < $n; ++$j ) { + if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) { + JpGraphError::RaiseL(6003,$j); + //("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)"); + } + if( $constrains[$j][0]==$data[$i][0] ) { + $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID); + } + } + + // Check if this activity have a progress bar + $n = count($progress); + for( $j=0; $j < $n; ++$j ) { + + if( empty($progress[$j]) || (count($progress[$j]) != 2) ) { + JpGraphError::RaiseL(6004,$j); + //("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)"); + } + if( $progress[$j][0]==$data[$i][0] ) { + $a->progress->Set($progress[$j][1]); + $a->progress->SetPattern($this->iSimpleProgressStyle, + $this->iSimpleProgressColor); + $a->progress->SetFillColor($this->iSimpleProgressBkgColor); + //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]); + break; + } + } + $csimpos = 6; + break; + + case ACTYPE_MILESTONE: + $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]); + $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); + $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); + $csimpos = 5; + break; + default: + die('Unknown activity type'); + break; + } + + // Setup caption + $a->caption->Set($data[$i][$csimpos-1]); + + // Check if this activity should have a CSIM target�? + if( !empty($data[$i][$csimpos]) ) { + $a->SetCSIMTarget($data[$i][$csimpos]); + $a->SetCSIMAlt($data[$i][$csimpos+1]); + } + if( !empty($data[$i][$csimpos+2]) ) { + $a->title->SetCSIMTarget($data[$i][$csimpos+2]); + $a->title->SetCSIMAlt($data[$i][$csimpos+3]); + } + + $this->Add($a); + } + } + + // Set user specified scale zoom factor when auto sizing is used + function SetZoomFactor($aZoom) { + $this->iZoomFactor = $aZoom; + } + + + // Set what headers should be shown + function ShowHeaders($aFlg) { + $this->scale->ShowHeaders($aFlg); + } + + // Specify the fraction of the font height that should be added + // as vertical margin + function SetLabelVMarginFactor($aVal) { + $this->iLabelVMarginFactor = $aVal; + } + + // Synonym to the method above + function SetVMarginFactor($aVal) { + $this->iLabelVMarginFactor = $aVal; + } + + + // Add a new Gantt object + function Add($aObject) { + if( is_array($aObject) && count($aObject) > 0 ) { + $cl = $aObject[0]; + if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) { + $this->AddIcon($aObject); + } + elseif( class_exists('Text',false) && ($cl instanceof Text) ) { + $this->AddText($aObject); + } + else { + $n = count($aObject); + for($i=0; $i < $n; ++$i) + $this->iObj[] = $aObject[$i]; + } + } + else { + if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) { + $this->AddIcon($aObject); + } + elseif( class_exists('Text',false) && ($aObject instanceof Text) ) { + $this->AddText($aObject); + } + else { + $this->iObj[] = $aObject; + } + } + } + + function StrokeTexts() { + // Stroke any user added text objects + if( $this->texts != null ) { + $n = count($this->texts); + for($i=0; $i < $n; ++$i) { + if( $this->texts[$i]->iScalePosX !== null && $this->texts[$i]->iScalePosY !== null ) { + $x = $this->scale->TranslateDate($this->texts[$i]->iScalePosX); + $y = $this->scale->TranslateVertPos($this->texts[$i]->iScalePosY); + $y -= $this->scale->GetVertSpacing()/2; + } + else { + $x = $y = null; + } + $this->texts[$i]->Stroke($this->img,$x,$y); + } + } + } + + // Override inherit method from Graph and give a warning message + function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) { + JpGraphError::RaiseL(6005); + //("SetScale() is not meaningfull with Gantt charts."); + } + + // Specify the date range for Gantt graphs (if this is not set it will be + // automtically determined from the input data) + function SetDateRange($aStart,$aEnd) { + // Adjust the start and end so that the indicate the + // begining and end of respective start and end days + if( strpos($aStart,':') === false ) + $aStart = date('Y-m-d 00:00',strtotime($aStart)); + if( strpos($aEnd,':') === false ) + $aEnd = date('Y-m-d 23:59',strtotime($aEnd)); + $this->scale->SetRange($aStart,$aEnd); + } + + // Get the maximum width of the activity titles columns for the bars + // The name is lightly misleading since we from now on can have + // multiple columns in the label section. When this was first written + // it only supported a single label, hence the name. + function GetMaxLabelWidth() { + $m=10; + if( $this->iObj != null ) { + $marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin; + $n = count($this->iObj); + for($i=0; $i < $n; ++$i) { + if( !empty($this->iObj[$i]->title) ) { + if( $this->iObj[$i]->title->HasTabs() ) { + list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true); + $m=max($m,$tot); + } + else + $m=max($m,$this->iObj[$i]->title->GetWidth($this->img)); + } + } + } + return $m; + } + + // Get the maximum height of the titles for the bars + function GetMaxLabelHeight() { + $m=10; + if( $this->iObj != null ) { + $n = count($this->iObj); + // We can not include the title of GnttVLine since that title is stroked at the bottom + // of the Gantt bar and not in the activity title columns + for($i=0; $i < $n; ++$i) { + if( !empty($this->iObj[$i]->title) && !($this->iObj[$i] instanceof GanttVLine) ) { + $m=max($m,$this->iObj[$i]->title->GetHeight($this->img)); + } + } + } + return $m; + } + + function GetMaxBarAbsHeight() { + $m=0; + if( $this->iObj != null ) { + $m = $this->iObj[0]->GetAbsHeight($this->img); + $n = count($this->iObj); + for($i=1; $i < $n; ++$i) { + $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img)); + } + } + return $m; + } + + // Get the maximum used line number (vertical position) for bars + function GetBarMaxLineNumber() { + $m=1; + if( $this->iObj != null ) { + $m = $this->iObj[0]->GetLineNbr(); + $n = count($this->iObj); + for($i=1; $i < $n; ++$i) { + $m=max($m,$this->iObj[$i]->GetLineNbr()); + } + } + return $m; + } + + // Get the minumum and maximum used dates for all bars + function GetBarMinMax() { + $start = 0 ; + $n = count($this->iObj); + while( $start < $n && $this->iObj[$start]->GetMaxDate() === false ) + ++$start; + if( $start >= $n ) { + JpgraphError::RaiseL(6006); + //('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]'); + } + + $max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate()); + $min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate()); + + for($i=$start+1; $i < $n; ++$i) { + $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate()); + if( $rmax != false ) + $max=Max($max,$rmax); + $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate()); + if( $rmin != false ) + $min=Min($min,$rmin); + } + $minDate = date("Y-m-d",$min); + $min = strtotime($minDate); + $maxDate = date("Y-m-d 23:59",$max); + $max = strtotime($maxDate); + return array($min,$max); + } + + // Create a new auto sized canvas if the user hasn't specified a size + // The size is determined by what scale the user has choosen and hence + // the minimum width needed to display the headers. Some margins are + // also added to make it better looking. + function AutoSize() { + + if( $this->img->img == null ) { + // The predefined left, right, top, bottom margins. + // Note that the top margin might incease depending on + // the title. + $hadj = $vadj = 0; + if( $this->doshadow ) { + $hadj = $this->shadow_width; + $vadj = $this->shadow_width+5; + } + + $lm = $this->img->left_margin; + $rm = $this->img->right_margin +$hadj; + $rm += 2 ; + $tm = $this->img->top_margin; + $bm = $this->img->bottom_margin + $vadj; + $bm += 2; + + // If there are any added GanttVLine we must make sure that the + // bottom margin is wide enough to hold a title. + $n = count($this->iObj); + for($i=0; $i < $n; ++$i) { + if( $this->iObj[$i] instanceof GanttVLine ) { + $bm = max($bm,$this->iObj[$i]->title->GetHeight($this->img)+10); + } + } + + // First find out the height + $n=$this->GetBarMaxLineNumber()+1; + $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); + $height=$n*((1+$this->iLabelVMarginFactor)*$m); + + // Add the height of the scale titles + $h=$this->scale->GetHeaderHeight(); + $height += $h; + + // Calculate the top margin needed for title and subtitle + if( $this->title->t != "" ) { + $tm += $this->title->GetFontHeight($this->img); + } + if( $this->subtitle->t != "" ) { + $tm += $this->subtitle->GetFontHeight($this->img); + } + + // ...and then take the bottom and top plot margins into account + $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin; + // Now find the minimum width for the chart required + + // If day scale or smaller is shown then we use the day font width + // as the base size unit. + // If only weeks or above is displayed we use a modified unit to + // get a smaller image. + if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) { + // Add 2 pixel margin on each side + $fw=$this->scale->day->GetFontWidth($this->img)+4; + } + elseif( $this->scale->IsDisplayWeek() ) { + $fw = 8; + } + elseif( $this->scale->IsDisplayMonth() ) { + $fw = 4; + } + else { + $fw = 2; + } + + $nd=$this->scale->GetNumberOfDays(); + + if( $this->scale->IsDisplayDay() ) { + // If the days are displayed we also need to figure out + // how much space each day's title will require. + switch( $this->scale->day->iStyle ) { + case DAYSTYLE_LONG : + $txt = "Monday"; + break; + case DAYSTYLE_LONGDAYDATE1 : + $txt = "Monday 23 Jun"; + break; + case DAYSTYLE_LONGDAYDATE2 : + $txt = "Monday 23 Jun 2003"; + break; + case DAYSTYLE_SHORT : + $txt = "Mon"; + break; + case DAYSTYLE_SHORTDAYDATE1 : + $txt = "Mon 23/6"; + break; + case DAYSTYLE_SHORTDAYDATE2 : + $txt = "Mon 23 Jun"; + break; + case DAYSTYLE_SHORTDAYDATE3 : + $txt = "Mon 23"; + break; + case DAYSTYLE_SHORTDATE1 : + $txt = "23/6"; + break; + case DAYSTYLE_SHORTDATE2 : + $txt = "23 Jun"; + break; + case DAYSTYLE_SHORTDATE3 : + $txt = "Mon 23"; + break; + case DAYSTYLE_SHORTDATE4 : + $txt = "88"; + break; + case DAYSTYLE_CUSTOM : + $txt = date($this->scale->day->iLabelFormStr,strtotime('2003-12-20 18:00')); + break; + case DAYSTYLE_ONELETTER : + default: + $txt = "M"; + break; + } + $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6; + } + + // If we have hours enabled we must make sure that each day has enough + // space to fit the number of hours to be displayed. + if( $this->scale->IsDisplayHour() ) { + // Depending on what format the user has choose we need different amount + // of space. We therefore create a typical string for the choosen format + // and determine the length of that string. + switch( $this->scale->hour->iStyle ) { + case HOURSTYLE_HMAMPM: + $txt = '12:00pm'; + break; + case HOURSTYLE_H24: + // 13 + $txt = '24'; + break; + case HOURSTYLE_HAMPM: + $txt = '12pm'; + break; + case HOURSTYLE_CUSTOM: + $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00')); + break; + case HOURSTYLE_HM24: + default: + $txt = '24:00'; + break; + } + + $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6; + $mw = $hfw; + if( $this->scale->IsDisplayMinute() ) { + // Depending on what format the user has choose we need different amount + // of space. We therefore create a typical string for the choosen format + // and determine the length of that string. + switch( $this->scale->minute->iStyle ) { + case HOURSTYLE_CUSTOM: + $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); + break; + case MINUTESTYLE_MM: + default: + $txt2 = '15'; + break; + } + + $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6; + $n2 = ceil(60 / $this->scale->minute->GetIntervall() ); + $mw = $n2 * $mfw; + } + $hfw = $hfw < $mw ? $mw : $hfw ; + $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) ); + $hw = $n * $hfw; + $fw = $fw < $hw ? $hw : $fw ; + } + + // We need to repeat this code block here as well. + // THIS iS NOT A MISTAKE ! + // We really need it since we need to adjust for minutes both in the case + // where hour scale is shown and when it is not shown. + + if( $this->scale->IsDisplayMinute() ) { + // Depending on what format the user has choose we need different amount + // of space. We therefore create a typical string for the choosen format + // and determine the length of that string. + switch( $this->scale->minute->iStyle ) { + case HOURSTYLE_CUSTOM: + $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); + break; + case MINUTESTYLE_MM: + default: + $txt = '15'; + break; + } + + $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6; + $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) ); + $mw = $n * $mfw; + $fw = $fw < $mw ? $mw : $fw ; + } + + // If we display week we must make sure that 7*$fw is enough + // to fit up to 10 characters of the week font (if the week is enabled) + if( $this->scale->IsDisplayWeek() ) { + // Depending on what format the user has choose we need different amount + // of space + $fsw = strlen($this->scale->week->iLabelFormStr); + if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { + $fsw += 8; + } + elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) { + $fsw += 7; + } + else { + $fsw += 4; + } + + $ww = $fsw*$this->scale->week->GetFontWidth($this->img); + if( 7*$fw < $ww ) { + $fw = ceil($ww/7); + } + } + + if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() && + !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || + $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) { + // If we don't display the individual days we can shrink the + // scale a little bit. This is a little bit pragmatic at the + // moment and should be re-written to take into account + // a) What scales exactly are shown and + // b) what format do they use so we know how wide we need to + // make each scale text space at minimum. + $fw /= 2; + if( !$this->scale->IsDisplayWeek() ) { + $fw /= 1.8; + } + } + + $cw = $this->GetMaxActInfoColWidth() ; + $this->scale->actinfo->SetMinColWidth($cw); + if( $this->img->width <= 0 ) { + // Now determine the width for the activity titles column + + // Firdst find out the maximum width of each object column + $titlewidth = max(max($this->GetMaxLabelWidth(), + $this->scale->tableTitle->GetWidth($this->img)), + $this->scale->actinfo->GetWidth($this->img)); + + // Add the width of the vertivcal divider line + $titlewidth += $this->scale->divider->iWeight*2; + + // Adjust the width by the user specified zoom factor + $fw *= $this->iZoomFactor; + + // Now get the total width taking + // titlewidth, left and rigt margin, dayfont size + // into account + $width = $titlewidth + $nd*$fw + $lm+$rm; + } + else { + $width = $this->img->width; + } + + $width = round($width); + $height = round($height); + // Make a sanity check on image size + if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) { + JpgraphError::RaiseL(6007,$width,$height); + //("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."); + } + $this->img->CreateImgCanvas($width,$height); + $this->img->SetMargin($lm,$rm,$tm,$bm); + } + } + + // Return an array width the maximum width for each activity + // column. This is used when we autosize the columns where we need + // to find out the maximum width of each column. In order to do that we + // must walk through all the objects, sigh... + function GetMaxActInfoColWidth() { + $n = count($this->iObj); + if( $n == 0 ) return; + $w = array(); + $m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin; + + for( $i=0; $i < $n; ++$i ) { + $tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m); + $nn = count($tmp); + for( $j=0; $j < $nn; ++$j ) { + if( empty($w[$j]) ) + $w[$j] = $tmp[$j]; + else + $w[$j] = max($w[$j],$tmp[$j]); + } + } + return $w; + } + + // Stroke the gantt chart + function Stroke($aStrokeFileName="") { + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // a best we can. Therefor you will see a lot of tests !$_csim in the + // code below. + $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); + + // Should we autoscale dates? + + if( !$this->scale->IsRangeSet() ) { + list($min,$max) = $this->GetBarMinMax(); + $this->scale->SetRange($min,$max); + } + + $this->scale->AdjustStartEndDay(); + + // Check if we should autoscale the image + $this->AutoSize(); + + // Should we start from the top or just spread the bars out even over the + // available height + $this->scale->SetVertLayout($this->iLayout); + if( $this->iLayout == GANTT_FROMTOP ) { + $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); + $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor)); + } + // If it hasn't been set find out the maximum line number + if( $this->scale->iVertLines == -1 ) + $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1; + + $maxwidth=max($this->scale->actinfo->GetWidth($this->img), + max($this->GetMaxLabelWidth(), + $this->scale->tableTitle->GetWidth($this->img))); + + $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor)); + + if( !$_csim ) { + $this->StrokePlotArea(); + if( $this->iIconDepth == DEPTH_BACK ) { + $this->StrokeIcons(); + } + } + + $this->scale->Stroke(); + + if( !$_csim ) { + // Due to a minor off by 1 bug we need to temporarily adjust the margin + $this->img->right_margin--; + $this->StrokePlotBox(); + $this->img->right_margin++; + } + + // Stroke Grid line + $this->hgrid->Stroke($this->img,$this->scale); + + $n = count($this->iObj); + for($i=0; $i < $n; ++$i) { + //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2)); + $this->iObj[$i]->Stroke($this->img,$this->scale); + } + + $this->StrokeTitles(); + + if( !$_csim ) { + $this->StrokeConstrains(); + $this->footer->Stroke($this->img); + + + if( $this->iIconDepth == DEPTH_FRONT) { + $this->StrokeIcons(); + } + + // Stroke all added user texts + $this->StrokeTexts(); + + // Should we do any final image transformation + if( $this->iImgTrans ) { + if( !class_exists('ImgTrans',false) ) { + require_once('jpgraph_imgtrans.php'); + } + + $tform = new ImgTrans($this->img->img); + $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, + $this->iImgTransDirection,$this->iImgTransHighQ, + $this->iImgTransMinSize,$this->iImgTransFillColor, + $this->iImgTransBorder); + } + + + // If the filename is given as the special "__handle" + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, + $aStrokeFileName); + } + } + } + + function StrokeConstrains() { + $n = count($this->iObj); + + // Stroke all constrains + for($i=0; $i < $n; ++$i) { + + // Some gantt objects may not have constraints associated with them + // for example we can add IconPlots which doesn't have this property. + if( empty($this->iObj[$i]->constraints) ) continue; + + $numConstrains = count($this->iObj[$i]->constraints); + + for( $k = 0; $k < $numConstrains; $k++ ) { + $vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow; + if( $vpos >= 0 ) { + $c1 = $this->iObj[$i]->iConstrainPos; + + // Find out which object is on the target row + $targetobj = -1; + for( $j=0; $j < $n && $targetobj == -1; ++$j ) { + if( $this->iObj[$j]->iVPos == $vpos ) { + $targetobj = $j; + } + } + if( $targetobj == -1 ) { + JpGraphError::RaiseL(6008,$this->iObj[$i]->iVPos,$vpos); + //('You have specifed a constrain from row='.$this->iObj[$i]->iVPos.' to row='.$vpos.' which does not have any activity.'); + } + $c2 = $this->iObj[$targetobj]->iConstrainPos; + if( count($c1) == 4 && count($c2 ) == 4) { + switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) { + case CONSTRAIN_ENDSTART: + if( $c1[1] < $c2[1] ) { + $link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]); + } + else { + $link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]); + } + $link->SetPath(3); + break; + case CONSTRAIN_STARTEND: + if( $c1[1] < $c2[1] ) { + $link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]); + } + else { + $link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]); + } + $link->SetPath(0); + break; + case CONSTRAIN_ENDEND: + if( $c1[1] < $c2[1] ) { + $link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]); + } + else { + $link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]); + } + $link->SetPath(1); + break; + case CONSTRAIN_STARTSTART: + if( $c1[1] < $c2[1] ) { + $link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]); + } + else { + $link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]); + } + $link->SetPath(3); + break; + default: + JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos); + //('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos); + break; + } + + $link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor); + $link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize, + $this->iObj[$i]->constraints[$k]->iConstrainArrowType); + + $link->Stroke($this->img); + } + } + } + } + } + + function GetCSIMAreas() { + if( !$this->iHasStroked ) + $this->Stroke(_CSIM_SPECIALFILE); + + $csim = $this->title->GetCSIMAreas(); + $csim .= $this->subtitle->GetCSIMAreas(); + $csim .= $this->subsubtitle->GetCSIMAreas(); + + $n = count($this->iObj); + for( $i=$n-1; $i >= 0; --$i ) + $csim .= $this->iObj[$i]->GetCSIMArea(); + return $csim; + } +} + +//=================================================== +// CLASS PredefIcons +// Description: Predefined icons for use with Gantt charts +//=================================================== +define('GICON_WARNINGRED',0); +define('GICON_TEXT',1); +define('GICON_ENDCONS',2); +define('GICON_MAIL',3); +define('GICON_STARTCONS',4); +define('GICON_CALC',5); +define('GICON_MAGNIFIER',6); +define('GICON_LOCK',7); +define('GICON_STOP',8); +define('GICON_WARNINGYELLOW',9); +define('GICON_FOLDEROPEN',10); +define('GICON_FOLDER',11); +define('GICON_TEXTIMPORTANT',12); + +class PredefIcons { + private $iBuiltinIcon = null, $iLen = -1 ; + + function GetLen() { + return $this->iLen ; + } + + function GetImg($aIdx) { + if( $aIdx < 0 || $aIdx >= $this->iLen ) { + JpGraphError::RaiseL(6010,$aIdx); + //('Illegal icon index for Gantt builtin icon ['.$aIdx.']'); + } + return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1])); + } + + function __construct() { + //========================================================== + // warning.png + //========================================================== + $this->iBuiltinIcon[0][0]= 1043 ; + $this->iBuiltinIcon[0][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. + 'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'. + '0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'. + '5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'. + 'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'. + 'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'. + '/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'. + 'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'. + 'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'. + 'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'. + 'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'. + 'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'. + 'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'. + 'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ; + + //========================================================== + // edit.png + //========================================================== + $this->iBuiltinIcon[1][0]= 959 ; + $this->iBuiltinIcon[1][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'. + 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'. + 'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'. + 'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'. + 'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'. + 'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'. + 'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'. + 'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'. + 'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'. + 'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'. + 'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'. + 'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'. + 'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ; + + //========================================================== + // endconstrain.png + //========================================================== + $this->iBuiltinIcon[2][0]= 666 ; + $this->iBuiltinIcon[2][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. + 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'. + 'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'. + 'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'. + 'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'. + '7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'. + '7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'. + 'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'. + 'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ; + + //========================================================== + // mail.png + //========================================================== + $this->iBuiltinIcon[3][0]= 1122 ; + $this->iBuiltinIcon[3][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. + 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'. + 'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'. + 'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'. + 'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'. + '3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'. + '7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'. + 'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'. + 'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'. + '6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'. + 'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'. + 'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'. + 'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'. + 'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'. + 'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ; + + //========================================================== + // startconstrain.png + //========================================================== + $this->iBuiltinIcon[4][0]= 725 ; + $this->iBuiltinIcon[4][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. + 'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'. + 'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'. + 'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'. + 'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'. + '5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'. + 'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'. + 'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'. + '5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'. + 'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ; + + //========================================================== + // calc.png + //========================================================== + $this->iBuiltinIcon[5][0]= 589 ; + $this->iBuiltinIcon[5][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'. + 'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'. + 'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'. + '3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'. + 'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'. + 'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'. + 'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'. + 'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ; + + //========================================================== + // mag.png + //========================================================== + $this->iBuiltinIcon[6][0]= 1415 ; + $this->iBuiltinIcon[6][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. + 'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'. + '0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'. + 'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'. + 'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'. + 'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'. + '8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'. + 'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'. + '/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'. + 'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'. + 'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'. + 'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'. + 'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'. + 'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'. + 'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'. + 'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'. + 'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'. + 'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'. + 'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ; + + //========================================================== + // lock.png + //========================================================== + $this->iBuiltinIcon[7][0]= 963 ; + $this->iBuiltinIcon[7][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. + 'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'. + 'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'. + 'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'. + 'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'. + 'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'. + 'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'. + 'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'. + 'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'. + 'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'. + 'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'. + '2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'. + 'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ; + + //========================================================== + // stop.png + //========================================================== + $this->iBuiltinIcon[8][0]= 889 ; + $this->iBuiltinIcon[8][1]= + 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. + 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'. + 'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'. + 'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'. + 'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'. + 'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'. + 'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'. + 'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'. + 'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'. + 'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'. + 'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'. + 'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ; + + //========================================================== + // error.png + //========================================================== + $this->iBuiltinIcon[9][0]= 541 ; + $this->iBuiltinIcon[9][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. + 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. + 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'. + '2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'. + 'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'. + 'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'. + 'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'. + 'iOsCHgAAAABJRU5ErkJggg==' ; + + //========================================================== + // openfolder.png + //========================================================== + $this->iBuiltinIcon[10][0]= 2040 ; + $this->iBuiltinIcon[10][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'. + 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'. + 'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'. + 'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'. + 'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'. + 'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'. + '9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'. + 'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'. + '4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'. + 'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'. + 'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'. + 'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'. + 'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'. + 'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'. + 'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'. + 'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'. + 'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'. + 'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'. + 'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'. + 'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'. + 'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'. + 'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'. + 'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'. + 'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'. + '+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'. + '4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'. + 'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'. + 'dBntAAAAAElFTkSuQmCC' ; + + //========================================================== + // folder.png + //========================================================== + $this->iBuiltinIcon[11][0]= 1824 ; + $this->iBuiltinIcon[11][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. + 'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'. + '6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'. + 'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'. + '309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'. + 'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'. + 'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'. + '3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'. + 'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'. + 'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'. + '/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'. + '4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'. + 'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'. + 'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'. + 'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'. + 'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'. + 'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'. + 'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'. + 'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'. + 'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'. + 'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'. + 'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'. + 'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'. + 'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'. + 'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ; + + //========================================================== + // file_important.png + //========================================================== + $this->iBuiltinIcon[12][0]= 1785 ; + $this->iBuiltinIcon[12][1]= + 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. + 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'. + 'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'. + 'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'. + '1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'. + 's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'. + 'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'. + 'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'. + 'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'. + '73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'. + '4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'. + 'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'. + 'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'. + 'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'. + 'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'. + 't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'. + '9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'. + 'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'. + 'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'. + 'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'. + '8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'. + 'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'. + 'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'. + '7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ; + + $this->iLen = count($this->iBuiltinIcon); + } +} + +//=================================================== +// Global cache for builtin images +//=================================================== +$_gPredefIcons = new PredefIcons(); + +//=================================================== +// CLASS IconImage +// Description: Holds properties for an icon image +//=================================================== +class IconImage { + private $iGDImage=null; + private $iWidth,$iHeight; + private $ixalign='left',$iyalign='center'; + private $iScale=1.0; + + function __construct($aIcon,$aScale=1) { + GLOBAL $_gPredefIcons ; + if( is_string($aIcon) ) { + $this->iGDImage = Graph::LoadBkgImage('',$aIcon); + } + elseif( is_integer($aIcon) ) { + // Builtin image + $this->iGDImage = $_gPredefIcons->GetImg($aIcon); + } + else { + JpGraphError::RaiseL(6011); + //('Argument to IconImage must be string or integer'); + } + $this->iScale = $aScale; + $this->iWidth = Image::GetWidth($this->iGDImage); + $this->iHeight = Image::GetHeight($this->iGDImage); + } + + function GetWidth() { + return round($this->iScale*$this->iWidth); + } + + function GetHeight() { + return round($this->iScale*$this->iHeight); + } + + function SetAlign($aX='left',$aY='center') { + $this->ixalign = $aX; + $this->iyalign = $aY; + } + + function Stroke($aImg,$x,$y) { + + if( $this->ixalign == 'right' ) { + $x -= $this->iWidth; + } + elseif( $this->ixalign == 'center' ) { + $x -= round($this->iWidth/2*$this->iScale); + } + + if( $this->iyalign == 'bottom' ) { + $y -= $this->iHeight; + } + elseif( $this->iyalign == 'center' ) { + $y -= round($this->iHeight/2*$this->iScale); + } + + $aImg->Copy($this->iGDImage, + $x,$y,0,0, + round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale), + $this->iWidth,$this->iHeight); + } +} + + +//=================================================== +// CLASS TextProperty +// Description: Holds properties for a text +//=================================================== +class TextProperty { + public $iShow=true; + public $csimtarget='',$csimwintarget='',$csimalt=''; + private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10; + private $iFontArray=array(); + private $iColor="black"; + private $iText=""; + private $iHAlign="left",$iVAlign="bottom"; + + //--------------- + // CONSTRUCTOR + function __construct($aTxt='') { + $this->iText = $aTxt; + } + + //--------------- + // PUBLIC METHODS + function Set($aTxt) { + $this->iText = $aTxt; + } + + function SetCSIMTarget($aTarget,$aAltText='',$aWinTarget='') { + if( is_string($aTarget) ) + $aTarget = array($aTarget); + $this->csimtarget=$aTarget; + + if( is_string($aWinTarget) ) + $aWinTarget = array($aWinTarget); + $this->csimwintarget=$aWinTarget; + + if( is_string($aAltText) ) + $aAltText = array($aAltText); + $this->csimalt=$aAltText; + + } + + function SetCSIMAlt($aAltText) { + if( is_string($aAltText) ) + $aAltText = array($aAltText); + $this->csimalt=$aAltText; + } + + // Set text color + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function HasTabs() { + if( is_string($this->iText) ) { + return substr_count($this->iText,"\t") > 0; + } + elseif( is_array($this->iText) ) { + return false; + } + } + + // Get number of tabs in string + function GetNbrTabs() { + if( is_string($this->iText) ) { + return substr_count($this->iText,"\t") ; + } + else{ + return 0; + } + } + + // Set alignment + function Align($aHAlign,$aVAlign="bottom") { + $this->iHAlign=$aHAlign; + $this->iVAlign=$aVAlign; + } + + // Synonym + function SetAlign($aHAlign,$aVAlign="bottom") { + $this->iHAlign=$aHAlign; + $this->iVAlign=$aVAlign; + } + + // Specify font + function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { + $this->iFFamily = $aFFamily; + $this->iFStyle = $aFStyle; + $this->iFSize = $aFSize; + } + + function SetColumnFonts($aFontArray) { + if( !is_array($aFontArray) || count($aFontArray[0]) != 3 ) { + JpGraphError::RaiseL(6033); + // 'Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)' + } + $this->iFontArray = $aFontArray; + } + + + function IsColumns() { + return is_array($this->iText) ; + } + + // Get width of text. If text contains several columns separated by + // tabs then return both the total width as well as an array with a + // width for each column. + function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) { + $extra_margin=4; + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + if( is_string($this->iText) ) { + if( strlen($this->iText) == 0 ) return 0; + $tmp = preg_split('/\t/',$this->iText); + if( count($tmp) <= 1 || !$aUseTabs ) { + $w = $aImg->GetTextWidth($this->iText); + return $w + 2*$extra_margin; + } + else { + $tot=0; + $n = count($tmp); + for($i=0; $i < $n; ++$i) { + $res[$i] = $aImg->GetTextWidth($tmp[$i]); + $tot += $res[$i]*$aTabExtraMargin; + } + return array(round($tot),$res); + } + } + elseif( is_object($this->iText) ) { + // A single icon + return $this->iText->GetWidth()+2*$extra_margin; + } + elseif( is_array($this->iText) ) { + // Must be an array of texts. In this case we return the sum of the + // length + a fixed margin of 4 pixels on each text string + $n = count($this->iText); + $nf = count($this->iFontArray); + for( $i=0, $w=0; $i < $n; ++$i ) { + if( $i < $nf ) { + $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); + } + else { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + } + $tmp = $this->iText[$i]; + if( is_string($tmp) ) { + $w += $aImg->GetTextWidth($tmp)+$extra_margin; + } + else { + if( is_object($tmp) === false ) { + JpGraphError::RaiseL(6012); + } + $w += $tmp->GetWidth()+$extra_margin; + } + } + return $w; + } + else { + JpGraphError::RaiseL(6012); + } + } + + // for the case where we have multiple columns this function returns the width of each + // column individually. If there is no columns just return the width of the single + // column as an array of one + function GetColWidth($aImg,$aMargin=0) { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + if( is_array($this->iText) ) { + $n = count($this->iText); + $nf = count($this->iFontArray); + for( $i=0, $w=array(); $i < $n; ++$i ) { + $tmp = $this->iText[$i]; + if( is_string($tmp) ) { + if( $i < $nf ) { + $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); + } + else { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + } + $w[$i] = $aImg->GetTextWidth($tmp)+$aMargin; + } + else { + if( is_object($tmp) === false ) { + JpGraphError::RaiseL(6012); + } + $w[$i] = $tmp->GetWidth()+$aMargin; + } + } + return $w; + } + else { + return array($this->GetWidth($aImg)); + } + } + + // Get total height of text + function GetHeight($aImg) { + $nf = count($this->iFontArray); + $maxheight = -1; + + if( $nf > 0 ) { + // We have to find out the largest font and take that one as the + // height of the row + for($i=0; $i < $nf; ++$i ) { + $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); + $height = $aImg->GetFontHeight(); + $maxheight = max($height,$maxheight); + } + } + + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + $height = $aImg->GetFontHeight(); + $maxheight = max($height,$maxheight); + return $maxheight; + } + + // Unhide/hide the text + function Show($aShow=true) { + $this->iShow=$aShow; + } + + // Stroke text at (x,y) coordinates. If the text contains tabs then the + // x parameter should be an array of positions to be used for each successive + // tab mark. If no array is supplied then the tabs will be ignored. + function Stroke($aImg,$aX,$aY) { + if( $this->iShow ) { + $aImg->SetColor($this->iColor); + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + $aImg->SetTextAlign($this->iHAlign,$this->iVAlign); + if( $this->GetNbrTabs() < 1 ) { + if( is_string($this->iText) ) { + if( is_array($aX) ) $aX=$aX[0]; + if( is_array($aY) ) $aY=$aY[0]; + $aImg->StrokeText($aX,$aY,$this->iText); + } + elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) { + $ax = is_array($aX) ; + $ay = is_array($aY) ; + if( $ax && $ay ) { + // Nothing; both are already arrays + } + elseif( $ax ) { + $aY = array_fill(0,$n,$aY); + } + elseif( $ay ) { + $aX = array_fill(0,$n,$aX); + } + else { + $aX = array_fill(0,$n,$aX); + $aY = array_fill(0,$n,$aY); + } + $n = min($n, count($aX) ) ; + $n = min($n, count($aY) ) ; + for($i=0; $i < $n; ++$i ) { + $tmp = $this->iText[$i]; + if( is_object($tmp) ) { + $tmp->Stroke($aImg,$aX[$i],$aY[$i]); + } + else { + if( $i < count($this->iFontArray) ) { + $font = $this->iFontArray[$i]; + $aImg->SetFont($font[0],$font[1],$font[2]); + } + else { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + } + $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp)); + } + } + } + } + else { + $tmp = preg_split('/\t/',$this->iText); + $n = min(count($tmp),count($aX)); + for($i=0; $i < $n; ++$i) { + if( $i < count($this->iFontArray) ) { + $font = $this->iFontArray[$i]; + $aImg->SetFont($font[0],$font[1],$font[2]); + } + else { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + } + $aImg->StrokeText($aX[$i],$aY,$tmp[$i]); + } + } + } + } +} + +//=================================================== +// CLASS HeaderProperty +// Description: Data encapsulating class to hold property +// for each type of the scale headers +//=================================================== +class HeaderProperty { + public $grid; + public $iShowLabels=true,$iShowGrid=true; + public $iTitleVertMargin=3,$iFFamily=FF_FONT0,$iFStyle=FS_NORMAL,$iFSize=8; + public $iStyle=0; + public $iFrameColor="black",$iFrameWeight=1; + public $iBackgroundColor="white"; + public $iWeekendBackgroundColor="lightgray",$iSundayTextColor="red"; // these are only used with day scale + public $iTextColor="black"; + public $iLabelFormStr="%d"; + public $iIntervall = 1; + + //--------------- + // CONSTRUCTOR + function __construct() { + $this->grid = new LineProperty(); + } + + //--------------- + // PUBLIC METHODS + function Show($aShow=true) { + $this->iShowLabels = $aShow; + } + + function SetIntervall($aInt) { + $this->iIntervall = $aInt; + } + + function SetInterval($aInt) { + $this->iIntervall = $aInt; + } + + function GetIntervall() { + return $this->iIntervall ; + } + + function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { + $this->iFFamily = $aFFamily; + $this->iFStyle = $aFStyle; + $this->iFSize = $aFSize; + } + + function SetFontColor($aColor) { + $this->iTextColor = $aColor; + } + + function GetFontHeight($aImg) { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + return $aImg->GetFontHeight(); + } + + function GetFontWidth($aImg) { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + return $aImg->GetFontWidth(); + } + + function GetStrWidth($aImg,$aStr) { + $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); + return $aImg->GetTextWidth($aStr); + } + + function SetStyle($aStyle) { + $this->iStyle = $aStyle; + } + + function SetBackgroundColor($aColor) { + $this->iBackgroundColor=$aColor; + } + + function SetFrameWeight($aWeight) { + $this->iFrameWeight=$aWeight; + } + + function SetFrameColor($aColor) { + $this->iFrameColor=$aColor; + } + + // Only used by day scale + function SetWeekendColor($aColor) { + $this->iWeekendBackgroundColor=$aColor; + } + + // Only used by day scale + function SetSundayFontColor($aColor) { + $this->iSundayTextColor=$aColor; + } + + function SetTitleVertMargin($aMargin) { + $this->iTitleVertMargin=$aMargin; + } + + function SetLabelFormatString($aStr) { + $this->iLabelFormStr=$aStr; + } + + function SetFormatString($aStr) { + $this->SetLabelFormatString($aStr); + } + + +} + +//=================================================== +// CLASS GanttScale +// Description: Responsible for calculating and showing +// the scale in a gantt chart. This includes providing methods for +// converting dates to position in the chart as well as stroking the +// date headers (days, week, etc). +//=================================================== +class GanttScale { + public $minute,$hour,$day,$week,$month,$year; + public $divider,$dividerh,$tableTitle; + public $iStartDate=-1,$iEndDate=-1; + // Number of gantt bar position (n.b not necessariliy the same as the number of bars) + // we could have on bar in position 1, and one bar in position 5 then there are two + // bars but the number of bar positions is 5 + public $actinfo; + public $iTopPlotMargin=10,$iBottomPlotMargin=15; + public $iVertLines=-1; + public $iVertHeaderSize=-1; + // The width of the labels (defaults to the widest of all labels) + private $iLabelWidth; + // Out image to stroke the scale to + private $iImg; + private $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black"; + private $iTableHeaderFrameWeight=1; + private $iAvailableHeight=-1,$iVertSpacing=-1; + private $iDateLocale; + private $iVertLayout=GANTT_EVEN; + private $iUsePlotWeekendBackground=true; + private $iWeekStart = 1; // Default to have weekends start on Monday + + //--------------- + // CONSTRUCTOR + function __construct($aImg) { + $this->iImg = $aImg; + $this->iDateLocale = new DateLocale(); + + $this->minute = new HeaderProperty(); + $this->minute->SetIntervall(15); + $this->minute->SetLabelFormatString('i'); + $this->minute->SetFont(FF_FONT0); + $this->minute->grid->SetColor("gray"); + + $this->hour = new HeaderProperty(); + $this->hour->SetFont(FF_FONT0); + $this->hour->SetIntervall(6); + $this->hour->SetStyle(HOURSTYLE_HM24); + $this->hour->SetLabelFormatString('H:i'); + $this->hour->grid->SetColor("gray"); + + $this->day = new HeaderProperty(); + $this->day->grid->SetColor("gray"); + $this->day->SetLabelFormatString('l'); + + $this->week = new HeaderProperty(); + $this->week->SetLabelFormatString("w%d"); + $this->week->SetFont(FF_FONT1); + + $this->month = new HeaderProperty(); + $this->month->SetFont(FF_FONT1,FS_BOLD); + + $this->year = new HeaderProperty(); + $this->year->SetFont(FF_FONT1,FS_BOLD); + + $this->divider=new LineProperty(); + $this->dividerh=new LineProperty(); + $this->dividerh->SetWeight(2); + $this->divider->SetWeight(6); + $this->divider->SetColor('gray'); + $this->divider->SetStyle('fancy'); + + $this->tableTitle=new TextProperty(); + $this->tableTitle->Show(false); + $this->actinfo = new GanttActivityInfo(); + } + + //--------------- + // PUBLIC METHODS + // Specify what headers should be visible + function ShowHeaders($aFlg) { + $this->day->Show($aFlg & GANTT_HDAY); + $this->week->Show($aFlg & GANTT_HWEEK); + $this->month->Show($aFlg & GANTT_HMONTH); + $this->year->Show($aFlg & GANTT_HYEAR); + $this->hour->Show($aFlg & GANTT_HHOUR); + $this->minute->Show($aFlg & GANTT_HMIN); + + // Make some default settings of gridlines whihc makes sense + if( $aFlg & GANTT_HWEEK ) { + $this->month->grid->Show(false); + $this->year->grid->Show(false); + } + if( $aFlg & GANTT_HHOUR ) { + $this->day->grid->SetColor("black"); + } + } + + // Should the weekend background stretch all the way down in the plotarea + function UseWeekendBackground($aShow) { + $this->iUsePlotWeekendBackground = $aShow; + } + + // Have a range been specified? + function IsRangeSet() { + return $this->iStartDate!=-1 && $this->iEndDate!=-1; + } + + // Should the layout be from top or even? + function SetVertLayout($aLayout) { + $this->iVertLayout = $aLayout; + } + + // Which locale should be used? + function SetDateLocale($aLocale) { + $this->iDateLocale->Set($aLocale); + } + + // Number of days we are showing + function GetNumberOfDays() { + return round(($this->iEndDate-$this->iStartDate)/SECPERDAY); + } + + // The width of the actual plot area + function GetPlotWidth() { + $img=$this->iImg; + return $img->width - $img->left_margin - $img->right_margin; + } + + // Specify the width of the titles(labels) for the activities + // (This is by default set to the minimum width enought for the + // widest title) + function SetLabelWidth($aLabelWidth) { + $this->iLabelWidth=$aLabelWidth; + } + + // Which day should the week start? + // 0==Sun, 1==Monday, 2==Tuesday etc + function SetWeekStart($aStartDay) { + $this->iWeekStart = $aStartDay % 7; + + //Recalculate the startday since this will change the week start + $this->SetRange($this->iStartDate,$this->iEndDate); + } + + // Do we show min scale? + function IsDisplayMinute() { + return $this->minute->iShowLabels; + } + + // Do we show day scale? + function IsDisplayHour() { + return $this->hour->iShowLabels; + } + + + // Do we show day scale? + function IsDisplayDay() { + return $this->day->iShowLabels; + } + + // Do we show week scale? + function IsDisplayWeek() { + return $this->week->iShowLabels; + } + + // Do we show month scale? + function IsDisplayMonth() { + return $this->month->iShowLabels; + } + + // Do we show year scale? + function IsDisplayYear() { + return $this->year->iShowLabels; + } + + // Specify spacing (in percent of bar height) between activity bars + function SetVertSpacing($aSpacing) { + $this->iVertSpacing = $aSpacing; + } + + // Specify scale min and max date either as timestamp or as date strings + // Always round to the nearest week boundary + function SetRange($aMin,$aMax) { + $this->iStartDate = $this->NormalizeDate($aMin); + $this->iEndDate = $this->NormalizeDate($aMax); + } + + + // Adjust the start and end date so they fit to beginning/ending + // of the week taking the specified week start day into account. + function AdjustStartEndDay() { + + if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) { + // Don't adjust + return; + } + + // Get day in week for start and ending date (Sun==0) + $ds=strftime("%w",$this->iStartDate); + $de=strftime("%w",$this->iEndDate); + + // We want to start on iWeekStart day. But first we subtract a week + // if the startdate is "behind" the day the week start at. + // This way we ensure that the given start date is always included + // in the range. If we don't do this the nearest correct weekday in the week + // to start at might be later than the start date. + if( $ds < $this->iWeekStart ) + $d = strtotime('-7 day',$this->iStartDate); + else + $d = $this->iStartDate; + $adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ ); + $this->iStartDate = $adjdate; + + // We want to end on the last day of the week + $preferredEndDay = ($this->iWeekStart+6)%7; + if( $preferredEndDay != $de ) { + // Solve equivalence eq: $de + x ~ $preferredDay (mod 7) + $adj = (7+($preferredEndDay - $de)) % 7; + $adjdate = strtotime("+$adj day",$this->iEndDate); + $this->iEndDate = $adjdate; + } + } + + // Specify background for the table title area (upper left corner of the table) + function SetTableTitleBackground($aColor) { + $this->iTableHeaderBackgroundColor = $aColor; + } + + /////////////////////////////////////// + // PRIVATE Methods + + // Determine the height of all the scale headers combined + function GetHeaderHeight() { + $img=$this->iImg; + $height=1; + if( $this->minute->iShowLabels ) { + $height += $this->minute->GetFontHeight($img); + $height += $this->minute->iTitleVertMargin; + } + if( $this->hour->iShowLabels ) { + $height += $this->hour->GetFontHeight($img); + $height += $this->hour->iTitleVertMargin; + } + if( $this->day->iShowLabels ) { + $height += $this->day->GetFontHeight($img); + $height += $this->day->iTitleVertMargin; + } + if( $this->week->iShowLabels ) { + $height += $this->week->GetFontHeight($img); + $height += $this->week->iTitleVertMargin; + } + if( $this->month->iShowLabels ) { + $height += $this->month->GetFontHeight($img); + $height += $this->month->iTitleVertMargin; + } + if( $this->year->iShowLabels ) { + $height += $this->year->GetFontHeight($img); + $height += $this->year->iTitleVertMargin; + } + return $height; + } + + // Get width (in pixels) for a single day + function GetDayWidth() { + return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays(); + } + + // Get width (in pixels) for a single hour + function GetHourWidth() { + return $this->GetDayWidth() / 24 ; + } + + function GetMinuteWidth() { + return $this->GetHourWidth() / 60 ; + } + + // Nuber of days in a year + function GetNumDaysInYear($aYear) { + if( $this->IsLeap($aYear) ) + return 366; + else + return 365; + } + + // Get week number + function GetWeekNbr($aDate,$aSunStart=true) { + // We can't use the internal strftime() since it gets the weeknumber + // wrong since it doesn't follow ISO on all systems since this is + // system linrary dependent. + // Even worse is that this works differently if we are on a Windows + // or UNIX box (it even differs between UNIX boxes how strftime() + // is natively implemented) + // + // Credit to Nicolas Hoizey for this elegant + // version of Week Nbr calculation. + + $day = $this->NormalizeDate($aDate); + if( $aSunStart ) + $day += 60*60*24; + + /*------------------------------------------------------------------------- + According to ISO-8601 : + "Week 01 of a year is per definition the first week that has the Thursday in this year, + which is equivalent to the week that contains the fourth day of January. + In other words, the first week of a new year is the week that has the majority of its + days in the new year." + + Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!! + + day of year = date("z", $day) + 1 + offset to thursday = 3 - (date("w", $day) + 6) % 7 + first thursday of year = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7 + week number = (thursday's day of year - first thursday's day of year) / 7 + 1 + ---------------------------------------------------------------------------*/ + + $thursday = $day + 60 * 60 * 24 * (3 - (date("w", $day) + 6) % 7); // take week's thursday + $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7; + + return $week; + } + + // Is year a leap year? + function IsLeap($aYear) { + // Is the year a leap year? + //$year = 0+date("Y",$aDate); + if( $aYear % 4 == 0) + if( !($aYear % 100 == 0) || ($aYear % 400 == 0) ) + return true; + return false; + } + + // Get current year + function GetYear($aDate) { + return 0+Date("Y",$aDate); + } + + // Return number of days in a year + function GetNumDaysInMonth($aMonth,$aYear) { + $days=array(31,28,31,30,31,30,31,31,30,31,30,31); + $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31); + if( $this->IsLeap($aYear)) + return $daysl[$aMonth]; + else + return $days[$aMonth]; + } + + // Get day in month + function GetMonthDayNbr($aDate) { + return 0+strftime("%d",$aDate); + } + + // Get day in year + function GetYearDayNbr($aDate) { + return 0+strftime("%j",$aDate); + } + + // Get month number + function GetMonthNbr($aDate) { + return 0+strftime("%m",$aDate); + } + + // Translate a date to screen coordinates (horizontal scale) + function TranslateDate($aDate) { + // + // In order to handle the problem with Daylight savings time + // the scale written with equal number of seconds per day beginning + // with the start date. This means that we "cement" the state of + // DST as it is in the start date. If later the scale includes the + // switchover date (depends on the locale) we need to adjust back + // if the date we try to translate has a different DST status since + // we would otherwise be off by one hour. + $aDate = $this->NormalizeDate($aDate); + $tmp = localtime($aDate); + $cloc = $tmp[8]; + $tmp = localtime($this->iStartDate); + $sloc = $tmp[8]; + $offset = 0; + if( $sloc != $cloc) { + if( $sloc ) + $offset = 3600; + else + $offset = -3600; + } + $img=$this->iImg; + return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;; + } + + // Get screen coordinatesz for the vertical position for a bar + function TranslateVertPos($aPos,$atTop=false) { + $img=$this->iImg; + if( $aPos > $this->iVertLines ) + JpGraphError::RaiseL(6015,$aPos); + // 'Illegal vertical position %d' + if( $this->iVertLayout == GANTT_EVEN ) { + // Position the top bar at 1 vert spacing from the scale + $pos = round($img->top_margin + $this->iVertHeaderSize + ($aPos+1)*$this->iVertSpacing); + } + else { + // position the top bar at 1/2 a vert spacing from the scale + $pos = round($img->top_margin + $this->iVertHeaderSize + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing); + } + + if( $atTop ) + $pos -= $this->iVertSpacing; + + return $pos; + } + + // What is the vertical spacing? + function GetVertSpacing() { + return $this->iVertSpacing; + } + + // Convert a date to timestamp + function NormalizeDate($aDate) { + if( $aDate === false ) return false; + if( is_string($aDate) ) { + $t = strtotime($aDate); + if( $t === FALSE || $t === -1 ) { + JpGraphError::RaiseL(6016,$aDate); + //("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"); + } + return $t; + } + elseif( is_int($aDate) || is_float($aDate) ) + return $aDate; + else + JpGraphError::RaiseL(6017,$aDate); + //Unknown date format in GanttScale ($aDate)."); + } + + + // Convert a time string to minutes + + function TimeToMinutes($aTimeString) { + // Split in hours and minutes + $pos=strpos($aTimeString,':'); + $minint=60; + if( $pos === false ) { + $hourint = $aTimeString; + $minint = 0; + } + else { + $hourint = floor(substr($aTimeString,0,$pos)); + $minint = floor(substr($aTimeString,$pos+1)); + } + $minint += 60 * $hourint; + return $minint; + } + + // Stroke the day scale (including gridlines) + function StrokeMinutes($aYCoord,$getHeight=false) { + $img=$this->iImg; + $xt=$img->left_margin+$this->iLabelWidth; + $yt=$aYCoord+$img->top_margin; + if( $this->minute->iShowLabels ) { + $img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize); + $yb = $yt + $img->GetFontHeight() + + $this->minute->iTitleVertMargin + $this->minute->iFrameWeight; + if( $getHeight ) { + return $yb - $img->top_margin; + } + $xb = $img->width-$img->right_margin+1; + $img->SetColor($this->minute->iBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + + $x = $xt; + $img->SetTextAlign("center"); + $day = date('w',$this->iStartDate); + $minint = $this->minute->GetIntervall() ; + + if( 60 % $minint !== 0 ) { + JpGraphError::RaiseL(6018,$minint); + //'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.'); + } + + + $n = 60 / $minint; + $datestamp = $this->iStartDate; + $width = $this->GetHourWidth() / $n ; + if( $width < 8 ) { + // TO small width to draw minute scale + JpGraphError::RaiseL(6019,$width); + //('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.'); + } + + $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) ); + $nd = $this->GetNumberOfDays(); + // Convert to intervall to seconds + $minint *= 60; + for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) { + for( $k=0; $k < $nh; ++$k ) { + for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) { + if( $day==6 || $day==0 ) { + + $img->PushColor($this->day->iWeekendBackgroundColor); + if( $this->iUsePlotWeekendBackground ) + $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); + else + $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); + $img->PopColor(); + + } + + if( $day==0 ) + $img->SetColor($this->day->iSundayTextColor); + else + $img->SetColor($this->day->iTextColor); + + switch( $this->minute->iStyle ) { + case MINUTESTYLE_CUSTOM: + $txt = date($this->minute->iLabelFormStr,$datestamp); + break; + case MINUTESTYLE_MM: + default: + // 15 + $txt = date('i',$datestamp); + break; + } + $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt); + + // Fix a rounding problem the wrong way .. + // If we also have hour scale then don't draw the firsta or last + // gridline since that will be overwritten by the hour scale gridline if such exists. + // However, due to the propagation of rounding of the 'x+=width' term in the loop + // this might sometimes be one pixel of so we fix this by not drawing it. + // The proper way to fix it would be to re-calculate the scale for each step and + // not using the additive term. + if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) { + $img->SetColor($this->minute->grid->iColor); + $img->SetLineWeight($this->minute->grid->iWeight); + $img->Line($x,$yt,$x,$yb); + $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); + } + } + } + } + $img->SetColor($this->minute->iFrameColor); + $img->SetLineWeight($this->minute->iFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + return $yb - $img->top_margin; + } + return $aYCoord; + } + + // Stroke the day scale (including gridlines) + function StrokeHours($aYCoord,$getHeight=false) { + $img=$this->iImg; + $xt=$img->left_margin+$this->iLabelWidth; + $yt=$aYCoord+$img->top_margin; + if( $this->hour->iShowLabels ) { + $img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize); + $yb = $yt + $img->GetFontHeight() + + $this->hour->iTitleVertMargin + $this->hour->iFrameWeight; + if( $getHeight ) { + return $yb - $img->top_margin; + } + $xb = $img->width-$img->right_margin+1; + $img->SetColor($this->hour->iBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + + $x = $xt; + $img->SetTextAlign("center"); + $tmp = $this->hour->GetIntervall() ; + $minint = $this->TimeToMinutes($tmp); + if( 1440 % $minint !== 0 ) { + JpGraphError::RaiseL(6020,$tmp); + //('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); + } + + $n = ceil(24*60 / $minint ); + $datestamp = $this->iStartDate; + $day = date('w',$this->iStartDate); + $doback = !$this->minute->iShowLabels; + $width = $this->GetDayWidth() / $n ; + for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) { + for($i=0; $i < $n ;++$i, $x+=$width) { + if( $day==6 || $day==0 ) { + + $img->PushColor($this->day->iWeekendBackgroundColor); + if( $this->iUsePlotWeekendBackground && $doback ) + $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); + else + $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); + $img->PopColor(); + + } + + if( $day==0 ) + $img->SetColor($this->day->iSundayTextColor); + else + $img->SetColor($this->day->iTextColor); + + switch( $this->hour->iStyle ) { + case HOURSTYLE_HMAMPM: + // 1:35pm + $txt = date('g:ia',$datestamp); + break; + case HOURSTYLE_H24: + // 13 + $txt = date('H',$datestamp); + break; + case HOURSTYLE_HAMPM: + $txt = date('ga',$datestamp); + break; + case HOURSTYLE_CUSTOM: + $txt = date($this->hour->iLabelFormStr,$datestamp); + break; + case HOURSTYLE_HM24: + default: + $txt = date('H:i',$datestamp); + break; + } + $img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt); + $img->SetColor($this->hour->grid->iColor); + $img->SetLineWeight($this->hour->grid->iWeight); + $img->Line($x,$yt,$x,$yb); + $this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); + //$datestamp += $minint*60 + $datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0, + date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); + + } + } + $img->SetColor($this->hour->iFrameColor); + $img->SetLineWeight($this->hour->iFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + return $yb - $img->top_margin; + } + return $aYCoord; + } + + + // Stroke the day scale (including gridlines) + function StrokeDays($aYCoord,$getHeight=false) { + $img=$this->iImg; + $daywidth=$this->GetDayWidth(); + $xt=$img->left_margin+$this->iLabelWidth; + $yt=$aYCoord+$img->top_margin; + if( $this->day->iShowLabels ) { + $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize); + $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight; + if( $getHeight ) { + return $yb - $img->top_margin; + } + $xb=$img->width-$img->right_margin+1; + $img->SetColor($this->day->iBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + + $x = $xt; + $img->SetTextAlign("center"); + $day = date('w',$this->iStartDate); + $datestamp = $this->iStartDate; + + $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels); + + setlocale(LC_TIME,$this->iDateLocale->iLocale); + + for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) { + if( $day==6 || $day==0 ) { + $img->SetColor($this->day->iWeekendBackgroundColor); + if( $this->iUsePlotWeekendBackground && $doback) + $img->FilledRectangle($x,$yt+$this->day->iFrameWeight, + $x+$daywidth,$img->height-$img->bottom_margin); + else + $img->FilledRectangle($x,$yt+$this->day->iFrameWeight, + $x+$daywidth,$yb-$this->day->iFrameWeight); + } + + $mn = strftime('%m',$datestamp); + if( $mn[0]=='0' ) + $mn = $mn[1]; + + switch( $this->day->iStyle ) { + case DAYSTYLE_LONG: + // "Monday" + $txt = strftime('%A',$datestamp); + break; + case DAYSTYLE_SHORT: + // "Mon" + $txt = strftime('%a',$datestamp); + break; + case DAYSTYLE_SHORTDAYDATE1: + // "Mon 23/6" + $txt = strftime('%a %d/'.$mn,$datestamp); + break; + case DAYSTYLE_SHORTDAYDATE2: + // "Mon 23 Jun" + $txt = strftime('%a %d %b',$datestamp); + break; + case DAYSTYLE_SHORTDAYDATE3: + // "Mon 23 Jun 2003" + $txt = strftime('%a %d %b %Y',$datestamp); + break; + case DAYSTYLE_LONGDAYDATE1: + // "Monday 23 Jun" + $txt = strftime('%A %d %b',$datestamp); + break; + case DAYSTYLE_LONGDAYDATE2: + // "Monday 23 Jun 2003" + $txt = strftime('%A %d %b %Y',$datestamp); + break; + case DAYSTYLE_SHORTDATE1: + // "23/6" + $txt = strftime('%d/'.$mn,$datestamp); + break; + case DAYSTYLE_SHORTDATE2: + // "23 Jun" + $txt = strftime('%d %b',$datestamp); + break; + case DAYSTYLE_SHORTDATE3: + // "Mon 23" + $txt = strftime('%a %d',$datestamp); + break; + case DAYSTYLE_SHORTDATE4: + // "23" + $txt = strftime('%d',$datestamp); + break; + case DAYSTYLE_CUSTOM: + // Custom format + $txt = strftime($this->day->iLabelFormStr,$datestamp); + break; + case DAYSTYLE_ONELETTER: + default: + // "M" + $txt = strftime('%A',$datestamp); + $txt = strtoupper($txt[0]); + break; + } + + if( $day==0 ) + $img->SetColor($this->day->iSundayTextColor); + else + $img->SetColor($this->day->iTextColor); + $img->StrokeText(round($x+$daywidth/2+1), + round($yb-$this->day->iTitleVertMargin),$txt); + $img->SetColor($this->day->grid->iColor); + $img->SetLineWeight($this->day->grid->iWeight); + $img->Line($x,$yt,$x,$yb); + $this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); + $datestamp = mktime(0,0,0,date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); + //$datestamp += SECPERDAY; + + } + $img->SetColor($this->day->iFrameColor); + $img->SetLineWeight($this->day->iFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + return $yb - $img->top_margin; + } + return $aYCoord; + } + + // Stroke week header and grid + function StrokeWeeks($aYCoord,$getHeight=false) { + if( $this->week->iShowLabels ) { + $img=$this->iImg; + $yt=$aYCoord+$img->top_margin; + $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize); + $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight; + + if( $getHeight ) { + return $yb - $img->top_margin; + } + + $xt=$img->left_margin+$this->iLabelWidth; + $weekwidth=$this->GetDayWidth()*7; + $wdays=$this->iDateLocale->GetDayAbb(); + $xb=$img->width-$img->right_margin+1; + $week = $this->iStartDate; + $weeknbr=$this->GetWeekNbr($week); + $img->SetColor($this->week->iBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + $img->SetColor($this->week->grid->iColor); + $x = $xt; + if( $this->week->iStyle==WEEKSTYLE_WNBR ) { + $img->SetTextAlign("center"); + $txtOffset = $weekwidth/2+1; + } + elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || + $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || + $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || + $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { + $img->SetTextAlign("left"); + $txtOffset = 3; + } + else { + JpGraphError::RaiseL(6021); + //("Unknown formatting style for week."); + } + + for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) { + $img->PushColor($this->week->iTextColor); + + if( $this->week->iStyle==WEEKSTYLE_WNBR ) + $txt = sprintf($this->week->iLabelFormStr,$weeknbr); + elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || + $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) + $txt = date("j/n",$week); + elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || + $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { + $monthnbr = date("n",$week)-1; + $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr); + $txt = Date("j",$week)." ".$shortmonth; + } + + if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || + $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { + $w = sprintf($this->week->iLabelFormStr,$weeknbr); + $txt .= ' '.$w; + } + + $img->StrokeText(round($x+$txtOffset), + round($yb-$this->week->iTitleVertMargin),$txt); + + $week = strtotime('+7 day',$week); + $weeknbr = $this->GetWeekNbr($week); + $img->PopColor(); + $img->SetLineWeight($this->week->grid->iWeight); + $img->Line($x,$yt,$x,$yb); + $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); + } + $img->SetColor($this->week->iFrameColor); + $img->SetLineWeight($this->week->iFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + return $yb-$img->top_margin; + } + return $aYCoord; + } + + // Format the mont scale header string + function GetMonthLabel($aMonthNbr,$year) { + $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr); + $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr); + switch($this->month->iStyle) { + case MONTHSTYLE_SHORTNAME: + $m=$sn; + break; + case MONTHSTYLE_LONGNAME: + $m=$ln; + break; + case MONTHSTYLE_SHORTNAMEYEAR2: + $m=$sn." '".substr("".$year,2); + break; + case MONTHSTYLE_SHORTNAMEYEAR4: + $m=$sn." ".$year; + break; + case MONTHSTYLE_LONGNAMEYEAR2: + $m=$ln." '".substr("".$year,2); + break; + case MONTHSTYLE_LONGNAMEYEAR4: + $m=$ln." ".$year; + break; + case MONTHSTYLE_FIRSTLETTER: + $m=$sn[0]; + break; + } + return $m; + } + + // Stroke month scale and gridlines + function StrokeMonths($aYCoord,$getHeight=false) { + if( $this->month->iShowLabels ) { + $img=$this->iImg; + $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize); + $yt=$aYCoord+$img->top_margin; + $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight; + if( $getHeight ) { + return $yb - $img->top_margin; + } + $monthnbr = $this->GetMonthNbr($this->iStartDate)-1; + $xt=$img->left_margin+$this->iLabelWidth; + $xb=$img->width-$img->right_margin+1; + + $img->SetColor($this->month->iBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + + $img->SetLineWeight($this->month->grid->iWeight); + $img->SetColor($this->month->iTextColor); + $year = 0+strftime("%Y",$this->iStartDate); + $img->SetTextAlign("center"); + if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) + && $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) { + $monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1); + } + else { + $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1); + } + // Is it enough space to stroke the first month? + $monthName = $this->GetMonthLabel($monthnbr,$year); + if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) { + $img->SetColor($this->month->iTextColor); + $img->StrokeText(round($xt+$monthwidth/2+1), + round($yb-$this->month->iTitleVertMargin), + $monthName); + } + $x = $xt + $monthwidth; + while( $x < $xb ) { + $img->SetColor($this->month->grid->iColor); + $img->Line($x,$yt,$x,$yb); + $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); + $monthnbr++; + if( $monthnbr==12 ) { + $monthnbr=0; + $year++; + } + $monthName = $this->GetMonthLabel($monthnbr,$year); + $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year); + if( $x + $monthwidth < $xb ) + $w = $monthwidth; + else + $w = $xb-$x; + if( $w >= 1.2*$img->GetTextWidth($monthName) ) { + $img->SetColor($this->month->iTextColor); + $img->StrokeText(round($x+$w/2+1), + round($yb-$this->month->iTitleVertMargin),$monthName); + } + $x += $monthwidth; + } + $img->SetColor($this->month->iFrameColor); + $img->SetLineWeight($this->month->iFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + return $yb-$img->top_margin; + } + return $aYCoord; + } + + // Stroke year scale and gridlines + function StrokeYears($aYCoord,$getHeight=false) { + if( $this->year->iShowLabels ) { + $img=$this->iImg; + $yt=$aYCoord+$img->top_margin; + $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize); + $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight; + + if( $getHeight ) { + return $yb - $img->top_margin; + } + + $xb=$img->width-$img->right_margin+1; + $xt=$img->left_margin+$this->iLabelWidth; + $year = $this->GetYear($this->iStartDate); + $img->SetColor($this->year->iBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + $img->SetLineWeight($this->year->grid->iWeight); + $img->SetTextAlign("center"); + if( $year == $this->GetYear($this->iEndDate) ) + $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1); + else + $yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1); + + // The space for a year must be at least 20% bigger than the actual text + // so we allow 10% margin on each side + if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) { + $img->SetColor($this->year->iTextColor); + $img->StrokeText(round($xt+$yearwidth/2+1), + round($yb-$this->year->iTitleVertMargin), + $year); + } + $x = $xt + $yearwidth; + while( $x < $xb ) { + $img->SetColor($this->year->grid->iColor); + $img->Line($x,$yt,$x,$yb); + $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); + $year += 1; + $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year); + if( $x + $yearwidth < $xb ) + $w = $yearwidth; + else + $w = $xb-$x; + if( $w >= 1.2*$img->GetTextWidth("".$year) ) { + $img->SetColor($this->year->iTextColor); + $img->StrokeText(round($x+$w/2+1), + round($yb-$this->year->iTitleVertMargin), + $year); + } + $x += $yearwidth; + } + $img->SetColor($this->year->iFrameColor); + $img->SetLineWeight($this->year->iFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + return $yb-$img->top_margin; + } + return $aYCoord; + } + + // Stroke table title (upper left corner) + function StrokeTableHeaders($aYBottom) { + $img=$this->iImg; + $xt=$img->left_margin; + $yt=$img->top_margin; + $xb=$xt+$this->iLabelWidth; + $yb=$aYBottom+$img->top_margin; + + if( $this->tableTitle->iShow ) { + $img->SetColor($this->iTableHeaderBackgroundColor); + $img->FilledRectangle($xt,$yt,$xb,$yb); + $this->tableTitle->Align("center","top"); + $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2); + $img->SetColor($this->iTableHeaderFrameColor); + $img->SetLineWeight($this->iTableHeaderFrameWeight); + $img->Rectangle($xt,$yt,$xb,$yb); + } + + $this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow); + + + // Draw the horizontal dividing line + $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb); + + // Draw the vertical dividing line + // We do the width "manually" since we want the line only to grow + // to the left + $fancy = $this->divider->iStyle == 'fancy' ; + if( $fancy ) { + $this->divider->iStyle = 'solid'; + } + + $tmp = $this->divider->iWeight; + $this->divider->iWeight=1; + $y = $img->height-$img->bottom_margin; + for($i=0; $i < $tmp; ++$i ) { + $this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y); + } + + // Should we draw "fancy" divider + if( $fancy ) { + $img->SetLineWeight(1); + $img->SetColor($this->iTableHeaderFrameColor); + $img->Line($xb,$yt,$xb,$y); + $img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y); + $img->SetColor('white'); + $img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y); + } + } + + // Main entry point to stroke scale + function Stroke() { + if( !$this->IsRangeSet() ) { + JpGraphError::RaiseL(6022); + //("Gantt scale has not been specified."); + } + $img=$this->iImg; + + // If minutes are displayed then hour interval must be 1 + if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) { + JpGraphError::RaiseL(6023); + //('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).'); + } + + // Stroke all headers. As argument we supply the offset from the + // top which depends on any previous headers + + // First find out the height of each header + $offy=$this->StrokeYears(0,true); + $offm=$this->StrokeMonths($offy,true); + $offw=$this->StrokeWeeks($offm,true); + $offd=$this->StrokeDays($offw,true); + $offh=$this->StrokeHours($offd,true); + $offmin=$this->StrokeMinutes($offh,true); + + + // ... then we can stroke them in the "backwards order to ensure that + // the larger scale gridlines is stroked over the smaller scale gridline + $this->StrokeMinutes($offh); + $this->StrokeHours($offd); + $this->StrokeDays($offw); + $this->StrokeWeeks($offm); + $this->StrokeMonths($offy); + $this->StrokeYears(0); + + // Now when we now the oaverall size of the scale headers + // we can stroke the overall table headers + $this->StrokeTableHeaders($offmin); + + // Now we can calculate the correct scaling factor for each vertical position + $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd; + + $this->iVertHeaderSize = $offmin; + if( $this->iVertSpacing == -1 ) + $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines; + } +} + + +//=================================================== +// CLASS GanttConstraint +// Just a structure to store all the values for a constraint +//=================================================== +class GanttConstraint { + public $iConstrainRow; + public $iConstrainType; + public $iConstrainColor; + public $iConstrainArrowSize; + public $iConstrainArrowType; + + //--------------- + // CONSTRUCTOR + function __construct($aRow,$aType,$aColor,$aArrowSize,$aArrowType){ + $this->iConstrainType = $aType; + $this->iConstrainRow = $aRow; + $this->iConstrainColor=$aColor; + $this->iConstrainArrowSize=$aArrowSize; + $this->iConstrainArrowType=$aArrowType; + } +} + + +//=================================================== +// CLASS GanttPlotObject +// The common signature for a Gantt object +//=================================================== +class GanttPlotObject { + public $title,$caption; + public $csimarea='',$csimtarget='',$csimwintarget='',$csimalt=''; + public $constraints = array(); + public $iCaptionMargin=5; + public $iConstrainPos=array(); + protected $iStart=""; // Start date + public $iVPos=0; // Vertical position + protected $iLabelLeftMargin=2; // Title margin + + function __construct() { + $this->title = new TextProperty(); + $this->title->Align('left','center'); + $this->caption = new TextProperty(); + } + + function GetCSIMArea() { + return $this->csimarea; + } + + function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') { + if( !is_string($aTarget) ) { + $tv = substr(var_export($aTarget,true),0,40); + JpGraphError::RaiseL(6024,$tv); + //('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv"); + } + if( !is_string($aAlt) ) { + $tv = substr(var_export($aAlt,true),0,40); + JpGraphError::RaiseL(6025,$tv); + //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); + } + + $this->csimtarget=$aTarget; + $this->csimwintarget=$aWinTarget; + $this->csimalt=$aAlt; + } + + function SetCSIMAlt($aAlt) { + if( !is_string($aAlt) ) { + $tv = substr(var_export($aAlt,true),0,40); + JpGraphError::RaiseL(6025,$tv); + //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); + } + $this->csimalt=$aAlt; + } + + function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) { + $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType); + } + + function SetConstrainPos($xt,$yt,$xb,$yb) { + $this->iConstrainPos = array($xt,$yt,$xb,$yb); + } + + function GetMinDate() { + return $this->iStart; + } + + function GetMaxDate() { + return $this->iStart; + } + + function SetCaptionMargin($aMarg) { + $this->iCaptionMargin=$aMarg; + } + + function GetAbsHeight($aImg) { + return 0; + } + + function GetLineNbr() { + return $this->iVPos; + } + + function SetLabelLeftMargin($aOff) { + $this->iLabelLeftMargin=$aOff; + } + + function StrokeActInfo($aImg,$aScale,$aYPos) { + $cols=array(); + $aScale->actinfo->GetColStart($aImg,$cols,true); + $this->title->Stroke($aImg,$cols,$aYPos); + } +} + +//=================================================== +// CLASS Progress +// Holds parameters for the progress indicator +// displyed within a bar +//=================================================== +class Progress { + public $iProgress=-1; + public $iPattern=GANTT_SOLID; + public $iColor="black", $iFillColor='black'; + public $iDensity=98, $iHeight=0.65; + + function Set($aProg) { + if( $aProg < 0.0 || $aProg > 1.0 ) { + JpGraphError::RaiseL(6027); + //("Progress value must in range [0, 1]"); + } + $this->iProgress = $aProg; + } + + function SetPattern($aPattern,$aColor="blue",$aDensity=98) { + $this->iPattern = $aPattern; + $this->iColor = $aColor; + $this->iDensity = $aDensity; + } + + function SetFillColor($aColor) { + $this->iFillColor = $aColor; + } + + function SetHeight($aHeight) { + $this->iHeight = $aHeight; + } +} + +define('GANTT_HGRID1',0); +define('GANTT_HGRID2',1); + +//=================================================== +// CLASS HorizontalGridLine +// Responsible for drawinf horizontal gridlines and filled alternatibg rows +//=================================================== +class HorizontalGridLine { + private $iGraph=NULL; + private $iRowColor1 = '', $iRowColor2 = ''; + private $iShow=false; + private $line=null; + private $iStart=0; // 0=from left margin, 1=just along header + + function __construct() { + $this->line = new LineProperty(); + $this->line->SetColor('gray@0.4'); + $this->line->SetStyle('dashed'); + } + + function Show($aShow=true) { + $this->iShow = $aShow; + } + + function SetRowFillColor($aColor1,$aColor2='') { + $this->iRowColor1 = $aColor1; + $this->iRowColor2 = $aColor2; + } + + function SetStart($aStart) { + $this->iStart = $aStart; + } + + function Stroke($aImg,$aScale) { + + if( ! $this->iShow ) return; + + // Get horizontal width of line + /* + $limst = $aScale->iStartDate; + $limen = $aScale->iEndDate; + $xt = round($aScale->TranslateDate($aScale->iStartDate)); + $xb = round($aScale->TranslateDate($limen)); + */ + + if( $this->iStart === 0 ) { + $xt = $aImg->left_margin-1; + } + else { + $xt = round($aScale->TranslateDate($aScale->iStartDate))+1; + } + + $xb = $aImg->width-$aImg->right_margin; + + $yt = round($aScale->TranslateVertPos(0)); + $yb = round($aScale->TranslateVertPos(1)); + $height = $yb - $yt; + + // Loop around for all lines in the chart + for($i=0; $i < $aScale->iVertLines; ++$i ) { + $yb = $yt - $height; + $this->line->Stroke($aImg,$xt,$yb,$xb,$yb); + if( $this->iRowColor1 !== '' ) { + if( $i % 2 == 0 ) { + $aImg->PushColor($this->iRowColor1); + $aImg->FilledRectangle($xt,$yt,$xb,$yb); + $aImg->PopColor(); + } + elseif( $this->iRowColor2 !== '' ) { + $aImg->PushColor($this->iRowColor2); + $aImg->FilledRectangle($xt,$yt,$xb,$yb); + $aImg->PopColor(); + } + } + $yt = round($aScale->TranslateVertPos($i+1)); + } + $yb = $yt - $height; + $this->line->Stroke($aImg,$xt,$yb,$xb,$yb); + } +} + + +//=================================================== +// CLASS GanttBar +// Responsible for formatting individual gantt bars +//=================================================== +class GanttBar extends GanttPlotObject { + public $progress; + public $leftMark,$rightMark; + private $iEnd; + private $iHeightFactor=0.5; + private $iFillColor="white",$iFrameColor="black"; + private $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black"; + private $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95; + private $iBreakStyle=false, $iBreakLineStyle='dotted',$iBreakLineWeight=1; + //--------------- + // CONSTRUCTOR + function __construct($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) { + parent::__construct(); + $this->iStart = $aStart; + // Is the end date given as a date or as number of days added to start date? + if( is_string($aEnd) ) { + // If end date has been specified without a time we will asssume + // end date is at the end of that date + if( strpos($aEnd,':') === false ) { + $this->iEnd = strtotime($aEnd)+SECPERDAY-1; + } + else { + $this->iEnd = $aEnd; + } + } + elseif(is_int($aEnd) || is_float($aEnd) ) { + $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY); + } + $this->iVPos = $aPos; + $this->iHeightFactor = $aHeightFactor; + $this->title->Set($aLabel); + $this->caption = new TextProperty($aCaption); + $this->caption->Align("left","center"); + $this->leftMark =new PlotMark(); + $this->leftMark->Hide(); + $this->rightMark=new PlotMark(); + $this->rightMark->Hide(); + $this->progress = new Progress(); + } + + //--------------- + // PUBLIC METHODS + function SetShadow($aShadow=true,$aColor="gray") { + $this->iShadow=$aShadow; + $this->iShadowColor=$aColor; + } + + function SetBreakStyle($aFlg=true,$aLineStyle='dotted',$aLineWeight=1) { + $this->iBreakStyle = $aFlg; + $this->iBreakLineStyle = $aLineStyle; + $this->iBreakLineWeight = $aLineWeight; + } + + function GetMaxDate() { + return $this->iEnd; + } + + function SetHeight($aHeight) { + $this->iHeightFactor = $aHeight; + } + + function SetColor($aColor) { + $this->iFrameColor = $aColor; + } + + function SetFillColor($aColor) { + $this->iFillColor = $aColor; + } + + function GetAbsHeight($aImg) { + if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) { + $m=-1; + if( is_int($this->iHeightFactor) ) + $m = $this->iHeightFactor; + if( $this->leftMark->show ) + $m = max($m,$this->leftMark->width*2); + if( $this->rightMark->show ) + $m = max($m,$this->rightMark->width*2); + return $m; + } + else + return -1; + } + + function SetPattern($aPattern,$aColor="blue",$aDensity=95) { + $this->iPattern = $aPattern; + $this->iPatternColor = $aColor; + $this->iPatternDensity = $aDensity; + } + + function Stroke($aImg,$aScale) { + $factory = new RectPatternFactory(); + $prect = $factory->Create($this->iPattern,$this->iPatternColor); + $prect->SetDensity($this->iPatternDensity); + + // If height factor is specified as a float between 0,1 then we take it as meaning + // percetage of the scale width between horizontal line. + // If it is an integer > 1 we take it to mean the absolute height in pixels + if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1) + $vs = $aScale->GetVertSpacing()*$this->iHeightFactor; + elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 ) + $vs = $this->iHeightFactor; + else { + JpGraphError::RaiseL(6028,$this->iHeightFactor); + // ("Specified height (".$this->iHeightFactor.") for gantt bar is out of range."); + } + + // Clip date to min max dates to show + $st = $aScale->NormalizeDate($this->iStart); + $en = $aScale->NormalizeDate($this->iEnd); + + $limst = max($st,$aScale->iStartDate); + $limen = min($en,$aScale->iEndDate); + + $xt = round($aScale->TranslateDate($limst)); + $xb = round($aScale->TranslateDate($limen)); + $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2)); + $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2)); + $middle = round($yt+($yb-$yt)/2); + $this->StrokeActInfo($aImg,$aScale,$middle); + + // CSIM for title + if( ! empty($this->title->csimtarget) ) { + $colwidth = $this->title->GetColWidth($aImg); + $colstarts=array(); + $aScale->actinfo->GetColStart($aImg,$colstarts,true); + $n = min(count($colwidth),count($this->title->csimtarget)); + for( $i=0; $i < $n; ++$i ) { + $title_xt = $colstarts[$i]; + $title_xb = $title_xt + $colwidth[$i]; + $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; + + if( ! empty($this->title->csimtarget[$i]) ) { + $this->csimarea .= "title->csimtarget[$i]."\""; + + if( ! empty($this->title->csimwintarget[$i]) ) { + $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" "; + } + + if( ! empty($this->title->csimalt[$i]) ) { + $tmp = $this->title->csimalt[$i]; + $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimarea .= " />\n"; + } + } + } + + // Check if the bar is totally outside the current scale range + if( $en < $aScale->iStartDate || $st > $aScale->iEndDate ) + return; + + + // Remember the positions for the bar + $this->SetConstrainPos($xt,$yt,$xb,$yb); + + + + $prect->ShowFrame(false); + $prect->SetBackground($this->iFillColor); + if( $this->iBreakStyle ) { + $aImg->SetColor($this->iFrameColor); + $olds = $aImg->SetLineStyle($this->iBreakLineStyle); + $oldw = $aImg->SetLineWeight($this->iBreakLineWeight); + $aImg->StyleLine($xt,$yt,$xb,$yt); + $aImg->StyleLine($xt,$yb,$xb,$yb); + $aImg->SetLineStyle($olds); + $aImg->SetLineWeight($oldw); + } + else { + if( $this->iShadow ) { + $aImg->SetColor($this->iFrameColor); + $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor); + $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2)); + $prect->Stroke($aImg); + } + else { + $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1)); + $prect->Stroke($aImg); + $aImg->SetColor($this->iFrameColor); + $aImg->Rectangle($xt,$yt,$xb,$yb); + } + } + // CSIM for bar + if( ! empty($this->csimtarget) ) { + + $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb"; + $this->csimarea .= "csimtarget."\""; + + if( !empty($this->csimwintarget) ) { + $this->csimarea .= " target=\"".$this->csimwintarget."\" "; + } + + if( $this->csimalt != '' ) { + $tmp = $this->csimalt; + $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimarea .= " />\n"; + } + + // Draw progress bar inside activity bar + if( $this->progress->iProgress > 0 ) { + + $xtp = $aScale->TranslateDate($st); + $xbp = $aScale->TranslateDate($en); + $len = ($xbp-$xtp)*$this->progress->iProgress; + + $endpos = $xtp+$len; + if( $endpos > $xt ) { + + // Take away the length of the progress that is not visible (before the start date) + $len -= ($xt-$xtp); + + // Is the the progress bar visible after the start date? + if( $xtp < $xt ) + $xtp = $xt; + + // Make sure that the progess bar doesn't extend over the end date + if( $xtp+$len-1 > $xb ) + $len = $xb - $xtp ; + + $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor); + $prog->SetDensity($this->progress->iDensity); + $prog->SetBackground($this->progress->iFillColor); + $barheight = ($yb-$yt+1); + if( $this->iShadow ) + $barheight -= $this->iShadowWidth; + $progressheight = floor($barheight*$this->progress->iHeight); + $marg = ceil(($barheight-$progressheight)/2); + $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg); + $prog->SetPos($pos); + $prog->Stroke($aImg); + } + } + + // We don't plot the end mark if the bar has been capped + if( $limst == $st ) { + $y = $middle; + // We treat the RIGHT and LEFT triangle mark a little bi + // special so that these marks are placed right under the + // bar. + if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) { + $y = $yb ; + } + $this->leftMark->Stroke($aImg,$xt,$y); + } + if( $limen == $en ) { + $y = $middle; + // We treat the RIGHT and LEFT triangle mark a little bi + // special so that these marks are placed right under the + // bar. + if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) { + $y = $yb ; + } + $this->rightMark->Stroke($aImg,$xb,$y); + + $margin = $this->iCaptionMargin; + if( $this->rightMark->show ) + $margin += $this->rightMark->GetWidth(); + $this->caption->Stroke($aImg,$xb+$margin,$middle); + } + } +} + +//=================================================== +// CLASS MileStone +// Responsible for formatting individual milestones +//=================================================== +class MileStone extends GanttPlotObject { + public $mark; + + //--------------- + // CONSTRUCTOR + function __construct($aVPos,$aLabel,$aDate,$aCaption="") { + GanttPlotObject::__construct(); + $this->caption->Set($aCaption); + $this->caption->Align("left","center"); + $this->caption->SetFont(FF_FONT1,FS_BOLD); + $this->title->Set($aLabel); + $this->title->SetColor("darkred"); + $this->mark = new PlotMark(); + $this->mark->SetWidth(10); + $this->mark->SetType(MARK_DIAMOND); + $this->mark->SetColor("darkred"); + $this->mark->SetFillColor("darkred"); + $this->iVPos = $aVPos; + $this->iStart = $aDate; + } + + //--------------- + // PUBLIC METHODS + + function GetAbsHeight($aImg) { + return max($this->title->GetHeight($aImg),$this->mark->GetWidth()); + } + + function Stroke($aImg,$aScale) { + // Put the mark in the middle at the middle of the day + $d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2; + $x = $aScale->TranslateDate($d); + $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2); + + $this->StrokeActInfo($aImg,$aScale,$y); + + // CSIM for title + if( ! empty($this->title->csimtarget) ) { + + $yt = round($y - $this->title->GetHeight($aImg)/2); + $yb = round($y + $this->title->GetHeight($aImg)/2); + + $colwidth = $this->title->GetColWidth($aImg); + $colstarts=array(); + $aScale->actinfo->GetColStart($aImg,$colstarts,true); + $n = min(count($colwidth),count($this->title->csimtarget)); + for( $i=0; $i < $n; ++$i ) { + $title_xt = $colstarts[$i]; + $title_xb = $title_xt + $colwidth[$i]; + $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; + + if( !empty($this->title->csimtarget[$i]) ) { + + $this->csimarea .= "title->csimtarget[$i]."\""; + + if( !empty($this->title->csimwintarget[$i]) ) { + $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\""; + } + + if( ! empty($this->title->csimalt[$i]) ) { + $tmp = $this->title->csimalt[$i]; + $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimarea .= " />\n"; + } + } + } + + if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) + return; + + // Remember the coordinates for any constrains linking to + // this milestone + $w = $this->mark->GetWidth()/2; + $this->SetConstrainPos($x,round($y-$w),$x,round($y+$w)); + + // Setup CSIM + if( $this->csimtarget != '' ) { + $this->mark->SetCSIMTarget( $this->csimtarget ); + $this->mark->SetCSIMAlt( $this->csimalt ); + } + + $this->mark->Stroke($aImg,$x,$y); + $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y); + + $this->csimarea .= $this->mark->GetCSIMAreas(); + } +} + + +//=================================================== +// CLASS GanttVLine +// Responsible for formatting individual milestones +//=================================================== + +class TextPropertyBelow extends TextProperty { + function __construct($aTxt='') { + parent::__construct($aTxt); + } + + function GetColWidth($aImg,$aMargin=0) { + // Since we are not stroking the title in the columns + // but rather under the graph we want this to return 0. + return array(0); + } +} + +class GanttVLine extends GanttPlotObject { + + private $iLine,$title_margin=3, $iDayOffset=0.5; + private $iStartRow = -1, $iEndRow = -1; + + //--------------- + // CONSTRUCTOR + function __construct($aDate,$aTitle="",$aColor="darkred",$aWeight=2,$aStyle="solid") { + GanttPlotObject::__construct(); + $this->iLine = new LineProperty(); + $this->iLine->SetColor($aColor); + $this->iLine->SetWeight($aWeight); + $this->iLine->SetStyle($aStyle); + $this->iStart = $aDate; + $this->title = new TextPropertyBelow(); + $this->title->Set($aTitle); + } + + //--------------- + // PUBLIC METHODS + + // Set start and end rows for the VLine. By default the entire heigh of the + // Gantt chart is used + function SetRowSpan($aStart, $aEnd=-1) { + $this->iStartRow = $aStart; + $this->iEndRow = $aEnd; + } + + function SetDayOffset($aOff=0.5) { + if( $aOff < 0.0 || $aOff > 1.0 ) { + JpGraphError::RaiseL(6029); + //("Offset for vertical line must be in range [0,1]"); + } + $this->iDayOffset = $aOff; + } + + function SetTitleMargin($aMarg) { + $this->title_margin = $aMarg; + } + + function SetWeight($aWeight) { + $this->iLine->SetWeight($aWeight); + } + + function Stroke($aImg,$aScale) { + $d = $aScale->NormalizeDate($this->iStart); + if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) + return; + if($this->iDayOffset != 0.0) + $d += 24*60*60*$this->iDayOffset; + $x = $aScale->TranslateDate($d);//d=1006858800, + + if( $this->iStartRow > -1 ) { + $y1 = $aScale->TranslateVertPos($this->iStartRow,true) ; + } + else { + $y1 = $aScale->iVertHeaderSize+$aImg->top_margin; + } + + if( $this->iEndRow > -1 ) { + $y2 = $aScale->TranslateVertPos($this->iEndRow); + } + else { + $y2 = $aImg->height - $aImg->bottom_margin; + } + + $this->iLine->Stroke($aImg,$x,$y1,$x,$y2); + $this->title->Align("center","top"); + $this->title->Stroke($aImg,$x,$y2+$this->title_margin); + } +} + +//=================================================== +// CLASS LinkArrow +// Handles the drawing of a an arrow +//=================================================== +class LinkArrow { + private $ix,$iy; + private $isizespec = array( + array(2,3),array(3,5),array(3,8),array(6,15),array(8,22)); + private $iDirection=ARROW_DOWN,$iType=ARROWT_SOLID,$iSize=ARROW_S2; + private $iColor='black'; + + function __construct($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) { + $this->iDirection = $aDirection; + $this->iType = $aType; + $this->iSize = $aSize; + $this->ix = $x; + $this->iy = $y; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function SetSize($aSize) { + $this->iSize = $aSize; + } + + function SetType($aType) { + $this->iType = $aType; + } + + function Stroke($aImg) { + list($dx,$dy) = $this->isizespec[$this->iSize]; + $x = $this->ix; + $y = $this->iy; + switch ( $this->iDirection ) { + case ARROW_DOWN: + $c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y); + break; + case ARROW_UP: + $c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y); + break; + case ARROW_LEFT: + $c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y); + break; + case ARROW_RIGHT: + $c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y); + break; + default: + JpGraphError::RaiseL(6030); + //('Unknown arrow direction for link.'); + die(); + break; + } + $aImg->SetColor($this->iColor); + switch( $this->iType ) { + case ARROWT_SOLID: + $aImg->FilledPolygon($c); + break; + case ARROWT_OPEN: + $aImg->Polygon($c); + break; + default: + JpGraphError::RaiseL(6031); + //('Unknown arrow type for link.'); + die(); + break; + } + } +} + +//=================================================== +// CLASS GanttLink +// Handles the drawing of a link line between 2 points +//=================================================== + +class GanttLink { + private $ix1,$ix2,$iy1,$iy2; + private $iPathType=2,$iPathExtend=15; + private $iColor='black',$iWeight=1; + private $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID; + + function __construct($x1=0,$y1=0,$x2=0,$y2=0) { + $this->ix1 = $x1; + $this->ix2 = $x2; + $this->iy1 = $y1; + $this->iy2 = $y2; + } + + function SetPos($x1,$y1,$x2,$y2) { + $this->ix1 = $x1; + $this->ix2 = $x2; + $this->iy1 = $y1; + $this->iy2 = $y2; + } + + function SetPath($aPath) { + $this->iPathType = $aPath; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function SetArrow($aSize,$aType=ARROWT_SOLID) { + $this->iArrowSize = $aSize; + $this->iArrowType = $aType; + } + + function SetWeight($aWeight) { + $this->iWeight = $aWeight; + } + + function Stroke($aImg) { + // The way the path for the arrow is constructed is partly based + // on some heuristics. This is not an exact science but draws the + // path in a way that, for me, makes esthetic sence. For example + // if the start and end activities are very close we make a small + // detour to endter the target horixontally. If there are more + // space between axctivities then no suh detour is made and the + // target is "hit" directly vertical. I have tried to keep this + // simple. no doubt this could become almost infinitive complex + // and have some real AI. Feel free to modify this. + // This will no-doubt be tweaked as times go by. One design aim + // is to avoid having the user choose what types of arrow + // he wants. + + // The arrow is drawn between (x1,y1) to (x2,y2) + $x1 = $this->ix1 ; + $x2 = $this->ix2 ; + $y1 = $this->iy1 ; + $y2 = $this->iy2 ; + + // Depending on if the target is below or above we have to + // handle thi different. + if( $y2 > $y1 ) { + $arrowtype = ARROW_DOWN; + $midy = round(($y2-$y1)/2+$y1); + if( $x2 > $x1 ) { + switch ( $this->iPathType ) { + case 0: + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + break; + case 1: + case 2: + case 3: + $c = array($x1,$y1,$x2,$y1,$x2,$y2); + break; + default: + JpGraphError::RaiseL(6032,$this->iPathType); + //('Internal error: Unknown path type (='.$this->iPathType .') specified for link.'); + exit(1); + break; + } + } + else { + switch ( $this->iPathType ) { + case 0: + case 1: + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + break; + case 2: + // Always extend out horizontally a bit from the first point + // If we draw a link back in time (end to start) and the bars + // are very close we also change the path so it comes in from + // the left on the activity + $c = array($x1,$y1,$x1+$this->iPathExtend,$y1, + $x1+$this->iPathExtend,$midy, + $x2,$midy,$x2,$y2); + break; + case 3: + if( $y2-$midy < 6 ) { + $c = array($x1,$y1,$x1,$midy, + $x2-$this->iPathExtend,$midy, + $x2-$this->iPathExtend,$y2, + $x2,$y2); + $arrowtype = ARROW_RIGHT; + } + else { + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + } + break; + default: + JpGraphError::RaiseL(6032,$this->iPathType); + //('Internal error: Unknown path type specified for link.'); + exit(1); + break; + } + } + $arrow = new LinkArrow($x2,$y2,$arrowtype); + } + else { + // Y2 < Y1 + $arrowtype = ARROW_UP; + $midy = round(($y1-$y2)/2+$y2); + if( $x2 > $x1 ) { + switch ( $this->iPathType ) { + case 0: + case 1: + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + break; + case 3: + if( $midy-$y2 < 8 ) { + $arrowtype = ARROW_RIGHT; + $c = array($x1,$y1,$x1,$y2,$x2,$y2); + } + else { + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + } + break; + default: + JpGraphError::RaiseL(6032,$this->iPathType); + //('Internal error: Unknown path type specified for link.'); + break; + } + } + else { + switch ( $this->iPathType ) { + case 0: + case 1: + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + break; + case 2: + // Always extend out horizontally a bit from the first point + $c = array($x1,$y1,$x1+$this->iPathExtend,$y1, + $x1+$this->iPathExtend,$midy, + $x2,$midy,$x2,$y2); + break; + case 3: + if( $midy-$y2 < 16 ) { + $arrowtype = ARROW_RIGHT; + $c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy, + $x2-$this->iPathExtend,$y2, + $x2,$y2); + } + else { + $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); + } + break; + default: + JpGraphError::RaiseL(6032,$this->iPathType); + //('Internal error: Unknown path type specified for link.'); + break; + } + } + $arrow = new LinkArrow($x2,$y2,$arrowtype); + } + $aImg->SetColor($this->iColor); + $aImg->SetLineWeight($this->iWeight); + $aImg->Polygon($c); + $aImg->SetLineWeight(1); + $arrow->SetColor($this->iColor); + $arrow->SetSize($this->iArrowSize); + $arrow->SetType($this->iArrowType); + $arrow->Stroke($aImg); + } +} + +// +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_gb2312.php b/web/public_php/admin/jpgraph/jpgraph_gb2312.php index df99a1173..eff07cbc5 100644 --- a/web/public_php/admin/jpgraph/jpgraph_gb2312.php +++ b/web/public_php/admin/jpgraph/jpgraph_gb2312.php @@ -1,1553 +1,1552 @@ - 12288, 8482 => 12289, 8483 => 12290, 8484 => 12539, 8485 => 713, - 8486 => 711, 8487 => 168, 8488 => 12291, 8489 => 12293, 8490 => 8213, - 8491 => 65374, 8492 => 8214, 8493 => 8230, 8494 => 8216, 8495 => 8217, - 8496 => 8220, 8497 => 8221, 8498 => 12308, 8499 => 12309, 8500 => 12296, - 8501 => 12297, 8502 => 12298, 8503 => 12299, 8504 => 12300, 8505 => 12301, - 8506 => 12302, 8507 => 12303, 8508 => 12310, 8509 => 12311, 8510 => 12304, - 8511 => 12305, 8512 => 177, 8513 => 215, 8514 => 247, 8515 => 8758, - 8516 => 8743, 8517 => 8744, 8518 => 8721, 8519 => 8719, 8520 => 8746, - 8521 => 8745, 8522 => 8712, 8523 => 8759, 8524 => 8730, 8525 => 8869, - 8526 => 8741, 8527 => 8736, 8528 => 8978, 8529 => 8857, 8530 => 8747, - 8531 => 8750, 8532 => 8801, 8533 => 8780, 8534 => 8776, 8535 => 8765, - 8536 => 8733, 8537 => 8800, 8538 => 8814, 8539 => 8815, 8540 => 8804, - 8541 => 8805, 8542 => 8734, 8543 => 8757, 8544 => 8756, 8545 => 9794, - 8546 => 9792, 8547 => 176, 8548 => 8242, 8549 => 8243, 8550 => 8451, - 8551 => 65284, 8552 => 164, 8553 => 65504, 8554 => 65505, 8555 => 8240, - 8556 => 167, 8557 => 8470, 8558 => 9734, 8559 => 9733, 8560 => 9675, - 8561 => 9679, 8562 => 9678, 8563 => 9671, 8564 => 9670, 8565 => 9633, - 8566 => 9632, 8567 => 9651, 8568 => 9650, 8569 => 8251, 8570 => 8594, - 8571 => 8592, 8572 => 8593, 8573 => 8595, 8574 => 12307, 8753 => 9352, - 8754 => 9353, 8755 => 9354, 8756 => 9355, 8757 => 9356, 8758 => 9357, - 8759 => 9358, 8760 => 9359, 8761 => 9360, 8762 => 9361, 8763 => 9362, - 8764 => 9363, 8765 => 9364, 8766 => 9365, 8767 => 9366, 8768 => 9367, - 8769 => 9368, 8770 => 9369, 8771 => 9370, 8772 => 9371, 8773 => 9332, - 8774 => 9333, 8775 => 9334, 8776 => 9335, 8777 => 9336, 8778 => 9337, - 8779 => 9338, 8780 => 9339, 8781 => 9340, 8782 => 9341, 8783 => 9342, - 8784 => 9343, 8785 => 9344, 8786 => 9345, 8787 => 9346, 8788 => 9347, - 8789 => 9348, 8790 => 9349, 8791 => 9350, 8792 => 9351, 8793 => 9312, - 8794 => 9313, 8795 => 9314, 8796 => 9315, 8797 => 9316, 8798 => 9317, - 8799 => 9318, 8800 => 9319, 8801 => 9320, 8802 => 9321, 8805 => 12832, - 8806 => 12833, 8807 => 12834, 8808 => 12835, 8809 => 12836, 8810 => 12837, - 8811 => 12838, 8812 => 12839, 8813 => 12840, 8814 => 12841, 8817 => 8544, - 8818 => 8545, 8819 => 8546, 8820 => 8547, 8821 => 8548, 8822 => 8549, - 8823 => 8550, 8824 => 8551, 8825 => 8552, 8826 => 8553, 8827 => 8554, - 8828 => 8555, 8993 => 65281, 8994 => 65282, 8995 => 65283, 8996 => 65509, - 8997 => 65285, 8998 => 65286, 8999 => 65287, 9000 => 65288, 9001 => 65289, - 9002 => 65290, 9003 => 65291, 9004 => 65292, 9005 => 65293, 9006 => 65294, - 9007 => 65295, 9008 => 65296, 9009 => 65297, 9010 => 65298, 9011 => 65299, - 9012 => 65300, 9013 => 65301, 9014 => 65302, 9015 => 65303, 9016 => 65304, - 9017 => 65305, 9018 => 65306, 9019 => 65307, 9020 => 65308, 9021 => 65309, - 9022 => 65310, 9023 => 65311, 9024 => 65312, 9025 => 65313, 9026 => 65314, - 9027 => 65315, 9028 => 65316, 9029 => 65317, 9030 => 65318, 9031 => 65319, - 9032 => 65320, 9033 => 65321, 9034 => 65322, 9035 => 65323, 9036 => 65324, - 9037 => 65325, 9038 => 65326, 9039 => 65327, 9040 => 65328, 9041 => 65329, - 9042 => 65330, 9043 => 65331, 9044 => 65332, 9045 => 65333, 9046 => 65334, - 9047 => 65335, 9048 => 65336, 9049 => 65337, 9050 => 65338, 9051 => 65339, - 9052 => 65340, 9053 => 65341, 9054 => 65342, 9055 => 65343, 9056 => 65344, - 9057 => 65345, 9058 => 65346, 9059 => 65347, 9060 => 65348, 9061 => 65349, - 9062 => 65350, 9063 => 65351, 9064 => 65352, 9065 => 65353, 9066 => 65354, - 9067 => 65355, 9068 => 65356, 9069 => 65357, 9070 => 65358, 9071 => 65359, - 9072 => 65360, 9073 => 65361, 9074 => 65362, 9075 => 65363, 9076 => 65364, - 9077 => 65365, 9078 => 65366, 9079 => 65367, 9080 => 65368, 9081 => 65369, - 9082 => 65370, 9083 => 65371, 9084 => 65372, 9085 => 65373, 9086 => 65507, - 9249 => 12353, 9250 => 12354, 9251 => 12355, 9252 => 12356, 9253 => 12357, - 9254 => 12358, 9255 => 12359, 9256 => 12360, 9257 => 12361, 9258 => 12362, - 9259 => 12363, 9260 => 12364, 9261 => 12365, 9262 => 12366, 9263 => 12367, - 9264 => 12368, 9265 => 12369, 9266 => 12370, 9267 => 12371, 9268 => 12372, - 9269 => 12373, 9270 => 12374, 9271 => 12375, 9272 => 12376, 9273 => 12377, - 9274 => 12378, 9275 => 12379, 9276 => 12380, 9277 => 12381, 9278 => 12382, - 9279 => 12383, 9280 => 12384, 9281 => 12385, 9282 => 12386, 9283 => 12387, - 9284 => 12388, 9285 => 12389, 9286 => 12390, 9287 => 12391, 9288 => 12392, - 9289 => 12393, 9290 => 12394, 9291 => 12395, 9292 => 12396, 9293 => 12397, - 9294 => 12398, 9295 => 12399, 9296 => 12400, 9297 => 12401, 9298 => 12402, - 9299 => 12403, 9300 => 12404, 9301 => 12405, 9302 => 12406, 9303 => 12407, - 9304 => 12408, 9305 => 12409, 9306 => 12410, 9307 => 12411, 9308 => 12412, - 9309 => 12413, 9310 => 12414, 9311 => 12415, 9312 => 12416, 9313 => 12417, - 9314 => 12418, 9315 => 12419, 9316 => 12420, 9317 => 12421, 9318 => 12422, - 9319 => 12423, 9320 => 12424, 9321 => 12425, 9322 => 12426, 9323 => 12427, - 9324 => 12428, 9325 => 12429, 9326 => 12430, 9327 => 12431, 9328 => 12432, - 9329 => 12433, 9330 => 12434, 9331 => 12435, 9505 => 12449, 9506 => 12450, - 9507 => 12451, 9508 => 12452, 9509 => 12453, 9510 => 12454, 9511 => 12455, - 9512 => 12456, 9513 => 12457, 9514 => 12458, 9515 => 12459, 9516 => 12460, - 9517 => 12461, 9518 => 12462, 9519 => 12463, 9520 => 12464, 9521 => 12465, - 9522 => 12466, 9523 => 12467, 9524 => 12468, 9525 => 12469, 9526 => 12470, - 9527 => 12471, 9528 => 12472, 9529 => 12473, 9530 => 12474, 9531 => 12475, - 9532 => 12476, 9533 => 12477, 9534 => 12478, 9535 => 12479, 9536 => 12480, - 9537 => 12481, 9538 => 12482, 9539 => 12483, 9540 => 12484, 9541 => 12485, - 9542 => 12486, 9543 => 12487, 9544 => 12488, 9545 => 12489, 9546 => 12490, - 9547 => 12491, 9548 => 12492, 9549 => 12493, 9550 => 12494, 9551 => 12495, - 9552 => 12496, 9553 => 12497, 9554 => 12498, 9555 => 12499, 9556 => 12500, - 9557 => 12501, 9558 => 12502, 9559 => 12503, 9560 => 12504, 9561 => 12505, - 9562 => 12506, 9563 => 12507, 9564 => 12508, 9565 => 12509, 9566 => 12510, - 9567 => 12511, 9568 => 12512, 9569 => 12513, 9570 => 12514, 9571 => 12515, - 9572 => 12516, 9573 => 12517, 9574 => 12518, 9575 => 12519, 9576 => 12520, - 9577 => 12521, 9578 => 12522, 9579 => 12523, 9580 => 12524, 9581 => 12525, - 9582 => 12526, 9583 => 12527, 9584 => 12528, 9585 => 12529, 9586 => 12530, - 9587 => 12531, 9588 => 12532, 9589 => 12533, 9590 => 12534, 9761 => 913, - 9762 => 914, 9763 => 915, 9764 => 916, 9765 => 917, 9766 => 918, - 9767 => 919, 9768 => 920, 9769 => 921, 9770 => 922, 9771 => 923, - 9772 => 924, 9773 => 925, 9774 => 926, 9775 => 927, 9776 => 928, - 9777 => 929, 9778 => 931, 9779 => 932, 9780 => 933, 9781 => 934, - 9782 => 935, 9783 => 936, 9784 => 937, 9793 => 945, 9794 => 946, - 9795 => 947, 9796 => 948, 9797 => 949, 9798 => 950, 9799 => 951, - 9800 => 952, 9801 => 953, 9802 => 954, 9803 => 955, 9804 => 956, - 9805 => 957, 9806 => 958, 9807 => 959, 9808 => 960, 9809 => 961, - 9810 => 963, 9811 => 964, 9812 => 965, 9813 => 966, 9814 => 967, - 9815 => 968, 9816 => 969, 10017 => 1040, 10018 => 1041, 10019 => 1042, - 10020 => 1043, 10021 => 1044, 10022 => 1045, 10023 => 1025, 10024 => 1046, - 10025 => 1047, 10026 => 1048, 10027 => 1049, 10028 => 1050, 10029 => 1051, - 10030 => 1052, 10031 => 1053, 10032 => 1054, 10033 => 1055, 10034 => 1056, - 10035 => 1057, 10036 => 1058, 10037 => 1059, 10038 => 1060, 10039 => 1061, - 10040 => 1062, 10041 => 1063, 10042 => 1064, 10043 => 1065, 10044 => 1066, - 10045 => 1067, 10046 => 1068, 10047 => 1069, 10048 => 1070, 10049 => 1071, - 10065 => 1072, 10066 => 1073, 10067 => 1074, 10068 => 1075, 10069 => 1076, - 10070 => 1077, 10071 => 1105, 10072 => 1078, 10073 => 1079, 10074 => 1080, - 10075 => 1081, 10076 => 1082, 10077 => 1083, 10078 => 1084, 10079 => 1085, - 10080 => 1086, 10081 => 1087, 10082 => 1088, 10083 => 1089, 10084 => 1090, - 10085 => 1091, 10086 => 1092, 10087 => 1093, 10088 => 1094, 10089 => 1095, - 10090 => 1096, 10091 => 1097, 10092 => 1098, 10093 => 1099, 10094 => 1100, - 10095 => 1101, 10096 => 1102, 10097 => 1103, 10273 => 257, 10274 => 225, - 10275 => 462, 10276 => 224, 10277 => 275, 10278 => 233, 10279 => 283, - 10280 => 232, 10281 => 299, 10282 => 237, 10283 => 464, 10284 => 236, - 10285 => 333, 10286 => 243, 10287 => 466, 10288 => 242, 10289 => 363, - 10290 => 250, 10291 => 468, 10292 => 249, 10293 => 470, 10294 => 472, - 10295 => 474, 10296 => 476, 10297 => 252, 10298 => 234, 10309 => 12549, - 10310 => 12550, 10311 => 12551, 10312 => 12552, 10313 => 12553, 10314 => 12554, - 10315 => 12555, 10316 => 12556, 10317 => 12557, 10318 => 12558, 10319 => 12559, - 10320 => 12560, 10321 => 12561, 10322 => 12562, 10323 => 12563, 10324 => 12564, - 10325 => 12565, 10326 => 12566, 10327 => 12567, 10328 => 12568, 10329 => 12569, - 10330 => 12570, 10331 => 12571, 10332 => 12572, 10333 => 12573, 10334 => 12574, - 10335 => 12575, 10336 => 12576, 10337 => 12577, 10338 => 12578, 10339 => 12579, - 10340 => 12580, 10341 => 12581, 10342 => 12582, 10343 => 12583, 10344 => 12584, - 10345 => 12585, 10532 => 9472, 10533 => 9473, 10534 => 9474, 10535 => 9475, - 10536 => 9476, 10537 => 9477, 10538 => 9478, 10539 => 9479, 10540 => 9480, - 10541 => 9481, 10542 => 9482, 10543 => 9483, 10544 => 9484, 10545 => 9485, - 10546 => 9486, 10547 => 9487, 10548 => 9488, 10549 => 9489, 10550 => 9490, - 10551 => 9491, 10552 => 9492, 10553 => 9493, 10554 => 9494, 10555 => 9495, - 10556 => 9496, 10557 => 9497, 10558 => 9498, 10559 => 9499, 10560 => 9500, - 10561 => 9501, 10562 => 9502, 10563 => 9503, 10564 => 9504, 10565 => 9505, - 10566 => 9506, 10567 => 9507, 10568 => 9508, 10569 => 9509, 10570 => 9510, - 10571 => 9511, 10572 => 9512, 10573 => 9513, 10574 => 9514, 10575 => 9515, - 10576 => 9516, 10577 => 9517, 10578 => 9518, 10579 => 9519, 10580 => 9520, - 10581 => 9521, 10582 => 9522, 10583 => 9523, 10584 => 9524, 10585 => 9525, - 10586 => 9526, 10587 => 9527, 10588 => 9528, 10589 => 9529, 10590 => 9530, - 10591 => 9531, 10592 => 9532, 10593 => 9533, 10594 => 9534, 10595 => 9535, - 10596 => 9536, 10597 => 9537, 10598 => 9538, 10599 => 9539, 10600 => 9540, - 10601 => 9541, 10602 => 9542, 10603 => 9543, 10604 => 9544, 10605 => 9545, - 10606 => 9546, 10607 => 9547, 12321 => 21834, 12322 => 38463, 12323 => 22467, - 12324 => 25384, 12325 => 21710, 12326 => 21769, 12327 => 21696, 12328 => 30353, - 12329 => 30284, 12330 => 34108, 12331 => 30702, 12332 => 33406, 12333 => 30861, - 12334 => 29233, 12335 => 38552, 12336 => 38797, 12337 => 27688, 12338 => 23433, - 12339 => 20474, 12340 => 25353, 12341 => 26263, 12342 => 23736, 12343 => 33018, - 12344 => 26696, 12345 => 32942, 12346 => 26114, 12347 => 30414, 12348 => 20985, - 12349 => 25942, 12350 => 29100, 12351 => 32753, 12352 => 34948, 12353 => 20658, - 12354 => 22885, 12355 => 25034, 12356 => 28595, 12357 => 33453, 12358 => 25420, - 12359 => 25170, 12360 => 21485, 12361 => 21543, 12362 => 31494, 12363 => 20843, - 12364 => 30116, 12365 => 24052, 12366 => 25300, 12367 => 36299, 12368 => 38774, - 12369 => 25226, 12370 => 32793, 12371 => 22365, 12372 => 38712, 12373 => 32610, - 12374 => 29240, 12375 => 30333, 12376 => 26575, 12377 => 30334, 12378 => 25670, - 12379 => 20336, 12380 => 36133, 12381 => 25308, 12382 => 31255, 12383 => 26001, - 12384 => 29677, 12385 => 25644, 12386 => 25203, 12387 => 33324, 12388 => 39041, - 12389 => 26495, 12390 => 29256, 12391 => 25198, 12392 => 25292, 12393 => 20276, - 12394 => 29923, 12395 => 21322, 12396 => 21150, 12397 => 32458, 12398 => 37030, - 12399 => 24110, 12400 => 26758, 12401 => 27036, 12402 => 33152, 12403 => 32465, - 12404 => 26834, 12405 => 30917, 12406 => 34444, 12407 => 38225, 12408 => 20621, - 12409 => 35876, 12410 => 33502, 12411 => 32990, 12412 => 21253, 12413 => 35090, - 12414 => 21093, 12577 => 34180, 12578 => 38649, 12579 => 20445, 12580 => 22561, - 12581 => 39281, 12582 => 23453, 12583 => 25265, 12584 => 25253, 12585 => 26292, - 12586 => 35961, 12587 => 40077, 12588 => 29190, 12589 => 26479, 12590 => 30865, - 12591 => 24754, 12592 => 21329, 12593 => 21271, 12594 => 36744, 12595 => 32972, - 12596 => 36125, 12597 => 38049, 12598 => 20493, 12599 => 29384, 12600 => 22791, - 12601 => 24811, 12602 => 28953, 12603 => 34987, 12604 => 22868, 12605 => 33519, - 12606 => 26412, 12607 => 31528, 12608 => 23849, 12609 => 32503, 12610 => 29997, - 12611 => 27893, 12612 => 36454, 12613 => 36856, 12614 => 36924, 12615 => 40763, - 12616 => 27604, 12617 => 37145, 12618 => 31508, 12619 => 24444, 12620 => 30887, - 12621 => 34006, 12622 => 34109, 12623 => 27605, 12624 => 27609, 12625 => 27606, - 12626 => 24065, 12627 => 24199, 12628 => 30201, 12629 => 38381, 12630 => 25949, - 12631 => 24330, 12632 => 24517, 12633 => 36767, 12634 => 22721, 12635 => 33218, - 12636 => 36991, 12637 => 38491, 12638 => 38829, 12639 => 36793, 12640 => 32534, - 12641 => 36140, 12642 => 25153, 12643 => 20415, 12644 => 21464, 12645 => 21342, - 12646 => 36776, 12647 => 36777, 12648 => 36779, 12649 => 36941, 12650 => 26631, - 12651 => 24426, 12652 => 33176, 12653 => 34920, 12654 => 40150, 12655 => 24971, - 12656 => 21035, 12657 => 30250, 12658 => 24428, 12659 => 25996, 12660 => 28626, - 12661 => 28392, 12662 => 23486, 12663 => 25672, 12664 => 20853, 12665 => 20912, - 12666 => 26564, 12667 => 19993, 12668 => 31177, 12669 => 39292, 12670 => 28851, - 12833 => 30149, 12834 => 24182, 12835 => 29627, 12836 => 33760, 12837 => 25773, - 12838 => 25320, 12839 => 38069, 12840 => 27874, 12841 => 21338, 12842 => 21187, - 12843 => 25615, 12844 => 38082, 12845 => 31636, 12846 => 20271, 12847 => 24091, - 12848 => 33334, 12849 => 33046, 12850 => 33162, 12851 => 28196, 12852 => 27850, - 12853 => 39539, 12854 => 25429, 12855 => 21340, 12856 => 21754, 12857 => 34917, - 12858 => 22496, 12859 => 19981, 12860 => 24067, 12861 => 27493, 12862 => 31807, - 12863 => 37096, 12864 => 24598, 12865 => 25830, 12866 => 29468, 12867 => 35009, - 12868 => 26448, 12869 => 25165, 12870 => 36130, 12871 => 30572, 12872 => 36393, - 12873 => 37319, 12874 => 24425, 12875 => 33756, 12876 => 34081, 12877 => 39184, - 12878 => 21442, 12879 => 34453, 12880 => 27531, 12881 => 24813, 12882 => 24808, - 12883 => 28799, 12884 => 33485, 12885 => 33329, 12886 => 20179, 12887 => 27815, - 12888 => 34255, 12889 => 25805, 12890 => 31961, 12891 => 27133, 12892 => 26361, - 12893 => 33609, 12894 => 21397, 12895 => 31574, 12896 => 20391, 12897 => 20876, - 12898 => 27979, 12899 => 23618, 12900 => 36461, 12901 => 25554, 12902 => 21449, - 12903 => 33580, 12904 => 33590, 12905 => 26597, 12906 => 30900, 12907 => 25661, - 12908 => 23519, 12909 => 23700, 12910 => 24046, 12911 => 35815, 12912 => 25286, - 12913 => 26612, 12914 => 35962, 12915 => 25600, 12916 => 25530, 12917 => 34633, - 12918 => 39307, 12919 => 35863, 12920 => 32544, 12921 => 38130, 12922 => 20135, - 12923 => 38416, 12924 => 39076, 12925 => 26124, 12926 => 29462, 13089 => 22330, - 13090 => 23581, 13091 => 24120, 13092 => 38271, 13093 => 20607, 13094 => 32928, - 13095 => 21378, 13096 => 25950, 13097 => 30021, 13098 => 21809, 13099 => 20513, - 13100 => 36229, 13101 => 25220, 13102 => 38046, 13103 => 26397, 13104 => 22066, - 13105 => 28526, 13106 => 24034, 13107 => 21557, 13108 => 28818, 13109 => 36710, - 13110 => 25199, 13111 => 25764, 13112 => 25507, 13113 => 24443, 13114 => 28552, - 13115 => 37108, 13116 => 33251, 13117 => 36784, 13118 => 23576, 13119 => 26216, - 13120 => 24561, 13121 => 27785, 13122 => 38472, 13123 => 36225, 13124 => 34924, - 13125 => 25745, 13126 => 31216, 13127 => 22478, 13128 => 27225, 13129 => 25104, - 13130 => 21576, 13131 => 20056, 13132 => 31243, 13133 => 24809, 13134 => 28548, - 13135 => 35802, 13136 => 25215, 13137 => 36894, 13138 => 39563, 13139 => 31204, -13140 => 21507, 13141 => 30196, 13142 => 25345, 13143 => 21273, 13144 => 27744, -13145 => 36831, 13146 => 24347, 13147 => 39536, 13148 => 32827, 13149 => 40831, -13150 => 20360, 13151 => 23610, 13152 => 36196, 13153 => 32709, 13154 => 26021, -13155 => 28861, 13156 => 20805, 13157 => 20914, 13158 => 34411, 13159 => 23815, -13160 => 23456, 13161 => 25277, 13162 => 37228, 13163 => 30068, 13164 => 36364, -13165 => 31264, 13166 => 24833, 13167 => 31609, 13168 => 20167, 13169 => 32504, -13170 => 30597, 13171 => 19985, 13172 => 33261, 13173 => 21021, 13174 => 20986, -13175 => 27249, 13176 => 21416, 13177 => 36487, 13178 => 38148, 13179 => 38607, -13180 => 28353, 13181 => 38500, 13182 => 26970, 13345 => 30784, 13346 => 20648, -13347 => 30679, 13348 => 25616, 13349 => 35302, 13350 => 22788, 13351 => 25571, -13352 => 24029, 13353 => 31359, 13354 => 26941, 13355 => 20256, 13356 => 33337, -13357 => 21912, 13358 => 20018, 13359 => 30126, 13360 => 31383, 13361 => 24162, -13362 => 24202, 13363 => 38383, 13364 => 21019, 13365 => 21561, 13366 => 28810, -13367 => 25462, 13368 => 38180, 13369 => 22402, 13370 => 26149, 13371 => 26943, -13372 => 37255, 13373 => 21767, 13374 => 28147, 13375 => 32431, 13376 => 34850, -13377 => 25139, 13378 => 32496, 13379 => 30133, 13380 => 33576, 13381 => 30913, -13382 => 38604, 13383 => 36766, 13384 => 24904, 13385 => 29943, 13386 => 35789, -13387 => 27492, 13388 => 21050, 13389 => 36176, 13390 => 27425, 13391 => 32874, -13392 => 33905, 13393 => 22257, 13394 => 21254, 13395 => 20174, 13396 => 19995, -13397 => 20945, 13398 => 31895, 13399 => 37259, 13400 => 31751, 13401 => 20419, -13402 => 36479, 13403 => 31713, 13404 => 31388, 13405 => 25703, 13406 => 23828, -13407 => 20652, 13408 => 33030, 13409 => 30209, 13410 => 31929, 13411 => 28140, -13412 => 32736, 13413 => 26449, 13414 => 23384, 13415 => 23544, 13416 => 30923, -13417 => 25774, 13418 => 25619, 13419 => 25514, 13420 => 25387, 13421 => 38169, -13422 => 25645, 13423 => 36798, 13424 => 31572, 13425 => 30249, 13426 => 25171, -13427 => 22823, 13428 => 21574, 13429 => 27513, 13430 => 20643, 13431 => 25140, -13432 => 24102, 13433 => 27526, 13434 => 20195, 13435 => 36151, 13436 => 34955, -13437 => 24453, 13438 => 36910, 13601 => 24608, 13602 => 32829, 13603 => 25285, -13604 => 20025, 13605 => 21333, 13606 => 37112, 13607 => 25528, 13608 => 32966, -13609 => 26086, 13610 => 27694, 13611 => 20294, 13612 => 24814, 13613 => 28129, -13614 => 35806, 13615 => 24377, 13616 => 34507, 13617 => 24403, 13618 => 25377, -13619 => 20826, 13620 => 33633, 13621 => 26723, 13622 => 20992, 13623 => 25443, -13624 => 36424, 13625 => 20498, 13626 => 23707, 13627 => 31095, 13628 => 23548, -13629 => 21040, 13630 => 31291, 13631 => 24764, 13632 => 36947, 13633 => 30423, -13634 => 24503, 13635 => 24471, 13636 => 30340, 13637 => 36460, 13638 => 28783, -13639 => 30331, 13640 => 31561, 13641 => 30634, 13642 => 20979, 13643 => 37011, -13644 => 22564, 13645 => 20302, 13646 => 28404, 13647 => 36842, 13648 => 25932, -13649 => 31515, 13650 => 29380, 13651 => 28068, 13652 => 32735, 13653 => 23265, -13654 => 25269, 13655 => 24213, 13656 => 22320, 13657 => 33922, 13658 => 31532, -13659 => 24093, 13660 => 24351, 13661 => 36882, 13662 => 32532, 13663 => 39072, -13664 => 25474, 13665 => 28359, 13666 => 30872, 13667 => 28857, 13668 => 20856, -13669 => 38747, 13670 => 22443, 13671 => 30005, 13672 => 20291, 13673 => 30008, -13674 => 24215, 13675 => 24806, 13676 => 22880, 13677 => 28096, 13678 => 27583, -13679 => 30857, 13680 => 21500, 13681 => 38613, 13682 => 20939, 13683 => 20993, -13684 => 25481, 13685 => 21514, 13686 => 38035, 13687 => 35843, 13688 => 36300, -13689 => 29241, 13690 => 30879, 13691 => 34678, 13692 => 36845, 13693 => 35853, -13694 => 21472, 13857 => 19969, 13858 => 30447, 13859 => 21486, 13860 => 38025, -13861 => 39030, 13862 => 40718, 13863 => 38189, 13864 => 23450, 13865 => 35746, -13866 => 20002, 13867 => 19996, 13868 => 20908, 13869 => 33891, 13870 => 25026, -13871 => 21160, 13872 => 26635, 13873 => 20375, 13874 => 24683, 13875 => 20923, -13876 => 27934, 13877 => 20828, 13878 => 25238, 13879 => 26007, 13880 => 38497, -13881 => 35910, 13882 => 36887, 13883 => 30168, 13884 => 37117, 13885 => 30563, -13886 => 27602, 13887 => 29322, 13888 => 29420, 13889 => 35835, 13890 => 22581, -13891 => 30585, 13892 => 36172, 13893 => 26460, 13894 => 38208, 13895 => 32922, -13896 => 24230, 13897 => 28193, 13898 => 22930, 13899 => 31471, 13900 => 30701, -13901 => 38203, 13902 => 27573, 13903 => 26029, 13904 => 32526, 13905 => 22534, -13906 => 20817, 13907 => 38431, 13908 => 23545, 13909 => 22697, 13910 => 21544, -13911 => 36466, 13912 => 25958, 13913 => 39039, 13914 => 22244, 13915 => 38045, -13916 => 30462, 13917 => 36929, 13918 => 25479, 13919 => 21702, 13920 => 22810, -13921 => 22842, 13922 => 22427, 13923 => 36530, 13924 => 26421, 13925 => 36346, -13926 => 33333, 13927 => 21057, 13928 => 24816, 13929 => 22549, 13930 => 34558, -13931 => 23784, 13932 => 40517, 13933 => 20420, 13934 => 39069, 13935 => 35769, -13936 => 23077, 13937 => 24694, 13938 => 21380, 13939 => 25212, 13940 => 36943, -13941 => 37122, 13942 => 39295, 13943 => 24681, 13944 => 32780, 13945 => 20799, -13946 => 32819, 13947 => 23572, 13948 => 39285, 13949 => 27953, 13950 => 20108, -14113 => 36144, 14114 => 21457, 14115 => 32602, 14116 => 31567, 14117 => 20240, -14118 => 20047, 14119 => 38400, 14120 => 27861, 14121 => 29648, 14122 => 34281, -14123 => 24070, 14124 => 30058, 14125 => 32763, 14126 => 27146, 14127 => 30718, -14128 => 38034, 14129 => 32321, 14130 => 20961, 14131 => 28902, 14132 => 21453, -14133 => 36820, 14134 => 33539, 14135 => 36137, 14136 => 29359, 14137 => 39277, -14138 => 27867, 14139 => 22346, 14140 => 33459, 14141 => 26041, 14142 => 32938, -14143 => 25151, 14144 => 38450, 14145 => 22952, 14146 => 20223, 14147 => 35775, -14148 => 32442, 14149 => 25918, 14150 => 33778, 14151 => 38750, 14152 => 21857, -14153 => 39134, 14154 => 32933, 14155 => 21290, 14156 => 35837, 14157 => 21536, -14158 => 32954, 14159 => 24223, 14160 => 27832, 14161 => 36153, 14162 => 33452, -14163 => 37210, 14164 => 21545, 14165 => 27675, 14166 => 20998, 14167 => 32439, -14168 => 22367, 14169 => 28954, 14170 => 27774, 14171 => 31881, 14172 => 22859, -14173 => 20221, 14174 => 24575, 14175 => 24868, 14176 => 31914, 14177 => 20016, -14178 => 23553, 14179 => 26539, 14180 => 34562, 14181 => 23792, 14182 => 38155, -14183 => 39118, 14184 => 30127, 14185 => 28925, 14186 => 36898, 14187 => 20911, -14188 => 32541, 14189 => 35773, 14190 => 22857, 14191 => 20964, 14192 => 20315, -14193 => 21542, 14194 => 22827, 14195 => 25975, 14196 => 32932, 14197 => 23413, -14198 => 25206, 14199 => 25282, 14200 => 36752, 14201 => 24133, 14202 => 27679, -14203 => 31526, 14204 => 20239, 14205 => 20440, 14206 => 26381, 14369 => 28014, -14370 => 28074, 14371 => 31119, 14372 => 34993, 14373 => 24343, 14374 => 29995, -14375 => 25242, 14376 => 36741, 14377 => 20463, 14378 => 37340, 14379 => 26023, -14380 => 33071, 14381 => 33105, 14382 => 24220, 14383 => 33104, 14384 => 36212, -14385 => 21103, 14386 => 35206, 14387 => 36171, 14388 => 22797, 14389 => 20613, -14390 => 20184, 14391 => 38428, 14392 => 29238, 14393 => 33145, 14394 => 36127, -14395 => 23500, 14396 => 35747, 14397 => 38468, 14398 => 22919, 14399 => 32538, -14400 => 21648, 14401 => 22134, 14402 => 22030, 14403 => 35813, 14404 => 25913, -14405 => 27010, 14406 => 38041, 14407 => 30422, 14408 => 28297, 14409 => 24178, -14410 => 29976, 14411 => 26438, 14412 => 26577, 14413 => 31487, 14414 => 32925, -14415 => 36214, 14416 => 24863, 14417 => 31174, 14418 => 25954, 14419 => 36195, -14420 => 20872, 14421 => 21018, 14422 => 38050, 14423 => 32568, 14424 => 32923, -14425 => 32434, 14426 => 23703, 14427 => 28207, 14428 => 26464, 14429 => 31705, -14430 => 30347, 14431 => 39640, 14432 => 33167, 14433 => 32660, 14434 => 31957, -14435 => 25630, 14436 => 38224, 14437 => 31295, 14438 => 21578, 14439 => 21733, -14440 => 27468, 14441 => 25601, 14442 => 25096, 14443 => 40509, 14444 => 33011, -14445 => 30105, 14446 => 21106, 14447 => 38761, 14448 => 33883, 14449 => 26684, -14450 => 34532, 14451 => 38401, 14452 => 38548, 14453 => 38124, 14454 => 20010, -14455 => 21508, 14456 => 32473, 14457 => 26681, 14458 => 36319, 14459 => 32789, -14460 => 26356, 14461 => 24218, 14462 => 32697, 14625 => 22466, 14626 => 32831, -14627 => 26775, 14628 => 24037, 14629 => 25915, 14630 => 21151, 14631 => 24685, -14632 => 40858, 14633 => 20379, 14634 => 36524, 14635 => 20844, 14636 => 23467, -14637 => 24339, 14638 => 24041, 14639 => 27742, 14640 => 25329, 14641 => 36129, -14642 => 20849, 14643 => 38057, 14644 => 21246, 14645 => 27807, 14646 => 33503, -14647 => 29399, 14648 => 22434, 14649 => 26500, 14650 => 36141, 14651 => 22815, -14652 => 36764, 14653 => 33735, 14654 => 21653, 14655 => 31629, 14656 => 20272, -14657 => 27837, 14658 => 23396, 14659 => 22993, 14660 => 40723, 14661 => 21476, -14662 => 34506, 14663 => 39592, 14664 => 35895, 14665 => 32929, 14666 => 25925, -14667 => 39038, 14668 => 22266, 14669 => 38599, 14670 => 21038, 14671 => 29916, -14672 => 21072, 14673 => 23521, 14674 => 25346, 14675 => 35074, 14676 => 20054, -14677 => 25296, 14678 => 24618, 14679 => 26874, 14680 => 20851, 14681 => 23448, -14682 => 20896, 14683 => 35266, 14684 => 31649, 14685 => 39302, 14686 => 32592, -14687 => 24815, 14688 => 28748, 14689 => 36143, 14690 => 20809, 14691 => 24191, -14692 => 36891, 14693 => 29808, 14694 => 35268, 14695 => 22317, 14696 => 30789, -14697 => 24402, 14698 => 40863, 14699 => 38394, 14700 => 36712, 14701 => 39740, -14702 => 35809, 14703 => 30328, 14704 => 26690, 14705 => 26588, 14706 => 36330, -14707 => 36149, 14708 => 21053, 14709 => 36746, 14710 => 28378, 14711 => 26829, -14712 => 38149, 14713 => 37101, 14714 => 22269, 14715 => 26524, 14716 => 35065, -14717 => 36807, 14718 => 21704, 14881 => 39608, 14882 => 23401, 14883 => 28023, -14884 => 27686, 14885 => 20133, 14886 => 23475, 14887 => 39559, 14888 => 37219, -14889 => 25000, 14890 => 37039, 14891 => 38889, 14892 => 21547, 14893 => 28085, -14894 => 23506, 14895 => 20989, 14896 => 21898, 14897 => 32597, 14898 => 32752, -14899 => 25788, 14900 => 25421, 14901 => 26097, 14902 => 25022, 14903 => 24717, -14904 => 28938, 14905 => 27735, 14906 => 27721, 14907 => 22831, 14908 => 26477, -14909 => 33322, 14910 => 22741, 14911 => 22158, 14912 => 35946, 14913 => 27627, -14914 => 37085, 14915 => 22909, 14916 => 32791, 14917 => 21495, 14918 => 28009, -14919 => 21621, 14920 => 21917, 14921 => 33655, 14922 => 33743, 14923 => 26680, -14924 => 31166, 14925 => 21644, 14926 => 20309, 14927 => 21512, 14928 => 30418, -14929 => 35977, 14930 => 38402, 14931 => 27827, 14932 => 28088, 14933 => 36203, -14934 => 35088, 14935 => 40548, 14936 => 36154, 14937 => 22079, 14938 => 40657, -14939 => 30165, 14940 => 24456, 14941 => 29408, 14942 => 24680, 14943 => 21756, -14944 => 20136, 14945 => 27178, 14946 => 34913, 14947 => 24658, 14948 => 36720, -14949 => 21700, 14950 => 28888, 14951 => 34425, 14952 => 40511, 14953 => 27946, -14954 => 23439, 14955 => 24344, 14956 => 32418, 14957 => 21897, 14958 => 20399, -14959 => 29492, 14960 => 21564, 14961 => 21402, 14962 => 20505, 14963 => 21518, -14964 => 21628, 14965 => 20046, 14966 => 24573, 14967 => 29786, 14968 => 22774, -14969 => 33899, 14970 => 32993, 14971 => 34676, 14972 => 29392, 14973 => 31946, -14974 => 28246, 15137 => 24359, 15138 => 34382, 15139 => 21804, 15140 => 25252, -15141 => 20114, 15142 => 27818, 15143 => 25143, 15144 => 33457, 15145 => 21719, -15146 => 21326, 15147 => 29502, 15148 => 28369, 15149 => 30011, 15150 => 21010, -15151 => 21270, 15152 => 35805, 15153 => 27088, 15154 => 24458, 15155 => 24576, -15156 => 28142, 15157 => 22351, 15158 => 27426, 15159 => 29615, 15160 => 26707, -15161 => 36824, 15162 => 32531, 15163 => 25442, 15164 => 24739, 15165 => 21796, -15166 => 30186, 15167 => 35938, 15168 => 28949, 15169 => 28067, 15170 => 23462, -15171 => 24187, 15172 => 33618, 15173 => 24908, 15174 => 40644, 15175 => 30970, -15176 => 34647, 15177 => 31783, 15178 => 30343, 15179 => 20976, 15180 => 24822, -15181 => 29004, 15182 => 26179, 15183 => 24140, 15184 => 24653, 15185 => 35854, -15186 => 28784, 15187 => 25381, 15188 => 36745, 15189 => 24509, 15190 => 24674, -15191 => 34516, 15192 => 22238, 15193 => 27585, 15194 => 24724, 15195 => 24935, -15196 => 21321, 15197 => 24800, 15198 => 26214, 15199 => 36159, 15200 => 31229, -15201 => 20250, 15202 => 28905, 15203 => 27719, 15204 => 35763, 15205 => 35826, -15206 => 32472, 15207 => 33636, 15208 => 26127, 15209 => 23130, 15210 => 39746, -15211 => 27985, 15212 => 28151, 15213 => 35905, 15214 => 27963, 15215 => 20249, -15216 => 28779, 15217 => 33719, 15218 => 25110, 15219 => 24785, 15220 => 38669, -15221 => 36135, 15222 => 31096, 15223 => 20987, 15224 => 22334, 15225 => 22522, -15226 => 26426, 15227 => 30072, 15228 => 31293, 15229 => 31215, 15230 => 31637, -15393 => 32908, 15394 => 39269, 15395 => 36857, 15396 => 28608, 15397 => 35749, -15398 => 40481, 15399 => 23020, 15400 => 32489, 15401 => 32521, 15402 => 21513, -15403 => 26497, 15404 => 26840, 15405 => 36753, 15406 => 31821, 15407 => 38598, -15408 => 21450, 15409 => 24613, 15410 => 30142, 15411 => 27762, 15412 => 21363, -15413 => 23241, 15414 => 32423, 15415 => 25380, 15416 => 20960, 15417 => 33034, -15418 => 24049, 15419 => 34015, 15420 => 25216, 15421 => 20864, 15422 => 23395, -15423 => 20238, 15424 => 31085, 15425 => 21058, 15426 => 24760, 15427 => 27982, -15428 => 23492, 15429 => 23490, 15430 => 35745, 15431 => 35760, 15432 => 26082, -15433 => 24524, 15434 => 38469, 15435 => 22931, 15436 => 32487, 15437 => 32426, -15438 => 22025, 15439 => 26551, 15440 => 22841, 15441 => 20339, 15442 => 23478, -15443 => 21152, 15444 => 33626, 15445 => 39050, 15446 => 36158, 15447 => 30002, -15448 => 38078, 15449 => 20551, 15450 => 31292, 15451 => 20215, 15452 => 26550, -15453 => 39550, 15454 => 23233, 15455 => 27516, 15456 => 30417, 15457 => 22362, -15458 => 23574, 15459 => 31546, 15460 => 38388, 15461 => 29006, 15462 => 20860, -15463 => 32937, 15464 => 33392, 15465 => 22904, 15466 => 32516, 15467 => 33575, -15468 => 26816, 15469 => 26604, 15470 => 30897, 15471 => 30839, 15472 => 25315, -15473 => 25441, 15474 => 31616, 15475 => 20461, 15476 => 21098, 15477 => 20943, -15478 => 33616, 15479 => 27099, 15480 => 37492, 15481 => 36341, 15482 => 36145, -15483 => 35265, 15484 => 38190, 15485 => 31661, 15486 => 20214, 15649 => 20581, -15650 => 33328, 15651 => 21073, 15652 => 39279, 15653 => 28176, 15654 => 28293, -15655 => 28071, 15656 => 24314, 15657 => 20725, 15658 => 23004, 15659 => 23558, -15660 => 27974, 15661 => 27743, 15662 => 30086, 15663 => 33931, 15664 => 26728, -15665 => 22870, 15666 => 35762, 15667 => 21280, 15668 => 37233, 15669 => 38477, -15670 => 34121, 15671 => 26898, 15672 => 30977, 15673 => 28966, 15674 => 33014, -15675 => 20132, 15676 => 37066, 15677 => 27975, 15678 => 39556, 15679 => 23047, -15680 => 22204, 15681 => 25605, 15682 => 38128, 15683 => 30699, 15684 => 20389, -15685 => 33050, 15686 => 29409, 15687 => 35282, 15688 => 39290, 15689 => 32564, -15690 => 32478, 15691 => 21119, 15692 => 25945, 15693 => 37237, 15694 => 36735, -15695 => 36739, 15696 => 21483, 15697 => 31382, 15698 => 25581, 15699 => 25509, -15700 => 30342, 15701 => 31224, 15702 => 34903, 15703 => 38454, 15704 => 25130, -15705 => 21163, 15706 => 33410, 15707 => 26708, 15708 => 26480, 15709 => 25463, -15710 => 30571, 15711 => 31469, 15712 => 27905, 15713 => 32467, 15714 => 35299, -15715 => 22992, 15716 => 25106, 15717 => 34249, 15718 => 33445, 15719 => 30028, -15720 => 20511, 15721 => 20171, 15722 => 30117, 15723 => 35819, 15724 => 23626, -15725 => 24062, 15726 => 31563, 15727 => 26020, 15728 => 37329, 15729 => 20170, -15730 => 27941, 15731 => 35167, 15732 => 32039, 15733 => 38182, 15734 => 20165, -15735 => 35880, 15736 => 36827, 15737 => 38771, 15738 => 26187, 15739 => 31105, -15740 => 36817, 15741 => 28908, 15742 => 28024, 15905 => 23613, 15906 => 21170, -15907 => 33606, 15908 => 20834, 15909 => 33550, 15910 => 30555, 15911 => 26230, -15912 => 40120, 15913 => 20140, 15914 => 24778, 15915 => 31934, 15916 => 31923, -15917 => 32463, 15918 => 20117, 15919 => 35686, 15920 => 26223, 15921 => 39048, -15922 => 38745, 15923 => 22659, 15924 => 25964, 15925 => 38236, 15926 => 24452, -15927 => 30153, 15928 => 38742, 15929 => 31455, 15930 => 31454, 15931 => 20928, -15932 => 28847, 15933 => 31384, 15934 => 25578, 15935 => 31350, 15936 => 32416, -15937 => 29590, 15938 => 38893, 15939 => 20037, 15940 => 28792, 15941 => 20061, -15942 => 37202, 15943 => 21417, 15944 => 25937, 15945 => 26087, 15946 => 33276, -15947 => 33285, 15948 => 21646, 15949 => 23601, 15950 => 30106, 15951 => 38816, -15952 => 25304, 15953 => 29401, 15954 => 30141, 15955 => 23621, 15956 => 39545, -15957 => 33738, 15958 => 23616, 15959 => 21632, 15960 => 30697, 15961 => 20030, -15962 => 27822, 15963 => 32858, 15964 => 25298, 15965 => 25454, 15966 => 24040, -15967 => 20855, 15968 => 36317, 15969 => 36382, 15970 => 38191, 15971 => 20465, -15972 => 21477, 15973 => 24807, 15974 => 28844, 15975 => 21095, 15976 => 25424, -15977 => 40515, 15978 => 23071, 15979 => 20518, 15980 => 30519, 15981 => 21367, -15982 => 32482, 15983 => 25733, 15984 => 25899, 15985 => 25225, 15986 => 25496, -15987 => 20500, 15988 => 29237, 15989 => 35273, 15990 => 20915, 15991 => 35776, -15992 => 32477, 15993 => 22343, 15994 => 33740, 15995 => 38055, 15996 => 20891, -15997 => 21531, 15998 => 23803, 16161 => 20426, 16162 => 31459, 16163 => 27994, -16164 => 37089, 16165 => 39567, 16166 => 21888, 16167 => 21654, 16168 => 21345, -16169 => 21679, 16170 => 24320, 16171 => 25577, 16172 => 26999, 16173 => 20975, -16174 => 24936, 16175 => 21002, 16176 => 22570, 16177 => 21208, 16178 => 22350, -16179 => 30733, 16180 => 30475, 16181 => 24247, 16182 => 24951, 16183 => 31968, -16184 => 25179, 16185 => 25239, 16186 => 20130, 16187 => 28821, 16188 => 32771, -16189 => 25335, 16190 => 28900, 16191 => 38752, 16192 => 22391, 16193 => 33499, -16194 => 26607, 16195 => 26869, 16196 => 30933, 16197 => 39063, 16198 => 31185, -16199 => 22771, 16200 => 21683, 16201 => 21487, 16202 => 28212, 16203 => 20811, -16204 => 21051, 16205 => 23458, 16206 => 35838, 16207 => 32943, 16208 => 21827, -16209 => 22438, 16210 => 24691, 16211 => 22353, 16212 => 21549, 16213 => 31354, -16214 => 24656, 16215 => 23380, 16216 => 25511, 16217 => 25248, 16218 => 21475, -16219 => 25187, 16220 => 23495, 16221 => 26543, 16222 => 21741, 16223 => 31391, -16224 => 33510, 16225 => 37239, 16226 => 24211, 16227 => 35044, 16228 => 22840, -16229 => 22446, 16230 => 25358, 16231 => 36328, 16232 => 33007, 16233 => 22359, -16234 => 31607, 16235 => 20393, 16236 => 24555, 16237 => 23485, 16238 => 27454, -16239 => 21281, 16240 => 31568, 16241 => 29378, 16242 => 26694, 16243 => 30719, -16244 => 30518, 16245 => 26103, 16246 => 20917, 16247 => 20111, 16248 => 30420, -16249 => 23743, 16250 => 31397, 16251 => 33909, 16252 => 22862, 16253 => 39745, -16254 => 20608, 16417 => 39304, 16418 => 24871, 16419 => 28291, 16420 => 22372, -16421 => 26118, 16422 => 25414, 16423 => 22256, 16424 => 25324, 16425 => 25193, -16426 => 24275, 16427 => 38420, 16428 => 22403, 16429 => 25289, 16430 => 21895, -16431 => 34593, 16432 => 33098, 16433 => 36771, 16434 => 21862, 16435 => 33713, -16436 => 26469, 16437 => 36182, 16438 => 34013, 16439 => 23146, 16440 => 26639, -16441 => 25318, 16442 => 31726, 16443 => 38417, 16444 => 20848, 16445 => 28572, -16446 => 35888, 16447 => 25597, 16448 => 35272, 16449 => 25042, 16450 => 32518, -16451 => 28866, 16452 => 28389, 16453 => 29701, 16454 => 27028, 16455 => 29436, -16456 => 24266, 16457 => 37070, 16458 => 26391, 16459 => 28010, 16460 => 25438, -16461 => 21171, 16462 => 29282, 16463 => 32769, 16464 => 20332, 16465 => 23013, -16466 => 37226, 16467 => 28889, 16468 => 28061, 16469 => 21202, 16470 => 20048, -16471 => 38647, 16472 => 38253, 16473 => 34174, 16474 => 30922, 16475 => 32047, -16476 => 20769, 16477 => 22418, 16478 => 25794, 16479 => 32907, 16480 => 31867, -16481 => 27882, 16482 => 26865, 16483 => 26974, 16484 => 20919, 16485 => 21400, -16486 => 26792, 16487 => 29313, 16488 => 40654, 16489 => 31729, 16490 => 29432, -16491 => 31163, 16492 => 28435, 16493 => 29702, 16494 => 26446, 16495 => 37324, -16496 => 40100, 16497 => 31036, 16498 => 33673, 16499 => 33620, 16500 => 21519, -16501 => 26647, 16502 => 20029, 16503 => 21385, 16504 => 21169, 16505 => 30782, -16506 => 21382, 16507 => 21033, 16508 => 20616, 16509 => 20363, 16510 => 20432, -16673 => 30178, 16674 => 31435, 16675 => 31890, 16676 => 27813, 16677 => 38582, -16678 => 21147, 16679 => 29827, 16680 => 21737, 16681 => 20457, 16682 => 32852, -16683 => 33714, 16684 => 36830, 16685 => 38256, 16686 => 24265, 16687 => 24604, -16688 => 28063, 16689 => 24088, 16690 => 25947, 16691 => 33080, 16692 => 38142, -16693 => 24651, 16694 => 28860, 16695 => 32451, 16696 => 31918, 16697 => 20937, -16698 => 26753, 16699 => 31921, 16700 => 33391, 16701 => 20004, 16702 => 36742, -16703 => 37327, 16704 => 26238, 16705 => 20142, 16706 => 35845, 16707 => 25769, -16708 => 32842, 16709 => 20698, 16710 => 30103, 16711 => 29134, 16712 => 23525, -16713 => 36797, 16714 => 28518, 16715 => 20102, 16716 => 25730, 16717 => 38243, -16718 => 24278, 16719 => 26009, 16720 => 21015, 16721 => 35010, 16722 => 28872, -16723 => 21155, 16724 => 29454, 16725 => 29747, 16726 => 26519, 16727 => 30967, -16728 => 38678, 16729 => 20020, 16730 => 37051, 16731 => 40158, 16732 => 28107, -16733 => 20955, 16734 => 36161, 16735 => 21533, 16736 => 25294, 16737 => 29618, -16738 => 33777, 16739 => 38646, 16740 => 40836, 16741 => 38083, 16742 => 20278, -16743 => 32666, 16744 => 20940, 16745 => 28789, 16746 => 38517, 16747 => 23725, -16748 => 39046, 16749 => 21478, 16750 => 20196, 16751 => 28316, 16752 => 29705, -16753 => 27060, 16754 => 30827, 16755 => 39311, 16756 => 30041, 16757 => 21016, -16758 => 30244, 16759 => 27969, 16760 => 26611, 16761 => 20845, 16762 => 40857, -16763 => 32843, 16764 => 21657, 16765 => 31548, 16766 => 31423, 16929 => 38534, -16930 => 22404, 16931 => 25314, 16932 => 38471, 16933 => 27004, 16934 => 23044, -16935 => 25602, 16936 => 31699, 16937 => 28431, 16938 => 38475, 16939 => 33446, -16940 => 21346, 16941 => 39045, 16942 => 24208, 16943 => 28809, 16944 => 25523, -16945 => 21348, 16946 => 34383, 16947 => 40065, 16948 => 40595, 16949 => 30860, -16950 => 38706, 16951 => 36335, 16952 => 36162, 16953 => 40575, 16954 => 28510, -16955 => 31108, 16956 => 24405, 16957 => 38470, 16958 => 25134, 16959 => 39540, -16960 => 21525, 16961 => 38109, 16962 => 20387, 16963 => 26053, 16964 => 23653, -16965 => 23649, 16966 => 32533, 16967 => 34385, 16968 => 27695, 16969 => 24459, -16970 => 29575, 16971 => 28388, 16972 => 32511, 16973 => 23782, 16974 => 25371, -16975 => 23402, 16976 => 28390, 16977 => 21365, 16978 => 20081, 16979 => 25504, -16980 => 30053, 16981 => 25249, 16982 => 36718, 16983 => 20262, 16984 => 20177, -16985 => 27814, 16986 => 32438, 16987 => 35770, 16988 => 33821, 16989 => 34746, -16990 => 32599, 16991 => 36923, 16992 => 38179, 16993 => 31657, 16994 => 39585, -16995 => 35064, 16996 => 33853, 16997 => 27931, 16998 => 39558, 16999 => 32476, -17000 => 22920, 17001 => 40635, 17002 => 29595, 17003 => 30721, 17004 => 34434, -17005 => 39532, 17006 => 39554, 17007 => 22043, 17008 => 21527, 17009 => 22475, -17010 => 20080, 17011 => 40614, 17012 => 21334, 17013 => 36808, 17014 => 33033, -17015 => 30610, 17016 => 39314, 17017 => 34542, 17018 => 28385, 17019 => 34067, -17020 => 26364, 17021 => 24930, 17022 => 28459, 17185 => 35881, 17186 => 33426, -17187 => 33579, 17188 => 30450, 17189 => 27667, 17190 => 24537, 17191 => 33725, -17192 => 29483, 17193 => 33541, 17194 => 38170, 17195 => 27611, 17196 => 30683, -17197 => 38086, 17198 => 21359, 17199 => 33538, 17200 => 20882, 17201 => 24125, -17202 => 35980, 17203 => 36152, 17204 => 20040, 17205 => 29611, 17206 => 26522, -17207 => 26757, 17208 => 37238, 17209 => 38665, 17210 => 29028, 17211 => 27809, -17212 => 30473, 17213 => 23186, 17214 => 38209, 17215 => 27599, 17216 => 32654, -17217 => 26151, 17218 => 23504, 17219 => 22969, 17220 => 23194, 17221 => 38376, -17222 => 38391, 17223 => 20204, 17224 => 33804, 17225 => 33945, 17226 => 27308, -17227 => 30431, 17228 => 38192, 17229 => 29467, 17230 => 26790, 17231 => 23391, -17232 => 30511, 17233 => 37274, 17234 => 38753, 17235 => 31964, 17236 => 36855, -17237 => 35868, 17238 => 24357, 17239 => 31859, 17240 => 31192, 17241 => 35269, -17242 => 27852, 17243 => 34588, 17244 => 23494, 17245 => 24130, 17246 => 26825, -17247 => 30496, 17248 => 32501, 17249 => 20885, 17250 => 20813, 17251 => 21193, -17252 => 23081, 17253 => 32517, 17254 => 38754, 17255 => 33495, 17256 => 25551, -17257 => 30596, 17258 => 34256, 17259 => 31186, 17260 => 28218, 17261 => 24217, -17262 => 22937, 17263 => 34065, 17264 => 28781, 17265 => 27665, 17266 => 25279, -17267 => 30399, 17268 => 25935, 17269 => 24751, 17270 => 38397, 17271 => 26126, -17272 => 34719, 17273 => 40483, 17274 => 38125, 17275 => 21517, 17276 => 21629, -17277 => 35884, 17278 => 25720, 17441 => 25721, 17442 => 34321, 17443 => 27169, -17444 => 33180, 17445 => 30952, 17446 => 25705, 17447 => 39764, 17448 => 25273, -17449 => 26411, 17450 => 33707, 17451 => 22696, 17452 => 40664, 17453 => 27819, -17454 => 28448, 17455 => 23518, 17456 => 38476, 17457 => 35851, 17458 => 29279, -17459 => 26576, 17460 => 25287, 17461 => 29281, 17462 => 20137, 17463 => 22982, -17464 => 27597, 17465 => 22675, 17466 => 26286, 17467 => 24149, 17468 => 21215, -17469 => 24917, 17470 => 26408, 17471 => 30446, 17472 => 30566, 17473 => 29287, -17474 => 31302, 17475 => 25343, 17476 => 21738, 17477 => 21584, 17478 => 38048, -17479 => 37027, 17480 => 23068, 17481 => 32435, 17482 => 27670, 17483 => 20035, -17484 => 22902, 17485 => 32784, 17486 => 22856, 17487 => 21335, 17488 => 30007, -17489 => 38590, 17490 => 22218, 17491 => 25376, 17492 => 33041, 17493 => 24700, -17494 => 38393, 17495 => 28118, 17496 => 21602, 17497 => 39297, 17498 => 20869, -17499 => 23273, 17500 => 33021, 17501 => 22958, 17502 => 38675, 17503 => 20522, -17504 => 27877, 17505 => 23612, 17506 => 25311, 17507 => 20320, 17508 => 21311, -17509 => 33147, 17510 => 36870, 17511 => 28346, 17512 => 34091, 17513 => 25288, -17514 => 24180, 17515 => 30910, 17516 => 25781, 17517 => 25467, 17518 => 24565, -17519 => 23064, 17520 => 37247, 17521 => 40479, 17522 => 23615, 17523 => 25423, -17524 => 32834, 17525 => 23421, 17526 => 21870, 17527 => 38218, 17528 => 38221, -17529 => 28037, 17530 => 24744, 17531 => 26592, 17532 => 29406, 17533 => 20957, -17534 => 23425, 17697 => 25319, 17698 => 27870, 17699 => 29275, 17700 => 25197, -17701 => 38062, 17702 => 32445, 17703 => 33043, 17704 => 27987, 17705 => 20892, -17706 => 24324, 17707 => 22900, 17708 => 21162, 17709 => 24594, 17710 => 22899, -17711 => 26262, 17712 => 34384, 17713 => 30111, 17714 => 25386, 17715 => 25062, -17716 => 31983, 17717 => 35834, 17718 => 21734, 17719 => 27431, 17720 => 40485, -17721 => 27572, 17722 => 34261, 17723 => 21589, 17724 => 20598, 17725 => 27812, -17726 => 21866, 17727 => 36276, 17728 => 29228, 17729 => 24085, 17730 => 24597, -17731 => 29750, 17732 => 25293, 17733 => 25490, 17734 => 29260, 17735 => 24472, -17736 => 28227, 17737 => 27966, 17738 => 25856, 17739 => 28504, 17740 => 30424, -17741 => 30928, 17742 => 30460, 17743 => 30036, 17744 => 21028, 17745 => 21467, -17746 => 20051, 17747 => 24222, 17748 => 26049, 17749 => 32810, 17750 => 32982, -17751 => 25243, 17752 => 21638, 17753 => 21032, 17754 => 28846, 17755 => 34957, -17756 => 36305, 17757 => 27873, 17758 => 21624, 17759 => 32986, 17760 => 22521, -17761 => 35060, 17762 => 36180, 17763 => 38506, 17764 => 37197, 17765 => 20329, -17766 => 27803, 17767 => 21943, 17768 => 30406, 17769 => 30768, 17770 => 25256, -17771 => 28921, 17772 => 28558, 17773 => 24429, 17774 => 34028, 17775 => 26842, -17776 => 30844, 17777 => 31735, 17778 => 33192, 17779 => 26379, 17780 => 40527, -17781 => 25447, 17782 => 30896, 17783 => 22383, 17784 => 30738, 17785 => 38713, -17786 => 25209, 17787 => 25259, 17788 => 21128, 17789 => 29749, 17790 => 27607, -17953 => 21860, 17954 => 33086, 17955 => 30130, 17956 => 30382, 17957 => 21305, -17958 => 30174, 17959 => 20731, 17960 => 23617, 17961 => 35692, 17962 => 31687, -17963 => 20559, 17964 => 29255, 17965 => 39575, 17966 => 39128, 17967 => 28418, -17968 => 29922, 17969 => 31080, 17970 => 25735, 17971 => 30629, 17972 => 25340, -17973 => 39057, 17974 => 36139, 17975 => 21697, 17976 => 32856, 17977 => 20050, -17978 => 22378, 17979 => 33529, 17980 => 33805, 17981 => 24179, 17982 => 20973, -17983 => 29942, 17984 => 35780, 17985 => 23631, 17986 => 22369, 17987 => 27900, -17988 => 39047, 17989 => 23110, 17990 => 30772, 17991 => 39748, 17992 => 36843, -17993 => 31893, 17994 => 21078, 17995 => 25169, 17996 => 38138, 17997 => 20166, -17998 => 33670, 17999 => 33889, 18000 => 33769, 18001 => 33970, 18002 => 22484, -18003 => 26420, 18004 => 22275, 18005 => 26222, 18006 => 28006, 18007 => 35889, -18008 => 26333, 18009 => 28689, 18010 => 26399, 18011 => 27450, 18012 => 26646, -18013 => 25114, 18014 => 22971, 18015 => 19971, 18016 => 20932, 18017 => 28422, -18018 => 26578, 18019 => 27791, 18020 => 20854, 18021 => 26827, 18022 => 22855, -18023 => 27495, 18024 => 30054, 18025 => 23822, 18026 => 33040, 18027 => 40784, -18028 => 26071, 18029 => 31048, 18030 => 31041, 18031 => 39569, 18032 => 36215, -18033 => 23682, 18034 => 20062, 18035 => 20225, 18036 => 21551, 18037 => 22865, -18038 => 30732, 18039 => 22120, 18040 => 27668, 18041 => 36804, 18042 => 24323, -18043 => 27773, 18044 => 27875, 18045 => 35755, 18046 => 25488, 18209 => 24688, -18210 => 27965, 18211 => 29301, 18212 => 25190, 18213 => 38030, 18214 => 38085, -18215 => 21315, 18216 => 36801, 18217 => 31614, 18218 => 20191, 18219 => 35878, -18220 => 20094, 18221 => 40660, 18222 => 38065, 18223 => 38067, 18224 => 21069, -18225 => 28508, 18226 => 36963, 18227 => 27973, 18228 => 35892, 18229 => 22545, -18230 => 23884, 18231 => 27424, 18232 => 27465, 18233 => 26538, 18234 => 21595, -18235 => 33108, 18236 => 32652, 18237 => 22681, 18238 => 34103, 18239 => 24378, -18240 => 25250, 18241 => 27207, 18242 => 38201, 18243 => 25970, 18244 => 24708, -18245 => 26725, 18246 => 30631, 18247 => 20052, 18248 => 20392, 18249 => 24039, -18250 => 38808, 18251 => 25772, 18252 => 32728, 18253 => 23789, 18254 => 20431, -18255 => 31373, 18256 => 20999, 18257 => 33540, 18258 => 19988, 18259 => 24623, -18260 => 31363, 18261 => 38054, 18262 => 20405, 18263 => 20146, 18264 => 31206, -18265 => 29748, 18266 => 21220, 18267 => 33465, 18268 => 25810, 18269 => 31165, -18270 => 23517, 18271 => 27777, 18272 => 38738, 18273 => 36731, 18274 => 27682, -18275 => 20542, 18276 => 21375, 18277 => 28165, 18278 => 25806, 18279 => 26228, -18280 => 27696, 18281 => 24773, 18282 => 39031, 18283 => 35831, 18284 => 24198, -18285 => 29756, 18286 => 31351, 18287 => 31179, 18288 => 19992, 18289 => 37041, -18290 => 29699, 18291 => 27714, 18292 => 22234, 18293 => 37195, 18294 => 27845, -18295 => 36235, 18296 => 21306, 18297 => 34502, 18298 => 26354, 18299 => 36527, -18300 => 23624, 18301 => 39537, 18302 => 28192, 18465 => 21462, 18466 => 23094, -18467 => 40843, 18468 => 36259, 18469 => 21435, 18470 => 22280, 18471 => 39079, -18472 => 26435, 18473 => 37275, 18474 => 27849, 18475 => 20840, 18476 => 30154, -18477 => 25331, 18478 => 29356, 18479 => 21048, 18480 => 21149, 18481 => 32570, -18482 => 28820, 18483 => 30264, 18484 => 21364, 18485 => 40522, 18486 => 27063, -18487 => 30830, 18488 => 38592, 18489 => 35033, 18490 => 32676, 18491 => 28982, -18492 => 29123, 18493 => 20873, 18494 => 26579, 18495 => 29924, 18496 => 22756, -18497 => 25880, 18498 => 22199, 18499 => 35753, 18500 => 39286, 18501 => 25200, -18502 => 32469, 18503 => 24825, 18504 => 28909, 18505 => 22764, 18506 => 20161, -18507 => 20154, 18508 => 24525, 18509 => 38887, 18510 => 20219, 18511 => 35748, -18512 => 20995, 18513 => 22922, 18514 => 32427, 18515 => 25172, 18516 => 20173, -18517 => 26085, 18518 => 25102, 18519 => 33592, 18520 => 33993, 18521 => 33635, -18522 => 34701, 18523 => 29076, 18524 => 28342, 18525 => 23481, 18526 => 32466, -18527 => 20887, 18528 => 25545, 18529 => 26580, 18530 => 32905, 18531 => 33593, -18532 => 34837, 18533 => 20754, 18534 => 23418, 18535 => 22914, 18536 => 36785, -18537 => 20083, 18538 => 27741, 18539 => 20837, 18540 => 35109, 18541 => 36719, -18542 => 38446, 18543 => 34122, 18544 => 29790, 18545 => 38160, 18546 => 38384, -18547 => 28070, 18548 => 33509, 18549 => 24369, 18550 => 25746, 18551 => 27922, -18552 => 33832, 18553 => 33134, 18554 => 40131, 18555 => 22622, 18556 => 36187, -18557 => 19977, 18558 => 21441, 18721 => 20254, 18722 => 25955, 18723 => 26705, -18724 => 21971, 18725 => 20007, 18726 => 25620, 18727 => 39578, 18728 => 25195, -18729 => 23234, 18730 => 29791, 18731 => 33394, 18732 => 28073, 18733 => 26862, -18734 => 20711, 18735 => 33678, 18736 => 30722, 18737 => 26432, 18738 => 21049, -18739 => 27801, 18740 => 32433, 18741 => 20667, 18742 => 21861, 18743 => 29022, -18744 => 31579, 18745 => 26194, 18746 => 29642, 18747 => 33515, 18748 => 26441, -18749 => 23665, 18750 => 21024, 18751 => 29053, 18752 => 34923, 18753 => 38378, -18754 => 38485, 18755 => 25797, 18756 => 36193, 18757 => 33203, 18758 => 21892, -18759 => 27733, 18760 => 25159, 18761 => 32558, 18762 => 22674, 18763 => 20260, -18764 => 21830, 18765 => 36175, 18766 => 26188, 18767 => 19978, 18768 => 23578, -18769 => 35059, 18770 => 26786, 18771 => 25422, 18772 => 31245, 18773 => 28903, -18774 => 33421, 18775 => 21242, 18776 => 38902, 18777 => 23569, 18778 => 21736, -18779 => 37045, 18780 => 32461, 18781 => 22882, 18782 => 36170, 18783 => 34503, -18784 => 33292, 18785 => 33293, 18786 => 36198, 18787 => 25668, 18788 => 23556, -18789 => 24913, 18790 => 28041, 18791 => 31038, 18792 => 35774, 18793 => 30775, -18794 => 30003, 18795 => 21627, 18796 => 20280, 18797 => 36523, 18798 => 28145, -18799 => 23072, 18800 => 32453, 18801 => 31070, 18802 => 27784, 18803 => 23457, -18804 => 23158, 18805 => 29978, 18806 => 32958, 18807 => 24910, 18808 => 28183, -18809 => 22768, 18810 => 29983, 18811 => 29989, 18812 => 29298, 18813 => 21319, -18814 => 32499, 18977 => 30465, 18978 => 30427, 18979 => 21097, 18980 => 32988, -18981 => 22307, 18982 => 24072, 18983 => 22833, 18984 => 29422, 18985 => 26045, -18986 => 28287, 18987 => 35799, 18988 => 23608, 18989 => 34417, 18990 => 21313, -18991 => 30707, 18992 => 25342, 18993 => 26102, 18994 => 20160, 18995 => 39135, -18996 => 34432, 18997 => 23454, 18998 => 35782, 18999 => 21490, 19000 => 30690, -19001 => 20351, 19002 => 23630, 19003 => 39542, 19004 => 22987, 19005 => 24335, -19006 => 31034, 19007 => 22763, 19008 => 19990, 19009 => 26623, 19010 => 20107, -19011 => 25325, 19012 => 35475, 19013 => 36893, 19014 => 21183, 19015 => 26159, -19016 => 21980, 19017 => 22124, 19018 => 36866, 19019 => 20181, 19020 => 20365, -19021 => 37322, 19022 => 39280, 19023 => 27663, 19024 => 24066, 19025 => 24643, -19026 => 23460, 19027 => 35270, 19028 => 35797, 19029 => 25910, 19030 => 25163, -19031 => 39318, 19032 => 23432, 19033 => 23551, 19034 => 25480, 19035 => 21806, -19036 => 21463, 19037 => 30246, 19038 => 20861, 19039 => 34092, 19040 => 26530, -19041 => 26803, 19042 => 27530, 19043 => 25234, 19044 => 36755, 19045 => 21460, -19046 => 33298, 19047 => 28113, 19048 => 30095, 19049 => 20070, 19050 => 36174, -19051 => 23408, 19052 => 29087, 19053 => 34223, 19054 => 26257, 19055 => 26329, -19056 => 32626, 19057 => 34560, 19058 => 40653, 19059 => 40736, 19060 => 23646, -19061 => 26415, 19062 => 36848, 19063 => 26641, 19064 => 26463, 19065 => 25101, -19066 => 31446, 19067 => 22661, 19068 => 24246, 19069 => 25968, 19070 => 28465, -19233 => 24661, 19234 => 21047, 19235 => 32781, 19236 => 25684, 19237 => 34928, -19238 => 29993, 19239 => 24069, 19240 => 26643, 19241 => 25332, 19242 => 38684, -19243 => 21452, 19244 => 29245, 19245 => 35841, 19246 => 27700, 19247 => 30561, -19248 => 31246, 19249 => 21550, 19250 => 30636, 19251 => 39034, 19252 => 33308, -19253 => 35828, 19254 => 30805, 19255 => 26388, 19256 => 28865, 19257 => 26031, -19258 => 25749, 19259 => 22070, 19260 => 24605, 19261 => 31169, 19262 => 21496, -19263 => 19997, 19264 => 27515, 19265 => 32902, 19266 => 23546, 19267 => 21987, -19268 => 22235, 19269 => 20282, 19270 => 20284, 19271 => 39282, 19272 => 24051, -19273 => 26494, 19274 => 32824, 19275 => 24578, 19276 => 39042, 19277 => 36865, -19278 => 23435, 19279 => 35772, 19280 => 35829, 19281 => 25628, 19282 => 33368, -19283 => 25822, 19284 => 22013, 19285 => 33487, 19286 => 37221, 19287 => 20439, -19288 => 32032, 19289 => 36895, 19290 => 31903, 19291 => 20723, 19292 => 22609, -19293 => 28335, 19294 => 23487, 19295 => 35785, 19296 => 32899, 19297 => 37240, -19298 => 33948, 19299 => 31639, 19300 => 34429, 19301 => 38539, 19302 => 38543, -19303 => 32485, 19304 => 39635, 19305 => 30862, 19306 => 23681, 19307 => 31319, -19308 => 36930, 19309 => 38567, 19310 => 31071, 19311 => 23385, 19312 => 25439, -19313 => 31499, 19314 => 34001, 19315 => 26797, 19316 => 21766, 19317 => 32553, -19318 => 29712, 19319 => 32034, 19320 => 38145, 19321 => 25152, 19322 => 22604, -19323 => 20182, 19324 => 23427, 19325 => 22905, 19326 => 22612, 19489 => 29549, -19490 => 25374, 19491 => 36427, 19492 => 36367, 19493 => 32974, 19494 => 33492, -19495 => 25260, 19496 => 21488, 19497 => 27888, 19498 => 37214, 19499 => 22826, -19500 => 24577, 19501 => 27760, 19502 => 22349, 19503 => 25674, 19504 => 36138, -19505 => 30251, 19506 => 28393, 19507 => 22363, 19508 => 27264, 19509 => 30192, -19510 => 28525, 19511 => 35885, 19512 => 35848, 19513 => 22374, 19514 => 27631, -19515 => 34962, 19516 => 30899, 19517 => 25506, 19518 => 21497, 19519 => 28845, -19520 => 27748, 19521 => 22616, 19522 => 25642, 19523 => 22530, 19524 => 26848, -19525 => 33179, 19526 => 21776, 19527 => 31958, 19528 => 20504, 19529 => 36538, -19530 => 28108, 19531 => 36255, 19532 => 28907, 19533 => 25487, 19534 => 28059, -19535 => 28372, 19536 => 32486, 19537 => 33796, 19538 => 26691, 19539 => 36867, -19540 => 28120, 19541 => 38518, 19542 => 35752, 19543 => 22871, 19544 => 29305, -19545 => 34276, 19546 => 33150, 19547 => 30140, 19548 => 35466, 19549 => 26799, -19550 => 21076, 19551 => 36386, 19552 => 38161, 19553 => 25552, 19554 => 39064, -19555 => 36420, 19556 => 21884, 19557 => 20307, 19558 => 26367, 19559 => 22159, -19560 => 24789, 19561 => 28053, 19562 => 21059, 19563 => 23625, 19564 => 22825, -19565 => 28155, 19566 => 22635, 19567 => 30000, 19568 => 29980, 19569 => 24684, -19570 => 33300, 19571 => 33094, 19572 => 25361, 19573 => 26465, 19574 => 36834, -19575 => 30522, 19576 => 36339, 19577 => 36148, 19578 => 38081, 19579 => 24086, -19580 => 21381, 19581 => 21548, 19582 => 28867, 19745 => 27712, 19746 => 24311, -19747 => 20572, 19748 => 20141, 19749 => 24237, 19750 => 25402, 19751 => 33351, -19752 => 36890, 19753 => 26704, 19754 => 37230, 19755 => 30643, 19756 => 21516, -19757 => 38108, 19758 => 24420, 19759 => 31461, 19760 => 26742, 19761 => 25413, -19762 => 31570, 19763 => 32479, 19764 => 30171, 19765 => 20599, 19766 => 25237, -19767 => 22836, 19768 => 36879, 19769 => 20984, 19770 => 31171, 19771 => 31361, -19772 => 22270, 19773 => 24466, 19774 => 36884, 19775 => 28034, 19776 => 23648, -19777 => 22303, 19778 => 21520, 19779 => 20820, 19780 => 28237, 19781 => 22242, -19782 => 25512, 19783 => 39059, 19784 => 33151, 19785 => 34581, 19786 => 35114, -19787 => 36864, 19788 => 21534, 19789 => 23663, 19790 => 33216, 19791 => 25302, -19792 => 25176, 19793 => 33073, 19794 => 40501, 19795 => 38464, 19796 => 39534, -19797 => 39548, 19798 => 26925, 19799 => 22949, 19800 => 25299, 19801 => 21822, -19802 => 25366, 19803 => 21703, 19804 => 34521, 19805 => 27964, 19806 => 23043, -19807 => 29926, 19808 => 34972, 19809 => 27498, 19810 => 22806, 19811 => 35916, -19812 => 24367, 19813 => 28286, 19814 => 29609, 19815 => 39037, 19816 => 20024, -19817 => 28919, 19818 => 23436, 19819 => 30871, 19820 => 25405, 19821 => 26202, -19822 => 30358, 19823 => 24779, 19824 => 23451, 19825 => 23113, 19826 => 19975, -19827 => 33109, 19828 => 27754, 19829 => 29579, 19830 => 20129, 19831 => 26505, -19832 => 32593, 19833 => 24448, 19834 => 26106, 19835 => 26395, 19836 => 24536, -19837 => 22916, 19838 => 23041, 20001 => 24013, 20002 => 24494, 20003 => 21361, -20004 => 38886, 20005 => 36829, 20006 => 26693, 20007 => 22260, 20008 => 21807, -20009 => 24799, 20010 => 20026, 20011 => 28493, 20012 => 32500, 20013 => 33479, -20014 => 33806, 20015 => 22996, 20016 => 20255, 20017 => 20266, 20018 => 23614, -20019 => 32428, 20020 => 26410, 20021 => 34074, 20022 => 21619, 20023 => 30031, -20024 => 32963, 20025 => 21890, 20026 => 39759, 20027 => 20301, 20028 => 28205, -20029 => 35859, 20030 => 23561, 20031 => 24944, 20032 => 21355, 20033 => 30239, -20034 => 28201, 20035 => 34442, 20036 => 25991, 20037 => 38395, 20038 => 32441, -20039 => 21563, 20040 => 31283, 20041 => 32010, 20042 => 38382, 20043 => 21985, -20044 => 32705, 20045 => 29934, 20046 => 25373, 20047 => 34583, 20048 => 28065, -20049 => 31389, 20050 => 25105, 20051 => 26017, 20052 => 21351, 20053 => 25569, -20054 => 27779, 20055 => 24043, 20056 => 21596, 20057 => 38056, 20058 => 20044, -20059 => 27745, 20060 => 35820, 20061 => 23627, 20062 => 26080, 20063 => 33436, -20064 => 26791, 20065 => 21566, 20066 => 21556, 20067 => 27595, 20068 => 27494, -20069 => 20116, 20070 => 25410, 20071 => 21320, 20072 => 33310, 20073 => 20237, -20074 => 20398, 20075 => 22366, 20076 => 25098, 20077 => 38654, 20078 => 26212, -20079 => 29289, 20080 => 21247, 20081 => 21153, 20082 => 24735, 20083 => 35823, -20084 => 26132, 20085 => 29081, 20086 => 26512, 20087 => 35199, 20088 => 30802, -20089 => 30717, 20090 => 26224, 20091 => 22075, 20092 => 21560, 20093 => 38177, -20094 => 29306, 20257 => 31232, 20258 => 24687, 20259 => 24076, 20260 => 24713, -20261 => 33181, 20262 => 22805, 20263 => 24796, 20264 => 29060, 20265 => 28911, -20266 => 28330, 20267 => 27728, 20268 => 29312, 20269 => 27268, 20270 => 34989, -20271 => 24109, 20272 => 20064, 20273 => 23219, 20274 => 21916, 20275 => 38115, -20276 => 27927, 20277 => 31995, 20278 => 38553, 20279 => 25103, 20280 => 32454, -20281 => 30606, 20282 => 34430, 20283 => 21283, 20284 => 38686, 20285 => 36758, -20286 => 26247, 20287 => 23777, 20288 => 20384, 20289 => 29421, 20290 => 19979, -20291 => 21414, 20292 => 22799, 20293 => 21523, 20294 => 25472, 20295 => 38184, -20296 => 20808, 20297 => 20185, 20298 => 40092, 20299 => 32420, 20300 => 21688, -20301 => 36132, 20302 => 34900, 20303 => 33335, 20304 => 38386, 20305 => 28046, -20306 => 24358, 20307 => 23244, 20308 => 26174, 20309 => 38505, 20310 => 29616, -20311 => 29486, 20312 => 21439, 20313 => 33146, 20314 => 39301, 20315 => 32673, -20316 => 23466, 20317 => 38519, 20318 => 38480, 20319 => 32447, 20320 => 30456, -20321 => 21410, 20322 => 38262, 20323 => 39321, 20324 => 31665, 20325 => 35140, -20326 => 28248, 20327 => 20065, 20328 => 32724, 20329 => 31077, 20330 => 35814, -20331 => 24819, 20332 => 21709, 20333 => 20139, 20334 => 39033, 20335 => 24055, -20336 => 27233, 20337 => 20687, 20338 => 21521, 20339 => 35937, 20340 => 33831, -20341 => 30813, 20342 => 38660, 20343 => 21066, 20344 => 21742, 20345 => 22179, -20346 => 38144, 20347 => 28040, 20348 => 23477, 20349 => 28102, 20350 => 26195, -20513 => 23567, 20514 => 23389, 20515 => 26657, 20516 => 32918, 20517 => 21880, -20518 => 31505, 20519 => 25928, 20520 => 26964, 20521 => 20123, 20522 => 27463, -20523 => 34638, 20524 => 38795, 20525 => 21327, 20526 => 25375, 20527 => 25658, -20528 => 37034, 20529 => 26012, 20530 => 32961, 20531 => 35856, 20532 => 20889, -20533 => 26800, 20534 => 21368, 20535 => 34809, 20536 => 25032, 20537 => 27844, -20538 => 27899, 20539 => 35874, 20540 => 23633, 20541 => 34218, 20542 => 33455, -20543 => 38156, 20544 => 27427, 20545 => 36763, 20546 => 26032, 20547 => 24571, -20548 => 24515, 20549 => 20449, 20550 => 34885, 20551 => 26143, 20552 => 33125, -20553 => 29481, 20554 => 24826, 20555 => 20852, 20556 => 21009, 20557 => 22411, -20558 => 24418, 20559 => 37026, 20560 => 34892, 20561 => 37266, 20562 => 24184, -20563 => 26447, 20564 => 24615, 20565 => 22995, 20566 => 20804, 20567 => 20982, -20568 => 33016, 20569 => 21256, 20570 => 27769, 20571 => 38596, 20572 => 29066, -20573 => 20241, 20574 => 20462, 20575 => 32670, 20576 => 26429, 20577 => 21957, -20578 => 38152, 20579 => 31168, 20580 => 34966, 20581 => 32483, 20582 => 22687, -20583 => 25100, 20584 => 38656, 20585 => 34394, 20586 => 22040, 20587 => 39035, -20588 => 24464, 20589 => 35768, 20590 => 33988, 20591 => 37207, 20592 => 21465, -20593 => 26093, 20594 => 24207, 20595 => 30044, 20596 => 24676, 20597 => 32110, -20598 => 23167, 20599 => 32490, 20600 => 32493, 20601 => 36713, 20602 => 21927, -20603 => 23459, 20604 => 24748, 20605 => 26059, 20606 => 29572, 20769 => 36873, -20770 => 30307, 20771 => 30505, 20772 => 32474, 20773 => 38772, 20774 => 34203, -20775 => 23398, 20776 => 31348, 20777 => 38634, 20778 => 34880, 20779 => 21195, -20780 => 29071, 20781 => 24490, 20782 => 26092, 20783 => 35810, 20784 => 23547, -20785 => 39535, 20786 => 24033, 20787 => 27529, 20788 => 27739, 20789 => 35757, -20790 => 35759, 20791 => 36874, 20792 => 36805, 20793 => 21387, 20794 => 25276, -20795 => 40486, 20796 => 40493, 20797 => 21568, 20798 => 20011, 20799 => 33469, -20800 => 29273, 20801 => 34460, 20802 => 23830, 20803 => 34905, 20804 => 28079, -20805 => 38597, 20806 => 21713, 20807 => 20122, 20808 => 35766, 20809 => 28937, -20810 => 21693, 20811 => 38409, 20812 => 28895, 20813 => 28153, 20814 => 30416, -20815 => 20005, 20816 => 30740, 20817 => 34578, 20818 => 23721, 20819 => 24310, -20820 => 35328, 20821 => 39068, 20822 => 38414, 20823 => 28814, 20824 => 27839, -20825 => 22852, 20826 => 25513, 20827 => 30524, 20828 => 34893, 20829 => 28436, -20830 => 33395, 20831 => 22576, 20832 => 29141, 20833 => 21388, 20834 => 30746, -20835 => 38593, 20836 => 21761, 20837 => 24422, 20838 => 28976, 20839 => 23476, -20840 => 35866, 20841 => 39564, 20842 => 27523, 20843 => 22830, 20844 => 40495, -20845 => 31207, 20846 => 26472, 20847 => 25196, 20848 => 20335, 20849 => 30113, -20850 => 32650, 20851 => 27915, 20852 => 38451, 20853 => 27687, 20854 => 20208, -20855 => 30162, 20856 => 20859, 20857 => 26679, 20858 => 28478, 20859 => 36992, -20860 => 33136, 20861 => 22934, 20862 => 29814, 21025 => 25671, 21026 => 23591, -21027 => 36965, 21028 => 31377, 21029 => 35875, 21030 => 23002, 21031 => 21676, -21032 => 33280, 21033 => 33647, 21034 => 35201, 21035 => 32768, 21036 => 26928, -21037 => 22094, 21038 => 32822, 21039 => 29239, 21040 => 37326, 21041 => 20918, -21042 => 20063, 21043 => 39029, 21044 => 25494, 21045 => 19994, 21046 => 21494, -21047 => 26355, 21048 => 33099, 21049 => 22812, 21050 => 28082, 21051 => 19968, -21052 => 22777, 21053 => 21307, 21054 => 25558, 21055 => 38129, 21056 => 20381, -21057 => 20234, 21058 => 34915, 21059 => 39056, 21060 => 22839, 21061 => 36951, -21062 => 31227, 21063 => 20202, 21064 => 33008, 21065 => 30097, 21066 => 27778, -21067 => 23452, 21068 => 23016, 21069 => 24413, 21070 => 26885, 21071 => 34433, -21072 => 20506, 21073 => 24050, 21074 => 20057, 21075 => 30691, 21076 => 20197, -21077 => 33402, 21078 => 25233, 21079 => 26131, 21080 => 37009, 21081 => 23673, -21082 => 20159, 21083 => 24441, 21084 => 33222, 21085 => 36920, 21086 => 32900, -21087 => 30123, 21088 => 20134, 21089 => 35028, 21090 => 24847, 21091 => 27589, -21092 => 24518, 21093 => 20041, 21094 => 30410, 21095 => 28322, 21096 => 35811, -21097 => 35758, 21098 => 35850, 21099 => 35793, 21100 => 24322, 21101 => 32764, -21102 => 32716, 21103 => 32462, 21104 => 33589, 21105 => 33643, 21106 => 22240, -21107 => 27575, 21108 => 38899, 21109 => 38452, 21110 => 23035, 21111 => 21535, -21112 => 38134, 21113 => 28139, 21114 => 23493, 21115 => 39278, 21116 => 23609, -21117 => 24341, 21118 => 38544, 21281 => 21360, 21282 => 33521, 21283 => 27185, -21284 => 23156, 21285 => 40560, 21286 => 24212, 21287 => 32552, 21288 => 33721, -21289 => 33828, 21290 => 33829, 21291 => 33639, 21292 => 34631, 21293 => 36814, -21294 => 36194, 21295 => 30408, 21296 => 24433, 21297 => 39062, 21298 => 30828, -21299 => 26144, 21300 => 21727, 21301 => 25317, 21302 => 20323, 21303 => 33219, -21304 => 30152, 21305 => 24248, 21306 => 38605, 21307 => 36362, 21308 => 34553, -21309 => 21647, 21310 => 27891, 21311 => 28044, 21312 => 27704, 21313 => 24703, -21314 => 21191, 21315 => 29992, 21316 => 24189, 21317 => 20248, 21318 => 24736, -21319 => 24551, 21320 => 23588, 21321 => 30001, 21322 => 37038, 21323 => 38080, -21324 => 29369, 21325 => 27833, 21326 => 28216, 21327 => 37193, 21328 => 26377, -21329 => 21451, 21330 => 21491, 21331 => 20305, 21332 => 37321, 21333 => 35825, -21334 => 21448, 21335 => 24188, 21336 => 36802, 21337 => 28132, 21338 => 20110, -21339 => 30402, 21340 => 27014, 21341 => 34398, 21342 => 24858, 21343 => 33286, -21344 => 20313, 21345 => 20446, 21346 => 36926, 21347 => 40060, 21348 => 24841, -21349 => 28189, 21350 => 28180, 21351 => 38533, 21352 => 20104, 21353 => 23089, -21354 => 38632, 21355 => 19982, 21356 => 23679, 21357 => 31161, 21358 => 23431, -21359 => 35821, 21360 => 32701, 21361 => 29577, 21362 => 22495, 21363 => 33419, -21364 => 37057, 21365 => 21505, 21366 => 36935, 21367 => 21947, 21368 => 23786, -21369 => 24481, 21370 => 24840, 21371 => 27442, 21372 => 29425, 21373 => 32946, -21374 => 35465, 21537 => 28020, 21538 => 23507, 21539 => 35029, 21540 => 39044, -21541 => 35947, 21542 => 39533, 21543 => 40499, 21544 => 28170, 21545 => 20900, -21546 => 20803, 21547 => 22435, 21548 => 34945, 21549 => 21407, 21550 => 25588, -21551 => 36757, 21552 => 22253, 21553 => 21592, 21554 => 22278, 21555 => 29503, -21556 => 28304, 21557 => 32536, 21558 => 36828, 21559 => 33489, 21560 => 24895, -21561 => 24616, 21562 => 38498, 21563 => 26352, 21564 => 32422, 21565 => 36234, -21566 => 36291, 21567 => 38053, 21568 => 23731, 21569 => 31908, 21570 => 26376, -21571 => 24742, 21572 => 38405, 21573 => 32792, 21574 => 20113, 21575 => 37095, -21576 => 21248, 21577 => 38504, 21578 => 20801, 21579 => 36816, 21580 => 34164, -21581 => 37213, 21582 => 26197, 21583 => 38901, 21584 => 23381, 21585 => 21277, -21586 => 30776, 21587 => 26434, 21588 => 26685, 21589 => 21705, 21590 => 28798, -21591 => 23472, 21592 => 36733, 21593 => 20877, 21594 => 22312, 21595 => 21681, -21596 => 25874, 21597 => 26242, 21598 => 36190, 21599 => 36163, 21600 => 33039, -21601 => 33900, 21602 => 36973, 21603 => 31967, 21604 => 20991, 21605 => 34299, -21606 => 26531, 21607 => 26089, 21608 => 28577, 21609 => 34468, 21610 => 36481, -21611 => 22122, 21612 => 36896, 21613 => 30338, 21614 => 28790, 21615 => 29157, -21616 => 36131, 21617 => 25321, 21618 => 21017, 21619 => 27901, 21620 => 36156, -21621 => 24590, 21622 => 22686, 21623 => 24974, 21624 => 26366, 21625 => 36192, -21626 => 25166, 21627 => 21939, 21628 => 28195, 21629 => 26413, 21630 => 36711, -21793 => 38113, 21794 => 38392, 21795 => 30504, 21796 => 26629, 21797 => 27048, -21798 => 21643, 21799 => 20045, 21800 => 28856, 21801 => 35784, 21802 => 25688, -21803 => 25995, 21804 => 23429, 21805 => 31364, 21806 => 20538, 21807 => 23528, -21808 => 30651, 21809 => 27617, 21810 => 35449, 21811 => 31896, 21812 => 27838, -21813 => 30415, 21814 => 26025, 21815 => 36759, 21816 => 23853, 21817 => 23637, -21818 => 34360, 21819 => 26632, 21820 => 21344, 21821 => 25112, 21822 => 31449, -21823 => 28251, 21824 => 32509, 21825 => 27167, 21826 => 31456, 21827 => 24432, -21828 => 28467, 21829 => 24352, 21830 => 25484, 21831 => 28072, 21832 => 26454, -21833 => 19976, 21834 => 24080, 21835 => 36134, 21836 => 20183, 21837 => 32960, -21838 => 30260, 21839 => 38556, 21840 => 25307, 21841 => 26157, 21842 => 25214, -21843 => 27836, 21844 => 36213, 21845 => 29031, 21846 => 32617, 21847 => 20806, -21848 => 32903, 21849 => 21484, 21850 => 36974, 21851 => 25240, 21852 => 21746, -21853 => 34544, 21854 => 36761, 21855 => 32773, 21856 => 38167, 21857 => 34071, -21858 => 36825, 21859 => 27993, 21860 => 29645, 21861 => 26015, 21862 => 30495, -21863 => 29956, 21864 => 30759, 21865 => 33275, 21866 => 36126, 21867 => 38024, -21868 => 20390, 21869 => 26517, 21870 => 30137, 21871 => 35786, 21872 => 38663, -21873 => 25391, 21874 => 38215, 21875 => 38453, 21876 => 33976, 21877 => 25379, -21878 => 30529, 21879 => 24449, 21880 => 29424, 21881 => 20105, 21882 => 24596, -21883 => 25972, 21884 => 25327, 21885 => 27491, 21886 => 25919, 22049 => 24103, -22050 => 30151, 22051 => 37073, 22052 => 35777, 22053 => 33437, 22054 => 26525, -22055 => 25903, 22056 => 21553, 22057 => 34584, 22058 => 30693, 22059 => 32930, -22060 => 33026, 22061 => 27713, 22062 => 20043, 22063 => 32455, 22064 => 32844, -22065 => 30452, 22066 => 26893, 22067 => 27542, 22068 => 25191, 22069 => 20540, -22070 => 20356, 22071 => 22336, 22072 => 25351, 22073 => 27490, 22074 => 36286, -22075 => 21482, 22076 => 26088, 22077 => 32440, 22078 => 24535, 22079 => 25370, -22080 => 25527, 22081 => 33267, 22082 => 33268, 22083 => 32622, 22084 => 24092, -22085 => 23769, 22086 => 21046, 22087 => 26234, 22088 => 31209, 22089 => 31258, -22090 => 36136, 22091 => 28825, 22092 => 30164, 22093 => 28382, 22094 => 27835, -22095 => 31378, 22096 => 20013, 22097 => 30405, 22098 => 24544, 22099 => 38047, -22100 => 34935, 22101 => 32456, 22102 => 31181, 22103 => 32959, 22104 => 37325, -22105 => 20210, 22106 => 20247, 22107 => 33311, 22108 => 21608, 22109 => 24030, -22110 => 27954, 22111 => 35788, 22112 => 31909, 22113 => 36724, 22114 => 32920, -22115 => 24090, 22116 => 21650, 22117 => 30385, 22118 => 23449, 22119 => 26172, -22120 => 39588, 22121 => 29664, 22122 => 26666, 22123 => 34523, 22124 => 26417, -22125 => 29482, 22126 => 35832, 22127 => 35803, 22128 => 36880, 22129 => 31481, -22130 => 28891, 22131 => 29038, 22132 => 25284, 22133 => 30633, 22134 => 22065, -22135 => 20027, 22136 => 33879, 22137 => 26609, 22138 => 21161, 22139 => 34496, -22140 => 36142, 22141 => 38136, 22142 => 31569, 22305 => 20303, 22306 => 27880, -22307 => 31069, 22308 => 39547, 22309 => 25235, 22310 => 29226, 22311 => 25341, -22312 => 19987, 22313 => 30742, 22314 => 36716, 22315 => 25776, 22316 => 36186, -22317 => 31686, 22318 => 26729, 22319 => 24196, 22320 => 35013, 22321 => 22918, -22322 => 25758, 22323 => 22766, 22324 => 29366, 22325 => 26894, 22326 => 38181, -22327 => 36861, 22328 => 36184, 22329 => 22368, 22330 => 32512, 22331 => 35846, -22332 => 20934, 22333 => 25417, 22334 => 25305, 22335 => 21331, 22336 => 26700, -22337 => 29730, 22338 => 33537, 22339 => 37196, 22340 => 21828, 22341 => 30528, -22342 => 28796, 22343 => 27978, 22344 => 20857, 22345 => 21672, 22346 => 36164, -22347 => 23039, 22348 => 28363, 22349 => 28100, 22350 => 23388, 22351 => 32043, -22352 => 20180, 22353 => 31869, 22354 => 28371, 22355 => 23376, 22356 => 33258, -22357 => 28173, 22358 => 23383, 22359 => 39683, 22360 => 26837, 22361 => 36394, -22362 => 23447, 22363 => 32508, 22364 => 24635, 22365 => 32437, 22366 => 37049, -22367 => 36208, 22368 => 22863, 22369 => 25549, 22370 => 31199, 22371 => 36275, -22372 => 21330, 22373 => 26063, 22374 => 31062, 22375 => 35781, 22376 => 38459, -22377 => 32452, 22378 => 38075, 22379 => 32386, 22380 => 22068, 22381 => 37257, -22382 => 26368, 22383 => 32618, 22384 => 23562, 22385 => 36981, 22386 => 26152, -22387 => 24038, 22388 => 20304, 22389 => 26590, 22390 => 20570, 22391 => 20316, -22392 => 22352, 22393 => 24231, 22561 => 20109, 22562 => 19980, 22563 => 20800, -22564 => 19984, 22565 => 24319, 22566 => 21317, 22567 => 19989, 22568 => 20120, -22569 => 19998, 22570 => 39730, 22571 => 23404, 22572 => 22121, 22573 => 20008, -22574 => 31162, 22575 => 20031, 22576 => 21269, 22577 => 20039, 22578 => 22829, -22579 => 29243, 22580 => 21358, 22581 => 27664, 22582 => 22239, 22583 => 32996, -22584 => 39319, 22585 => 27603, 22586 => 30590, 22587 => 40727, 22588 => 20022, -22589 => 20127, 22590 => 40720, 22591 => 20060, 22592 => 20073, 22593 => 20115, -22594 => 33416, 22595 => 23387, 22596 => 21868, 22597 => 22031, 22598 => 20164, -22599 => 21389, 22600 => 21405, 22601 => 21411, 22602 => 21413, 22603 => 21422, -22604 => 38757, 22605 => 36189, 22606 => 21274, 22607 => 21493, 22608 => 21286, -22609 => 21294, 22610 => 21310, 22611 => 36188, 22612 => 21350, 22613 => 21347, -22614 => 20994, 22615 => 21000, 22616 => 21006, 22617 => 21037, 22618 => 21043, -22619 => 21055, 22620 => 21056, 22621 => 21068, 22622 => 21086, 22623 => 21089, -22624 => 21084, 22625 => 33967, 22626 => 21117, 22627 => 21122, 22628 => 21121, -22629 => 21136, 22630 => 21139, 22631 => 20866, 22632 => 32596, 22633 => 20155, -22634 => 20163, 22635 => 20169, 22636 => 20162, 22637 => 20200, 22638 => 20193, -22639 => 20203, 22640 => 20190, 22641 => 20251, 22642 => 20211, 22643 => 20258, -22644 => 20324, 22645 => 20213, 22646 => 20261, 22647 => 20263, 22648 => 20233, -22649 => 20267, 22650 => 20318, 22651 => 20327, 22652 => 25912, 22653 => 20314, -22654 => 20317, 22817 => 20319, 22818 => 20311, 22819 => 20274, 22820 => 20285, -22821 => 20342, 22822 => 20340, 22823 => 20369, 22824 => 20361, 22825 => 20355, -22826 => 20367, 22827 => 20350, 22828 => 20347, 22829 => 20394, 22830 => 20348, -22831 => 20396, 22832 => 20372, 22833 => 20454, 22834 => 20456, 22835 => 20458, -22836 => 20421, 22837 => 20442, 22838 => 20451, 22839 => 20444, 22840 => 20433, -22841 => 20447, 22842 => 20472, 22843 => 20521, 22844 => 20556, 22845 => 20467, -22846 => 20524, 22847 => 20495, 22848 => 20526, 22849 => 20525, 22850 => 20478, -22851 => 20508, 22852 => 20492, 22853 => 20517, 22854 => 20520, 22855 => 20606, -22856 => 20547, 22857 => 20565, 22858 => 20552, 22859 => 20558, 22860 => 20588, -22861 => 20603, 22862 => 20645, 22863 => 20647, 22864 => 20649, 22865 => 20666, -22866 => 20694, 22867 => 20742, 22868 => 20717, 22869 => 20716, 22870 => 20710, -22871 => 20718, 22872 => 20743, 22873 => 20747, 22874 => 20189, 22875 => 27709, -22876 => 20312, 22877 => 20325, 22878 => 20430, 22879 => 40864, 22880 => 27718, -22881 => 31860, 22882 => 20846, 22883 => 24061, 22884 => 40649, 22885 => 39320, -22886 => 20865, 22887 => 22804, 22888 => 21241, 22889 => 21261, 22890 => 35335, -22891 => 21264, 22892 => 20971, 22893 => 22809, 22894 => 20821, 22895 => 20128, -22896 => 20822, 22897 => 20147, 22898 => 34926, 22899 => 34980, 22900 => 20149, -22901 => 33044, 22902 => 35026, 22903 => 31104, 22904 => 23348, 22905 => 34819, -22906 => 32696, 22907 => 20907, 22908 => 20913, 22909 => 20925, 22910 => 20924, -23073 => 20935, 23074 => 20886, 23075 => 20898, 23076 => 20901, 23077 => 35744, -23078 => 35750, 23079 => 35751, 23080 => 35754, 23081 => 35764, 23082 => 35765, -23083 => 35767, 23084 => 35778, 23085 => 35779, 23086 => 35787, 23087 => 35791, -23088 => 35790, 23089 => 35794, 23090 => 35795, 23091 => 35796, 23092 => 35798, -23093 => 35800, 23094 => 35801, 23095 => 35804, 23096 => 35807, 23097 => 35808, -23098 => 35812, 23099 => 35816, 23100 => 35817, 23101 => 35822, 23102 => 35824, -23103 => 35827, 23104 => 35830, 23105 => 35833, 23106 => 35836, 23107 => 35839, -23108 => 35840, 23109 => 35842, 23110 => 35844, 23111 => 35847, 23112 => 35852, -23113 => 35855, 23114 => 35857, 23115 => 35858, 23116 => 35860, 23117 => 35861, -23118 => 35862, 23119 => 35865, 23120 => 35867, 23121 => 35864, 23122 => 35869, -23123 => 35871, 23124 => 35872, 23125 => 35873, 23126 => 35877, 23127 => 35879, -23128 => 35882, 23129 => 35883, 23130 => 35886, 23131 => 35887, 23132 => 35890, -23133 => 35891, 23134 => 35893, 23135 => 35894, 23136 => 21353, 23137 => 21370, -23138 => 38429, 23139 => 38434, 23140 => 38433, 23141 => 38449, 23142 => 38442, -23143 => 38461, 23144 => 38460, 23145 => 38466, 23146 => 38473, 23147 => 38484, -23148 => 38495, 23149 => 38503, 23150 => 38508, 23151 => 38514, 23152 => 38516, -23153 => 38536, 23154 => 38541, 23155 => 38551, 23156 => 38576, 23157 => 37015, -23158 => 37019, 23159 => 37021, 23160 => 37017, 23161 => 37036, 23162 => 37025, -23163 => 37044, 23164 => 37043, 23165 => 37046, 23166 => 37050, 23329 => 37048, -23330 => 37040, 23331 => 37071, 23332 => 37061, 23333 => 37054, 23334 => 37072, -23335 => 37060, 23336 => 37063, 23337 => 37075, 23338 => 37094, 23339 => 37090, -23340 => 37084, 23341 => 37079, 23342 => 37083, 23343 => 37099, 23344 => 37103, -23345 => 37118, 23346 => 37124, 23347 => 37154, 23348 => 37150, 23349 => 37155, -23350 => 37169, 23351 => 37167, 23352 => 37177, 23353 => 37187, 23354 => 37190, -23355 => 21005, 23356 => 22850, 23357 => 21154, 23358 => 21164, 23359 => 21165, -23360 => 21182, 23361 => 21759, 23362 => 21200, 23363 => 21206, 23364 => 21232, -23365 => 21471, 23366 => 29166, 23367 => 30669, 23368 => 24308, 23369 => 20981, -23370 => 20988, 23371 => 39727, 23372 => 21430, 23373 => 24321, 23374 => 30042, -23375 => 24047, 23376 => 22348, 23377 => 22441, 23378 => 22433, 23379 => 22654, -23380 => 22716, 23381 => 22725, 23382 => 22737, 23383 => 22313, 23384 => 22316, -23385 => 22314, 23386 => 22323, 23387 => 22329, 23388 => 22318, 23389 => 22319, -23390 => 22364, 23391 => 22331, 23392 => 22338, 23393 => 22377, 23394 => 22405, -23395 => 22379, 23396 => 22406, 23397 => 22396, 23398 => 22395, 23399 => 22376, -23400 => 22381, 23401 => 22390, 23402 => 22387, 23403 => 22445, 23404 => 22436, -23405 => 22412, 23406 => 22450, 23407 => 22479, 23408 => 22439, 23409 => 22452, -23410 => 22419, 23411 => 22432, 23412 => 22485, 23413 => 22488, 23414 => 22490, -23415 => 22489, 23416 => 22482, 23417 => 22456, 23418 => 22516, 23419 => 22511, -23420 => 22520, 23421 => 22500, 23422 => 22493, 23585 => 22539, 23586 => 22541, -23587 => 22525, 23588 => 22509, 23589 => 22528, 23590 => 22558, 23591 => 22553, -23592 => 22596, 23593 => 22560, 23594 => 22629, 23595 => 22636, 23596 => 22657, -23597 => 22665, 23598 => 22682, 23599 => 22656, 23600 => 39336, 23601 => 40729, -23602 => 25087, 23603 => 33401, 23604 => 33405, 23605 => 33407, 23606 => 33423, -23607 => 33418, 23608 => 33448, 23609 => 33412, 23610 => 33422, 23611 => 33425, -23612 => 33431, 23613 => 33433, 23614 => 33451, 23615 => 33464, 23616 => 33470, -23617 => 33456, 23618 => 33480, 23619 => 33482, 23620 => 33507, 23621 => 33432, -23622 => 33463, 23623 => 33454, 23624 => 33483, 23625 => 33484, 23626 => 33473, -23627 => 33449, 23628 => 33460, 23629 => 33441, 23630 => 33450, 23631 => 33439, -23632 => 33476, 23633 => 33486, 23634 => 33444, 23635 => 33505, 23636 => 33545, -23637 => 33527, 23638 => 33508, 23639 => 33551, 23640 => 33543, 23641 => 33500, -23642 => 33524, 23643 => 33490, 23644 => 33496, 23645 => 33548, 23646 => 33531, -23647 => 33491, 23648 => 33553, 23649 => 33562, 23650 => 33542, 23651 => 33556, -23652 => 33557, 23653 => 33504, 23654 => 33493, 23655 => 33564, 23656 => 33617, -23657 => 33627, 23658 => 33628, 23659 => 33544, 23660 => 33682, 23661 => 33596, -23662 => 33588, 23663 => 33585, 23664 => 33691, 23665 => 33630, 23666 => 33583, -23667 => 33615, 23668 => 33607, 23669 => 33603, 23670 => 33631, 23671 => 33600, -23672 => 33559, 23673 => 33632, 23674 => 33581, 23675 => 33594, 23676 => 33587, -23677 => 33638, 23678 => 33637, 23841 => 33640, 23842 => 33563, 23843 => 33641, -23844 => 33644, 23845 => 33642, 23846 => 33645, 23847 => 33646, 23848 => 33712, -23849 => 33656, 23850 => 33715, 23851 => 33716, 23852 => 33696, 23853 => 33706, -23854 => 33683, 23855 => 33692, 23856 => 33669, 23857 => 33660, 23858 => 33718, -23859 => 33705, 23860 => 33661, 23861 => 33720, 23862 => 33659, 23863 => 33688, -23864 => 33694, 23865 => 33704, 23866 => 33722, 23867 => 33724, 23868 => 33729, -23869 => 33793, 23870 => 33765, 23871 => 33752, 23872 => 22535, 23873 => 33816, -23874 => 33803, 23875 => 33757, 23876 => 33789, 23877 => 33750, 23878 => 33820, -23879 => 33848, 23880 => 33809, 23881 => 33798, 23882 => 33748, 23883 => 33759, -23884 => 33807, 23885 => 33795, 23886 => 33784, 23887 => 33785, 23888 => 33770, -23889 => 33733, 23890 => 33728, 23891 => 33830, 23892 => 33776, 23893 => 33761, -23894 => 33884, 23895 => 33873, 23896 => 33882, 23897 => 33881, 23898 => 33907, -23899 => 33927, 23900 => 33928, 23901 => 33914, 23902 => 33929, 23903 => 33912, -23904 => 33852, 23905 => 33862, 23906 => 33897, 23907 => 33910, 23908 => 33932, -23909 => 33934, 23910 => 33841, 23911 => 33901, 23912 => 33985, 23913 => 33997, -23914 => 34000, 23915 => 34022, 23916 => 33981, 23917 => 34003, 23918 => 33994, -23919 => 33983, 23920 => 33978, 23921 => 34016, 23922 => 33953, 23923 => 33977, -23924 => 33972, 23925 => 33943, 23926 => 34021, 23927 => 34019, 23928 => 34060, -23929 => 29965, 23930 => 34104, 23931 => 34032, 23932 => 34105, 23933 => 34079, -23934 => 34106, 24097 => 34134, 24098 => 34107, 24099 => 34047, 24100 => 34044, -24101 => 34137, 24102 => 34120, 24103 => 34152, 24104 => 34148, 24105 => 34142, -24106 => 34170, 24107 => 30626, 24108 => 34115, 24109 => 34162, 24110 => 34171, -24111 => 34212, 24112 => 34216, 24113 => 34183, 24114 => 34191, 24115 => 34169, -24116 => 34222, 24117 => 34204, 24118 => 34181, 24119 => 34233, 24120 => 34231, -24121 => 34224, 24122 => 34259, 24123 => 34241, 24124 => 34268, 24125 => 34303, -24126 => 34343, 24127 => 34309, 24128 => 34345, 24129 => 34326, 24130 => 34364, -24131 => 24318, 24132 => 24328, 24133 => 22844, 24134 => 22849, 24135 => 32823, -24136 => 22869, 24137 => 22874, 24138 => 22872, 24139 => 21263, 24140 => 23586, -24141 => 23589, 24142 => 23596, 24143 => 23604, 24144 => 25164, 24145 => 25194, -24146 => 25247, 24147 => 25275, 24148 => 25290, 24149 => 25306, 24150 => 25303, -24151 => 25326, 24152 => 25378, 24153 => 25334, 24154 => 25401, 24155 => 25419, -24156 => 25411, 24157 => 25517, 24158 => 25590, 24159 => 25457, 24160 => 25466, -24161 => 25486, 24162 => 25524, 24163 => 25453, 24164 => 25516, 24165 => 25482, -24166 => 25449, 24167 => 25518, 24168 => 25532, 24169 => 25586, 24170 => 25592, -24171 => 25568, 24172 => 25599, 24173 => 25540, 24174 => 25566, 24175 => 25550, -24176 => 25682, 24177 => 25542, 24178 => 25534, 24179 => 25669, 24180 => 25665, -24181 => 25611, 24182 => 25627, 24183 => 25632, 24184 => 25612, 24185 => 25638, -24186 => 25633, 24187 => 25694, 24188 => 25732, 24189 => 25709, 24190 => 25750, -24353 => 25722, 24354 => 25783, 24355 => 25784, 24356 => 25753, 24357 => 25786, -24358 => 25792, 24359 => 25808, 24360 => 25815, 24361 => 25828, 24362 => 25826, -24363 => 25865, 24364 => 25893, 24365 => 25902, 24366 => 24331, 24367 => 24530, -24368 => 29977, 24369 => 24337, 24370 => 21343, 24371 => 21489, 24372 => 21501, -24373 => 21481, 24374 => 21480, 24375 => 21499, 24376 => 21522, 24377 => 21526, -24378 => 21510, 24379 => 21579, 24380 => 21586, 24381 => 21587, 24382 => 21588, -24383 => 21590, 24384 => 21571, 24385 => 21537, 24386 => 21591, 24387 => 21593, -24388 => 21539, 24389 => 21554, 24390 => 21634, 24391 => 21652, 24392 => 21623, -24393 => 21617, 24394 => 21604, 24395 => 21658, 24396 => 21659, 24397 => 21636, -24398 => 21622, 24399 => 21606, 24400 => 21661, 24401 => 21712, 24402 => 21677, -24403 => 21698, 24404 => 21684, 24405 => 21714, 24406 => 21671, 24407 => 21670, -24408 => 21715, 24409 => 21716, 24410 => 21618, 24411 => 21667, 24412 => 21717, -24413 => 21691, 24414 => 21695, 24415 => 21708, 24416 => 21721, 24417 => 21722, -24418 => 21724, 24419 => 21673, 24420 => 21674, 24421 => 21668, 24422 => 21725, -24423 => 21711, 24424 => 21726, 24425 => 21787, 24426 => 21735, 24427 => 21792, -24428 => 21757, 24429 => 21780, 24430 => 21747, 24431 => 21794, 24432 => 21795, -24433 => 21775, 24434 => 21777, 24435 => 21799, 24436 => 21802, 24437 => 21863, -24438 => 21903, 24439 => 21941, 24440 => 21833, 24441 => 21869, 24442 => 21825, -24443 => 21845, 24444 => 21823, 24445 => 21840, 24446 => 21820, 24609 => 21815, -24610 => 21846, 24611 => 21877, 24612 => 21878, 24613 => 21879, 24614 => 21811, -24615 => 21808, 24616 => 21852, 24617 => 21899, 24618 => 21970, 24619 => 21891, -24620 => 21937, 24621 => 21945, 24622 => 21896, 24623 => 21889, 24624 => 21919, -24625 => 21886, 24626 => 21974, 24627 => 21905, 24628 => 21883, 24629 => 21983, -24630 => 21949, 24631 => 21950, 24632 => 21908, 24633 => 21913, 24634 => 21994, -24635 => 22007, 24636 => 21961, 24637 => 22047, 24638 => 21969, 24639 => 21995, -24640 => 21996, 24641 => 21972, 24642 => 21990, 24643 => 21981, 24644 => 21956, -24645 => 21999, 24646 => 21989, 24647 => 22002, 24648 => 22003, 24649 => 21964, -24650 => 21965, 24651 => 21992, 24652 => 22005, 24653 => 21988, 24654 => 36756, -24655 => 22046, 24656 => 22024, 24657 => 22028, 24658 => 22017, 24659 => 22052, -24660 => 22051, 24661 => 22014, 24662 => 22016, 24663 => 22055, 24664 => 22061, -24665 => 22104, 24666 => 22073, 24667 => 22103, 24668 => 22060, 24669 => 22093, -24670 => 22114, 24671 => 22105, 24672 => 22108, 24673 => 22092, 24674 => 22100, -24675 => 22150, 24676 => 22116, 24677 => 22129, 24678 => 22123, 24679 => 22139, -24680 => 22140, 24681 => 22149, 24682 => 22163, 24683 => 22191, 24684 => 22228, -24685 => 22231, 24686 => 22237, 24687 => 22241, 24688 => 22261, 24689 => 22251, -24690 => 22265, 24691 => 22271, 24692 => 22276, 24693 => 22282, 24694 => 22281, -24695 => 22300, 24696 => 24079, 24697 => 24089, 24698 => 24084, 24699 => 24081, -24700 => 24113, 24701 => 24123, 24702 => 24124, 24865 => 24119, 24866 => 24132, -24867 => 24148, 24868 => 24155, 24869 => 24158, 24870 => 24161, 24871 => 23692, -24872 => 23674, 24873 => 23693, 24874 => 23696, 24875 => 23702, 24876 => 23688, -24877 => 23704, 24878 => 23705, 24879 => 23697, 24880 => 23706, 24881 => 23708, -24882 => 23733, 24883 => 23714, 24884 => 23741, 24885 => 23724, 24886 => 23723, -24887 => 23729, 24888 => 23715, 24889 => 23745, 24890 => 23735, 24891 => 23748, -24892 => 23762, 24893 => 23780, 24894 => 23755, 24895 => 23781, 24896 => 23810, -24897 => 23811, 24898 => 23847, 24899 => 23846, 24900 => 23854, 24901 => 23844, -24902 => 23838, 24903 => 23814, 24904 => 23835, 24905 => 23896, 24906 => 23870, -24907 => 23860, 24908 => 23869, 24909 => 23916, 24910 => 23899, 24911 => 23919, -24912 => 23901, 24913 => 23915, 24914 => 23883, 24915 => 23882, 24916 => 23913, -24917 => 23924, 24918 => 23938, 24919 => 23961, 24920 => 23965, 24921 => 35955, -24922 => 23991, 24923 => 24005, 24924 => 24435, 24925 => 24439, 24926 => 24450, -24927 => 24455, 24928 => 24457, 24929 => 24460, 24930 => 24469, 24931 => 24473, -24932 => 24476, 24933 => 24488, 24934 => 24493, 24935 => 24501, 24936 => 24508, -24937 => 34914, 24938 => 24417, 24939 => 29357, 24940 => 29360, 24941 => 29364, -24942 => 29367, 24943 => 29368, 24944 => 29379, 24945 => 29377, 24946 => 29390, -24947 => 29389, 24948 => 29394, 24949 => 29416, 24950 => 29423, 24951 => 29417, -24952 => 29426, 24953 => 29428, 24954 => 29431, 24955 => 29441, 24956 => 29427, -24957 => 29443, 24958 => 29434, 25121 => 29435, 25122 => 29463, 25123 => 29459, -25124 => 29473, 25125 => 29450, 25126 => 29470, 25127 => 29469, 25128 => 29461, -25129 => 29474, 25130 => 29497, 25131 => 29477, 25132 => 29484, 25133 => 29496, -25134 => 29489, 25135 => 29520, 25136 => 29517, 25137 => 29527, 25138 => 29536, -25139 => 29548, 25140 => 29551, 25141 => 29566, 25142 => 33307, 25143 => 22821, -25144 => 39143, 25145 => 22820, 25146 => 22786, 25147 => 39267, 25148 => 39271, -25149 => 39272, 25150 => 39273, 25151 => 39274, 25152 => 39275, 25153 => 39276, -25154 => 39284, 25155 => 39287, 25156 => 39293, 25157 => 39296, 25158 => 39300, -25159 => 39303, 25160 => 39306, 25161 => 39309, 25162 => 39312, 25163 => 39313, -25164 => 39315, 25165 => 39316, 25166 => 39317, 25167 => 24192, 25168 => 24209, -25169 => 24203, 25170 => 24214, 25171 => 24229, 25172 => 24224, 25173 => 24249, -25174 => 24245, 25175 => 24254, 25176 => 24243, 25177 => 36179, 25178 => 24274, -25179 => 24273, 25180 => 24283, 25181 => 24296, 25182 => 24298, 25183 => 33210, -25184 => 24516, 25185 => 24521, 25186 => 24534, 25187 => 24527, 25188 => 24579, -25189 => 24558, 25190 => 24580, 25191 => 24545, 25192 => 24548, 25193 => 24574, -25194 => 24581, 25195 => 24582, 25196 => 24554, 25197 => 24557, 25198 => 24568, -25199 => 24601, 25200 => 24629, 25201 => 24614, 25202 => 24603, 25203 => 24591, -25204 => 24589, 25205 => 24617, 25206 => 24619, 25207 => 24586, 25208 => 24639, -25209 => 24609, 25210 => 24696, 25211 => 24697, 25212 => 24699, 25213 => 24698, -25214 => 24642, 25377 => 24682, 25378 => 24701, 25379 => 24726, 25380 => 24730, -25381 => 24749, 25382 => 24733, 25383 => 24707, 25384 => 24722, 25385 => 24716, -25386 => 24731, 25387 => 24812, 25388 => 24763, 25389 => 24753, 25390 => 24797, -25391 => 24792, 25392 => 24774, 25393 => 24794, 25394 => 24756, 25395 => 24864, -25396 => 24870, 25397 => 24853, 25398 => 24867, 25399 => 24820, 25400 => 24832, -25401 => 24846, 25402 => 24875, 25403 => 24906, 25404 => 24949, 25405 => 25004, -25406 => 24980, 25407 => 24999, 25408 => 25015, 25409 => 25044, 25410 => 25077, -25411 => 24541, 25412 => 38579, 25413 => 38377, 25414 => 38379, 25415 => 38385, -25416 => 38387, 25417 => 38389, 25418 => 38390, 25419 => 38396, 25420 => 38398, -25421 => 38403, 25422 => 38404, 25423 => 38406, 25424 => 38408, 25425 => 38410, -25426 => 38411, 25427 => 38412, 25428 => 38413, 25429 => 38415, 25430 => 38418, -25431 => 38421, 25432 => 38422, 25433 => 38423, 25434 => 38425, 25435 => 38426, -25436 => 20012, 25437 => 29247, 25438 => 25109, 25439 => 27701, 25440 => 27732, -25441 => 27740, 25442 => 27722, 25443 => 27811, 25444 => 27781, 25445 => 27792, -25446 => 27796, 25447 => 27788, 25448 => 27752, 25449 => 27753, 25450 => 27764, -25451 => 27766, 25452 => 27782, 25453 => 27817, 25454 => 27856, 25455 => 27860, -25456 => 27821, 25457 => 27895, 25458 => 27896, 25459 => 27889, 25460 => 27863, -25461 => 27826, 25462 => 27872, 25463 => 27862, 25464 => 27898, 25465 => 27883, -25466 => 27886, 25467 => 27825, 25468 => 27859, 25469 => 27887, 25470 => 27902, -25633 => 27961, 25634 => 27943, 25635 => 27916, 25636 => 27971, 25637 => 27976, -25638 => 27911, 25639 => 27908, 25640 => 27929, 25641 => 27918, 25642 => 27947, -25643 => 27981, 25644 => 27950, 25645 => 27957, 25646 => 27930, 25647 => 27983, -25648 => 27986, 25649 => 27988, 25650 => 27955, 25651 => 28049, 25652 => 28015, -25653 => 28062, 25654 => 28064, 25655 => 27998, 25656 => 28051, 25657 => 28052, -25658 => 27996, 25659 => 28000, 25660 => 28028, 25661 => 28003, 25662 => 28186, -25663 => 28103, 25664 => 28101, 25665 => 28126, 25666 => 28174, 25667 => 28095, -25668 => 28128, 25669 => 28177, 25670 => 28134, 25671 => 28125, 25672 => 28121, -25673 => 28182, 25674 => 28075, 25675 => 28172, 25676 => 28078, 25677 => 28203, -25678 => 28270, 25679 => 28238, 25680 => 28267, 25681 => 28338, 25682 => 28255, -25683 => 28294, 25684 => 28243, 25685 => 28244, 25686 => 28210, 25687 => 28197, -25688 => 28228, 25689 => 28383, 25690 => 28337, 25691 => 28312, 25692 => 28384, -25693 => 28461, 25694 => 28386, 25695 => 28325, 25696 => 28327, 25697 => 28349, -25698 => 28347, 25699 => 28343, 25700 => 28375, 25701 => 28340, 25702 => 28367, -25703 => 28303, 25704 => 28354, 25705 => 28319, 25706 => 28514, 25707 => 28486, -25708 => 28487, 25709 => 28452, 25710 => 28437, 25711 => 28409, 25712 => 28463, -25713 => 28470, 25714 => 28491, 25715 => 28532, 25716 => 28458, 25717 => 28425, -25718 => 28457, 25719 => 28553, 25720 => 28557, 25721 => 28556, 25722 => 28536, -25723 => 28530, 25724 => 28540, 25725 => 28538, 25726 => 28625, 25889 => 28617, -25890 => 28583, 25891 => 28601, 25892 => 28598, 25893 => 28610, 25894 => 28641, -25895 => 28654, 25896 => 28638, 25897 => 28640, 25898 => 28655, 25899 => 28698, -25900 => 28707, 25901 => 28699, 25902 => 28729, 25903 => 28725, 25904 => 28751, -25905 => 28766, 25906 => 23424, 25907 => 23428, 25908 => 23445, 25909 => 23443, -25910 => 23461, 25911 => 23480, 25912 => 29999, 25913 => 39582, 25914 => 25652, -25915 => 23524, 25916 => 23534, 25917 => 35120, 25918 => 23536, 25919 => 36423, -25920 => 35591, 25921 => 36790, 25922 => 36819, 25923 => 36821, 25924 => 36837, -25925 => 36846, 25926 => 36836, 25927 => 36841, 25928 => 36838, 25929 => 36851, -25930 => 36840, 25931 => 36869, 25932 => 36868, 25933 => 36875, 25934 => 36902, -25935 => 36881, 25936 => 36877, 25937 => 36886, 25938 => 36897, 25939 => 36917, -25940 => 36918, 25941 => 36909, 25942 => 36911, 25943 => 36932, 25944 => 36945, -25945 => 36946, 25946 => 36944, 25947 => 36968, 25948 => 36952, 25949 => 36962, -25950 => 36955, 25951 => 26297, 25952 => 36980, 25953 => 36989, 25954 => 36994, -25955 => 37000, 25956 => 36995, 25957 => 37003, 25958 => 24400, 25959 => 24407, -25960 => 24406, 25961 => 24408, 25962 => 23611, 25963 => 21675, 25964 => 23632, -25965 => 23641, 25966 => 23409, 25967 => 23651, 25968 => 23654, 25969 => 32700, -25970 => 24362, 25971 => 24361, 25972 => 24365, 25973 => 33396, 25974 => 24380, -25975 => 39739, 25976 => 23662, 25977 => 22913, 25978 => 22915, 25979 => 22925, -25980 => 22953, 25981 => 22954, 25982 => 22947, 26145 => 22935, 26146 => 22986, -26147 => 22955, 26148 => 22942, 26149 => 22948, 26150 => 22994, 26151 => 22962, -26152 => 22959, 26153 => 22999, 26154 => 22974, 26155 => 23045, 26156 => 23046, -26157 => 23005, 26158 => 23048, 26159 => 23011, 26160 => 23000, 26161 => 23033, -26162 => 23052, 26163 => 23049, 26164 => 23090, 26165 => 23092, 26166 => 23057, -26167 => 23075, 26168 => 23059, 26169 => 23104, 26170 => 23143, 26171 => 23114, -26172 => 23125, 26173 => 23100, 26174 => 23138, 26175 => 23157, 26176 => 33004, -26177 => 23210, 26178 => 23195, 26179 => 23159, 26180 => 23162, 26181 => 23230, -26182 => 23275, 26183 => 23218, 26184 => 23250, 26185 => 23252, 26186 => 23224, -26187 => 23264, 26188 => 23267, 26189 => 23281, 26190 => 23254, 26191 => 23270, -26192 => 23256, 26193 => 23260, 26194 => 23305, 26195 => 23319, 26196 => 23318, -26197 => 23346, 26198 => 23351, 26199 => 23360, 26200 => 23573, 26201 => 23580, -26202 => 23386, 26203 => 23397, 26204 => 23411, 26205 => 23377, 26206 => 23379, -26207 => 23394, 26208 => 39541, 26209 => 39543, 26210 => 39544, 26211 => 39546, -26212 => 39551, 26213 => 39549, 26214 => 39552, 26215 => 39553, 26216 => 39557, -26217 => 39560, 26218 => 39562, 26219 => 39568, 26220 => 39570, 26221 => 39571, -26222 => 39574, 26223 => 39576, 26224 => 39579, 26225 => 39580, 26226 => 39581, -26227 => 39583, 26228 => 39584, 26229 => 39586, 26230 => 39587, 26231 => 39589, -26232 => 39591, 26233 => 32415, 26234 => 32417, 26235 => 32419, 26236 => 32421, -26237 => 32424, 26238 => 32425, 26401 => 32429, 26402 => 32432, 26403 => 32446, -26404 => 32448, 26405 => 32449, 26406 => 32450, 26407 => 32457, 26408 => 32459, -26409 => 32460, 26410 => 32464, 26411 => 32468, 26412 => 32471, 26413 => 32475, -26414 => 32480, 26415 => 32481, 26416 => 32488, 26417 => 32491, 26418 => 32494, -26419 => 32495, 26420 => 32497, 26421 => 32498, 26422 => 32525, 26423 => 32502, -26424 => 32506, 26425 => 32507, 26426 => 32510, 26427 => 32513, 26428 => 32514, -26429 => 32515, 26430 => 32519, 26431 => 32520, 26432 => 32523, 26433 => 32524, -26434 => 32527, 26435 => 32529, 26436 => 32530, 26437 => 32535, 26438 => 32537, -26439 => 32540, 26440 => 32539, 26441 => 32543, 26442 => 32545, 26443 => 32546, -26444 => 32547, 26445 => 32548, 26446 => 32549, 26447 => 32550, 26448 => 32551, -26449 => 32554, 26450 => 32555, 26451 => 32556, 26452 => 32557, 26453 => 32559, -26454 => 32560, 26455 => 32561, 26456 => 32562, 26457 => 32563, 26458 => 32565, -26459 => 24186, 26460 => 30079, 26461 => 24027, 26462 => 30014, 26463 => 37013, -26464 => 29582, 26465 => 29585, 26466 => 29614, 26467 => 29602, 26468 => 29599, -26469 => 29647, 26470 => 29634, 26471 => 29649, 26472 => 29623, 26473 => 29619, -26474 => 29632, 26475 => 29641, 26476 => 29640, 26477 => 29669, 26478 => 29657, -26479 => 39036, 26480 => 29706, 26481 => 29673, 26482 => 29671, 26483 => 29662, -26484 => 29626, 26485 => 29682, 26486 => 29711, 26487 => 29738, 26488 => 29787, -26489 => 29734, 26490 => 29733, 26491 => 29736, 26492 => 29744, 26493 => 29742, -26494 => 29740, 26657 => 29723, 26658 => 29722, 26659 => 29761, 26660 => 29788, -26661 => 29783, 26662 => 29781, 26663 => 29785, 26664 => 29815, 26665 => 29805, -26666 => 29822, 26667 => 29852, 26668 => 29838, 26669 => 29824, 26670 => 29825, -26671 => 29831, 26672 => 29835, 26673 => 29854, 26674 => 29864, 26675 => 29865, -26676 => 29840, 26677 => 29863, 26678 => 29906, 26679 => 29882, 26680 => 38890, -26681 => 38891, 26682 => 38892, 26683 => 26444, 26684 => 26451, 26685 => 26462, -26686 => 26440, 26687 => 26473, 26688 => 26533, 26689 => 26503, 26690 => 26474, -26691 => 26483, 26692 => 26520, 26693 => 26535, 26694 => 26485, 26695 => 26536, -26696 => 26526, 26697 => 26541, 26698 => 26507, 26699 => 26487, 26700 => 26492, -26701 => 26608, 26702 => 26633, 26703 => 26584, 26704 => 26634, 26705 => 26601, -26706 => 26544, 26707 => 26636, 26708 => 26585, 26709 => 26549, 26710 => 26586, -26711 => 26547, 26712 => 26589, 26713 => 26624, 26714 => 26563, 26715 => 26552, -26716 => 26594, 26717 => 26638, 26718 => 26561, 26719 => 26621, 26720 => 26674, -26721 => 26675, 26722 => 26720, 26723 => 26721, 26724 => 26702, 26725 => 26722, -26726 => 26692, 26727 => 26724, 26728 => 26755, 26729 => 26653, 26730 => 26709, -26731 => 26726, 26732 => 26689, 26733 => 26727, 26734 => 26688, 26735 => 26686, -26736 => 26698, 26737 => 26697, 26738 => 26665, 26739 => 26805, 26740 => 26767, -26741 => 26740, 26742 => 26743, 26743 => 26771, 26744 => 26731, 26745 => 26818, -26746 => 26990, 26747 => 26876, 26748 => 26911, 26749 => 26912, 26750 => 26873, -26913 => 26916, 26914 => 26864, 26915 => 26891, 26916 => 26881, 26917 => 26967, -26918 => 26851, 26919 => 26896, 26920 => 26993, 26921 => 26937, 26922 => 26976, -26923 => 26946, 26924 => 26973, 26925 => 27012, 26926 => 26987, 26927 => 27008, -26928 => 27032, 26929 => 27000, 26930 => 26932, 26931 => 27084, 26932 => 27015, -26933 => 27016, 26934 => 27086, 26935 => 27017, 26936 => 26982, 26937 => 26979, -26938 => 27001, 26939 => 27035, 26940 => 27047, 26941 => 27067, 26942 => 27051, -26943 => 27053, 26944 => 27092, 26945 => 27057, 26946 => 27073, 26947 => 27082, -26948 => 27103, 26949 => 27029, 26950 => 27104, 26951 => 27021, 26952 => 27135, -26953 => 27183, 26954 => 27117, 26955 => 27159, 26956 => 27160, 26957 => 27237, -26958 => 27122, 26959 => 27204, 26960 => 27198, 26961 => 27296, 26962 => 27216, -26963 => 27227, 26964 => 27189, 26965 => 27278, 26966 => 27257, 26967 => 27197, -26968 => 27176, 26969 => 27224, 26970 => 27260, 26971 => 27281, 26972 => 27280, -26973 => 27305, 26974 => 27287, 26975 => 27307, 26976 => 29495, 26977 => 29522, -26978 => 27521, 26979 => 27522, 26980 => 27527, 26981 => 27524, 26982 => 27538, -26983 => 27539, 26984 => 27533, 26985 => 27546, 26986 => 27547, 26987 => 27553, -26988 => 27562, 26989 => 36715, 26990 => 36717, 26991 => 36721, 26992 => 36722, -26993 => 36723, 26994 => 36725, 26995 => 36726, 26996 => 36728, 26997 => 36727, -26998 => 36729, 26999 => 36730, 27000 => 36732, 27001 => 36734, 27002 => 36737, -27003 => 36738, 27004 => 36740, 27005 => 36743, 27006 => 36747, 27169 => 36749, -27170 => 36750, 27171 => 36751, 27172 => 36760, 27173 => 36762, 27174 => 36558, -27175 => 25099, 27176 => 25111, 27177 => 25115, 27178 => 25119, 27179 => 25122, -27180 => 25121, 27181 => 25125, 27182 => 25124, 27183 => 25132, 27184 => 33255, -27185 => 29935, 27186 => 29940, 27187 => 29951, 27188 => 29967, 27189 => 29969, -27190 => 29971, 27191 => 25908, 27192 => 26094, 27193 => 26095, 27194 => 26096, -27195 => 26122, 27196 => 26137, 27197 => 26482, 27198 => 26115, 27199 => 26133, -27200 => 26112, 27201 => 28805, 27202 => 26359, 27203 => 26141, 27204 => 26164, -27205 => 26161, 27206 => 26166, 27207 => 26165, 27208 => 32774, 27209 => 26207, -27210 => 26196, 27211 => 26177, 27212 => 26191, 27213 => 26198, 27214 => 26209, -27215 => 26199, 27216 => 26231, 27217 => 26244, 27218 => 26252, 27219 => 26279, -27220 => 26269, 27221 => 26302, 27222 => 26331, 27223 => 26332, 27224 => 26342, -27225 => 26345, 27226 => 36146, 27227 => 36147, 27228 => 36150, 27229 => 36155, -27230 => 36157, 27231 => 36160, 27232 => 36165, 27233 => 36166, 27234 => 36168, -27235 => 36169, 27236 => 36167, 27237 => 36173, 27238 => 36181, 27239 => 36185, -27240 => 35271, 27241 => 35274, 27242 => 35275, 27243 => 35276, 27244 => 35278, -27245 => 35279, 27246 => 35280, 27247 => 35281, 27248 => 29294, 27249 => 29343, -27250 => 29277, 27251 => 29286, 27252 => 29295, 27253 => 29310, 27254 => 29311, -27255 => 29316, 27256 => 29323, 27257 => 29325, 27258 => 29327, 27259 => 29330, -27260 => 25352, 27261 => 25394, 27262 => 25520, 27425 => 25663, 27426 => 25816, -27427 => 32772, 27428 => 27626, 27429 => 27635, 27430 => 27645, 27431 => 27637, -27432 => 27641, 27433 => 27653, 27434 => 27655, 27435 => 27654, 27436 => 27661, -27437 => 27669, 27438 => 27672, 27439 => 27673, 27440 => 27674, 27441 => 27681, -27442 => 27689, 27443 => 27684, 27444 => 27690, 27445 => 27698, 27446 => 25909, -27447 => 25941, 27448 => 25963, 27449 => 29261, 27450 => 29266, 27451 => 29270, -27452 => 29232, 27453 => 34402, 27454 => 21014, 27455 => 32927, 27456 => 32924, -27457 => 32915, 27458 => 32956, 27459 => 26378, 27460 => 32957, 27461 => 32945, -27462 => 32939, 27463 => 32941, 27464 => 32948, 27465 => 32951, 27466 => 32999, -27467 => 33000, 27468 => 33001, 27469 => 33002, 27470 => 32987, 27471 => 32962, -27472 => 32964, 27473 => 32985, 27474 => 32973, 27475 => 32983, 27476 => 26384, -27477 => 32989, 27478 => 33003, 27479 => 33009, 27480 => 33012, 27481 => 33005, -27482 => 33037, 27483 => 33038, 27484 => 33010, 27485 => 33020, 27486 => 26389, -27487 => 33042, 27488 => 35930, 27489 => 33078, 27490 => 33054, 27491 => 33068, -27492 => 33048, 27493 => 33074, 27494 => 33096, 27495 => 33100, 27496 => 33107, -27497 => 33140, 27498 => 33113, 27499 => 33114, 27500 => 33137, 27501 => 33120, -27502 => 33129, 27503 => 33148, 27504 => 33149, 27505 => 33133, 27506 => 33127, -27507 => 22605, 27508 => 23221, 27509 => 33160, 27510 => 33154, 27511 => 33169, -27512 => 28373, 27513 => 33187, 27514 => 33194, 27515 => 33228, 27516 => 26406, -27517 => 33226, 27518 => 33211, 27681 => 33217, 27682 => 33190, 27683 => 27428, -27684 => 27447, 27685 => 27449, 27686 => 27459, 27687 => 27462, 27688 => 27481, -27689 => 39121, 27690 => 39122, 27691 => 39123, 27692 => 39125, 27693 => 39129, -27694 => 39130, 27695 => 27571, 27696 => 24384, 27697 => 27586, 27698 => 35315, -27699 => 26000, 27700 => 40785, 27701 => 26003, 27702 => 26044, 27703 => 26054, -27704 => 26052, 27705 => 26051, 27706 => 26060, 27707 => 26062, 27708 => 26066, -27709 => 26070, 27710 => 28800, 27711 => 28828, 27712 => 28822, 27713 => 28829, -27714 => 28859, 27715 => 28864, 27716 => 28855, 27717 => 28843, 27718 => 28849, -27719 => 28904, 27720 => 28874, 27721 => 28944, 27722 => 28947, 27723 => 28950, -27724 => 28975, 27725 => 28977, 27726 => 29043, 27727 => 29020, 27728 => 29032, -27729 => 28997, 27730 => 29042, 27731 => 29002, 27732 => 29048, 27733 => 29050, -27734 => 29080, 27735 => 29107, 27736 => 29109, 27737 => 29096, 27738 => 29088, -27739 => 29152, 27740 => 29140, 27741 => 29159, 27742 => 29177, 27743 => 29213, -27744 => 29224, 27745 => 28780, 27746 => 28952, 27747 => 29030, 27748 => 29113, -27749 => 25150, 27750 => 25149, 27751 => 25155, 27752 => 25160, 27753 => 25161, -27754 => 31035, 27755 => 31040, 27756 => 31046, 27757 => 31049, 27758 => 31067, -27759 => 31068, 27760 => 31059, 27761 => 31066, 27762 => 31074, 27763 => 31063, -27764 => 31072, 27765 => 31087, 27766 => 31079, 27767 => 31098, 27768 => 31109, -27769 => 31114, 27770 => 31130, 27771 => 31143, 27772 => 31155, 27773 => 24529, -27774 => 24528, 27937 => 24636, 27938 => 24669, 27939 => 24666, 27940 => 24679, -27941 => 24641, 27942 => 24665, 27943 => 24675, 27944 => 24747, 27945 => 24838, -27946 => 24845, 27947 => 24925, 27948 => 25001, 27949 => 24989, 27950 => 25035, -27951 => 25041, 27952 => 25094, 27953 => 32896, 27954 => 32895, 27955 => 27795, -27956 => 27894, 27957 => 28156, 27958 => 30710, 27959 => 30712, 27960 => 30720, -27961 => 30729, 27962 => 30743, 27963 => 30744, 27964 => 30737, 27965 => 26027, -27966 => 30765, 27967 => 30748, 27968 => 30749, 27969 => 30777, 27970 => 30778, -27971 => 30779, 27972 => 30751, 27973 => 30780, 27974 => 30757, 27975 => 30764, -27976 => 30755, 27977 => 30761, 27978 => 30798, 27979 => 30829, 27980 => 30806, -27981 => 30807, 27982 => 30758, 27983 => 30800, 27984 => 30791, 27985 => 30796, -27986 => 30826, 27987 => 30875, 27988 => 30867, 27989 => 30874, 27990 => 30855, -27991 => 30876, 27992 => 30881, 27993 => 30883, 27994 => 30898, 27995 => 30905, -27996 => 30885, 27997 => 30932, 27998 => 30937, 27999 => 30921, 28000 => 30956, -28001 => 30962, 28002 => 30981, 28003 => 30964, 28004 => 30995, 28005 => 31012, -28006 => 31006, 28007 => 31028, 28008 => 40859, 28009 => 40697, 28010 => 40699, -28011 => 40700, 28012 => 30449, 28013 => 30468, 28014 => 30477, 28015 => 30457, -28016 => 30471, 28017 => 30472, 28018 => 30490, 28019 => 30498, 28020 => 30489, -28021 => 30509, 28022 => 30502, 28023 => 30517, 28024 => 30520, 28025 => 30544, -28026 => 30545, 28027 => 30535, 28028 => 30531, 28029 => 30554, 28030 => 30568, -28193 => 30562, 28194 => 30565, 28195 => 30591, 28196 => 30605, 28197 => 30589, -28198 => 30592, 28199 => 30604, 28200 => 30609, 28201 => 30623, 28202 => 30624, -28203 => 30640, 28204 => 30645, 28205 => 30653, 28206 => 30010, 28207 => 30016, -28208 => 30030, 28209 => 30027, 28210 => 30024, 28211 => 30043, 28212 => 30066, -28213 => 30073, 28214 => 30083, 28215 => 32600, 28216 => 32609, 28217 => 32607, -28218 => 35400, 28219 => 32616, 28220 => 32628, 28221 => 32625, 28222 => 32633, -28223 => 32641, 28224 => 32638, 28225 => 30413, 28226 => 30437, 28227 => 34866, -28228 => 38021, 28229 => 38022, 28230 => 38023, 28231 => 38027, 28232 => 38026, -28233 => 38028, 28234 => 38029, 28235 => 38031, 28236 => 38032, 28237 => 38036, -28238 => 38039, 28239 => 38037, 28240 => 38042, 28241 => 38043, 28242 => 38044, -28243 => 38051, 28244 => 38052, 28245 => 38059, 28246 => 38058, 28247 => 38061, -28248 => 38060, 28249 => 38063, 28250 => 38064, 28251 => 38066, 28252 => 38068, -28253 => 38070, 28254 => 38071, 28255 => 38072, 28256 => 38073, 28257 => 38074, -28258 => 38076, 28259 => 38077, 28260 => 38079, 28261 => 38084, 28262 => 38088, -28263 => 38089, 28264 => 38090, 28265 => 38091, 28266 => 38092, 28267 => 38093, -28268 => 38094, 28269 => 38096, 28270 => 38097, 28271 => 38098, 28272 => 38101, -28273 => 38102, 28274 => 38103, 28275 => 38105, 28276 => 38104, 28277 => 38107, -28278 => 38110, 28279 => 38111, 28280 => 38112, 28281 => 38114, 28282 => 38116, -28283 => 38117, 28284 => 38119, 28285 => 38120, 28286 => 38122, 28449 => 38121, -28450 => 38123, 28451 => 38126, 28452 => 38127, 28453 => 38131, 28454 => 38132, -28455 => 38133, 28456 => 38135, 28457 => 38137, 28458 => 38140, 28459 => 38141, -28460 => 38143, 28461 => 38147, 28462 => 38146, 28463 => 38150, 28464 => 38151, -28465 => 38153, 28466 => 38154, 28467 => 38157, 28468 => 38158, 28469 => 38159, -28470 => 38162, 28471 => 38163, 28472 => 38164, 28473 => 38165, 28474 => 38166, -28475 => 38168, 28476 => 38171, 28477 => 38173, 28478 => 38174, 28479 => 38175, -28480 => 38178, 28481 => 38186, 28482 => 38187, 28483 => 38185, 28484 => 38188, -28485 => 38193, 28486 => 38194, 28487 => 38196, 28488 => 38198, 28489 => 38199, -28490 => 38200, 28491 => 38204, 28492 => 38206, 28493 => 38207, 28494 => 38210, -28495 => 38197, 28496 => 38212, 28497 => 38213, 28498 => 38214, 28499 => 38217, -28500 => 38220, 28501 => 38222, 28502 => 38223, 28503 => 38226, 28504 => 38227, -28505 => 38228, 28506 => 38230, 28507 => 38231, 28508 => 38232, 28509 => 38233, -28510 => 38235, 28511 => 38238, 28512 => 38239, 28513 => 38237, 28514 => 38241, -28515 => 38242, 28516 => 38244, 28517 => 38245, 28518 => 38246, 28519 => 38247, -28520 => 38248, 28521 => 38249, 28522 => 38250, 28523 => 38251, 28524 => 38252, -28525 => 38255, 28526 => 38257, 28527 => 38258, 28528 => 38259, 28529 => 38202, -28530 => 30695, 28531 => 30700, 28532 => 38601, 28533 => 31189, 28534 => 31213, -28535 => 31203, 28536 => 31211, 28537 => 31238, 28538 => 23879, 28539 => 31235, -28540 => 31234, 28541 => 31262, 28542 => 31252, 28705 => 31289, 28706 => 31287, -28707 => 31313, 28708 => 40655, 28709 => 39333, 28710 => 31344, 28711 => 30344, -28712 => 30350, 28713 => 30355, 28714 => 30361, 28715 => 30372, 28716 => 29918, -28717 => 29920, 28718 => 29996, 28719 => 40480, 28720 => 40482, 28721 => 40488, -28722 => 40489, 28723 => 40490, 28724 => 40491, 28725 => 40492, 28726 => 40498, -28727 => 40497, 28728 => 40502, 28729 => 40504, 28730 => 40503, 28731 => 40505, -28732 => 40506, 28733 => 40510, 28734 => 40513, 28735 => 40514, 28736 => 40516, -28737 => 40518, 28738 => 40519, 28739 => 40520, 28740 => 40521, 28741 => 40523, -28742 => 40524, 28743 => 40526, 28744 => 40529, 28745 => 40533, 28746 => 40535, -28747 => 40538, 28748 => 40539, 28749 => 40540, 28750 => 40542, 28751 => 40547, -28752 => 40550, 28753 => 40551, 28754 => 40552, 28755 => 40553, 28756 => 40554, -28757 => 40555, 28758 => 40556, 28759 => 40561, 28760 => 40557, 28761 => 40563, -28762 => 30098, 28763 => 30100, 28764 => 30102, 28765 => 30112, 28766 => 30109, -28767 => 30124, 28768 => 30115, 28769 => 30131, 28770 => 30132, 28771 => 30136, -28772 => 30148, 28773 => 30129, 28774 => 30128, 28775 => 30147, 28776 => 30146, -28777 => 30166, 28778 => 30157, 28779 => 30179, 28780 => 30184, 28781 => 30182, -28782 => 30180, 28783 => 30187, 28784 => 30183, 28785 => 30211, 28786 => 30193, -28787 => 30204, 28788 => 30207, 28789 => 30224, 28790 => 30208, 28791 => 30213, -28792 => 30220, 28793 => 30231, 28794 => 30218, 28795 => 30245, 28796 => 30232, -28797 => 30229, 28798 => 30233, 28961 => 30235, 28962 => 30268, 28963 => 30242, -28964 => 30240, 28965 => 30272, 28966 => 30253, 28967 => 30256, 28968 => 30271, -28969 => 30261, 28970 => 30275, 28971 => 30270, 28972 => 30259, 28973 => 30285, -28974 => 30302, 28975 => 30292, 28976 => 30300, 28977 => 30294, 28978 => 30315, -28979 => 30319, 28980 => 32714, 28981 => 31462, 28982 => 31352, 28983 => 31353, -28984 => 31360, 28985 => 31366, 28986 => 31368, 28987 => 31381, 28988 => 31398, -28989 => 31392, 28990 => 31404, 28991 => 31400, 28992 => 31405, 28993 => 31411, -28994 => 34916, 28995 => 34921, 28996 => 34930, 28997 => 34941, 28998 => 34943, -28999 => 34946, 29000 => 34978, 29001 => 35014, 29002 => 34999, 29003 => 35004, -29004 => 35017, 29005 => 35042, 29006 => 35022, 29007 => 35043, 29008 => 35045, -29009 => 35057, 29010 => 35098, 29011 => 35068, 29012 => 35048, 29013 => 35070, -29014 => 35056, 29015 => 35105, 29016 => 35097, 29017 => 35091, 29018 => 35099, -29019 => 35082, 29020 => 35124, 29021 => 35115, 29022 => 35126, 29023 => 35137, -29024 => 35174, 29025 => 35195, 29026 => 30091, 29027 => 32997, 29028 => 30386, -29029 => 30388, 29030 => 30684, 29031 => 32786, 29032 => 32788, 29033 => 32790, -29034 => 32796, 29035 => 32800, 29036 => 32802, 29037 => 32805, 29038 => 32806, -29039 => 32807, 29040 => 32809, 29041 => 32808, 29042 => 32817, 29043 => 32779, -29044 => 32821, 29045 => 32835, 29046 => 32838, 29047 => 32845, 29048 => 32850, -29049 => 32873, 29050 => 32881, 29051 => 35203, 29052 => 39032, 29053 => 39040, -29054 => 39043, 29217 => 39049, 29218 => 39052, 29219 => 39053, 29220 => 39055, -29221 => 39060, 29222 => 39066, 29223 => 39067, 29224 => 39070, 29225 => 39071, -29226 => 39073, 29227 => 39074, 29228 => 39077, 29229 => 39078, 29230 => 34381, -29231 => 34388, 29232 => 34412, 29233 => 34414, 29234 => 34431, 29235 => 34426, -29236 => 34428, 29237 => 34427, 29238 => 34472, 29239 => 34445, 29240 => 34443, -29241 => 34476, 29242 => 34461, 29243 => 34471, 29244 => 34467, 29245 => 34474, -29246 => 34451, 29247 => 34473, 29248 => 34486, 29249 => 34500, 29250 => 34485, -29251 => 34510, 29252 => 34480, 29253 => 34490, 29254 => 34481, 29255 => 34479, -29256 => 34505, 29257 => 34511, 29258 => 34484, 29259 => 34537, 29260 => 34545, -29261 => 34546, 29262 => 34541, 29263 => 34547, 29264 => 34512, 29265 => 34579, -29266 => 34526, 29267 => 34548, 29268 => 34527, 29269 => 34520, 29270 => 34513, -29271 => 34563, 29272 => 34567, 29273 => 34552, 29274 => 34568, 29275 => 34570, -29276 => 34573, 29277 => 34569, 29278 => 34595, 29279 => 34619, 29280 => 34590, -29281 => 34597, 29282 => 34606, 29283 => 34586, 29284 => 34622, 29285 => 34632, -29286 => 34612, 29287 => 34609, 29288 => 34601, 29289 => 34615, 29290 => 34623, -29291 => 34690, 29292 => 34594, 29293 => 34685, 29294 => 34686, 29295 => 34683, -29296 => 34656, 29297 => 34672, 29298 => 34636, 29299 => 34670, 29300 => 34699, -29301 => 34643, 29302 => 34659, 29303 => 34684, 29304 => 34660, 29305 => 34649, -29306 => 34661, 29307 => 34707, 29308 => 34735, 29309 => 34728, 29310 => 34770, -29473 => 34758, 29474 => 34696, 29475 => 34693, 29476 => 34733, 29477 => 34711, -29478 => 34691, 29479 => 34731, 29480 => 34789, 29481 => 34732, 29482 => 34741, -29483 => 34739, 29484 => 34763, 29485 => 34771, 29486 => 34749, 29487 => 34769, -29488 => 34752, 29489 => 34762, 29490 => 34779, 29491 => 34794, 29492 => 34784, -29493 => 34798, 29494 => 34838, 29495 => 34835, 29496 => 34814, 29497 => 34826, -29498 => 34843, 29499 => 34849, 29500 => 34873, 29501 => 34876, 29502 => 32566, -29503 => 32578, 29504 => 32580, 29505 => 32581, 29506 => 33296, 29507 => 31482, -29508 => 31485, 29509 => 31496, 29510 => 31491, 29511 => 31492, 29512 => 31509, -29513 => 31498, 29514 => 31531, 29515 => 31503, 29516 => 31559, 29517 => 31544, -29518 => 31530, 29519 => 31513, 29520 => 31534, 29521 => 31537, 29522 => 31520, -29523 => 31525, 29524 => 31524, 29525 => 31539, 29526 => 31550, 29527 => 31518, -29528 => 31576, 29529 => 31578, 29530 => 31557, 29531 => 31605, 29532 => 31564, -29533 => 31581, 29534 => 31584, 29535 => 31598, 29536 => 31611, 29537 => 31586, -29538 => 31602, 29539 => 31601, 29540 => 31632, 29541 => 31654, 29542 => 31655, -29543 => 31672, 29544 => 31660, 29545 => 31645, 29546 => 31656, 29547 => 31621, -29548 => 31658, 29549 => 31644, 29550 => 31650, 29551 => 31659, 29552 => 31668, -29553 => 31697, 29554 => 31681, 29555 => 31692, 29556 => 31709, 29557 => 31706, -29558 => 31717, 29559 => 31718, 29560 => 31722, 29561 => 31756, 29562 => 31742, -29563 => 31740, 29564 => 31759, 29565 => 31766, 29566 => 31755, 29729 => 31775, -29730 => 31786, 29731 => 31782, 29732 => 31800, 29733 => 31809, 29734 => 31808, -29735 => 33278, 29736 => 33281, 29737 => 33282, 29738 => 33284, 29739 => 33260, -29740 => 34884, 29741 => 33313, 29742 => 33314, 29743 => 33315, 29744 => 33325, -29745 => 33327, 29746 => 33320, 29747 => 33323, 29748 => 33336, 29749 => 33339, -29750 => 33331, 29751 => 33332, 29752 => 33342, 29753 => 33348, 29754 => 33353, -29755 => 33355, 29756 => 33359, 29757 => 33370, 29758 => 33375, 29759 => 33384, -29760 => 34942, 29761 => 34949, 29762 => 34952, 29763 => 35032, 29764 => 35039, -29765 => 35166, 29766 => 32669, 29767 => 32671, 29768 => 32679, 29769 => 32687, -29770 => 32688, 29771 => 32690, 29772 => 31868, 29773 => 25929, 29774 => 31889, -29775 => 31901, 29776 => 31900, 29777 => 31902, 29778 => 31906, 29779 => 31922, -29780 => 31932, 29781 => 31933, 29782 => 31937, 29783 => 31943, 29784 => 31948, -29785 => 31949, 29786 => 31944, 29787 => 31941, 29788 => 31959, 29789 => 31976, -29790 => 33390, 29791 => 26280, 29792 => 32703, 29793 => 32718, 29794 => 32725, -29795 => 32741, 29796 => 32737, 29797 => 32742, 29798 => 32745, 29799 => 32750, -29800 => 32755, 29801 => 31992, 29802 => 32119, 29803 => 32166, 29804 => 32174, -29805 => 32327, 29806 => 32411, 29807 => 40632, 29808 => 40628, 29809 => 36211, -29810 => 36228, 29811 => 36244, 29812 => 36241, 29813 => 36273, 29814 => 36199, -29815 => 36205, 29816 => 35911, 29817 => 35913, 29818 => 37194, 29819 => 37200, -29820 => 37198, 29821 => 37199, 29822 => 37220, 29985 => 37218, 29986 => 37217, -29987 => 37232, 29988 => 37225, 29989 => 37231, 29990 => 37245, 29991 => 37246, -29992 => 37234, 29993 => 37236, 29994 => 37241, 29995 => 37260, 29996 => 37253, -29997 => 37264, 29998 => 37261, 29999 => 37265, 30000 => 37282, 30001 => 37283, -30002 => 37290, 30003 => 37293, 30004 => 37294, 30005 => 37295, 30006 => 37301, -30007 => 37300, 30008 => 37306, 30009 => 35925, 30010 => 40574, 30011 => 36280, -30012 => 36331, 30013 => 36357, 30014 => 36441, 30015 => 36457, 30016 => 36277, -30017 => 36287, 30018 => 36284, 30019 => 36282, 30020 => 36292, 30021 => 36310, -30022 => 36311, 30023 => 36314, 30024 => 36318, 30025 => 36302, 30026 => 36303, -30027 => 36315, 30028 => 36294, 30029 => 36332, 30030 => 36343, 30031 => 36344, -30032 => 36323, 30033 => 36345, 30034 => 36347, 30035 => 36324, 30036 => 36361, -30037 => 36349, 30038 => 36372, 30039 => 36381, 30040 => 36383, 30041 => 36396, -30042 => 36398, 30043 => 36387, 30044 => 36399, 30045 => 36410, 30046 => 36416, -30047 => 36409, 30048 => 36405, 30049 => 36413, 30050 => 36401, 30051 => 36425, -30052 => 36417, 30053 => 36418, 30054 => 36433, 30055 => 36434, 30056 => 36426, -30057 => 36464, 30058 => 36470, 30059 => 36476, 30060 => 36463, 30061 => 36468, -30062 => 36485, 30063 => 36495, 30064 => 36500, 30065 => 36496, 30066 => 36508, -30067 => 36510, 30068 => 35960, 30069 => 35970, 30070 => 35978, 30071 => 35973, -30072 => 35992, 30073 => 35988, 30074 => 26011, 30075 => 35286, 30076 => 35294, -30077 => 35290, 30078 => 35292, 30241 => 35301, 30242 => 35307, 30243 => 35311, -30244 => 35390, 30245 => 35622, 30246 => 38739, 30247 => 38633, 30248 => 38643, -30249 => 38639, 30250 => 38662, 30251 => 38657, 30252 => 38664, 30253 => 38671, -30254 => 38670, 30255 => 38698, 30256 => 38701, 30257 => 38704, 30258 => 38718, -30259 => 40832, 30260 => 40835, 30261 => 40837, 30262 => 40838, 30263 => 40839, -30264 => 40840, 30265 => 40841, 30266 => 40842, 30267 => 40844, 30268 => 40702, -30269 => 40715, 30270 => 40717, 30271 => 38585, 30272 => 38588, 30273 => 38589, -30274 => 38606, 30275 => 38610, 30276 => 30655, 30277 => 38624, 30278 => 37518, -30279 => 37550, 30280 => 37576, 30281 => 37694, 30282 => 37738, 30283 => 37834, -30284 => 37775, 30285 => 37950, 30286 => 37995, 30287 => 40063, 30288 => 40066, -30289 => 40069, 30290 => 40070, 30291 => 40071, 30292 => 40072, 30293 => 31267, -30294 => 40075, 30295 => 40078, 30296 => 40080, 30297 => 40081, 30298 => 40082, -30299 => 40084, 30300 => 40085, 30301 => 40090, 30302 => 40091, 30303 => 40094, -30304 => 40095, 30305 => 40096, 30306 => 40097, 30307 => 40098, 30308 => 40099, -30309 => 40101, 30310 => 40102, 30311 => 40103, 30312 => 40104, 30313 => 40105, -30314 => 40107, 30315 => 40109, 30316 => 40110, 30317 => 40112, 30318 => 40113, -30319 => 40114, 30320 => 40115, 30321 => 40116, 30322 => 40117, 30323 => 40118, -30324 => 40119, 30325 => 40122, 30326 => 40123, 30327 => 40124, 30328 => 40125, -30329 => 40132, 30330 => 40133, 30331 => 40134, 30332 => 40135, 30333 => 40138, -30334 => 40139, 30497 => 40140, 30498 => 40141, 30499 => 40142, 30500 => 40143, -30501 => 40144, 30502 => 40147, 30503 => 40148, 30504 => 40149, 30505 => 40151, -30506 => 40152, 30507 => 40153, 30508 => 40156, 30509 => 40157, 30510 => 40159, -30511 => 40162, 30512 => 38780, 30513 => 38789, 30514 => 38801, 30515 => 38802, -30516 => 38804, 30517 => 38831, 30518 => 38827, 30519 => 38819, 30520 => 38834, -30521 => 38836, 30522 => 39601, 30523 => 39600, 30524 => 39607, 30525 => 40536, -30526 => 39606, 30527 => 39610, 30528 => 39612, 30529 => 39617, 30530 => 39616, -30531 => 39621, 30532 => 39618, 30533 => 39627, 30534 => 39628, 30535 => 39633, -30536 => 39749, 30537 => 39747, 30538 => 39751, 30539 => 39753, 30540 => 39752, -30541 => 39757, 30542 => 39761, 30543 => 39144, 30544 => 39181, 30545 => 39214, -30546 => 39253, 30547 => 39252, 30548 => 39647, 30549 => 39649, 30550 => 39654, -30551 => 39663, 30552 => 39659, 30553 => 39675, 30554 => 39661, 30555 => 39673, -30556 => 39688, 30557 => 39695, 30558 => 39699, 30559 => 39711, 30560 => 39715, -30561 => 40637, 30562 => 40638, 30563 => 32315, 30564 => 40578, 30565 => 40583, -30566 => 40584, 30567 => 40587, 30568 => 40594, 30569 => 37846, 30570 => 40605, -30571 => 40607, 30572 => 40667, 30573 => 40668, 30574 => 40669, 30575 => 40672, -30576 => 40671, 30577 => 40674, 30578 => 40681, 30579 => 40679, 30580 => 40677, -30581 => 40682, 30582 => 40687, 30583 => 40738, 30584 => 40748, 30585 => 40751, -30586 => 40761, 30587 => 40759, 30588 => 40765, 30589 => 40766, 30590 => 40772, -0 => 0 ); - - function gb2utf8($gb) { - if( !trim($gb) ) return $gb; - $utf8=''; - while($gb) { - if( ord(substr($gb,0,1)) > 127 ) { - $t=substr($gb,0,2); - $gb=substr($gb,2); - $utf8 .= $this->u2utf8($this->codetable[hexdec(bin2hex($t))-0x8080]); - } - else { - $t=substr($gb,0,1); - $gb=substr($gb,1); - $utf8 .= $this->u2utf8($t); - } - } - return $utf8; - } - - function u2utf8($c) { - $str=''; - if ($c < 0x80) { - $str.=$c; - } - else if ($c < 0x800) { - $str.=chr(0xC0 | $c>>6); - $str.=chr(0x80 | $c & 0x3F); - } - else if ($c < 0x10000) { - $str.=chr(0xE0 | $c>>12); - $str.=chr(0x80 | $c>>6 & 0x3F); - $str.=chr(0x80 | $c & 0x3F); - } - else if ($c < 0x200000) { - $str.=chr(0xF0 | $c>>18); - $str.=chr(0x80 | $c>>12 & 0x3F); - $str.=chr(0x80 | $c>>6 & 0x3F); - $str.=chr(0x80 | $c & 0x3F); - } - return $str; - } - -} // END Class - -?> + 12288, 8482 => 12289, 8483 => 12290, 8484 => 12539, 8485 => 713, + 8486 => 711, 8487 => 168, 8488 => 12291, 8489 => 12293, 8490 => 8213, + 8491 => 65374, 8492 => 8214, 8493 => 8230, 8494 => 8216, 8495 => 8217, + 8496 => 8220, 8497 => 8221, 8498 => 12308, 8499 => 12309, 8500 => 12296, + 8501 => 12297, 8502 => 12298, 8503 => 12299, 8504 => 12300, 8505 => 12301, + 8506 => 12302, 8507 => 12303, 8508 => 12310, 8509 => 12311, 8510 => 12304, + 8511 => 12305, 8512 => 177, 8513 => 215, 8514 => 247, 8515 => 8758, + 8516 => 8743, 8517 => 8744, 8518 => 8721, 8519 => 8719, 8520 => 8746, + 8521 => 8745, 8522 => 8712, 8523 => 8759, 8524 => 8730, 8525 => 8869, + 8526 => 8741, 8527 => 8736, 8528 => 8978, 8529 => 8857, 8530 => 8747, + 8531 => 8750, 8532 => 8801, 8533 => 8780, 8534 => 8776, 8535 => 8765, + 8536 => 8733, 8537 => 8800, 8538 => 8814, 8539 => 8815, 8540 => 8804, + 8541 => 8805, 8542 => 8734, 8543 => 8757, 8544 => 8756, 8545 => 9794, + 8546 => 9792, 8547 => 176, 8548 => 8242, 8549 => 8243, 8550 => 8451, + 8551 => 65284, 8552 => 164, 8553 => 65504, 8554 => 65505, 8555 => 8240, + 8556 => 167, 8557 => 8470, 8558 => 9734, 8559 => 9733, 8560 => 9675, + 8561 => 9679, 8562 => 9678, 8563 => 9671, 8564 => 9670, 8565 => 9633, + 8566 => 9632, 8567 => 9651, 8568 => 9650, 8569 => 8251, 8570 => 8594, + 8571 => 8592, 8572 => 8593, 8573 => 8595, 8574 => 12307, 8753 => 9352, + 8754 => 9353, 8755 => 9354, 8756 => 9355, 8757 => 9356, 8758 => 9357, + 8759 => 9358, 8760 => 9359, 8761 => 9360, 8762 => 9361, 8763 => 9362, + 8764 => 9363, 8765 => 9364, 8766 => 9365, 8767 => 9366, 8768 => 9367, + 8769 => 9368, 8770 => 9369, 8771 => 9370, 8772 => 9371, 8773 => 9332, + 8774 => 9333, 8775 => 9334, 8776 => 9335, 8777 => 9336, 8778 => 9337, + 8779 => 9338, 8780 => 9339, 8781 => 9340, 8782 => 9341, 8783 => 9342, + 8784 => 9343, 8785 => 9344, 8786 => 9345, 8787 => 9346, 8788 => 9347, + 8789 => 9348, 8790 => 9349, 8791 => 9350, 8792 => 9351, 8793 => 9312, + 8794 => 9313, 8795 => 9314, 8796 => 9315, 8797 => 9316, 8798 => 9317, + 8799 => 9318, 8800 => 9319, 8801 => 9320, 8802 => 9321, 8805 => 12832, + 8806 => 12833, 8807 => 12834, 8808 => 12835, 8809 => 12836, 8810 => 12837, + 8811 => 12838, 8812 => 12839, 8813 => 12840, 8814 => 12841, 8817 => 8544, + 8818 => 8545, 8819 => 8546, 8820 => 8547, 8821 => 8548, 8822 => 8549, + 8823 => 8550, 8824 => 8551, 8825 => 8552, 8826 => 8553, 8827 => 8554, + 8828 => 8555, 8993 => 65281, 8994 => 65282, 8995 => 65283, 8996 => 65509, + 8997 => 65285, 8998 => 65286, 8999 => 65287, 9000 => 65288, 9001 => 65289, + 9002 => 65290, 9003 => 65291, 9004 => 65292, 9005 => 65293, 9006 => 65294, + 9007 => 65295, 9008 => 65296, 9009 => 65297, 9010 => 65298, 9011 => 65299, + 9012 => 65300, 9013 => 65301, 9014 => 65302, 9015 => 65303, 9016 => 65304, + 9017 => 65305, 9018 => 65306, 9019 => 65307, 9020 => 65308, 9021 => 65309, + 9022 => 65310, 9023 => 65311, 9024 => 65312, 9025 => 65313, 9026 => 65314, + 9027 => 65315, 9028 => 65316, 9029 => 65317, 9030 => 65318, 9031 => 65319, + 9032 => 65320, 9033 => 65321, 9034 => 65322, 9035 => 65323, 9036 => 65324, + 9037 => 65325, 9038 => 65326, 9039 => 65327, 9040 => 65328, 9041 => 65329, + 9042 => 65330, 9043 => 65331, 9044 => 65332, 9045 => 65333, 9046 => 65334, + 9047 => 65335, 9048 => 65336, 9049 => 65337, 9050 => 65338, 9051 => 65339, + 9052 => 65340, 9053 => 65341, 9054 => 65342, 9055 => 65343, 9056 => 65344, + 9057 => 65345, 9058 => 65346, 9059 => 65347, 9060 => 65348, 9061 => 65349, + 9062 => 65350, 9063 => 65351, 9064 => 65352, 9065 => 65353, 9066 => 65354, + 9067 => 65355, 9068 => 65356, 9069 => 65357, 9070 => 65358, 9071 => 65359, + 9072 => 65360, 9073 => 65361, 9074 => 65362, 9075 => 65363, 9076 => 65364, + 9077 => 65365, 9078 => 65366, 9079 => 65367, 9080 => 65368, 9081 => 65369, + 9082 => 65370, 9083 => 65371, 9084 => 65372, 9085 => 65373, 9086 => 65507, + 9249 => 12353, 9250 => 12354, 9251 => 12355, 9252 => 12356, 9253 => 12357, + 9254 => 12358, 9255 => 12359, 9256 => 12360, 9257 => 12361, 9258 => 12362, + 9259 => 12363, 9260 => 12364, 9261 => 12365, 9262 => 12366, 9263 => 12367, + 9264 => 12368, 9265 => 12369, 9266 => 12370, 9267 => 12371, 9268 => 12372, + 9269 => 12373, 9270 => 12374, 9271 => 12375, 9272 => 12376, 9273 => 12377, + 9274 => 12378, 9275 => 12379, 9276 => 12380, 9277 => 12381, 9278 => 12382, + 9279 => 12383, 9280 => 12384, 9281 => 12385, 9282 => 12386, 9283 => 12387, + 9284 => 12388, 9285 => 12389, 9286 => 12390, 9287 => 12391, 9288 => 12392, + 9289 => 12393, 9290 => 12394, 9291 => 12395, 9292 => 12396, 9293 => 12397, + 9294 => 12398, 9295 => 12399, 9296 => 12400, 9297 => 12401, 9298 => 12402, + 9299 => 12403, 9300 => 12404, 9301 => 12405, 9302 => 12406, 9303 => 12407, + 9304 => 12408, 9305 => 12409, 9306 => 12410, 9307 => 12411, 9308 => 12412, + 9309 => 12413, 9310 => 12414, 9311 => 12415, 9312 => 12416, 9313 => 12417, + 9314 => 12418, 9315 => 12419, 9316 => 12420, 9317 => 12421, 9318 => 12422, + 9319 => 12423, 9320 => 12424, 9321 => 12425, 9322 => 12426, 9323 => 12427, + 9324 => 12428, 9325 => 12429, 9326 => 12430, 9327 => 12431, 9328 => 12432, + 9329 => 12433, 9330 => 12434, 9331 => 12435, 9505 => 12449, 9506 => 12450, + 9507 => 12451, 9508 => 12452, 9509 => 12453, 9510 => 12454, 9511 => 12455, + 9512 => 12456, 9513 => 12457, 9514 => 12458, 9515 => 12459, 9516 => 12460, + 9517 => 12461, 9518 => 12462, 9519 => 12463, 9520 => 12464, 9521 => 12465, + 9522 => 12466, 9523 => 12467, 9524 => 12468, 9525 => 12469, 9526 => 12470, + 9527 => 12471, 9528 => 12472, 9529 => 12473, 9530 => 12474, 9531 => 12475, + 9532 => 12476, 9533 => 12477, 9534 => 12478, 9535 => 12479, 9536 => 12480, + 9537 => 12481, 9538 => 12482, 9539 => 12483, 9540 => 12484, 9541 => 12485, + 9542 => 12486, 9543 => 12487, 9544 => 12488, 9545 => 12489, 9546 => 12490, + 9547 => 12491, 9548 => 12492, 9549 => 12493, 9550 => 12494, 9551 => 12495, + 9552 => 12496, 9553 => 12497, 9554 => 12498, 9555 => 12499, 9556 => 12500, + 9557 => 12501, 9558 => 12502, 9559 => 12503, 9560 => 12504, 9561 => 12505, + 9562 => 12506, 9563 => 12507, 9564 => 12508, 9565 => 12509, 9566 => 12510, + 9567 => 12511, 9568 => 12512, 9569 => 12513, 9570 => 12514, 9571 => 12515, + 9572 => 12516, 9573 => 12517, 9574 => 12518, 9575 => 12519, 9576 => 12520, + 9577 => 12521, 9578 => 12522, 9579 => 12523, 9580 => 12524, 9581 => 12525, + 9582 => 12526, 9583 => 12527, 9584 => 12528, 9585 => 12529, 9586 => 12530, + 9587 => 12531, 9588 => 12532, 9589 => 12533, 9590 => 12534, 9761 => 913, + 9762 => 914, 9763 => 915, 9764 => 916, 9765 => 917, 9766 => 918, + 9767 => 919, 9768 => 920, 9769 => 921, 9770 => 922, 9771 => 923, + 9772 => 924, 9773 => 925, 9774 => 926, 9775 => 927, 9776 => 928, + 9777 => 929, 9778 => 931, 9779 => 932, 9780 => 933, 9781 => 934, + 9782 => 935, 9783 => 936, 9784 => 937, 9793 => 945, 9794 => 946, + 9795 => 947, 9796 => 948, 9797 => 949, 9798 => 950, 9799 => 951, + 9800 => 952, 9801 => 953, 9802 => 954, 9803 => 955, 9804 => 956, + 9805 => 957, 9806 => 958, 9807 => 959, 9808 => 960, 9809 => 961, + 9810 => 963, 9811 => 964, 9812 => 965, 9813 => 966, 9814 => 967, + 9815 => 968, 9816 => 969, 10017 => 1040, 10018 => 1041, 10019 => 1042, + 10020 => 1043, 10021 => 1044, 10022 => 1045, 10023 => 1025, 10024 => 1046, + 10025 => 1047, 10026 => 1048, 10027 => 1049, 10028 => 1050, 10029 => 1051, + 10030 => 1052, 10031 => 1053, 10032 => 1054, 10033 => 1055, 10034 => 1056, + 10035 => 1057, 10036 => 1058, 10037 => 1059, 10038 => 1060, 10039 => 1061, + 10040 => 1062, 10041 => 1063, 10042 => 1064, 10043 => 1065, 10044 => 1066, + 10045 => 1067, 10046 => 1068, 10047 => 1069, 10048 => 1070, 10049 => 1071, + 10065 => 1072, 10066 => 1073, 10067 => 1074, 10068 => 1075, 10069 => 1076, + 10070 => 1077, 10071 => 1105, 10072 => 1078, 10073 => 1079, 10074 => 1080, + 10075 => 1081, 10076 => 1082, 10077 => 1083, 10078 => 1084, 10079 => 1085, + 10080 => 1086, 10081 => 1087, 10082 => 1088, 10083 => 1089, 10084 => 1090, + 10085 => 1091, 10086 => 1092, 10087 => 1093, 10088 => 1094, 10089 => 1095, + 10090 => 1096, 10091 => 1097, 10092 => 1098, 10093 => 1099, 10094 => 1100, + 10095 => 1101, 10096 => 1102, 10097 => 1103, 10273 => 257, 10274 => 225, + 10275 => 462, 10276 => 224, 10277 => 275, 10278 => 233, 10279 => 283, + 10280 => 232, 10281 => 299, 10282 => 237, 10283 => 464, 10284 => 236, + 10285 => 333, 10286 => 243, 10287 => 466, 10288 => 242, 10289 => 363, + 10290 => 250, 10291 => 468, 10292 => 249, 10293 => 470, 10294 => 472, + 10295 => 474, 10296 => 476, 10297 => 252, 10298 => 234, 10309 => 12549, + 10310 => 12550, 10311 => 12551, 10312 => 12552, 10313 => 12553, 10314 => 12554, + 10315 => 12555, 10316 => 12556, 10317 => 12557, 10318 => 12558, 10319 => 12559, + 10320 => 12560, 10321 => 12561, 10322 => 12562, 10323 => 12563, 10324 => 12564, + 10325 => 12565, 10326 => 12566, 10327 => 12567, 10328 => 12568, 10329 => 12569, + 10330 => 12570, 10331 => 12571, 10332 => 12572, 10333 => 12573, 10334 => 12574, + 10335 => 12575, 10336 => 12576, 10337 => 12577, 10338 => 12578, 10339 => 12579, + 10340 => 12580, 10341 => 12581, 10342 => 12582, 10343 => 12583, 10344 => 12584, + 10345 => 12585, 10532 => 9472, 10533 => 9473, 10534 => 9474, 10535 => 9475, + 10536 => 9476, 10537 => 9477, 10538 => 9478, 10539 => 9479, 10540 => 9480, + 10541 => 9481, 10542 => 9482, 10543 => 9483, 10544 => 9484, 10545 => 9485, + 10546 => 9486, 10547 => 9487, 10548 => 9488, 10549 => 9489, 10550 => 9490, + 10551 => 9491, 10552 => 9492, 10553 => 9493, 10554 => 9494, 10555 => 9495, + 10556 => 9496, 10557 => 9497, 10558 => 9498, 10559 => 9499, 10560 => 9500, + 10561 => 9501, 10562 => 9502, 10563 => 9503, 10564 => 9504, 10565 => 9505, + 10566 => 9506, 10567 => 9507, 10568 => 9508, 10569 => 9509, 10570 => 9510, + 10571 => 9511, 10572 => 9512, 10573 => 9513, 10574 => 9514, 10575 => 9515, + 10576 => 9516, 10577 => 9517, 10578 => 9518, 10579 => 9519, 10580 => 9520, + 10581 => 9521, 10582 => 9522, 10583 => 9523, 10584 => 9524, 10585 => 9525, + 10586 => 9526, 10587 => 9527, 10588 => 9528, 10589 => 9529, 10590 => 9530, + 10591 => 9531, 10592 => 9532, 10593 => 9533, 10594 => 9534, 10595 => 9535, + 10596 => 9536, 10597 => 9537, 10598 => 9538, 10599 => 9539, 10600 => 9540, + 10601 => 9541, 10602 => 9542, 10603 => 9543, 10604 => 9544, 10605 => 9545, + 10606 => 9546, 10607 => 9547, 12321 => 21834, 12322 => 38463, 12323 => 22467, + 12324 => 25384, 12325 => 21710, 12326 => 21769, 12327 => 21696, 12328 => 30353, + 12329 => 30284, 12330 => 34108, 12331 => 30702, 12332 => 33406, 12333 => 30861, + 12334 => 29233, 12335 => 38552, 12336 => 38797, 12337 => 27688, 12338 => 23433, + 12339 => 20474, 12340 => 25353, 12341 => 26263, 12342 => 23736, 12343 => 33018, + 12344 => 26696, 12345 => 32942, 12346 => 26114, 12347 => 30414, 12348 => 20985, + 12349 => 25942, 12350 => 29100, 12351 => 32753, 12352 => 34948, 12353 => 20658, + 12354 => 22885, 12355 => 25034, 12356 => 28595, 12357 => 33453, 12358 => 25420, + 12359 => 25170, 12360 => 21485, 12361 => 21543, 12362 => 31494, 12363 => 20843, + 12364 => 30116, 12365 => 24052, 12366 => 25300, 12367 => 36299, 12368 => 38774, + 12369 => 25226, 12370 => 32793, 12371 => 22365, 12372 => 38712, 12373 => 32610, + 12374 => 29240, 12375 => 30333, 12376 => 26575, 12377 => 30334, 12378 => 25670, + 12379 => 20336, 12380 => 36133, 12381 => 25308, 12382 => 31255, 12383 => 26001, + 12384 => 29677, 12385 => 25644, 12386 => 25203, 12387 => 33324, 12388 => 39041, + 12389 => 26495, 12390 => 29256, 12391 => 25198, 12392 => 25292, 12393 => 20276, + 12394 => 29923, 12395 => 21322, 12396 => 21150, 12397 => 32458, 12398 => 37030, + 12399 => 24110, 12400 => 26758, 12401 => 27036, 12402 => 33152, 12403 => 32465, + 12404 => 26834, 12405 => 30917, 12406 => 34444, 12407 => 38225, 12408 => 20621, + 12409 => 35876, 12410 => 33502, 12411 => 32990, 12412 => 21253, 12413 => 35090, + 12414 => 21093, 12577 => 34180, 12578 => 38649, 12579 => 20445, 12580 => 22561, + 12581 => 39281, 12582 => 23453, 12583 => 25265, 12584 => 25253, 12585 => 26292, + 12586 => 35961, 12587 => 40077, 12588 => 29190, 12589 => 26479, 12590 => 30865, + 12591 => 24754, 12592 => 21329, 12593 => 21271, 12594 => 36744, 12595 => 32972, + 12596 => 36125, 12597 => 38049, 12598 => 20493, 12599 => 29384, 12600 => 22791, + 12601 => 24811, 12602 => 28953, 12603 => 34987, 12604 => 22868, 12605 => 33519, + 12606 => 26412, 12607 => 31528, 12608 => 23849, 12609 => 32503, 12610 => 29997, + 12611 => 27893, 12612 => 36454, 12613 => 36856, 12614 => 36924, 12615 => 40763, + 12616 => 27604, 12617 => 37145, 12618 => 31508, 12619 => 24444, 12620 => 30887, + 12621 => 34006, 12622 => 34109, 12623 => 27605, 12624 => 27609, 12625 => 27606, + 12626 => 24065, 12627 => 24199, 12628 => 30201, 12629 => 38381, 12630 => 25949, + 12631 => 24330, 12632 => 24517, 12633 => 36767, 12634 => 22721, 12635 => 33218, + 12636 => 36991, 12637 => 38491, 12638 => 38829, 12639 => 36793, 12640 => 32534, + 12641 => 36140, 12642 => 25153, 12643 => 20415, 12644 => 21464, 12645 => 21342, + 12646 => 36776, 12647 => 36777, 12648 => 36779, 12649 => 36941, 12650 => 26631, + 12651 => 24426, 12652 => 33176, 12653 => 34920, 12654 => 40150, 12655 => 24971, + 12656 => 21035, 12657 => 30250, 12658 => 24428, 12659 => 25996, 12660 => 28626, + 12661 => 28392, 12662 => 23486, 12663 => 25672, 12664 => 20853, 12665 => 20912, + 12666 => 26564, 12667 => 19993, 12668 => 31177, 12669 => 39292, 12670 => 28851, + 12833 => 30149, 12834 => 24182, 12835 => 29627, 12836 => 33760, 12837 => 25773, + 12838 => 25320, 12839 => 38069, 12840 => 27874, 12841 => 21338, 12842 => 21187, + 12843 => 25615, 12844 => 38082, 12845 => 31636, 12846 => 20271, 12847 => 24091, + 12848 => 33334, 12849 => 33046, 12850 => 33162, 12851 => 28196, 12852 => 27850, + 12853 => 39539, 12854 => 25429, 12855 => 21340, 12856 => 21754, 12857 => 34917, + 12858 => 22496, 12859 => 19981, 12860 => 24067, 12861 => 27493, 12862 => 31807, + 12863 => 37096, 12864 => 24598, 12865 => 25830, 12866 => 29468, 12867 => 35009, + 12868 => 26448, 12869 => 25165, 12870 => 36130, 12871 => 30572, 12872 => 36393, + 12873 => 37319, 12874 => 24425, 12875 => 33756, 12876 => 34081, 12877 => 39184, + 12878 => 21442, 12879 => 34453, 12880 => 27531, 12881 => 24813, 12882 => 24808, + 12883 => 28799, 12884 => 33485, 12885 => 33329, 12886 => 20179, 12887 => 27815, + 12888 => 34255, 12889 => 25805, 12890 => 31961, 12891 => 27133, 12892 => 26361, + 12893 => 33609, 12894 => 21397, 12895 => 31574, 12896 => 20391, 12897 => 20876, + 12898 => 27979, 12899 => 23618, 12900 => 36461, 12901 => 25554, 12902 => 21449, + 12903 => 33580, 12904 => 33590, 12905 => 26597, 12906 => 30900, 12907 => 25661, + 12908 => 23519, 12909 => 23700, 12910 => 24046, 12911 => 35815, 12912 => 25286, + 12913 => 26612, 12914 => 35962, 12915 => 25600, 12916 => 25530, 12917 => 34633, + 12918 => 39307, 12919 => 35863, 12920 => 32544, 12921 => 38130, 12922 => 20135, + 12923 => 38416, 12924 => 39076, 12925 => 26124, 12926 => 29462, 13089 => 22330, + 13090 => 23581, 13091 => 24120, 13092 => 38271, 13093 => 20607, 13094 => 32928, + 13095 => 21378, 13096 => 25950, 13097 => 30021, 13098 => 21809, 13099 => 20513, + 13100 => 36229, 13101 => 25220, 13102 => 38046, 13103 => 26397, 13104 => 22066, + 13105 => 28526, 13106 => 24034, 13107 => 21557, 13108 => 28818, 13109 => 36710, + 13110 => 25199, 13111 => 25764, 13112 => 25507, 13113 => 24443, 13114 => 28552, + 13115 => 37108, 13116 => 33251, 13117 => 36784, 13118 => 23576, 13119 => 26216, + 13120 => 24561, 13121 => 27785, 13122 => 38472, 13123 => 36225, 13124 => 34924, + 13125 => 25745, 13126 => 31216, 13127 => 22478, 13128 => 27225, 13129 => 25104, + 13130 => 21576, 13131 => 20056, 13132 => 31243, 13133 => 24809, 13134 => 28548, + 13135 => 35802, 13136 => 25215, 13137 => 36894, 13138 => 39563, 13139 => 31204, + 13140 => 21507, 13141 => 30196, 13142 => 25345, 13143 => 21273, 13144 => 27744, + 13145 => 36831, 13146 => 24347, 13147 => 39536, 13148 => 32827, 13149 => 40831, + 13150 => 20360, 13151 => 23610, 13152 => 36196, 13153 => 32709, 13154 => 26021, + 13155 => 28861, 13156 => 20805, 13157 => 20914, 13158 => 34411, 13159 => 23815, + 13160 => 23456, 13161 => 25277, 13162 => 37228, 13163 => 30068, 13164 => 36364, + 13165 => 31264, 13166 => 24833, 13167 => 31609, 13168 => 20167, 13169 => 32504, + 13170 => 30597, 13171 => 19985, 13172 => 33261, 13173 => 21021, 13174 => 20986, + 13175 => 27249, 13176 => 21416, 13177 => 36487, 13178 => 38148, 13179 => 38607, + 13180 => 28353, 13181 => 38500, 13182 => 26970, 13345 => 30784, 13346 => 20648, + 13347 => 30679, 13348 => 25616, 13349 => 35302, 13350 => 22788, 13351 => 25571, + 13352 => 24029, 13353 => 31359, 13354 => 26941, 13355 => 20256, 13356 => 33337, + 13357 => 21912, 13358 => 20018, 13359 => 30126, 13360 => 31383, 13361 => 24162, + 13362 => 24202, 13363 => 38383, 13364 => 21019, 13365 => 21561, 13366 => 28810, + 13367 => 25462, 13368 => 38180, 13369 => 22402, 13370 => 26149, 13371 => 26943, + 13372 => 37255, 13373 => 21767, 13374 => 28147, 13375 => 32431, 13376 => 34850, + 13377 => 25139, 13378 => 32496, 13379 => 30133, 13380 => 33576, 13381 => 30913, + 13382 => 38604, 13383 => 36766, 13384 => 24904, 13385 => 29943, 13386 => 35789, + 13387 => 27492, 13388 => 21050, 13389 => 36176, 13390 => 27425, 13391 => 32874, + 13392 => 33905, 13393 => 22257, 13394 => 21254, 13395 => 20174, 13396 => 19995, + 13397 => 20945, 13398 => 31895, 13399 => 37259, 13400 => 31751, 13401 => 20419, + 13402 => 36479, 13403 => 31713, 13404 => 31388, 13405 => 25703, 13406 => 23828, + 13407 => 20652, 13408 => 33030, 13409 => 30209, 13410 => 31929, 13411 => 28140, + 13412 => 32736, 13413 => 26449, 13414 => 23384, 13415 => 23544, 13416 => 30923, + 13417 => 25774, 13418 => 25619, 13419 => 25514, 13420 => 25387, 13421 => 38169, + 13422 => 25645, 13423 => 36798, 13424 => 31572, 13425 => 30249, 13426 => 25171, + 13427 => 22823, 13428 => 21574, 13429 => 27513, 13430 => 20643, 13431 => 25140, + 13432 => 24102, 13433 => 27526, 13434 => 20195, 13435 => 36151, 13436 => 34955, + 13437 => 24453, 13438 => 36910, 13601 => 24608, 13602 => 32829, 13603 => 25285, + 13604 => 20025, 13605 => 21333, 13606 => 37112, 13607 => 25528, 13608 => 32966, + 13609 => 26086, 13610 => 27694, 13611 => 20294, 13612 => 24814, 13613 => 28129, + 13614 => 35806, 13615 => 24377, 13616 => 34507, 13617 => 24403, 13618 => 25377, + 13619 => 20826, 13620 => 33633, 13621 => 26723, 13622 => 20992, 13623 => 25443, + 13624 => 36424, 13625 => 20498, 13626 => 23707, 13627 => 31095, 13628 => 23548, + 13629 => 21040, 13630 => 31291, 13631 => 24764, 13632 => 36947, 13633 => 30423, + 13634 => 24503, 13635 => 24471, 13636 => 30340, 13637 => 36460, 13638 => 28783, + 13639 => 30331, 13640 => 31561, 13641 => 30634, 13642 => 20979, 13643 => 37011, + 13644 => 22564, 13645 => 20302, 13646 => 28404, 13647 => 36842, 13648 => 25932, + 13649 => 31515, 13650 => 29380, 13651 => 28068, 13652 => 32735, 13653 => 23265, + 13654 => 25269, 13655 => 24213, 13656 => 22320, 13657 => 33922, 13658 => 31532, + 13659 => 24093, 13660 => 24351, 13661 => 36882, 13662 => 32532, 13663 => 39072, + 13664 => 25474, 13665 => 28359, 13666 => 30872, 13667 => 28857, 13668 => 20856, + 13669 => 38747, 13670 => 22443, 13671 => 30005, 13672 => 20291, 13673 => 30008, + 13674 => 24215, 13675 => 24806, 13676 => 22880, 13677 => 28096, 13678 => 27583, + 13679 => 30857, 13680 => 21500, 13681 => 38613, 13682 => 20939, 13683 => 20993, + 13684 => 25481, 13685 => 21514, 13686 => 38035, 13687 => 35843, 13688 => 36300, + 13689 => 29241, 13690 => 30879, 13691 => 34678, 13692 => 36845, 13693 => 35853, + 13694 => 21472, 13857 => 19969, 13858 => 30447, 13859 => 21486, 13860 => 38025, + 13861 => 39030, 13862 => 40718, 13863 => 38189, 13864 => 23450, 13865 => 35746, + 13866 => 20002, 13867 => 19996, 13868 => 20908, 13869 => 33891, 13870 => 25026, + 13871 => 21160, 13872 => 26635, 13873 => 20375, 13874 => 24683, 13875 => 20923, + 13876 => 27934, 13877 => 20828, 13878 => 25238, 13879 => 26007, 13880 => 38497, + 13881 => 35910, 13882 => 36887, 13883 => 30168, 13884 => 37117, 13885 => 30563, + 13886 => 27602, 13887 => 29322, 13888 => 29420, 13889 => 35835, 13890 => 22581, + 13891 => 30585, 13892 => 36172, 13893 => 26460, 13894 => 38208, 13895 => 32922, + 13896 => 24230, 13897 => 28193, 13898 => 22930, 13899 => 31471, 13900 => 30701, + 13901 => 38203, 13902 => 27573, 13903 => 26029, 13904 => 32526, 13905 => 22534, + 13906 => 20817, 13907 => 38431, 13908 => 23545, 13909 => 22697, 13910 => 21544, + 13911 => 36466, 13912 => 25958, 13913 => 39039, 13914 => 22244, 13915 => 38045, + 13916 => 30462, 13917 => 36929, 13918 => 25479, 13919 => 21702, 13920 => 22810, + 13921 => 22842, 13922 => 22427, 13923 => 36530, 13924 => 26421, 13925 => 36346, + 13926 => 33333, 13927 => 21057, 13928 => 24816, 13929 => 22549, 13930 => 34558, + 13931 => 23784, 13932 => 40517, 13933 => 20420, 13934 => 39069, 13935 => 35769, + 13936 => 23077, 13937 => 24694, 13938 => 21380, 13939 => 25212, 13940 => 36943, + 13941 => 37122, 13942 => 39295, 13943 => 24681, 13944 => 32780, 13945 => 20799, + 13946 => 32819, 13947 => 23572, 13948 => 39285, 13949 => 27953, 13950 => 20108, + 14113 => 36144, 14114 => 21457, 14115 => 32602, 14116 => 31567, 14117 => 20240, + 14118 => 20047, 14119 => 38400, 14120 => 27861, 14121 => 29648, 14122 => 34281, + 14123 => 24070, 14124 => 30058, 14125 => 32763, 14126 => 27146, 14127 => 30718, + 14128 => 38034, 14129 => 32321, 14130 => 20961, 14131 => 28902, 14132 => 21453, + 14133 => 36820, 14134 => 33539, 14135 => 36137, 14136 => 29359, 14137 => 39277, + 14138 => 27867, 14139 => 22346, 14140 => 33459, 14141 => 26041, 14142 => 32938, + 14143 => 25151, 14144 => 38450, 14145 => 22952, 14146 => 20223, 14147 => 35775, + 14148 => 32442, 14149 => 25918, 14150 => 33778, 14151 => 38750, 14152 => 21857, + 14153 => 39134, 14154 => 32933, 14155 => 21290, 14156 => 35837, 14157 => 21536, + 14158 => 32954, 14159 => 24223, 14160 => 27832, 14161 => 36153, 14162 => 33452, + 14163 => 37210, 14164 => 21545, 14165 => 27675, 14166 => 20998, 14167 => 32439, + 14168 => 22367, 14169 => 28954, 14170 => 27774, 14171 => 31881, 14172 => 22859, + 14173 => 20221, 14174 => 24575, 14175 => 24868, 14176 => 31914, 14177 => 20016, + 14178 => 23553, 14179 => 26539, 14180 => 34562, 14181 => 23792, 14182 => 38155, + 14183 => 39118, 14184 => 30127, 14185 => 28925, 14186 => 36898, 14187 => 20911, + 14188 => 32541, 14189 => 35773, 14190 => 22857, 14191 => 20964, 14192 => 20315, + 14193 => 21542, 14194 => 22827, 14195 => 25975, 14196 => 32932, 14197 => 23413, + 14198 => 25206, 14199 => 25282, 14200 => 36752, 14201 => 24133, 14202 => 27679, + 14203 => 31526, 14204 => 20239, 14205 => 20440, 14206 => 26381, 14369 => 28014, + 14370 => 28074, 14371 => 31119, 14372 => 34993, 14373 => 24343, 14374 => 29995, + 14375 => 25242, 14376 => 36741, 14377 => 20463, 14378 => 37340, 14379 => 26023, + 14380 => 33071, 14381 => 33105, 14382 => 24220, 14383 => 33104, 14384 => 36212, + 14385 => 21103, 14386 => 35206, 14387 => 36171, 14388 => 22797, 14389 => 20613, + 14390 => 20184, 14391 => 38428, 14392 => 29238, 14393 => 33145, 14394 => 36127, + 14395 => 23500, 14396 => 35747, 14397 => 38468, 14398 => 22919, 14399 => 32538, + 14400 => 21648, 14401 => 22134, 14402 => 22030, 14403 => 35813, 14404 => 25913, + 14405 => 27010, 14406 => 38041, 14407 => 30422, 14408 => 28297, 14409 => 24178, + 14410 => 29976, 14411 => 26438, 14412 => 26577, 14413 => 31487, 14414 => 32925, + 14415 => 36214, 14416 => 24863, 14417 => 31174, 14418 => 25954, 14419 => 36195, + 14420 => 20872, 14421 => 21018, 14422 => 38050, 14423 => 32568, 14424 => 32923, + 14425 => 32434, 14426 => 23703, 14427 => 28207, 14428 => 26464, 14429 => 31705, + 14430 => 30347, 14431 => 39640, 14432 => 33167, 14433 => 32660, 14434 => 31957, + 14435 => 25630, 14436 => 38224, 14437 => 31295, 14438 => 21578, 14439 => 21733, + 14440 => 27468, 14441 => 25601, 14442 => 25096, 14443 => 40509, 14444 => 33011, + 14445 => 30105, 14446 => 21106, 14447 => 38761, 14448 => 33883, 14449 => 26684, + 14450 => 34532, 14451 => 38401, 14452 => 38548, 14453 => 38124, 14454 => 20010, + 14455 => 21508, 14456 => 32473, 14457 => 26681, 14458 => 36319, 14459 => 32789, + 14460 => 26356, 14461 => 24218, 14462 => 32697, 14625 => 22466, 14626 => 32831, + 14627 => 26775, 14628 => 24037, 14629 => 25915, 14630 => 21151, 14631 => 24685, + 14632 => 40858, 14633 => 20379, 14634 => 36524, 14635 => 20844, 14636 => 23467, + 14637 => 24339, 14638 => 24041, 14639 => 27742, 14640 => 25329, 14641 => 36129, + 14642 => 20849, 14643 => 38057, 14644 => 21246, 14645 => 27807, 14646 => 33503, + 14647 => 29399, 14648 => 22434, 14649 => 26500, 14650 => 36141, 14651 => 22815, + 14652 => 36764, 14653 => 33735, 14654 => 21653, 14655 => 31629, 14656 => 20272, + 14657 => 27837, 14658 => 23396, 14659 => 22993, 14660 => 40723, 14661 => 21476, + 14662 => 34506, 14663 => 39592, 14664 => 35895, 14665 => 32929, 14666 => 25925, + 14667 => 39038, 14668 => 22266, 14669 => 38599, 14670 => 21038, 14671 => 29916, + 14672 => 21072, 14673 => 23521, 14674 => 25346, 14675 => 35074, 14676 => 20054, + 14677 => 25296, 14678 => 24618, 14679 => 26874, 14680 => 20851, 14681 => 23448, + 14682 => 20896, 14683 => 35266, 14684 => 31649, 14685 => 39302, 14686 => 32592, + 14687 => 24815, 14688 => 28748, 14689 => 36143, 14690 => 20809, 14691 => 24191, + 14692 => 36891, 14693 => 29808, 14694 => 35268, 14695 => 22317, 14696 => 30789, + 14697 => 24402, 14698 => 40863, 14699 => 38394, 14700 => 36712, 14701 => 39740, + 14702 => 35809, 14703 => 30328, 14704 => 26690, 14705 => 26588, 14706 => 36330, + 14707 => 36149, 14708 => 21053, 14709 => 36746, 14710 => 28378, 14711 => 26829, + 14712 => 38149, 14713 => 37101, 14714 => 22269, 14715 => 26524, 14716 => 35065, + 14717 => 36807, 14718 => 21704, 14881 => 39608, 14882 => 23401, 14883 => 28023, + 14884 => 27686, 14885 => 20133, 14886 => 23475, 14887 => 39559, 14888 => 37219, + 14889 => 25000, 14890 => 37039, 14891 => 38889, 14892 => 21547, 14893 => 28085, + 14894 => 23506, 14895 => 20989, 14896 => 21898, 14897 => 32597, 14898 => 32752, + 14899 => 25788, 14900 => 25421, 14901 => 26097, 14902 => 25022, 14903 => 24717, + 14904 => 28938, 14905 => 27735, 14906 => 27721, 14907 => 22831, 14908 => 26477, + 14909 => 33322, 14910 => 22741, 14911 => 22158, 14912 => 35946, 14913 => 27627, + 14914 => 37085, 14915 => 22909, 14916 => 32791, 14917 => 21495, 14918 => 28009, + 14919 => 21621, 14920 => 21917, 14921 => 33655, 14922 => 33743, 14923 => 26680, + 14924 => 31166, 14925 => 21644, 14926 => 20309, 14927 => 21512, 14928 => 30418, + 14929 => 35977, 14930 => 38402, 14931 => 27827, 14932 => 28088, 14933 => 36203, + 14934 => 35088, 14935 => 40548, 14936 => 36154, 14937 => 22079, 14938 => 40657, + 14939 => 30165, 14940 => 24456, 14941 => 29408, 14942 => 24680, 14943 => 21756, + 14944 => 20136, 14945 => 27178, 14946 => 34913, 14947 => 24658, 14948 => 36720, + 14949 => 21700, 14950 => 28888, 14951 => 34425, 14952 => 40511, 14953 => 27946, + 14954 => 23439, 14955 => 24344, 14956 => 32418, 14957 => 21897, 14958 => 20399, + 14959 => 29492, 14960 => 21564, 14961 => 21402, 14962 => 20505, 14963 => 21518, + 14964 => 21628, 14965 => 20046, 14966 => 24573, 14967 => 29786, 14968 => 22774, + 14969 => 33899, 14970 => 32993, 14971 => 34676, 14972 => 29392, 14973 => 31946, + 14974 => 28246, 15137 => 24359, 15138 => 34382, 15139 => 21804, 15140 => 25252, + 15141 => 20114, 15142 => 27818, 15143 => 25143, 15144 => 33457, 15145 => 21719, + 15146 => 21326, 15147 => 29502, 15148 => 28369, 15149 => 30011, 15150 => 21010, + 15151 => 21270, 15152 => 35805, 15153 => 27088, 15154 => 24458, 15155 => 24576, + 15156 => 28142, 15157 => 22351, 15158 => 27426, 15159 => 29615, 15160 => 26707, + 15161 => 36824, 15162 => 32531, 15163 => 25442, 15164 => 24739, 15165 => 21796, + 15166 => 30186, 15167 => 35938, 15168 => 28949, 15169 => 28067, 15170 => 23462, + 15171 => 24187, 15172 => 33618, 15173 => 24908, 15174 => 40644, 15175 => 30970, + 15176 => 34647, 15177 => 31783, 15178 => 30343, 15179 => 20976, 15180 => 24822, + 15181 => 29004, 15182 => 26179, 15183 => 24140, 15184 => 24653, 15185 => 35854, + 15186 => 28784, 15187 => 25381, 15188 => 36745, 15189 => 24509, 15190 => 24674, + 15191 => 34516, 15192 => 22238, 15193 => 27585, 15194 => 24724, 15195 => 24935, + 15196 => 21321, 15197 => 24800, 15198 => 26214, 15199 => 36159, 15200 => 31229, + 15201 => 20250, 15202 => 28905, 15203 => 27719, 15204 => 35763, 15205 => 35826, + 15206 => 32472, 15207 => 33636, 15208 => 26127, 15209 => 23130, 15210 => 39746, + 15211 => 27985, 15212 => 28151, 15213 => 35905, 15214 => 27963, 15215 => 20249, + 15216 => 28779, 15217 => 33719, 15218 => 25110, 15219 => 24785, 15220 => 38669, + 15221 => 36135, 15222 => 31096, 15223 => 20987, 15224 => 22334, 15225 => 22522, + 15226 => 26426, 15227 => 30072, 15228 => 31293, 15229 => 31215, 15230 => 31637, + 15393 => 32908, 15394 => 39269, 15395 => 36857, 15396 => 28608, 15397 => 35749, + 15398 => 40481, 15399 => 23020, 15400 => 32489, 15401 => 32521, 15402 => 21513, + 15403 => 26497, 15404 => 26840, 15405 => 36753, 15406 => 31821, 15407 => 38598, + 15408 => 21450, 15409 => 24613, 15410 => 30142, 15411 => 27762, 15412 => 21363, + 15413 => 23241, 15414 => 32423, 15415 => 25380, 15416 => 20960, 15417 => 33034, + 15418 => 24049, 15419 => 34015, 15420 => 25216, 15421 => 20864, 15422 => 23395, + 15423 => 20238, 15424 => 31085, 15425 => 21058, 15426 => 24760, 15427 => 27982, + 15428 => 23492, 15429 => 23490, 15430 => 35745, 15431 => 35760, 15432 => 26082, + 15433 => 24524, 15434 => 38469, 15435 => 22931, 15436 => 32487, 15437 => 32426, + 15438 => 22025, 15439 => 26551, 15440 => 22841, 15441 => 20339, 15442 => 23478, + 15443 => 21152, 15444 => 33626, 15445 => 39050, 15446 => 36158, 15447 => 30002, + 15448 => 38078, 15449 => 20551, 15450 => 31292, 15451 => 20215, 15452 => 26550, + 15453 => 39550, 15454 => 23233, 15455 => 27516, 15456 => 30417, 15457 => 22362, + 15458 => 23574, 15459 => 31546, 15460 => 38388, 15461 => 29006, 15462 => 20860, + 15463 => 32937, 15464 => 33392, 15465 => 22904, 15466 => 32516, 15467 => 33575, + 15468 => 26816, 15469 => 26604, 15470 => 30897, 15471 => 30839, 15472 => 25315, + 15473 => 25441, 15474 => 31616, 15475 => 20461, 15476 => 21098, 15477 => 20943, + 15478 => 33616, 15479 => 27099, 15480 => 37492, 15481 => 36341, 15482 => 36145, + 15483 => 35265, 15484 => 38190, 15485 => 31661, 15486 => 20214, 15649 => 20581, + 15650 => 33328, 15651 => 21073, 15652 => 39279, 15653 => 28176, 15654 => 28293, + 15655 => 28071, 15656 => 24314, 15657 => 20725, 15658 => 23004, 15659 => 23558, + 15660 => 27974, 15661 => 27743, 15662 => 30086, 15663 => 33931, 15664 => 26728, + 15665 => 22870, 15666 => 35762, 15667 => 21280, 15668 => 37233, 15669 => 38477, + 15670 => 34121, 15671 => 26898, 15672 => 30977, 15673 => 28966, 15674 => 33014, + 15675 => 20132, 15676 => 37066, 15677 => 27975, 15678 => 39556, 15679 => 23047, + 15680 => 22204, 15681 => 25605, 15682 => 38128, 15683 => 30699, 15684 => 20389, + 15685 => 33050, 15686 => 29409, 15687 => 35282, 15688 => 39290, 15689 => 32564, + 15690 => 32478, 15691 => 21119, 15692 => 25945, 15693 => 37237, 15694 => 36735, + 15695 => 36739, 15696 => 21483, 15697 => 31382, 15698 => 25581, 15699 => 25509, + 15700 => 30342, 15701 => 31224, 15702 => 34903, 15703 => 38454, 15704 => 25130, + 15705 => 21163, 15706 => 33410, 15707 => 26708, 15708 => 26480, 15709 => 25463, + 15710 => 30571, 15711 => 31469, 15712 => 27905, 15713 => 32467, 15714 => 35299, + 15715 => 22992, 15716 => 25106, 15717 => 34249, 15718 => 33445, 15719 => 30028, + 15720 => 20511, 15721 => 20171, 15722 => 30117, 15723 => 35819, 15724 => 23626, + 15725 => 24062, 15726 => 31563, 15727 => 26020, 15728 => 37329, 15729 => 20170, + 15730 => 27941, 15731 => 35167, 15732 => 32039, 15733 => 38182, 15734 => 20165, + 15735 => 35880, 15736 => 36827, 15737 => 38771, 15738 => 26187, 15739 => 31105, + 15740 => 36817, 15741 => 28908, 15742 => 28024, 15905 => 23613, 15906 => 21170, + 15907 => 33606, 15908 => 20834, 15909 => 33550, 15910 => 30555, 15911 => 26230, + 15912 => 40120, 15913 => 20140, 15914 => 24778, 15915 => 31934, 15916 => 31923, + 15917 => 32463, 15918 => 20117, 15919 => 35686, 15920 => 26223, 15921 => 39048, + 15922 => 38745, 15923 => 22659, 15924 => 25964, 15925 => 38236, 15926 => 24452, + 15927 => 30153, 15928 => 38742, 15929 => 31455, 15930 => 31454, 15931 => 20928, + 15932 => 28847, 15933 => 31384, 15934 => 25578, 15935 => 31350, 15936 => 32416, + 15937 => 29590, 15938 => 38893, 15939 => 20037, 15940 => 28792, 15941 => 20061, + 15942 => 37202, 15943 => 21417, 15944 => 25937, 15945 => 26087, 15946 => 33276, + 15947 => 33285, 15948 => 21646, 15949 => 23601, 15950 => 30106, 15951 => 38816, + 15952 => 25304, 15953 => 29401, 15954 => 30141, 15955 => 23621, 15956 => 39545, + 15957 => 33738, 15958 => 23616, 15959 => 21632, 15960 => 30697, 15961 => 20030, + 15962 => 27822, 15963 => 32858, 15964 => 25298, 15965 => 25454, 15966 => 24040, + 15967 => 20855, 15968 => 36317, 15969 => 36382, 15970 => 38191, 15971 => 20465, + 15972 => 21477, 15973 => 24807, 15974 => 28844, 15975 => 21095, 15976 => 25424, + 15977 => 40515, 15978 => 23071, 15979 => 20518, 15980 => 30519, 15981 => 21367, + 15982 => 32482, 15983 => 25733, 15984 => 25899, 15985 => 25225, 15986 => 25496, + 15987 => 20500, 15988 => 29237, 15989 => 35273, 15990 => 20915, 15991 => 35776, + 15992 => 32477, 15993 => 22343, 15994 => 33740, 15995 => 38055, 15996 => 20891, + 15997 => 21531, 15998 => 23803, 16161 => 20426, 16162 => 31459, 16163 => 27994, + 16164 => 37089, 16165 => 39567, 16166 => 21888, 16167 => 21654, 16168 => 21345, + 16169 => 21679, 16170 => 24320, 16171 => 25577, 16172 => 26999, 16173 => 20975, + 16174 => 24936, 16175 => 21002, 16176 => 22570, 16177 => 21208, 16178 => 22350, + 16179 => 30733, 16180 => 30475, 16181 => 24247, 16182 => 24951, 16183 => 31968, + 16184 => 25179, 16185 => 25239, 16186 => 20130, 16187 => 28821, 16188 => 32771, + 16189 => 25335, 16190 => 28900, 16191 => 38752, 16192 => 22391, 16193 => 33499, + 16194 => 26607, 16195 => 26869, 16196 => 30933, 16197 => 39063, 16198 => 31185, + 16199 => 22771, 16200 => 21683, 16201 => 21487, 16202 => 28212, 16203 => 20811, + 16204 => 21051, 16205 => 23458, 16206 => 35838, 16207 => 32943, 16208 => 21827, + 16209 => 22438, 16210 => 24691, 16211 => 22353, 16212 => 21549, 16213 => 31354, + 16214 => 24656, 16215 => 23380, 16216 => 25511, 16217 => 25248, 16218 => 21475, + 16219 => 25187, 16220 => 23495, 16221 => 26543, 16222 => 21741, 16223 => 31391, + 16224 => 33510, 16225 => 37239, 16226 => 24211, 16227 => 35044, 16228 => 22840, + 16229 => 22446, 16230 => 25358, 16231 => 36328, 16232 => 33007, 16233 => 22359, + 16234 => 31607, 16235 => 20393, 16236 => 24555, 16237 => 23485, 16238 => 27454, + 16239 => 21281, 16240 => 31568, 16241 => 29378, 16242 => 26694, 16243 => 30719, + 16244 => 30518, 16245 => 26103, 16246 => 20917, 16247 => 20111, 16248 => 30420, + 16249 => 23743, 16250 => 31397, 16251 => 33909, 16252 => 22862, 16253 => 39745, + 16254 => 20608, 16417 => 39304, 16418 => 24871, 16419 => 28291, 16420 => 22372, + 16421 => 26118, 16422 => 25414, 16423 => 22256, 16424 => 25324, 16425 => 25193, + 16426 => 24275, 16427 => 38420, 16428 => 22403, 16429 => 25289, 16430 => 21895, + 16431 => 34593, 16432 => 33098, 16433 => 36771, 16434 => 21862, 16435 => 33713, + 16436 => 26469, 16437 => 36182, 16438 => 34013, 16439 => 23146, 16440 => 26639, + 16441 => 25318, 16442 => 31726, 16443 => 38417, 16444 => 20848, 16445 => 28572, + 16446 => 35888, 16447 => 25597, 16448 => 35272, 16449 => 25042, 16450 => 32518, + 16451 => 28866, 16452 => 28389, 16453 => 29701, 16454 => 27028, 16455 => 29436, + 16456 => 24266, 16457 => 37070, 16458 => 26391, 16459 => 28010, 16460 => 25438, + 16461 => 21171, 16462 => 29282, 16463 => 32769, 16464 => 20332, 16465 => 23013, + 16466 => 37226, 16467 => 28889, 16468 => 28061, 16469 => 21202, 16470 => 20048, + 16471 => 38647, 16472 => 38253, 16473 => 34174, 16474 => 30922, 16475 => 32047, + 16476 => 20769, 16477 => 22418, 16478 => 25794, 16479 => 32907, 16480 => 31867, + 16481 => 27882, 16482 => 26865, 16483 => 26974, 16484 => 20919, 16485 => 21400, + 16486 => 26792, 16487 => 29313, 16488 => 40654, 16489 => 31729, 16490 => 29432, + 16491 => 31163, 16492 => 28435, 16493 => 29702, 16494 => 26446, 16495 => 37324, + 16496 => 40100, 16497 => 31036, 16498 => 33673, 16499 => 33620, 16500 => 21519, + 16501 => 26647, 16502 => 20029, 16503 => 21385, 16504 => 21169, 16505 => 30782, + 16506 => 21382, 16507 => 21033, 16508 => 20616, 16509 => 20363, 16510 => 20432, + 16673 => 30178, 16674 => 31435, 16675 => 31890, 16676 => 27813, 16677 => 38582, + 16678 => 21147, 16679 => 29827, 16680 => 21737, 16681 => 20457, 16682 => 32852, + 16683 => 33714, 16684 => 36830, 16685 => 38256, 16686 => 24265, 16687 => 24604, + 16688 => 28063, 16689 => 24088, 16690 => 25947, 16691 => 33080, 16692 => 38142, + 16693 => 24651, 16694 => 28860, 16695 => 32451, 16696 => 31918, 16697 => 20937, + 16698 => 26753, 16699 => 31921, 16700 => 33391, 16701 => 20004, 16702 => 36742, + 16703 => 37327, 16704 => 26238, 16705 => 20142, 16706 => 35845, 16707 => 25769, + 16708 => 32842, 16709 => 20698, 16710 => 30103, 16711 => 29134, 16712 => 23525, + 16713 => 36797, 16714 => 28518, 16715 => 20102, 16716 => 25730, 16717 => 38243, + 16718 => 24278, 16719 => 26009, 16720 => 21015, 16721 => 35010, 16722 => 28872, + 16723 => 21155, 16724 => 29454, 16725 => 29747, 16726 => 26519, 16727 => 30967, + 16728 => 38678, 16729 => 20020, 16730 => 37051, 16731 => 40158, 16732 => 28107, + 16733 => 20955, 16734 => 36161, 16735 => 21533, 16736 => 25294, 16737 => 29618, + 16738 => 33777, 16739 => 38646, 16740 => 40836, 16741 => 38083, 16742 => 20278, + 16743 => 32666, 16744 => 20940, 16745 => 28789, 16746 => 38517, 16747 => 23725, + 16748 => 39046, 16749 => 21478, 16750 => 20196, 16751 => 28316, 16752 => 29705, + 16753 => 27060, 16754 => 30827, 16755 => 39311, 16756 => 30041, 16757 => 21016, + 16758 => 30244, 16759 => 27969, 16760 => 26611, 16761 => 20845, 16762 => 40857, + 16763 => 32843, 16764 => 21657, 16765 => 31548, 16766 => 31423, 16929 => 38534, + 16930 => 22404, 16931 => 25314, 16932 => 38471, 16933 => 27004, 16934 => 23044, + 16935 => 25602, 16936 => 31699, 16937 => 28431, 16938 => 38475, 16939 => 33446, + 16940 => 21346, 16941 => 39045, 16942 => 24208, 16943 => 28809, 16944 => 25523, + 16945 => 21348, 16946 => 34383, 16947 => 40065, 16948 => 40595, 16949 => 30860, + 16950 => 38706, 16951 => 36335, 16952 => 36162, 16953 => 40575, 16954 => 28510, + 16955 => 31108, 16956 => 24405, 16957 => 38470, 16958 => 25134, 16959 => 39540, + 16960 => 21525, 16961 => 38109, 16962 => 20387, 16963 => 26053, 16964 => 23653, + 16965 => 23649, 16966 => 32533, 16967 => 34385, 16968 => 27695, 16969 => 24459, + 16970 => 29575, 16971 => 28388, 16972 => 32511, 16973 => 23782, 16974 => 25371, + 16975 => 23402, 16976 => 28390, 16977 => 21365, 16978 => 20081, 16979 => 25504, + 16980 => 30053, 16981 => 25249, 16982 => 36718, 16983 => 20262, 16984 => 20177, + 16985 => 27814, 16986 => 32438, 16987 => 35770, 16988 => 33821, 16989 => 34746, + 16990 => 32599, 16991 => 36923, 16992 => 38179, 16993 => 31657, 16994 => 39585, + 16995 => 35064, 16996 => 33853, 16997 => 27931, 16998 => 39558, 16999 => 32476, + 17000 => 22920, 17001 => 40635, 17002 => 29595, 17003 => 30721, 17004 => 34434, + 17005 => 39532, 17006 => 39554, 17007 => 22043, 17008 => 21527, 17009 => 22475, + 17010 => 20080, 17011 => 40614, 17012 => 21334, 17013 => 36808, 17014 => 33033, + 17015 => 30610, 17016 => 39314, 17017 => 34542, 17018 => 28385, 17019 => 34067, + 17020 => 26364, 17021 => 24930, 17022 => 28459, 17185 => 35881, 17186 => 33426, + 17187 => 33579, 17188 => 30450, 17189 => 27667, 17190 => 24537, 17191 => 33725, + 17192 => 29483, 17193 => 33541, 17194 => 38170, 17195 => 27611, 17196 => 30683, + 17197 => 38086, 17198 => 21359, 17199 => 33538, 17200 => 20882, 17201 => 24125, + 17202 => 35980, 17203 => 36152, 17204 => 20040, 17205 => 29611, 17206 => 26522, + 17207 => 26757, 17208 => 37238, 17209 => 38665, 17210 => 29028, 17211 => 27809, + 17212 => 30473, 17213 => 23186, 17214 => 38209, 17215 => 27599, 17216 => 32654, + 17217 => 26151, 17218 => 23504, 17219 => 22969, 17220 => 23194, 17221 => 38376, + 17222 => 38391, 17223 => 20204, 17224 => 33804, 17225 => 33945, 17226 => 27308, + 17227 => 30431, 17228 => 38192, 17229 => 29467, 17230 => 26790, 17231 => 23391, + 17232 => 30511, 17233 => 37274, 17234 => 38753, 17235 => 31964, 17236 => 36855, + 17237 => 35868, 17238 => 24357, 17239 => 31859, 17240 => 31192, 17241 => 35269, + 17242 => 27852, 17243 => 34588, 17244 => 23494, 17245 => 24130, 17246 => 26825, + 17247 => 30496, 17248 => 32501, 17249 => 20885, 17250 => 20813, 17251 => 21193, + 17252 => 23081, 17253 => 32517, 17254 => 38754, 17255 => 33495, 17256 => 25551, + 17257 => 30596, 17258 => 34256, 17259 => 31186, 17260 => 28218, 17261 => 24217, + 17262 => 22937, 17263 => 34065, 17264 => 28781, 17265 => 27665, 17266 => 25279, + 17267 => 30399, 17268 => 25935, 17269 => 24751, 17270 => 38397, 17271 => 26126, + 17272 => 34719, 17273 => 40483, 17274 => 38125, 17275 => 21517, 17276 => 21629, + 17277 => 35884, 17278 => 25720, 17441 => 25721, 17442 => 34321, 17443 => 27169, + 17444 => 33180, 17445 => 30952, 17446 => 25705, 17447 => 39764, 17448 => 25273, + 17449 => 26411, 17450 => 33707, 17451 => 22696, 17452 => 40664, 17453 => 27819, + 17454 => 28448, 17455 => 23518, 17456 => 38476, 17457 => 35851, 17458 => 29279, + 17459 => 26576, 17460 => 25287, 17461 => 29281, 17462 => 20137, 17463 => 22982, + 17464 => 27597, 17465 => 22675, 17466 => 26286, 17467 => 24149, 17468 => 21215, + 17469 => 24917, 17470 => 26408, 17471 => 30446, 17472 => 30566, 17473 => 29287, + 17474 => 31302, 17475 => 25343, 17476 => 21738, 17477 => 21584, 17478 => 38048, + 17479 => 37027, 17480 => 23068, 17481 => 32435, 17482 => 27670, 17483 => 20035, + 17484 => 22902, 17485 => 32784, 17486 => 22856, 17487 => 21335, 17488 => 30007, + 17489 => 38590, 17490 => 22218, 17491 => 25376, 17492 => 33041, 17493 => 24700, + 17494 => 38393, 17495 => 28118, 17496 => 21602, 17497 => 39297, 17498 => 20869, + 17499 => 23273, 17500 => 33021, 17501 => 22958, 17502 => 38675, 17503 => 20522, + 17504 => 27877, 17505 => 23612, 17506 => 25311, 17507 => 20320, 17508 => 21311, + 17509 => 33147, 17510 => 36870, 17511 => 28346, 17512 => 34091, 17513 => 25288, + 17514 => 24180, 17515 => 30910, 17516 => 25781, 17517 => 25467, 17518 => 24565, + 17519 => 23064, 17520 => 37247, 17521 => 40479, 17522 => 23615, 17523 => 25423, + 17524 => 32834, 17525 => 23421, 17526 => 21870, 17527 => 38218, 17528 => 38221, + 17529 => 28037, 17530 => 24744, 17531 => 26592, 17532 => 29406, 17533 => 20957, + 17534 => 23425, 17697 => 25319, 17698 => 27870, 17699 => 29275, 17700 => 25197, + 17701 => 38062, 17702 => 32445, 17703 => 33043, 17704 => 27987, 17705 => 20892, + 17706 => 24324, 17707 => 22900, 17708 => 21162, 17709 => 24594, 17710 => 22899, + 17711 => 26262, 17712 => 34384, 17713 => 30111, 17714 => 25386, 17715 => 25062, + 17716 => 31983, 17717 => 35834, 17718 => 21734, 17719 => 27431, 17720 => 40485, + 17721 => 27572, 17722 => 34261, 17723 => 21589, 17724 => 20598, 17725 => 27812, + 17726 => 21866, 17727 => 36276, 17728 => 29228, 17729 => 24085, 17730 => 24597, + 17731 => 29750, 17732 => 25293, 17733 => 25490, 17734 => 29260, 17735 => 24472, + 17736 => 28227, 17737 => 27966, 17738 => 25856, 17739 => 28504, 17740 => 30424, + 17741 => 30928, 17742 => 30460, 17743 => 30036, 17744 => 21028, 17745 => 21467, + 17746 => 20051, 17747 => 24222, 17748 => 26049, 17749 => 32810, 17750 => 32982, + 17751 => 25243, 17752 => 21638, 17753 => 21032, 17754 => 28846, 17755 => 34957, + 17756 => 36305, 17757 => 27873, 17758 => 21624, 17759 => 32986, 17760 => 22521, + 17761 => 35060, 17762 => 36180, 17763 => 38506, 17764 => 37197, 17765 => 20329, + 17766 => 27803, 17767 => 21943, 17768 => 30406, 17769 => 30768, 17770 => 25256, + 17771 => 28921, 17772 => 28558, 17773 => 24429, 17774 => 34028, 17775 => 26842, + 17776 => 30844, 17777 => 31735, 17778 => 33192, 17779 => 26379, 17780 => 40527, + 17781 => 25447, 17782 => 30896, 17783 => 22383, 17784 => 30738, 17785 => 38713, + 17786 => 25209, 17787 => 25259, 17788 => 21128, 17789 => 29749, 17790 => 27607, + 17953 => 21860, 17954 => 33086, 17955 => 30130, 17956 => 30382, 17957 => 21305, + 17958 => 30174, 17959 => 20731, 17960 => 23617, 17961 => 35692, 17962 => 31687, + 17963 => 20559, 17964 => 29255, 17965 => 39575, 17966 => 39128, 17967 => 28418, + 17968 => 29922, 17969 => 31080, 17970 => 25735, 17971 => 30629, 17972 => 25340, + 17973 => 39057, 17974 => 36139, 17975 => 21697, 17976 => 32856, 17977 => 20050, + 17978 => 22378, 17979 => 33529, 17980 => 33805, 17981 => 24179, 17982 => 20973, + 17983 => 29942, 17984 => 35780, 17985 => 23631, 17986 => 22369, 17987 => 27900, + 17988 => 39047, 17989 => 23110, 17990 => 30772, 17991 => 39748, 17992 => 36843, + 17993 => 31893, 17994 => 21078, 17995 => 25169, 17996 => 38138, 17997 => 20166, + 17998 => 33670, 17999 => 33889, 18000 => 33769, 18001 => 33970, 18002 => 22484, + 18003 => 26420, 18004 => 22275, 18005 => 26222, 18006 => 28006, 18007 => 35889, + 18008 => 26333, 18009 => 28689, 18010 => 26399, 18011 => 27450, 18012 => 26646, + 18013 => 25114, 18014 => 22971, 18015 => 19971, 18016 => 20932, 18017 => 28422, + 18018 => 26578, 18019 => 27791, 18020 => 20854, 18021 => 26827, 18022 => 22855, + 18023 => 27495, 18024 => 30054, 18025 => 23822, 18026 => 33040, 18027 => 40784, + 18028 => 26071, 18029 => 31048, 18030 => 31041, 18031 => 39569, 18032 => 36215, + 18033 => 23682, 18034 => 20062, 18035 => 20225, 18036 => 21551, 18037 => 22865, + 18038 => 30732, 18039 => 22120, 18040 => 27668, 18041 => 36804, 18042 => 24323, + 18043 => 27773, 18044 => 27875, 18045 => 35755, 18046 => 25488, 18209 => 24688, + 18210 => 27965, 18211 => 29301, 18212 => 25190, 18213 => 38030, 18214 => 38085, + 18215 => 21315, 18216 => 36801, 18217 => 31614, 18218 => 20191, 18219 => 35878, + 18220 => 20094, 18221 => 40660, 18222 => 38065, 18223 => 38067, 18224 => 21069, + 18225 => 28508, 18226 => 36963, 18227 => 27973, 18228 => 35892, 18229 => 22545, + 18230 => 23884, 18231 => 27424, 18232 => 27465, 18233 => 26538, 18234 => 21595, + 18235 => 33108, 18236 => 32652, 18237 => 22681, 18238 => 34103, 18239 => 24378, + 18240 => 25250, 18241 => 27207, 18242 => 38201, 18243 => 25970, 18244 => 24708, + 18245 => 26725, 18246 => 30631, 18247 => 20052, 18248 => 20392, 18249 => 24039, + 18250 => 38808, 18251 => 25772, 18252 => 32728, 18253 => 23789, 18254 => 20431, + 18255 => 31373, 18256 => 20999, 18257 => 33540, 18258 => 19988, 18259 => 24623, + 18260 => 31363, 18261 => 38054, 18262 => 20405, 18263 => 20146, 18264 => 31206, + 18265 => 29748, 18266 => 21220, 18267 => 33465, 18268 => 25810, 18269 => 31165, + 18270 => 23517, 18271 => 27777, 18272 => 38738, 18273 => 36731, 18274 => 27682, + 18275 => 20542, 18276 => 21375, 18277 => 28165, 18278 => 25806, 18279 => 26228, + 18280 => 27696, 18281 => 24773, 18282 => 39031, 18283 => 35831, 18284 => 24198, + 18285 => 29756, 18286 => 31351, 18287 => 31179, 18288 => 19992, 18289 => 37041, + 18290 => 29699, 18291 => 27714, 18292 => 22234, 18293 => 37195, 18294 => 27845, + 18295 => 36235, 18296 => 21306, 18297 => 34502, 18298 => 26354, 18299 => 36527, + 18300 => 23624, 18301 => 39537, 18302 => 28192, 18465 => 21462, 18466 => 23094, + 18467 => 40843, 18468 => 36259, 18469 => 21435, 18470 => 22280, 18471 => 39079, + 18472 => 26435, 18473 => 37275, 18474 => 27849, 18475 => 20840, 18476 => 30154, + 18477 => 25331, 18478 => 29356, 18479 => 21048, 18480 => 21149, 18481 => 32570, + 18482 => 28820, 18483 => 30264, 18484 => 21364, 18485 => 40522, 18486 => 27063, + 18487 => 30830, 18488 => 38592, 18489 => 35033, 18490 => 32676, 18491 => 28982, + 18492 => 29123, 18493 => 20873, 18494 => 26579, 18495 => 29924, 18496 => 22756, + 18497 => 25880, 18498 => 22199, 18499 => 35753, 18500 => 39286, 18501 => 25200, + 18502 => 32469, 18503 => 24825, 18504 => 28909, 18505 => 22764, 18506 => 20161, + 18507 => 20154, 18508 => 24525, 18509 => 38887, 18510 => 20219, 18511 => 35748, + 18512 => 20995, 18513 => 22922, 18514 => 32427, 18515 => 25172, 18516 => 20173, + 18517 => 26085, 18518 => 25102, 18519 => 33592, 18520 => 33993, 18521 => 33635, + 18522 => 34701, 18523 => 29076, 18524 => 28342, 18525 => 23481, 18526 => 32466, + 18527 => 20887, 18528 => 25545, 18529 => 26580, 18530 => 32905, 18531 => 33593, + 18532 => 34837, 18533 => 20754, 18534 => 23418, 18535 => 22914, 18536 => 36785, + 18537 => 20083, 18538 => 27741, 18539 => 20837, 18540 => 35109, 18541 => 36719, + 18542 => 38446, 18543 => 34122, 18544 => 29790, 18545 => 38160, 18546 => 38384, + 18547 => 28070, 18548 => 33509, 18549 => 24369, 18550 => 25746, 18551 => 27922, + 18552 => 33832, 18553 => 33134, 18554 => 40131, 18555 => 22622, 18556 => 36187, + 18557 => 19977, 18558 => 21441, 18721 => 20254, 18722 => 25955, 18723 => 26705, + 18724 => 21971, 18725 => 20007, 18726 => 25620, 18727 => 39578, 18728 => 25195, + 18729 => 23234, 18730 => 29791, 18731 => 33394, 18732 => 28073, 18733 => 26862, + 18734 => 20711, 18735 => 33678, 18736 => 30722, 18737 => 26432, 18738 => 21049, + 18739 => 27801, 18740 => 32433, 18741 => 20667, 18742 => 21861, 18743 => 29022, + 18744 => 31579, 18745 => 26194, 18746 => 29642, 18747 => 33515, 18748 => 26441, + 18749 => 23665, 18750 => 21024, 18751 => 29053, 18752 => 34923, 18753 => 38378, + 18754 => 38485, 18755 => 25797, 18756 => 36193, 18757 => 33203, 18758 => 21892, + 18759 => 27733, 18760 => 25159, 18761 => 32558, 18762 => 22674, 18763 => 20260, + 18764 => 21830, 18765 => 36175, 18766 => 26188, 18767 => 19978, 18768 => 23578, + 18769 => 35059, 18770 => 26786, 18771 => 25422, 18772 => 31245, 18773 => 28903, + 18774 => 33421, 18775 => 21242, 18776 => 38902, 18777 => 23569, 18778 => 21736, + 18779 => 37045, 18780 => 32461, 18781 => 22882, 18782 => 36170, 18783 => 34503, + 18784 => 33292, 18785 => 33293, 18786 => 36198, 18787 => 25668, 18788 => 23556, + 18789 => 24913, 18790 => 28041, 18791 => 31038, 18792 => 35774, 18793 => 30775, + 18794 => 30003, 18795 => 21627, 18796 => 20280, 18797 => 36523, 18798 => 28145, + 18799 => 23072, 18800 => 32453, 18801 => 31070, 18802 => 27784, 18803 => 23457, + 18804 => 23158, 18805 => 29978, 18806 => 32958, 18807 => 24910, 18808 => 28183, + 18809 => 22768, 18810 => 29983, 18811 => 29989, 18812 => 29298, 18813 => 21319, + 18814 => 32499, 18977 => 30465, 18978 => 30427, 18979 => 21097, 18980 => 32988, + 18981 => 22307, 18982 => 24072, 18983 => 22833, 18984 => 29422, 18985 => 26045, + 18986 => 28287, 18987 => 35799, 18988 => 23608, 18989 => 34417, 18990 => 21313, + 18991 => 30707, 18992 => 25342, 18993 => 26102, 18994 => 20160, 18995 => 39135, + 18996 => 34432, 18997 => 23454, 18998 => 35782, 18999 => 21490, 19000 => 30690, + 19001 => 20351, 19002 => 23630, 19003 => 39542, 19004 => 22987, 19005 => 24335, + 19006 => 31034, 19007 => 22763, 19008 => 19990, 19009 => 26623, 19010 => 20107, + 19011 => 25325, 19012 => 35475, 19013 => 36893, 19014 => 21183, 19015 => 26159, + 19016 => 21980, 19017 => 22124, 19018 => 36866, 19019 => 20181, 19020 => 20365, + 19021 => 37322, 19022 => 39280, 19023 => 27663, 19024 => 24066, 19025 => 24643, + 19026 => 23460, 19027 => 35270, 19028 => 35797, 19029 => 25910, 19030 => 25163, + 19031 => 39318, 19032 => 23432, 19033 => 23551, 19034 => 25480, 19035 => 21806, + 19036 => 21463, 19037 => 30246, 19038 => 20861, 19039 => 34092, 19040 => 26530, + 19041 => 26803, 19042 => 27530, 19043 => 25234, 19044 => 36755, 19045 => 21460, + 19046 => 33298, 19047 => 28113, 19048 => 30095, 19049 => 20070, 19050 => 36174, + 19051 => 23408, 19052 => 29087, 19053 => 34223, 19054 => 26257, 19055 => 26329, + 19056 => 32626, 19057 => 34560, 19058 => 40653, 19059 => 40736, 19060 => 23646, + 19061 => 26415, 19062 => 36848, 19063 => 26641, 19064 => 26463, 19065 => 25101, + 19066 => 31446, 19067 => 22661, 19068 => 24246, 19069 => 25968, 19070 => 28465, + 19233 => 24661, 19234 => 21047, 19235 => 32781, 19236 => 25684, 19237 => 34928, + 19238 => 29993, 19239 => 24069, 19240 => 26643, 19241 => 25332, 19242 => 38684, + 19243 => 21452, 19244 => 29245, 19245 => 35841, 19246 => 27700, 19247 => 30561, + 19248 => 31246, 19249 => 21550, 19250 => 30636, 19251 => 39034, 19252 => 33308, + 19253 => 35828, 19254 => 30805, 19255 => 26388, 19256 => 28865, 19257 => 26031, + 19258 => 25749, 19259 => 22070, 19260 => 24605, 19261 => 31169, 19262 => 21496, + 19263 => 19997, 19264 => 27515, 19265 => 32902, 19266 => 23546, 19267 => 21987, + 19268 => 22235, 19269 => 20282, 19270 => 20284, 19271 => 39282, 19272 => 24051, + 19273 => 26494, 19274 => 32824, 19275 => 24578, 19276 => 39042, 19277 => 36865, + 19278 => 23435, 19279 => 35772, 19280 => 35829, 19281 => 25628, 19282 => 33368, + 19283 => 25822, 19284 => 22013, 19285 => 33487, 19286 => 37221, 19287 => 20439, + 19288 => 32032, 19289 => 36895, 19290 => 31903, 19291 => 20723, 19292 => 22609, + 19293 => 28335, 19294 => 23487, 19295 => 35785, 19296 => 32899, 19297 => 37240, + 19298 => 33948, 19299 => 31639, 19300 => 34429, 19301 => 38539, 19302 => 38543, + 19303 => 32485, 19304 => 39635, 19305 => 30862, 19306 => 23681, 19307 => 31319, + 19308 => 36930, 19309 => 38567, 19310 => 31071, 19311 => 23385, 19312 => 25439, + 19313 => 31499, 19314 => 34001, 19315 => 26797, 19316 => 21766, 19317 => 32553, + 19318 => 29712, 19319 => 32034, 19320 => 38145, 19321 => 25152, 19322 => 22604, + 19323 => 20182, 19324 => 23427, 19325 => 22905, 19326 => 22612, 19489 => 29549, + 19490 => 25374, 19491 => 36427, 19492 => 36367, 19493 => 32974, 19494 => 33492, + 19495 => 25260, 19496 => 21488, 19497 => 27888, 19498 => 37214, 19499 => 22826, + 19500 => 24577, 19501 => 27760, 19502 => 22349, 19503 => 25674, 19504 => 36138, + 19505 => 30251, 19506 => 28393, 19507 => 22363, 19508 => 27264, 19509 => 30192, + 19510 => 28525, 19511 => 35885, 19512 => 35848, 19513 => 22374, 19514 => 27631, + 19515 => 34962, 19516 => 30899, 19517 => 25506, 19518 => 21497, 19519 => 28845, + 19520 => 27748, 19521 => 22616, 19522 => 25642, 19523 => 22530, 19524 => 26848, + 19525 => 33179, 19526 => 21776, 19527 => 31958, 19528 => 20504, 19529 => 36538, + 19530 => 28108, 19531 => 36255, 19532 => 28907, 19533 => 25487, 19534 => 28059, + 19535 => 28372, 19536 => 32486, 19537 => 33796, 19538 => 26691, 19539 => 36867, + 19540 => 28120, 19541 => 38518, 19542 => 35752, 19543 => 22871, 19544 => 29305, + 19545 => 34276, 19546 => 33150, 19547 => 30140, 19548 => 35466, 19549 => 26799, + 19550 => 21076, 19551 => 36386, 19552 => 38161, 19553 => 25552, 19554 => 39064, + 19555 => 36420, 19556 => 21884, 19557 => 20307, 19558 => 26367, 19559 => 22159, + 19560 => 24789, 19561 => 28053, 19562 => 21059, 19563 => 23625, 19564 => 22825, + 19565 => 28155, 19566 => 22635, 19567 => 30000, 19568 => 29980, 19569 => 24684, + 19570 => 33300, 19571 => 33094, 19572 => 25361, 19573 => 26465, 19574 => 36834, + 19575 => 30522, 19576 => 36339, 19577 => 36148, 19578 => 38081, 19579 => 24086, + 19580 => 21381, 19581 => 21548, 19582 => 28867, 19745 => 27712, 19746 => 24311, + 19747 => 20572, 19748 => 20141, 19749 => 24237, 19750 => 25402, 19751 => 33351, + 19752 => 36890, 19753 => 26704, 19754 => 37230, 19755 => 30643, 19756 => 21516, + 19757 => 38108, 19758 => 24420, 19759 => 31461, 19760 => 26742, 19761 => 25413, + 19762 => 31570, 19763 => 32479, 19764 => 30171, 19765 => 20599, 19766 => 25237, + 19767 => 22836, 19768 => 36879, 19769 => 20984, 19770 => 31171, 19771 => 31361, + 19772 => 22270, 19773 => 24466, 19774 => 36884, 19775 => 28034, 19776 => 23648, + 19777 => 22303, 19778 => 21520, 19779 => 20820, 19780 => 28237, 19781 => 22242, + 19782 => 25512, 19783 => 39059, 19784 => 33151, 19785 => 34581, 19786 => 35114, + 19787 => 36864, 19788 => 21534, 19789 => 23663, 19790 => 33216, 19791 => 25302, + 19792 => 25176, 19793 => 33073, 19794 => 40501, 19795 => 38464, 19796 => 39534, + 19797 => 39548, 19798 => 26925, 19799 => 22949, 19800 => 25299, 19801 => 21822, + 19802 => 25366, 19803 => 21703, 19804 => 34521, 19805 => 27964, 19806 => 23043, + 19807 => 29926, 19808 => 34972, 19809 => 27498, 19810 => 22806, 19811 => 35916, + 19812 => 24367, 19813 => 28286, 19814 => 29609, 19815 => 39037, 19816 => 20024, + 19817 => 28919, 19818 => 23436, 19819 => 30871, 19820 => 25405, 19821 => 26202, + 19822 => 30358, 19823 => 24779, 19824 => 23451, 19825 => 23113, 19826 => 19975, + 19827 => 33109, 19828 => 27754, 19829 => 29579, 19830 => 20129, 19831 => 26505, + 19832 => 32593, 19833 => 24448, 19834 => 26106, 19835 => 26395, 19836 => 24536, + 19837 => 22916, 19838 => 23041, 20001 => 24013, 20002 => 24494, 20003 => 21361, + 20004 => 38886, 20005 => 36829, 20006 => 26693, 20007 => 22260, 20008 => 21807, + 20009 => 24799, 20010 => 20026, 20011 => 28493, 20012 => 32500, 20013 => 33479, + 20014 => 33806, 20015 => 22996, 20016 => 20255, 20017 => 20266, 20018 => 23614, + 20019 => 32428, 20020 => 26410, 20021 => 34074, 20022 => 21619, 20023 => 30031, + 20024 => 32963, 20025 => 21890, 20026 => 39759, 20027 => 20301, 20028 => 28205, + 20029 => 35859, 20030 => 23561, 20031 => 24944, 20032 => 21355, 20033 => 30239, + 20034 => 28201, 20035 => 34442, 20036 => 25991, 20037 => 38395, 20038 => 32441, + 20039 => 21563, 20040 => 31283, 20041 => 32010, 20042 => 38382, 20043 => 21985, + 20044 => 32705, 20045 => 29934, 20046 => 25373, 20047 => 34583, 20048 => 28065, + 20049 => 31389, 20050 => 25105, 20051 => 26017, 20052 => 21351, 20053 => 25569, + 20054 => 27779, 20055 => 24043, 20056 => 21596, 20057 => 38056, 20058 => 20044, + 20059 => 27745, 20060 => 35820, 20061 => 23627, 20062 => 26080, 20063 => 33436, + 20064 => 26791, 20065 => 21566, 20066 => 21556, 20067 => 27595, 20068 => 27494, + 20069 => 20116, 20070 => 25410, 20071 => 21320, 20072 => 33310, 20073 => 20237, + 20074 => 20398, 20075 => 22366, 20076 => 25098, 20077 => 38654, 20078 => 26212, + 20079 => 29289, 20080 => 21247, 20081 => 21153, 20082 => 24735, 20083 => 35823, + 20084 => 26132, 20085 => 29081, 20086 => 26512, 20087 => 35199, 20088 => 30802, + 20089 => 30717, 20090 => 26224, 20091 => 22075, 20092 => 21560, 20093 => 38177, + 20094 => 29306, 20257 => 31232, 20258 => 24687, 20259 => 24076, 20260 => 24713, + 20261 => 33181, 20262 => 22805, 20263 => 24796, 20264 => 29060, 20265 => 28911, + 20266 => 28330, 20267 => 27728, 20268 => 29312, 20269 => 27268, 20270 => 34989, + 20271 => 24109, 20272 => 20064, 20273 => 23219, 20274 => 21916, 20275 => 38115, + 20276 => 27927, 20277 => 31995, 20278 => 38553, 20279 => 25103, 20280 => 32454, + 20281 => 30606, 20282 => 34430, 20283 => 21283, 20284 => 38686, 20285 => 36758, + 20286 => 26247, 20287 => 23777, 20288 => 20384, 20289 => 29421, 20290 => 19979, + 20291 => 21414, 20292 => 22799, 20293 => 21523, 20294 => 25472, 20295 => 38184, + 20296 => 20808, 20297 => 20185, 20298 => 40092, 20299 => 32420, 20300 => 21688, + 20301 => 36132, 20302 => 34900, 20303 => 33335, 20304 => 38386, 20305 => 28046, + 20306 => 24358, 20307 => 23244, 20308 => 26174, 20309 => 38505, 20310 => 29616, + 20311 => 29486, 20312 => 21439, 20313 => 33146, 20314 => 39301, 20315 => 32673, + 20316 => 23466, 20317 => 38519, 20318 => 38480, 20319 => 32447, 20320 => 30456, + 20321 => 21410, 20322 => 38262, 20323 => 39321, 20324 => 31665, 20325 => 35140, + 20326 => 28248, 20327 => 20065, 20328 => 32724, 20329 => 31077, 20330 => 35814, + 20331 => 24819, 20332 => 21709, 20333 => 20139, 20334 => 39033, 20335 => 24055, + 20336 => 27233, 20337 => 20687, 20338 => 21521, 20339 => 35937, 20340 => 33831, + 20341 => 30813, 20342 => 38660, 20343 => 21066, 20344 => 21742, 20345 => 22179, + 20346 => 38144, 20347 => 28040, 20348 => 23477, 20349 => 28102, 20350 => 26195, + 20513 => 23567, 20514 => 23389, 20515 => 26657, 20516 => 32918, 20517 => 21880, + 20518 => 31505, 20519 => 25928, 20520 => 26964, 20521 => 20123, 20522 => 27463, + 20523 => 34638, 20524 => 38795, 20525 => 21327, 20526 => 25375, 20527 => 25658, + 20528 => 37034, 20529 => 26012, 20530 => 32961, 20531 => 35856, 20532 => 20889, + 20533 => 26800, 20534 => 21368, 20535 => 34809, 20536 => 25032, 20537 => 27844, + 20538 => 27899, 20539 => 35874, 20540 => 23633, 20541 => 34218, 20542 => 33455, + 20543 => 38156, 20544 => 27427, 20545 => 36763, 20546 => 26032, 20547 => 24571, + 20548 => 24515, 20549 => 20449, 20550 => 34885, 20551 => 26143, 20552 => 33125, + 20553 => 29481, 20554 => 24826, 20555 => 20852, 20556 => 21009, 20557 => 22411, + 20558 => 24418, 20559 => 37026, 20560 => 34892, 20561 => 37266, 20562 => 24184, + 20563 => 26447, 20564 => 24615, 20565 => 22995, 20566 => 20804, 20567 => 20982, + 20568 => 33016, 20569 => 21256, 20570 => 27769, 20571 => 38596, 20572 => 29066, + 20573 => 20241, 20574 => 20462, 20575 => 32670, 20576 => 26429, 20577 => 21957, + 20578 => 38152, 20579 => 31168, 20580 => 34966, 20581 => 32483, 20582 => 22687, + 20583 => 25100, 20584 => 38656, 20585 => 34394, 20586 => 22040, 20587 => 39035, + 20588 => 24464, 20589 => 35768, 20590 => 33988, 20591 => 37207, 20592 => 21465, + 20593 => 26093, 20594 => 24207, 20595 => 30044, 20596 => 24676, 20597 => 32110, + 20598 => 23167, 20599 => 32490, 20600 => 32493, 20601 => 36713, 20602 => 21927, + 20603 => 23459, 20604 => 24748, 20605 => 26059, 20606 => 29572, 20769 => 36873, + 20770 => 30307, 20771 => 30505, 20772 => 32474, 20773 => 38772, 20774 => 34203, + 20775 => 23398, 20776 => 31348, 20777 => 38634, 20778 => 34880, 20779 => 21195, + 20780 => 29071, 20781 => 24490, 20782 => 26092, 20783 => 35810, 20784 => 23547, + 20785 => 39535, 20786 => 24033, 20787 => 27529, 20788 => 27739, 20789 => 35757, + 20790 => 35759, 20791 => 36874, 20792 => 36805, 20793 => 21387, 20794 => 25276, + 20795 => 40486, 20796 => 40493, 20797 => 21568, 20798 => 20011, 20799 => 33469, + 20800 => 29273, 20801 => 34460, 20802 => 23830, 20803 => 34905, 20804 => 28079, + 20805 => 38597, 20806 => 21713, 20807 => 20122, 20808 => 35766, 20809 => 28937, + 20810 => 21693, 20811 => 38409, 20812 => 28895, 20813 => 28153, 20814 => 30416, + 20815 => 20005, 20816 => 30740, 20817 => 34578, 20818 => 23721, 20819 => 24310, + 20820 => 35328, 20821 => 39068, 20822 => 38414, 20823 => 28814, 20824 => 27839, + 20825 => 22852, 20826 => 25513, 20827 => 30524, 20828 => 34893, 20829 => 28436, + 20830 => 33395, 20831 => 22576, 20832 => 29141, 20833 => 21388, 20834 => 30746, + 20835 => 38593, 20836 => 21761, 20837 => 24422, 20838 => 28976, 20839 => 23476, + 20840 => 35866, 20841 => 39564, 20842 => 27523, 20843 => 22830, 20844 => 40495, + 20845 => 31207, 20846 => 26472, 20847 => 25196, 20848 => 20335, 20849 => 30113, + 20850 => 32650, 20851 => 27915, 20852 => 38451, 20853 => 27687, 20854 => 20208, + 20855 => 30162, 20856 => 20859, 20857 => 26679, 20858 => 28478, 20859 => 36992, + 20860 => 33136, 20861 => 22934, 20862 => 29814, 21025 => 25671, 21026 => 23591, + 21027 => 36965, 21028 => 31377, 21029 => 35875, 21030 => 23002, 21031 => 21676, + 21032 => 33280, 21033 => 33647, 21034 => 35201, 21035 => 32768, 21036 => 26928, + 21037 => 22094, 21038 => 32822, 21039 => 29239, 21040 => 37326, 21041 => 20918, + 21042 => 20063, 21043 => 39029, 21044 => 25494, 21045 => 19994, 21046 => 21494, + 21047 => 26355, 21048 => 33099, 21049 => 22812, 21050 => 28082, 21051 => 19968, + 21052 => 22777, 21053 => 21307, 21054 => 25558, 21055 => 38129, 21056 => 20381, + 21057 => 20234, 21058 => 34915, 21059 => 39056, 21060 => 22839, 21061 => 36951, + 21062 => 31227, 21063 => 20202, 21064 => 33008, 21065 => 30097, 21066 => 27778, + 21067 => 23452, 21068 => 23016, 21069 => 24413, 21070 => 26885, 21071 => 34433, + 21072 => 20506, 21073 => 24050, 21074 => 20057, 21075 => 30691, 21076 => 20197, + 21077 => 33402, 21078 => 25233, 21079 => 26131, 21080 => 37009, 21081 => 23673, + 21082 => 20159, 21083 => 24441, 21084 => 33222, 21085 => 36920, 21086 => 32900, + 21087 => 30123, 21088 => 20134, 21089 => 35028, 21090 => 24847, 21091 => 27589, + 21092 => 24518, 21093 => 20041, 21094 => 30410, 21095 => 28322, 21096 => 35811, + 21097 => 35758, 21098 => 35850, 21099 => 35793, 21100 => 24322, 21101 => 32764, + 21102 => 32716, 21103 => 32462, 21104 => 33589, 21105 => 33643, 21106 => 22240, + 21107 => 27575, 21108 => 38899, 21109 => 38452, 21110 => 23035, 21111 => 21535, + 21112 => 38134, 21113 => 28139, 21114 => 23493, 21115 => 39278, 21116 => 23609, + 21117 => 24341, 21118 => 38544, 21281 => 21360, 21282 => 33521, 21283 => 27185, + 21284 => 23156, 21285 => 40560, 21286 => 24212, 21287 => 32552, 21288 => 33721, + 21289 => 33828, 21290 => 33829, 21291 => 33639, 21292 => 34631, 21293 => 36814, + 21294 => 36194, 21295 => 30408, 21296 => 24433, 21297 => 39062, 21298 => 30828, + 21299 => 26144, 21300 => 21727, 21301 => 25317, 21302 => 20323, 21303 => 33219, + 21304 => 30152, 21305 => 24248, 21306 => 38605, 21307 => 36362, 21308 => 34553, + 21309 => 21647, 21310 => 27891, 21311 => 28044, 21312 => 27704, 21313 => 24703, + 21314 => 21191, 21315 => 29992, 21316 => 24189, 21317 => 20248, 21318 => 24736, + 21319 => 24551, 21320 => 23588, 21321 => 30001, 21322 => 37038, 21323 => 38080, + 21324 => 29369, 21325 => 27833, 21326 => 28216, 21327 => 37193, 21328 => 26377, + 21329 => 21451, 21330 => 21491, 21331 => 20305, 21332 => 37321, 21333 => 35825, + 21334 => 21448, 21335 => 24188, 21336 => 36802, 21337 => 28132, 21338 => 20110, + 21339 => 30402, 21340 => 27014, 21341 => 34398, 21342 => 24858, 21343 => 33286, + 21344 => 20313, 21345 => 20446, 21346 => 36926, 21347 => 40060, 21348 => 24841, + 21349 => 28189, 21350 => 28180, 21351 => 38533, 21352 => 20104, 21353 => 23089, + 21354 => 38632, 21355 => 19982, 21356 => 23679, 21357 => 31161, 21358 => 23431, + 21359 => 35821, 21360 => 32701, 21361 => 29577, 21362 => 22495, 21363 => 33419, + 21364 => 37057, 21365 => 21505, 21366 => 36935, 21367 => 21947, 21368 => 23786, + 21369 => 24481, 21370 => 24840, 21371 => 27442, 21372 => 29425, 21373 => 32946, + 21374 => 35465, 21537 => 28020, 21538 => 23507, 21539 => 35029, 21540 => 39044, + 21541 => 35947, 21542 => 39533, 21543 => 40499, 21544 => 28170, 21545 => 20900, + 21546 => 20803, 21547 => 22435, 21548 => 34945, 21549 => 21407, 21550 => 25588, + 21551 => 36757, 21552 => 22253, 21553 => 21592, 21554 => 22278, 21555 => 29503, + 21556 => 28304, 21557 => 32536, 21558 => 36828, 21559 => 33489, 21560 => 24895, + 21561 => 24616, 21562 => 38498, 21563 => 26352, 21564 => 32422, 21565 => 36234, + 21566 => 36291, 21567 => 38053, 21568 => 23731, 21569 => 31908, 21570 => 26376, + 21571 => 24742, 21572 => 38405, 21573 => 32792, 21574 => 20113, 21575 => 37095, + 21576 => 21248, 21577 => 38504, 21578 => 20801, 21579 => 36816, 21580 => 34164, + 21581 => 37213, 21582 => 26197, 21583 => 38901, 21584 => 23381, 21585 => 21277, + 21586 => 30776, 21587 => 26434, 21588 => 26685, 21589 => 21705, 21590 => 28798, + 21591 => 23472, 21592 => 36733, 21593 => 20877, 21594 => 22312, 21595 => 21681, + 21596 => 25874, 21597 => 26242, 21598 => 36190, 21599 => 36163, 21600 => 33039, + 21601 => 33900, 21602 => 36973, 21603 => 31967, 21604 => 20991, 21605 => 34299, + 21606 => 26531, 21607 => 26089, 21608 => 28577, 21609 => 34468, 21610 => 36481, + 21611 => 22122, 21612 => 36896, 21613 => 30338, 21614 => 28790, 21615 => 29157, + 21616 => 36131, 21617 => 25321, 21618 => 21017, 21619 => 27901, 21620 => 36156, + 21621 => 24590, 21622 => 22686, 21623 => 24974, 21624 => 26366, 21625 => 36192, + 21626 => 25166, 21627 => 21939, 21628 => 28195, 21629 => 26413, 21630 => 36711, + 21793 => 38113, 21794 => 38392, 21795 => 30504, 21796 => 26629, 21797 => 27048, + 21798 => 21643, 21799 => 20045, 21800 => 28856, 21801 => 35784, 21802 => 25688, + 21803 => 25995, 21804 => 23429, 21805 => 31364, 21806 => 20538, 21807 => 23528, + 21808 => 30651, 21809 => 27617, 21810 => 35449, 21811 => 31896, 21812 => 27838, + 21813 => 30415, 21814 => 26025, 21815 => 36759, 21816 => 23853, 21817 => 23637, + 21818 => 34360, 21819 => 26632, 21820 => 21344, 21821 => 25112, 21822 => 31449, + 21823 => 28251, 21824 => 32509, 21825 => 27167, 21826 => 31456, 21827 => 24432, + 21828 => 28467, 21829 => 24352, 21830 => 25484, 21831 => 28072, 21832 => 26454, + 21833 => 19976, 21834 => 24080, 21835 => 36134, 21836 => 20183, 21837 => 32960, + 21838 => 30260, 21839 => 38556, 21840 => 25307, 21841 => 26157, 21842 => 25214, + 21843 => 27836, 21844 => 36213, 21845 => 29031, 21846 => 32617, 21847 => 20806, + 21848 => 32903, 21849 => 21484, 21850 => 36974, 21851 => 25240, 21852 => 21746, + 21853 => 34544, 21854 => 36761, 21855 => 32773, 21856 => 38167, 21857 => 34071, + 21858 => 36825, 21859 => 27993, 21860 => 29645, 21861 => 26015, 21862 => 30495, + 21863 => 29956, 21864 => 30759, 21865 => 33275, 21866 => 36126, 21867 => 38024, + 21868 => 20390, 21869 => 26517, 21870 => 30137, 21871 => 35786, 21872 => 38663, + 21873 => 25391, 21874 => 38215, 21875 => 38453, 21876 => 33976, 21877 => 25379, + 21878 => 30529, 21879 => 24449, 21880 => 29424, 21881 => 20105, 21882 => 24596, + 21883 => 25972, 21884 => 25327, 21885 => 27491, 21886 => 25919, 22049 => 24103, + 22050 => 30151, 22051 => 37073, 22052 => 35777, 22053 => 33437, 22054 => 26525, + 22055 => 25903, 22056 => 21553, 22057 => 34584, 22058 => 30693, 22059 => 32930, + 22060 => 33026, 22061 => 27713, 22062 => 20043, 22063 => 32455, 22064 => 32844, + 22065 => 30452, 22066 => 26893, 22067 => 27542, 22068 => 25191, 22069 => 20540, + 22070 => 20356, 22071 => 22336, 22072 => 25351, 22073 => 27490, 22074 => 36286, + 22075 => 21482, 22076 => 26088, 22077 => 32440, 22078 => 24535, 22079 => 25370, + 22080 => 25527, 22081 => 33267, 22082 => 33268, 22083 => 32622, 22084 => 24092, + 22085 => 23769, 22086 => 21046, 22087 => 26234, 22088 => 31209, 22089 => 31258, + 22090 => 36136, 22091 => 28825, 22092 => 30164, 22093 => 28382, 22094 => 27835, + 22095 => 31378, 22096 => 20013, 22097 => 30405, 22098 => 24544, 22099 => 38047, + 22100 => 34935, 22101 => 32456, 22102 => 31181, 22103 => 32959, 22104 => 37325, + 22105 => 20210, 22106 => 20247, 22107 => 33311, 22108 => 21608, 22109 => 24030, + 22110 => 27954, 22111 => 35788, 22112 => 31909, 22113 => 36724, 22114 => 32920, + 22115 => 24090, 22116 => 21650, 22117 => 30385, 22118 => 23449, 22119 => 26172, + 22120 => 39588, 22121 => 29664, 22122 => 26666, 22123 => 34523, 22124 => 26417, + 22125 => 29482, 22126 => 35832, 22127 => 35803, 22128 => 36880, 22129 => 31481, + 22130 => 28891, 22131 => 29038, 22132 => 25284, 22133 => 30633, 22134 => 22065, + 22135 => 20027, 22136 => 33879, 22137 => 26609, 22138 => 21161, 22139 => 34496, + 22140 => 36142, 22141 => 38136, 22142 => 31569, 22305 => 20303, 22306 => 27880, + 22307 => 31069, 22308 => 39547, 22309 => 25235, 22310 => 29226, 22311 => 25341, + 22312 => 19987, 22313 => 30742, 22314 => 36716, 22315 => 25776, 22316 => 36186, + 22317 => 31686, 22318 => 26729, 22319 => 24196, 22320 => 35013, 22321 => 22918, + 22322 => 25758, 22323 => 22766, 22324 => 29366, 22325 => 26894, 22326 => 38181, + 22327 => 36861, 22328 => 36184, 22329 => 22368, 22330 => 32512, 22331 => 35846, + 22332 => 20934, 22333 => 25417, 22334 => 25305, 22335 => 21331, 22336 => 26700, + 22337 => 29730, 22338 => 33537, 22339 => 37196, 22340 => 21828, 22341 => 30528, + 22342 => 28796, 22343 => 27978, 22344 => 20857, 22345 => 21672, 22346 => 36164, + 22347 => 23039, 22348 => 28363, 22349 => 28100, 22350 => 23388, 22351 => 32043, + 22352 => 20180, 22353 => 31869, 22354 => 28371, 22355 => 23376, 22356 => 33258, + 22357 => 28173, 22358 => 23383, 22359 => 39683, 22360 => 26837, 22361 => 36394, + 22362 => 23447, 22363 => 32508, 22364 => 24635, 22365 => 32437, 22366 => 37049, + 22367 => 36208, 22368 => 22863, 22369 => 25549, 22370 => 31199, 22371 => 36275, + 22372 => 21330, 22373 => 26063, 22374 => 31062, 22375 => 35781, 22376 => 38459, + 22377 => 32452, 22378 => 38075, 22379 => 32386, 22380 => 22068, 22381 => 37257, + 22382 => 26368, 22383 => 32618, 22384 => 23562, 22385 => 36981, 22386 => 26152, + 22387 => 24038, 22388 => 20304, 22389 => 26590, 22390 => 20570, 22391 => 20316, + 22392 => 22352, 22393 => 24231, 22561 => 20109, 22562 => 19980, 22563 => 20800, + 22564 => 19984, 22565 => 24319, 22566 => 21317, 22567 => 19989, 22568 => 20120, + 22569 => 19998, 22570 => 39730, 22571 => 23404, 22572 => 22121, 22573 => 20008, + 22574 => 31162, 22575 => 20031, 22576 => 21269, 22577 => 20039, 22578 => 22829, + 22579 => 29243, 22580 => 21358, 22581 => 27664, 22582 => 22239, 22583 => 32996, + 22584 => 39319, 22585 => 27603, 22586 => 30590, 22587 => 40727, 22588 => 20022, + 22589 => 20127, 22590 => 40720, 22591 => 20060, 22592 => 20073, 22593 => 20115, + 22594 => 33416, 22595 => 23387, 22596 => 21868, 22597 => 22031, 22598 => 20164, + 22599 => 21389, 22600 => 21405, 22601 => 21411, 22602 => 21413, 22603 => 21422, + 22604 => 38757, 22605 => 36189, 22606 => 21274, 22607 => 21493, 22608 => 21286, + 22609 => 21294, 22610 => 21310, 22611 => 36188, 22612 => 21350, 22613 => 21347, + 22614 => 20994, 22615 => 21000, 22616 => 21006, 22617 => 21037, 22618 => 21043, + 22619 => 21055, 22620 => 21056, 22621 => 21068, 22622 => 21086, 22623 => 21089, + 22624 => 21084, 22625 => 33967, 22626 => 21117, 22627 => 21122, 22628 => 21121, + 22629 => 21136, 22630 => 21139, 22631 => 20866, 22632 => 32596, 22633 => 20155, + 22634 => 20163, 22635 => 20169, 22636 => 20162, 22637 => 20200, 22638 => 20193, + 22639 => 20203, 22640 => 20190, 22641 => 20251, 22642 => 20211, 22643 => 20258, + 22644 => 20324, 22645 => 20213, 22646 => 20261, 22647 => 20263, 22648 => 20233, + 22649 => 20267, 22650 => 20318, 22651 => 20327, 22652 => 25912, 22653 => 20314, + 22654 => 20317, 22817 => 20319, 22818 => 20311, 22819 => 20274, 22820 => 20285, + 22821 => 20342, 22822 => 20340, 22823 => 20369, 22824 => 20361, 22825 => 20355, + 22826 => 20367, 22827 => 20350, 22828 => 20347, 22829 => 20394, 22830 => 20348, + 22831 => 20396, 22832 => 20372, 22833 => 20454, 22834 => 20456, 22835 => 20458, + 22836 => 20421, 22837 => 20442, 22838 => 20451, 22839 => 20444, 22840 => 20433, + 22841 => 20447, 22842 => 20472, 22843 => 20521, 22844 => 20556, 22845 => 20467, + 22846 => 20524, 22847 => 20495, 22848 => 20526, 22849 => 20525, 22850 => 20478, + 22851 => 20508, 22852 => 20492, 22853 => 20517, 22854 => 20520, 22855 => 20606, + 22856 => 20547, 22857 => 20565, 22858 => 20552, 22859 => 20558, 22860 => 20588, + 22861 => 20603, 22862 => 20645, 22863 => 20647, 22864 => 20649, 22865 => 20666, + 22866 => 20694, 22867 => 20742, 22868 => 20717, 22869 => 20716, 22870 => 20710, + 22871 => 20718, 22872 => 20743, 22873 => 20747, 22874 => 20189, 22875 => 27709, + 22876 => 20312, 22877 => 20325, 22878 => 20430, 22879 => 40864, 22880 => 27718, + 22881 => 31860, 22882 => 20846, 22883 => 24061, 22884 => 40649, 22885 => 39320, + 22886 => 20865, 22887 => 22804, 22888 => 21241, 22889 => 21261, 22890 => 35335, + 22891 => 21264, 22892 => 20971, 22893 => 22809, 22894 => 20821, 22895 => 20128, + 22896 => 20822, 22897 => 20147, 22898 => 34926, 22899 => 34980, 22900 => 20149, + 22901 => 33044, 22902 => 35026, 22903 => 31104, 22904 => 23348, 22905 => 34819, + 22906 => 32696, 22907 => 20907, 22908 => 20913, 22909 => 20925, 22910 => 20924, + 23073 => 20935, 23074 => 20886, 23075 => 20898, 23076 => 20901, 23077 => 35744, + 23078 => 35750, 23079 => 35751, 23080 => 35754, 23081 => 35764, 23082 => 35765, + 23083 => 35767, 23084 => 35778, 23085 => 35779, 23086 => 35787, 23087 => 35791, + 23088 => 35790, 23089 => 35794, 23090 => 35795, 23091 => 35796, 23092 => 35798, + 23093 => 35800, 23094 => 35801, 23095 => 35804, 23096 => 35807, 23097 => 35808, + 23098 => 35812, 23099 => 35816, 23100 => 35817, 23101 => 35822, 23102 => 35824, + 23103 => 35827, 23104 => 35830, 23105 => 35833, 23106 => 35836, 23107 => 35839, + 23108 => 35840, 23109 => 35842, 23110 => 35844, 23111 => 35847, 23112 => 35852, + 23113 => 35855, 23114 => 35857, 23115 => 35858, 23116 => 35860, 23117 => 35861, + 23118 => 35862, 23119 => 35865, 23120 => 35867, 23121 => 35864, 23122 => 35869, + 23123 => 35871, 23124 => 35872, 23125 => 35873, 23126 => 35877, 23127 => 35879, + 23128 => 35882, 23129 => 35883, 23130 => 35886, 23131 => 35887, 23132 => 35890, + 23133 => 35891, 23134 => 35893, 23135 => 35894, 23136 => 21353, 23137 => 21370, + 23138 => 38429, 23139 => 38434, 23140 => 38433, 23141 => 38449, 23142 => 38442, + 23143 => 38461, 23144 => 38460, 23145 => 38466, 23146 => 38473, 23147 => 38484, + 23148 => 38495, 23149 => 38503, 23150 => 38508, 23151 => 38514, 23152 => 38516, + 23153 => 38536, 23154 => 38541, 23155 => 38551, 23156 => 38576, 23157 => 37015, + 23158 => 37019, 23159 => 37021, 23160 => 37017, 23161 => 37036, 23162 => 37025, + 23163 => 37044, 23164 => 37043, 23165 => 37046, 23166 => 37050, 23329 => 37048, + 23330 => 37040, 23331 => 37071, 23332 => 37061, 23333 => 37054, 23334 => 37072, + 23335 => 37060, 23336 => 37063, 23337 => 37075, 23338 => 37094, 23339 => 37090, + 23340 => 37084, 23341 => 37079, 23342 => 37083, 23343 => 37099, 23344 => 37103, + 23345 => 37118, 23346 => 37124, 23347 => 37154, 23348 => 37150, 23349 => 37155, + 23350 => 37169, 23351 => 37167, 23352 => 37177, 23353 => 37187, 23354 => 37190, + 23355 => 21005, 23356 => 22850, 23357 => 21154, 23358 => 21164, 23359 => 21165, + 23360 => 21182, 23361 => 21759, 23362 => 21200, 23363 => 21206, 23364 => 21232, + 23365 => 21471, 23366 => 29166, 23367 => 30669, 23368 => 24308, 23369 => 20981, + 23370 => 20988, 23371 => 39727, 23372 => 21430, 23373 => 24321, 23374 => 30042, + 23375 => 24047, 23376 => 22348, 23377 => 22441, 23378 => 22433, 23379 => 22654, + 23380 => 22716, 23381 => 22725, 23382 => 22737, 23383 => 22313, 23384 => 22316, + 23385 => 22314, 23386 => 22323, 23387 => 22329, 23388 => 22318, 23389 => 22319, + 23390 => 22364, 23391 => 22331, 23392 => 22338, 23393 => 22377, 23394 => 22405, + 23395 => 22379, 23396 => 22406, 23397 => 22396, 23398 => 22395, 23399 => 22376, + 23400 => 22381, 23401 => 22390, 23402 => 22387, 23403 => 22445, 23404 => 22436, + 23405 => 22412, 23406 => 22450, 23407 => 22479, 23408 => 22439, 23409 => 22452, + 23410 => 22419, 23411 => 22432, 23412 => 22485, 23413 => 22488, 23414 => 22490, + 23415 => 22489, 23416 => 22482, 23417 => 22456, 23418 => 22516, 23419 => 22511, + 23420 => 22520, 23421 => 22500, 23422 => 22493, 23585 => 22539, 23586 => 22541, + 23587 => 22525, 23588 => 22509, 23589 => 22528, 23590 => 22558, 23591 => 22553, + 23592 => 22596, 23593 => 22560, 23594 => 22629, 23595 => 22636, 23596 => 22657, + 23597 => 22665, 23598 => 22682, 23599 => 22656, 23600 => 39336, 23601 => 40729, + 23602 => 25087, 23603 => 33401, 23604 => 33405, 23605 => 33407, 23606 => 33423, + 23607 => 33418, 23608 => 33448, 23609 => 33412, 23610 => 33422, 23611 => 33425, + 23612 => 33431, 23613 => 33433, 23614 => 33451, 23615 => 33464, 23616 => 33470, + 23617 => 33456, 23618 => 33480, 23619 => 33482, 23620 => 33507, 23621 => 33432, + 23622 => 33463, 23623 => 33454, 23624 => 33483, 23625 => 33484, 23626 => 33473, + 23627 => 33449, 23628 => 33460, 23629 => 33441, 23630 => 33450, 23631 => 33439, + 23632 => 33476, 23633 => 33486, 23634 => 33444, 23635 => 33505, 23636 => 33545, + 23637 => 33527, 23638 => 33508, 23639 => 33551, 23640 => 33543, 23641 => 33500, + 23642 => 33524, 23643 => 33490, 23644 => 33496, 23645 => 33548, 23646 => 33531, + 23647 => 33491, 23648 => 33553, 23649 => 33562, 23650 => 33542, 23651 => 33556, + 23652 => 33557, 23653 => 33504, 23654 => 33493, 23655 => 33564, 23656 => 33617, + 23657 => 33627, 23658 => 33628, 23659 => 33544, 23660 => 33682, 23661 => 33596, + 23662 => 33588, 23663 => 33585, 23664 => 33691, 23665 => 33630, 23666 => 33583, + 23667 => 33615, 23668 => 33607, 23669 => 33603, 23670 => 33631, 23671 => 33600, + 23672 => 33559, 23673 => 33632, 23674 => 33581, 23675 => 33594, 23676 => 33587, + 23677 => 33638, 23678 => 33637, 23841 => 33640, 23842 => 33563, 23843 => 33641, + 23844 => 33644, 23845 => 33642, 23846 => 33645, 23847 => 33646, 23848 => 33712, + 23849 => 33656, 23850 => 33715, 23851 => 33716, 23852 => 33696, 23853 => 33706, + 23854 => 33683, 23855 => 33692, 23856 => 33669, 23857 => 33660, 23858 => 33718, + 23859 => 33705, 23860 => 33661, 23861 => 33720, 23862 => 33659, 23863 => 33688, + 23864 => 33694, 23865 => 33704, 23866 => 33722, 23867 => 33724, 23868 => 33729, + 23869 => 33793, 23870 => 33765, 23871 => 33752, 23872 => 22535, 23873 => 33816, + 23874 => 33803, 23875 => 33757, 23876 => 33789, 23877 => 33750, 23878 => 33820, + 23879 => 33848, 23880 => 33809, 23881 => 33798, 23882 => 33748, 23883 => 33759, + 23884 => 33807, 23885 => 33795, 23886 => 33784, 23887 => 33785, 23888 => 33770, + 23889 => 33733, 23890 => 33728, 23891 => 33830, 23892 => 33776, 23893 => 33761, + 23894 => 33884, 23895 => 33873, 23896 => 33882, 23897 => 33881, 23898 => 33907, + 23899 => 33927, 23900 => 33928, 23901 => 33914, 23902 => 33929, 23903 => 33912, + 23904 => 33852, 23905 => 33862, 23906 => 33897, 23907 => 33910, 23908 => 33932, + 23909 => 33934, 23910 => 33841, 23911 => 33901, 23912 => 33985, 23913 => 33997, + 23914 => 34000, 23915 => 34022, 23916 => 33981, 23917 => 34003, 23918 => 33994, + 23919 => 33983, 23920 => 33978, 23921 => 34016, 23922 => 33953, 23923 => 33977, + 23924 => 33972, 23925 => 33943, 23926 => 34021, 23927 => 34019, 23928 => 34060, + 23929 => 29965, 23930 => 34104, 23931 => 34032, 23932 => 34105, 23933 => 34079, + 23934 => 34106, 24097 => 34134, 24098 => 34107, 24099 => 34047, 24100 => 34044, + 24101 => 34137, 24102 => 34120, 24103 => 34152, 24104 => 34148, 24105 => 34142, + 24106 => 34170, 24107 => 30626, 24108 => 34115, 24109 => 34162, 24110 => 34171, + 24111 => 34212, 24112 => 34216, 24113 => 34183, 24114 => 34191, 24115 => 34169, + 24116 => 34222, 24117 => 34204, 24118 => 34181, 24119 => 34233, 24120 => 34231, + 24121 => 34224, 24122 => 34259, 24123 => 34241, 24124 => 34268, 24125 => 34303, + 24126 => 34343, 24127 => 34309, 24128 => 34345, 24129 => 34326, 24130 => 34364, + 24131 => 24318, 24132 => 24328, 24133 => 22844, 24134 => 22849, 24135 => 32823, + 24136 => 22869, 24137 => 22874, 24138 => 22872, 24139 => 21263, 24140 => 23586, + 24141 => 23589, 24142 => 23596, 24143 => 23604, 24144 => 25164, 24145 => 25194, + 24146 => 25247, 24147 => 25275, 24148 => 25290, 24149 => 25306, 24150 => 25303, + 24151 => 25326, 24152 => 25378, 24153 => 25334, 24154 => 25401, 24155 => 25419, + 24156 => 25411, 24157 => 25517, 24158 => 25590, 24159 => 25457, 24160 => 25466, + 24161 => 25486, 24162 => 25524, 24163 => 25453, 24164 => 25516, 24165 => 25482, + 24166 => 25449, 24167 => 25518, 24168 => 25532, 24169 => 25586, 24170 => 25592, + 24171 => 25568, 24172 => 25599, 24173 => 25540, 24174 => 25566, 24175 => 25550, + 24176 => 25682, 24177 => 25542, 24178 => 25534, 24179 => 25669, 24180 => 25665, + 24181 => 25611, 24182 => 25627, 24183 => 25632, 24184 => 25612, 24185 => 25638, + 24186 => 25633, 24187 => 25694, 24188 => 25732, 24189 => 25709, 24190 => 25750, + 24353 => 25722, 24354 => 25783, 24355 => 25784, 24356 => 25753, 24357 => 25786, + 24358 => 25792, 24359 => 25808, 24360 => 25815, 24361 => 25828, 24362 => 25826, + 24363 => 25865, 24364 => 25893, 24365 => 25902, 24366 => 24331, 24367 => 24530, + 24368 => 29977, 24369 => 24337, 24370 => 21343, 24371 => 21489, 24372 => 21501, + 24373 => 21481, 24374 => 21480, 24375 => 21499, 24376 => 21522, 24377 => 21526, + 24378 => 21510, 24379 => 21579, 24380 => 21586, 24381 => 21587, 24382 => 21588, + 24383 => 21590, 24384 => 21571, 24385 => 21537, 24386 => 21591, 24387 => 21593, + 24388 => 21539, 24389 => 21554, 24390 => 21634, 24391 => 21652, 24392 => 21623, + 24393 => 21617, 24394 => 21604, 24395 => 21658, 24396 => 21659, 24397 => 21636, + 24398 => 21622, 24399 => 21606, 24400 => 21661, 24401 => 21712, 24402 => 21677, + 24403 => 21698, 24404 => 21684, 24405 => 21714, 24406 => 21671, 24407 => 21670, + 24408 => 21715, 24409 => 21716, 24410 => 21618, 24411 => 21667, 24412 => 21717, + 24413 => 21691, 24414 => 21695, 24415 => 21708, 24416 => 21721, 24417 => 21722, + 24418 => 21724, 24419 => 21673, 24420 => 21674, 24421 => 21668, 24422 => 21725, + 24423 => 21711, 24424 => 21726, 24425 => 21787, 24426 => 21735, 24427 => 21792, + 24428 => 21757, 24429 => 21780, 24430 => 21747, 24431 => 21794, 24432 => 21795, + 24433 => 21775, 24434 => 21777, 24435 => 21799, 24436 => 21802, 24437 => 21863, + 24438 => 21903, 24439 => 21941, 24440 => 21833, 24441 => 21869, 24442 => 21825, + 24443 => 21845, 24444 => 21823, 24445 => 21840, 24446 => 21820, 24609 => 21815, + 24610 => 21846, 24611 => 21877, 24612 => 21878, 24613 => 21879, 24614 => 21811, + 24615 => 21808, 24616 => 21852, 24617 => 21899, 24618 => 21970, 24619 => 21891, + 24620 => 21937, 24621 => 21945, 24622 => 21896, 24623 => 21889, 24624 => 21919, + 24625 => 21886, 24626 => 21974, 24627 => 21905, 24628 => 21883, 24629 => 21983, + 24630 => 21949, 24631 => 21950, 24632 => 21908, 24633 => 21913, 24634 => 21994, + 24635 => 22007, 24636 => 21961, 24637 => 22047, 24638 => 21969, 24639 => 21995, + 24640 => 21996, 24641 => 21972, 24642 => 21990, 24643 => 21981, 24644 => 21956, + 24645 => 21999, 24646 => 21989, 24647 => 22002, 24648 => 22003, 24649 => 21964, + 24650 => 21965, 24651 => 21992, 24652 => 22005, 24653 => 21988, 24654 => 36756, + 24655 => 22046, 24656 => 22024, 24657 => 22028, 24658 => 22017, 24659 => 22052, + 24660 => 22051, 24661 => 22014, 24662 => 22016, 24663 => 22055, 24664 => 22061, + 24665 => 22104, 24666 => 22073, 24667 => 22103, 24668 => 22060, 24669 => 22093, + 24670 => 22114, 24671 => 22105, 24672 => 22108, 24673 => 22092, 24674 => 22100, + 24675 => 22150, 24676 => 22116, 24677 => 22129, 24678 => 22123, 24679 => 22139, + 24680 => 22140, 24681 => 22149, 24682 => 22163, 24683 => 22191, 24684 => 22228, + 24685 => 22231, 24686 => 22237, 24687 => 22241, 24688 => 22261, 24689 => 22251, + 24690 => 22265, 24691 => 22271, 24692 => 22276, 24693 => 22282, 24694 => 22281, + 24695 => 22300, 24696 => 24079, 24697 => 24089, 24698 => 24084, 24699 => 24081, + 24700 => 24113, 24701 => 24123, 24702 => 24124, 24865 => 24119, 24866 => 24132, + 24867 => 24148, 24868 => 24155, 24869 => 24158, 24870 => 24161, 24871 => 23692, + 24872 => 23674, 24873 => 23693, 24874 => 23696, 24875 => 23702, 24876 => 23688, + 24877 => 23704, 24878 => 23705, 24879 => 23697, 24880 => 23706, 24881 => 23708, + 24882 => 23733, 24883 => 23714, 24884 => 23741, 24885 => 23724, 24886 => 23723, + 24887 => 23729, 24888 => 23715, 24889 => 23745, 24890 => 23735, 24891 => 23748, + 24892 => 23762, 24893 => 23780, 24894 => 23755, 24895 => 23781, 24896 => 23810, + 24897 => 23811, 24898 => 23847, 24899 => 23846, 24900 => 23854, 24901 => 23844, + 24902 => 23838, 24903 => 23814, 24904 => 23835, 24905 => 23896, 24906 => 23870, + 24907 => 23860, 24908 => 23869, 24909 => 23916, 24910 => 23899, 24911 => 23919, + 24912 => 23901, 24913 => 23915, 24914 => 23883, 24915 => 23882, 24916 => 23913, + 24917 => 23924, 24918 => 23938, 24919 => 23961, 24920 => 23965, 24921 => 35955, + 24922 => 23991, 24923 => 24005, 24924 => 24435, 24925 => 24439, 24926 => 24450, + 24927 => 24455, 24928 => 24457, 24929 => 24460, 24930 => 24469, 24931 => 24473, + 24932 => 24476, 24933 => 24488, 24934 => 24493, 24935 => 24501, 24936 => 24508, + 24937 => 34914, 24938 => 24417, 24939 => 29357, 24940 => 29360, 24941 => 29364, + 24942 => 29367, 24943 => 29368, 24944 => 29379, 24945 => 29377, 24946 => 29390, + 24947 => 29389, 24948 => 29394, 24949 => 29416, 24950 => 29423, 24951 => 29417, + 24952 => 29426, 24953 => 29428, 24954 => 29431, 24955 => 29441, 24956 => 29427, + 24957 => 29443, 24958 => 29434, 25121 => 29435, 25122 => 29463, 25123 => 29459, + 25124 => 29473, 25125 => 29450, 25126 => 29470, 25127 => 29469, 25128 => 29461, + 25129 => 29474, 25130 => 29497, 25131 => 29477, 25132 => 29484, 25133 => 29496, + 25134 => 29489, 25135 => 29520, 25136 => 29517, 25137 => 29527, 25138 => 29536, + 25139 => 29548, 25140 => 29551, 25141 => 29566, 25142 => 33307, 25143 => 22821, + 25144 => 39143, 25145 => 22820, 25146 => 22786, 25147 => 39267, 25148 => 39271, + 25149 => 39272, 25150 => 39273, 25151 => 39274, 25152 => 39275, 25153 => 39276, + 25154 => 39284, 25155 => 39287, 25156 => 39293, 25157 => 39296, 25158 => 39300, + 25159 => 39303, 25160 => 39306, 25161 => 39309, 25162 => 39312, 25163 => 39313, + 25164 => 39315, 25165 => 39316, 25166 => 39317, 25167 => 24192, 25168 => 24209, + 25169 => 24203, 25170 => 24214, 25171 => 24229, 25172 => 24224, 25173 => 24249, + 25174 => 24245, 25175 => 24254, 25176 => 24243, 25177 => 36179, 25178 => 24274, + 25179 => 24273, 25180 => 24283, 25181 => 24296, 25182 => 24298, 25183 => 33210, + 25184 => 24516, 25185 => 24521, 25186 => 24534, 25187 => 24527, 25188 => 24579, + 25189 => 24558, 25190 => 24580, 25191 => 24545, 25192 => 24548, 25193 => 24574, + 25194 => 24581, 25195 => 24582, 25196 => 24554, 25197 => 24557, 25198 => 24568, + 25199 => 24601, 25200 => 24629, 25201 => 24614, 25202 => 24603, 25203 => 24591, + 25204 => 24589, 25205 => 24617, 25206 => 24619, 25207 => 24586, 25208 => 24639, + 25209 => 24609, 25210 => 24696, 25211 => 24697, 25212 => 24699, 25213 => 24698, + 25214 => 24642, 25377 => 24682, 25378 => 24701, 25379 => 24726, 25380 => 24730, + 25381 => 24749, 25382 => 24733, 25383 => 24707, 25384 => 24722, 25385 => 24716, + 25386 => 24731, 25387 => 24812, 25388 => 24763, 25389 => 24753, 25390 => 24797, + 25391 => 24792, 25392 => 24774, 25393 => 24794, 25394 => 24756, 25395 => 24864, + 25396 => 24870, 25397 => 24853, 25398 => 24867, 25399 => 24820, 25400 => 24832, + 25401 => 24846, 25402 => 24875, 25403 => 24906, 25404 => 24949, 25405 => 25004, + 25406 => 24980, 25407 => 24999, 25408 => 25015, 25409 => 25044, 25410 => 25077, + 25411 => 24541, 25412 => 38579, 25413 => 38377, 25414 => 38379, 25415 => 38385, + 25416 => 38387, 25417 => 38389, 25418 => 38390, 25419 => 38396, 25420 => 38398, + 25421 => 38403, 25422 => 38404, 25423 => 38406, 25424 => 38408, 25425 => 38410, + 25426 => 38411, 25427 => 38412, 25428 => 38413, 25429 => 38415, 25430 => 38418, + 25431 => 38421, 25432 => 38422, 25433 => 38423, 25434 => 38425, 25435 => 38426, + 25436 => 20012, 25437 => 29247, 25438 => 25109, 25439 => 27701, 25440 => 27732, + 25441 => 27740, 25442 => 27722, 25443 => 27811, 25444 => 27781, 25445 => 27792, + 25446 => 27796, 25447 => 27788, 25448 => 27752, 25449 => 27753, 25450 => 27764, + 25451 => 27766, 25452 => 27782, 25453 => 27817, 25454 => 27856, 25455 => 27860, + 25456 => 27821, 25457 => 27895, 25458 => 27896, 25459 => 27889, 25460 => 27863, + 25461 => 27826, 25462 => 27872, 25463 => 27862, 25464 => 27898, 25465 => 27883, + 25466 => 27886, 25467 => 27825, 25468 => 27859, 25469 => 27887, 25470 => 27902, + 25633 => 27961, 25634 => 27943, 25635 => 27916, 25636 => 27971, 25637 => 27976, + 25638 => 27911, 25639 => 27908, 25640 => 27929, 25641 => 27918, 25642 => 27947, + 25643 => 27981, 25644 => 27950, 25645 => 27957, 25646 => 27930, 25647 => 27983, + 25648 => 27986, 25649 => 27988, 25650 => 27955, 25651 => 28049, 25652 => 28015, + 25653 => 28062, 25654 => 28064, 25655 => 27998, 25656 => 28051, 25657 => 28052, + 25658 => 27996, 25659 => 28000, 25660 => 28028, 25661 => 28003, 25662 => 28186, + 25663 => 28103, 25664 => 28101, 25665 => 28126, 25666 => 28174, 25667 => 28095, + 25668 => 28128, 25669 => 28177, 25670 => 28134, 25671 => 28125, 25672 => 28121, + 25673 => 28182, 25674 => 28075, 25675 => 28172, 25676 => 28078, 25677 => 28203, + 25678 => 28270, 25679 => 28238, 25680 => 28267, 25681 => 28338, 25682 => 28255, + 25683 => 28294, 25684 => 28243, 25685 => 28244, 25686 => 28210, 25687 => 28197, + 25688 => 28228, 25689 => 28383, 25690 => 28337, 25691 => 28312, 25692 => 28384, + 25693 => 28461, 25694 => 28386, 25695 => 28325, 25696 => 28327, 25697 => 28349, + 25698 => 28347, 25699 => 28343, 25700 => 28375, 25701 => 28340, 25702 => 28367, + 25703 => 28303, 25704 => 28354, 25705 => 28319, 25706 => 28514, 25707 => 28486, + 25708 => 28487, 25709 => 28452, 25710 => 28437, 25711 => 28409, 25712 => 28463, + 25713 => 28470, 25714 => 28491, 25715 => 28532, 25716 => 28458, 25717 => 28425, + 25718 => 28457, 25719 => 28553, 25720 => 28557, 25721 => 28556, 25722 => 28536, + 25723 => 28530, 25724 => 28540, 25725 => 28538, 25726 => 28625, 25889 => 28617, + 25890 => 28583, 25891 => 28601, 25892 => 28598, 25893 => 28610, 25894 => 28641, + 25895 => 28654, 25896 => 28638, 25897 => 28640, 25898 => 28655, 25899 => 28698, + 25900 => 28707, 25901 => 28699, 25902 => 28729, 25903 => 28725, 25904 => 28751, + 25905 => 28766, 25906 => 23424, 25907 => 23428, 25908 => 23445, 25909 => 23443, + 25910 => 23461, 25911 => 23480, 25912 => 29999, 25913 => 39582, 25914 => 25652, + 25915 => 23524, 25916 => 23534, 25917 => 35120, 25918 => 23536, 25919 => 36423, + 25920 => 35591, 25921 => 36790, 25922 => 36819, 25923 => 36821, 25924 => 36837, + 25925 => 36846, 25926 => 36836, 25927 => 36841, 25928 => 36838, 25929 => 36851, + 25930 => 36840, 25931 => 36869, 25932 => 36868, 25933 => 36875, 25934 => 36902, + 25935 => 36881, 25936 => 36877, 25937 => 36886, 25938 => 36897, 25939 => 36917, + 25940 => 36918, 25941 => 36909, 25942 => 36911, 25943 => 36932, 25944 => 36945, + 25945 => 36946, 25946 => 36944, 25947 => 36968, 25948 => 36952, 25949 => 36962, + 25950 => 36955, 25951 => 26297, 25952 => 36980, 25953 => 36989, 25954 => 36994, + 25955 => 37000, 25956 => 36995, 25957 => 37003, 25958 => 24400, 25959 => 24407, + 25960 => 24406, 25961 => 24408, 25962 => 23611, 25963 => 21675, 25964 => 23632, + 25965 => 23641, 25966 => 23409, 25967 => 23651, 25968 => 23654, 25969 => 32700, + 25970 => 24362, 25971 => 24361, 25972 => 24365, 25973 => 33396, 25974 => 24380, + 25975 => 39739, 25976 => 23662, 25977 => 22913, 25978 => 22915, 25979 => 22925, + 25980 => 22953, 25981 => 22954, 25982 => 22947, 26145 => 22935, 26146 => 22986, + 26147 => 22955, 26148 => 22942, 26149 => 22948, 26150 => 22994, 26151 => 22962, + 26152 => 22959, 26153 => 22999, 26154 => 22974, 26155 => 23045, 26156 => 23046, + 26157 => 23005, 26158 => 23048, 26159 => 23011, 26160 => 23000, 26161 => 23033, + 26162 => 23052, 26163 => 23049, 26164 => 23090, 26165 => 23092, 26166 => 23057, + 26167 => 23075, 26168 => 23059, 26169 => 23104, 26170 => 23143, 26171 => 23114, + 26172 => 23125, 26173 => 23100, 26174 => 23138, 26175 => 23157, 26176 => 33004, + 26177 => 23210, 26178 => 23195, 26179 => 23159, 26180 => 23162, 26181 => 23230, + 26182 => 23275, 26183 => 23218, 26184 => 23250, 26185 => 23252, 26186 => 23224, + 26187 => 23264, 26188 => 23267, 26189 => 23281, 26190 => 23254, 26191 => 23270, + 26192 => 23256, 26193 => 23260, 26194 => 23305, 26195 => 23319, 26196 => 23318, + 26197 => 23346, 26198 => 23351, 26199 => 23360, 26200 => 23573, 26201 => 23580, + 26202 => 23386, 26203 => 23397, 26204 => 23411, 26205 => 23377, 26206 => 23379, + 26207 => 23394, 26208 => 39541, 26209 => 39543, 26210 => 39544, 26211 => 39546, + 26212 => 39551, 26213 => 39549, 26214 => 39552, 26215 => 39553, 26216 => 39557, + 26217 => 39560, 26218 => 39562, 26219 => 39568, 26220 => 39570, 26221 => 39571, + 26222 => 39574, 26223 => 39576, 26224 => 39579, 26225 => 39580, 26226 => 39581, + 26227 => 39583, 26228 => 39584, 26229 => 39586, 26230 => 39587, 26231 => 39589, + 26232 => 39591, 26233 => 32415, 26234 => 32417, 26235 => 32419, 26236 => 32421, + 26237 => 32424, 26238 => 32425, 26401 => 32429, 26402 => 32432, 26403 => 32446, + 26404 => 32448, 26405 => 32449, 26406 => 32450, 26407 => 32457, 26408 => 32459, + 26409 => 32460, 26410 => 32464, 26411 => 32468, 26412 => 32471, 26413 => 32475, + 26414 => 32480, 26415 => 32481, 26416 => 32488, 26417 => 32491, 26418 => 32494, + 26419 => 32495, 26420 => 32497, 26421 => 32498, 26422 => 32525, 26423 => 32502, + 26424 => 32506, 26425 => 32507, 26426 => 32510, 26427 => 32513, 26428 => 32514, + 26429 => 32515, 26430 => 32519, 26431 => 32520, 26432 => 32523, 26433 => 32524, + 26434 => 32527, 26435 => 32529, 26436 => 32530, 26437 => 32535, 26438 => 32537, + 26439 => 32540, 26440 => 32539, 26441 => 32543, 26442 => 32545, 26443 => 32546, + 26444 => 32547, 26445 => 32548, 26446 => 32549, 26447 => 32550, 26448 => 32551, + 26449 => 32554, 26450 => 32555, 26451 => 32556, 26452 => 32557, 26453 => 32559, + 26454 => 32560, 26455 => 32561, 26456 => 32562, 26457 => 32563, 26458 => 32565, + 26459 => 24186, 26460 => 30079, 26461 => 24027, 26462 => 30014, 26463 => 37013, + 26464 => 29582, 26465 => 29585, 26466 => 29614, 26467 => 29602, 26468 => 29599, + 26469 => 29647, 26470 => 29634, 26471 => 29649, 26472 => 29623, 26473 => 29619, + 26474 => 29632, 26475 => 29641, 26476 => 29640, 26477 => 29669, 26478 => 29657, + 26479 => 39036, 26480 => 29706, 26481 => 29673, 26482 => 29671, 26483 => 29662, + 26484 => 29626, 26485 => 29682, 26486 => 29711, 26487 => 29738, 26488 => 29787, + 26489 => 29734, 26490 => 29733, 26491 => 29736, 26492 => 29744, 26493 => 29742, + 26494 => 29740, 26657 => 29723, 26658 => 29722, 26659 => 29761, 26660 => 29788, + 26661 => 29783, 26662 => 29781, 26663 => 29785, 26664 => 29815, 26665 => 29805, + 26666 => 29822, 26667 => 29852, 26668 => 29838, 26669 => 29824, 26670 => 29825, + 26671 => 29831, 26672 => 29835, 26673 => 29854, 26674 => 29864, 26675 => 29865, + 26676 => 29840, 26677 => 29863, 26678 => 29906, 26679 => 29882, 26680 => 38890, + 26681 => 38891, 26682 => 38892, 26683 => 26444, 26684 => 26451, 26685 => 26462, + 26686 => 26440, 26687 => 26473, 26688 => 26533, 26689 => 26503, 26690 => 26474, + 26691 => 26483, 26692 => 26520, 26693 => 26535, 26694 => 26485, 26695 => 26536, + 26696 => 26526, 26697 => 26541, 26698 => 26507, 26699 => 26487, 26700 => 26492, + 26701 => 26608, 26702 => 26633, 26703 => 26584, 26704 => 26634, 26705 => 26601, + 26706 => 26544, 26707 => 26636, 26708 => 26585, 26709 => 26549, 26710 => 26586, + 26711 => 26547, 26712 => 26589, 26713 => 26624, 26714 => 26563, 26715 => 26552, + 26716 => 26594, 26717 => 26638, 26718 => 26561, 26719 => 26621, 26720 => 26674, + 26721 => 26675, 26722 => 26720, 26723 => 26721, 26724 => 26702, 26725 => 26722, + 26726 => 26692, 26727 => 26724, 26728 => 26755, 26729 => 26653, 26730 => 26709, + 26731 => 26726, 26732 => 26689, 26733 => 26727, 26734 => 26688, 26735 => 26686, + 26736 => 26698, 26737 => 26697, 26738 => 26665, 26739 => 26805, 26740 => 26767, + 26741 => 26740, 26742 => 26743, 26743 => 26771, 26744 => 26731, 26745 => 26818, + 26746 => 26990, 26747 => 26876, 26748 => 26911, 26749 => 26912, 26750 => 26873, + 26913 => 26916, 26914 => 26864, 26915 => 26891, 26916 => 26881, 26917 => 26967, + 26918 => 26851, 26919 => 26896, 26920 => 26993, 26921 => 26937, 26922 => 26976, + 26923 => 26946, 26924 => 26973, 26925 => 27012, 26926 => 26987, 26927 => 27008, + 26928 => 27032, 26929 => 27000, 26930 => 26932, 26931 => 27084, 26932 => 27015, + 26933 => 27016, 26934 => 27086, 26935 => 27017, 26936 => 26982, 26937 => 26979, + 26938 => 27001, 26939 => 27035, 26940 => 27047, 26941 => 27067, 26942 => 27051, + 26943 => 27053, 26944 => 27092, 26945 => 27057, 26946 => 27073, 26947 => 27082, + 26948 => 27103, 26949 => 27029, 26950 => 27104, 26951 => 27021, 26952 => 27135, + 26953 => 27183, 26954 => 27117, 26955 => 27159, 26956 => 27160, 26957 => 27237, + 26958 => 27122, 26959 => 27204, 26960 => 27198, 26961 => 27296, 26962 => 27216, + 26963 => 27227, 26964 => 27189, 26965 => 27278, 26966 => 27257, 26967 => 27197, + 26968 => 27176, 26969 => 27224, 26970 => 27260, 26971 => 27281, 26972 => 27280, + 26973 => 27305, 26974 => 27287, 26975 => 27307, 26976 => 29495, 26977 => 29522, + 26978 => 27521, 26979 => 27522, 26980 => 27527, 26981 => 27524, 26982 => 27538, + 26983 => 27539, 26984 => 27533, 26985 => 27546, 26986 => 27547, 26987 => 27553, + 26988 => 27562, 26989 => 36715, 26990 => 36717, 26991 => 36721, 26992 => 36722, + 26993 => 36723, 26994 => 36725, 26995 => 36726, 26996 => 36728, 26997 => 36727, + 26998 => 36729, 26999 => 36730, 27000 => 36732, 27001 => 36734, 27002 => 36737, + 27003 => 36738, 27004 => 36740, 27005 => 36743, 27006 => 36747, 27169 => 36749, + 27170 => 36750, 27171 => 36751, 27172 => 36760, 27173 => 36762, 27174 => 36558, + 27175 => 25099, 27176 => 25111, 27177 => 25115, 27178 => 25119, 27179 => 25122, + 27180 => 25121, 27181 => 25125, 27182 => 25124, 27183 => 25132, 27184 => 33255, + 27185 => 29935, 27186 => 29940, 27187 => 29951, 27188 => 29967, 27189 => 29969, + 27190 => 29971, 27191 => 25908, 27192 => 26094, 27193 => 26095, 27194 => 26096, + 27195 => 26122, 27196 => 26137, 27197 => 26482, 27198 => 26115, 27199 => 26133, + 27200 => 26112, 27201 => 28805, 27202 => 26359, 27203 => 26141, 27204 => 26164, + 27205 => 26161, 27206 => 26166, 27207 => 26165, 27208 => 32774, 27209 => 26207, + 27210 => 26196, 27211 => 26177, 27212 => 26191, 27213 => 26198, 27214 => 26209, + 27215 => 26199, 27216 => 26231, 27217 => 26244, 27218 => 26252, 27219 => 26279, + 27220 => 26269, 27221 => 26302, 27222 => 26331, 27223 => 26332, 27224 => 26342, + 27225 => 26345, 27226 => 36146, 27227 => 36147, 27228 => 36150, 27229 => 36155, + 27230 => 36157, 27231 => 36160, 27232 => 36165, 27233 => 36166, 27234 => 36168, + 27235 => 36169, 27236 => 36167, 27237 => 36173, 27238 => 36181, 27239 => 36185, + 27240 => 35271, 27241 => 35274, 27242 => 35275, 27243 => 35276, 27244 => 35278, + 27245 => 35279, 27246 => 35280, 27247 => 35281, 27248 => 29294, 27249 => 29343, + 27250 => 29277, 27251 => 29286, 27252 => 29295, 27253 => 29310, 27254 => 29311, + 27255 => 29316, 27256 => 29323, 27257 => 29325, 27258 => 29327, 27259 => 29330, + 27260 => 25352, 27261 => 25394, 27262 => 25520, 27425 => 25663, 27426 => 25816, + 27427 => 32772, 27428 => 27626, 27429 => 27635, 27430 => 27645, 27431 => 27637, + 27432 => 27641, 27433 => 27653, 27434 => 27655, 27435 => 27654, 27436 => 27661, + 27437 => 27669, 27438 => 27672, 27439 => 27673, 27440 => 27674, 27441 => 27681, + 27442 => 27689, 27443 => 27684, 27444 => 27690, 27445 => 27698, 27446 => 25909, + 27447 => 25941, 27448 => 25963, 27449 => 29261, 27450 => 29266, 27451 => 29270, + 27452 => 29232, 27453 => 34402, 27454 => 21014, 27455 => 32927, 27456 => 32924, + 27457 => 32915, 27458 => 32956, 27459 => 26378, 27460 => 32957, 27461 => 32945, + 27462 => 32939, 27463 => 32941, 27464 => 32948, 27465 => 32951, 27466 => 32999, + 27467 => 33000, 27468 => 33001, 27469 => 33002, 27470 => 32987, 27471 => 32962, + 27472 => 32964, 27473 => 32985, 27474 => 32973, 27475 => 32983, 27476 => 26384, + 27477 => 32989, 27478 => 33003, 27479 => 33009, 27480 => 33012, 27481 => 33005, + 27482 => 33037, 27483 => 33038, 27484 => 33010, 27485 => 33020, 27486 => 26389, + 27487 => 33042, 27488 => 35930, 27489 => 33078, 27490 => 33054, 27491 => 33068, + 27492 => 33048, 27493 => 33074, 27494 => 33096, 27495 => 33100, 27496 => 33107, + 27497 => 33140, 27498 => 33113, 27499 => 33114, 27500 => 33137, 27501 => 33120, + 27502 => 33129, 27503 => 33148, 27504 => 33149, 27505 => 33133, 27506 => 33127, + 27507 => 22605, 27508 => 23221, 27509 => 33160, 27510 => 33154, 27511 => 33169, + 27512 => 28373, 27513 => 33187, 27514 => 33194, 27515 => 33228, 27516 => 26406, + 27517 => 33226, 27518 => 33211, 27681 => 33217, 27682 => 33190, 27683 => 27428, + 27684 => 27447, 27685 => 27449, 27686 => 27459, 27687 => 27462, 27688 => 27481, + 27689 => 39121, 27690 => 39122, 27691 => 39123, 27692 => 39125, 27693 => 39129, + 27694 => 39130, 27695 => 27571, 27696 => 24384, 27697 => 27586, 27698 => 35315, + 27699 => 26000, 27700 => 40785, 27701 => 26003, 27702 => 26044, 27703 => 26054, + 27704 => 26052, 27705 => 26051, 27706 => 26060, 27707 => 26062, 27708 => 26066, + 27709 => 26070, 27710 => 28800, 27711 => 28828, 27712 => 28822, 27713 => 28829, + 27714 => 28859, 27715 => 28864, 27716 => 28855, 27717 => 28843, 27718 => 28849, + 27719 => 28904, 27720 => 28874, 27721 => 28944, 27722 => 28947, 27723 => 28950, + 27724 => 28975, 27725 => 28977, 27726 => 29043, 27727 => 29020, 27728 => 29032, + 27729 => 28997, 27730 => 29042, 27731 => 29002, 27732 => 29048, 27733 => 29050, + 27734 => 29080, 27735 => 29107, 27736 => 29109, 27737 => 29096, 27738 => 29088, + 27739 => 29152, 27740 => 29140, 27741 => 29159, 27742 => 29177, 27743 => 29213, + 27744 => 29224, 27745 => 28780, 27746 => 28952, 27747 => 29030, 27748 => 29113, + 27749 => 25150, 27750 => 25149, 27751 => 25155, 27752 => 25160, 27753 => 25161, + 27754 => 31035, 27755 => 31040, 27756 => 31046, 27757 => 31049, 27758 => 31067, + 27759 => 31068, 27760 => 31059, 27761 => 31066, 27762 => 31074, 27763 => 31063, + 27764 => 31072, 27765 => 31087, 27766 => 31079, 27767 => 31098, 27768 => 31109, + 27769 => 31114, 27770 => 31130, 27771 => 31143, 27772 => 31155, 27773 => 24529, + 27774 => 24528, 27937 => 24636, 27938 => 24669, 27939 => 24666, 27940 => 24679, + 27941 => 24641, 27942 => 24665, 27943 => 24675, 27944 => 24747, 27945 => 24838, + 27946 => 24845, 27947 => 24925, 27948 => 25001, 27949 => 24989, 27950 => 25035, + 27951 => 25041, 27952 => 25094, 27953 => 32896, 27954 => 32895, 27955 => 27795, + 27956 => 27894, 27957 => 28156, 27958 => 30710, 27959 => 30712, 27960 => 30720, + 27961 => 30729, 27962 => 30743, 27963 => 30744, 27964 => 30737, 27965 => 26027, + 27966 => 30765, 27967 => 30748, 27968 => 30749, 27969 => 30777, 27970 => 30778, + 27971 => 30779, 27972 => 30751, 27973 => 30780, 27974 => 30757, 27975 => 30764, + 27976 => 30755, 27977 => 30761, 27978 => 30798, 27979 => 30829, 27980 => 30806, + 27981 => 30807, 27982 => 30758, 27983 => 30800, 27984 => 30791, 27985 => 30796, + 27986 => 30826, 27987 => 30875, 27988 => 30867, 27989 => 30874, 27990 => 30855, + 27991 => 30876, 27992 => 30881, 27993 => 30883, 27994 => 30898, 27995 => 30905, + 27996 => 30885, 27997 => 30932, 27998 => 30937, 27999 => 30921, 28000 => 30956, + 28001 => 30962, 28002 => 30981, 28003 => 30964, 28004 => 30995, 28005 => 31012, + 28006 => 31006, 28007 => 31028, 28008 => 40859, 28009 => 40697, 28010 => 40699, + 28011 => 40700, 28012 => 30449, 28013 => 30468, 28014 => 30477, 28015 => 30457, + 28016 => 30471, 28017 => 30472, 28018 => 30490, 28019 => 30498, 28020 => 30489, + 28021 => 30509, 28022 => 30502, 28023 => 30517, 28024 => 30520, 28025 => 30544, + 28026 => 30545, 28027 => 30535, 28028 => 30531, 28029 => 30554, 28030 => 30568, + 28193 => 30562, 28194 => 30565, 28195 => 30591, 28196 => 30605, 28197 => 30589, + 28198 => 30592, 28199 => 30604, 28200 => 30609, 28201 => 30623, 28202 => 30624, + 28203 => 30640, 28204 => 30645, 28205 => 30653, 28206 => 30010, 28207 => 30016, + 28208 => 30030, 28209 => 30027, 28210 => 30024, 28211 => 30043, 28212 => 30066, + 28213 => 30073, 28214 => 30083, 28215 => 32600, 28216 => 32609, 28217 => 32607, + 28218 => 35400, 28219 => 32616, 28220 => 32628, 28221 => 32625, 28222 => 32633, + 28223 => 32641, 28224 => 32638, 28225 => 30413, 28226 => 30437, 28227 => 34866, + 28228 => 38021, 28229 => 38022, 28230 => 38023, 28231 => 38027, 28232 => 38026, + 28233 => 38028, 28234 => 38029, 28235 => 38031, 28236 => 38032, 28237 => 38036, + 28238 => 38039, 28239 => 38037, 28240 => 38042, 28241 => 38043, 28242 => 38044, + 28243 => 38051, 28244 => 38052, 28245 => 38059, 28246 => 38058, 28247 => 38061, + 28248 => 38060, 28249 => 38063, 28250 => 38064, 28251 => 38066, 28252 => 38068, + 28253 => 38070, 28254 => 38071, 28255 => 38072, 28256 => 38073, 28257 => 38074, + 28258 => 38076, 28259 => 38077, 28260 => 38079, 28261 => 38084, 28262 => 38088, + 28263 => 38089, 28264 => 38090, 28265 => 38091, 28266 => 38092, 28267 => 38093, + 28268 => 38094, 28269 => 38096, 28270 => 38097, 28271 => 38098, 28272 => 38101, + 28273 => 38102, 28274 => 38103, 28275 => 38105, 28276 => 38104, 28277 => 38107, + 28278 => 38110, 28279 => 38111, 28280 => 38112, 28281 => 38114, 28282 => 38116, + 28283 => 38117, 28284 => 38119, 28285 => 38120, 28286 => 38122, 28449 => 38121, + 28450 => 38123, 28451 => 38126, 28452 => 38127, 28453 => 38131, 28454 => 38132, + 28455 => 38133, 28456 => 38135, 28457 => 38137, 28458 => 38140, 28459 => 38141, + 28460 => 38143, 28461 => 38147, 28462 => 38146, 28463 => 38150, 28464 => 38151, + 28465 => 38153, 28466 => 38154, 28467 => 38157, 28468 => 38158, 28469 => 38159, + 28470 => 38162, 28471 => 38163, 28472 => 38164, 28473 => 38165, 28474 => 38166, + 28475 => 38168, 28476 => 38171, 28477 => 38173, 28478 => 38174, 28479 => 38175, + 28480 => 38178, 28481 => 38186, 28482 => 38187, 28483 => 38185, 28484 => 38188, + 28485 => 38193, 28486 => 38194, 28487 => 38196, 28488 => 38198, 28489 => 38199, + 28490 => 38200, 28491 => 38204, 28492 => 38206, 28493 => 38207, 28494 => 38210, + 28495 => 38197, 28496 => 38212, 28497 => 38213, 28498 => 38214, 28499 => 38217, + 28500 => 38220, 28501 => 38222, 28502 => 38223, 28503 => 38226, 28504 => 38227, + 28505 => 38228, 28506 => 38230, 28507 => 38231, 28508 => 38232, 28509 => 38233, + 28510 => 38235, 28511 => 38238, 28512 => 38239, 28513 => 38237, 28514 => 38241, + 28515 => 38242, 28516 => 38244, 28517 => 38245, 28518 => 38246, 28519 => 38247, + 28520 => 38248, 28521 => 38249, 28522 => 38250, 28523 => 38251, 28524 => 38252, + 28525 => 38255, 28526 => 38257, 28527 => 38258, 28528 => 38259, 28529 => 38202, + 28530 => 30695, 28531 => 30700, 28532 => 38601, 28533 => 31189, 28534 => 31213, + 28535 => 31203, 28536 => 31211, 28537 => 31238, 28538 => 23879, 28539 => 31235, + 28540 => 31234, 28541 => 31262, 28542 => 31252, 28705 => 31289, 28706 => 31287, + 28707 => 31313, 28708 => 40655, 28709 => 39333, 28710 => 31344, 28711 => 30344, + 28712 => 30350, 28713 => 30355, 28714 => 30361, 28715 => 30372, 28716 => 29918, + 28717 => 29920, 28718 => 29996, 28719 => 40480, 28720 => 40482, 28721 => 40488, + 28722 => 40489, 28723 => 40490, 28724 => 40491, 28725 => 40492, 28726 => 40498, + 28727 => 40497, 28728 => 40502, 28729 => 40504, 28730 => 40503, 28731 => 40505, + 28732 => 40506, 28733 => 40510, 28734 => 40513, 28735 => 40514, 28736 => 40516, + 28737 => 40518, 28738 => 40519, 28739 => 40520, 28740 => 40521, 28741 => 40523, + 28742 => 40524, 28743 => 40526, 28744 => 40529, 28745 => 40533, 28746 => 40535, + 28747 => 40538, 28748 => 40539, 28749 => 40540, 28750 => 40542, 28751 => 40547, + 28752 => 40550, 28753 => 40551, 28754 => 40552, 28755 => 40553, 28756 => 40554, + 28757 => 40555, 28758 => 40556, 28759 => 40561, 28760 => 40557, 28761 => 40563, + 28762 => 30098, 28763 => 30100, 28764 => 30102, 28765 => 30112, 28766 => 30109, + 28767 => 30124, 28768 => 30115, 28769 => 30131, 28770 => 30132, 28771 => 30136, + 28772 => 30148, 28773 => 30129, 28774 => 30128, 28775 => 30147, 28776 => 30146, + 28777 => 30166, 28778 => 30157, 28779 => 30179, 28780 => 30184, 28781 => 30182, + 28782 => 30180, 28783 => 30187, 28784 => 30183, 28785 => 30211, 28786 => 30193, + 28787 => 30204, 28788 => 30207, 28789 => 30224, 28790 => 30208, 28791 => 30213, + 28792 => 30220, 28793 => 30231, 28794 => 30218, 28795 => 30245, 28796 => 30232, + 28797 => 30229, 28798 => 30233, 28961 => 30235, 28962 => 30268, 28963 => 30242, + 28964 => 30240, 28965 => 30272, 28966 => 30253, 28967 => 30256, 28968 => 30271, + 28969 => 30261, 28970 => 30275, 28971 => 30270, 28972 => 30259, 28973 => 30285, + 28974 => 30302, 28975 => 30292, 28976 => 30300, 28977 => 30294, 28978 => 30315, + 28979 => 30319, 28980 => 32714, 28981 => 31462, 28982 => 31352, 28983 => 31353, + 28984 => 31360, 28985 => 31366, 28986 => 31368, 28987 => 31381, 28988 => 31398, + 28989 => 31392, 28990 => 31404, 28991 => 31400, 28992 => 31405, 28993 => 31411, + 28994 => 34916, 28995 => 34921, 28996 => 34930, 28997 => 34941, 28998 => 34943, + 28999 => 34946, 29000 => 34978, 29001 => 35014, 29002 => 34999, 29003 => 35004, + 29004 => 35017, 29005 => 35042, 29006 => 35022, 29007 => 35043, 29008 => 35045, + 29009 => 35057, 29010 => 35098, 29011 => 35068, 29012 => 35048, 29013 => 35070, + 29014 => 35056, 29015 => 35105, 29016 => 35097, 29017 => 35091, 29018 => 35099, + 29019 => 35082, 29020 => 35124, 29021 => 35115, 29022 => 35126, 29023 => 35137, + 29024 => 35174, 29025 => 35195, 29026 => 30091, 29027 => 32997, 29028 => 30386, + 29029 => 30388, 29030 => 30684, 29031 => 32786, 29032 => 32788, 29033 => 32790, + 29034 => 32796, 29035 => 32800, 29036 => 32802, 29037 => 32805, 29038 => 32806, + 29039 => 32807, 29040 => 32809, 29041 => 32808, 29042 => 32817, 29043 => 32779, + 29044 => 32821, 29045 => 32835, 29046 => 32838, 29047 => 32845, 29048 => 32850, + 29049 => 32873, 29050 => 32881, 29051 => 35203, 29052 => 39032, 29053 => 39040, + 29054 => 39043, 29217 => 39049, 29218 => 39052, 29219 => 39053, 29220 => 39055, + 29221 => 39060, 29222 => 39066, 29223 => 39067, 29224 => 39070, 29225 => 39071, + 29226 => 39073, 29227 => 39074, 29228 => 39077, 29229 => 39078, 29230 => 34381, + 29231 => 34388, 29232 => 34412, 29233 => 34414, 29234 => 34431, 29235 => 34426, + 29236 => 34428, 29237 => 34427, 29238 => 34472, 29239 => 34445, 29240 => 34443, + 29241 => 34476, 29242 => 34461, 29243 => 34471, 29244 => 34467, 29245 => 34474, + 29246 => 34451, 29247 => 34473, 29248 => 34486, 29249 => 34500, 29250 => 34485, + 29251 => 34510, 29252 => 34480, 29253 => 34490, 29254 => 34481, 29255 => 34479, + 29256 => 34505, 29257 => 34511, 29258 => 34484, 29259 => 34537, 29260 => 34545, + 29261 => 34546, 29262 => 34541, 29263 => 34547, 29264 => 34512, 29265 => 34579, + 29266 => 34526, 29267 => 34548, 29268 => 34527, 29269 => 34520, 29270 => 34513, + 29271 => 34563, 29272 => 34567, 29273 => 34552, 29274 => 34568, 29275 => 34570, + 29276 => 34573, 29277 => 34569, 29278 => 34595, 29279 => 34619, 29280 => 34590, + 29281 => 34597, 29282 => 34606, 29283 => 34586, 29284 => 34622, 29285 => 34632, + 29286 => 34612, 29287 => 34609, 29288 => 34601, 29289 => 34615, 29290 => 34623, + 29291 => 34690, 29292 => 34594, 29293 => 34685, 29294 => 34686, 29295 => 34683, + 29296 => 34656, 29297 => 34672, 29298 => 34636, 29299 => 34670, 29300 => 34699, + 29301 => 34643, 29302 => 34659, 29303 => 34684, 29304 => 34660, 29305 => 34649, + 29306 => 34661, 29307 => 34707, 29308 => 34735, 29309 => 34728, 29310 => 34770, + 29473 => 34758, 29474 => 34696, 29475 => 34693, 29476 => 34733, 29477 => 34711, + 29478 => 34691, 29479 => 34731, 29480 => 34789, 29481 => 34732, 29482 => 34741, + 29483 => 34739, 29484 => 34763, 29485 => 34771, 29486 => 34749, 29487 => 34769, + 29488 => 34752, 29489 => 34762, 29490 => 34779, 29491 => 34794, 29492 => 34784, + 29493 => 34798, 29494 => 34838, 29495 => 34835, 29496 => 34814, 29497 => 34826, + 29498 => 34843, 29499 => 34849, 29500 => 34873, 29501 => 34876, 29502 => 32566, + 29503 => 32578, 29504 => 32580, 29505 => 32581, 29506 => 33296, 29507 => 31482, + 29508 => 31485, 29509 => 31496, 29510 => 31491, 29511 => 31492, 29512 => 31509, + 29513 => 31498, 29514 => 31531, 29515 => 31503, 29516 => 31559, 29517 => 31544, + 29518 => 31530, 29519 => 31513, 29520 => 31534, 29521 => 31537, 29522 => 31520, + 29523 => 31525, 29524 => 31524, 29525 => 31539, 29526 => 31550, 29527 => 31518, + 29528 => 31576, 29529 => 31578, 29530 => 31557, 29531 => 31605, 29532 => 31564, + 29533 => 31581, 29534 => 31584, 29535 => 31598, 29536 => 31611, 29537 => 31586, + 29538 => 31602, 29539 => 31601, 29540 => 31632, 29541 => 31654, 29542 => 31655, + 29543 => 31672, 29544 => 31660, 29545 => 31645, 29546 => 31656, 29547 => 31621, + 29548 => 31658, 29549 => 31644, 29550 => 31650, 29551 => 31659, 29552 => 31668, + 29553 => 31697, 29554 => 31681, 29555 => 31692, 29556 => 31709, 29557 => 31706, + 29558 => 31717, 29559 => 31718, 29560 => 31722, 29561 => 31756, 29562 => 31742, + 29563 => 31740, 29564 => 31759, 29565 => 31766, 29566 => 31755, 29729 => 31775, + 29730 => 31786, 29731 => 31782, 29732 => 31800, 29733 => 31809, 29734 => 31808, + 29735 => 33278, 29736 => 33281, 29737 => 33282, 29738 => 33284, 29739 => 33260, + 29740 => 34884, 29741 => 33313, 29742 => 33314, 29743 => 33315, 29744 => 33325, + 29745 => 33327, 29746 => 33320, 29747 => 33323, 29748 => 33336, 29749 => 33339, + 29750 => 33331, 29751 => 33332, 29752 => 33342, 29753 => 33348, 29754 => 33353, + 29755 => 33355, 29756 => 33359, 29757 => 33370, 29758 => 33375, 29759 => 33384, + 29760 => 34942, 29761 => 34949, 29762 => 34952, 29763 => 35032, 29764 => 35039, + 29765 => 35166, 29766 => 32669, 29767 => 32671, 29768 => 32679, 29769 => 32687, + 29770 => 32688, 29771 => 32690, 29772 => 31868, 29773 => 25929, 29774 => 31889, + 29775 => 31901, 29776 => 31900, 29777 => 31902, 29778 => 31906, 29779 => 31922, + 29780 => 31932, 29781 => 31933, 29782 => 31937, 29783 => 31943, 29784 => 31948, + 29785 => 31949, 29786 => 31944, 29787 => 31941, 29788 => 31959, 29789 => 31976, + 29790 => 33390, 29791 => 26280, 29792 => 32703, 29793 => 32718, 29794 => 32725, + 29795 => 32741, 29796 => 32737, 29797 => 32742, 29798 => 32745, 29799 => 32750, + 29800 => 32755, 29801 => 31992, 29802 => 32119, 29803 => 32166, 29804 => 32174, + 29805 => 32327, 29806 => 32411, 29807 => 40632, 29808 => 40628, 29809 => 36211, + 29810 => 36228, 29811 => 36244, 29812 => 36241, 29813 => 36273, 29814 => 36199, + 29815 => 36205, 29816 => 35911, 29817 => 35913, 29818 => 37194, 29819 => 37200, + 29820 => 37198, 29821 => 37199, 29822 => 37220, 29985 => 37218, 29986 => 37217, + 29987 => 37232, 29988 => 37225, 29989 => 37231, 29990 => 37245, 29991 => 37246, + 29992 => 37234, 29993 => 37236, 29994 => 37241, 29995 => 37260, 29996 => 37253, + 29997 => 37264, 29998 => 37261, 29999 => 37265, 30000 => 37282, 30001 => 37283, + 30002 => 37290, 30003 => 37293, 30004 => 37294, 30005 => 37295, 30006 => 37301, + 30007 => 37300, 30008 => 37306, 30009 => 35925, 30010 => 40574, 30011 => 36280, + 30012 => 36331, 30013 => 36357, 30014 => 36441, 30015 => 36457, 30016 => 36277, + 30017 => 36287, 30018 => 36284, 30019 => 36282, 30020 => 36292, 30021 => 36310, + 30022 => 36311, 30023 => 36314, 30024 => 36318, 30025 => 36302, 30026 => 36303, + 30027 => 36315, 30028 => 36294, 30029 => 36332, 30030 => 36343, 30031 => 36344, + 30032 => 36323, 30033 => 36345, 30034 => 36347, 30035 => 36324, 30036 => 36361, + 30037 => 36349, 30038 => 36372, 30039 => 36381, 30040 => 36383, 30041 => 36396, + 30042 => 36398, 30043 => 36387, 30044 => 36399, 30045 => 36410, 30046 => 36416, + 30047 => 36409, 30048 => 36405, 30049 => 36413, 30050 => 36401, 30051 => 36425, + 30052 => 36417, 30053 => 36418, 30054 => 36433, 30055 => 36434, 30056 => 36426, + 30057 => 36464, 30058 => 36470, 30059 => 36476, 30060 => 36463, 30061 => 36468, + 30062 => 36485, 30063 => 36495, 30064 => 36500, 30065 => 36496, 30066 => 36508, + 30067 => 36510, 30068 => 35960, 30069 => 35970, 30070 => 35978, 30071 => 35973, + 30072 => 35992, 30073 => 35988, 30074 => 26011, 30075 => 35286, 30076 => 35294, + 30077 => 35290, 30078 => 35292, 30241 => 35301, 30242 => 35307, 30243 => 35311, + 30244 => 35390, 30245 => 35622, 30246 => 38739, 30247 => 38633, 30248 => 38643, + 30249 => 38639, 30250 => 38662, 30251 => 38657, 30252 => 38664, 30253 => 38671, + 30254 => 38670, 30255 => 38698, 30256 => 38701, 30257 => 38704, 30258 => 38718, + 30259 => 40832, 30260 => 40835, 30261 => 40837, 30262 => 40838, 30263 => 40839, + 30264 => 40840, 30265 => 40841, 30266 => 40842, 30267 => 40844, 30268 => 40702, + 30269 => 40715, 30270 => 40717, 30271 => 38585, 30272 => 38588, 30273 => 38589, + 30274 => 38606, 30275 => 38610, 30276 => 30655, 30277 => 38624, 30278 => 37518, + 30279 => 37550, 30280 => 37576, 30281 => 37694, 30282 => 37738, 30283 => 37834, + 30284 => 37775, 30285 => 37950, 30286 => 37995, 30287 => 40063, 30288 => 40066, + 30289 => 40069, 30290 => 40070, 30291 => 40071, 30292 => 40072, 30293 => 31267, + 30294 => 40075, 30295 => 40078, 30296 => 40080, 30297 => 40081, 30298 => 40082, + 30299 => 40084, 30300 => 40085, 30301 => 40090, 30302 => 40091, 30303 => 40094, + 30304 => 40095, 30305 => 40096, 30306 => 40097, 30307 => 40098, 30308 => 40099, + 30309 => 40101, 30310 => 40102, 30311 => 40103, 30312 => 40104, 30313 => 40105, + 30314 => 40107, 30315 => 40109, 30316 => 40110, 30317 => 40112, 30318 => 40113, + 30319 => 40114, 30320 => 40115, 30321 => 40116, 30322 => 40117, 30323 => 40118, + 30324 => 40119, 30325 => 40122, 30326 => 40123, 30327 => 40124, 30328 => 40125, + 30329 => 40132, 30330 => 40133, 30331 => 40134, 30332 => 40135, 30333 => 40138, + 30334 => 40139, 30497 => 40140, 30498 => 40141, 30499 => 40142, 30500 => 40143, + 30501 => 40144, 30502 => 40147, 30503 => 40148, 30504 => 40149, 30505 => 40151, + 30506 => 40152, 30507 => 40153, 30508 => 40156, 30509 => 40157, 30510 => 40159, + 30511 => 40162, 30512 => 38780, 30513 => 38789, 30514 => 38801, 30515 => 38802, + 30516 => 38804, 30517 => 38831, 30518 => 38827, 30519 => 38819, 30520 => 38834, + 30521 => 38836, 30522 => 39601, 30523 => 39600, 30524 => 39607, 30525 => 40536, + 30526 => 39606, 30527 => 39610, 30528 => 39612, 30529 => 39617, 30530 => 39616, + 30531 => 39621, 30532 => 39618, 30533 => 39627, 30534 => 39628, 30535 => 39633, + 30536 => 39749, 30537 => 39747, 30538 => 39751, 30539 => 39753, 30540 => 39752, + 30541 => 39757, 30542 => 39761, 30543 => 39144, 30544 => 39181, 30545 => 39214, + 30546 => 39253, 30547 => 39252, 30548 => 39647, 30549 => 39649, 30550 => 39654, + 30551 => 39663, 30552 => 39659, 30553 => 39675, 30554 => 39661, 30555 => 39673, + 30556 => 39688, 30557 => 39695, 30558 => 39699, 30559 => 39711, 30560 => 39715, + 30561 => 40637, 30562 => 40638, 30563 => 32315, 30564 => 40578, 30565 => 40583, + 30566 => 40584, 30567 => 40587, 30568 => 40594, 30569 => 37846, 30570 => 40605, + 30571 => 40607, 30572 => 40667, 30573 => 40668, 30574 => 40669, 30575 => 40672, + 30576 => 40671, 30577 => 40674, 30578 => 40681, 30579 => 40679, 30580 => 40677, + 30581 => 40682, 30582 => 40687, 30583 => 40738, 30584 => 40748, 30585 => 40751, + 30586 => 40761, 30587 => 40759, 30588 => 40765, 30589 => 40766, 30590 => 40772, + 0 => 0 ); + + function gb2utf8($gb) { + if( !trim($gb) ) return $gb; + $utf8=''; + while($gb) { + if( ord(substr($gb,0,1)) > 127 ) { + $t=substr($gb,0,2); + $gb=substr($gb,2); + $utf8 .= $this->u2utf8($this->codetable[hexdec(bin2hex($t))-0x8080]); + } + else { + $t=substr($gb,0,1); + $gb=substr($gb,1); + $utf8 .= $this->u2utf8($t); + } + } + return $utf8; + } + + function u2utf8($c) { + $str=''; + if ($c < 0x80) { + $str.=$c; + } + else if ($c < 0x800) { + $str.=chr(0xC0 | $c>>6); + $str.=chr(0x80 | $c & 0x3F); + } + else if ($c < 0x10000) { + $str.=chr(0xE0 | $c>>12); + $str.=chr(0x80 | $c>>6 & 0x3F); + $str.=chr(0x80 | $c & 0x3F); + } + else if ($c < 0x200000) { + $str.=chr(0xF0 | $c>>18); + $str.=chr(0x80 | $c>>12 & 0x3F); + $str.=chr(0x80 | $c>>6 & 0x3F); + $str.=chr(0x80 | $c & 0x3F); + } + return $str; + } + +} // END Class + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_gradient.php b/web/public_php/admin/jpgraph/jpgraph_gradient.php index 356657950..e3c24d3af 100644 --- a/web/public_php/admin/jpgraph/jpgraph_gradient.php +++ b/web/public_php/admin/jpgraph/jpgraph_gradient.php @@ -1,377 +1,434 @@ -img = &$img; - } - - - function SetNumColors($aNum) { - $this->numcolors=$aNum; - } -//--------------- -// PUBLIC METHODS - // Produce a gradient filled rectangle with a smooth transition between - // two colors. - // ($xl,$yt) Top left corner - // ($xr,$yb) Bottom right - // $from_color Starting color in gradient - // $to_color End color in the gradient - // $style Which way is the gradient oriented? - function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) { - switch( $style ) { - case GRAD_VER: - $steps = round(abs($xr-$xl)); - $delta = $xr>=$xl ? 1 : -1; - $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); - for( $i=0, $x=$xl; $i < $steps; ++$i ) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yt,$x,$yb); - $x += $delta; - } - break; - - case GRAD_HOR: - $steps = round(abs($yb-$yt)); - $delta = $yb>=$yt ? 1 : -1; - $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); - for($i=0,$y=$yt; $i < $steps; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($xl,$y,$xr,$y); - $y += $delta; - } - break; - - case GRAD_MIDHOR: - $steps = round(abs($yb-$yt)/2); - $delta = $yb >= $yt ? 1 : -1; - $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); - for($y=$yt, $i=0; $i < $steps; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($xl,$y,$xr,$y); - $y += $delta; - } - --$i; - if( abs($yb-$yt) % 2 == 1 ) --$steps; - for($j=0; $j < $steps; ++$j, --$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($xl,$y,$xr,$y); - $y += $delta; - } - $this->img->Line($xl,$y,$xr,$y); - break; - - case GRAD_MIDVER: - $steps = round(abs($xr-$xl)/2); - $delta = $xr>=$xl ? 1 : -1; - $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); - for($x=$xl, $i=0; $i < $steps; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - --$i; - if( abs($xr-$xl) % 2 == 1 ) --$steps; - for($j=0; $j < $steps; ++$j, --$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - $this->img->Line($x,$yb,$x,$yt); - break; - - case GRAD_WIDE_MIDVER: - $diff = round(abs($xr-$xl)); - $steps = floor(abs($diff)/3); - $firststep = $diff - 2*$steps ; - $delta = $xr >= $xl ? 1 : -1; - $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors); - for($x=$xl, $i=0; $i < $firststep; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - --$i; - $this->img->current_color = $colors[$i]; - for($j=0; $j< $steps; ++$j) { - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - - for($j=0; $j < $steps; ++$j, --$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - break; - - case GRAD_WIDE_MIDHOR: - $diff = round(abs($yb-$yt)); - $steps = floor(abs($diff)/3); - $firststep = $diff - 2*$steps ; - $delta = $yb >= $yt? 1 : -1; - $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors); - for($y=$yt, $i=0; $i < $firststep; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($xl,$y,$xr,$y); - $y += $delta; - } - --$i; - $this->img->current_color = $colors[$i]; - for($j=0; $j < $steps; ++$j) { - $this->img->Line($xl,$y,$xr,$y); - $y += $delta; - } - for($j=0; $j < $steps; ++$j, --$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($xl,$y,$xr,$y); - $y += $delta; - } - break; - - case GRAD_LEFT_REFLECTION: - $steps1 = round(0.3*abs($xr-$xl)); - $delta = $xr>=$xl ? 1 : -1; - - $from_color = $this->img->rgb->Color($from_color); - $adj = 1.4; - $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2])))); - $from_color2 = array(min(255,$from_color[0]+$m), - min(255,$from_color[1]+$m), min(255,$from_color[2]+$m)); - - $this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors); - $n = count($colors); - for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - $steps2 = max(1,round(0.08*abs($xr-$xl))); - $this->img->SetColor($to_color); - for($j=0; $j< $steps2; ++$j) { - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - $steps = abs($xr-$xl)-$steps1-$steps2; - $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors); - $n = count($colors); - for($i=0; $i < $steps && $i < $n; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - break; - - case GRAD_RIGHT_REFLECTION: - $steps1 = round(0.7*abs($xr-$xl)); - $delta = $xr>=$xl ? 1 : -1; - - $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors); - $n = count($colors); - for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - $steps2 = max(1,round(0.08*abs($xr-$xl))); - $this->img->SetColor($to_color); - for($j=0; $j< $steps2; ++$j) { - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - - $from_color = $this->img->rgb->Color($from_color); - $adj = 1.4; - $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2])))); - $from_color = array(min(255,$from_color[0]+$m), - min(255,$from_color[1]+$m), min(255,$from_color[2]+$m)); - - $steps = abs($xr-$xl)-$steps1-$steps2; - $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors); - $n = count($colors); - for($i=0; $i < $steps && $i < $n; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - break; - - case GRAD_CENTER: - $steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2); - $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); - $dx = ($xr-$xl)/2; - $dy = ($yb-$yt)/2; - $x=$xl;$y=$yt;$x2=$xr;$y2=$yb; - $n = count($colors); - for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Rectangle($x,$y,$x2,$y2); - } - $this->img->Line($x,$y,$x2,$y2); - break; - - case GRAD_RAISED_PANEL: - // right to left - $steps1 = $xr-$xl; - $delta = $xr>=$xl ? 1 : -1; - $this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors); - $n = count($colors); - for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { - $this->img->current_color = $colors[$i]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - - // left to right - $xr -= 3; - $xl += 3; - $yb -= 3; - $yt += 3; - $steps2 = $xr-$xl; - $delta = $xr>=$xl ? 1 : -1; - for($x=$xl, $j=$steps2; $j >= 0; --$j) { - $this->img->current_color = $colors[$j]; - $this->img->Line($x,$yb,$x,$yt); - $x += $delta; - } - break; - - default: - JpGraphError::RaiseL(7001,$style); -//("Unknown gradient style (=$style)."); - break; - } - } - - // Fill a special case of a polygon with a flat bottom - // with a gradient. Can be used for filled line plots. - // Please note that this is NOT a generic gradient polygon fill - // routine. It assumes that the bottom is flat (like a drawing - // of a mountain) - function FilledFlatPolygon($pts,$from_color,$to_color) { - if( count($pts) == 0 ) return; - - $maxy=$pts[1]; - $miny=$pts[1]; - $n = count($pts) ; - for( $i=0, $idx=0; $i < $n; $i += 2) { - $x = round($pts[$i]); - $y = round($pts[$i+1]); - $miny = min($miny,$y); - $maxy = max($maxy,$y); - } - - $colors = array(); - $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors); - for($i=$miny, $idx=0; $i <= $maxy; ++$i ) { - $colmap[$i] = $colors[$idx++]; - } - - $n = count($pts)/2 ; - $idx = 0 ; - while( $idx < $n-1 ) { - $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1])); - $p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1])); - - // Find the largest rectangle we can fill - $y = max($p1[1],$p2[1]) ; - for($yy=$maxy; $yy > $y; --$yy) { - $this->img->current_color = $colmap[$yy]; - $this->img->Line($p1[0],$yy,$p2[0]-1,$yy); - } - - if( $p1[1] == $p2[1] ) continue; - - // Fill the rest using lines (slow...) - $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]); - $x1 = $p1[0]; - $x2 = $p2[0]; //-1; - $start = $y; - if( $p1[1] > $p2[1] ) { - while( $y >= $p2[1] ) { - $x1=$slope*($start-$y)+$p1[0]; - $this->img->current_color = $colmap[$y]; - $this->img->Line($x1,$y,$x2,$y); - --$y; - } - } - else { - while( $y >= $p1[1] ) { - $x2=$p2[0]+$slope*($start-$y); - $this->img->current_color = $colmap[$y]; - $this->img->Line($x1,$y,$x2,$y); - --$y; - } - } - } - } - -//--------------- -// PRIVATE METHODS - // Add to the image color map the necessary colors to do the transition - // between the two colors using $numcolors intermediate colors - function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) { - if( $arr_size==0 ) return; - // If color is given as text get it's corresponding r,g,b values - $from_color = $this->img->rgb->Color($from_color); - $to_color = $this->img->rgb->Color($to_color); - - $rdelta=($to_color[0]-$from_color[0])/$numcols; - $gdelta=($to_color[1]-$from_color[1])/$numcols; - $bdelta=($to_color[2]-$from_color[2])/$numcols; - $colorsperstep = $numcols/$arr_size; - $prevcolnum = -1; - $from_alpha = $from_color[3]; - $to_alpha = $to_color[3]; - $adelta = ( $to_alpha - $from_alpha ) / $numcols ; - for ($i=0; $i < $arr_size; ++$i) { - $colnum = floor($colorsperstep*$i); - if ( $colnum == $prevcolnum ) - $colors[$i] = $colidx; - else { - $r = floor($from_color[0] + $colnum*$rdelta); - $g = floor($from_color[1] + $colnum*$gdelta); - $b = floor($from_color[2] + $colnum*$bdelta); - $alpha = $from_alpha + $colnum*$adelta; - $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha); - $colors[$i] = $colidx; - } - $prevcolnum = $colnum; - } - } -} // Class - -?> +img = $img; + } + + + function SetNumColors($aNum) { + $this->numcolors=$aNum; + } + //--------------- + // PUBLIC METHODS + // Produce a gradient filled rectangle with a smooth transition between + // two colors. + // ($xl,$yt) Top left corner + // ($xr,$yb) Bottom right + // $from_color Starting color in gradient + // $to_color End color in the gradient + // $style Which way is the gradient oriented? + function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) { + $this->img->SetLineWeight(1); + switch( $style ) { + case GRAD_VER: + $steps = ceil(abs($xr-$xl)+1); + $delta = $xr>=$xl ? 1 : -1; + $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); + for( $i=0, $x=$xl; $i < $steps; ++$i ) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yt,$x,$yb); + $x += $delta; + } + break; + + case GRAD_HOR: + $steps = ceil(abs($yb-$yt)+1); + $delta = $yb >= $yt ? 1 : -1; + $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); + for($i=0,$y=$yt; $i < $steps; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($xl,$y,$xr,$y); + $y += $delta; + } + break; + + case GRAD_MIDHOR: + $steps = ceil(abs($yb-$yt)/2); + $delta = $yb >= $yt ? 1 : -1; + $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); + for($y=$yt, $i=0; $i < $steps; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($xl,$y,$xr,$y); + $y += $delta; + } + --$i; + if( abs($yb-$yt) % 2 == 1 ) { + --$steps; + } + for($j=0; $j < $steps; ++$j, --$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($xl,$y,$xr,$y); + $y += $delta; + } + $this->img->Line($xl,$y,$xr,$y); + break; + + case GRAD_MIDVER: + $steps = ceil(abs($xr-$xl)/2); + $delta = $xr>=$xl ? 1 : -1; + $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); + for($x=$xl, $i=0; $i < $steps; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + --$i; + if( abs($xr-$xl) % 2 == 1 ) { + --$steps; + } + for($j=0; $j < $steps; ++$j, --$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + $this->img->Line($x,$yb,$x,$yt); + break; + + case GRAD_WIDE_MIDVER: + $diff = ceil(abs($xr-$xl)); + $steps = floor(abs($diff)/3); + $firststep = $diff - 2*$steps ; + $delta = $xr >= $xl ? 1 : -1; + $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors); + for($x=$xl, $i=0; $i < $firststep; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + --$i; + $this->img->current_color = $colors[$i]; + for($j=0; $j< $steps; ++$j) { + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + + for($j=0; $j < $steps; ++$j, --$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + break; + + case GRAD_WIDE_MIDHOR: + $diff = ceil(abs($yb-$yt)); + $steps = floor(abs($diff)/3); + $firststep = $diff - 2*$steps ; + $delta = $yb >= $yt? 1 : -1; + $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors); + for($y=$yt, $i=0; $i < $firststep; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($xl,$y,$xr,$y); + $y += $delta; + } + --$i; + $this->img->current_color = $colors[$i]; + for($j=0; $j < $steps; ++$j) { + $this->img->Line($xl,$y,$xr,$y); + $y += $delta; + } + for($j=0; $j < $steps; ++$j, --$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($xl,$y,$xr,$y); + $y += $delta; + } + break; + + case GRAD_LEFT_REFLECTION: + $steps1 = ceil(0.3*abs($xr-$xl)); + $delta = $xr>=$xl ? 1 : -1; + + $from_color = $this->img->rgb->Color($from_color); + $adj = 1.4; + $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2])))); + $from_color2 = array(min(255,$from_color[0]+$m), + min(255,$from_color[1]+$m), min(255,$from_color[2]+$m)); + + $this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors); + $n = count($colors); + for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + $steps2 = max(1,ceil(0.08*abs($xr-$xl))); + $this->img->SetColor($to_color); + for($j=0; $j< $steps2; ++$j) { + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + $steps = abs($xr-$xl)-$steps1-$steps2; + $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors); + $n = count($colors); + for($i=0; $i < $steps && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + break; + + case GRAD_RIGHT_REFLECTION: + $steps1 = ceil(0.7*abs($xr-$xl)); + $delta = $xr>=$xl ? 1 : -1; + + $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors); + $n = count($colors); + for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + $steps2 = max(1,ceil(0.08*abs($xr-$xl))); + $this->img->SetColor($to_color); + for($j=0; $j< $steps2; ++$j) { + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + + $from_color = $this->img->rgb->Color($from_color); + $adj = 1.4; + $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2])))); + $from_color = array(min(255,$from_color[0]+$m), + min(255,$from_color[1]+$m), min(255,$from_color[2]+$m)); + + $steps = abs($xr-$xl)-$steps1-$steps2; + $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors); + $n = count($colors); + for($i=0; $i < $steps && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + break; + + case GRAD_CENTER: + $steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2); + $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); + $dx = ($xr-$xl)/2; + $dy = ($yb-$yt)/2; + $x=$xl;$y=$yt;$x2=$xr;$y2=$yb; + $n = count($colors); + for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Rectangle($x,$y,$x2,$y2); + } + $this->img->Line($x,$y,$x2,$y2); + break; + + case GRAD_RAISED_PANEL: + // right to left + $steps1 = $xr-$xl; + $delta = $xr>=$xl ? 1 : -1; + $this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors); + $n = count($colors); + for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + + // left to right + $xr -= 3; + $xl += 3; + $yb -= 3; + $yt += 3; + $steps2 = $xr-$xl; + $delta = $xr>=$xl ? 1 : -1; + for($x=$xl, $j=$steps2; $j >= 0; --$j) { + $this->img->current_color = $colors[$j]; + $this->img->Line($x,$yb,$x,$yt); + $x += $delta; + } + break; + + case GRAD_DIAGONAL: + // use the longer dimension to determine the required number of steps. + // first loop draws from one corner to the mid-diagonal and the second + // loop draws from the mid-diagonal to the opposing corner. + if($xr-$xl > $yb - $yt) { + // width is greater than height -> use x-dimension for steps + $steps = $xr-$xl; + $delta = $xr>=$xl ? 1 : -1; + $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors); + $n = count($colors); + + for($x=$xl, $i=0; $i < $steps && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $y = $yt+($i/$steps)*($yb-$yt)*$delta; + $this->img->Line($x,$yt,$xl,$y); + $x += $delta; + } + + for($x=$xl, $i = 0; $i < $steps && $i < $n; ++$i) { + $this->img->current_color = $colors[$steps+$i]; + $y = $yt+($i/$steps)*($yb-$yt)*$delta; + $this->img->Line($x,$yb,$xr,$y); + $x += $delta; + } + } else { + // height is greater than width -> use y-dimension for steps + $steps = $yb-$yt; + $delta = $yb>=$yt ? 1 : -1; + $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors); + $n = count($colors); + + for($y=$yt, $i=0; $i < $steps && $i < $n; ++$i) { + $this->img->current_color = $colors[$i]; + $x = $xl+($i/$steps)*($xr-$xl)*$delta; + $this->img->Line($x,$yt,$xl,$y); + $y += $delta; + } + + for($y=$yt, $i = 0; $i < $steps && $i < $n; ++$i) { + $this->img->current_color = $colors[$steps+$i]; + $x = $xl+($i/$steps)*($xr-$xl)*$delta; + $this->img->Line($x,$yb,$xr,$y); + $x += $delta; + } + + } + break; + + default: + JpGraphError::RaiseL(7001,$style); + //("Unknown gradient style (=$style)."); + break; + } + } + + // Fill a special case of a polygon with a flat bottom + // with a gradient. Can be used for filled line plots. + // Please note that this is NOT a generic gradient polygon fill + // routine. It assumes that the bottom is flat (like a drawing + // of a mountain) + function FilledFlatPolygon($pts,$from_color,$to_color) { + if( count($pts) == 0 ) return; + + $maxy=$pts[1]; + $miny=$pts[1]; + $n = count($pts) ; + for( $i=0, $idx=0; $i < $n; $i += 2) { + $x = round($pts[$i]); + $y = round($pts[$i+1]); + $miny = min($miny,$y); + $maxy = max($maxy,$y); + } + + $colors = array(); + $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors); + for($i=$miny, $idx=0; $i <= $maxy; ++$i ) { + $colmap[$i] = $colors[$idx++]; + } + + $n = count($pts)/2 ; + $idx = 0 ; + while( $idx < $n-1 ) { + $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1])); + $p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1])); + + // Find the largest rectangle we can fill + $y = max($p1[1],$p2[1]) ; + for($yy=$maxy; $yy > $y; --$yy) { + $this->img->current_color = $colmap[$yy]; + $this->img->Line($p1[0],$yy,$p2[0]-1,$yy); + } + + if( $p1[1] == $p2[1] ) { + continue; + } + + // Fill the rest using lines (slow...) + $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]); + $x1 = $p1[0]; + $x2 = $p2[0]-1; + $start = $y; + if( $p1[1] > $p2[1] ) { + while( $y >= $p2[1] ) { + $x1=$slope*($start-$y)+$p1[0]; + $this->img->current_color = $colmap[$y]; + $this->img->Line($x1,$y,$x2,$y); + --$y; + } + } + else { + while( $y >= $p1[1] ) { + $x2=$p2[0]+$slope*($start-$y); + $this->img->current_color = $colmap[$y]; + $this->img->Line($x1,$y,$x2,$y); + --$y; + } + } + } + } + + //--------------- + // PRIVATE METHODS + // Add to the image color map the necessary colors to do the transition + // between the two colors using $numcolors intermediate colors + function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) { + if( $arr_size==0 ) { + return; + } + + // If color is given as text get it's corresponding r,g,b values + $from_color = $this->img->rgb->Color($from_color); + $to_color = $this->img->rgb->Color($to_color); + + $rdelta=($to_color[0]-$from_color[0])/$numcols; + $gdelta=($to_color[1]-$from_color[1])/$numcols; + $bdelta=($to_color[2]-$from_color[2])/$numcols; + $colorsperstep = $numcols/$arr_size; + $prevcolnum = -1; + $from_alpha = floatval($from_color[3]); + $to_alpha = floatval($to_color[3]); + $adelta = ( $to_alpha - $from_alpha ) / $numcols ; + for ($i=0; $i < $arr_size; ++$i) { + $colnum = floor($colorsperstep*$i); + if ( $colnum == $prevcolnum ) { + $colors[$i] = $colidx; + } + else { + $r = floor($from_color[0] + $colnum*$rdelta); + $g = floor($from_color[1] + $colnum*$gdelta); + $b = floor($from_color[2] + $colnum*$bdelta); + $alpha = $from_alpha + $colnum*$adelta; + $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha); + $colors[$i] = $colidx; + } + $prevcolnum = $colnum; + } + } +} // Class + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_iconplot.php b/web/public_php/admin/jpgraph/jpgraph_iconplot.php index 4e25b55de..584f80176 100644 --- a/web/public_php/admin/jpgraph/jpgraph_iconplot.php +++ b/web/public_php/admin/jpgraph/jpgraph_iconplot.php @@ -1,190 +1,190 @@ -iFile = $aFile; - $this->iX=$aX; - $this->iY=$aY; - $this->iScale= $aScale; - if( $aMix < 0 || $aMix > 100 ) { - JpGraphError::RaiseL(8001); //('Mix value for icon must be between 0 and 100.'); - } - $this->iMix = $aMix ; - } - - function CreateFromString($aStr) { - $this->iImgString = $aStr; - } - - function SetCountryFlag($aFlag,$aX=0,$aY=0,$aScale=1.0,$aMix=100,$aStdSize=3) { - $this->iCountryFlag = $aFlag; - $this->iX=$aX; - $this->iY=$aY; - $this->iScale= $aScale; - if( $aMix < 0 || $aMix > 100 ) { - JpGraphError::RaiseL(8001);//'Mix value for icon must be between 0 and 100.'); - } - $this->iMix = $aMix; - $this->iCountryStdSize = $aStdSize; - } - - function SetPos($aX,$aY) { - $this->iX=$aX; - $this->iY=$aY; - } - - function SetScalePos($aX,$aY) { - $this->iScalePosX = $aX; - $this->iScalePosY = $aY; - } - - function SetScale($aScale) { - $this->iScale = $aScale; - } - - function SetMix($aMix) { - if( $aMix < 0 || $aMix > 100 ) { - JpGraphError::RaiseL(8001);//('Mix value for icon must be between 0 and 100.'); - } - $this->iMix = $aMix ; - } - - function SetAnchor($aXAnchor='left',$aYAnchor='center') { - if( !in_array($aXAnchor,$this->iAnchors) || - !in_array($aYAnchor,$this->iAnchors) ) { - JpGraphError::RaiseL(8002);//("Anchor position for icons must be one of 'top', 'bottom', 'left', 'right' or 'center'"); - } - $this->iHorAnchor=$aXAnchor; - $this->iVertAnchor=$aYAnchor; - } - - function PreStrokeAdjust($aGraph) { - // Nothing to do ... - } - - function DoLegend($aGraph) { - // Nothing to do ... - } - - function Max() { - return array(false,false); - } - - - // The next four function are framework function tht gets called - // from Gantt and is not menaiungfull in the context of Icons but - // they must be implemented to avoid errors. - function GetMaxDate() { return false; } - function GetMinDate() { return false; } - function GetLineNbr() { return 0; } - function GetAbsHeight() {return 0; } - - - function Min() { - return array(false,false); - } - - function StrokeMargin(&$aImg) { - return true; - } - - function Stroke(&$aImg,$axscale,$ayscale) { - $this->StrokeWithScale($aImg,$axscale,$ayscale); - } - - function StrokeWithScale(&$aImg,$axscale,$ayscale) { - if( $this->iScalePosX === null || - $this->iScalePosY === null ) { - $this->_Stroke($aImg); - } - else { - $this->_Stroke($aImg, - round($axscale->Translate($this->iScalePosX)), - round($ayscale->Translate($this->iScalePosY))); - } - } - - function GetWidthHeight() { - $dummy=0; - return $this->_Stroke($dummy,null,null,true); - } - - function _Stroke(&$aImg,$x=null,$y=null,$aReturnWidthHeight=false) { - if( $this->iFile != '' && $this->iCountryFlag != '' ) { - JpGraphError::RaiseL(8003);//('It is not possible to specify both an image file and a country flag for the same icon.'); - } - if( $this->iFile != '' ) { - $gdimg = Graph::LoadBkgImage('',$this->iFile); - } - elseif( $this->iImgString != '') { - $gdimg = Image::CreateFromString($this->iImgString); - } - else { - if( ! class_exists('FlagImages') ) { - JpGraphError::RaiseL(8004);//('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.'); - } - $fobj = new FlagImages($this->iCountryStdSize); - $dummy=''; - $gdimg = $fobj->GetImgByName($this->iCountryFlag,$dummy); - } - - $iconw = imagesx($gdimg); - $iconh = imagesy($gdimg); - - if( $aReturnWidthHeight ) { - return array(round($iconw*$this->iScale),round($iconh*$this->iScale)); - } - - if( $x !== null && $y !== null ) { - $this->iX = $x; $this->iY = $y; - } - if( $this->iX >= 0 && $this->iX <= 1.0 ) { - $w = imagesx($aImg->img); - $this->iX = round($w*$this->iX); - } - if( $this->iY >= 0 && $this->iY <= 1.0 ) { - $h = imagesy($aImg->img); - $this->iY = round($h*$this->iY); - } - - if( $this->iHorAnchor == 'center' ) - $this->iX -= round($iconw*$this->iScale/2); - if( $this->iHorAnchor == 'right' ) - $this->iX -= round($iconw*$this->iScale); - if( $this->iVertAnchor == 'center' ) - $this->iY -= round($iconh*$this->iScale/2); - if( $this->iVertAnchor == 'bottom' ) - $this->iY -= round($iconh*$this->iScale); - - $aImg->CopyMerge($gdimg,$this->iX,$this->iY,0,0, - round($iconw*$this->iScale),round($iconh*$this->iScale), - $iconw,$iconh, - $this->iMix); - } -} - -?> +iFile = $aFile; + $this->iX=$aX; + $this->iY=$aY; + $this->iScale= $aScale; + if( $aMix < 0 || $aMix > 100 ) { + JpGraphError::RaiseL(8001); //('Mix value for icon must be between 0 and 100.'); + } + $this->iMix = $aMix ; + } + + function SetCountryFlag($aFlag,$aX=0,$aY=0,$aScale=1.0,$aMix=100,$aStdSize=3) { + $this->iCountryFlag = $aFlag; + $this->iX=$aX; + $this->iY=$aY; + $this->iScale= $aScale; + if( $aMix < 0 || $aMix > 100 ) { + JpGraphError::RaiseL(8001);//'Mix value for icon must be between 0 and 100.'); + } + $this->iMix = $aMix; + $this->iCountryStdSize = $aStdSize; + } + + function SetPos($aX,$aY) { + $this->iX=$aX; + $this->iY=$aY; + } + + function CreateFromString($aStr) { + $this->iImgString = $aStr; + } + + function SetScalePos($aX,$aY) { + $this->iScalePosX = $aX; + $this->iScalePosY = $aY; + } + + function SetScale($aScale) { + $this->iScale = $aScale; + } + + function SetMix($aMix) { + if( $aMix < 0 || $aMix > 100 ) { + JpGraphError::RaiseL(8001);//('Mix value for icon must be between 0 and 100.'); + } + $this->iMix = $aMix ; + } + + function SetAnchor($aXAnchor='left',$aYAnchor='center') { + if( !in_array($aXAnchor,$this->iAnchors) || + !in_array($aYAnchor,$this->iAnchors) ) { + JpGraphError::RaiseL(8002);//("Anchor position for icons must be one of 'top', 'bottom', 'left', 'right' or 'center'"); + } + $this->iHorAnchor=$aXAnchor; + $this->iVertAnchor=$aYAnchor; + } + + function PreStrokeAdjust($aGraph) { + // Nothing to do ... + } + + function DoLegend($aGraph) { + // Nothing to do ... + } + + function Max() { + return array(false,false); + } + + + // The next four function are framework function tht gets called + // from Gantt and is not menaiungfull in the context of Icons but + // they must be implemented to avoid errors. + function GetMaxDate() { return false; } + function GetMinDate() { return false; } + function GetLineNbr() { return 0; } + function GetAbsHeight() {return 0; } + + + function Min() { + return array(false,false); + } + + function StrokeMargin(&$aImg) { + return true; + } + + function Stroke($aImg,$axscale=null,$ayscale=null) { + $this->StrokeWithScale($aImg,$axscale,$ayscale); + } + + function StrokeWithScale($aImg,$axscale,$ayscale) { + if( $this->iScalePosX === null || $this->iScalePosY === null || + $axscale === null || $ayscale === null ) { + $this->_Stroke($aImg); + } + else { + $this->_Stroke($aImg, + round($axscale->Translate($this->iScalePosX)), + round($ayscale->Translate($this->iScalePosY))); + } + } + + function GetWidthHeight() { + $dummy=0; + return $this->_Stroke($dummy,null,null,true); + } + + function _Stroke($aImg,$x=null,$y=null,$aReturnWidthHeight=false) { + if( $this->iFile != '' && $this->iCountryFlag != '' ) { + JpGraphError::RaiseL(8003);//('It is not possible to specify both an image file and a country flag for the same icon.'); + } + if( $this->iFile != '' ) { + $gdimg = Graph::LoadBkgImage('',$this->iFile); + } + elseif( $this->iImgString != '') { + $gdimg = Image::CreateFromString($this->iImgString); + } + + else { + if( ! class_exists('FlagImages',false) ) { + JpGraphError::RaiseL(8004);//('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.'); + } + $fobj = new FlagImages($this->iCountryStdSize); + $dummy=''; + $gdimg = $fobj->GetImgByName($this->iCountryFlag,$dummy); + } + + $iconw = imagesx($gdimg); + $iconh = imagesy($gdimg); + + if( $aReturnWidthHeight ) { + return array(round($iconw*$this->iScale),round($iconh*$this->iScale)); + } + + if( $x !== null && $y !== null ) { + $this->iX = $x; $this->iY = $y; + } + if( $this->iX >= 0 && $this->iX <= 1.0 ) { + $w = imagesx($aImg->img); + $this->iX = round($w*$this->iX); + } + if( $this->iY >= 0 && $this->iY <= 1.0 ) { + $h = imagesy($aImg->img); + $this->iY = round($h*$this->iY); + } + + if( $this->iHorAnchor == 'center' ) + $this->iX -= round($iconw*$this->iScale/2); + if( $this->iHorAnchor == 'right' ) + $this->iX -= round($iconw*$this->iScale); + if( $this->iVertAnchor == 'center' ) + $this->iY -= round($iconh*$this->iScale/2); + if( $this->iVertAnchor == 'bottom' ) + $this->iY -= round($iconh*$this->iScale); + + $aImg->CopyMerge($gdimg,$this->iX,$this->iY,0,0, + round($iconw*$this->iScale),round($iconh*$this->iScale), + $iconw,$iconh, + $this->iMix); + } +} + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_imgtrans.php b/web/public_php/admin/jpgraph/jpgraph_imgtrans.php index c2f260b26..411a7811f 100644 --- a/web/public_php/admin/jpgraph/jpgraph_imgtrans.php +++ b/web/public_php/admin/jpgraph/jpgraph_imgtrans.php @@ -1,224 +1,223 @@ -gdImg = $aGdImg; - } - - // -------------------------------------------------------------------- - // _TransVert3D() and _TransHor3D() are helper methods to - // Skew3D(). - // -------------------------------------------------------------------- - function _TransVert3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_DOWN,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) { - - - // Parameter check - if( $aHorizonPos < 0 || $aHorizonPos > 1.0 ) { - JpGraphError::RaiseL(9001); -//("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1."); - } - - $w = imagesx($aGdImg); - $h = imagesy($aGdImg); - - // Create new image - $ww = $w; - if( $aMinSize ) - $hh = ceil($h * $aHorizon / ($aSkewDist+$h)); - else - $hh = $h; - - $newgdh = imagecreatetruecolor($ww,$hh); - $crgb = new RGB( $newgdh ); - $fillColor = $crgb->Allocate($aFillColor); - imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor); - - if( $aBorder ) { - $colidx = $crgb->Allocate($aBorder); - imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx); - } - - $mid = round($w * $aHorizonPos); - - $last=$h; - for($y=0; $y < $h; ++$y) { - - $yp = $h-$y-1; - $yt = floor($yp * $aHorizon / ($aSkewDist + $yp)); - - if( !$aQuality ) { - if( $last <= $yt ) continue ; - $last = $yt; - } - - for($x=0; $x < $w; ++$x) { - $xt = ($x-$mid) * $aSkewDist / ($aSkewDist + $yp); - if( $aDir == SKEW3D_UP ) - $rgb = imagecolorat($aGdImg,$x,$h-$y-1); - else - $rgb = imagecolorat($aGdImg,$x,$y); - $r = ($rgb >> 16) & 0xFF; - $g = ($rgb >> 8) & 0xFF; - $b = $rgb & 0xFF; - $colidx = imagecolorallocate($newgdh,$r,$g,$b); - $xt = round($xt+$mid); - if( $aDir == SKEW3D_UP ) { - $syt = $yt; - } - else { - $syt = $hh-$yt-1; - } - - if( !empty($set[$yt]) ) { - $nrgb = imagecolorat($newgdh,$xt,$syt); - $nr = ($nrgb >> 16) & 0xFF; - $ng = ($nrgb >> 8) & 0xFF; - $nb = $nrgb & 0xFF; - $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2), - floor(($g+$ng)/2),floor(($b+$nb)/2)); - } - - imagesetpixel($newgdh,$xt,$syt,$colidx); - } - - $set[$yt] = true; - } - - return $newgdh; - } - - // -------------------------------------------------------------------- - // _TransVert3D() and _TransHor3D() are helper methods to - // Skew3D(). - // -------------------------------------------------------------------- - function _TransHor3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_LEFT,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) { - - $w = imagesx($aGdImg); - $h = imagesy($aGdImg); - - // Create new image - $hh = $h; - if( $aMinSize ) - $ww = ceil($w * $aHorizon / ($aSkewDist+$w)); - else - $ww = $w; - - $newgdh = imagecreatetruecolor($ww,$hh); - $crgb = new RGB( $newgdh ); - $fillColor = $crgb->Allocate($aFillColor); - imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor); - - if( $aBorder ) { - $colidx = $crgb->Allocate($aBorder); - imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx); - } - - $mid = round($h * $aHorizonPos); - - $last = -1; - for($x=0; $x < $w-1; ++$x) { - $xt = floor($x * $aHorizon / ($aSkewDist + $x)); - if( !$aQuality ) { - if( $last >= $xt ) continue ; - $last = $xt; - } - - for($y=0; $y < $h; ++$y) { - $yp = $h-$y-1; - $yt = ($yp-$mid) * $aSkewDist / ($aSkewDist + $x); - - if( $aDir == SKEW3D_RIGHT ) - $rgb = imagecolorat($aGdImg,$w-$x-1,$y); - else - $rgb = imagecolorat($aGdImg,$x,$y); - $r = ($rgb >> 16) & 0xFF; - $g = ($rgb >> 8) & 0xFF; - $b = $rgb & 0xFF; - $colidx = imagecolorallocate($newgdh,$r,$g,$b); - $yt = floor($hh-$yt-$mid-1); - if( $aDir == SKEW3D_RIGHT ) { - $sxt = $ww-$xt-1; - } - else - $sxt = $xt ; - - if( !empty($set[$xt]) ) { - $nrgb = imagecolorat($newgdh,$sxt,$yt); - $nr = ($nrgb >> 16) & 0xFF; - $ng = ($nrgb >> 8) & 0xFF; - $nb = $nrgb & 0xFF; - $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2), - floor(($g+$ng)/2),floor(($b+$nb)/2)); - } - imagesetpixel($newgdh,$sxt,$yt,$colidx); - } - - $set[$xt] = true; - } - - return $newgdh; - } - - // -------------------------------------------------------------------- - // Skew image for the apperance of a 3D effect - // This transforms an image into a 3D-skewed version - // of the image. The transformation is specified by giving the height - // of the artificial horizon and specifying a "skew" factor which - // is the distance on the horizon line between the point of - // convergence and perspective line. - // - // The function returns the GD handle of the transformed image - // leaving the original image untouched. - // - // Parameters: - // * $aGdImg, GD handle to the image to be transformed - // * $aHorizon, Distance to the horizon - // * $aSkewDist, Distance from the horizon point of convergence - // on the horizon line to the perspective points. A larger - // value will fore-shorten the image more - // * $aDir, parameter specifies type of convergence. This of this - // as the walls in a room you are looking at. This specifies if the - // image should be applied on the left,right,top or bottom walls. - // * $aMinSize, true=make the new image just as big as needed, - // false = keep the image the same size as the original image - // * $aFillColor, Background fill color in the image - // * $aHiQuality, true=performa some interpolation that improves - // the image quality but at the expense of performace. Enabling - // high quality will have a dramatic effect on the time it takes - // to transform an image. - // * $aBorder, if set to anything besides false this will draw a - // a border of the speciied color around the image - // -------------------------------------------------------------------- - function Skew3D($aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) { - return $this->_Skew3D($this->gdImg,$aHorizon,$aSkewDist,$aDir,$aHiQuality, - $aMinSize,$aFillColor,$aBorder); - } - - function _Skew3D($aGdImg,$aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) { - if( $aDir == SKEW3D_DOWN || $aDir == SKEW3D_UP ) - return $this->_TransVert3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder); - else - return $this->_TransHor3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder); - - } - -} - - -?> \ No newline at end of file +gdImg = $aGdImg; + } + + // -------------------------------------------------------------------- + // _TransVert3D() and _TransHor3D() are helper methods to + // Skew3D(). + // -------------------------------------------------------------------- + function _TransVert3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_DOWN,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) { + + + // Parameter check + if( $aHorizonPos < 0 || $aHorizonPos > 1.0 ) { + JpGraphError::RaiseL(9001); + //("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1."); + } + + $w = imagesx($aGdImg); + $h = imagesy($aGdImg); + + // Create new image + $ww = $w; + if( $aMinSize ) + $hh = ceil($h * $aHorizon / ($aSkewDist+$h)); + else + $hh = $h; + + $newgdh = imagecreatetruecolor($ww,$hh); + $crgb = new RGB( $newgdh ); + $fillColor = $crgb->Allocate($aFillColor); + imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor); + + if( $aBorder ) { + $colidx = $crgb->Allocate($aBorder); + imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx); + } + + $mid = round($w * $aHorizonPos); + + $last=$h; + for($y=0; $y < $h; ++$y) { + + $yp = $h-$y-1; + $yt = floor($yp * $aHorizon / ($aSkewDist + $yp)); + + if( !$aQuality ) { + if( $last <= $yt ) continue ; + $last = $yt; + } + + for($x=0; $x < $w; ++$x) { + $xt = ($x-$mid) * $aSkewDist / ($aSkewDist + $yp); + if( $aDir == SKEW3D_UP ) + $rgb = imagecolorat($aGdImg,$x,$h-$y-1); + else + $rgb = imagecolorat($aGdImg,$x,$y); + $r = ($rgb >> 16) & 0xFF; + $g = ($rgb >> 8) & 0xFF; + $b = $rgb & 0xFF; + $colidx = imagecolorallocate($newgdh,$r,$g,$b); + $xt = round($xt+$mid); + if( $aDir == SKEW3D_UP ) { + $syt = $yt; + } + else { + $syt = $hh-$yt-1; + } + + if( !empty($set[$yt]) ) { + $nrgb = imagecolorat($newgdh,$xt,$syt); + $nr = ($nrgb >> 16) & 0xFF; + $ng = ($nrgb >> 8) & 0xFF; + $nb = $nrgb & 0xFF; + $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2), + floor(($g+$ng)/2),floor(($b+$nb)/2)); + } + + imagesetpixel($newgdh,$xt,$syt,$colidx); + } + + $set[$yt] = true; + } + + return $newgdh; + } + + // -------------------------------------------------------------------- + // _TransVert3D() and _TransHor3D() are helper methods to + // Skew3D(). + // -------------------------------------------------------------------- + function _TransHor3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_LEFT,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) { + + $w = imagesx($aGdImg); + $h = imagesy($aGdImg); + + // Create new image + $hh = $h; + if( $aMinSize ) + $ww = ceil($w * $aHorizon / ($aSkewDist+$w)); + else + $ww = $w; + + $newgdh = imagecreatetruecolor($ww,$hh); + $crgb = new RGB( $newgdh ); + $fillColor = $crgb->Allocate($aFillColor); + imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor); + + if( $aBorder ) { + $colidx = $crgb->Allocate($aBorder); + imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx); + } + + $mid = round($h * $aHorizonPos); + + $last = -1; + for($x=0; $x < $w-1; ++$x) { + $xt = floor($x * $aHorizon / ($aSkewDist + $x)); + if( !$aQuality ) { + if( $last >= $xt ) continue ; + $last = $xt; + } + + for($y=0; $y < $h; ++$y) { + $yp = $h-$y-1; + $yt = ($yp-$mid) * $aSkewDist / ($aSkewDist + $x); + + if( $aDir == SKEW3D_RIGHT ) + $rgb = imagecolorat($aGdImg,$w-$x-1,$y); + else + $rgb = imagecolorat($aGdImg,$x,$y); + $r = ($rgb >> 16) & 0xFF; + $g = ($rgb >> 8) & 0xFF; + $b = $rgb & 0xFF; + $colidx = imagecolorallocate($newgdh,$r,$g,$b); + $yt = floor($hh-$yt-$mid-1); + if( $aDir == SKEW3D_RIGHT ) { + $sxt = $ww-$xt-1; + } + else + $sxt = $xt ; + + if( !empty($set[$xt]) ) { + $nrgb = imagecolorat($newgdh,$sxt,$yt); + $nr = ($nrgb >> 16) & 0xFF; + $ng = ($nrgb >> 8) & 0xFF; + $nb = $nrgb & 0xFF; + $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2), + floor(($g+$ng)/2),floor(($b+$nb)/2)); + } + imagesetpixel($newgdh,$sxt,$yt,$colidx); + } + + $set[$xt] = true; + } + + return $newgdh; + } + + // -------------------------------------------------------------------- + // Skew image for the apperance of a 3D effect + // This transforms an image into a 3D-skewed version + // of the image. The transformation is specified by giving the height + // of the artificial horizon and specifying a "skew" factor which + // is the distance on the horizon line between the point of + // convergence and perspective line. + // + // The function returns the GD handle of the transformed image + // leaving the original image untouched. + // + // Parameters: + // * $aGdImg, GD handle to the image to be transformed + // * $aHorizon, Distance to the horizon + // * $aSkewDist, Distance from the horizon point of convergence + // on the horizon line to the perspective points. A larger + // value will fore-shorten the image more + // * $aDir, parameter specifies type of convergence. This of this + // as the walls in a room you are looking at. This specifies if the + // image should be applied on the left,right,top or bottom walls. + // * $aMinSize, true=make the new image just as big as needed, + // false = keep the image the same size as the original image + // * $aFillColor, Background fill color in the image + // * $aHiQuality, true=performa some interpolation that improves + // the image quality but at the expense of performace. Enabling + // high quality will have a dramatic effect on the time it takes + // to transform an image. + // * $aBorder, if set to anything besides false this will draw a + // a border of the speciied color around the image + // -------------------------------------------------------------------- + function Skew3D($aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) { + return $this->_Skew3D($this->gdImg,$aHorizon,$aSkewDist,$aDir,$aHiQuality, + $aMinSize,$aFillColor,$aBorder); + } + + function _Skew3D($aGdImg,$aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) { + if( $aDir == SKEW3D_DOWN || $aDir == SKEW3D_UP ) + return $this->_TransVert3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder); + else + return $this->_TransHor3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder); + + } + +} + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_led.php b/web/public_php/admin/jpgraph/jpgraph_led.php new file mode 100644 index 000000000..83bb2692a --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_led.php @@ -0,0 +1,311 @@ + array('red','darkred:0.9','red:0.3'),// 0 + LEDC_GREEN => array('green','darkgreen','green:0.3'),// 1 + LEDC_BLUE => array('lightblue:0.9','darkblue:0.85','darkblue:0.7'),// 2 + LEDC_YELLOW => array('yellow','yellow:0.4','yellow:0.3'),// 3 + LEDC_GRAY => array('gray:1.4','darkgray:0.85','darkgray:0.7'), + LEDC_CHOCOLATE => array('chocolate','chocolate:0.7','chocolate:0.5'), + LEDC_PERU => array('peru:0.95','peru:0.6','peru:0.5'), + LEDC_GOLDENROD => array('goldenrod','goldenrod:0.6','goldenrod:0.5'), + LEDC_KHAKI => array('khaki:0.7','khaki:0.4','khaki:0.3'), + LEDC_OLIVE => array('#808000','#808000:0.7','#808000:0.6'), + LEDC_LIMEGREEN => array('limegreen:0.9','limegreen:0.5','limegreen:0.4'), + LEDC_FORESTGREEN => array('forestgreen','forestgreen:0.7','forestgreen:0.5'), + LEDC_TEAL => array('teal','teal:0.7','teal:0.5'), + LEDC_STEELBLUE => array('steelblue','steelblue:0.65','steelblue:0.5'), + LEDC_NAVY => array('navy:1.3','navy:0.95','navy:0.8'),//14 + LEDC_INVERTGRAY => array('darkgray','lightgray:1.5','white')//15 + ), + + /* Each line of the character is encoded as a 4 bit value + 0 ____ + 1 ___x + 2 __x_ + 3 __xx + 4 _x__ + 5 _x_x + 6 _xx_ + 7 _xxx + 8 x___ + 9 x__x + 10 x_x_ + 11 x_xx + 12 xx__ + 13 xx_x + 14 xxx_ + 15 xxxx + */ + + $iLEDSpec = array( + 0 => array(6,9,11,15,13,9,6), + 1 => array(2,6,10,2,2,2,2), + 2 => array(6,9,1,2,4,8,15), + 3 => array(6,9,1,6,1,9,6), + 4 => array(1,3,5,9,15,1,1), + 5 => array(15,8,8,14,1,9,6), + 6 => array(6,8,8,14,9,9,6), + 7 => array(15,1,1,2,4,4,4), + 8 => array(6,9,9,6,9,9,6), + 9 => array(6,9,9,7,1,1,6), + '!' => array(4,4,4,4,4,0,4), + '?' => array(6,9,1,2,2,0,2), + '#' => array(0,9,15,9,15,9,0), + '@' => array(6,9,11,11,10,9,6), + '-' => array(0,0,0,15,0,0,0), + '_' => array(0,0,0,0,0,0,15), + '=' => array(0,0,15,0,15,0,0), + '+' => array(0,0,4,14,4,0,0), + '|' => array(4,4,4,4,4,4,4), //vertical line, used for simulate rus 'Ы' + ',' => array(0,0,0,0,0,12,4), + '.' => array(0,0,0,0,0,12,12), + ':' => array(12,12,0,0,0,12,12), + ';' => array(12,12,0,0,0,12,4), + '[' => array(3,2,2,2,2,2,3), + ']' => array(12,4,4,4,4,4,12), + '(' => array(1,2,2,2,2,2,1), + ')' => array(8,4,4,4,4,4,8), + '{' => array(3,2,2,6,2,2,3), + '}' => array(12,4,4,6,4,4,12), + '<' => array(1,2,4,8,4,2,1), + '>' => array(8,4,2,1,2,4,8), + '*' => array(9,6,15,6,9,0,0), + '"' => array(10,10,0,0,0,0,0), + '\'' => array(4,4,0,0,0,0,0), + '`' => array(4,2,0,0,0,0,0), + '~' => array(13,11,0,0,0,0,0), + '^' => array(4,10,0,0,0,0,0), + '\\' => array(8,8,4,6,2,1,1), + '/' => array(1,1,2,6,4,8,8), + '%' => array(1,9,2,6,4,9,8), + '&' => array(0,4,10,4,11,10,5), + '$' => array(2,7,8,6,1,14,4), + ' ' => array(0,0,0,0,0,0,0), + '•' => array(0,0,6,6,0,0,0), //149 + '°' => array(14,10,14,0,0,0,0), //176 + '†' => array(4,4,14,4,4,4,4), //134 + '‡' => array(4,4,14,4,14,4,4), //135 + '±' => array(0,4,14,4,0,14,0), //177 + '‰' => array(0,4,2,15,2,4,0), //137 show right arrow + 'â„¢' => array(0,2,4,15,4,2,0), //156 show left arrow + 'ÐŽ' => array(0,0,8,8,0,0,0), //159 show small hi-stick - that need for simulate rus 'Ф' + "\t" => array(8,8,8,0,0,0,0), //show hi-stick - that need for simulate rus 'У' + "\r" => array(8,8,8,8,8,8,8), //vertical line - that need for simulate 'M', 'W' and rus 'Ðœ','Ш' ,'Щ' + "\n" => array(15,15,15,15,15,15,15), //fill up - that need for simulate rus 'Ж' + "Ò" => array(10,5,10,5,10,5,10), //chess + "µ" => array(15,0,15,0,15,0,15), //4 horizontal lines + // latin + 'A' => array(6,9,9,15,9,9,9), + 'B' => array(14,9,9,14,9,9,14), + 'C' => array(6,9,8,8,8,9,6), + 'D' => array(14,9,9,9,9,9,14), + 'E' => array(15,8,8,14,8,8,15), + 'F' => array(15,8,8,14,8,8,8), + 'G' => array(6,9,8,8,11,9,6), + 'H' => array(9,9,9,15,9,9,9), + 'I' => array(14,4,4,4,4,4,14), + 'J' => array(15,1,1,1,1,9,6), + 'K' => array(8,9,10,12,12,10,9), + 'L' => array(8,8,8,8,8,8,15), + 'M' => array(8,13,10,8,8,8,8),// need to add \r + 'N' => array(9,9,13,11,9,9,9), + 'O' => array(6,9,9,9,9,9,6), + 'P' => array(14,9,9,14,8,8,8), + 'Q' => array(6,9,9,9,13,11,6), + 'R' => array(14,9,9,14,12,10,9), + 'S' => array(6,9,8,6,1,9,6), + 'T' => array(14,4,4,4,4,4,4), + 'U' => array(9,9,9,9,9,9,6), + 'V' => array(0,0,0,10,10,10,4), + 'W' => array(8,8,8,8,10,13,8),// need to add \r + 'X' => array(9,9,6,6,6,9,9), + 'Y' => array(10,10,10,10,4,4,4), + 'Z' => array(15,1,2,6,4,8,15), + // russian utf-8 + 'Ð' => array(6,9,9,15,9,9,9), + 'Б' => array(14,8,8,14,9,9,14), + 'Ð’' => array(14,9,9,14,9,9,14), + 'Г' => array(15,8,8,8,8,8,8), + 'Д' => array(14,9,9,9,9,9,14), + 'Е' => array(15,8,8,14,8,8,15), + 'Ð' => array(6,15,8,14,8,8,15), + //Ж is combine: >\n< + 'З' => array(6,9,1,2,1,9,6), + 'И' => array(9,9,9,11,13,9,9), + 'Й' => array(13,9,9,11,13,9,9), + 'К' => array(9,10,12,10,9,9,9), + 'Л' => array(7,9,9,9,9,9,9), + 'Ðœ' => array(8,13,10,8,8,8,8),// need to add \r + 'Ð' => array(9,9,9,15,9,9,9), + 'О' => array(6,9,9,9,9,9,6), + 'П' => array(15,9,9,9,9,9,9), + 'Р' => array(14,9,9,14,8,8,8), + 'С' => array(6,9,8,8,8,9,6), + 'Т' => array(14,4,4,4,4,4,4), + 'У' => array(9,9,9,7,1,9,6), + 'Ф' => array(2,7,10,10,7,2,2),// need to add ÐŽ + 'Ð¥' => array(9,9,6,6,6,9,9), + 'Ц' => array(10,10,10,10,10,15,1), + 'Ч' => array(9,9,9,7,1,1,1), + 'Ш' => array(10,10,10,10,10,10,15),// \r + 'Щ' => array(10,10,10,10,10,15,0),// need to add \r + 'Ъ' => array(12,4,4,6,5,5,6), + 'Ы' => array(8,8,8,14,9,9,14),// need to add | + 'Ь' => array(8,8,8,14,9,9,14), + 'Э' => array(6,9,1,7,1,9,6), + 'Ю' => array(2,2,2,3,2,2,2),// need to add O + 'Я' => array(7,9,9,7,3,5,9) + ), + + $iSuperSampling = 3, $iMarg = 1, $iRad = 4; + + function __construct($aRadius = 2, $aMargin= 0.6) { + $this->iRad = $aRadius; + $this->iMarg = $aMargin; + } + + function SetSupersampling($aSuperSampling = 2) { + $this->iSuperSampling = $aSuperSampling; + } + + function _GetLED($aLedIdx, $aColor = 0) { + $width= $this->iLED_X*$this->iRad*2 + ($this->iLED_X+1)*$this->iMarg + $this->iRad ; + $height= $this->iLED_Y*$this->iRad*2 + ($this->iLED_Y)*$this->iMarg + $this->iRad * 2; + + // Adjust radious for supersampling + $rad = $this->iRad * $this->iSuperSampling; + + // Margin in between "Led" dots + $marg = $this->iMarg * $this->iSuperSampling; + + $swidth = $width*$this->iSuperSampling; + $sheight = $height*$this->iSuperSampling; + + $simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false); + $simg->SetColor($this->iColorSchema[$aColor][2]); + $simg->FilledRectangle(0, 0, $swidth-1, $sheight-1); + + if( array_key_exists($aLedIdx, $this->iLEDSpec) ) { + $d = $this->iLEDSpec[$aLedIdx]; + } + else { + $d = array(0,0,0,0,0,0,0); + } + + for($r = 0; $r < 7; ++$r) { + $dr = $d[$r]; + for($c = 0; $c < 4; ++$c) { + if( ($dr & pow(2,3-$c)) !== 0 ) { + $color = $this->iColorSchema[$aColor][0]; + } + else { + $color = $this->iColorSchema[$aColor][1]; + } + + $x = 2*$rad*$c+$rad + ($c+1)*$marg + $rad ; + $y = 2*$rad*$r+$rad + ($r+1)*$marg + $rad ; + + $simg->SetColor($color); + $simg->FilledCircle($x,$y,$rad); + } + } + + $img = new Image($width, $height, DEFAULT_GFORMAT, false); + $img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight); + $simg->Destroy(); + unset($simg); + return $img; + } + + + function Stroke($aValStr, $aColor = 0, $aFileName = '') { + $this->StrokeNumber($aValStr, $aColor, $aFileName); + } + + + function StrokeNumber($aValStr, $aColor = 0, $aFileName = '') { + if( $aColor < 0 || $aColor >= sizeof($this->iColorSchema) ) { + $aColor = 0; + } + + if(($n = mb_strlen($aValStr,'utf8')) == 0) { + $aValStr = ' '; + $n = 1; + } + + for($i = 0; $i < $n; ++$i) { + $d = mb_substr($aValStr, $i, 1, 'utf8'); + if( ctype_digit($d) ) { + $d = (int)$d; + } + else { + $d = strtoupper($d); + } + $digit_img[$i] = $this->_GetLED($d, $aColor); + } + + $w = imagesx($digit_img[0]->img); + $h = imagesy($digit_img[0]->img); + + $number_img = new Image($w*$n, $h, DEFAULT_GFORMAT, false); + + for($i = 0; $i < $n; ++$i) { + $number_img->Copy($digit_img[$i]->img, $i*$w, 0, 0, 0, $w, $h, $w, $h); + } + + if( $aFileName != '' ) { + $number_img->Stream($aFileName); + } else { + $number_img->Headers(); + $number_img->Stream(); + } + } +} +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_legend.inc.php b/web/public_php/admin/jpgraph/jpgraph_legend.inc.php new file mode 100644 index 000000000..c7f38b511 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_legend.inc.php @@ -0,0 +1,494 @@ +hide=$aHide; + } + + function SetHColMargin($aXMarg) { + $this->xmargin = $aXMarg; + } + + function SetVColMargin($aSpacing) { + $this->ylinespacing = $aSpacing ; + } + + function SetLeftMargin($aXMarg) { + $this->xlmargin = $aXMarg; + } + + // Synonym + function SetLineSpacing($aSpacing) { + $this->ylinespacing = $aSpacing ; + } + + function SetShadow($aShow='gray',$aWidth=4) { + if( is_string($aShow) ) { + $this->shadow_color = $aShow; + $this->shadow=true; + } + else { + $this->shadow = $aShow; + } + $this->shadow_width = $aWidth; + } + + function SetMarkAbsSize($aSize) { + $this->mark_abs_vsize = $aSize ; + $this->mark_abs_hsize = $aSize ; + } + + function SetMarkAbsVSize($aSize) { + $this->mark_abs_vsize = $aSize ; + } + + function SetMarkAbsHSize($aSize) { + $this->mark_abs_hsize = $aSize ; + } + + function SetLineWeight($aWeight) { + $this->weight = $aWeight; + } + + function SetFrameWeight($aWeight) { + $this->frameweight = $aWeight; + } + + function SetLayout($aDirection=LEGEND_VERT) { + $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ; + } + + function SetColumns($aCols) { + $this->layout_n = $aCols ; + } + + function SetReverse($f=true) { + $this->reverse = $f ; + } + + // Set color on frame around box + function SetColor($aFontColor,$aColor='black') { + $this->font_color=$aFontColor; + $this->color=$aColor; + } + + function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { + $this->font_family = $aFamily; + $this->font_style = $aStyle; + $this->font_size = $aSize; + } + + function SetPos($aX,$aY,$aHAlign='right',$aVAlign='top') { + $this->Pos($aX,$aY,$aHAlign,$aVAlign); + } + + function SetAbsPos($aX,$aY,$aHAlign='right',$aVAlign='top') { + $this->xabspos=$aX; + $this->yabspos=$aY; + $this->halign=$aHAlign; + $this->valign=$aVAlign; + } + + function Pos($aX,$aY,$aHAlign='right',$aVAlign='top') { + if( !($aX<1 && $aY<1) ) { + JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1"); + } + $this->xpos=$aX; + $this->ypos=$aY; + $this->halign=$aHAlign; + $this->valign=$aVAlign; + } + + function SetFillColor($aColor) { + $this->fill_color=$aColor; + } + + function Clear() { + $this->txtcol = array(); + } + + function Add($aTxt,$aColor,$aPlotmark='',$aLinestyle=0,$csimtarget='',$csimalt='',$csimwintarget='') { + $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget); + } + + function GetCSIMAreas() { + return $this->csimareas; + } + + function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2) { + $this->bkg_gradtype=$aGradType; + $this->bkg_gradfrom = $aFrom; + $this->bkg_gradto = $aTo; + } + + function HasItems() { + return (boolean)(count($this->txtcol)); + } + + function Stroke($aImg) { + // Constant + $fillBoxFrameWeight=1; + + if( $this->hide ) return; + + $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); + + if( $this->reverse ) { + $this->txtcol = array_reverse($this->txtcol); + } + + $n=count($this->txtcol); + if( $n == 0 ) return; + + // Find out the max width and height of each column to be able + // to size the legend box. + $numcolumns = ($n > $this->layout_n ? $this->layout_n : $n); + for( $i=0; $i < $numcolumns; ++$i ) { + $colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) + + 2*$this->xmargin + 2*$this->mark_abs_hsize; + $colheight[$i] = 0; + + } + + // Find our maximum height in each row + $rows = 0 ; $rowheight[0] = 0; + for( $i=0; $i < $n; ++$i ) { + $h = max($this->mark_abs_vsize,$aImg->GetTextHeight($this->txtcol[$i][0]))+$this->ylinespacing; + + // Makes sure we always have a minimum of 1/4 (1/2 on each side) of the mark as space + // between two vertical legend entries + //$h = round(max($h,$this->mark_abs_vsize+$this->ymargin)); + //echo "Textheight #$i: tetxheight=".$aImg->GetTextHeight($this->txtcol[$i][0]).', '; + //echo "h=$h ({$this->mark_abs_vsize},{$this->ymargin})
"; + if( $i % $numcolumns == 0 ) { + $rows++; + $rowheight[$rows-1] = 0; + } + $rowheight[$rows-1] = max($rowheight[$rows-1],$h)+1; + } + + $abs_height = 0; + for( $i=0; $i < $rows; ++$i ) { + $abs_height += $rowheight[$i] ; + } + + // Make sure that the height is at least as high as mark size + ymargin + $abs_height = max($abs_height,$this->mark_abs_vsize); + $abs_height += $this->ybottom_margin; + + // Find out the maximum width in each column + for( $i=$numcolumns; $i < $n; ++$i ) { + $colwidth[$i % $numcolumns] = max( + $aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize, + $colwidth[$i % $numcolumns]); + } + + // Get the total width + $mtw = 0; + for( $i=0; $i < $numcolumns; ++$i ) { + $mtw += $colwidth[$i] ; + } + + // remove the last rows interpace margin (since there is no next row) + $abs_height -= $this->ylinespacing; + + + // Find out maximum width we need for legend box + $abs_width = $mtw+$this->xlmargin+($numcolumns-1)*$this->mark_abs_hsize; + + if( $this->xabspos === -1 && $this->yabspos === -1 ) { + $this->xabspos = $this->xpos*$aImg->width ; + $this->yabspos = $this->ypos*$aImg->height ; + } + + // Positioning of the legend box + if( $this->halign == 'left' ) { + $xp = $this->xabspos; + } + elseif( $this->halign == 'center' ) { + $xp = $this->xabspos - $abs_width/2; + } + else { + $xp = $aImg->width - $this->xabspos - $abs_width; + } + + $yp=$this->yabspos; + if( $this->valign == 'center' ) { + $yp-=$abs_height/2; + } + elseif( $this->valign == 'bottom' ) { + $yp-=$abs_height; + } + + // Stroke legend box + $aImg->SetColor($this->color); + $aImg->SetLineWeight($this->frameweight); + $aImg->SetLineStyle('solid'); + + if( $this->shadow ) { + $aImg->ShadowRectangle($xp,$yp, + $xp+$abs_width+$this->shadow_width+2, + $yp+$abs_height+$this->shadow_width+2, + $this->fill_color,$this->shadow_width+2,$this->shadow_color); + } + else { + $aImg->SetColor($this->fill_color); + $aImg->FilledRectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height); + $aImg->SetColor($this->color); + $aImg->Rectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height); + } + + if( $this->bkg_gradtype >= 0 ) { + $grad = new Gradient($aImg); + $grad->FilledRectangle($xp+1, $yp+1, + $xp+$abs_width-3, $yp+$abs_height-3, + $this->bkg_gradfrom, $this->bkg_gradto, + $this->bkg_gradtype); + } + + // x1,y1 is the position for the legend marker + text + // The vertical position is the baseline position for the text + // and every marker is adjusted acording to that. + + // For multiline texts this get more complicated. + + $x1 = $xp + $this->xlmargin; + $y1 = $yp + $rowheight[0] - $this->ylinespacing + 2 ; // The ymargin is included in rowheight + + // Now, y1 is the bottom vertical position of the first legend, i.e if + // the legend has multiple lines it is the bottom line. + + $grad = new Gradient($aImg); + $patternFactory = null; + + // Now stroke each legend in turn + // Each plot has added the following information to the legend + // p[0] = Legend text + // p[1] = Color, + // p[2] = For markers a reference to the PlotMark object + // p[3] = For lines the line style, for gradient the negative gradient style + // p[4] = CSIM target + // p[5] = CSIM Alt text + $i = 1 ; $row = 0; + foreach($this->txtcol as $p) { + + // STROKE DEBUG BOX + if( _JPG_DEBUG ) { + $aImg->SetLineWeight(1); + $aImg->SetColor('red'); + $aImg->SetLineStyle('solid'); + $aImg->Rectangle($x1,$y1,$xp+$abs_width-1,$y1-$rowheight[$row]); + } + + $aImg->SetLineWeight($this->weight); + $x1 = round($x1)+1; // We add one to not collide with the border + $y1=round($y1); + + // This is the center offset up from the baseline which is + // considered the "center" of the marks. This gets slightly complicated since + // we need to consider if the text is a multiline paragraph or if it is only + // a single line. The reason is that for single line the y1 corresponds to the baseline + // and that is fine. However for a multiline paragraph there is no single baseline + // and in that case the y1 corresponds to the lowest y for the bounding box. In that + // case we center the mark in the middle of the paragraph + if( !preg_match('/\n/',$p[0]) ) { + // Single line + $marky = ceil($y1-$this->mark_abs_vsize/2)-1; + } else { + // Paragraph + $marky = $y1 - $aImg->GetTextHeight($p[0])/2; + + // echo "y1=$y1, p[o]={$p[0]}, marky=$marky
"; + } + + //echo "
Mark #$i: marky=$marky
"; + + $x1 += $this->mark_abs_hsize; + + if ( !empty($p[2]) && $p[2]->GetType() > -1 ) { + + + // Make a plot mark legend. This is constructed with a mark which + // is run through with a line + + // First construct a bit of the line that looks exactly like the + // line in the plot + $aImg->SetColor($p[1]); + if( is_string($p[3]) || $p[3]>0 ) { + $aImg->SetLineStyle($p[3]); + $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky,$x1+$this->mark_abs_hsize,$marky); + } + + // Stroke a mark using image + if( $p[2]->GetType() == MARK_IMG ) { + $p[2]->Stroke($aImg,$x1,$marky); + } + + // Stroke a mark with the standard size + // (As long as it is not an image mark ) + if( $p[2]->GetType() != MARK_IMG ) { + + // Clear any user callbacks since we ont want them called for + // the legend marks + $p[2]->iFormatCallback = ''; + $p[2]->iFormatCallback2 = ''; + + // Since size for circles is specified as the radius + // this means that we must half the size to make the total + // width behave as the other marks + if( $p[2]->GetType() == MARK_FILLEDCIRCLE || $p[2]->GetType() == MARK_CIRCLE ) { + $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)/2); + $p[2]->Stroke($aImg,$x1,$marky); + } + else { + $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)); + $p[2]->Stroke($aImg,$x1,$marky); + } + } + } + elseif ( !empty($p[2]) && (is_string($p[3]) || $p[3]>0 ) ) { + // Draw a styled line + $aImg->SetColor($p[1]); + $aImg->SetLineStyle($p[3]); + $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky,$x1+$this->mark_abs_hsize,$marky); + $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky+1,$x1+$this->mark_abs_hsize,$marky+1); + } + else { + // Draw a colored box + $color = $p[1] ; + + // We make boxes slightly larger to better show + $boxsize = max($this->mark_abs_vsize,$this->mark_abs_hsize) + 2 ; + + $ym = $marky-ceil($boxsize/2) ; // Marker y-coordinate + + // We either need to plot a gradient or a + // pattern. To differentiate we use a kludge. + // Patterns have a p[3] value of < -100 + if( $p[3] < -100 ) { + // p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity + if( $patternFactory == null ) { + $patternFactory = new RectPatternFactory(); + } + $prect = $patternFactory->Create($p[1][0],$p[1][1],1); + $prect->SetBackground($p[1][3]); + $prect->SetDensity($p[1][2]+1); + $prect->SetPos(new Rectangle($x1,$ym,$boxsize,$boxsize)); + $prect->Stroke($aImg); + $prect=null; + } + else { + if( is_array($color) && count($color)==2 ) { + // The client want a gradient color + $grad->FilledRectangle($x1-$boxsize/2,$ym, + $x1+$boxsize/2,$ym+$boxsize, + $color[0],$color[1],-$p[3]); + } + else { + $aImg->SetColor($p[1]); + $aImg->FilledRectangle($x1-$boxsize/2,$ym, $x1+$boxsize/2,$ym+$boxsize); + } + + // Draw a plot frame line + $aImg->SetColor($this->color); + $aImg->SetLineWeight($fillBoxFrameWeight); + $aImg->Rectangle($x1-$boxsize/2,$ym, + $x1+$boxsize/2,$ym+$boxsize); + } + } + $aImg->SetColor($this->font_color); + $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); + $aImg->SetTextAlign('left','baseline'); + + $debug=false; + $aImg->StrokeText($x1+$this->mark_abs_hsize+$this->xmargin,$y1,$p[0], + 0,'left',$debug); + + // Add CSIM for Legend if defined + if( !empty($p[4]) ) { + + $xs = $x1 - $this->mark_abs_hsize ; + $ys = $y1 + 1 ; + $xe = $x1 + $aImg->GetTextWidth($p[0]) + $this->mark_abs_hsize + $this->xmargin ; + $ye = $y1-$rowheight[$row]+1; + $coords = "$xs,$ys,$xe,$y1,$xe,$ye,$xs,$ye"; + if( ! empty($p[4]) ) { + $this->csimareas .= "csimareas .= " target=\"".$p[6]."\""; + } + + if( !empty($p[5]) ) { + $tmp=sprintf($p[5],$p[0]); + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + } + + if( $i >= $this->layout_n ) { + $x1 = $xp+$this->xlmargin; + $row++; + if( !empty($rowheight[$row]) ) + $y1 += $rowheight[$row]; + $i = 1; + } + else { + $x1 += $colwidth[($i-1) % $numcolumns] ; + ++$i; + } + } + } +} // Class + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_line.php b/web/public_php/admin/jpgraph/jpgraph_line.php index 60ef128ce..81756598b 100644 --- a/web/public_php/admin/jpgraph/jpgraph_line.php +++ b/web/public_php/admin/jpgraph/jpgraph_line.php @@ -1,625 +1,682 @@ -mark = new PlotMark(); - } -//--------------- -// PUBLIC METHODS - - // Set style, filled or open - function SetFilled($aFlag=true) { - JpGraphError::RaiseL(10001);//('LinePlot::SetFilled() is deprecated. Use SetFillColor()'); - } - - function SetBarCenter($aFlag=true) { - $this->barcenter=$aFlag; - } - - function SetStyle($aStyle) { - $this->line_style=$aStyle; - } - - function SetStepStyle($aFlag=true) { - $this->step_style = $aFlag; - } - - function SetColor($aColor) { - parent::SetColor($aColor); - } - - function SetFillFromYMin($f=true) { - $this->fillFromMin = $f ; - } - - function SetFillColor($aColor,$aFilled=true) { - $this->fill_color=$aColor; - $this->filled=$aFilled; - } - - function SetFillGradient($aFromColor,$aToColor,$aNumColors=100,$aFilled=true) { - $this->fillgrad_fromcolor = $aFromColor; - $this->fillgrad_tocolor = $aToColor; - $this->fillgrad_numcolors = $aNumColors; - $this->filled = $aFilled; - $this->fillgrad = true; - } - - function Legend(&$graph) { - if( $this->legend!="" ) { - if( $this->filled && !$this->fillgrad ) { - $graph->legend->Add($this->legend, - $this->fill_color,$this->mark,0, - $this->legendcsimtarget,$this->legendcsimalt); - } - elseif( $this->fillgrad ) { - $color=array($this->fillgrad_fromcolor,$this->fillgrad_tocolor); - // In order to differentiate between gradients and cooors specified as an RGB triple - $graph->legend->Add($this->legend,$color,"",-2 /* -GRAD_HOR */, - $this->legendcsimtarget,$this->legendcsimalt); - } - else { - $graph->legend->Add($this->legend, - $this->color,$this->mark,$this->line_style, - $this->legendcsimtarget,$this->legendcsimalt); - } - } - } - - function AddArea($aMin=0,$aMax=0,$aFilled=LP_AREA_NOT_FILLED,$aColor="gray9",$aBorder=LP_AREA_BORDER) { - if($aMin > $aMax) { - // swap - $tmp = $aMin; - $aMin = $aMax; - $aMax = $tmp; - } - $this->filledAreas[] = array($aMin,$aMax,$aColor,$aFilled,$aBorder); - } - - // Gets called before any axis are stroked - function PreStrokeAdjust(&$graph) { - - // If another plot type have already adjusted the - // offset we don't touch it. - // (We check for empty in case the scale is a log scale - // and hence doesn't contain any xlabel_offset) - if( empty($graph->xaxis->scale->ticks->xlabel_offset) || - $graph->xaxis->scale->ticks->xlabel_offset == 0 ) { - if( $this->center ) { - ++$this->numpoints; - $a=0.5; $b=0.5; - } else { - $a=0; $b=0; - } - $graph->xaxis->scale->ticks->SetXLabelOffset($a); - $graph->SetTextScaleOff($b); - //$graph->xaxis->scale->ticks->SupressMinorTickMarks(); - } - } - - function SetFastStroke($aFlg=true) { - $this->iFastStroke = $aFlg; - } - - function FastStroke(&$img,&$xscale,&$yscale,$aStartPoint=0,$exist_x=true) { - // An optimized stroke for many data points with no extra - // features but 60% faster. You can't have values or line styles, or null - // values in plots. - $numpoints=count($this->coords[0]); - if( $this->barcenter ) - $textadj = 0.5-$xscale->text_scale_off; - else - $textadj = 0; - - $img->SetColor($this->color); - $img->SetLineWeight($this->weight); - $pnts=$aStartPoint; - while( $pnts < $numpoints ) { - if( $exist_x ) $x=$this->coords[1][$pnts]; - else $x=$pnts+$textadj; - $xt = $xscale->Translate($x); - $y=$this->coords[0][$pnts]; - $yt = $yscale->Translate($y); - if( is_numeric($y) ) { - $cord[] = $xt; - $cord[] = $yt; - } - elseif( $y == '-' && $pnts > 0 ) { - // Just ignore - } - else { - JpGraphError::RaiseL(10002);//('Plot too complicated for fast line Stroke. Use standard Stroke()'); - return; - } - ++$pnts; - } // WHILE - - $img->Polygon($cord,false,true); - - } - - function Stroke(&$img,&$xscale,&$yscale) { - $idx=0; - $numpoints=count($this->coords[0]); - if( isset($this->coords[1]) ) { - if( count($this->coords[1])!=$numpoints ) - JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); -//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints"); - else - $exist_x = true; - } - else - $exist_x = false; - - if( $this->barcenter ) - $textadj = 0.5-$xscale->text_scale_off; - else - $textadj = 0; - - // Find the first numeric data point - $startpoint=0; - while( $startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint]) ) - ++$startpoint; - - // Bail out if no data points - if( $startpoint == $numpoints ) - return; - - if( $this->iFastStroke ) { - $this->FastStroke($img,$xscale,$yscale,$startpoint,$exist_x); - return; - } - - if( $exist_x ) - $xs=$this->coords[1][$startpoint]; - else - $xs= $textadj+$startpoint; - - $img->SetStartPoint($xscale->Translate($xs), - $yscale->Translate($this->coords[0][$startpoint])); - - if( $this->filled ) { - $min = $yscale->GetMinVal(); - if( $min > 0 || $this->fillFromMin ) - $fillmin = $yscale->scale_abs[0];//Translate($min); - else - $fillmin = $yscale->Translate(0); - - $cord[$idx++] = $xscale->Translate($xs); - $cord[$idx++] = $fillmin; - } - $xt = $xscale->Translate($xs); - $yt = $yscale->Translate($this->coords[0][$startpoint]); - $cord[$idx++] = $xt; - $cord[$idx++] = $yt; - $yt_old = $yt; - $xt_old = $xt; - $y_old = $this->coords[0][$startpoint]; - - $this->value->Stroke($img,$this->coords[0][$startpoint],$xt,$yt); - - $img->SetColor($this->color); - $img->SetLineWeight($this->weight); - $img->SetLineStyle($this->line_style); - $pnts=$startpoint+1; - $firstnonumeric = false; - while( $pnts < $numpoints ) { - - if( $exist_x ) $x=$this->coords[1][$pnts]; - else $x=$pnts+$textadj; - $xt = $xscale->Translate($x); - $yt = $yscale->Translate($this->coords[0][$pnts]); - - $y=$this->coords[0][$pnts]; - if( $this->step_style ) { - // To handle null values within step style we need to record the - // first non numeric value so we know from where to start if the - // non value is '-'. - if( is_numeric($y) ) { - $firstnonumeric = false; - if( is_numeric($y_old) ) { - $img->StyleLine($xt_old,$yt_old,$xt,$yt_old); - $img->StyleLine($xt,$yt_old,$xt,$yt); - } - elseif( $y_old == '-' ) { - $img->StyleLine($xt_first,$yt_first,$xt,$yt_first); - $img->StyleLine($xt,$yt_first,$xt,$yt); - } - else { - $yt_old = $yt; - $xt_old = $xt; - } - $cord[$idx++] = $xt; - $cord[$idx++] = $yt_old; - $cord[$idx++] = $xt; - $cord[$idx++] = $yt; - } - elseif( $firstnonumeric==false ) { - $firstnonumeric = true; - $yt_first = $yt_old; - $xt_first = $xt_old; - } - } - else { - $tmp1=$y; - $prev=$this->coords[0][$pnts-1]; - if( $tmp1==='' || $tmp1===NULL || $tmp1==='X' ) $tmp1 = 'x'; - if( $prev==='' || $prev===null || $prev==='X' ) $prev = 'x'; - - if( is_numeric($y) || (is_string($y) && $y != '-') ) { - if( is_numeric($y) && (is_numeric($prev) || $prev === '-' ) ) { - $img->StyleLineTo($xt,$yt); - } - else { - $img->SetStartPoint($xt,$yt); - } - } - if( $this->filled && $tmp1 !== '-' ) { - if( $tmp1 === 'x' ) { - $cord[$idx++] = $cord[$idx-3]; - $cord[$idx++] = $fillmin; - } - elseif( $prev === 'x' ) { - $cord[$idx++] = $xt; - $cord[$idx++] = $fillmin; - $cord[$idx++] = $xt; - $cord[$idx++] = $yt; - } - else { - $cord[$idx++] = $xt; - $cord[$idx++] = $yt; - } - } - else { - if( is_numeric($tmp1) && (is_numeric($prev) || $prev === '-' ) ) { - $cord[$idx++] = $xt; - $cord[$idx++] = $yt; - } - } - } - $yt_old = $yt; - $xt_old = $xt; - $y_old = $y; - - $this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt); - - ++$pnts; - } - - if( $this->filled ) { - $cord[$idx++] = $xt; - if( $min > 0 || $this->fillFromMin ) - $cord[$idx++] = $yscale->Translate($min); - else - $cord[$idx++] = $yscale->Translate(0); - if( $this->fillgrad ) { - $img->SetLineWeight(1); - $grad = new Gradient($img); - $grad->SetNumColors($this->fillgrad_numcolors); - $grad->FilledFlatPolygon($cord,$this->fillgrad_fromcolor,$this->fillgrad_tocolor); - $img->SetLineWeight($this->weight); - } - else { - $img->SetColor($this->fill_color); - $img->FilledPolygon($cord); - } - if( $this->line_weight > 0 ) { - $img->SetColor($this->color); - $img->Polygon($cord); - } - } - - if(!empty($this->filledAreas)) { - - $minY = $yscale->Translate($yscale->GetMinVal()); - $factor = ($this->step_style ? 4 : 2); - - for($i = 0; $i < sizeof($this->filledAreas); ++$i) { - // go through all filled area elements ordered by insertion - // fill polygon array - $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor]; - $areaCoords[] = $minY; - - $areaCoords = - array_merge($areaCoords, - array_slice($cord, - $this->filledAreas[$i][0] * $factor, - ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1)) * $factor)); - $areaCoords[] = $areaCoords[sizeof($areaCoords)-2]; // last x - $areaCoords[] = $minY; // last y - - if($this->filledAreas[$i][3]) { - $img->SetColor($this->filledAreas[$i][2]); - $img->FilledPolygon($areaCoords); - $img->SetColor($this->color); - } - // Check if we should draw the frame. - // If not we still re-draw the line since it might have been - // partially overwritten by the filled area and it doesn't look - // very good. - // TODO: The behaviour is undefined if the line does not have - // any line at the position of the area. - if( $this->filledAreas[$i][4] ) - $img->Polygon($areaCoords); - else - $img->Polygon($cord); - - $areaCoords = array(); - } - } - - if( $this->mark->type == -1 || $this->mark->show == false ) - return; - - for( $pnts=0; $pnts<$numpoints; ++$pnts) { - - if( $exist_x ) $x=$this->coords[1][$pnts]; - else $x=$pnts+$textadj; - $xt = $xscale->Translate($x); - $yt = $yscale->Translate($this->coords[0][$pnts]); - - if( is_numeric($this->coords[0][$pnts]) ) { - if( !empty($this->csimtargets[$pnts]) ) { - $this->mark->SetCSIMTarget($this->csimtargets[$pnts]); - $this->mark->SetCSIMAlt($this->csimalts[$pnts]); - } - if( $exist_x ) - $x=$this->coords[1][$pnts]; - else - $x=$pnts; - $this->mark->SetCSIMAltVal($this->coords[0][$pnts],$x); - $this->mark->Stroke($img,$xt,$yt); - $this->csimareas .= $this->mark->GetCSIMAreas(); - $this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt); - } - } - - - } -} // Class - - -//=================================================== -// CLASS AccLinePlot -// Description: -//=================================================== -class AccLinePlot extends Plot { - var $plots=null,$nbrplots=0,$numpoints=0; - var $iStartEndZero=true; -//--------------- -// CONSTRUCTOR - function __construct($plots) { - $this->plots = $plots; - $this->nbrplots = count($plots); - $this->numpoints = $plots[0]->numpoints; - - for($i=0; $i < $this->nbrplots; ++$i ) { - $this->LineInterpolate($this->plots[$i]->coords[0]); - } - } - -//--------------- -// PUBLIC METHODS - function Legend(&$graph) { - $n=count($this->plots); - for($i=0; $i < $n; ++$i ) - $this->plots[$i]->DoLegend($graph); - } - - function Max() { - list($xmax) = $this->plots[0]->Max(); - $nmax=0; - $n = count($this->plots); - for($i=0; $i < $n; ++$i) { - $nc = count($this->plots[$i]->coords[0]); - $nmax = max($nmax,$nc); - list($x) = $this->plots[$i]->Max(); - $xmax = Max($xmax,$x); - } - for( $i = 0; $i < $nmax; $i++ ) { - // Get y-value for line $i by adding the - // individual bars from all the plots added. - // It would be wrong to just add the - // individual plots max y-value since that - // would in most cases give to large y-value. - $y=$this->plots[0]->coords[0][$i]; - for( $j = 1; $j < $this->nbrplots; $j++ ) { - $y += $this->plots[ $j ]->coords[0][$i]; - } - $ymax[$i] = $y; - } - $ymax = max($ymax); - return array($xmax,$ymax); - } - - function Min() { - $nmax=0; - list($xmin,$ysetmin) = $this->plots[0]->Min(); - $n = count($this->plots); - for($i=0; $i < $n; ++$i) { - $nc = count($this->plots[$i]->coords[0]); - $nmax = max($nmax,$nc); - list($x,$y) = $this->plots[$i]->Min(); - $xmin = Min($xmin,$x); - $ysetmin = Min($y,$ysetmin); - } - for( $i = 0; $i < $nmax; $i++ ) { - // Get y-value for line $i by adding the - // individual bars from all the plots added. - // It would be wrong to just add the - // individual plots min y-value since that - // would in most cases give to small y-value. - $y=$this->plots[0]->coords[0][$i]; - for( $j = 1; $j < $this->nbrplots; $j++ ) { - $y += $this->plots[ $j ]->coords[0][$i]; - } - $ymin[$i] = $y; - } - $ymin = Min($ysetmin,Min($ymin)); - return array($xmin,$ymin); - } - - // Gets called before any axis are stroked - function PreStrokeAdjust(&$graph) { - - // If another plot type have already adjusted the - // offset we don't touch it. - // (We check for empty in case the scale is a log scale - // and hence doesn't contain any xlabel_offset) - - if( empty($graph->xaxis->scale->ticks->xlabel_offset) || - $graph->xaxis->scale->ticks->xlabel_offset == 0 ) { - if( $this->center ) { - ++$this->numpoints; - $a=0.5; $b=0.5; - } else { - $a=0; $b=0; - } - $graph->xaxis->scale->ticks->SetXLabelOffset($a); - $graph->SetTextScaleOff($b); - $graph->xaxis->scale->ticks->SupressMinorTickMarks(); - } - - } - - function SetInterpolateMode($aIntMode) { - $this->iStartEndZero=$aIntMode; - } - - // Replace all '-' with an interpolated value. We use straightforward - // linear interpolation. If the data starts with one or several '-' they - // will be replaced by the the first valid data point - function LineInterpolate(&$aData) { - - $n=count($aData); - $i=0; - - // If first point is undefined we will set it to the same as the first - // valid data - if( $aData[$i]==='-' ) { - // Find the first valid data - while( $i < $n && $aData[$i]==='-' ) { - ++$i; - } - if( $i < $n ) { - for($j=0; $j < $i; ++$j ) { - if( $this->iStartEndZero ) - $aData[$i] = 0; - else - $aData[$j] = $aData[$i]; - } - } - else { - // All '-' => Error - return false; - } - } - - while($i < $n) { - while( $i < $n && $aData[$i] !== '-' ) { - ++$i; - } - if( $i < $n ) { - $pstart=$i-1; - - // Now see how long this segment of '-' are - while( $i < $n && $aData[$i] === '-' ) - ++$i; - if( $i < $n ) { - $pend=$i; - $size=$pend-$pstart; - $k=($aData[$pend]-$aData[$pstart])/$size; - // Replace the segment of '-' with a linear interpolated value. - for($j=1; $j < $size; ++$j ) { - $aData[$pstart+$j] = $aData[$pstart] + $j*$k ; - } - } - else { - // There are no valid end point. The '-' goes all the way to the end - // In that case we just set all the remaining values the the same as the - // last valid data point. - for( $j=$pstart+1; $j < $n; ++$j ) - if( $this->iStartEndZero ) - $aData[$j] = 0; - else - $aData[$j] = $aData[$pstart] ; - } - } - } - return true; - } - - - - // To avoid duplicate of line drawing code here we just - // change the y-values for each plot and then restore it - // after we have made the stroke. We must do this copy since - // it wouldn't be possible to create an acc line plot - // with the same graphs, i.e AccLinePlot(array($pl,$pl,$pl)); - // since this method would have a side effect. - function Stroke(&$img,&$xscale,&$yscale) { - $img->SetLineWeight($this->weight); - $this->numpoints = count($this->plots[0]->coords[0]); - // Allocate array - $coords[$this->nbrplots][$this->numpoints]=0; - for($i=0; $i<$this->numpoints; $i++) { - $coords[0][$i]=$this->plots[0]->coords[0][$i]; - $accy=$coords[0][$i]; - for($j=1; $j<$this->nbrplots; ++$j ) { - $coords[$j][$i] = $this->plots[$j]->coords[0][$i]+$accy; - $accy = $coords[$j][$i]; - } - } - for($j=$this->nbrplots-1; $j>=0; --$j) { - $p=$this->plots[$j]; - for( $i=0; $i<$this->numpoints; ++$i) { - $tmp[$i]=$p->coords[0][$i]; - $p->coords[0][$i]=$coords[$j][$i]; - } - $p->Stroke($img,$xscale,$yscale); - for( $i=0; $i<$this->numpoints; ++$i) - $p->coords[0][$i]=$tmp[$i]; - $p->coords[0][]=$tmp; - } - } -} // Class - - -/* EOF */ -?> +mark = new PlotMark() ; + $this->color = ColorFactory::getColor(); + $this->fill_color = $this->color; + } + //--------------- + // PUBLIC METHODS + + function SetFilled($aFlg=true) { + $this->filled = $aFlg; + } + + function SetBarCenter($aFlag=true) { + $this->barcenter=$aFlag; + } + + function SetStyle($aStyle) { + $this->line_style=$aStyle; + } + + function SetStepStyle($aFlag=true) { + $this->step_style = $aFlag; + } + + function SetColor($aColor) { + parent::SetColor($aColor); + } + + function SetFillFromYMin($f=true) { + $this->fillFromMin = $f ; + } + + function SetFillFromYMax($f=true) { + $this->fillFromMax = $f ; + } + + function SetFillColor($aColor,$aFilled=true) { + //$this->color = $aColor; + $this->fill_color=$aColor; + $this->filled=$aFilled; + } + + function SetFillGradient($aFromColor,$aToColor,$aNumColors=100,$aFilled=true) { + $this->fillgrad_fromcolor = $aFromColor; + $this->fillgrad_tocolor = $aToColor; + $this->fillgrad_numcolors = $aNumColors; + $this->filled = $aFilled; + $this->fillgrad = true; + } + + function Legend($graph) { + if( $this->legend!="" ) { + if( $this->filled && !$this->fillgrad ) { + $graph->legend->Add($this->legend, + $this->fill_color,$this->mark,0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + elseif( $this->fillgrad ) { + $color=array($this->fillgrad_fromcolor,$this->fillgrad_tocolor); + // In order to differentiate between gradients and cooors specified as an RGB triple + $graph->legend->Add($this->legend,$color,"",-2 /* -GRAD_HOR */, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } else { + $graph->legend->Add($this->legend, + $this->color,$this->mark,$this->line_style, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } + } + + function AddArea($aMin=0,$aMax=0,$aFilled=LP_AREA_NOT_FILLED,$aColor="gray9",$aBorder=LP_AREA_BORDER) { + if($aMin > $aMax) { + // swap + $tmp = $aMin; + $aMin = $aMax; + $aMax = $tmp; + } + $this->filledAreas[] = array($aMin,$aMax,$aColor,$aFilled,$aBorder); + } + + // Gets called before any axis are stroked + function PreStrokeAdjust($graph) { + + // If another plot type have already adjusted the + // offset we don't touch it. + // (We check for empty in case the scale is a log scale + // and hence doesn't contain any xlabel_offset) + if( empty($graph->xaxis->scale->ticks->xlabel_offset) || $graph->xaxis->scale->ticks->xlabel_offset == 0 ) { + if( $this->center ) { + ++$this->numpoints; + $a=0.5; $b=0.5; + } else { + $a=0; $b=0; + } + $graph->xaxis->scale->ticks->SetXLabelOffset($a); + $graph->SetTextScaleOff($b); + //$graph->xaxis->scale->ticks->SupressMinorTickMarks(); + } + } + + function SetFastStroke($aFlg=true) { + $this->iFastStroke = $aFlg; + } + + function FastStroke($img,$xscale,$yscale,$aStartPoint=0,$exist_x=true) { + // An optimized stroke for many data points with no extra + // features but 60% faster. You can't have values or line styles, or null + // values in plots. + $numpoints=count($this->coords[0]); + if( $this->barcenter ) { + $textadj = 0.5-$xscale->text_scale_off; + } + else { + $textadj = 0; + } + + $img->SetColor($this->color); + $img->SetLineWeight($this->weight); + $pnts=$aStartPoint; + while( $pnts < $numpoints ) { + if( $exist_x ) { + $x=$this->coords[1][$pnts]; + } + else { + $x=$pnts+$textadj; + } + $xt = $xscale->Translate($x); + $y=$this->coords[0][$pnts]; + $yt = $yscale->Translate($y); + if( is_numeric($y) ) { + $cord[] = $xt; + $cord[] = $yt; + } + elseif( $y == '-' && $pnts > 0 ) { + // Just ignore + } + else { + JpGraphError::RaiseL(10002);//('Plot too complicated for fast line Stroke. Use standard Stroke()'); + } + ++$pnts; + } // WHILE + + $img->Polygon($cord,false,true); + } + + function Stroke($img,$xscale,$yscale) { + $idx=0; + $numpoints=count($this->coords[0]); + if( isset($this->coords[1]) ) { + if( count($this->coords[1])!=$numpoints ) { + JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); + //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints"); + } + else { + $exist_x = true; + } + } + else { + $exist_x = false; + } + + if( $this->barcenter ) { + $textadj = 0.5-$xscale->text_scale_off; + } + else { + $textadj = 0; + } + + // Find the first numeric data point + $startpoint=0; + while( $startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint]) ) { + ++$startpoint; + } + + // Bail out if no data points + if( $startpoint == $numpoints ) return; + + if( $this->iFastStroke ) { + $this->FastStroke($img,$xscale,$yscale,$startpoint,$exist_x); + return; + } + + if( $exist_x ) { + $xs=$this->coords[1][$startpoint]; + } + else { + $xs= $textadj+$startpoint; + } + + $img->SetStartPoint($xscale->Translate($xs), + $yscale->Translate($this->coords[0][$startpoint])); + + if( $this->filled ) { + if( $this->fillFromMax ) { + //$max = $yscale->GetMaxVal(); + $cord[$idx++] = $xscale->Translate($xs); + $cord[$idx++] = $yscale->scale_abs[1]; + } + else { + $min = $yscale->GetMinVal(); + if( $min > 0 || $this->fillFromMin ) { + $fillmin = $yscale->scale_abs[0];//Translate($min); + } + else { + $fillmin = $yscale->Translate(0); + } + + $cord[$idx++] = $xscale->Translate($xs); + $cord[$idx++] = $fillmin; + } + } + $xt = $xscale->Translate($xs); + $yt = $yscale->Translate($this->coords[0][$startpoint]); + $cord[$idx++] = $xt; + $cord[$idx++] = $yt; + $yt_old = $yt; + $xt_old = $xt; + $y_old = $this->coords[0][$startpoint]; + + $this->value->Stroke($img,$this->coords[0][$startpoint],$xt,$yt); + + $img->SetColor($this->color); + $img->SetLineWeight($this->weight); + $img->SetLineStyle($this->line_style); + $pnts=$startpoint+1; + $firstnonumeric = false; + + + while( $pnts < $numpoints ) { + + if( $exist_x ) { + $x=$this->coords[1][$pnts]; + } + else { + $x=$pnts+$textadj; + } + $xt = $xscale->Translate($x); + $yt = $yscale->Translate($this->coords[0][$pnts]); + + $y=$this->coords[0][$pnts]; + if( $this->step_style ) { + // To handle null values within step style we need to record the + // first non numeric value so we know from where to start if the + // non value is '-'. + if( is_numeric($y) ) { + $firstnonumeric = false; + if( is_numeric($y_old) ) { + $img->StyleLine($xt_old,$yt_old,$xt,$yt_old); + $img->StyleLine($xt,$yt_old,$xt,$yt); + } + elseif( $y_old == '-' ) { + $img->StyleLine($xt_first,$yt_first,$xt,$yt_first); + $img->StyleLine($xt,$yt_first,$xt,$yt); + } + else { + $yt_old = $yt; + $xt_old = $xt; + } + $cord[$idx++] = $xt; + $cord[$idx++] = $yt_old; + $cord[$idx++] = $xt; + $cord[$idx++] = $yt; + } + elseif( $firstnonumeric==false ) { + $firstnonumeric = true; + $yt_first = $yt_old; + $xt_first = $xt_old; + } + } + else { + $tmp1=$y; + $prev=$this->coords[0][$pnts-1]; + if( $tmp1==='' || $tmp1===NULL || $tmp1==='X' ) $tmp1 = 'x'; + if( $prev==='' || $prev===null || $prev==='X' ) $prev = 'x'; + + if( is_numeric($y) || (is_string($y) && $y != '-') ) { + if( is_numeric($y) && (is_numeric($prev) || $prev === '-' ) ) { + $img->StyleLineTo($xt,$yt); + } + else { + $img->SetStartPoint($xt,$yt); + } + } + if( $this->filled && $tmp1 !== '-' ) { + if( $tmp1 === 'x' ) { + $cord[$idx++] = $cord[$idx-3]; + $cord[$idx++] = $fillmin; + } + elseif( $prev === 'x' ) { + $cord[$idx++] = $xt; + $cord[$idx++] = $fillmin; + $cord[$idx++] = $xt; + $cord[$idx++] = $yt; + } + else { + $cord[$idx++] = $xt; + $cord[$idx++] = $yt; + } + } + else { + if( is_numeric($tmp1) && (is_numeric($prev) || $prev === '-' ) ) { + $cord[$idx++] = $xt; + $cord[$idx++] = $yt; + } + } + } + $yt_old = $yt; + $xt_old = $xt; + $y_old = $y; + + $this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt); + + ++$pnts; + } + + if( $this->filled ) { + $cord[$idx++] = $xt; + if( $this->fillFromMax ) { + $cord[$idx++] = $yscale->scale_abs[1]; + } + else { + if( $min > 0 || $this->fillFromMin ) { + $cord[$idx++] = $yscale->Translate($min); + } + else { + $cord[$idx++] = $yscale->Translate(0); + } + } + if( $this->fillgrad ) { + $img->SetLineWeight(1); + $grad = new Gradient($img); + $grad->SetNumColors($this->fillgrad_numcolors); + $grad->FilledFlatPolygon($cord,$this->fillgrad_fromcolor,$this->fillgrad_tocolor); + $img->SetLineWeight($this->weight); + } + else { + $img->SetColor($this->fill_color); + $img->FilledPolygon($cord); + } + if( $this->weight > 0 ) { + $img->SetLineWeight($this->weight); + $img->SetColor($this->color); + // Remove first and last coordinate before drawing the line + // sine we otherwise get the vertical start and end lines which + // doesn't look appropriate + $img->Polygon(array_slice($cord,2,count($cord)-4)); + } + } + + if(!empty($this->filledAreas)) { + + $minY = $yscale->Translate($yscale->GetMinVal()); + $factor = ($this->step_style ? 4 : 2); + + for($i = 0; $i < sizeof($this->filledAreas); ++$i) { + // go through all filled area elements ordered by insertion + // fill polygon array + $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor]; + $areaCoords[] = $minY; + + $areaCoords = + array_merge($areaCoords, + array_slice($cord, + $this->filledAreas[$i][0] * $factor, + ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1)) * $factor)); + $areaCoords[] = $areaCoords[sizeof($areaCoords)-2]; // last x + $areaCoords[] = $minY; // last y + + if($this->filledAreas[$i][3]) { + $img->SetColor($this->filledAreas[$i][2]); + $img->FilledPolygon($areaCoords); + $img->SetColor($this->color); + } + // Check if we should draw the frame. + // If not we still re-draw the line since it might have been + // partially overwritten by the filled area and it doesn't look + // very good. + if( $this->filledAreas[$i][4] ) { + $img->Polygon($areaCoords); + } + else { + $img->Polygon($cord); + } + + $areaCoords = array(); + } + } + + if( $this->mark->type == -1 || $this->mark->show == false ) + return; + + for( $pnts=0; $pnts<$numpoints; ++$pnts) { + + if( $exist_x ) { + $x=$this->coords[1][$pnts]; + } + else { + $x=$pnts+$textadj; + } + $xt = $xscale->Translate($x); + $yt = $yscale->Translate($this->coords[0][$pnts]); + + if( is_numeric($this->coords[0][$pnts]) ) { + if( !empty($this->csimtargets[$pnts]) ) { + if( !empty($this->csimwintargets[$pnts]) ) { + $this->mark->SetCSIMTarget($this->csimtargets[$pnts],$this->csimwintargets[$pnts]); + } + else { + $this->mark->SetCSIMTarget($this->csimtargets[$pnts]); + } + $this->mark->SetCSIMAlt($this->csimalts[$pnts]); + } + if( $exist_x ) { + $x=$this->coords[1][$pnts]; + } + else { + $x=$pnts; + } + $this->mark->SetCSIMAltVal($this->coords[0][$pnts],$x); + $this->mark->Stroke($img,$xt,$yt); + $this->csimareas .= $this->mark->GetCSIMAreas(); + } + } + } +} // Class + + +//=================================================== +// CLASS AccLinePlot +// Description: +//=================================================== +class AccLinePlot extends Plot { + protected $plots=null,$nbrplots=0; + private $iStartEndZero=true; + //--------------- + // CONSTRUCTOR + function __construct($plots) { + $this->plots = $plots; + $this->nbrplots = count($plots); + $this->numpoints = $plots[0]->numpoints; + + // Verify that all plots have the same number of data points + for( $i=1; $i < $this->nbrplots; ++$i ) { + if( $plots[$i]->numpoints != $this->numpoints ) { + JpGraphError::RaiseL(10003);//('Each plot in an accumulated lineplot must have the same number of data points',0) + } + } + + for($i=0; $i < $this->nbrplots; ++$i ) { + $this->LineInterpolate($this->plots[$i]->coords[0]); + } + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + foreach( $this->plots as $p ) { + $p->DoLegend($graph); + } + } + + function Max() { + list($xmax) = $this->plots[0]->Max(); + $nmax=0; + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + $nc = count($this->plots[$i]->coords[0]); + $nmax = max($nmax,$nc); + list($x) = $this->plots[$i]->Max(); + $xmax = Max($xmax,$x); + } + for( $i = 0; $i < $nmax; $i++ ) { + // Get y-value for line $i by adding the + // individual bars from all the plots added. + // It would be wrong to just add the + // individual plots max y-value since that + // would in most cases give to large y-value. + $y=$this->plots[0]->coords[0][$i]; + for( $j = 1; $j < $this->nbrplots; $j++ ) { + $y += $this->plots[ $j ]->coords[0][$i]; + } + $ymax[$i] = $y; + } + $ymax = max($ymax); + return array($xmax,$ymax); + } + + function Min() { + $nmax=0; + list($xmin,$ysetmin) = $this->plots[0]->Min(); + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + $nc = count($this->plots[$i]->coords[0]); + $nmax = max($nmax,$nc); + list($x,$y) = $this->plots[$i]->Min(); + $xmin = Min($xmin,$x); + $ysetmin = Min($y,$ysetmin); + } + for( $i = 0; $i < $nmax; $i++ ) { + // Get y-value for line $i by adding the + // individual bars from all the plots added. + // It would be wrong to just add the + // individual plots min y-value since that + // would in most cases give to small y-value. + $y=$this->plots[0]->coords[0][$i]; + for( $j = 1; $j < $this->nbrplots; $j++ ) { + $y += $this->plots[ $j ]->coords[0][$i]; + } + $ymin[$i] = $y; + } + $ymin = Min($ysetmin,Min($ymin)); + return array($xmin,$ymin); + } + + // Gets called before any axis are stroked + function PreStrokeAdjust($graph) { + + // If another plot type have already adjusted the + // offset we don't touch it. + // (We check for empty in case the scale is a log scale + // and hence doesn't contain any xlabel_offset) + + if( empty($graph->xaxis->scale->ticks->xlabel_offset) || + $graph->xaxis->scale->ticks->xlabel_offset == 0 ) { + if( $this->center ) { + ++$this->numpoints; + $a=0.5; $b=0.5; + } else { + $a=0; $b=0; + } + $graph->xaxis->scale->ticks->SetXLabelOffset($a); + $graph->SetTextScaleOff($b); + $graph->xaxis->scale->ticks->SupressMinorTickMarks(); + } + + } + + function SetInterpolateMode($aIntMode) { + $this->iStartEndZero=$aIntMode; + } + + // Replace all '-' with an interpolated value. We use straightforward + // linear interpolation. If the data starts with one or several '-' they + // will be replaced by the the first valid data point + function LineInterpolate(&$aData) { + + $n=count($aData); + $i=0; + + // If first point is undefined we will set it to the same as the first + // valid data + if( $aData[$i]==='-' ) { + // Find the first valid data + while( $i < $n && $aData[$i]==='-' ) { + ++$i; + } + if( $i < $n ) { + for($j=0; $j < $i; ++$j ) { + if( $this->iStartEndZero ) + $aData[$i] = 0; + else + $aData[$j] = $aData[$i]; + } + } + else { + // All '-' => Error + return false; + } + } + + while($i < $n) { + while( $i < $n && $aData[$i] !== '-' ) { + ++$i; + } + if( $i < $n ) { + $pstart=$i-1; + + // Now see how long this segment of '-' are + while( $i < $n && $aData[$i] === '-' ) { + ++$i; + } + if( $i < $n ) { + $pend=$i; + $size=$pend-$pstart; + $k=($aData[$pend]-$aData[$pstart])/$size; + // Replace the segment of '-' with a linear interpolated value. + for($j=1; $j < $size; ++$j ) { + $aData[$pstart+$j] = $aData[$pstart] + $j*$k ; + } + } + else { + // There are no valid end point. The '-' goes all the way to the end + // In that case we just set all the remaining values the the same as the + // last valid data point. + for( $j=$pstart+1; $j < $n; ++$j ) + if( $this->iStartEndZero ) { + $aData[$j] = 0; + } + else { + $aData[$j] = $aData[$pstart] ; + } + } + } + } + return true; + } + + // To avoid duplicate of line drawing code here we just + // change the y-values for each plot and then restore it + // after we have made the stroke. We must do this copy since + // it wouldn't be possible to create an acc line plot + // with the same graphs, i.e AccLinePlot(array($pl,$pl,$pl)); + // since this method would have a side effect. + function Stroke($img,$xscale,$yscale) { + $img->SetLineWeight($this->weight); + $this->numpoints = count($this->plots[0]->coords[0]); + // Allocate array + $coords[$this->nbrplots][$this->numpoints]=0; + for($i=0; $i<$this->numpoints; $i++) { + $coords[0][$i]=$this->plots[0]->coords[0][$i]; + $accy=$coords[0][$i]; + for($j=1; $j<$this->nbrplots; ++$j ) { + $coords[$j][$i] = $this->plots[$j]->coords[0][$i]+$accy; + $accy = $coords[$j][$i]; + } + } + for($j=$this->nbrplots-1; $j>=0; --$j) { + $p=$this->plots[$j]; + for( $i=0; $i<$this->numpoints; ++$i) { + $tmp[$i]=$p->coords[0][$i]; + $p->coords[0][$i]=$coords[$j][$i]; + } + $p->Stroke($img,$xscale,$yscale); + for( $i=0; $i<$this->numpoints; ++$i) { + $p->coords[0][$i]=$tmp[$i]; + } + $p->coords[0][]=$tmp; + } + } +} // Class + + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_log.php b/web/public_php/admin/jpgraph/jpgraph_log.php index d9561f56e..2f7e4e86b 100644 --- a/web/public_php/admin/jpgraph/jpgraph_log.php +++ b/web/public_php/admin/jpgraph/jpgraph_log.php @@ -1,268 +1,305 @@ -ticks = new LogTicks(); - $this->name = 'log'; - } - -//---------------- -// PUBLIC METHODS - - // Translate between world and screen - function Translate($a) { - if( !is_numeric($a) ) { - if( $a != '' && $a != '-' && $a != 'x' ) - JpGraphError::RaiseL(11001); -//('Your data contains non-numeric values.'); - return 1; - } - if( $a < 0 ) { - JpGraphError::RaiseL(11002); -//("Negative data values can not be used in a log scale."); - exit(1); - } - if( $a==0 ) $a=1; - $a=log10($a); - return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor); - } - - // Relative translate (don't include offset) usefull when we just want - // to know the relative position (in pixels) on the axis - function RelTranslate($a) { - if( !is_numeric($a) ) { - if( $a != '' && $a != '-' && $a != 'x' ) - JpGraphError::RaiseL(11001); -//('Your data contains non-numeric values.'); - return 1; - } - if( $a==0 ) $a=1; - $a=log10($a); - return round(($a*1.0 - $this->scale[0]) * $this->scale_factor); - } - - // Use bcpow() for increased precision - function GetMinVal() { - if( function_exists("bcpow") ) - return round(bcpow(10,$this->scale[0],15),14); - else - return round(pow(10,$this->scale[0]),14); - } - - function GetMaxVal() { - if( function_exists("bcpow") ) - return round(bcpow(10,$this->scale[1],15),14); - else - return round(pow(10,$this->scale[1]),14); - } - - // Logarithmic autoscaling is much simplier since we just - // set the min and max to logs of the min and max values. - // Note that for log autoscale the "maxstep" the fourth argument - // isn't used. This is just included to give the method the same - // signature as the linear counterpart. - function AutoScale(&$img,$min,$max,$dummy, $dummy2 = true) { - if( $min==0 ) $min=1; - - if( $max <= 0 ) { - JpGraphError::RaiseL(11004); -//('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.'); - } - $smin = floor(log10($min)); - $smax = ceil(log10($max)); - $this->Update($img,$smin,$smax); - } -//--------------- -// PRIVATE METHODS -} // Class - -//=================================================== -// CLASS LogTicks -// Description: -//=================================================== -class LogTicks extends Ticks{ - var $label_logtype=LOGLABELS_MAGNITUDE; -//--------------- -// CONSTRUCTOR - function __construct() { - parent::__construct(); - } -//--------------- -// PUBLIC METHODS - function IsSpecified() { - return true; - } - - function SetLabelLogType($aType) { - $this->label_logtype = $aType; - } - - // For log scale it's meaningless to speak about a major step - // We just return -1 to make the framework happy (specifically - // StrokeLabels() ) - function GetMajor() { - return -1; - } - - function SetTextLabelStart($aStart) { - JpGraphError::RaiseL(11005); -//('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.'); - } - - function SetXLabelOffset($dummy) { - // For log scales we dont care about XLabel offset - } - - // Draw ticks on image "img" using scale "scale". The axis absolute - // position in the image is specified in pos, i.e. for an x-axis - // it specifies the absolute y-coord and for Y-ticks it specified the - // absolute x-position. - function Stroke(&$img,&$scale,$pos) { - $start = $scale->GetMinVal(); - $limit = $scale->GetMaxVal(); - $nextMajor = 10*$start; - $step = $nextMajor / 10.0; - - - $img->SetLineWeight($this->weight); - - if( $scale->type == "y" ) { - // member direction specified if the ticks should be on - // left or right side. - $a=$pos + $this->direction*$this->GetMinTickAbsSize(); - $a2=$pos + $this->direction*$this->GetMajTickAbsSize(); - - $count=1; - $this->maj_ticks_pos[0]=$scale->Translate($start); - $this->maj_ticklabels_pos[0]=$scale->Translate($start); - if( $this->supress_first ) - $this->maj_ticks_label[0]=""; - else { - if( $this->label_formfunc != '' ) { - $f = $this->label_formfunc; - $this->maj_ticks_label[0]=call_user_func($f,$start); - } - elseif( $this->label_logtype == LOGLABELS_PLAIN ) - $this->maj_ticks_label[0]=$start; - else - $this->maj_ticks_label[0]='10^'.round(log10($start)); - } - $i=1; - for($y=$start; $y<=$limit; $y+=$step,++$count ) { - $ys=$scale->Translate($y); - $this->ticks_pos[]=$ys; - $this->ticklabels_pos[]=$ys; - if( $count % 10 == 0 ) { - if( !$this->supress_tickmarks ) { - if( $this->majcolor!="" ) { - $img->PushColor($this->majcolor); - $img->Line($pos,$ys,$a2,$ys); - $img->PopColor(); - } - else - $img->Line($pos,$ys,$a2,$ys); - } - - $this->maj_ticks_pos[$i]=$ys; - $this->maj_ticklabels_pos[$i]=$ys; - - if( $this->label_formfunc != '' ) { - $f = $this->label_formfunc; - $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor); - } - elseif( $this->label_logtype == 0 ) - $this->maj_ticks_label[$i]=$nextMajor; - else - $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor)); - ++$i; - $nextMajor *= 10; - $step *= 10; - $count=1; - } - else { - if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { - if( $this->mincolor!="" ) $img->PushColor($this->mincolor); - $img->Line($pos,$ys,$a,$ys); - if( $this->mincolor!="" ) $img->PopColor(); - } - } - } - } - else { - $a=$pos - $this->direction*$this->GetMinTickAbsSize(); - $a2=$pos - $this->direction*$this->GetMajTickAbsSize(); - $count=1; - $this->maj_ticks_pos[0]=$scale->Translate($start); - $this->maj_ticklabels_pos[0]=$scale->Translate($start); - if( $this->supress_first ) - $this->maj_ticks_label[0]=""; - else { - if( $this->label_formfunc != '' ) { - $f = $this->label_formfunc; - $this->maj_ticks_label[0]=call_user_func($f,$start); - } - elseif( $this->label_logtype == 0 ) - $this->maj_ticks_label[0]=$start; - else - $this->maj_ticks_label[0]='10^'.round(log10($start)); - } - $i=1; - for($x=$start; $x<=$limit; $x+=$step,++$count ) { - $xs=$scale->Translate($x); - $this->ticks_pos[]=$xs; - $this->ticklabels_pos[]=$xs; - if( $count % 10 == 0 ) { - if( !$this->supress_tickmarks ) { - $img->Line($xs,$pos,$xs,$a2); - } - $this->maj_ticks_pos[$i]=$xs; - $this->maj_ticklabels_pos[$i]=$xs; - - if( $this->label_formfunc != '' ) { - $f = $this->label_formfunc; - $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor); - } - elseif( $this->label_logtype == 0 ) - $this->maj_ticks_label[$i]=$nextMajor; - else - $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor)); - ++$i; - $nextMajor *= 10; - $step *= 10; - $count=1; - } - else { - if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { - $img->Line($xs,$pos,$xs,$a); - } - } - } - } - return true; - } -} // Class -/* EOF */ -?> +ticks = new LogTicks(); + $this->name = 'log'; + } + + //---------------- + // PUBLIC METHODS + + // Translate between world and screen + function Translate($a) { + if( !is_numeric($a) ) { + if( $a != '' && $a != '-' && $a != 'x' ) { + JpGraphError::RaiseL(11001); + // ('Your data contains non-numeric values.'); + } + return 1; + } + if( $a < 0 ) { + JpGraphError::RaiseL(11002); + //("Negative data values can not be used in a log scale."); + exit(1); + } + if( $a==0 ) $a=1; + $a=log10($a); + return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor); + } + + // Relative translate (don't include offset) usefull when we just want + // to know the relative position (in pixels) on the axis + function RelTranslate($a) { + if( !is_numeric($a) ) { + if( $a != '' && $a != '-' && $a != 'x' ) { + JpGraphError::RaiseL(11001); + //('Your data contains non-numeric values.'); + } + return 1; + } + if( $a==0 ) { + $a=1; + } + $a=log10($a); + return round(($a*1.0 - $this->scale[0]) * $this->scale_factor); + } + + // Use bcpow() for increased precision + function GetMinVal() { + if( function_exists("bcpow") ) { + return round(bcpow(10,$this->scale[0],15),14); + } + else { + return round(pow(10,$this->scale[0]),14); + } + } + + function GetMaxVal() { + if( function_exists("bcpow") ) { + return round(bcpow(10,$this->scale[1],15),14); + } + else { + return round(pow(10,$this->scale[1]),14); + } + } + + // Logarithmic autoscaling is much simplier since we just + // set the min and max to logs of the min and max values. + // Note that for log autoscale the "maxstep" the fourth argument + // isn't used. This is just included to give the method the same + // signature as the linear counterpart. + function AutoScale($img,$min,$max,$maxsteps,$majend=true) { + if( $min==0 ) $min=1; + + if( $max <= 0 ) { + JpGraphError::RaiseL(11004); + //('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.'); + } + if( is_numeric($this->autoscale_min) ) { + $smin = round($this->autoscale_min); + $smax = ceil(log10($max)); + if( $min >= $max ) { + 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.'); + } + } + else { + $smin = floor(log10($min)); + if( is_numeric($this->autoscale_max) ) { + $smax = round($this->autoscale_max); + if( $smin >= $smax ) { + 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.'); + } + } + else + $smax = ceil(log10($max)); + } + + $this->Update($img,$smin,$smax); + } + //--------------- + // PRIVATE METHODS +} // Class + +//=================================================== +// CLASS LogTicks +// Description: +//=================================================== +class LogTicks extends Ticks{ + private $label_logtype=LOGLABELS_MAGNITUDE; + private $ticklabels_pos = array(); + //--------------- + // CONSTRUCTOR + function __construct() { + } + //--------------- + // PUBLIC METHODS + function IsSpecified() { + return true; + } + + function SetLabelLogType($aType) { + $this->label_logtype = $aType; + } + + // For log scale it's meaningless to speak about a major step + // We just return -1 to make the framework happy (specifically + // StrokeLabels() ) + function GetMajor() { + return -1; + } + + function SetTextLabelStart($aStart) { + JpGraphError::RaiseL(11005); + //('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.'); + } + + function SetXLabelOffset($dummy) { + // For log scales we dont care about XLabel offset + } + + // Draw ticks on image "img" using scale "scale". The axis absolute + // position in the image is specified in pos, i.e. for an x-axis + // it specifies the absolute y-coord and for Y-ticks it specified the + // absolute x-position. + function Stroke($img,$scale,$pos) { + $start = $scale->GetMinVal(); + $limit = $scale->GetMaxVal(); + $nextMajor = 10*$start; + $step = $nextMajor / 10.0; + + + $img->SetLineWeight($this->weight); + + if( $scale->type == "y" ) { + // member direction specified if the ticks should be on + // left or right side. + $a=$pos + $this->direction*$this->GetMinTickAbsSize(); + $a2=$pos + $this->direction*$this->GetMajTickAbsSize(); + + $count=1; + $this->maj_ticks_pos[0]=$scale->Translate($start); + $this->maj_ticklabels_pos[0]=$scale->Translate($start); + if( $this->supress_first ) + $this->maj_ticks_label[0]=""; + else { + if( $this->label_formfunc != '' ) { + $f = $this->label_formfunc; + $this->maj_ticks_label[0]=call_user_func($f,$start); + } + elseif( $this->label_logtype == LOGLABELS_PLAIN ) { + $this->maj_ticks_label[0]=$start; + } + else { + $this->maj_ticks_label[0]='10^'.round(log10($start)); + } + } + $i=1; + for($y=$start; $y<=$limit; $y+=$step,++$count ) { + $ys=$scale->Translate($y); + $this->ticks_pos[]=$ys; + $this->ticklabels_pos[]=$ys; + if( $count % 10 == 0 ) { + if( !$this->supress_tickmarks ) { + if( $this->majcolor!="" ) { + $img->PushColor($this->majcolor); + $img->Line($pos,$ys,$a2,$ys); + $img->PopColor(); + } + else { + $img->Line($pos,$ys,$a2,$ys); + } + } + + $this->maj_ticks_pos[$i]=$ys; + $this->maj_ticklabels_pos[$i]=$ys; + + if( $this->label_formfunc != '' ) { + $f = $this->label_formfunc; + $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor); + } + elseif( $this->label_logtype == 0 ) { + $this->maj_ticks_label[$i]=$nextMajor; + } + else { + $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor)); + } + ++$i; + $nextMajor *= 10; + $step *= 10; + $count=1; + } + else { + if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { + if( $this->mincolor!="" ) { + $img->PushColor($this->mincolor); + } + $img->Line($pos,$ys,$a,$ys); + if( $this->mincolor!="" ) { + $img->PopColor(); + } + } + } + } + } + else { + $a=$pos - $this->direction*$this->GetMinTickAbsSize(); + $a2=$pos - $this->direction*$this->GetMajTickAbsSize(); + $count=1; + $this->maj_ticks_pos[0]=$scale->Translate($start); + $this->maj_ticklabels_pos[0]=$scale->Translate($start); + if( $this->supress_first ) { + $this->maj_ticks_label[0]=""; + } + else { + if( $this->label_formfunc != '' ) { + $f = $this->label_formfunc; + $this->maj_ticks_label[0]=call_user_func($f,$start); + } + elseif( $this->label_logtype == 0 ) { + $this->maj_ticks_label[0]=$start; + } + else { + $this->maj_ticks_label[0]='10^'.round(log10($start)); + } + } + $i=1; + for($x=$start; $x<=$limit; $x+=$step,++$count ) { + $xs=$scale->Translate($x); + $this->ticks_pos[]=$xs; + $this->ticklabels_pos[]=$xs; + if( $count % 10 == 0 ) { + if( !$this->supress_tickmarks ) { + $img->Line($xs,$pos,$xs,$a2); + } + $this->maj_ticks_pos[$i]=$xs; + $this->maj_ticklabels_pos[$i]=$xs; + + if( $this->label_formfunc != '' ) { + $f = $this->label_formfunc; + $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor); + } + elseif( $this->label_logtype == 0 ) { + $this->maj_ticks_label[$i]=$nextMajor; + } + else { + $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor)); + } + ++$i; + $nextMajor *= 10; + $step *= 10; + $count=1; + } + else { + if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { + $img->Line($xs,$pos,$xs,$a); + } + } + } + } + return true; + } +} // Class +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_meshinterpolate.inc.php b/web/public_php/admin/jpgraph/jpgraph_meshinterpolate.inc.php new file mode 100644 index 000000000..7e8ae5355 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_meshinterpolate.inc.php @@ -0,0 +1,105 @@ +Linear($aData,$aFactor); +} + +/** + * Utility class to interpolate a given data matrix + * + */ +class MeshInterpolate { + private $data = array(); + + /** + * Calculate the mid points of the given rectangle which has its top left + * corner at $row,$col. The $aFactordecides how many spliots should be done. + * i.e. how many more divisions should be done recursively + * + * @param $row Top left corner of square to work with + * @param $col Top left corner of square to work with + * $param $aFactor In how many subsquare should we split this square. A value of 1 indicates that no action + */ + function IntSquare( $aRow, $aCol, $aFactor ) { + if ( $aFactor <= 1 ) + return; + + $step = pow( 2, $aFactor-1 ); + + $v0 = $this->data[$aRow][$aCol]; + $v1 = $this->data[$aRow][$aCol + $step]; + $v2 = $this->data[$aRow + $step][$aCol]; + $v3 = $this->data[$aRow + $step][$aCol + $step]; + + $this->data[$aRow][$aCol + $step / 2] = ( $v0 + $v1 ) / 2; + $this->data[$aRow + $step / 2][$aCol] = ( $v0 + $v2 ) / 2; + $this->data[$aRow + $step][$aCol + $step / 2] = ( $v2 + $v3 ) / 2; + $this->data[$aRow + $step / 2][$aCol + $step] = ( $v1 + $v3 ) / 2; + $this->data[$aRow + $step / 2][$aCol + $step / 2] = ( $v0 + $v1 + $v2 + $v3 ) / 4; + + $this->IntSquare( $aRow, $aCol, $aFactor-1 ); + $this->IntSquare( $aRow, $aCol + $step / 2, $aFactor-1 ); + $this->IntSquare( $aRow + $step / 2, $aCol, $aFactor-1 ); + $this->IntSquare( $aRow + $step / 2, $aCol + $step / 2, $aFactor-1 ); + } + + /** + * Interpolate values in a matrice so that the total number of data points + * in vert and horizontal axis are $aIntNbr more. For example $aIntNbr=2 will + * make the data matrice have tiwce as many vertical and horizontal dta points. + * + * Note: This will blow up the matrcide in memory size in the order of $aInNbr^2 + * + * @param $ &$aData The original data matricde + * @param $aInNbr Interpolation factor + * @return the interpolated matrice + */ + function Linear( &$aData, $aIntFactor ) { + $step = pow( 2, $aIntFactor-1 ); + + $orig_cols = count( $aData[0] ); + $orig_rows = count( $aData ); + // Number of new columns/rows + // N = (a-1) * 2^(f-1) + 1 + $p = pow( 2, $aIntFactor-1 ); + $new_cols = $p * ( $orig_cols - 1 ) + 1; + $new_rows = $p * ( $orig_rows - 1 ) + 1; + + $this->data = array_fill( 0, $new_rows, array_fill( 0, $new_cols, 0 ) ); + // Initialize the new matrix with the values that we know + for ( $i = 0; $i < $new_rows; $i++ ) { + for ( $j = 0; $j < $new_cols; $j++ ) { + $v = 0 ; + if ( ( $i % $step == 0 ) && ( $j % $step == 0 ) ) { + $v = $aData[$i / $step][$j / $step]; + } + $this->data[$i][$j] = $v; + } + } + + for ( $i = 0; $i < $new_rows-1; $i += $step ) { + for ( $j = 0; $j < $new_cols-1; $j += $step ) { + $this->IntSquare( $i, $j, $aIntFactor ); + } + } + + return $this->data; + } +} + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_mgraph.php b/web/public_php/admin/jpgraph/jpgraph_mgraph.php new file mode 100644 index 000000000..80b2b6d71 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_mgraph.php @@ -0,0 +1,345 @@ +iWidth = $aWidth; + $this->iHeight = $aHeight; + + // If the cached version exist just read it directly from the + // cache, stream it back to browser and exit + if( $aCachedName!='' && READ_CACHE && $aInline ) { + $this->cache = new ImgStreamCache(); + $this->cache->SetTimeOut($aTimeOut); + $image = new Image(); + if( $this->cache->GetAndStream($image,$aCachedName) ) { + exit(); + } + } + $this->inline = $aInline; + $this->cache_name = $aCachedName; + + $this->title = new Text(); + $this->title->ParagraphAlign('center'); + $this->title->SetFont(FF_FONT2,FS_BOLD); + $this->title->SetMargin(3); + $this->title->SetAlign('center'); + + $this->subtitle = new Text(); + $this->subtitle->ParagraphAlign('center'); + $this->subtitle->SetFont(FF_FONT1,FS_BOLD); + $this->subtitle->SetMargin(3); + $this->subtitle->SetAlign('center'); + + $this->subsubtitle = new Text(); + $this->subsubtitle->ParagraphAlign('center'); + $this->subsubtitle->SetFont(FF_FONT1,FS_NORMAL); + $this->subsubtitle->SetMargin(3); + $this->subsubtitle->SetAlign('center'); + + $this->footer = new Footer(); + + } + + // Specify background fill color for the combined graph + function SetFillColor($aColor) { + $this->iFillColor = $aColor; + } + + // Add a frame around the combined graph + function SetFrame($aFlg,$aColor='black',$aWeight=1) { + $this->iDoFrame = $aFlg; + $this->iFrameColor = $aColor; + $this->iFrameWeight = $aWeight; + } + + // Specify a background image blend + function SetBackgroundImageMix($aMix) { + $this->background_image_mix = $aMix ; + } + + // Specify a background image + function SetBackgroundImage($aFileName,$aCenter_aX=NULL,$aY=NULL) { + // Second argument can be either a boolean value or + // a numeric + $aCenter=TRUE; + $aX=NULL; + + if( is_numeric($aCenter_aX) ) { + $aX=$aCenter_aX; + } + + // Get extension to determine image type + $e = explode('.',$aFileName); + if( !$e ) { + JpGraphError::RaiseL(12002,$aFileName); + //('Incorrect file name for MGraph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type'); + } + + $valid_formats = array('png', 'jpg', 'gif'); + $aImgFormat = strtolower($e[count($e)-1]); + if ($aImgFormat == 'jpeg') { + $aImgFormat = 'jpg'; + } + elseif (!in_array($aImgFormat, $valid_formats) ) { + JpGraphError::RaiseL(12003,$aImgFormat,$aFileName); + //('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName); + } + + $this->background_image = $aFileName; + $this->background_image_center=$aCenter; + $this->background_image_format=$aImgFormat; + $this->background_image_x = $aX; + $this->background_image_y = $aY; + } + + function _strokeBackgroundImage() { + if( $this->background_image == '' ) return; + + $bkgimg = Graph::LoadBkgImage('',$this->background_image); + + // Background width & Heoght + $bw = imagesx($bkgimg); + $bh = imagesy($bkgimg); + + // Canvas width and height + $cw = imagesx($this->img); + $ch = imagesy($this->img); + + if( $this->doshadow ) { + $cw -= $this->shadow_width; + $ch -= $this->shadow_width; + } + + if( $this->background_image_x === NULL || $this->background_image_y === NULL ) { + if( $this->background_image_center ) { + // Center original image in the plot area + $x = round($cw/2-$bw/2); $y = round($ch/2-$bh/2); + } + else { + // Just copy the image from left corner, no resizing + $x=0; $y=0; + } + } + else { + $x = $this->background_image_x; + $y = $this->background_image_y; + } + imagecopymerge($this->img,$bkgimg,$x,$y,0,0,$bw,$bh,$this->background_image_mix); + } + + function AddMix($aGraph,$x=0,$y=0,$mix=100,$fx=0,$fy=0,$w=0,$h=0) { + $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h,$mix); + } + + function Add($aGraph,$x=0,$y=0,$fx=0,$fy=0,$w=0,$h=0) { + $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h); + } + + function _gdImgHandle($agdCanvas,$x,$y,$fx=0,$fy=0,$w=0,$h=0,$mix=100) { + if( $w == 0 ) { + $w = @imagesx($agdCanvas); + } + if( $w === NULL ) { + JpGraphError::RaiseL(12007); + //('Argument to MGraph::Add() is not a valid GD image handle.'); + return; + } + if( $h == 0 ) { + $h = @imagesy($agdCanvas); + } + $this->iGraphs[$this->iCnt++] = array($agdCanvas,$x,$y,$fx,$fy,$w,$h,$mix); + } + + function SetMargin($lm,$rm,$tm,$bm) { + $this->lm = $lm; + $this->rm = $rm; + $this->tm = $tm; + $this->bm = $bm; + } + + function SetExpired($aFlg=true) { + $this->expired = $aFlg; + } + + function SetImgFormat($aFormat,$aQuality=75) { + $this->image_format = $aFormat; + $this->image_quality = $aQuality; + } + + // Set the shadow around the whole image + function SetShadow($aShowShadow=true,$aShadowWidth=4,$aShadowColor='gray@0.3') { + $this->doshadow = $aShowShadow; + $this->shadow_color = $aShadowColor; + $this->shadow_width = $aShadowWidth; + $this->footer->iBottomMargin += $aShadowWidth; + $this->footer->iRightMargin += $aShadowWidth; + } + + function StrokeTitle($image,$w,$h) { + // Stroke title + if( $this->title->t !== '' ) { + + $margin = 3; + + $y = $this->title->margin; + if( $this->title->halign == 'center' ) { + $this->title->Center(0,$w,$y); + } + elseif( $this->title->halign == 'left' ) { + $this->title->SetPos($this->title->margin+2,$y); + } + elseif( $this->title->halign == 'right' ) { + $indent = 0; + if( $this->doshadow ) { + $indent = $this->shadow_width+2; + } + $this->title->SetPos($w-$this->title->margin-$indent,$y,'right'); + } + $this->title->Stroke($image); + + // ... and subtitle + $y += $this->title->GetTextHeight($image) + $margin + $this->subtitle->margin; + if( $this->subtitle->halign == 'center' ) { + $this->subtitle->Center(0,$w,$y); + } + elseif( $this->subtitle->halign == 'left' ) { + $this->subtitle->SetPos($this->subtitle->margin+2,$y); + } + elseif( $this->subtitle->halign == 'right' ) { + $indent = 0; + if( $this->doshadow ) { + $indent = $this->shadow_width+2; + } + $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right'); + } + $this->subtitle->Stroke($image); + + // ... and subsubtitle + $y += $this->subtitle->GetTextHeight($image) + $margin + $this->subsubtitle->margin; + if( $this->subsubtitle->halign == 'center' ) { + $this->subsubtitle->Center(0,$w,$y); + } + elseif( $this->subsubtitle->halign == 'left' ) { + $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y); + } + elseif( $this->subsubtitle->halign == 'right' ) { + $indent = 0; + if( $this->doshadow ) { + $indent = $this->shadow_width+2; + } + $this->subsubtitle->SetPos($w-$this->subsubtitle->margin-$indent,$y,'right'); + } + $this->subsubtitle->Stroke($image); + + } + } + + function Stroke($aFileName='') { + // Find out the necessary size for the container image + $w=0; $h=0; + for($i=0; $i < $this->iCnt; ++$i ) { + $maxw = $this->iGraphs[$i][1]+$this->iGraphs[$i][5]; + $maxh = $this->iGraphs[$i][2]+$this->iGraphs[$i][6]; + $w = max( $w, $maxw ); + $h = max( $h, $maxh ); + } + $w += $this->lm+$this->rm; + $h += $this->tm+$this->bm; + + // User specified width,height overrides + if( $this->iWidth !== NULL && $this->iWidth !== 0 ) $w = $this->iWidth; + if( $this->iHeight!== NULL && $this->iHeight !== 0) $h = $this->iHeight; + + if( $this->doshadow ) { + $w += $this->shadow_width; + $h += $this->shadow_width; + } + + $image = new Image($w,$h); + $image->SetImgFormat( $this->image_format,$this->image_quality); + + if( $this->doshadow ) { + $image->SetColor($this->iFrameColor); + $image->ShadowRectangle(0,0,$w-1,$h-1,$this->iFillColor,$this->shadow_width,$this->shadow_color); + $w -= $this->shadow_width; + $h -= $this->shadow_width; + } + else { + $image->SetColor($this->iFillColor); + $image->FilledRectangle(0,0,$w-1,$h-1); + } + $image->SetExpired($this->expired); + + $this->img = $image->img; + $this->_strokeBackgroundImage(); + + if( $this->iDoFrame && ! $this->doshadow ) { + $image->SetColor($this->iFrameColor); + $image->SetLineWeight($this->iFrameWeight); + $image->Rectangle(0,0,$w-1,$h-1); + } + + // Copy all sub graphs to the container + for($i=0; $i < $this->iCnt; ++$i ) { + $image->CopyMerge($this->iGraphs[$i][0], + $this->iGraphs[$i][1]+$this->lm,$this->iGraphs[$i][2]+$this->tm, + $this->iGraphs[$i][3],$this->iGraphs[$i][4], + $this->iGraphs[$i][5],$this->iGraphs[$i][6], + -1,-1, /* Full from width and height */ + $this->iGraphs[$i][7]); + + + } + + $this->StrokeTitle($image,$w,$h); + $this->footer->Stroke($image); + + // Output image + if( $aFileName == _IMG_HANDLER ) { + return $image->img; + } + else { + //Finally stream the generated picture + $this->cache = new ImgStreamCache(); + $this->cache->PutAndStream($image,$this->cache_name,$this->inline,$aFileName); + } + } +} + +// EOF + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_pie.php b/web/public_php/admin/jpgraph/jpgraph_pie.php index d9a1abd16..2bc1deb6a 100644 --- a/web/public_php/admin/jpgraph/jpgraph_pie.php +++ b/web/public_php/admin/jpgraph/jpgraph_pie.php @@ -1,1341 +1,1499 @@ - array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430), - "pastel" => array(27,415,128,59,66,79,105,110,42,147,152,230,236,240,331,337,405,38), - "water" => array(8,370,24,40,335,56,213,237,268,14,326,387,10,388), - "sand" => array(27,168,34,170,19,50,65,72,131,209,46,393)); - var $theme="earth"; - var $setslicecolors=array(); - var $labeltype=0; // Default to percentage - var $pie_border=true,$pie_interior_border=true; - var $value; - var $ishadowcolor='',$ishadowdrop=4; - var $ilabelposadj=1; - var $legendcsimtargets = array(); - var $legendcsimalts = array(); - var $adjusted_data = array(); - var $guideline = null,$guidelinemargin=10; - var $iShowGuideLineForSingle = false; - var $iGuideLineCurve = false,$iGuideVFactor=1.4,$iGuideLineRFactor=0.8; -//--------------- -// CONSTRUCTOR - function PiePlot($data) { - $this->data = array_reverse($data); - $this->title = new Text(""); - $this->title->SetFont(FF_FONT1,FS_BOLD); - $this->value = new DisplayValue(); - $this->value->Show(); - $this->value->SetFormat('%.1f%%'); - $this->guideline = new LineProperty(); - } - -//--------------- -// PUBLIC METHODS - function SetCenter($x,$y=0.5) { - $this->posx = $x; - $this->posy = $y; - } - - // Enable guideline and set drwaing policy - function SetGuideLines($aFlg=true,$aCurved=true,$aAlways=false) { - $this->guideline->Show($aFlg); - $this->iShowGuideLineForSingle = $aAlways; - $this->iGuideLineCurve = $aCurved; - } - - // Adjuste the distance between labels and labels and pie - function SetGuideLinesAdjust($aVFactor,$aRFactor=0.8) { - $this->iGuideVFactor=$aVFactor; - $this->iGuideLineRFactor=$aRFactor; - } - - function SetColor($aColor) { - $this->color = $aColor; - } - - function SetSliceColors($aColors) { - $this->setslicecolors = $aColors; - } - - function SetShadow($aColor='darkgray',$aDropWidth=4) { - $this->ishadowcolor = $aColor; - $this->ishadowdrop = $aDropWidth; - } - - function SetCSIMTargets($targets,$alts=null) { - $this->csimtargets=array_reverse($targets); - if( is_array($alts) ) - $this->csimalts=array_reverse($alts); - } - - function GetCSIMareas() { - return $this->csimareas; - } - - function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { - - //Slice number, ellipse centre (x,y), height, width, start angle, end angle - while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI; - while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI; - - $sa = 2*M_PI - $sa; - $ea = 2*M_PI - $ea; - - // Special case when we have only one slice since then both start and end - // angle will be == 0 - if( abs($sa - $ea) < 0.0001 ) { - $sa=2*M_PI; $ea=0; - } - - //add coordinates of the centre to the map - $xc = floor($xc);$yc=floor($yc); - $coords = "$xc, $yc"; - - //add coordinates of the first point on the arc to the map - $xp = floor(($radius*cos($ea))+$xc); - $yp = floor($yc-$radius*sin($ea)); - $coords.= ", $xp, $yp"; - //add coordinates every 0.2 radians - $a=$ea+0.2; - - // If we cross the 260-limit with a slice we need to handle - // the fact that end angle is smaller than start - if( $sa < $ea ) { - while ($a <= 2*M_PI) { - $xp = floor($radius*cos($a)+$xc); - $yp = floor($yc-$radius*sin($a)); - $coords.= ", $xp, $yp"; - $a += 0.2; - } - $a -= 2*M_PI; - } - - while ($a < $sa) { - $xp = floor($radius*cos($a)+$xc); - $yp = floor($yc-$radius*sin($a)); - $coords.= ", $xp, $yp"; - $a += 0.2; - } - - //Add the last point on the arc - $xp = floor($radius*cos($sa)+$xc); - $yp = floor($yc-$radius*sin($sa)); - $coords.= ", $xp, $yp"; - if( !empty($this->csimtargets[$i]) ) { - $this->csimareas .= "csimtargets[$i]."\""; - $tmp=""; - if( !empty($this->csimalts[$i]) ) { - $tmp=sprintf($this->csimalts[$i],$this->data[$i]); - $this->csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"$tmp\" />\n"; - } - } - - - function SetTheme($aTheme) { - if( in_array($aTheme,array_keys($this->themearr)) ) - $this->theme = $aTheme; - else - JpGraphError::RaiseL(15001,$aTheme);//("PiePLot::SetTheme() Unknown theme: $aTheme"); - } - - function ExplodeSlice($e,$radius=20) { - if( ! is_integer($e) ) - JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer'); - $this->explode_radius[$e]=$radius; - } - - function ExplodeAll($radius=20) { - $this->explode_all=true; - $this->explode_r = $radius; - } - - function Explode($aExplodeArr) { - if( !is_array($aExplodeArr) ) { - JpGraphError::RaiseL(15003); -//("Argument to PiePlot::Explode() must be an array with integer distances."); - } - $this->explode_radius = $aExplodeArr; - } - - function SetStartAngle($aStart) { - if( $aStart < 0 || $aStart > 360 ) { - JpGraphError::RaiseL(15004);//('Slice start angle must be between 0 and 360 degrees.'); - } - $this->startangle = 360-$aStart; - $this->startangle *= M_PI/180; - } - - function SetFont($family,$style=FS_NORMAL,$size=10) { - JpGraphError::RaiseL(15005);//('PiePlot::SetFont() is deprecated. Use PiePlot->value->SetFont() instead.'); - } - - // Size in percentage - function SetSize($aSize) { - if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) ) - $this->radius = $aSize; - else - JpGraphError::RaiseL(15006); -//("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]"); - } - - function SetFontColor($aColor) { - JpGraphError::RaiseL(15007); -//('PiePlot::SetFontColor() is deprecated. Use PiePlot->value->SetColor() instead.'); - } - - // Set label arrays - function SetLegends($aLegend) { - $this->legends = $aLegend; - } - - // Set text labels for slices - function SetLabels($aLabels,$aLblPosAdj="auto") { - $this->labels = array_reverse($aLabels); - $this->ilabelposadj=$aLblPosAdj; - } - - function SetLabelPos($aLblPosAdj) { - $this->ilabelposadj=$aLblPosAdj; - } - - // Should we display actual value or percentage? - function SetLabelType($t) { - if( $t < 0 || $t > 2 ) - JpGraphError::RaiseL(15008,$t); -//("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t)."); - $this->labeltype=$t; - } - - // Deprecated. - function SetValueType($aType) { - $this->SetLabelType($aType); - } - - // Should the circle around a pie plot be displayed - function ShowBorder($exterior=true,$interior=true) { - $this->pie_border = $exterior; - $this->pie_interior_border = $interior; - } - - // Setup the legends (Framework method) - function Legend(&$graph) { - $colors = array_keys($graph->img->rgb->rgb_table); - sort($colors); - $ta=$this->themearr[$this->theme]; - $n = count($this->data); - - if( $this->setslicecolors==null ) { - $numcolors=count($ta); - if( is_a($this,'PiePlot3D') ) { - $ta = array_reverse(array_slice($ta,0,$n)); - } - } - else { - $this->setslicecolors = array_slice($this->setslicecolors,0,$n); - $numcolors=count($this->setslicecolors); - if( $graph->pieaa && is_a($this,'PiePlot') ) { - $this->setslicecolors = array_reverse($this->setslicecolors); - } - } - - $sum=0; - for($i=0; $i < $n; ++$i) - $sum += $this->data[$i]; - - // Bail out with error if the sum is 0 - if( $sum==0 ) - JpGraphError::RaiseL(15009);//("Illegal pie plot. Sum of all data is zero for Pie!"); - - // Make sure we don't plot more values than data points - // (in case the user added more legends than data points) - $n = min(count($this->legends),count($this->data)); - if( $this->legends != "" ) { - $this->legends = array_reverse(array_slice($this->legends,0,$n)); - } - for( $i=$n-1; $i >= 0; --$i ) { - $l = $this->legends[$i]; - // Replace possible format with actual values - if( count($this->csimalts) > $i ) { - $fmt = $this->csimalts[$i]; - } - else { - $fmt = "%d"; // Deafult Alt if no other has been specified - } - if( $this->labeltype==0 ) { - $l = sprintf($l,100*$this->data[$i]/$sum); - $alt = sprintf($fmt,$this->data[$i]); - - } - elseif( $this->labeltype == 1) { - $l = sprintf($l,$this->data[$i]); - $alt = sprintf($fmt,$this->data[$i]); - - } - else { - $l = sprintf($l,$this->adjusted_data[$i]); - $alt = sprintf($fmt,$this->adjusted_data[$i]); - } - - if( $this->setslicecolors==null ) { - $graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,$this->csimtargets[$i],$alt); - } - else { - $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,$this->csimtargets[$i],$alt); - } - } - } - - // Adjust the rounded percetage value so that the sum of - // of the pie slices are always 100% - // Using the Hare/Niemeyer method - function AdjPercentage($aData,$aPrec=0) { - $mul=100; - if( $aPrec > 0 && $aPrec < 3 ) { - if( $aPrec == 1 ) - $mul=1000; - else - $mul=10000; - } - - $tmp = array(); - $result = array(); - $quote_sum=0; - $n = count($aData) ; - for( $i=0, $sum=0; $i < $n; ++$i ) - $sum+=$aData[$i]; - foreach($aData as $index => $value) { - $tmp_percentage=$value/$sum*$mul; - $result[$index]=floor($tmp_percentage); - $tmp[$index]=$tmp_percentage-$result[$index]; - $quote_sum+=$result[$index]; - } - if( $quote_sum == $mul) { - if( $mul > 100 ) { - $tmp = $mul / 100; - for( $i=0; $i < $n; ++$i ) { - $result[$i] /= $tmp ; - } - } - return $result; - } - arsort($tmp,SORT_NUMERIC); - reset($tmp); - for($i=0; $i < $mul-$quote_sum; $i++) - { - $result[key($tmp)]++; - next($tmp); - } - if( $mul > 100 ) { - $tmp = $mul / 100; - for( $i=0; $i < $n; ++$i ) { - $result[$i] /= $tmp ; - } - } - return $result; - } - - - function Stroke(&$img,$aaoption=0) { - // aaoption is used to handle antialias - // aaoption == 0 a normal pie - // aaoption == 1 just the body - // aaoption == 2 just the values - - // Explode scaling. If anti anti alias we scale the image - // twice and we also need to scale the exploding distance - $expscale = $aaoption === 1 ? 2 : 1; - - if( $this->labeltype == 2 ) { - // Adjust the data so that it will add up to 100% - $this->adjusted_data = $this->AdjPercentage($this->data); - } - - $colors = array_keys($img->rgb->rgb_table); - sort($colors); - $ta=$this->themearr[$this->theme]; - $n = count($this->data); - - if( $this->setslicecolors==null ) { - $numcolors=count($ta); - } - else { - $this->setslicecolors = array_reverse(array_slice($this->setslicecolors,0,$n)); - $numcolors=count($this->setslicecolors); - $tt = array_slice($this->setslicecolors,$n % $numcolors); - $tt2 = array_slice($this->setslicecolors,0,$n % $numcolors); - $tt2 = array_merge($tt, $tt2); - $this->setslicecolors = $tt + $tt2; - } - - // Draw the slices - $sum=0; - for($i=0; $i < $n; ++$i) - $sum += $this->data[$i]; - - // Bail out with error if the sum is 0 - if( $sum==0 ) - JpGraphError::RaiseL(15009);//("Sum of all data is 0 for Pie."); - - // Set up the pie-circle - if( $this->radius <= 1 ) - $radius = floor($this->radius*min($img->width,$img->height)); - else { - $radius = $aaoption === 1 ? $this->radius*2 : $this->radius; - } - - if( $this->posx <= 1 && $this->posx > 0 ) - $xc = round($this->posx*$img->width); - else - $xc = $this->posx ; - - if( $this->posy <= 1 && $this->posy > 0 ) - $yc = round($this->posy*$img->height); - else - $yc = $this->posy ; - - $n = count($this->data); - - if( $this->explode_all ) - for($i=0; $i < $n; ++$i) - $this->explode_radius[$i]=$this->explode_r; - - if( $this->ishadowcolor != "" && $aaoption !== 2) { - $accsum=0; - $angle2 = $this->startangle; - $img->SetColor($this->ishadowcolor); - for($i=0; $sum > 0 && $i < $n; ++$i) { - $j = $n-$i-1; - $d = $this->data[$i]; - $angle1 = $angle2; - $accsum += $d; - $angle2 = $this->startangle+2*M_PI*$accsum/$sum; - if( empty($this->explode_radius[$j]) ) - $this->explode_radius[$j]=0; - - $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); - - $xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale; - $ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale; - - $xcm += $this->ishadowdrop*$expscale; - $ycm += $this->ishadowdrop*$expscale; - - $img->CakeSlice($xcm,$ycm,$radius,$radius, - $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor); - - } - } - - $accsum=0; - $angle2 = $this->startangle; - $img->SetColor($this->color); - for($i=0; $sum>0 && $i < $n; ++$i) { - $j = $n-$i-1; - if( empty($this->explode_radius[$j]) ) - $this->explode_radius[$j]=0; - $d = $this->data[$i]; - $angle1 = $angle2; - $accsum += $d; - $angle2 = $this->startangle+2*M_PI*$accsum/$sum; - $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); - - if( $d == 0 ) continue; - - if( $this->setslicecolors==null ) - $slicecolor=$colors[$ta[$i%$numcolors]]; - else - $slicecolor=$this->setslicecolors[$i%$numcolors]; - - if( $this->pie_interior_border && $aaoption===0 ) - $img->SetColor($this->color); - else - $img->SetColor($slicecolor); - - $arccolor = $this->pie_border && $aaoption===0 ? $this->color : ""; - - $xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale; - $ycm = $yc - $this->explode_radius[$j]*sin($this->la[$i])*$expscale; - - if( $aaoption !== 2 ) { - $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1, - $angle1*180/M_PI,$angle2*180/M_PI,$slicecolor,$arccolor); - } - - if( $this->csimtargets && $aaoption !== 1 ) { - $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2); - } - } - - // Format the titles for each slice - if( $aaoption!==2) { - for( $i=0; $i < $n; ++$i) { - if( $this->labeltype==0 ) { - if( $sum != 0 ) - $l = 100.0*$this->data[$i]/$sum; - else - $l = 0.0; - } - elseif( $this->labeltype==1 ) { - $l = $this->data[$i]*1.0; - } - else { - $l = $this->adjusted_data[$i]; - } - if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) - $this->labels[$i]=sprintf($this->labels[$i],$l); - else - $this->labels[$i]=$l; - } - } - - If( $this->value->show && $aaoption !== 1 ) { - $this->StrokeAllLabels($img,$xc,$yc,$radius); - } - - // Adjust title position - if( $aaoption !== 1 ) { - $this->title->Pos($xc, - $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin, - "center","bottom"); - $this->title->Stroke($img); - } - - } - -//--------------- -// PRIVATE METHODS - - function NormAngle($a) { - while( $a < 0 ) $a += 2*M_PI; - while( $a > 2*M_PI ) $a -= 2*M_PI; - return $a; - } - - function Quadrant($a) { - $a=$this->NormAngle($a); - if( $a > 0 && $a <= M_PI/2 ) - return 0; - if( $a > M_PI/2 && $a <= M_PI ) - return 1; - if( $a > M_PI && $a <= 1.5*M_PI ) - return 2; - if( $a > 1.5*M_PI ) - return 3; - } - - function StrokeGuideLabels($img,$xc,$yc,$radius) { - $n = count($this->labels); - - //----------------------------------------------------------------------- - // Step 1 of the algorithm is to construct a number of clusters - // a cluster is defined as all slices within the same quadrant (almost) - // that has an angular distance less than the threshold - //----------------------------------------------------------------------- - $tresh_hold=25 * M_PI/180; // 25 degrees difference to be in a cluster - $incluster=false; // flag if we are currently in a cluster or not - $clusters = array(); // array of clusters - $cidx=-1; // running cluster index - - // Go through all the labels and construct a number of clusters - for($i=0; $i < $n-1; ++$i) { - // Calc the angle distance between two consecutive slices - $a1=$this->la[$i]; - $a2=$this->la[$i+1]; - $q1 = $this->Quadrant($a1); - $q2 = $this->Quadrant($a2); - $diff = abs($a1-$a2); - if( $diff < $tresh_hold ) { - if( $incluster ) { - $clusters[$cidx][1]++; - // Each cluster can only cover one quadrant - // Do we cross a quadrant ( and must break the cluster) - if( $q1 != $q2 ) { - // If we cross a quadrant boundary we normally start a - // new cluster. However we need to take the 12'a clock - // and 6'a clock positions into a special consideration. - // Case 1: WE go from q=1 to q=2 if the last slice on - // the cluster for q=1 is close to 12'a clock and the - // first slice in q=0 is small we extend the previous - // cluster - if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) { - if( $i < $n-2 ) { - $a3 = $this->la[$i+2]; - // If there isn't a cluster coming up with the next-next slice - // we extend the previous cluster to cover this slice as well - if( abs($a3-$a2) >= $tresh_hold ) { - $clusters[$cidx][1]++; - $i++; - } - } - } - elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) { - if( $i < $n-2 ) { - $a3 = $this->la[$i+2]; - // If there isn't a cluster coming up with the next-next slice - // we extend the previous cluster to cover this slice as well - if( abs($a3-$a2) >= $tresh_hold ) { - $clusters[$cidx][1]++; - $i++; - } - } - } - - if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) { - $clusters[$cidx][1]++; - $i++; - } - - $incluster = false; - } - } - elseif( $q1 == $q2) { - $incluster = true; - // Now we have a special case for quadrant 0. If we previously - // have a cluster of one in quadrant 0 we just extend that - // cluster. If we don't do this then we risk that the label - // for the cluster of one will cross the guide-line - if( $q1 == 0 && $cidx > -1 && - $clusters[$cidx][1] == 1 && - $this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) { - $clusters[$cidx][1]++; - } - else { - $cidx++; - $clusters[$cidx][0] = $i; - $clusters[$cidx][1] = 1; - } - } - else { - // Create a "cluster" of one since we are just crossing - // a quadrant - $cidx++; - $clusters[$cidx][0] = $i; - $clusters[$cidx][1] = 1; - } - } - else { - if( $incluster ) { - // Add the last slice - $clusters[$cidx][1]++; - $incluster = false; - } - else { // Create a "cluster" of one - $cidx++; - $clusters[$cidx][0] = $i; - $clusters[$cidx][1] = 1; - } - } - } - // Handle the very last slice - if( $incluster ) { - $clusters[$cidx][1]++; - } - else { // Create a "cluster" of one - $cidx++; - $clusters[$cidx][0] = $i; - $clusters[$cidx][1] = 1; - } - - /* - if( true ) { - // Debug printout in labels - for( $i=0; $i <= $cidx; ++$i ) { - for( $j=0; $j < $clusters[$i][1]; ++$j ) { - $a = $this->la[$clusters[$i][0]+$j]; - $aa = round($a*180/M_PI); - $q = $this->Quadrant($a); - $this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j"; - } - } - } - */ - - //----------------------------------------------------------------------- - // Step 2 of the algorithm is use the clusters and draw the labels - // and guidelines - //----------------------------------------------------------------------- - - // We use the font height as the base factor for how far we need to - // spread the labels in the Y-direction. - $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize); - $fh = $img->GetFontHeight(); - $origvstep=$fh*$this->iGuideVFactor; - $this->value->SetMargin(0); - - // Number of clusters found - $nc = count($clusters); - - // Walk through all the clusters - for($i=0; $i < $nc; ++$i) { - - // Start angle and number of slices in this cluster - $csize = $clusters[$i][1]; - $a = $this->la[$clusters[$i][0]]; - $q = $this->Quadrant($a); - - // Now set up the start and end conditions to make sure that - // in each cluster we walk through the all the slices starting with the slice - // closest to the equator. Since all slices are numbered clockwise from "3'a clock" - // we have different conditions depending on in which quadrant the slice lies within. - if( $q == 0 ) { - $start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep; - } - elseif( $q == 1 ) { - $start = 0; $idx = $start; $step = 1; $vstep = -$origvstep; - } - elseif( $q == 2 ) { - $start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep; - } - elseif( $q == 3 ) { - $start = 0; $idx = $start; $step = 1; $vstep = $origvstep; - } - - // Walk through all slices within this cluster - for($j=0; $j < $csize; ++$j) { - // Now adjust the position of the labels in each cluster starting - // with the slice that is closest to the equator of the pie - $a = $this->la[$clusters[$i][0]+$idx]; - - // Guide line start in the center of the arc of the slice - $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; - $x = round($r*cos($a)+$xc); - $y = round($yc-$r*sin($a)); - - // The distance from the arc depends on chosen font and the "R-Factor" - $r += $fh*$this->iGuideLineRFactor; - - // Should the labels be placed curved along the pie or in straight columns - // outside the pie? - if( $this->iGuideLineCurve ) - $xt=round($r*cos($a)+$xc); - - // If this is the first slice in the cluster we need some first time - // proessing - if( $idx == $start ) { - if( ! $this->iGuideLineCurve ) - $xt=round($r*cos($a)+$xc); - $yt=round($yc-$r*sin($a)); - - // Some special consideration in case this cluster starts - // in quadrant 1 or 3 very close to the "equator" (< 20 degrees) - // and the previous clusters last slice is within the tolerance. - // In that case we add a font height to this labels Y-position - // so it doesn't collide with - // the slice in the previous cluster - $prevcluster = ($i + ($nc-1) ) % $nc; - $previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1; - if( $q == 1 && $a > 160*M_PI/180 ) { - // Get the angle for the previous clusters last slice - $diff = abs($a-$this->la[$previdx]); - if( $diff < $tresh_hold ) { - $yt -= $fh; - } - } - elseif( $q == 3 && $a > 340*M_PI/180 ) { - // We need to subtract 360 to compare angle distance between - // q=0 and q=3 - $diff = abs($a-$this->la[$previdx]-360*M_PI/180); - if( $diff < $tresh_hold ) { - $yt += $fh; - } - } - - } - else { - // The step is at minimum $vstep but if the slices are relatively large - // we make sure that we add at least a step that corresponds to the vertical - // distance between the centers at the arc on the slice - $prev_a = $this->la[$clusters[$i][0]+($idx-$step)]; - $dy = abs($radius*(sin($a)-sin($prev_a))*1.2); - if( $vstep > 0 ) - $yt += max($vstep,$dy); - else - $yt += min($vstep,-$dy); - } - - $label = $this->labels[$clusters[$i][0]+$idx]; - - if( $csize == 1 ) { - // A "meta" cluster with only one slice - $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; - $rr = $r+$img->GetFontHeight()/2; - $xt=round($rr*cos($a)+$xc); - $yt=round($yc-$rr*sin($a)); - $this->StrokeLabel($label,$img,$xc,$yc,$a,$r); - if( $this->iShowGuideLineForSingle ) - $this->guideline->Stroke($img,$x,$y,$xt,$yt); - } - else { - $this->guideline->Stroke($img,$x,$y,$xt,$yt); - if( $q==1 || $q==2 ) { - // Left side of Pie - $this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt); - $lbladj = -$this->guidelinemargin-5; - $this->value->halign = "right"; - $this->value->valign = "center"; - } - else { - // Right side of pie - $this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt); - $lbladj = $this->guidelinemargin+5; - $this->value->halign = "left"; - $this->value->valign = "center"; - } - $this->value->Stroke($img,$label,$xt+$lbladj,$yt); - } - - // Udate idx to point to next slice in the cluster to process - $idx += $step; - } - } - } - - function StrokeAllLabels($img,$xc,$yc,$radius) { - // First normalize all angles for labels - $n = count($this->la); - for($i=0; $i < $n; ++$i) { - $this->la[$i] = $this->NormAngle($this->la[$i]); - } - if( $this->guideline->iShow ) { - $this->StrokeGuideLabels($img,$xc,$yc,$radius); - } - else { - $n = count($this->labels); - for($i=0; $i < $n; ++$i) { - $this->StrokeLabel($this->labels[$i],$img,$xc,$yc, - $this->la[$i], - $radius + $this->explode_radius[$n-1-$i]); - } - } - } - - // Position the labels of each slice - function StrokeLabel($label,$img,$xc,$yc,$a,$radius) { - - // Default value - if( $this->ilabelposadj === 'auto' ) - $this->ilabelposadj = 0.65; - $r = $radius; - - // We position the values diferently depending on if they are inside - // or outside the pie - if( $this->ilabelposadj < 1.0 ) { - - $this->value->SetAlign('center','center'); - $this->value->margin = 0; - - $xt=round($this->ilabelposadj*$r*cos($a)+$xc); - $yt=round($yc-$this->ilabelposadj*$r*sin($a)); - - $this->value->Stroke($img,$label,$xt,$yt); - } - else { - - $this->value->halign = "left"; - $this->value->valign = "top"; - $this->value->margin = 0; - - // Position the axis title. - // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text - // that intersects with the extension of the corresponding axis. The code looks a little - // bit messy but this is really the only way of having a reasonable position of the - // axis titles. - $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize); - $h=$img->GetTextHeight($label); - // For numeric values the format of the display value - // must be taken into account - if( is_numeric($label) ) { - if( $label > 0 ) - $w=$img->GetTextWidth(sprintf($this->value->format,$label)); - else - $w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); - } - else - $w=$img->GetTextWidth($label); - if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) { - $r *= $this->ilabelposadj; - } - - $r += $img->GetFontHeight()/1.5; - - $xt=round($r*cos($a)+$xc); - $yt=round($yc-$r*sin($a)); - - // Normalize angle - while( $a < 0 ) $a += 2*M_PI; - while( $a > 2*M_PI ) $a -= 2*M_PI; - - if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; - if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; - if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; - if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); - - if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; - if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI); - if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; - if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); - if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; - - $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h); - } - } -} // Class - - -//=================================================== -// CLASS PiePlotC -// Description: Same as a normal pie plot but with a -// filled circle in the center -//=================================================== -class PiePlotC extends PiePlot { - var $imidsize=0.5; // Fraction of total width - var $imidcolor='white'; - var $midtitle=''; - var $middlecsimtarget="",$middlecsimalt=""; - - function PiePlotC($data,$aCenterTitle='') { - parent::PiePlot($data); - $this->midtitle = new Text(); - $this->midtitle->ParagraphAlign('center'); - } - - function SetMid($aTitle,$aColor='white',$aSize=0.5) { - $this->midtitle->Set($aTitle); - - $this->imidsize = $aSize ; - $this->imidcolor = $aColor ; - } - - function SetMidTitle($aTitle) { - $this->midtitle->Set($aTitle); - } - - function SetMidSize($aSize) { - $this->imidsize = $aSize ; - } - - function SetMidColor($aColor) { - $this->imidcolor = $aColor ; - } - - function SetMidCSIM($aTarget,$aAlt) { - $this->middlecsimtarget = $aTarget; - $this->middlecsimalt = $aAlt; - } - - function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { - - //Slice number, ellipse centre (x,y), radius, start angle, end angle - while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI; - while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI; - - $sa = 2*M_PI - $sa; - $ea = 2*M_PI - $ea; - - // Special case when we have only one slice since then both start and end - // angle will be == 0 - if( abs($sa - $ea) < 0.0001 ) { - $sa=2*M_PI; $ea=0; - } - - // Add inner circle first point - $xp = floor(($this->imidsize*$radius*cos($ea))+$xc); - $yp = floor($yc-($this->imidsize*$radius*sin($ea))); - $coords = "$xp, $yp"; - - //add coordinates every 0.25 radians - $a=$ea+0.25; - - // If we cross the 260-limit with a slice we need to handle - // the fact that end angle is smaller than start - if( $sa < $ea ) { - while ($a <= 2*M_PI) { - $xp = floor($radius*cos($a)+$xc); - $yp = floor($yc-$radius*sin($a)); - $coords.= ", $xp, $yp"; - $a += 0.25; - } - $a -= 2*M_PI; - } - - while ($a < $sa) { - $xp = floor(($this->imidsize*$radius*cos($a)+$xc)); - $yp = floor($yc-($this->imidsize*$radius*sin($a))); - $coords.= ", $xp, $yp"; - $a += 0.25; - } - - // Make sure we end at the last point - $xp = floor(($this->imidsize*$radius*cos($sa)+$xc)); - $yp = floor($yc-($this->imidsize*$radius*sin($sa))); - $coords.= ", $xp, $yp"; - - // Straight line to outer circle - $xp = floor($radius*cos($sa)+$xc); - $yp = floor($yc-$radius*sin($sa)); - $coords.= ", $xp, $yp"; - - //add coordinates every 0.25 radians - $a=$sa - 0.25; - while ($a > $ea) { - $xp = floor($radius*cos($a)+$xc); - $yp = floor($yc-$radius*sin($a)); - $coords.= ", $xp, $yp"; - $a -= 0.25; - } - - //Add the last point on the arc - $xp = floor($radius*cos($ea)+$xc); - $yp = floor($yc-$radius*sin($ea)); - $coords.= ", $xp, $yp"; - - // Close the arc - $xp = floor(($this->imidsize*$radius*cos($ea))+$xc); - $yp = floor($yc-($this->imidsize*$radius*sin($ea))); - $coords .= ", $xp, $yp"; - - if( !empty($this->csimtargets[$i]) ) { - $this->csimareas .= "csimtargets[$i]."\""; - if( !empty($this->csimalts[$i]) ) { - $tmp=sprintf($this->csimalts[$i],$this->data[$i]); - $this->csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"$tmp\" />\n"; - } - } - - - function Stroke($img,$aaoption=0) { - - // Stroke the pie but don't stroke values - $tmp = $this->value->show; - $this->value->show = false; - parent::Stroke($img,$aaoption); - $this->value->show = $tmp; - - $xc = round($this->posx*$img->width); - $yc = round($this->posy*$img->height); - - $radius = floor($this->radius * min($img->width,$img->height)) ; - - - if( $this->imidsize > 0 && $aaoption !== 2 ) { - - if( $this->ishadowcolor != "" ) { - $img->SetColor($this->ishadowcolor); - $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop, - round($radius*$this->imidsize)); - } - - $img->SetColor($this->imidcolor); - $img->FilledCircle($xc,$yc,round($radius*$this->imidsize)); - - if( $this->pie_border && $aaoption === 0 ) { - $img->SetColor($this->color); - $img->Circle($xc,$yc,round($radius*$this->imidsize)); - } - - if( !empty($this->middlecsimtarget) ) - $this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize)); - - } - - if( $this->value->show && $aaoption !== 1) { - $this->StrokeAllLabels($img,$xc,$yc,$radius); - $this->midtitle->Pos($xc,$yc,'center','center'); - $this->midtitle->Stroke($img); - } - - } - - function AddMiddleCSIM($xc,$yc,$r) { - $xc=round($xc);$yc=round($yc);$r=round($r); - $this->csimareas .= "middlecsimtarget."\""; - if( !empty($this->middlecsimalt) ) { - $tmp = $this->middlecsimalt; - $this->csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"$tmp\" />\n"; - } - - function StrokeLabel($label,$img,$xc,$yc,$a,$r) { - - if( $this->ilabelposadj === 'auto' ) - $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize; - - parent::StrokeLabel($label,$img,$xc,$yc,$a,$r); - - } - -} - - -//=================================================== -// CLASS PieGraph -// Description: -//=================================================== -class PieGraph extends Graph { - var $posx, $posy, $radius; - var $legends=array(); - var $plots=array(); - var $pieaa = false ; -//--------------- -// CONSTRUCTOR - function PieGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { - $this->Graph($width,$height,$cachedName,$timeout,$inline); - $this->posx=$width/2; - $this->posy=$height/2; - $this->SetColor(array(255,255,255)); - } - -//--------------- -// PUBLIC METHODS - function Add($aObj) { - - if( is_array($aObj) && count($aObj) > 0 ) - $cl = $aObj[0]; - else - $cl = $aObj; - - if( is_a($cl,'Text') ) - $this->AddText($aObj); - elseif( is_a($cl,'IconPlot') ) - $this->AddIcon($aObj); - else { - if( is_array($aObj) ) { - $n = count($aObj); - for($i=0; $i < $n; ++$i ) { - $this->plots[] = $aObj[$i]; - } - } - else { - $this->plots[] = $aObj; - } - } - } - - function SetAntiAliasing($aFlg=true) { - $this->pieaa = $aFlg; - } - - function SetColor($c) { - $this->SetMarginColor($c); - } - - function DisplayCSIMAreas() { - $csim=""; - foreach($this->plots as $p ) { - $csim .= $p->GetCSIMareas(); - } - //$csim.= $this->legend->GetCSIMareas(); - if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) { - $this->img->SetColor($this->csimcolor); - $n = count($coords[0]); - for ($i=0; $i < $n; $i++) { - if ($coords[1][$i]=="poly") { - preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts); - $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]); - $m = count($pts[0]); - for ($j=0; $j < $m; $j++) { - $this->img->LineTo($pts[1][$j],$pts[2][$j]); - } - } else if ($coords[1][$i]=="rect") { - $pts = preg_split('/,/', $coords[2][$i]); - $this->img->SetStartPoint($pts[0],$pts[1]); - $this->img->LineTo($pts[2],$pts[1]); - $this->img->LineTo($pts[2],$pts[3]); - $this->img->LineTo($pts[0],$pts[3]); - $this->img->LineTo($pts[0],$pts[1]); - - } - } - } - } - - // Method description - function Stroke($aStrokeFileName="") { - // If the filename is the predefined value = '_csim_special_' - // we assume that the call to stroke only needs to do enough - // to correctly generate the CSIM maps. - // We use this variable to skip things we don't strictly need - // to do to generate the image map to improve performance - // a best we can. Therefor you will see a lot of tests !$_csim in the - // code below. - $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); - - // We need to know if we have stroked the plot in the - // GetCSIMareas. Otherwise the CSIM hasn't been generated - // and in the case of GetCSIM called before stroke to generate - // CSIM without storing an image to disk GetCSIM must call Stroke. - $this->iHasStroked = true; - - $n = count($this->plots); - - if( $this->pieaa ) { - - if( !$_csim ) { - if( $this->background_image != "" ) { - $this->StrokeFrameBackground(); - } - else { - $this->StrokeFrame(); - } - } - - - $w = $this->img->width; - $h = $this->img->height; - $oldimg = $this->img->img; - - $this->img->CreateImgCanvas(2*$w,2*$h); - - $this->img->SetColor( $this->margin_color ); - $this->img->FilledRectangle(0,0,2*$w-1,2*$h-1); - - // Make all icons *2 i size since we will be scaling down the - // image to do the anti aliasing - $ni = count($this->iIcons); - for($i=0; $i < $ni; ++$i) { - $this->iIcons[$i]->iScale *= 2 ; - } - $this->StrokeIcons(); - - for($i=0; $i < $n; ++$i) { - if( $this->plots[$i]->posx > 1 ) - $this->plots[$i]->posx *= 2 ; - if( $this->plots[$i]->posy > 1 ) - $this->plots[$i]->posy *= 2 ; - - $this->plots[$i]->Stroke($this->img,1); - - if( $this->plots[$i]->posx > 1 ) - $this->plots[$i]->posx /= 2 ; - if( $this->plots[$i]->posy > 1 ) - $this->plots[$i]->posy /= 2 ; - } - - $indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ; - $indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ; - $this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent, - $w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent)); - - $this->img->img = $oldimg ; - $this->img->width = $w ; - $this->img->height = $h ; - - for($i=0; $i < $n; ++$i) { - $this->plots[$i]->Stroke($this->img,2); // Stroke labels - $this->plots[$i]->Legend($this); - } - - } - else { - // No antialias - if( !$_csim ) { - if( $this->background_image != "" ) { - $this->StrokeFrameBackground(); - } - else { - $this->StrokeFrame(); - $this->StrokeBackgroundGrad(); - } - } - - $this->StrokeIcons(); - - for($i=0; $i < $n; ++$i) { - $this->plots[$i]->Stroke($this->img); - $this->plots[$i]->Legend($this); - } - } - - $this->legend->Stroke($this->img); - $this->footer->Stroke($this->img); - $this->StrokeTitles(); - - if( !$_csim ) { - - // Stroke texts - if( $this->texts != null ) { - $n = count($this->texts); - for($i=0; $i < $n; ++$i ) { - $this->texts[$i]->Stroke($this->img); - } - } - - if( _JPG_DEBUG ) { - $this->DisplayCSIMAreas(); - } - - // Should we do any final image transformation - if( $this->iImgTrans ) { - if( !class_exists('ImgTrans') ) { - require_once('jpgraph_imgtrans.php'); - //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.'); - } - - $tform = new ImgTrans($this->img->img); - $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, - $this->iImgTransDirection,$this->iImgTransHighQ, - $this->iImgTransMinSize,$this->iImgTransFillColor, - $this->iImgTransBorder); - } - - - // If the filename is given as the special "__handle" - // then the image handler is returned and the image is NOT - // streamed back - if( $aStrokeFileName == _IMG_HANDLER ) { - return $this->img->img; - } - else { - // Finally stream the generated picture - $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, - $aStrokeFileName); - } - } - } -} // Class - -/* EOF */ -?> + array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430), + "pastel" => array(27,415,128,59,66,79,105,110,42,147,152,230,236,240,331,337,405,38), + "water" => array(8,370,24,40,335,56,213,237,268,14,326,387,10,388), + "sand" => array(27,168,34,170,19,50,65,72,131,209,46,393)); + protected $setslicecolors=array(); + protected $labeltype=0; // Default to percentage + protected $pie_border=true,$pie_interior_border=true; + public $value; + protected $ishadowcolor='',$ishadowdrop=4; + protected $ilabelposadj=1; + protected $legendcsimtargets = array(),$legendcsimwintargets = array(); + protected $legendcsimalts = array(); + protected $adjusted_data = array(); + public $guideline = null; + protected $guidelinemargin=10,$iShowGuideLineForSingle = false; + protected $iGuideLineCurve = false,$iGuideVFactor=1.4,$iGuideLineRFactor=0.8; + protected $la = array(); // Holds the exact angle for each label + + //--------------- + // CONSTRUCTOR + function __construct($data) { + $this->data = array_reverse($data); + $this->title = new Text(""); + $this->title->SetFont(FF_DEFAULT,FS_BOLD); + $this->value = new DisplayValue(); + $this->value->Show(); + $this->value->SetFormat('%.1f%%'); + $this->guideline = new LineProperty(); + } + + //--------------- + // PUBLIC METHODS + function SetCenter($x,$y=0.5) { + $this->posx = $x; + $this->posy = $y; + } + + // Enable guideline and set drwaing policy + function SetGuideLines($aFlg=true,$aCurved=true,$aAlways=false) { + $this->guideline->Show($aFlg); + $this->iShowGuideLineForSingle = $aAlways; + $this->iGuideLineCurve = $aCurved; + } + + // Adjuste the distance between labels and labels and pie + function SetGuideLinesAdjust($aVFactor,$aRFactor=0.8) { + $this->iGuideVFactor=$aVFactor; + $this->iGuideLineRFactor=$aRFactor; + } + + function SetColor($aColor) { + $this->color = $aColor; + } + + function SetSliceColors($aColors) { + $this->setslicecolors = $aColors; + } + + function SetShadow($aColor='darkgray',$aDropWidth=4) { + $this->ishadowcolor = $aColor; + $this->ishadowdrop = $aDropWidth; + } + + function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') { + $this->csimtargets=array_reverse($aTargets); + if( is_array($aWinTargets) ) + $this->csimwintargets=array_reverse($aWinTargets); + if( is_array($aAlts) ) + $this->csimalts=array_reverse($aAlts); + } + + function GetCSIMareas() { + return $this->csimareas; + } + + function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { + //Slice number, ellipse centre (x,y), height, width, start angle, end angle + while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI; + while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI; + + $sa = 2*M_PI - $sa; + $ea = 2*M_PI - $ea; + + // Special case when we have only one slice since then both start and end + // angle will be == 0 + if( abs($sa - $ea) < 0.0001 ) { + $sa=2*M_PI; $ea=0; + } + + //add coordinates of the centre to the map + $xc = floor($xc);$yc=floor($yc); + $coords = "$xc, $yc"; + + //add coordinates of the first point on the arc to the map + $xp = floor(($radius*cos($ea))+$xc); + $yp = floor($yc-$radius*sin($ea)); + $coords.= ", $xp, $yp"; + + //add coordinates every 0.2 radians + $a=$ea+0.2; + + // If we cross the 360-limit with a slice we need to handle + // the fact that end angle is smaller than start + if( $sa < $ea ) { + while ($a <= 2*M_PI) { + $xp = floor($radius*cos($a)+$xc); + $yp = floor($yc-$radius*sin($a)); + $coords.= ", $xp, $yp"; + $a += 0.2; + } + $a -= 2*M_PI; + } + + + while ($a < $sa) { + $xp = floor($radius*cos($a)+$xc); + $yp = floor($yc-$radius*sin($a)); + $coords.= ", $xp, $yp"; + $a += 0.2; + } + + //Add the last point on the arc + $xp = floor($radius*cos($sa)+$xc); + $yp = floor($yc-$radius*sin($sa)); + $coords.= ", $xp, $yp"; + if( !empty($this->csimtargets[$i]) ) { + $this->csimareas .= "csimtargets[$i]."\""; + $tmp=""; + if( !empty($this->csimwintargets[$i]) ) { + $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; + } + if( !empty($this->csimalts[$i]) ) { + $tmp=sprintf($this->csimalts[$i],$this->data[$i]); + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + } + + + function SetTheme($aTheme) { +// JpGraphError::RaiseL(15012,$aTheme); +// return; + + if( in_array($aTheme,array_keys($this->themearr)) ) { + $this->theme = $aTheme; + $this->is_using_plot_theme = true; + } else { + JpGraphError::RaiseL(15001,$aTheme);//("PiePLot::SetTheme() Unknown theme: $aTheme"); + } + } + + function ExplodeSlice($e,$radius=20) { + if( ! is_integer($e) ) + JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer'); + $this->explode_radius[$e]=$radius; + } + + function ExplodeAll($radius=20) { + $this->explode_all=true; + $this->explode_r = $radius; + } + + function Explode($aExplodeArr) { + if( !is_array($aExplodeArr) ) { + JpGraphError::RaiseL(15003); + //("Argument to PiePlot::Explode() must be an array with integer distances."); + } + $this->explode_radius = $aExplodeArr; + } + + function SetStartAngle($aStart) { + if( $aStart < 0 || $aStart > 360 ) { + JpGraphError::RaiseL(15004);//('Slice start angle must be between 0 and 360 degrees.'); + } + if( $aStart == 0 ) { + $this->startangle = 0; + } + else { + $this->startangle = 360-$aStart; + $this->startangle *= M_PI/180; + } + } + + // Size in percentage + function SetSize($aSize) { + if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) ) + $this->radius = $aSize; + else + JpGraphError::RaiseL(15006); + //("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]"); + } + + // Set label arrays + function SetLegends($aLegend) { + $this->legends = $aLegend; + } + + // Set text labels for slices + function SetLabels($aLabels,$aLblPosAdj="auto") { + $this->labels = array_reverse($aLabels); + $this->ilabelposadj=$aLblPosAdj; + } + + function SetLabelPos($aLblPosAdj) { + $this->ilabelposadj=$aLblPosAdj; + } + + // Should we display actual value or percentage? + function SetLabelType($aType) { + if( $aType < 0 || $aType > 2 ) + JpGraphError::RaiseL(15008,$aType); + //("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t)."); + $this->labeltype = $aType; + } + + // Deprecated. + function SetValueType($aType) { + $this->SetLabelType($aType); + } + + // Should the circle around a pie plot be displayed + function ShowBorder($exterior=true,$interior=true) { + $this->pie_border = $exterior; + $this->pie_interior_border = $interior; + } + + // Setup the legends + function Legend($graph) { + $colors = array_keys($graph->img->rgb->rgb_table); + sort($colors); + $ta=$this->themearr[$this->theme]; + $n = count($this->data); + + if( $this->setslicecolors==null ) { + $numcolors=count($ta); + if( class_exists('PiePlot3D',false) && ($this instanceof PiePlot3D) ) { + $ta = array_reverse(array_slice($ta,0,$n)); + } + } + else { + $this->setslicecolors = array_slice($this->setslicecolors,0,$n); + $numcolors=count($this->setslicecolors); + if( $graph->pieaa && !($this instanceof PiePlot3D) ) { + $this->setslicecolors = array_reverse($this->setslicecolors); + } + } + + $sum=0; + for($i=0; $i < $n; ++$i) + $sum += $this->data[$i]; + + // Bail out with error if the sum is 0 + if( $sum==0 ) + JpGraphError::RaiseL(15009);//("Illegal pie plot. Sum of all data is zero for Pie!"); + + // Make sure we don't plot more values than data points + // (in case the user added more legends than data points) + $legendsCount = is_array($this->legends) ? count($this->legends) : 0; + $n = min($legendsCount,count($this->data)); + if( $this->legends != "" ) { + $this->legends = array_reverse(array_slice($this->legends,0,$n)); + } + for( $i=$n-1; $i >= 0; --$i ) { + $l = $this->legends[$i]; + // Replace possible format with actual values + $count = is_array($this->csimalts) ? count($this->csimalts) : 0; + if( $count > $i ) { + $fmt = $this->csimalts[$i]; + } + else { + $fmt = "%d"; // Deafult Alt if no other has been specified + } + if( $this->labeltype==0 ) { + $l = sprintf($l,100*$this->data[$i]/$sum); + $alt = sprintf($fmt,$this->data[$i]); + + } + elseif( $this->labeltype == 1) { + $l = sprintf($l,$this->data[$i]); + $alt = sprintf($fmt,$this->data[$i]); + + } + else { + $l = sprintf($l,$this->adjusted_data[$i]); + $alt = sprintf($fmt,$this->adjusted_data[$i]); + } + + if( empty($this->csimwintargets[$i]) ) { + $wintarg = ''; + } + else { + $wintarg = $this->csimwintargets[$i]; + } + + if( $this->setslicecolors==null ) { + $csimtarget = isset($this->csimtargets[$i]) ? $this->csimtargets[$i] : null; + $graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,$csimtarget,$alt,$wintarg); + } + else { + $csimtarget = isset($this->csimtargets[$i]) ? $this->csimtargets[$i] : null; + $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,$csimtarget,$alt,$wintarg); + } + } + } + + // Adjust the rounded percetage value so that the sum of + // of the pie slices are always 100% + // Using the Hare/Niemeyer method + function AdjPercentage($aData,$aPrec=0) { + $mul=100; + if( $aPrec > 0 && $aPrec < 3 ) { + if( $aPrec == 1 ) + $mul=1000; + else + $mul=10000; + } + + $tmp = array(); + $result = array(); + $quote_sum=0; + $n = count($aData) ; + for( $i=0, $sum=0; $i < $n; ++$i ) + $sum+=$aData[$i]; + foreach($aData as $index => $value) { + $tmp_percentage=$value/$sum*$mul; + $result[$index]=floor($tmp_percentage); + $tmp[$index]=$tmp_percentage-$result[$index]; + $quote_sum+=$result[$index]; + } + if( $quote_sum == $mul) { + if( $mul > 100 ) { + $tmp = $mul / 100; + for( $i=0; $i < $n; ++$i ) { + $result[$i] /= $tmp ; + } + } + return $result; + } + arsort($tmp,SORT_NUMERIC); + reset($tmp); + for($i=0; $i < $mul-$quote_sum; $i++) + { + $result[key($tmp)]++; + next($tmp); + } + if( $mul > 100 ) { + $tmp = $mul / 100; + for( $i=0; $i < $n; ++$i ) { + $result[$i] /= $tmp ; + } + } + return $result; + } + + + function Stroke($img,$aaoption=0) { + // aaoption is used to handle antialias + // aaoption == 0 a normal pie + // aaoption == 1 just the body + // aaoption == 2 just the values + + // Explode scaling. If anti alias we scale the image + // twice and we also need to scale the exploding distance + $expscale = $aaoption === 1 ? 2 : 1; + + if( $this->labeltype == 2 ) { + // Adjust the data so that it will add up to 100% + $this->adjusted_data = $this->AdjPercentage($this->data); + } + + if ($this->use_plot_theme_colors) { + $this->setslicecolors = null; + } + + $colors = array_keys($img->rgb->rgb_table); + sort($colors); + $ta=$this->themearr[$this->theme]; + $n = count($this->data); + + if( $this->setslicecolors==null ) { + $numcolors=count($ta); + } + else { + // We need to create an array of colors as long as the data + // since we need to reverse it to get the colors in the right order + $numcolors=count($this->setslicecolors); + $i = 2*$numcolors; + while( $n > $i ) { + $this->setslicecolors = array_merge($this->setslicecolors,$this->setslicecolors); + $i += $n; + } + $tt = array_slice($this->setslicecolors,0,$n % $numcolors); + $this->setslicecolors = array_merge($this->setslicecolors,$tt); + $this->setslicecolors = array_reverse($this->setslicecolors); + } + + // Draw the slices + $sum=0; + for($i=0; $i < $n; ++$i) + $sum += $this->data[$i]; + + // Bail out with error if the sum is 0 + if( $sum==0 ) { + JpGraphError::RaiseL(15009);//("Sum of all data is 0 for Pie."); + } + + // Set up the pie-circle + if( $this->radius <= 1 ) { + $radius = floor($this->radius*min($img->width,$img->height)); + } + else { + $radius = $aaoption === 1 ? $this->radius*2 : $this->radius; + } + + if( $this->posx <= 1 && $this->posx > 0 ) { + $xc = round($this->posx*$img->width); + } + else { + $xc = $this->posx ; + } + + if( $this->posy <= 1 && $this->posy > 0 ) { + $yc = round($this->posy*$img->height); + } + else { + $yc = $this->posy ; + } + + $n = count($this->data); + + if( $this->explode_all ) { + for($i=0; $i < $n; ++$i) { + $this->explode_radius[$i]=$this->explode_r; + } + } + + // If we have a shadow and not just drawing the labels + if( $this->ishadowcolor != "" && $aaoption !== 2) { + $accsum=0; + $angle2 = $this->startangle; + $img->SetColor($this->ishadowcolor); + for($i=0; $sum > 0 && $i < $n; ++$i) { + $j = $n-$i-1; + $d = $this->data[$i]; + $angle1 = $angle2; + $accsum += $d; + $angle2 = $this->startangle+2*M_PI*$accsum/$sum; + if( empty($this->explode_radius[$j]) ) { + $this->explode_radius[$j]=0; + } + + if( $d < 0.00001 ) continue; + + $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); + + $xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale; + $ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale; + + $xcm += $this->ishadowdrop*$expscale; + $ycm += $this->ishadowdrop*$expscale; + + $_sa = round($angle1*180/M_PI); + $_ea = round($angle2*180/M_PI); + + // The CakeSlice method draws a full circle in case of start angle = end angle + // for pie slices we don't want this behaviour unless we only have one + // slice in the pie in case it is the wanted behaviour + if( $_ea-$_sa > 0.1 || $n==1 ) { + $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1, + $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor); + } + } + } + + //-------------------------------------------------------------------------------- + // This is the main loop to draw each cake slice + //-------------------------------------------------------------------------------- + + // Set up the accumulated sum, start angle for first slice and border color + $accsum=0; + $angle2 = $this->startangle; + $img->SetColor($this->color); + + // Loop though all the slices if there is a pie to draw (sum>0) + // There are n slices in total + for($i=0; $sum>0 && $i < $n; ++$i) { + + // $j is the actual index used for the slice + $j = $n-$i-1; + + // Make sure we havea valid distance to explode the slice + if( empty($this->explode_radius[$j]) ) { + $this->explode_radius[$j]=0; + } + + // The actual numeric value for the slice + $d = $this->data[$i]; + + $angle1 = $angle2; + + // Accumlate the sum + $accsum += $d; + + // The new angle when we add the "size" of this slice + // angle1 is then the start and angle2 the end of this slice + $angle2 = $this->NormAngle($this->startangle+2*M_PI*$accsum/$sum); + + // We avoid some trouble by not allowing end angle to be 0, in that case + // we translate to 360 + + // la is used to hold the label angle, which is centered on the slice + if( $angle2 < 0.0001 && $angle1 > 0.0001 ) { + $this->la[$i] = 2*M_PI - (abs(2*M_PI-$angle1)/2.0+$angle1); + } + elseif( $angle1 > $angle2 ) { + // The case where the slice crosses the 3 a'clock line + // Remember that the slices are counted clockwise and + // labels are counted counter clockwise so we need to revert with 2 PI + $this->la[$i] = 2*M_PI-$this->NormAngle($angle1 + ((2*M_PI - $angle1)+$angle2)/2); + } + else { + $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); + } + + // Too avoid rounding problems we skip the slice if it is too small + if( $d < 0.00001 ) continue; + + // If the user has specified an array of colors for each slice then use + // that a color otherwise use the theme array (ta) of colors + if( $this->setslicecolors==null ) { + $slicecolor=$colors[$ta[$i%$numcolors]]; + } + else { + $slicecolor=$this->setslicecolors[$i%$numcolors]; + } + +// $_sa = round($angle1*180/M_PI); +// $_ea = round($angle2*180/M_PI); +// $_la = round($this->la[$i]*180/M_PI); +// echo "Slice#$i: ang1=$_sa , ang2=$_ea, la=$_la, color=$slicecolor
"; + + + // If we have enabled antialias then we don't draw any border so + // make the bordedr color the same as the slice color + if( $this->pie_interior_border && $aaoption===0 ) { + $img->SetColor($this->color); + } + else { + $img->SetColor($slicecolor); + } + $arccolor = $this->pie_border && $aaoption===0 ? $this->color : ""; + + // Calculate the x,y coordinates for the base of this slice taking + // the exploded distance into account. Here we use the mid angle as the + // ray of extension and we have the mid angle handy as it is also the + // label angle + $xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale; + $ycm = $yc - $this->explode_radius[$j]*sin($this->la[$i])*$expscale; + + // If we are not just drawing the labels then draw this cake slice + if( $aaoption !== 2 ) { + + $_sa = round($angle1*180/M_PI); + $_ea = round($angle2*180/M_PI); + $_la = round($this->la[$i]*180/M_PI); + //echo "[$i] sa=$_sa, ea=$_ea, la[$i]=$_la, (color=$slicecolor)
"; + + // The CakeSlice method draws a full circle in case of start angle = end angle + // for pie slices we want this in case the slice have a value larger than 99% of the + // total sum + if( abs($_ea-$_sa) >= 1 || $d == $sum ) { + $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,$_sa,$_ea,$slicecolor,$arccolor); + } + } + + // If the CSIM is used then make sure we register a CSIM area for this slice as well + if( $this->csimtargets && $aaoption !== 1 ) { + $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2); + } + } + + // Format the titles for each slice + if( $aaoption !== 2 ) { + for( $i=0; $i < $n; ++$i) { + if( $this->labeltype==0 ) { + if( $sum != 0 ) + $l = 100.0*$this->data[$i]/$sum; + else + $l = 0.0; + } + elseif( $this->labeltype==1 ) { + $l = $this->data[$i]*1.0; + } + else { + $l = $this->adjusted_data[$i]; + } + if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) + $this->labels[$i]=sprintf($this->labels[$i],$l); + else + $this->labels[$i]=$l; + } + } + + if( $this->value->show && $aaoption !== 1 ) { + $this->StrokeAllLabels($img,$xc,$yc,$radius); + } + + // Adjust title position + if( $aaoption !== 1 ) { + $this->title->SetPos($xc, + $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin, + "center","bottom"); + $this->title->Stroke($img); + } + + } + + //--------------- + // PRIVATE METHODS + + function NormAngle($a) { + while( $a < 0 ) $a += 2*M_PI; + while( $a > 2*M_PI ) $a -= 2*M_PI; + return $a; + } + + function Quadrant($a) { + $a=$this->NormAngle($a); + if( $a > 0 && $a <= M_PI/2 ) + return 0; + if( $a > M_PI/2 && $a <= M_PI ) + return 1; + if( $a > M_PI && $a <= 1.5*M_PI ) + return 2; + if( $a > 1.5*M_PI ) + return 3; + } + + function StrokeGuideLabels($img,$xc,$yc,$radius) { + $n = count($this->labels); + + //----------------------------------------------------------------------- + // Step 1 of the algorithm is to construct a number of clusters + // a cluster is defined as all slices within the same quadrant (almost) + // that has an angular distance less than the treshold + //----------------------------------------------------------------------- + $tresh_hold=25 * M_PI/180; // 25 degrees difference to be in a cluster + $incluster=false; // flag if we are currently in a cluster or not + $clusters = array(); // array of clusters + $cidx=-1; // running cluster index + + // Go through all the labels and construct a number of clusters + for($i=0; $i < $n-1; ++$i) { + // Calc the angle distance between two consecutive slices + $a1=$this->la[$i]; + $a2=$this->la[$i+1]; + $q1 = $this->Quadrant($a1); + $q2 = $this->Quadrant($a2); + $diff = abs($a1-$a2); + if( $diff < $tresh_hold ) { + if( $incluster ) { + $clusters[$cidx][1]++; + // Each cluster can only cover one quadrant + // Do we cross a quadrant ( and must break the cluster) + if( $q1 != $q2 ) { + // If we cross a quadrant boundary we normally start a + // new cluster. However we need to take the 12'a clock + // and 6'a clock positions into a special consideration. + // Case 1: WE go from q=1 to q=2 if the last slice on + // the cluster for q=1 is close to 12'a clock and the + // first slice in q=0 is small we extend the previous + // cluster + if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) { + if( $i < $n-2 ) { + $a3 = $this->la[$i+2]; + // If there isn't a cluster coming up with the next-next slice + // we extend the previous cluster to cover this slice as well + if( abs($a3-$a2) >= $tresh_hold ) { + $clusters[$cidx][1]++; + $i++; + } + } + } + elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) { + if( $i < $n-2 ) { + $a3 = $this->la[$i+2]; + // If there isn't a cluster coming up with the next-next slice + // we extend the previous cluster to cover this slice as well + if( abs($a3-$a2) >= $tresh_hold ) { + $clusters[$cidx][1]++; + $i++; + } + } + } + + if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) { + $clusters[$cidx][1]++; + $i++; + } + + $incluster = false; + } + } + elseif( $q1 == $q2) { + $incluster = true; + // Now we have a special case for quadrant 0. If we previously + // have a cluster of one in quadrant 0 we just extend that + // cluster. If we don't do this then we risk that the label + // for the cluster of one will cross the guide-line + if( $q1 == 0 && $cidx > -1 && + $clusters[$cidx][1] == 1 && + $this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) { + $clusters[$cidx][1]++; + } + else { + $cidx++; + $clusters[$cidx][0] = $i; + $clusters[$cidx][1] = 1; + } + } + else { + // Create a "cluster" of one since we are just crossing + // a quadrant + $cidx++; + $clusters[$cidx][0] = $i; + $clusters[$cidx][1] = 1; + } + } + else { + if( $incluster ) { + // Add the last slice + $clusters[$cidx][1]++; + $incluster = false; + } + else { // Create a "cluster" of one + $cidx++; + $clusters[$cidx][0] = $i; + $clusters[$cidx][1] = 1; + } + } + } + // Handle the very last slice + if( $incluster ) { + $clusters[$cidx][1]++; + } + else { // Create a "cluster" of one + $cidx++; + $clusters[$cidx][0] = $i; + $clusters[$cidx][1] = 1; + } + + /* + if( true ) { + // Debug printout in labels + for( $i=0; $i <= $cidx; ++$i ) { + for( $j=0; $j < $clusters[$i][1]; ++$j ) { + $a = $this->la[$clusters[$i][0]+$j]; + $aa = round($a*180/M_PI); + $q = $this->Quadrant($a); + $this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j"; + } + } + } + */ + + //----------------------------------------------------------------------- + // Step 2 of the algorithm is use the clusters and draw the labels + // and guidelines + //----------------------------------------------------------------------- + + // We use the font height as the base factor for how far we need to + // spread the labels in the Y-direction. + $this->value->ApplyFont($img); + $fh = $img->GetFontHeight(); + $origvstep=$fh*$this->iGuideVFactor; + $this->value->SetMargin(0); + + // Number of clusters found + $nc = count($clusters); + + // Walk through all the clusters + for($i=0; $i < $nc; ++$i) { + + // Start angle and number of slices in this cluster + $csize = $clusters[$i][1]; + $a = $this->la[$clusters[$i][0]]; + $q = $this->Quadrant($a); + + // Now set up the start and end conditions to make sure that + // in each cluster we walk through the all the slices starting with the slice + // closest to the equator. Since all slices are numbered clockwise from "3'a clock" + // we have different conditions depending on in which quadrant the slice lies within. + if( $q == 0 ) { + $start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep; + } + elseif( $q == 1 ) { + $start = 0; $idx = $start; $step = 1; $vstep = -$origvstep; + } + elseif( $q == 2 ) { + $start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep; + } + elseif( $q == 3 ) { + $start = 0; $idx = $start; $step = 1; $vstep = $origvstep; + } + + // Walk through all slices within this cluster + for($j=0; $j < $csize; ++$j) { + // Now adjust the position of the labels in each cluster starting + // with the slice that is closest to the equator of the pie + $a = $this->la[$clusters[$i][0]+$idx]; + + // Guide line start in the center of the arc of the slice + $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; + $x = round($r*cos($a)+$xc); + $y = round($yc-$r*sin($a)); + + // The distance from the arc depends on chosen font and the "R-Factor" + $r += $fh*$this->iGuideLineRFactor; + + // Should the labels be placed curved along the pie or in straight columns + // outside the pie? + if( $this->iGuideLineCurve ) + $xt=round($r*cos($a)+$xc); + + // If this is the first slice in the cluster we need some first time + // proessing + if( $idx == $start ) { + if( ! $this->iGuideLineCurve ) + $xt=round($r*cos($a)+$xc); + $yt=round($yc-$r*sin($a)); + + // Some special consideration in case this cluster starts + // in quadrant 1 or 3 very close to the "equator" (< 20 degrees) + // and the previous clusters last slice is within the tolerance. + // In that case we add a font height to this labels Y-position + // so it doesn't collide with + // the slice in the previous cluster + $prevcluster = ($i + ($nc-1) ) % $nc; + $previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1; + if( $q == 1 && $a > 160*M_PI/180 ) { + // Get the angle for the previous clusters last slice + $diff = abs($a-$this->la[$previdx]); + if( $diff < $tresh_hold ) { + $yt -= $fh; + } + } + elseif( $q == 3 && $a > 340*M_PI/180 ) { + // We need to subtract 360 to compare angle distance between + // q=0 and q=3 + $diff = abs($a-$this->la[$previdx]-360*M_PI/180); + if( $diff < $tresh_hold ) { + $yt += $fh; + } + } + + } + else { + // The step is at minimum $vstep but if the slices are relatively large + // we make sure that we add at least a step that corresponds to the vertical + // distance between the centers at the arc on the slice + $prev_a = $this->la[$clusters[$i][0]+($idx-$step)]; + $dy = abs($radius*(sin($a)-sin($prev_a))*1.2); + if( $vstep > 0 ) + $yt += max($vstep,$dy); + else + $yt += min($vstep,-$dy); + } + + $label = $this->labels[$clusters[$i][0]+$idx]; + + if( $csize == 1 ) { + // A "meta" cluster with only one slice + $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; + $rr = $r+$img->GetFontHeight()/2; + $xt=round($rr*cos($a)+$xc); + $yt=round($yc-$rr*sin($a)); + $this->StrokeLabel($label,$img,$xc,$yc,$a,$r); + if( $this->iShowGuideLineForSingle ) + $this->guideline->Stroke($img,$x,$y,$xt,$yt); + } + else { + $this->guideline->Stroke($img,$x,$y,$xt,$yt); + if( $q==1 || $q==2 ) { + // Left side of Pie + $this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt); + $lbladj = -$this->guidelinemargin-5; + $this->value->halign = "right"; + $this->value->valign = "center"; + } + else { + // Right side of pie + $this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt); + $lbladj = $this->guidelinemargin+5; + $this->value->halign = "left"; + $this->value->valign = "center"; + } + $this->value->Stroke($img,$label,$xt+$lbladj,$yt); + } + + // Udate idx to point to next slice in the cluster to process + $idx += $step; + } + } + } + + function StrokeAllLabels($img,$xc,$yc,$radius) { + // First normalize all angles for labels + $n = count($this->la); + for($i=0; $i < $n; ++$i) { + $this->la[$i] = $this->NormAngle($this->la[$i]); + } + if( $this->guideline->iShow ) { + $this->StrokeGuideLabels($img,$xc,$yc,$radius); + } + else { + $n = count($this->labels); + for($i=0; $i < $n; ++$i) { + $this->StrokeLabel($this->labels[$i],$img,$xc,$yc, + $this->la[$i], + $radius + $this->explode_radius[$n-1-$i]); + } + } + } + + // Position the labels of each slice + function StrokeLabel($label,$img,$xc,$yc,$a,$r) { + + // Default value + if( $this->ilabelposadj === 'auto' ) + $this->ilabelposadj = 0.65; + + // We position the values diferently depending on if they are inside + // or outside the pie + if( $this->ilabelposadj < 1.0 ) { + + $this->value->SetAlign('center','center'); + $this->value->margin = 0; + + $xt=round($this->ilabelposadj*$r*cos($a)+$xc); + $yt=round($yc-$this->ilabelposadj*$r*sin($a)); + + $this->value->Stroke($img,$label,$xt,$yt); + } + else { + + $this->value->halign = "left"; + $this->value->valign = "top"; + $this->value->margin = 0; + + // Position the axis title. + // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text + // that intersects with the extension of the corresponding axis. The code looks a little + // bit messy but this is really the only way of having a reasonable position of the + // axis titles. + $this->value->ApplyFont($img); + $h=$img->GetTextHeight($label); + // For numeric values the format of the display value + // must be taken into account + if( is_numeric($label) ) { + if( $label > 0 ) + $w=$img->GetTextWidth(sprintf($this->value->format,$label)); + else + $w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); + } + else + $w=$img->GetTextWidth($label); + + if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) { + $r *= $this->ilabelposadj; + } + + $r += $img->GetFontHeight()/1.5; + + $xt=round($r*cos($a)+$xc); + $yt=round($yc-$r*sin($a)); + + // Normalize angle + while( $a < 0 ) $a += 2*M_PI; + while( $a > 2*M_PI ) $a -= 2*M_PI; + + if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); + + if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; + if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI); + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; + + $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h); + } + } + + function UsePlotThemeColors($flag = true) { + $this->use_plot_theme_colors = $flag; + } +} // Class + + +//=================================================== +// CLASS PiePlotC +// Description: Same as a normal pie plot but with a +// filled circle in the center +//=================================================== +class PiePlotC extends PiePlot { + private $imidsize=0.5; // Fraction of total width + private $imidcolor='white'; + public $midtitle=''; + private $middlecsimtarget='',$middlecsimwintarget='',$middlecsimalt=''; + + function __construct($data,$aCenterTitle='') { + parent::__construct($data); + $this->midtitle = new Text(); + $this->midtitle->ParagraphAlign('center'); + } + + function SetMid($aTitle,$aColor='white',$aSize=0.5) { + $this->midtitle->Set($aTitle); + + $this->imidsize = $aSize ; + $this->imidcolor = $aColor ; + } + + function SetMidTitle($aTitle) { + $this->midtitle->Set($aTitle); + } + + function SetMidSize($aSize) { + $this->imidsize = $aSize ; + } + + function SetMidColor($aColor) { + $this->imidcolor = $aColor ; + } + + function SetMidCSIM($aTarget,$aAlt='',$aWinTarget='') { + $this->middlecsimtarget = $aTarget; + $this->middlecsimwintarget = $aWinTarget; + $this->middlecsimalt = $aAlt; + } + + function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { + //Slice number, ellipse centre (x,y), radius, start angle, end angle + while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI; + while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI; + + $sa = 2*M_PI - $sa; + $ea = 2*M_PI - $ea; + + // Special case when we have only one slice since then both start and end + // angle will be == 0 + if( abs($sa - $ea) < 0.0001 ) { + $sa=2*M_PI; $ea=0; + } + + // Add inner circle first point + $xp = floor(($this->imidsize*$radius*cos($ea))+$xc); + $yp = floor($yc-($this->imidsize*$radius*sin($ea))); + $coords = "$xp, $yp"; + + //add coordinates every 0.25 radians + $a=$ea+0.25; + + // If we cross the 360-limit with a slice we need to handle + // the fact that end angle is smaller than start + if( $sa < $ea ) { + while ($a <= 2*M_PI) { + $xp = floor($radius*cos($a)+$xc); + $yp = floor($yc-$radius*sin($a)); + $coords.= ", $xp, $yp"; + $a += 0.25; + } + $a -= 2*M_PI; + } + + while ($a < $sa) { + $xp = floor(($this->imidsize*$radius*cos($a)+$xc)); + $yp = floor($yc-($this->imidsize*$radius*sin($a))); + $coords.= ", $xp, $yp"; + $a += 0.25; + } + + // Make sure we end at the last point + $xp = floor(($this->imidsize*$radius*cos($sa)+$xc)); + $yp = floor($yc-($this->imidsize*$radius*sin($sa))); + $coords.= ", $xp, $yp"; + + // Straight line to outer circle + $xp = floor($radius*cos($sa)+$xc); + $yp = floor($yc-$radius*sin($sa)); + $coords.= ", $xp, $yp"; + + //add coordinates every 0.25 radians + $a=$sa - 0.25; + while ($a > $ea) { + $xp = floor($radius*cos($a)+$xc); + $yp = floor($yc-$radius*sin($a)); + $coords.= ", $xp, $yp"; + $a -= 0.25; + } + + //Add the last point on the arc + $xp = floor($radius*cos($ea)+$xc); + $yp = floor($yc-$radius*sin($ea)); + $coords.= ", $xp, $yp"; + + // Close the arc + $xp = floor(($this->imidsize*$radius*cos($ea))+$xc); + $yp = floor($yc-($this->imidsize*$radius*sin($ea))); + $coords .= ", $xp, $yp"; + + if( !empty($this->csimtargets[$i]) ) { + $this->csimareas .= "csimtargets[$i]."\""; + if( !empty($this->csimwintargets[$i]) ) { + $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; + } + if( !empty($this->csimalts[$i]) ) { + $tmp=sprintf($this->csimalts[$i],$this->data[$i]); + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + } + + + function Stroke($img,$aaoption=0) { + + // Stroke the pie but don't stroke values + $tmp = $this->value->show; + $this->value->show = false; + parent::Stroke($img,$aaoption); + $this->value->show = $tmp; + + $xc = round($this->posx*$img->width); + $yc = round($this->posy*$img->height); + + $radius = floor($this->radius * min($img->width,$img->height)) ; + + + if( $this->imidsize > 0 && $aaoption !== 2 ) { + + if( $this->ishadowcolor != "" ) { + $img->SetColor($this->ishadowcolor); + $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop, + round($radius*$this->imidsize)); + } + + $img->SetColor($this->imidcolor); + $img->FilledCircle($xc,$yc,round($radius*$this->imidsize)); + + if( $this->pie_border && $aaoption === 0 ) { + $img->SetColor($this->color); + $img->Circle($xc,$yc,round($radius*$this->imidsize)); + } + + if( !empty($this->middlecsimtarget) ) + $this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize)); + + } + + if( $this->value->show && $aaoption !== 1) { + $this->StrokeAllLabels($img,$xc,$yc,$radius); + $this->midtitle->SetPos($xc,$yc,'center','center'); + $this->midtitle->Stroke($img); + } + + } + + function AddMiddleCSIM($xc,$yc,$r) { + $xc=round($xc);$yc=round($yc);$r=round($r); + $this->csimareas .= "middlecsimtarget."\""; + if( !empty($this->middlecsimwintarget) ) { + $this->csimareas .= " target=\"".$this->middlecsimwintarget."\""; + } + if( !empty($this->middlecsimalt) ) { + $tmp = $this->middlecsimalt; + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + + function StrokeLabel($label,$img,$xc,$yc,$a,$r) { + + if( $this->ilabelposadj === 'auto' ) + $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize; + + parent::StrokeLabel($label,$img,$xc,$yc,$a,$r); + + } + +} + + +//=================================================== +// CLASS PieGraph +// Description: +//=================================================== +class PieGraph extends Graph { + private $posx, $posy, $radius; + private $legends=array(); + public $plots=array(); + public $pieaa = false ; + //--------------- + // CONSTRUCTOR + function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { + parent::__construct($width,$height,$cachedName,$timeout,$inline); + $this->posx=$width/2; + $this->posy=$height/2; + $this->SetColor(array(255,255,255)); + + if ($this->graph_theme) { + $this->graph_theme->ApplyGraph($this); + } + } + + //--------------- + // PUBLIC METHODS + function Add($aObj) { + + if( is_array($aObj) && count($aObj) > 0 ) + $cl = $aObj[0]; + else + $cl = $aObj; + + if( $cl instanceof Text ) + $this->AddText($aObj); + elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) + $this->AddIcon($aObj); + else { + if( is_array($aObj) ) { + $n = count($aObj); + for($i=0; $i < $n; ++$i ) { + //if ($aObj[$i]->theme) { + // $this->ClearTheme(); + //} + $this->plots[] = $aObj[$i]; + } + } + else { + //if ($aObj->theme) { + // $this->ClearTheme(); + //} + $this->plots[] = $aObj; + } + } + + if ($this->graph_theme) { + $this->graph_theme->SetupPlot($aObj); + if ($aObj->is_using_plot_theme) { + $aObj->UsePlotThemeColors(); + } + } + } + + function SetAntiAliasing($aFlg=true) { + $this->pieaa = $aFlg; + } + + function SetColor($c) { + $this->SetMarginColor($c); + } + + + function DisplayCSIMAreas() { + $csim=""; + foreach($this->plots as $p ) { + $csim .= $p->GetCSIMareas(); + } + + $csim.= $this->legend->GetCSIMareas(); + if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) { + $this->img->SetColor($this->csimcolor); + $n = count($coords[0]); + for ($i=0; $i < $n; $i++) { + if ($coords[1][$i]=="poly") { + preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts); + $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]); + $m = count($pts[0]); + for ($j=0; $j < $m; $j++) { + $this->img->LineTo($pts[1][$j],$pts[2][$j]); + } + } else if ($coords[1][$i]=="rect") { + $pts = preg_split('/,/', $coords[2][$i]); + $this->img->SetStartPoint($pts[0],$pts[1]); + $this->img->LineTo($pts[2],$pts[1]); + $this->img->LineTo($pts[2],$pts[3]); + $this->img->LineTo($pts[0],$pts[3]); + $this->img->LineTo($pts[0],$pts[1]); + + } + } + } + } + + // Method description + function Stroke($aStrokeFileName="") { + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // a best we can. Therefor you will see a lot of tests !$_csim in the + // code below. + $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); + + // If we are called the second time (perhaps the user has called GetHTMLImageMap() + // himself then the legends have alsready been populated once in order to get the + // CSIM coordinats. Since we do not want the legends to be populated a second time + // we clear the legends + $this->legend->Clear(); + + // We need to know if we have stroked the plot in the + // GetCSIMareas. Otherwise the CSIM hasn't been generated + // and in the case of GetCSIM called before stroke to generate + // CSIM without storing an image to disk GetCSIM must call Stroke. + $this->iHasStroked = true; + + $n = count($this->plots); + + if( $this->pieaa ) { + + if( !$_csim ) { + if( $this->background_image != "" ) { + $this->StrokeFrameBackground(); + } + else { + $this->StrokeFrame(); + $this->StrokeBackgroundGrad(); + } + } + + + $w = $this->img->width; + $h = $this->img->height; + $oldimg = $this->img->img; + + $this->img->CreateImgCanvas(2*$w,2*$h); + + $this->img->SetColor( $this->margin_color ); + $this->img->FilledRectangle(0,0,2*$w-1,2*$h-1); + + // Make all icons *2 i size since we will be scaling down the + // imahe to do the anti aliasing + $ni = count($this->iIcons); + for($i=0; $i < $ni; ++$i) { + $this->iIcons[$i]->iScale *= 2 ; + if( $this->iIcons[$i]->iX > 1 ) + $this->iIcons[$i]->iX *= 2 ; + if( $this->iIcons[$i]->iY > 1 ) + $this->iIcons[$i]->iY *= 2 ; + } + + $this->StrokeIcons(); + + for($i=0; $i < $n; ++$i) { + if( $this->plots[$i]->posx > 1 ) + $this->plots[$i]->posx *= 2 ; + if( $this->plots[$i]->posy > 1 ) + $this->plots[$i]->posy *= 2 ; + + $this->plots[$i]->Stroke($this->img,1); + + if( $this->plots[$i]->posx > 1 ) + $this->plots[$i]->posx /= 2 ; + if( $this->plots[$i]->posy > 1 ) + $this->plots[$i]->posy /= 2 ; + } + + $indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ; + $indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ; + $this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent, + $w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent)); + + $this->img->img = $oldimg ; + $this->img->width = $w ; + $this->img->height = $h ; + + for($i=0; $i < $n; ++$i) { + $this->plots[$i]->Stroke($this->img,2); // Stroke labels + $this->plots[$i]->Legend($this); + } + + } + else { + + if( !$_csim ) { + if( $this->background_image != "" ) { + $this->StrokeFrameBackground(); + } + else { + $this->StrokeFrame(); + $this->StrokeBackgroundGrad(); + } + } + + $this->StrokeIcons(); + + for($i=0; $i < $n; ++$i) { + $this->plots[$i]->Stroke($this->img); + $this->plots[$i]->Legend($this); + } + } + + $this->legend->Stroke($this->img); + $this->footer->Stroke($this->img); + $this->StrokeTitles(); + + if( !$_csim ) { + + // Stroke texts + if( $this->texts != null ) { + $n = count($this->texts); + for($i=0; $i < $n; ++$i ) { + $this->texts[$i]->Stroke($this->img); + } + } + + if( _JPG_DEBUG ) { + $this->DisplayCSIMAreas(); + } + + // Should we do any final image transformation + if( $this->iImgTrans ) { + if( !class_exists('ImgTrans',false) ) { + require_once('jpgraph_imgtrans.php'); + //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.'); + } + + $tform = new ImgTrans($this->img->img); + $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, + $this->iImgTransDirection,$this->iImgTransHighQ, + $this->iImgTransMinSize,$this->iImgTransFillColor, + $this->iImgTransBorder); + } + + + // If the filename is given as the special "__handle" + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, + $aStrokeFileName); + } + } + } +} // Class + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_pie3d.php b/web/public_php/admin/jpgraph/jpgraph_pie3d.php index 4d8fd4b62..52b8631e6 100644 --- a/web/public_php/admin/jpgraph/jpgraph_pie3d.php +++ b/web/public_php/admin/jpgraph/jpgraph_pie3d.php @@ -1,912 +1,933 @@ -radius = 0.5; - $this->data = $data; - $this->title = new Text(""); - $this->title->SetFont(FF_FONT1,FS_BOLD); - $this->value = new DisplayValue(); - $this->value->Show(); - $this->value->SetFormat('%.0f%%'); - } - -//--------------- -// PUBLIC METHODS - - // Set label arrays - function SetLegends($aLegend) { - $this->legends = array_reverse(array_slice($aLegend,0,count($this->data))); - } - - function SetSliceColors($aColors) { - $this->setslicecolors = $aColors; - } - - function Legend(&$aGraph) { - parent::Legend($aGraph); - $aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol); - } - - function SetCSIMTargets($targets,$alts=null) { - $this->csimtargets = $targets; - $this->csimalts = $alts; - } - - // Should the slices be separated by a line? If color is specified as "" no line - // will be used to separate pie slices. - function SetEdge($aColor='black',$aWeight=1) { - $this->edgecolor = $aColor; - $this->edgeweight = $aWeight; - } - - // Dummy function to make Pie3D behave in a similair way to 2D - function ShowBorder($exterior=true,$interior=true) { - JpGraphError::RaiseL(14001); -//('Pie3D::ShowBorder() . Deprecated function. Use Pie3D::SetEdge() to control the edges around slices.'); - } - - // Specify projection angle for 3D in degrees - // Must be between 20 and 70 degrees - function SetAngle($a) { - if( $a<5 || $a>90 ) - JpGraphError::RaiseL(14002); -//("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees."); - else - $this->angle = $a; - } - - function AddSliceToCSIM($i,$xc,$yc,$height,$width,$thick,$sa,$ea) { //Slice number, ellipse centre (x,y), height, width, start angle, end angle - - $sa *= M_PI/180; - $ea *= M_PI/180; - - //add coordinates of the centre to the map - $coords = "$xc, $yc"; - - //add coordinates of the first point on the arc to the map - $xp = floor($width*cos($sa)/2+$xc); - $yp = floor($yc-$height*sin($sa)/2); - $coords.= ", $xp, $yp"; - - //If on the front half, add the thickness offset - if ($sa >= M_PI && $sa <= 2*M_PI*1.01) { - $yp = floor($yp+$thick); - $coords.= ", $xp, $yp"; - } - - //add coordinates every 0.2 radians - $a=$sa+0.2; - while ($a<$ea) { - $xp = floor($width*cos($a)/2+$xc); - if ($a >= M_PI && $a <= 2*M_PI*1.01) { - $yp = floor($yc-($height*sin($a)/2)+$thick); - } else { - $yp = floor($yc-$height*sin($a)/2); - } - $coords.= ", $xp, $yp"; - $a += 0.2; - } - - //Add the last point on the arc - $xp = floor($width*cos($ea)/2+$xc); - $yp = floor($yc-$height*sin($ea)/2); - - - if ($ea >= M_PI && $ea <= 2*M_PI*1.01) { - $coords.= ", $xp, ".floor($yp+$thick); - } - $coords.= ", $xp, $yp"; - $alt=''; - if( !empty($this->csimalts[$i]) ) { - $tmp=sprintf($this->csimalts[$i],$this->data[$i]); - $alt="alt=\"$tmp\" title=\"$tmp\""; - } - if( !empty($this->csimtargets[$i]) ) - $this->csimareas .= "csimtargets[$i]."\" $alt />\n"; - } - - function SetLabels($aLabels,$aLblPosAdj="auto") { - $this->labels = $aLabels; - $this->ilabelposadj=$aLblPosAdj; - } - - - // Distance from the pie to the labels - function SetLabelMargin($m) { - $this->value->SetMargin($m); - } - - // Show a thin line from the pie to the label for a specific slice - function ShowLabelHint($f=true) { - $this->showlabelhint=$f; - } - - // Set color of hint line to label for each slice - function SetLabelHintColor($c) { - $this->labelhintcolor=$c; - } - - function SetHeight($aHeight) { - $this->iThickness = $aHeight; - } - - -// Normalize Angle between 0-360 - function NormAngle($a) { - // Normalize anle to 0 to 2M_PI - // - if( $a > 0 ) { - while($a > 360) $a -= 360; - } - else { - while($a < 0) $a += 360; - } - if( $a < 0 ) - $a = 360 + $a; - - if( $a == 360 ) $a=0; - return $a; - } - - - -// Draw one 3D pie slice at position ($xc,$yc) with height $z - function Pie3DSlice($img,$xc,$yc,$w,$h,$sa,$ea,$z,$fillcolor,$shadow=0.65) { - - // Due to the way the 3D Pie algorithm works we are - // guaranteed that any slice we get into this method - // belongs to either the left or right side of the - // pie ellipse. Hence, no slice will cross 90 or 270 - // point. - if( ($sa < 90 && $ea > 90) || ( ($sa > 90 && $sa < 270) && $ea > 270) ) { - JpGraphError::RaiseL(14003);//('Internal assertion failed. Pie3D::Pie3DSlice'); - exit(1); - } - - $p[] = array(); - - // Setup pre-calculated values - $rsa = $sa/180*M_PI; // to Rad - $rea = $ea/180*M_PI; // to Rad - $sinsa = sin($rsa); - $cossa = cos($rsa); - $sinea = sin($rea); - $cosea = cos($rea); - - // p[] is the points for the overall slice and - // pt[] is the points for the top pie - - // Angular step when approximating the arc with a polygon train. - $step = 0.05; - - if( $sa >= 270 ) { - if( $ea > 360 || ($ea > 0 && $ea <= 90) ) { - if( $ea > 0 && $ea <= 90 ) { - // Adjust angle to simplify conditions in loops - $rea += 2*M_PI; - } - - $p = array($xc,$yc,$xc,$yc+$z, - $xc+$w*$cossa,$z+$yc-$h*$sinsa); - $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); - - for( $a=$rsa; $a < 2*M_PI; $a += $step ) { - $tca = cos($a); - $tsa = sin($a); - $p[] = $xc+$w*$tca; - $p[] = $z+$yc-$h*$tsa; - $pt[] = $xc+$w*$tca; - $pt[] = $yc-$h*$tsa; - } - - $pt[] = $xc+$w; - $pt[] = $yc; - - $p[] = $xc+$w; - $p[] = $z+$yc; - $p[] = $xc+$w; - $p[] = $yc; - $p[] = $xc; - $p[] = $yc; - - for( $a=2*M_PI+$step; $a < $rea; $a += $step ) { - $pt[] = $xc + $w*cos($a); - $pt[] = $yc - $h*sin($a); - } - - $pt[] = $xc+$w*$cosea; - $pt[] = $yc-$h*$sinea; - $pt[] = $xc; - $pt[] = $yc; - - } - else { - $p = array($xc,$yc,$xc,$yc+$z, - $xc+$w*$cossa,$z+$yc-$h*$sinsa); - $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); - - $rea = $rea == 0.0 ? 2*M_PI : $rea; - for( $a=$rsa; $a < $rea; $a += $step ) { - $tca = cos($a); - $tsa = sin($a); - $p[] = $xc+$w*$tca; - $p[] = $z+$yc-$h*$tsa; - $pt[] = $xc+$w*$tca; - $pt[] = $yc-$h*$tsa; - } - - $pt[] = $xc+$w*$cosea; - $pt[] = $yc-$h*$sinea; - $pt[] = $xc; - $pt[] = $yc; - - $p[] = $xc+$w*$cosea; - $p[] = $z+$yc-$h*$sinea; - $p[] = $xc+$w*$cosea; - $p[] = $yc-$h*$sinea; - $p[] = $xc; - $p[] = $yc; - } - } - elseif( $sa >= 180 ) { - $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea); - $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); - - for( $a=$rea; $a>$rsa; $a -= $step ) { - $tca = cos($a); - $tsa = sin($a); - $p[] = $xc+$w*$tca; - $p[] = $z+$yc-$h*$tsa; - $pt[] = $xc+$w*$tca; - $pt[] = $yc-$h*$tsa; - } - - $pt[] = $xc+$w*$cossa; - $pt[] = $yc-$h*$sinsa; - $pt[] = $xc; - $pt[] = $yc; - - $p[] = $xc+$w*$cossa; - $p[] = $z+$yc-$h*$sinsa; - $p[] = $xc+$w*$cossa; - $p[] = $yc-$h*$sinsa; - $p[] = $xc; - $p[] = $yc; - - } - elseif( $sa >= 90 ) { - if( $ea > 180 ) { - $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea); - $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); - - for( $a=$rea; $a > M_PI; $a -= $step ) { - $tca = cos($a); - $tsa = sin($a); - $p[] = $xc+$w*$tca; - $p[] = $z + $yc - $h*$tsa; - $pt[] = $xc+$w*$tca; - $pt[] = $yc-$h*$tsa; - } - - $p[] = $xc-$w; - $p[] = $z+$yc; - $p[] = $xc-$w; - $p[] = $yc; - $p[] = $xc; - $p[] = $yc; - - $pt[] = $xc-$w; - $pt[] = $z+$yc; - $pt[] = $xc-$w; - $pt[] = $yc; - - for( $a=M_PI-$step; $a > $rsa; $a -= $step ) { - $pt[] = $xc + $w*cos($a); - $pt[] = $yc - $h*sin($a); - } - - $pt[] = $xc+$w*$cossa; - $pt[] = $yc-$h*$sinsa; - $pt[] = $xc; - $pt[] = $yc; - - } - else { // $sa >= 90 && $ea <= 180 - $p = array($xc,$yc,$xc,$yc+$z, - $xc+$w*$cosea,$z+$yc-$h*$sinea, - $xc+$w*$cosea,$yc-$h*$sinea, - $xc,$yc); - - $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); - - for( $a=$rea; $a>$rsa; $a -= $step ) { - $pt[] = $xc + $w*cos($a); - $pt[] = $yc - $h*sin($a); - } - - $pt[] = $xc+$w*$cossa; - $pt[] = $yc-$h*$sinsa; - $pt[] = $xc; - $pt[] = $yc; - - } - } - else { // sa > 0 && ea < 90 - - $p = array($xc,$yc,$xc,$yc+$z, - $xc+$w*$cossa,$z+$yc-$h*$sinsa, - $xc+$w*$cossa,$yc-$h*$sinsa, - $xc,$yc); - - $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); - - for( $a=$rsa; $a < $rea; $a += $step ) { - $pt[] = $xc + $w*cos($a); - $pt[] = $yc - $h*sin($a); - } - - $pt[] = $xc+$w*$cosea; - $pt[] = $yc-$h*$sinea; - $pt[] = $xc; - $pt[] = $yc; - } - - $img->PushColor($fillcolor.":".$shadow); - $img->FilledPolygon($p); - $img->PopColor(); - - $img->PushColor($fillcolor); - $img->FilledPolygon($pt); - $img->PopColor(); - } - - function SetStartAngle($aStart) { - if( $aStart < 0 || $aStart > 360 ) { - JpGraphError::RaiseL(14004);//('Slice start angle must be between 0 and 360 degrees.'); - } - $this->startangle = $aStart; - } - -// Draw a 3D Pie - function Pie3D($aaoption,$img,$data,$colors,$xc,$yc,$d,$angle,$z, - $shadow=0.65,$startangle=0,$edgecolor="",$edgeweight=1) { - - //--------------------------------------------------------------------------- - // As usual the algorithm get more complicated than I originally - // envisioned. I believe that this is as simple as it is possible - // to do it with the features I want. It's a good exercise to start - // thinking on how to do this to convince your self that all this - // is really needed for the general case. - // - // The algorithm two draw 3D pies without "real 3D" is done in - // two steps. - // First imagine the pie cut in half through a thought line between - // 12'a clock and 6'a clock. It now easy to imagine that we can plot - // the individual slices for each half by starting with the topmost - // pie slice and continue down to 6'a clock. - // - // In the algortithm this is done in three principal steps - // Step 1. Do the knife cut to ensure by splitting slices that extends - // over the cut line. This is done by splitting the original slices into - // upto 3 subslices. - // Step 2. Find the top slice for each half - // Step 3. Draw the slices from top to bottom - // - // The thing that slightly complicates this scheme with all the - // angle comparisons below is that we can have an arbitrary start - // angle so we must take into account the different equivalence classes. - // For the same reason we must walk through the angle array in a - // modulo fashion. - // - // Limitations of algorithm: - // * A small exploded slice which crosses the 270 degree point - // will get slightly nagged close to the center due to the fact that - // we print the slices in Z-order and that the slice left part - // get printed first and might get slightly nagged by a larger - // slice on the right side just before the right part of the small - // slice. Not a major problem though. - //--------------------------------------------------------------------------- - - - // Determine the height of the ellippse which gives an - // indication of the inclination angle - $h = ($angle/90.0)*$d; - $sum = 0; - for($i=0; $ilabeltype == 2 ) { - $this->adjusted_data = $this->AdjPercentage($data); - } - - // Setup the start - $accsum = 0; - $a = $startangle; - $a = $this->NormAngle($a); - - // - // Step 1 . Split all slices that crosses 90 or 270 - // - $idx=0; - $adjexplode=array(); - $numcolors = count($colors); - for($i=0; $iexplode_radius[$i]) ) - $this->explode_radius[$i]=0; - - $expscale=1; - if( $aaoption == 1 ) - $expscale=2; - - $la = $a + $da/2; - $explode = array( $xc + $this->explode_radius[$i]*cos($la*M_PI/180)*$expscale, - $yc - $this->explode_radius[$i]*sin($la*M_PI/180) * ($h/$d) *$expscale ); - $adjexplode[$idx] = $explode; - $labeldata[$i] = array($la,$explode[0],$explode[1]); - $originalangles[$i] = array($a,$a+$da); - - $ne = $this->NormAngle($a+$da); - if( $da <= 180 ) { - // If the slice size is <= 90 it can at maximum cut across - // one boundary (either 90 or 270) where it needs to be split - $split=-1; // no split - if( ($da<=90 && ($a <= 90 && $ne > 90)) || - (($da <= 180 && $da >90) && (($a < 90 || $a >= 270) && $ne > 90)) ) { - $split = 90; - } - elseif( ($da<=90 && ($a <= 270 && $ne > 270)) || - (($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) { - $split = 270; - } - if( $split > 0 ) { // split in two - $angles[$idx] = array($a,$split); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - $angles[++$idx] = array($split,$ne); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - } - else { // no split - $angles[$idx] = array($a,$ne); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - } - } - else { - // da>180 - // Slice may, depending on position, cross one or two - // bonudaries - - if( $a < 90 ) - $split = 90; - elseif( $a <= 270 ) - $split = 270; - else - $split = 90; - - $angles[$idx] = array($a,$split); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - //if( $a+$da > 360-$split ) { - // For slices larger than 270 degrees we might cross - // another boundary as well. This means that we must - // split the slice further. The comparison gets a little - // bit complicated since we must take into accound that - // a pie might have a startangle >0 and hence a slice might - // wrap around the 0 angle. - // Three cases: - // a) Slice starts before 90 and hence gets a split=90, but - // we must also check if we need to split at 270 - // b) Slice starts after 90 but before 270 and slices - // crosses 90 (after a wrap around of 0) - // c) If start is > 270 (hence the firstr split is at 90) - // and the slice is so large that it goes all the way - // around 270. - if( ($a < 90 && ($a+$da > 270)) || - ($a > 90 && $a<=270 && ($a+$da>360+90) ) || - ($a > 270 && $this->NormAngle($a+$da)>270) ) { - $angles[++$idx] = array($split,360-$split); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - $angles[++$idx] = array(360-$split,$ne); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - } - else { - // Just a simple split to the previous decided - // angle. - $angles[++$idx] = array($split,$ne); - $adjcolors[$idx] = $colors[$i % $numcolors]; - $adjexplode[$idx] = $explode; - } - } - $a += $da; - $a = $this->NormAngle($a); - } - - // Total number of slices - $n = count($angles); - - for($i=0; $i<$n; ++$i) { - list($dbgs,$dbge) = $angles[$i]; - } - - // - // Step 2. Find start index (first pie that starts in upper left quadrant) - // - $minval = $angles[0][0]; - $min = 0; - for( $i=0; $i<$n; ++$i ) { - if( $angles[$i][0] < $minval ) { - $minval = $angles[$i][0]; - $min = $i; - } - } - $j = $min; - $cnt = 0; - while( $angles[$j][1] <= 90 ) { - $j++; - if( $j>=$n) { - $j=0; - } - if( $cnt > $n ) { - JpGraphError::RaiseL(14005); -//("Pie3D Internal error (#1). Trying to wrap twice when looking for start index"); - } - ++$cnt; - } - $start = $j; - - // - // Step 3. Print slices in z-order - // - $cnt = 0; - - // First stroke all the slices between 90 and 270 (left half circle) - // counterclockwise - - while( $angles[$j][0] < 270 && $aaoption !== 2 ) { - - list($x,$y) = $adjexplode[$j]; - - $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], - $z,$adjcolors[$j],$shadow); - - $last = array($x,$y,$j); - - $j++; - if( $j >= $n ) $j=0; - if( $cnt > $n ) { - JpGraphError::RaiseL(14006); -//("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); - } - ++$cnt; - } - - $slice_left = $n-$cnt; - $j=$start-1; - if($j<0) $j=$n-1; - $cnt = 0; - - // The stroke all slices from 90 to -90 (right half circle) - // clockwise - while( $cnt < $slice_left && $aaoption !== 2 ) { - - list($x,$y) = $adjexplode[$j]; - - $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], - $z,$adjcolors[$j],$shadow); - $j--; - if( $cnt > $n ) { - JpGraphError::RaiseL(14006); -//("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); - } - if($j<0) $j=$n-1; - $cnt++; - } - - // Now do a special thing. Stroke the last slice on the left - // halfcircle one more time. This is needed in the case where - // the slice close to 270 have been exploded. In that case the - // part of the slice close to the center of the pie might be - // slightly nagged. - if( $aaoption !== 2 ) - $this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0], - $angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow); - - - if( $aaoption !== 1 ) { - // Now print possible labels and add csim - $img->SetFont($this->value->ff,$this->value->fs); - $margin = $img->GetFontHeight()/2 + $this->value->margin ; - for($i=0; $i < count($data); ++$i ) { - $la = $labeldata[$i][0]; - $x = $labeldata[$i][1] + cos($la*M_PI/180)*($d+$margin); - $y = $labeldata[$i][2] - sin($la*M_PI/180)*($h+$margin); - if( $la > 180 && $la < 360 ) $y += $z; - if( $this->labeltype == 0 ) { - if( $sum > 0 ) - $l = 100*$data[$i]/$sum; - else - $l = 0; - } - elseif( $this->labeltype == 1 ) { - $l = $data[$i]; - } - else { - $l = $this->adjusted_data[$i]; - } - if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) - $l=sprintf($this->labels[$i],$l); - - $this->StrokeLabels($l,$img,$labeldata[$i][0]*M_PI/180,$x,$y,$z); - - $this->AddSliceToCSIM($i,$labeldata[$i][1],$labeldata[$i][2],$h*2,$d*2,$z, - $originalangles[$i][0],$originalangles[$i][1]); - } - } - - // - // Finally add potential lines in pie - // - - if( $edgecolor=="" || $aaoption !== 0 ) return; - - $accsum = 0; - $a = $startangle; - $a = $this->NormAngle($a); - - $a *= M_PI/180.0; - - $idx=0; - $img->PushColor($edgecolor); - $img->SetLineWeight($edgeweight); - - $fulledge = true; - for($i=0; $i < count($data) && $fulledge; ++$i ) { - if( empty($this->explode_radius[$i]) ) - $this->explode_radius[$i]=0; - if( $this->explode_radius[$i] > 0 ) { - $fulledge = false; - } - } - - - for($i=0; $i < count($data); ++$i, ++$idx ) { - - $da = $data[$i]/$sum * 2*M_PI; - $this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor, - $this->explode_radius[$i],$fulledge); - $a += $da; - } - $img->PopColor(); - } - - function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) { - $step = 0.02; - - if( $exploderadius > 0 ) { - $la = ($sa+$ea)/2; - $xc += $exploderadius*cos($la); - $yc -= $exploderadius*sin($la) * ($h/$w) ; - - } - - $p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa)); - - for($a=$sa; $a < $ea; $a += $step ) { - $p[] = $xc + $w*cos($a); - $p[] = $yc - $h*sin($a); - } - - $p[] = $xc+$w*cos($ea); - $p[] = $yc-$h*sin($ea); - $p[] = $xc; - $p[] = $yc; - - $img->SetColor($edgecolor); - $img->Polygon($p); - - // Unfortunately we can't really draw the full edge around the whole of - // of the slice if any of the slices are exploded. The reason is that - // this algorithm is to simply. There are cases where the edges will - // "overwrite" other slices when they have been exploded. - // Doing the full, proper 3D hidden lines stiff is actually quite - // tricky. So for exploded pies we only draw the top edge. Not perfect - // but the "real" solution is much more complicated. - if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) { - - if($sa < M_PI && $ea > M_PI) - $sa = M_PI; - - if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) ) - $ea = 2*M_PI; - - if( $sa >= M_PI && $ea <= 2*M_PI ) { - $p = array($xc + $w*cos($sa),$yc - $h*sin($sa), - $xc + $w*cos($sa),$z + $yc - $h*sin($sa)); - - for($a=$sa+$step; $a < $ea; $a += $step ) { - $p[] = $xc + $w*cos($a); - $p[] = $z + $yc - $h*sin($a); - } - $p[] = $xc + $w*cos($ea); - $p[] = $z + $yc - $h*sin($ea); - $p[] = $xc + $w*cos($ea); - $p[] = $yc - $h*sin($ea); - $img->SetColor($edgecolor); - $img->Polygon($p); - } - } - } - - function Stroke($img,$aaoption=0) { - $n = count($this->data); - - // If user hasn't set the colors use the theme array - if( $this->setslicecolors==null ) { - $colors = array_keys($img->rgb->rgb_table); - sort($colors); - $idx_a=$this->themearr[$this->theme]; - $ca = array(); - $m = count($idx_a); - for($i=0; $i < $m; ++$i) - $ca[$i] = $colors[$idx_a[$i]]; - $ca = array_reverse(array_slice($ca,0,$n)); - } - else { - $ca = $this->setslicecolors; - } - - - if( $this->posx <= 1 && $this->posx > 0 ) - $xc = round($this->posx*$img->width); - else - $xc = $this->posx ; - - if( $this->posy <= 1 && $this->posy > 0 ) - $yc = round($this->posy*$img->height); - else - $yc = $this->posy ; - - if( $this->radius <= 1 ) { - $width = floor($this->radius*min($img->width,$img->height)); - // Make sure that the pie doesn't overflow the image border - // The 0.9 factor is simply an extra margin to leave some space - // between the pie an the border of the image. - $width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9)); - } - else { - $width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ; - } - - // Add a sanity check for width - if( $width < 1 ) { - JpGraphError::RaiseL(14007);//("Width for 3D Pie is 0. Specify a size > 0"); - } - - // Establish a thickness. By default the thickness is a fifth of the - // pie slice width (=pie radius) but since the perspective depends - // on the inclination angle we use some heuristics to make the edge - // slightly thicker the less the angle. - - // Has user specified an absolute thickness? In that case use - // that instead - - if( $this->iThickness ) { - $thick = $this->iThickness; - $thick *= ($aaoption === 1 ? 2 : 1 ); - } - else - $thick = $width/12; - $a = $this->angle; - if( $a <= 30 ) $thick *= 1.6; - elseif( $a <= 40 ) $thick *= 1.4; - elseif( $a <= 50 ) $thick *= 1.2; - elseif( $a <= 60 ) $thick *= 1.0; - elseif( $a <= 70 ) $thick *= 0.8; - elseif( $a <= 80 ) $thick *= 0.7; - else $thick *= 0.6; - - $thick = floor($thick); - - if( $this->explode_all ) - for($i=0; $i < $n; ++$i) - $this->explode_radius[$i]=$this->explode_r; - - $this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle, - $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight); - - // Adjust title position - if( $aaoption != 1 ) { - $this->title->Pos($xc,$yc-$this->title->GetFontHeight($img)-$width/2-$this->title->margin, "center","bottom"); - $this->title->Stroke($img); - } - } - -//--------------- -// PRIVATE METHODS - - // Position the labels of each slice - function StrokeLabels($label,$img,$a,$xp,$yp,$z) { - $this->value->halign="left"; - $this->value->valign="top"; - - // Position the axis title. - // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text - // that intersects with the extension of the corresponding axis. The code looks a little - // bit messy but this is really the only way of having a reasonable position of the - // axis titles. - $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize); - $h=$img->GetTextHeight($label); - // For numeric values the format of the display value - // must be taken into account - if( is_numeric($label) ) { - if( $label >= 0 ) - $w=$img->GetTextWidth(sprintf($this->value->format,$label)); - else - $w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); - } - else - $w=$img->GetTextWidth($label); - while( $a > 2*M_PI ) $a -= 2*M_PI; - if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; - if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; - if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; - if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); - - if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; - if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI); - if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; - if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); - if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; - - $x = round($xp-$dx*$w); - $y = round($yp-$dy*$h); - - - // Mark anchor point for debugging - /* - $img->SetColor('red'); - $img->Line($xp-10,$yp,$xp+10,$yp); - $img->Line($xp,$yp-10,$xp,$yp+10); - */ - $oldmargin = $this->value->margin; - $this->value->margin=0; - $this->value->Stroke($img,$label,$x,$y); - $this->value->margin=$oldmargin; - - } -} // Class - -/* EOF */ -?> +radius = 0.5; + $this->data = $data; + $this->title = new Text(""); + $this->title->SetFont(FF_FONT1,FS_BOLD); + $this->value = new DisplayValue(); + $this->value->Show(); + $this->value->SetFormat('%.0f%%'); + } + + //--------------- + // PUBLIC METHODS + + // Set label arrays + function SetLegends($aLegend) { + $this->legends = array_reverse(array_slice($aLegend,0,count($this->data))); + } + + function SetSliceColors($aColors) { + $this->setslicecolors = $aColors; + } + + function Legend($aGraph) { + parent::Legend($aGraph); + $aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol); + } + + function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') { + $this->csimtargets = $aTargets; + $this->csimwintargets = $aWinTargets; + $this->csimalts = $aAlts; + } + + // Should the slices be separated by a line? If color is specified as "" no line + // will be used to separate pie slices. + function SetEdge($aColor='black',$aWeight=1) { + $this->edgecolor = $aColor; + $this->edgeweight = $aWeight; + } + + // Specify projection angle for 3D in degrees + // Must be between 20 and 70 degrees + function SetAngle($a) { + if( $a<5 || $a>90 ) { + JpGraphError::RaiseL(14002); + //("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees."); + } + else { + $this->angle = $a; + } + } + + function Add3DSliceToCSIM($i,$xc,$yc,$height,$width,$thick,$sa,$ea) { //Slice number, ellipse centre (x,y), height, width, start angle, end angle + + $sa *= M_PI/180; + $ea *= M_PI/180; + + //add coordinates of the centre to the map + $coords = "$xc, $yc"; + + //add coordinates of the first point on the arc to the map + $xp = floor($width*cos($sa)/2+$xc); + $yp = floor($yc-$height*sin($sa)/2); + $coords.= ", $xp, $yp"; + + //If on the front half, add the thickness offset + if ($sa >= M_PI && $sa <= 2*M_PI*1.01) { + $yp = floor($yp+$thick); + $coords.= ", $xp, $yp"; + } + + //add coordinates every 0.2 radians + $a=$sa+0.2; + while ($a<$ea) { + $xp = floor($width*cos($a)/2+$xc); + if ($a >= M_PI && $a <= 2*M_PI*1.01) { + $yp = floor($yc-($height*sin($a)/2)+$thick); + } else { + $yp = floor($yc-$height*sin($a)/2); + } + $coords.= ", $xp, $yp"; + $a += 0.2; + } + + //Add the last point on the arc + $xp = floor($width*cos($ea)/2+$xc); + $yp = floor($yc-$height*sin($ea)/2); + + + if ($ea >= M_PI && $ea <= 2*M_PI*1.01) { + $coords.= ", $xp, ".floor($yp+$thick); + } + $coords.= ", $xp, $yp"; + $alt=''; + + if( !empty($this->csimtargets[$i]) ) { + $this->csimareas .= "csimtargets[$i]."\""; + + if( !empty($this->csimwintargets[$i]) ) { + $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; + } + + if( !empty($this->csimalts[$i]) ) { + $tmp=sprintf($this->csimalts[$i],$this->data[$i]); + $this->csimareas .= "alt=\"$tmp\" title=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + + } + + function SetLabels($aLabels,$aLblPosAdj="auto") { + $this->labels = $aLabels; + $this->ilabelposadj=$aLblPosAdj; + } + + + // Distance from the pie to the labels + function SetLabelMargin($m) { + $this->value->SetMargin($m); + } + + // Show a thin line from the pie to the label for a specific slice + function ShowLabelHint($f=true) { + $this->showlabelhint=$f; + } + + // Set color of hint line to label for each slice + function SetLabelHintColor($c) { + $this->labelhintcolor=$c; + } + + function SetHeight($aHeight) { + $this->iThickness = $aHeight; + } + + + // Normalize Angle between 0-360 + function NormAngle($a) { + // Normalize anle to 0 to 2M_PI + // + if( $a > 0 ) { + while($a > 360) $a -= 360; + } + else { + while($a < 0) $a += 360; + } + if( $a < 0 ) + $a = 360 + $a; + + if( $a == 360 ) $a=0; + return $a; + } + + + + // Draw one 3D pie slice at position ($xc,$yc) with height $z + function Pie3DSlice($img,$xc,$yc,$w,$h,$sa,$ea,$z,$fillcolor,$shadow=0.65) { + + // Due to the way the 3D Pie algorithm works we are + // guaranteed that any slice we get into this method + // belongs to either the left or right side of the + // pie ellipse. Hence, no slice will cross 90 or 270 + // point. + if( ($sa < 90 && $ea > 90) || ( ($sa > 90 && $sa < 270) && $ea > 270) ) { + JpGraphError::RaiseL(14003);//('Internal assertion failed. Pie3D::Pie3DSlice'); + exit(1); + } + + $p[] = array(); + + // Setup pre-calculated values + $rsa = $sa/180*M_PI; // to Rad + $rea = $ea/180*M_PI; // to Rad + $sinsa = sin($rsa); + $cossa = cos($rsa); + $sinea = sin($rea); + $cosea = cos($rea); + + // p[] is the points for the overall slice and + // pt[] is the points for the top pie + + // Angular step when approximating the arc with a polygon train. + $step = 0.05; + + if( $sa >= 270 ) { + if( $ea > 360 || ($ea > 0 && $ea <= 90) ) { + if( $ea > 0 && $ea <= 90 ) { + // Adjust angle to simplify conditions in loops + $rea += 2*M_PI; + } + + $p = array($xc,$yc,$xc,$yc+$z, + $xc+$w*$cossa,$z+$yc-$h*$sinsa); + $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); + + for( $a=$rsa; $a < 2*M_PI; $a += $step ) { + $tca = cos($a); + $tsa = sin($a); + $p[] = $xc+$w*$tca; + $p[] = $z+$yc-$h*$tsa; + $pt[] = $xc+$w*$tca; + $pt[] = $yc-$h*$tsa; + } + + $pt[] = $xc+$w; + $pt[] = $yc; + + $p[] = $xc+$w; + $p[] = $z+$yc; + $p[] = $xc+$w; + $p[] = $yc; + $p[] = $xc; + $p[] = $yc; + + for( $a=2*M_PI+$step; $a < $rea; $a += $step ) { + $pt[] = $xc + $w*cos($a); + $pt[] = $yc - $h*sin($a); + } + + $pt[] = $xc+$w*$cosea; + $pt[] = $yc-$h*$sinea; + $pt[] = $xc; + $pt[] = $yc; + + } + else { + $p = array($xc,$yc,$xc,$yc+$z, + $xc+$w*$cossa,$z+$yc-$h*$sinsa); + $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); + + $rea = $rea == 0.0 ? 2*M_PI : $rea; + for( $a=$rsa; $a < $rea; $a += $step ) { + $tca = cos($a); + $tsa = sin($a); + $p[] = $xc+$w*$tca; + $p[] = $z+$yc-$h*$tsa; + $pt[] = $xc+$w*$tca; + $pt[] = $yc-$h*$tsa; + } + + $pt[] = $xc+$w*$cosea; + $pt[] = $yc-$h*$sinea; + $pt[] = $xc; + $pt[] = $yc; + + $p[] = $xc+$w*$cosea; + $p[] = $z+$yc-$h*$sinea; + $p[] = $xc+$w*$cosea; + $p[] = $yc-$h*$sinea; + $p[] = $xc; + $p[] = $yc; + } + } + elseif( $sa >= 180 ) { + $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea); + $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); + + for( $a=$rea; $a>$rsa; $a -= $step ) { + $tca = cos($a); + $tsa = sin($a); + $p[] = $xc+$w*$tca; + $p[] = $z+$yc-$h*$tsa; + $pt[] = $xc+$w*$tca; + $pt[] = $yc-$h*$tsa; + } + + $pt[] = $xc+$w*$cossa; + $pt[] = $yc-$h*$sinsa; + $pt[] = $xc; + $pt[] = $yc; + + $p[] = $xc+$w*$cossa; + $p[] = $z+$yc-$h*$sinsa; + $p[] = $xc+$w*$cossa; + $p[] = $yc-$h*$sinsa; + $p[] = $xc; + $p[] = $yc; + + } + elseif( $sa >= 90 ) { + if( $ea > 180 ) { + $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea); + $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); + + for( $a=$rea; $a > M_PI; $a -= $step ) { + $tca = cos($a); + $tsa = sin($a); + $p[] = $xc+$w*$tca; + $p[] = $z + $yc - $h*$tsa; + $pt[] = $xc+$w*$tca; + $pt[] = $yc-$h*$tsa; + } + + $p[] = $xc-$w; + $p[] = $z+$yc; + $p[] = $xc-$w; + $p[] = $yc; + $p[] = $xc; + $p[] = $yc; + + $pt[] = $xc-$w; + $pt[] = $z+$yc; + $pt[] = $xc-$w; + $pt[] = $yc; + + for( $a=M_PI-$step; $a > $rsa; $a -= $step ) { + $pt[] = $xc + $w*cos($a); + $pt[] = $yc - $h*sin($a); + } + + $pt[] = $xc+$w*$cossa; + $pt[] = $yc-$h*$sinsa; + $pt[] = $xc; + $pt[] = $yc; + + } + else { // $sa >= 90 && $ea <= 180 + $p = array($xc,$yc,$xc,$yc+$z, + $xc+$w*$cosea,$z+$yc-$h*$sinea, + $xc+$w*$cosea,$yc-$h*$sinea, + $xc,$yc); + + $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); + + for( $a=$rea; $a>$rsa; $a -= $step ) { + $pt[] = $xc + $w*cos($a); + $pt[] = $yc - $h*sin($a); + } + + $pt[] = $xc+$w*$cossa; + $pt[] = $yc-$h*$sinsa; + $pt[] = $xc; + $pt[] = $yc; + + } + } + else { // sa > 0 && ea < 90 + + $p = array($xc,$yc,$xc,$yc+$z, + $xc+$w*$cossa,$z+$yc-$h*$sinsa, + $xc+$w*$cossa,$yc-$h*$sinsa, + $xc,$yc); + + $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); + + for( $a=$rsa; $a < $rea; $a += $step ) { + $pt[] = $xc + $w*cos($a); + $pt[] = $yc - $h*sin($a); + } + + $pt[] = $xc+$w*$cosea; + $pt[] = $yc-$h*$sinea; + $pt[] = $xc; + $pt[] = $yc; + } + + $img->PushColor($fillcolor.":".$shadow); + $img->FilledPolygon($p); + $img->PopColor(); + + $img->PushColor($fillcolor); + $img->FilledPolygon($pt); + $img->PopColor(); + } + + function SetStartAngle($aStart) { + if( $aStart < 0 || $aStart > 360 ) { + JpGraphError::RaiseL(14004);//('Slice start angle must be between 0 and 360 degrees.'); + } + $this->startangle = $aStart; + } + + // Draw a 3D Pie + function Pie3D($aaoption,$img,$data,$colors,$xc,$yc,$d,$angle,$z, + $shadow=0.65,$startangle=0,$edgecolor="",$edgeweight=1) { + + //--------------------------------------------------------------------------- + // As usual the algorithm get more complicated than I originally + // envisioned. I believe that this is as simple as it is possible + // to do it with the features I want. It's a good exercise to start + // thinking on how to do this to convince your self that all this + // is really needed for the general case. + // + // The algorithm two draw 3D pies without "real 3D" is done in + // two steps. + // First imagine the pie cut in half through a thought line between + // 12'a clock and 6'a clock. It now easy to imagine that we can plot + // the individual slices for each half by starting with the topmost + // pie slice and continue down to 6'a clock. + // + // In the algortithm this is done in three principal steps + // Step 1. Do the knife cut to ensure by splitting slices that extends + // over the cut line. This is done by splitting the original slices into + // upto 3 subslices. + // Step 2. Find the top slice for each half + // Step 3. Draw the slices from top to bottom + // + // The thing that slightly complicates this scheme with all the + // angle comparisons below is that we can have an arbitrary start + // angle so we must take into account the different equivalence classes. + // For the same reason we must walk through the angle array in a + // modulo fashion. + // + // Limitations of algorithm: + // * A small exploded slice which crosses the 270 degree point + // will get slightly nagged close to the center due to the fact that + // we print the slices in Z-order and that the slice left part + // get printed first and might get slightly nagged by a larger + // slice on the right side just before the right part of the small + // slice. Not a major problem though. + //--------------------------------------------------------------------------- + + + // Determine the height of the ellippse which gives an + // indication of the inclination angle + $h = ($angle/90.0)*$d; + $sum = 0; + for($i=0; $ilabeltype == 2 ) { + $this->adjusted_data = $this->AdjPercentage($data); + } + + // Setup the start + $accsum = 0; + $a = $startangle; + $a = $this->NormAngle($a); + + // + // Step 1 . Split all slices that crosses 90 or 270 + // + $idx=0; + $adjexplode=array(); + $numcolors = count($colors); + for($i=0; $iexplode_radius[$i]) ) { + $this->explode_radius[$i]=0; + } + + $expscale=1; + if( $aaoption == 1 ) { + $expscale=2; + } + + $la = $a + $da/2; + $explode = array( $xc + $this->explode_radius[$i]*cos($la*M_PI/180)*$expscale, + $yc - $this->explode_radius[$i]*sin($la*M_PI/180) * ($h/$d) *$expscale ); + $adjexplode[$idx] = $explode; + $labeldata[$i] = array($la,$explode[0],$explode[1]); + $originalangles[$i] = array($a,$a+$da); + + $ne = $this->NormAngle($a+$da); + if( $da <= 180 ) { + // If the slice size is <= 90 it can at maximum cut across + // one boundary (either 90 or 270) where it needs to be split + $split=-1; // no split + if( ($da<=90 && ($a <= 90 && $ne > 90)) || + (($da <= 180 && $da >90) && (($a < 90 || $a >= 270) && $ne > 90)) ) { + $split = 90; + } + elseif( ($da<=90 && ($a <= 270 && $ne > 270)) || + (($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) { + $split = 270; + } + if( $split > 0 ) { // split in two + $angles[$idx] = array($a,$split); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + $angles[++$idx] = array($split,$ne); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + } + else { // no split + $angles[$idx] = array($a,$ne); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + } + } + else { + // da>180 + // Slice may, depending on position, cross one or two + // bonudaries + + if( $a < 90 ) $split = 90; + elseif( $a <= 270 ) $split = 270; + else $split = 90; + + $angles[$idx] = array($a,$split); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + //if( $a+$da > 360-$split ) { + // For slices larger than 270 degrees we might cross + // another boundary as well. This means that we must + // split the slice further. The comparison gets a little + // bit complicated since we must take into accound that + // a pie might have a startangle >0 and hence a slice might + // wrap around the 0 angle. + // Three cases: + // a) Slice starts before 90 and hence gets a split=90, but + // we must also check if we need to split at 270 + // b) Slice starts after 90 but before 270 and slices + // crosses 90 (after a wrap around of 0) + // c) If start is > 270 (hence the firstr split is at 90) + // and the slice is so large that it goes all the way + // around 270. + if( ($a < 90 && ($a+$da > 270)) || ($a > 90 && $a<=270 && ($a+$da>360+90) ) || ($a > 270 && $this->NormAngle($a+$da)>270) ) { + $angles[++$idx] = array($split,360-$split); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + $angles[++$idx] = array(360-$split,$ne); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + } + else { + // Just a simple split to the previous decided + // angle. + $angles[++$idx] = array($split,$ne); + $adjcolors[$idx] = $colors[$i % $numcolors]; + $adjexplode[$idx] = $explode; + } + } + $a += $da; + $a = $this->NormAngle($a); + } + + // Total number of slices + $n = count($angles); + + for($i=0; $i<$n; ++$i) { + list($dbgs,$dbge) = $angles[$i]; + } + + // + // Step 2. Find start index (first pie that starts in upper left quadrant) + // + $minval = $angles[0][0]; + $min = 0; + for( $i=0; $i<$n; ++$i ) { + if( $angles[$i][0] < $minval ) { + $minval = $angles[$i][0]; + $min = $i; + } + } + $j = $min; + $cnt = 0; + while( $angles[$j][1] <= 90 ) { + $j++; + if( $j>=$n) { + $j=0; + } + if( $cnt > $n ) { + JpGraphError::RaiseL(14005); + //("Pie3D Internal error (#1). Trying to wrap twice when looking for start index"); + } + ++$cnt; + } + $start = $j; + + // + // Step 3. Print slices in z-order + // + $cnt = 0; + + // First stroke all the slices between 90 and 270 (left half circle) + // counterclockwise + + while( $angles[$j][0] < 270 && $aaoption !== 2 ) { + + list($x,$y) = $adjexplode[$j]; + + $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], + $z,$adjcolors[$j],$shadow); + + $last = array($x,$y,$j); + + $j++; + if( $j >= $n ) $j=0; + if( $cnt > $n ) { + JpGraphError::RaiseL(14006); + //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); + } + ++$cnt; + } + + $slice_left = $n-$cnt; + $j=$start-1; + if($j<0) $j=$n-1; + $cnt = 0; + + // The stroke all slices from 90 to -90 (right half circle) + // clockwise + while( $cnt < $slice_left && $aaoption !== 2 ) { + + list($x,$y) = $adjexplode[$j]; + + $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], + $z,$adjcolors[$j],$shadow); + $j--; + if( $cnt > $n ) { + JpGraphError::RaiseL(14006); + //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); + } + if($j<0) $j=$n-1; + $cnt++; + } + + // Now do a special thing. Stroke the last slice on the left + // halfcircle one more time. This is needed in the case where + // the slice close to 270 have been exploded. In that case the + // part of the slice close to the center of the pie might be + // slightly nagged. + if( $aaoption !== 2 ) + $this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0], + $angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow); + + + if( $aaoption !== 1 ) { + // Now print possible labels and add csim + $this->value->ApplyFont($img); + $margin = $img->GetFontHeight()/2 + $this->value->margin ; + for($i=0; $i < count($data); ++$i ) { + $la = $labeldata[$i][0]; + $x = $labeldata[$i][1] + cos($la*M_PI/180)*($d+$margin)*$this->ilabelposadj; + $y = $labeldata[$i][2] - sin($la*M_PI/180)*($h+$margin)*$this->ilabelposadj; + if( $this->ilabelposadj >= 1.0 ) { + if( $la > 180 && $la < 360 ) $y += $z; + } + if( $this->labeltype == 0 ) { + if( $sum > 0 ) $l = 100*$data[$i]/$sum; + else $l = 0; + } + elseif( $this->labeltype == 1 ) { + $l = $data[$i]; + } + else { + $l = $this->adjusted_data[$i]; + } + if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) { + $l=sprintf($this->labels[$i],$l); + } + + $this->StrokeLabels($l,$img,$labeldata[$i][0]*M_PI/180,$x,$y,$z); + + $this->Add3DSliceToCSIM($i,$labeldata[$i][1],$labeldata[$i][2],$h*2,$d*2,$z, + $originalangles[$i][0],$originalangles[$i][1]); + } + } + + // + // Finally add potential lines in pie + // + + if( $edgecolor=="" || $aaoption !== 0 ) return; + + $accsum = 0; + $a = $startangle; + $a = $this->NormAngle($a); + + $a *= M_PI/180.0; + + $idx=0; + $img->PushColor($edgecolor); + $img->SetLineWeight($edgeweight); + + $fulledge = true; + for($i=0; $i < count($data) && $fulledge; ++$i ) { + if( empty($this->explode_radius[$i]) ) { + $this->explode_radius[$i]=0; + } + if( $this->explode_radius[$i] > 0 ) { + $fulledge = false; + } + } + + + for($i=0; $i < count($data); ++$i, ++$idx ) { + + $da = $data[$i]/$sum * 2*M_PI; + $this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor, + $this->explode_radius[$i],$fulledge); + $a += $da; + } + $img->PopColor(); + } + + function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) { + $step = 0.02; + + if( $exploderadius > 0 ) { + $la = ($sa+$ea)/2; + $xc += $exploderadius*cos($la); + $yc -= $exploderadius*sin($la) * ($h/$w) ; + + } + + $p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa)); + + for($a=$sa; $a < $ea; $a += $step ) { + $p[] = $xc + $w*cos($a); + $p[] = $yc - $h*sin($a); + } + + $p[] = $xc+$w*cos($ea); + $p[] = $yc-$h*sin($ea); + $p[] = $xc; + $p[] = $yc; + + $img->SetColor($edgecolor); + $img->Polygon($p); + + // Unfortunately we can't really draw the full edge around the whole of + // of the slice if any of the slices are exploded. The reason is that + // this algorithm is to simply. There are cases where the edges will + // "overwrite" other slices when they have been exploded. + // Doing the full, proper 3D hidden lines stiff is actually quite + // tricky. So for exploded pies we only draw the top edge. Not perfect + // but the "real" solution is much more complicated. + if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) { + + if($sa < M_PI && $ea > M_PI) { + $sa = M_PI; + } + + if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) ) { + $ea = 2*M_PI; + } + + if( $sa >= M_PI && $ea <= 2*M_PI ) { + $p = array($xc + $w*cos($sa),$yc - $h*sin($sa), + $xc + $w*cos($sa),$z + $yc - $h*sin($sa)); + + for($a=$sa+$step; $a < $ea; $a += $step ) { + $p[] = $xc + $w*cos($a); + $p[] = $z + $yc - $h*sin($a); + } + $p[] = $xc + $w*cos($ea); + $p[] = $z + $yc - $h*sin($ea); + $p[] = $xc + $w*cos($ea); + $p[] = $yc - $h*sin($ea); + $img->SetColor($edgecolor); + $img->Polygon($p); + } + } + } + + function Stroke($img,$aaoption=0) { + $n = count($this->data); + + // If user hasn't set the colors use the theme array + if( $this->setslicecolors==null ) { + $colors = array_keys($img->rgb->rgb_table); + sort($colors); + $idx_a=$this->themearr[$this->theme]; + $ca = array(); + $m = count($idx_a); + for($i=0; $i < $m; ++$i) { + $ca[$i] = $colors[$idx_a[$i]]; + } + $ca = array_reverse(array_slice($ca,0,$n)); + } + else { + $ca = $this->setslicecolors; + } + + + if( $this->posx <= 1 && $this->posx > 0 ) { + $xc = round($this->posx*$img->width); + } + else { + $xc = $this->posx ; + } + + if( $this->posy <= 1 && $this->posy > 0 ) { + $yc = round($this->posy*$img->height); + } + else { + $yc = $this->posy ; + } + + if( $this->radius <= 1 ) { + $width = floor($this->radius*min($img->width,$img->height)); + // Make sure that the pie doesn't overflow the image border + // The 0.9 factor is simply an extra margin to leave some space + // between the pie an the border of the image. + $width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9)); + } + else { + $width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ; + } + + // Add a sanity check for width + if( $width < 1 ) { + JpGraphError::RaiseL(14007);//("Width for 3D Pie is 0. Specify a size > 0"); + } + + // Establish a thickness. By default the thickness is a fifth of the + // pie slice width (=pie radius) but since the perspective depends + // on the inclination angle we use some heuristics to make the edge + // slightly thicker the less the angle. + + // Has user specified an absolute thickness? In that case use + // that instead + + if( $this->iThickness ) { + $thick = $this->iThickness; + $thick *= ($aaoption === 1 ? 2 : 1 ); + } + else { + $thick = $width/12; + } + $a = $this->angle; + + if( $a <= 30 ) $thick *= 1.6; + elseif( $a <= 40 ) $thick *= 1.4; + elseif( $a <= 50 ) $thick *= 1.2; + elseif( $a <= 60 ) $thick *= 1.0; + elseif( $a <= 70 ) $thick *= 0.8; + elseif( $a <= 80 ) $thick *= 0.7; + else $thick *= 0.6; + + $thick = floor($thick); + + if( $this->explode_all ) { + for($i=0; $i < $n; ++$i) + $this->explode_radius[$i]=$this->explode_r; + } + + $this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle, + $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight); + + // Adjust title position + if( $aaoption != 1 ) { + $this->title->SetPos($xc,$yc-$this->title->GetFontHeight($img)-$width/2-$this->title->margin, "center","bottom"); + $this->title->Stroke($img); + } + } + + //--------------- + // PRIVATE METHODS + + // Position the labels of each slice + function StrokeLabels($label,$img,$a,$xp,$yp,$z) { + $this->value->halign="left"; + $this->value->valign="top"; + + // Position the axis title. + // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text + // that intersects with the extension of the corresponding axis. The code looks a little + // bit messy but this is really the only way of having a reasonable position of the + // axis titles. + $this->value->ApplyFont($img); + $h=$img->GetTextHeight($label); + // For numeric values the format of the display value + // must be taken into account + if( is_numeric($label) ) { + if( $label >= 0 ) { + $w=$img->GetTextWidth(sprintf($this->value->format,$label)); + } + else { + $w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); + } + } + else { + $w=$img->GetTextWidth($label); + } + + while( $a > 2*M_PI ) { + $a -= 2*M_PI; + } + + if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); + + if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; + if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI); + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; + + $x = round($xp-$dx*$w); + $y = round($yp-$dy*$h); + + // Mark anchor point for debugging + /* + $img->SetColor('red'); + $img->Line($xp-10,$yp,$xp+10,$yp); + $img->Line($xp,$yp-10,$xp,$yp+10); + */ + + $oldmargin = $this->value->margin; + $this->value->margin=0; + $this->value->Stroke($img,$label,$x,$y); + $this->value->margin=$oldmargin; + + } +} // Class + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_plotband.php b/web/public_php/admin/jpgraph/jpgraph_plotband.php index a969e5720..b7aef7506 100644 --- a/web/public_php/admin/jpgraph/jpgraph_plotband.php +++ b/web/public_php/admin/jpgraph/jpgraph_plotband.php @@ -1,635 +1,635 @@ -x=$aX; - $this->y=$aY; - $this->w=$aWidth; - $this->h=$aHeight; - $this->xe=$aX+$aWidth-1; - $this->ye=$aY+$aHeight-1; - } -} - -//===================================================================== -// Class RectPattern -// Base class for pattern hierarchi that is used to display patterned -// bands on the graph. Any subclass that doesn't override Stroke() -// must at least implement method DoPattern(&$aImg) which is responsible -// for drawing the pattern onto the graph. -//===================================================================== -class RectPattern { - var $color; - var $weight; - var $rect=null; - var $doframe=true; - var $linespacing; // Line spacing in pixels - var $iBackgroundColor=-1; // Default is no background fill - - function RectPattern($aColor,$aWeight=1) { - $this->color = $aColor; - $this->weight = $aWeight; - } - - function SetBackground($aBackgroundColor) { - $this->iBackgroundColor=$aBackgroundColor; - } - - function SetPos(&$aRect) { - $this->rect = $aRect; - } - - function ShowFrame($aShow=true) { - $this->doframe=$aShow; - } - - function SetDensity($aDens) { - if( $aDens < 1 || $aDens > 100 ) - JpGraphError::RaiseL(16001,$aDens); -//(" Desity for pattern must be between 1 and 100. (You tried $aDens)"); - // 1% corresponds to linespacing=50 - // 100 % corresponds to linespacing 1 - $this->linespacing = floor(((100-$aDens)/100.0)*50)+1; - - } - - function Stroke(&$aImg) { - if( $this->rect == null ) - JpGraphError::RaiseL(16002); -//(" No positions specified for pattern."); - - if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) { - $aImg->SetColor($this->iBackgroundColor); - $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); - } - - $aImg->SetColor($this->color); - $aImg->SetLineWeight($this->weight); - - // Virtual function implemented by subclass - $this->DoPattern($aImg); - - // Frame around the pattern area - if( $this->doframe ) - $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); - } - -} - - -//===================================================================== -// Class RectPatternSolid -// Implements a solid band -//===================================================================== -class RectPatternSolid extends RectPattern { - - function RectPatternSolid($aColor="black",$aWeight=1) { - parent::RectPattern($aColor,$aWeight); - } - - function DoPattern(&$aImg) { - $aImg->SetColor($this->color); - $aImg->FilledRectangle($this->rect->x,$this->rect->y, - $this->rect->xe,$this->rect->ye); - } -} - -//===================================================================== -// Class RectPatternHor -// Implements horizontal line pattern -//===================================================================== -class RectPatternHor extends RectPattern { - - function RectPatternHor($aColor="black",$aWeight=1,$aLineSpacing=7) { - parent::RectPattern($aColor,$aWeight); - $this->linespacing = $aLineSpacing; - } - - function DoPattern(&$aImg) { - $x0 = $this->rect->x; - $x1 = $this->rect->xe; - $y = $this->rect->y; - while( $y < $this->rect->ye ) { - $aImg->Line($x0,$y,$x1,$y); - $y += $this->linespacing; - } - } -} - -//===================================================================== -// Class RectPatternVert -// Implements vertical line pattern -//===================================================================== -class RectPatternVert extends RectPattern { - var $linespacing=10; // Line spacing in pixels - - function RectPatternVert($aColor="black",$aWeight=1,$aLineSpacing=7) { - parent::RectPattern($aColor,$aWeight); - $this->linespacing = $aLineSpacing; - } - - //-------------------- - // Private methods - // - function DoPattern(&$aImg) { - $x = $this->rect->x; - $y0 = $this->rect->y; - $y1 = $this->rect->ye; - while( $x < $this->rect->xe ) { - $aImg->Line($x,$y0,$x,$y1); - $x += $this->linespacing; - } - } -} - - -//===================================================================== -// Class RectPatternRDiag -// Implements right diagonal pattern -//===================================================================== -class RectPatternRDiag extends RectPattern { - var $linespacing; // Line spacing in pixels - - function RectPatternRDiag($aColor="black",$aWeight=1,$aLineSpacing=12) { - parent::RectPattern($aColor,$aWeight); - $this->linespacing = $aLineSpacing; - } - - function DoPattern(&$aImg) { - // -------------------- - // | / / / / /| - // |/ / / / / | - // | / / / / | - // -------------------- - $xe = $this->rect->xe; - $ye = $this->rect->ye; - $x0 = $this->rect->x + round($this->linespacing/2); - $y0 = $this->rect->y; - $x1 = $this->rect->x; - $y1 = $this->rect->y + round($this->linespacing/2); - - while($x0<=$xe && $y1<=$ye) { - $aImg->Line($x0,$y0,$x1,$y1); - $x0 += $this->linespacing; - $y1 += $this->linespacing; - } - - if( $xe-$x1 > $ye-$y0 ) { - // Width larger than height - $x1 = $this->rect->x + ($y1-$ye); - $y1 = $ye; - $y0 = $this->rect->y; - while( $x0 <= $xe ) { - $aImg->Line($x0,$y0,$x1,$y1); - $x0 += $this->linespacing; - $x1 += $this->linespacing; - } - - $y0=$this->rect->y + ($x0-$xe); - $x0=$xe; - } - else { - // Height larger than width - $diff = $x0-$xe; - $y0 = $diff+$this->rect->y; - $x0 = $xe; - $x1 = $this->rect->x; - while( $y1 <= $ye ) { - $aImg->Line($x0,$y0,$x1,$y1); - $y1 += $this->linespacing; - $y0 += $this->linespacing; - } - - $diff = $y1-$ye; - $y1 = $ye; - $x1 = $diff + $this->rect->x; - } - - while( $y0 <= $ye ) { - $aImg->Line($x0,$y0,$x1,$y1); - $y0 += $this->linespacing; - $x1 += $this->linespacing; - } - } -} - -//===================================================================== -// Class RectPatternLDiag -// Implements left diagonal pattern -//===================================================================== -class RectPatternLDiag extends RectPattern { - var $linespacing; // Line spacing in pixels - - function RectPatternLDiag($aColor="black",$aWeight=1,$aLineSpacing=12) { - $this->linespacing = $aLineSpacing; - parent::RectPattern($aColor,$aWeight); - } - - function DoPattern(&$aImg) { - // -------------------- - // |\ \ \ \ \ | - // | \ \ \ \ \| - // | \ \ \ \ | - // |------------------| - $xe = $this->rect->xe; - $ye = $this->rect->ye; - $x0 = $this->rect->x + round($this->linespacing/2); - $y0 = $this->rect->ye; - $x1 = $this->rect->x; - $y1 = $this->rect->ye - round($this->linespacing/2); - - while($x0<=$xe && $y1>=$this->rect->y) { - $aImg->Line($x0,$y0,$x1,$y1); - $x0 += $this->linespacing; - $y1 -= $this->linespacing; - } - if( $xe-$x1 > $ye-$this->rect->y ) { - // Width larger than height - $x1 = $this->rect->x + ($this->rect->y-$y1); - $y0=$ye; $y1=$this->rect->y; - while( $x0 <= $xe ) { - $aImg->Line($x0,$y0,$x1,$y1); - $x0 += $this->linespacing; - $x1 += $this->linespacing; - } - - $y0=$this->rect->ye - ($x0-$xe); - $x0=$xe; - } - else { - // Height larger than width - $diff = $x0-$xe; - $y0 = $ye-$diff; - $x0 = $xe; - while( $y1 >= $this->rect->y ) { - $aImg->Line($x0,$y0,$x1,$y1); - $y0 -= $this->linespacing; - $y1 -= $this->linespacing; - } - $diff = $this->rect->y - $y1; - $x1 = $this->rect->x + $diff; - $y1 = $this->rect->y; - } - while( $y0 >= $this->rect->y ) { - $aImg->Line($x0,$y0,$x1,$y1); - $y0 -= $this->linespacing; - $x1 += $this->linespacing; - } - } -} - -//===================================================================== -// Class RectPattern3DPlane -// Implements "3D" plane pattern -//===================================================================== -class RectPattern3DPlane extends RectPattern { - var $alpha=50; // Parameter that specifies the distance - // to "simulated" horizon in pixel from the - // top of the band. Specifies how fast the lines - // converge. - - function RectPattern3DPlane($aColor="black",$aWeight=1) { - parent::RectPattern($aColor,$aWeight); - $this->SetDensity(10); // Slightly larger default - } - - function SetHorizon($aHorizon) { - $this->alpha=$aHorizon; - } - - function DoPattern(&$aImg) { - // "Fake" a nice 3D grid-effect. - $x0 = $this->rect->x + $this->rect->w/2; - $y0 = $this->rect->y; - $x1 = $x0; - $y1 = $this->rect->ye; - $x0_right = $x0; - $x1_right = $x1; - - // BTW "apa" means monkey in Swedish but is really a shortform for - // "alpha+a" which was the labels I used on paper when I derived the - // geometric to get the 3D perspective right. - // $apa is the height of the bounding rectangle plus the distance to the - // artifical horizon (alpha) - $apa = $this->rect->h + $this->alpha; - - // Three cases and three loops - // 1) The endpoint of the line ends on the bottom line - // 2) The endpoint ends on the side - // 3) Horizontal lines - - // Endpoint falls on bottom line - $middle=$this->rect->x + $this->rect->w/2; - $dist=$this->linespacing; - $factor=$this->alpha /($apa); - while($x1>$this->rect->x) { - $aImg->Line($x0,$y0,$x1,$y1); - $aImg->Line($x0_right,$y0,$x1_right,$y1); - $x1 = $middle - $dist; - $x0 = $middle - $dist * $factor; - $x1_right = $middle + $dist; - $x0_right = $middle + $dist * $factor; - $dist += $this->linespacing; - } - - // Endpoint falls on sides - $dist -= $this->linespacing; - $d=$this->rect->w/2; - $c = $apa - $d*$apa/$dist; - while( $x0>$this->rect->x ) { - $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c); - $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c); - $dist += $this->linespacing; - $x0 = $middle - $dist * $factor; - $x1 = $middle - $dist; - $x0_right = $middle + $dist * $factor; - $c = $apa - $d*$apa/$dist; - } - - // Horizontal lines - // They need some serious consideration since they are a function - // of perspective depth (alpha) and density (linespacing) - $x0=$this->rect->x; - $x1=$this->rect->xe; - $y=$this->rect->ye; - - // The first line is drawn directly. Makes the loop below slightly - // more readable. - $aImg->Line($x0,$y,$x1,$y); - $hls = $this->linespacing; - - // A correction factor for vertical "brick" line spacing to account for - // a) the difference in number of pixels hor vs vert - // b) visual apperance to make the first layer of "bricks" look more - // square. - $vls = $this->linespacing*0.6; - - $ds = $hls*($apa-$vls)/$apa; - // Get the slope for the "perspective line" going from bottom right - // corner to top left corner of the "first" brick. - - // Uncomment the following lines if you want to get a visual understanding - // of what this helpline does. BTW this mimics the way you would get the - // perspective right when drawing on paper. - /* - $x0 = $middle; - $y0 = $this->rect->ye; - $len=floor(($this->rect->ye-$this->rect->y)/$vls); - $x1 = $middle+round($len*$ds); - $y1 = $this->rect->ye-$len*$vls; - $aImg->PushColor("red"); - $aImg->Line($x0,$y0,$x1,$y1); - $aImg->PopColor(); - */ - - $y -= $vls; - $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds)); - $dist = $hls; - while( $y>$this->rect->y ) { - $aImg->Line($this->rect->x,$y,$this->rect->xe,$y); - $adj = $k*$dist/(1+$dist*$k/$apa); - if( $adj < 2 ) $adj=1; - $y = $this->rect->ye - round($adj); - $dist += $hls; - } - } -} - -//===================================================================== -// Class RectPatternCross -// Vert/Hor crosses -//===================================================================== -class RectPatternCross extends RectPattern { - var $vert=null; - var $hor=null; - function RectPatternCross($aColor="black",$aWeight=1) { - parent::RectPattern($aColor,$aWeight); - $this->vert = new RectPatternVert($aColor,$aWeight); - $this->hor = new RectPatternHor($aColor,$aWeight); - } - - function SetOrder($aDepth) { - $this->vert->SetOrder($aDepth); - $this->hor->SetOrder($aDepth); - } - - function SetPos(&$aRect) { - parent::SetPos($aRect); - $this->vert->SetPos($aRect); - $this->hor->SetPos($aRect); - } - - function SetDensity($aDens) { - $this->vert->SetDensity($aDens); - $this->hor->SetDensity($aDens); - } - - function DoPattern(&$aImg) { - $this->vert->DoPattern($aImg); - $this->hor->DoPattern($aImg); - } -} - -//===================================================================== -// Class RectPatternDiagCross -// Vert/Hor crosses -//===================================================================== - -class RectPatternDiagCross extends RectPattern { - var $left=null; - var $right=null; - function RectPatternDiagCross($aColor="black",$aWeight=1) { - parent::RectPattern($aColor,$aWeight); - $this->right = new RectPatternRDiag($aColor,$aWeight); - $this->left = new RectPatternLDiag($aColor,$aWeight); - } - - function SetOrder($aDepth) { - $this->left->SetOrder($aDepth); - $this->right->SetOrder($aDepth); - } - - function SetPos(&$aRect) { - parent::SetPos($aRect); - $this->left->SetPos($aRect); - $this->right->SetPos($aRect); - } - - function SetDensity($aDens) { - $this->left->SetDensity($aDens); - $this->right->SetDensity($aDens); - } - - function DoPattern(&$aImg) { - $this->left->DoPattern($aImg); - $this->right->DoPattern($aImg); - } - -} - -//===================================================================== -// Class RectPatternFactory -// Factory class for rectangular pattern -//===================================================================== -class RectPatternFactory { - function RectPatternFactory() { - // Empty - } - function Create($aPattern,$aColor,$aWeight=1) { - switch($aPattern) { - case BAND_RDIAG: - $obj = new RectPatternRDiag($aColor,$aWeight); - break; - case BAND_LDIAG: - $obj = new RectPatternLDiag($aColor,$aWeight); - break; - case BAND_SOLID: - $obj = new RectPatternSolid($aColor,$aWeight); - break; - case BAND_VLINE: - $obj = new RectPatternVert($aColor,$aWeight); - break; - case BAND_HLINE: - $obj = new RectPatternHor($aColor,$aWeight); - break; - case BAND_3DPLANE: - $obj = new RectPattern3DPlane($aColor,$aWeight); - break; - case BAND_HVCROSS: - $obj = new RectPatternCross($aColor,$aWeight); - break; - case BAND_DIAGCROSS: - $obj = new RectPatternDiagCross($aColor,$aWeight); - break; - default: - JpGraphError::RaiseL(16003,$aPattern); -//(" Unknown pattern specification ($aPattern)"); - } - return $obj; - } -} - - -//===================================================================== -// Class PlotBand -// Factory class which is used by the client. -// It is responsible for factoring the corresponding pattern -// concrete class. -//===================================================================== -class PlotBand { - var $prect=null; - var $depth; - var $dir, $min, $max; - - function PlotBand($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) { - $f = new RectPatternFactory(); - $this->prect = $f->Create($aPattern,$aColor,$aWeight); - if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) ) - JpGraphError::RaiseL(16004); -//('Min value for plotband is larger than specified max value. Please correct.'); - $this->dir = $aDir; - $this->min = $aMin; - $this->max = $aMax; - $this->depth=$aDepth; - } - - // Set position. aRect contains absolute image coordinates - function SetPos(&$aRect) { - assert( $this->prect != null ) ; - $this->prect->SetPos($aRect); - } - - function ShowFrame($aFlag=true) { - $this->prect->ShowFrame($aFlag); - } - - // Set z-order. In front of pplot or in the back - function SetOrder($aDepth) { - $this->depth=$aDepth; - } - - function SetDensity($aDens) { - $this->prect->SetDensity($aDens); - } - - function GetDir() { - return $this->dir; - } - - function GetMin() { - return $this->min; - } - - function GetMax() { - return $this->max; - } - - // Display band - function Stroke(&$aImg,&$aXScale,&$aYScale) { - assert( $this->prect != null ) ; - if( $this->dir == HORIZONTAL ) { - if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal(); - if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal(); - - // Only draw the bar if it actually appears in the range - if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) { - - // Trucate to limit of axis - $this->min = max($this->min, $aYScale->GetMinVal()); - $this->max = min($this->max, $aYScale->GetMaxVal()); - - $x=$aXScale->scale_abs[0]; - $y=$aYScale->Translate($this->max); - $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1; - $height=abs($y-$aYScale->Translate($this->min))+1; - $this->prect->SetPos(new Rectangle($x,$y,$width,$height)); - $this->prect->Stroke($aImg); - } - } - else { // VERTICAL - if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal(); - if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal(); - - // Only draw the bar if it actually appears in the range - if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) { - - // Trucate to limit of axis - $this->min = max($this->min, $aXScale->GetMinVal()); - $this->max = min($this->max, $aXScale->GetMaxVal()); - - $y=$aYScale->scale_abs[1]; - $x=$aXScale->Translate($this->min); - $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]); - $width=abs($x-$aXScale->Translate($this->max)); - $this->prect->SetPos(new Rectangle($x,$y,$width,$height)); - $this->prect->Stroke($aImg); - } - } - } -} - - -?> +x=$aX; + $this->y=$aY; + $this->w=$aWidth; + $this->h=$aHeight; + $this->xe=$aX+$aWidth-1; + $this->ye=$aY+$aHeight-1; + } +} + +//===================================================================== +// Class RectPattern +// Base class for pattern hierarchi that is used to display patterned +// bands on the graph. Any subclass that doesn't override Stroke() +// must at least implement method DoPattern($aImg) which is responsible +// for drawing the pattern onto the graph. +//===================================================================== +class RectPattern { + protected $color; + protected $weight; + protected $rect=null; + protected $doframe=true; + protected $linespacing; // Line spacing in pixels + protected $iBackgroundColor=-1; // Default is no background fill + + function __construct($aColor,$aWeight=1) { + $this->color = $aColor; + $this->weight = $aWeight; + } + + function SetBackground($aBackgroundColor) { + $this->iBackgroundColor=$aBackgroundColor; + } + + function SetPos($aRect) { + $this->rect = $aRect; + } + + function ShowFrame($aShow=true) { + $this->doframe=$aShow; + } + + function SetDensity($aDens) { + if( $aDens < 1 || $aDens > 100 ) + JpGraphError::RaiseL(16001,$aDens); + //(" Desity for pattern must be between 1 and 100. (You tried $aDens)"); + // 1% corresponds to linespacing=50 + // 100 % corresponds to linespacing 1 + $this->linespacing = floor(((100-$aDens)/100.0)*50)+1; + + } + + function Stroke($aImg) { + if( $this->rect == null ) + JpGraphError::RaiseL(16002); + //(" No positions specified for pattern."); + + if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) { + $aImg->SetColor($this->iBackgroundColor); + $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); + } + + $aImg->SetColor($this->color); + $aImg->SetLineWeight($this->weight); + + // Virtual function implemented by subclass + $this->DoPattern($aImg); + + // Frame around the pattern area + if( $this->doframe ) + $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); + } + +} + + +//===================================================================== +// Class RectPatternSolid +// Implements a solid band +//===================================================================== +class RectPatternSolid extends RectPattern { + + function __construct($aColor="black",$aWeight=1) { + parent::__construct($aColor,$aWeight); + } + + function DoPattern($aImg) { + $aImg->SetColor($this->color); + $aImg->FilledRectangle($this->rect->x,$this->rect->y, + $this->rect->xe,$this->rect->ye); + } +} + +//===================================================================== +// Class RectPatternHor +// Implements horizontal line pattern +//===================================================================== +class RectPatternHor extends RectPattern { + + function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) { + parent::__construct($aColor,$aWeight); + $this->linespacing = $aLineSpacing; + } + + function DoPattern($aImg) { + $x0 = $this->rect->x; + $x1 = $this->rect->xe; + $y = $this->rect->y; + while( $y < $this->rect->ye ) { + $aImg->Line($x0,$y,$x1,$y); + $y += $this->linespacing; + } + } +} + +//===================================================================== +// Class RectPatternVert +// Implements vertical line pattern +//===================================================================== +class RectPatternVert extends RectPattern { + + function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) { + parent::__construct($aColor,$aWeight); + $this->linespacing = $aLineSpacing; + } + + //-------------------- + // Private methods + // + function DoPattern($aImg) { + $x = $this->rect->x; + $y0 = $this->rect->y; + $y1 = $this->rect->ye; + while( $x < $this->rect->xe ) { + $aImg->Line($x,$y0,$x,$y1); + $x += $this->linespacing; + } + } +} + + +//===================================================================== +// Class RectPatternRDiag +// Implements right diagonal pattern +//===================================================================== +class RectPatternRDiag extends RectPattern { + + function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) { + parent::__construct($aColor,$aWeight); + $this->linespacing = $aLineSpacing; + } + + function DoPattern($aImg) { + // -------------------- + // | / / / / /| + // |/ / / / / | + // | / / / / | + // -------------------- + $xe = $this->rect->xe; + $ye = $this->rect->ye; + $x0 = $this->rect->x + round($this->linespacing/2); + $y0 = $this->rect->y; + $x1 = $this->rect->x; + $y1 = $this->rect->y + round($this->linespacing/2); + + while($x0<=$xe && $y1<=$ye) { + $aImg->Line($x0,$y0,$x1,$y1); + $x0 += $this->linespacing; + $y1 += $this->linespacing; + } + + if( $xe-$x1 > $ye-$y0 ) { + // Width larger than height + $x1 = $this->rect->x + ($y1-$ye); + $y1 = $ye; + $y0 = $this->rect->y; + while( $x0 <= $xe ) { + $aImg->Line($x0,$y0,$x1,$y1); + $x0 += $this->linespacing; + $x1 += $this->linespacing; + } + + $y0=$this->rect->y + ($x0-$xe); + $x0=$xe; + } + else { + // Height larger than width + $diff = $x0-$xe; + $y0 = $diff+$this->rect->y; + $x0 = $xe; + $x1 = $this->rect->x; + while( $y1 <= $ye ) { + $aImg->Line($x0,$y0,$x1,$y1); + $y1 += $this->linespacing; + $y0 += $this->linespacing; + } + + $diff = $y1-$ye; + $y1 = $ye; + $x1 = $diff + $this->rect->x; + } + + while( $y0 <= $ye ) { + $aImg->Line($x0,$y0,$x1,$y1); + $y0 += $this->linespacing; + $x1 += $this->linespacing; + } + } +} + +//===================================================================== +// Class RectPatternLDiag +// Implements left diagonal pattern +//===================================================================== +class RectPatternLDiag extends RectPattern { + + function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) { + $this->linespacing = $aLineSpacing; + parent::__construct($aColor,$aWeight); + } + + function DoPattern($aImg) { + // -------------------- + // |\ \ \ \ \ | + // | \ \ \ \ \| + // | \ \ \ \ | + // |------------------| + $xe = $this->rect->xe; + $ye = $this->rect->ye; + $x0 = $this->rect->x + round($this->linespacing/2); + $y0 = $this->rect->ye; + $x1 = $this->rect->x; + $y1 = $this->rect->ye - round($this->linespacing/2); + + while($x0<=$xe && $y1>=$this->rect->y) { + $aImg->Line($x0,$y0,$x1,$y1); + $x0 += $this->linespacing; + $y1 -= $this->linespacing; + } + if( $xe-$x1 > $ye-$this->rect->y ) { + // Width larger than height + $x1 = $this->rect->x + ($this->rect->y-$y1); + $y0=$ye; $y1=$this->rect->y; + while( $x0 <= $xe ) { + $aImg->Line($x0,$y0,$x1,$y1); + $x0 += $this->linespacing; + $x1 += $this->linespacing; + } + + $y0=$this->rect->ye - ($x0-$xe); + $x0=$xe; + } + else { + // Height larger than width + $diff = $x0-$xe; + $y0 = $ye-$diff; + $x0 = $xe; + while( $y1 >= $this->rect->y ) { + $aImg->Line($x0,$y0,$x1,$y1); + $y0 -= $this->linespacing; + $y1 -= $this->linespacing; + } + $diff = $this->rect->y - $y1; + $x1 = $this->rect->x + $diff; + $y1 = $this->rect->y; + } + while( $y0 >= $this->rect->y ) { + $aImg->Line($x0,$y0,$x1,$y1); + $y0 -= $this->linespacing; + $x1 += $this->linespacing; + } + } +} + +//===================================================================== +// Class RectPattern3DPlane +// Implements "3D" plane pattern +//===================================================================== +class RectPattern3DPlane extends RectPattern { + private $alpha=50; // Parameter that specifies the distance + // to "simulated" horizon in pixel from the + // top of the band. Specifies how fast the lines + // converge. + + function __construct($aColor="black",$aWeight=1) { + parent::__construct($aColor,$aWeight); + $this->SetDensity(10); // Slightly larger default + } + + function SetHorizon($aHorizon) { + $this->alpha=$aHorizon; + } + + function DoPattern($aImg) { + // "Fake" a nice 3D grid-effect. + $x0 = $this->rect->x + $this->rect->w/2; + $y0 = $this->rect->y; + $x1 = $x0; + $y1 = $this->rect->ye; + $x0_right = $x0; + $x1_right = $x1; + + // BTW "apa" means monkey in Swedish but is really a shortform for + // "alpha+a" which was the labels I used on paper when I derived the + // geometric to get the 3D perspective right. + // $apa is the height of the bounding rectangle plus the distance to the + // artifical horizon (alpha) + $apa = $this->rect->h + $this->alpha; + + // Three cases and three loops + // 1) The endpoint of the line ends on the bottom line + // 2) The endpoint ends on the side + // 3) Horizontal lines + + // Endpoint falls on bottom line + $middle=$this->rect->x + $this->rect->w/2; + $dist=$this->linespacing; + $factor=$this->alpha /($apa); + while($x1>$this->rect->x) { + $aImg->Line($x0,$y0,$x1,$y1); + $aImg->Line($x0_right,$y0,$x1_right,$y1); + $x1 = $middle - $dist; + $x0 = $middle - $dist * $factor; + $x1_right = $middle + $dist; + $x0_right = $middle + $dist * $factor; + $dist += $this->linespacing; + } + + // Endpoint falls on sides + $dist -= $this->linespacing; + $d=$this->rect->w/2; + $c = $apa - $d*$apa/$dist; + while( $x0>$this->rect->x ) { + $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c); + $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c); + $dist += $this->linespacing; + $x0 = $middle - $dist * $factor; + $x1 = $middle - $dist; + $x0_right = $middle + $dist * $factor; + $c = $apa - $d*$apa/$dist; + } + + // Horizontal lines + // They need some serious consideration since they are a function + // of perspective depth (alpha) and density (linespacing) + $x0=$this->rect->x; + $x1=$this->rect->xe; + $y=$this->rect->ye; + + // The first line is drawn directly. Makes the loop below slightly + // more readable. + $aImg->Line($x0,$y,$x1,$y); + $hls = $this->linespacing; + + // A correction factor for vertical "brick" line spacing to account for + // a) the difference in number of pixels hor vs vert + // b) visual apperance to make the first layer of "bricks" look more + // square. + $vls = $this->linespacing*0.6; + + $ds = $hls*($apa-$vls)/$apa; + // Get the slope for the "perspective line" going from bottom right + // corner to top left corner of the "first" brick. + + // Uncomment the following lines if you want to get a visual understanding + // of what this helpline does. BTW this mimics the way you would get the + // perspective right when drawing on paper. + /* + $x0 = $middle; + $y0 = $this->rect->ye; + $len=floor(($this->rect->ye-$this->rect->y)/$vls); + $x1 = $middle+round($len*$ds); + $y1 = $this->rect->ye-$len*$vls; + $aImg->PushColor("red"); + $aImg->Line($x0,$y0,$x1,$y1); + $aImg->PopColor(); + */ + + $y -= $vls; + $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds)); + $dist = $hls; + while( $y>$this->rect->y ) { + $aImg->Line($this->rect->x,$y,$this->rect->xe,$y); + $adj = $k*$dist/(1+$dist*$k/$apa); + if( $adj < 2 ) $adj=1; + $y = $this->rect->ye - round($adj); + $dist += $hls; + } + } +} + +//===================================================================== +// Class RectPatternCross +// Vert/Hor crosses +//===================================================================== +class RectPatternCross extends RectPattern { + private $vert=null; + private $hor=null; + function __construct($aColor="black",$aWeight=1) { + parent::__construct($aColor,$aWeight); + $this->vert = new RectPatternVert($aColor,$aWeight); + $this->hor = new RectPatternHor($aColor,$aWeight); + } + + function SetOrder($aDepth) { + $this->vert->SetOrder($aDepth); + $this->hor->SetOrder($aDepth); + } + + function SetPos($aRect) { + parent::SetPos($aRect); + $this->vert->SetPos($aRect); + $this->hor->SetPos($aRect); + } + + function SetDensity($aDens) { + $this->vert->SetDensity($aDens); + $this->hor->SetDensity($aDens); + } + + function DoPattern($aImg) { + $this->vert->DoPattern($aImg); + $this->hor->DoPattern($aImg); + } +} + +//===================================================================== +// Class RectPatternDiagCross +// Vert/Hor crosses +//===================================================================== + +class RectPatternDiagCross extends RectPattern { + private $left=null; + private $right=null; + function __construct($aColor="black",$aWeight=1) { + parent::__construct($aColor,$aWeight); + $this->right = new RectPatternRDiag($aColor,$aWeight); + $this->left = new RectPatternLDiag($aColor,$aWeight); + } + + function SetOrder($aDepth) { + $this->left->SetOrder($aDepth); + $this->right->SetOrder($aDepth); + } + + function SetPos($aRect) { + parent::SetPos($aRect); + $this->left->SetPos($aRect); + $this->right->SetPos($aRect); + } + + function SetDensity($aDens) { + $this->left->SetDensity($aDens); + $this->right->SetDensity($aDens); + } + + function DoPattern($aImg) { + $this->left->DoPattern($aImg); + $this->right->DoPattern($aImg); + } + +} + +//===================================================================== +// Class RectPatternFactory +// Factory class for rectangular pattern +//===================================================================== +class RectPatternFactory { + function __construct() { + // Empty + } + function Create($aPattern,$aColor,$aWeight=1) { + switch($aPattern) { + case BAND_RDIAG: + $obj = new RectPatternRDiag($aColor,$aWeight); + break; + case BAND_LDIAG: + $obj = new RectPatternLDiag($aColor,$aWeight); + break; + case BAND_SOLID: + $obj = new RectPatternSolid($aColor,$aWeight); + break; + case BAND_VLINE: + $obj = new RectPatternVert($aColor,$aWeight); + break; + case BAND_HLINE: + $obj = new RectPatternHor($aColor,$aWeight); + break; + case BAND_3DPLANE: + $obj = new RectPattern3DPlane($aColor,$aWeight); + break; + case BAND_HVCROSS: + $obj = new RectPatternCross($aColor,$aWeight); + break; + case BAND_DIAGCROSS: + $obj = new RectPatternDiagCross($aColor,$aWeight); + break; + default: + JpGraphError::RaiseL(16003,$aPattern); + //(" Unknown pattern specification ($aPattern)"); + } + return $obj; + } +} + + +//===================================================================== +// Class PlotBand +// Factory class which is used by the client. +// It is responsible for factoring the corresponding pattern +// concrete class. +//===================================================================== +class PlotBand { + public $depth; // Determine if band should be over or under the plots + private $prect=null; + private $dir, $min, $max; + + function __construct($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) { + $f = new RectPatternFactory(); + $this->prect = $f->Create($aPattern,$aColor,$aWeight); + if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) ) + JpGraphError::RaiseL(16004); + //('Min value for plotband is larger than specified max value. Please correct.'); + $this->dir = $aDir; + $this->min = $aMin; + $this->max = $aMax; + $this->depth=$aDepth; + } + + // Set position. aRect contains absolute image coordinates + function SetPos($aRect) { + assert( $this->prect != null ) ; + $this->prect->SetPos($aRect); + } + + function ShowFrame($aFlag=true) { + $this->prect->ShowFrame($aFlag); + } + + // Set z-order. In front of pplot or in the back + function SetOrder($aDepth) { + $this->depth=$aDepth; + } + + function SetDensity($aDens) { + $this->prect->SetDensity($aDens); + } + + function GetDir() { + return $this->dir; + } + + function GetMin() { + return $this->min; + } + + function GetMax() { + return $this->max; + } + + function PreStrokeAdjust($aGraph) { + // Nothing to do + } + + // Display band + function Stroke($aImg,$aXScale,$aYScale) { + assert( $this->prect != null ) ; + if( $this->dir == HORIZONTAL ) { + if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal(); + if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal(); + + // Only draw the bar if it actually appears in the range + if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) { + + // Trucate to limit of axis + $this->min = max($this->min, $aYScale->GetMinVal()); + $this->max = min($this->max, $aYScale->GetMaxVal()); + + $x=$aXScale->scale_abs[0]; + $y=$aYScale->Translate($this->max); + $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1; + $height=abs($y-$aYScale->Translate($this->min))+1; + $this->prect->SetPos(new Rectangle($x,$y,$width,$height)); + $this->prect->Stroke($aImg); + } + } + else { // VERTICAL + if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal(); + if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal(); + + // Only draw the bar if it actually appears in the range + if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) { + + // Trucate to limit of axis + $this->min = max($this->min, $aXScale->GetMinVal()); + $this->max = min($this->max, $aXScale->GetMaxVal()); + + $y=$aYScale->scale_abs[1]; + $x=$aXScale->Translate($this->min); + $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]); + $width=abs($x-$aXScale->Translate($this->max)); + $this->prect->SetPos(new Rectangle($x,$y,$width,$height)); + $this->prect->Stroke($aImg); + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_plotline.php b/web/public_php/admin/jpgraph/jpgraph_plotline.php new file mode 100644 index 000000000..4ee0f5648 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_plotline.php @@ -0,0 +1,142 @@ +direction = $aDir; + $this->color=$aColor; + $this->weight=$aWeight; + $this->scaleposition=$aPos; + } + + function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') { + $this->legend = $aLegend; + $this->legendcsimtarget = $aCSIM; + $this->legendcsimwintarget = $aCSIMWinTarget; + $this->legendcsimalt = $aCSIMAlt; + } + + function HideLegend($f=true) { + $this->hidelegend = $f; + } + + function SetPosition($aScalePosition) { + $this->scaleposition=$aScalePosition; + } + + function SetDirection($aDir) { + $this->direction = $aDir; + } + + function SetColor($aColor) { + $this->color=$aColor; + } + + function SetWeight($aWeight) { + $this->weight=$aWeight; + } + + function SetLineStyle($aStyle) { + $this->iLineStyle = $aStyle; + } + + function GetCSIMAreas() { + return ''; + } + + //--------------- + // PRIVATE METHODS + + function DoLegend($graph) { + if( !$this->hidelegend ) $this->Legend($graph); + } + + // Framework function the chance for each plot class to set a legend + function Legend($aGraph) { + if( $this->legend != '' ) { + $dummyPlotMark = new PlotMark(); + $lineStyle = 1; + $aGraph->legend->Add($this->legend,$this->color,$dummyPlotMark,$lineStyle, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } + + function PreStrokeAdjust($aGraph) { + // Nothing to do + } + + // Called by framework to allow the object to draw + // optional information in the margin area + function StrokeMargin($aImg) { + // Nothing to do + } + + // Framework function to allow the object to adjust the scale + function PrescaleSetup($aGraph) { + // Nothing to do + } + + function Min() { + return array(null,null); + } + + function Max() { + return array(null,null); + } + + function _Stroke($aImg,$aMinX,$aMinY,$aMaxX,$aMaxY,$aXPos,$aYPos) { + $aImg->SetColor($this->color); + $aImg->SetLineWeight($this->weight); + $oldStyle = $aImg->SetLineStyle($this->iLineStyle); + if( $this->direction == VERTICAL ) { + $ymin_abs = $aMinY; + $ymax_abs = $aMaxY; + $xpos_abs = $aXPos; + $aImg->StyleLine($xpos_abs, $ymin_abs, $xpos_abs, $ymax_abs); + } + elseif( $this->direction == HORIZONTAL ) { + $xmin_abs = $aMinX; + $xmax_abs = $aMaxX; + $ypos_abs = $aYPos; + $aImg->StyleLine($xmin_abs, $ypos_abs, $xmax_abs, $ypos_abs); + } + else { + JpGraphError::RaiseL(25125);//(" Illegal direction for static line"); + } + $aImg->SetLineStyle($oldStyle); + } + + function Stroke($aImg,$aXScale,$aYScale) { + $this->_Stroke($aImg, + $aImg->left_margin, + $aYScale->Translate($aYScale->GetMinVal()), + $aImg->width-$aImg->right_margin, + $aYScale->Translate($aYScale->GetMaxVal()), + $aXScale->Translate($this->scaleposition), + $aYScale->Translate($this->scaleposition) + ); + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_plotmark.inc b/web/public_php/admin/jpgraph/jpgraph_plotmark.inc deleted file mode 100644 index c555aab6e..000000000 --- a/web/public_php/admin/jpgraph/jpgraph_plotmark.inc +++ /dev/null @@ -1,482 +0,0 @@ -an[$aMark]; - if( is_string($aIdx) ) { - if( !in_array($aIdx,$this->colors) ) { - JpGraphError::RaiseL(23001,$this->name,$aIdx); //('This marker "'.($this->name).'" does not exist in color: '.$aIdx); - } - $idx = $this->index[$aIdx]; - } - elseif( !is_integer($aIdx) || - (is_integer($aIdx) && $aIdx > $this->maxidx ) ) { - JpGraphError::RaiseL(23002,$this->name); -//('Mark color index too large for marker "'.($this->name).'"'); - } - else - $idx = $aIdx ; - return Image::CreateFromString(base64_decode($this->{$n}[$idx][1])); - } - function GetAnchor() { - return array($this->anchor_x,$this->anchor_y); - } -} - - -// Keep a global flag cache to reduce memory usage -$_gFlagCache=array( - 1 => null, - 2 => null, - 3 => null, - 4 => null, -); -// Only supposed to b called as statics -class FlagCache { - function GetFlagImgByName($aSize,$aName) { - global $_gFlagCache; - require_once('jpgraph_flags.php'); - if( $_gFlagCache[$aSize] === null ) { - $_gFlagCache[$aSize] = new FlagImages($aSize); - } - $f =& $_gFlagCache[$aSize]; - $idx = $f->GetIdxByName($aName,$aFullName); - return $f->GetImgByIdx($idx); - } -} - -//=================================================== -// CLASS PlotMark -// Description: Handles the plot marks in graphs -//=================================================== -class PlotMark { - var $title, $show=true; - var $type,$weight=1; - var $color="black", $width=4, $fill_color="blue"; - var $yvalue,$xvalue='',$csimtarget,$csimalt,$csimareas; - var $iFormatCallback=""; - var $iFormatCallback2=""; - var $markimg='',$iScale=1.0; - var $oldfilename='',$iFileName=''; - var $imgdata_balls = null; - var $imgdata_diamonds = null; - var $imgdata_squares = null; - var $imgdata_bevels = null; - var $imgdata_stars = null; - var $imgdata_pushpins = null; - -//-------------- -// CONSTRUCTOR - function __construct() { - $this->title = new Text(); - $this->title->Hide(); - $this->csimareas = ''; - $this->csimalt = ''; - $this->type=-1; - } -//--------------- -// PUBLIC METHODS - function SetType($aType,$aFileName='',$aScale=1.0) { - $this->type = $aType; - if( $aType == MARK_IMG && $aFileName=='' ) { - JpGraphError::RaiseL(23003);//('A filename must be specified if you set the mark type to MARK_IMG.'); - } - $this->iFileName = $aFileName; - $this->iScale = $aScale; - } - - function SetCallback($aFunc) { - $this->iFormatCallback = $aFunc; - } - - function SetCallbackYX($aFunc) { - $this->iFormatCallback2 = $aFunc; - } - - function GetType() { - return $this->type; - } - - function SetColor($aColor) { - $this->color=$aColor; - } - - function SetFillColor($aFillColor) { - $this->fill_color = $aFillColor; - } - - function SetWeight($aWeight) { - $this->weight = $aWeight; - } - - // Synonym for SetWidth() - function SetSize($aWidth) { - $this->width=$aWidth; - } - - function SetWidth($aWidth) { - $this->width=$aWidth; - } - - function SetDefaultWidth() { - switch( $this->type ) { - case MARK_CIRCLE: - case MARK_FILLEDCIRCLE: - $this->width=4; - break; - default: - $this->width=7; - } - } - - function GetWidth() { - return $this->width; - } - - function Hide($aHide=true) { - $this->show = !$aHide; - } - - function Show($aShow=true) { - $this->show = $aShow; - } - - function SetCSIMAltVal($aY,$aX='') { - $this->yvalue=$aY; - $this->xvalue=$aX; - } - - function SetCSIMTarget($aTarget) { - $this->csimtarget=$aTarget; - } - - function SetCSIMAlt($aAlt) { - $this->csimalt=$aAlt; - } - - function GetCSIMAreas(){ - return $this->csimareas; - } - - function AddCSIMPoly($aPts) { - $coords = round($aPts[0]).", ".round($aPts[1]); - $n = count($aPts)/2; - for( $i=1; $i < $n; ++$i){ - $coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]); - } - $this->csimareas=""; - if( !empty($this->csimtarget) ) { - $this->csimareas .= "csimtarget."\""; - if( !empty($this->csimalt) ) { - $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); - $this->csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"$tmp\" />\n"; - } - } - - function AddCSIMCircle($x,$y,$r) { - $x = round($x); $y=round($y); $r=round($r); - $this->csimareas=""; - if( !empty($this->csimtarget) ) { - $this->csimareas .= "csimtarget."\""; - if( !empty($this->csimalt) ) { - $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); - $this->csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"$tmp\" />\n"; - } - } - - function Stroke(&$img,$x,$y) { - if( !$this->show ) return; - - if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) { - - if( $this->iFormatCallback != '' ) { - $f = $this->iFormatCallback; - list($width,$color,$fcolor) = call_user_func($f,$this->yvalue); - $filename = $this->iFileName; - $imgscale = $this->iScale; - } - else { - $f = $this->iFormatCallback2; - list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue); - if( $filename=="" ) $filename = $this->iFileName; - if( $imgscale=="" ) $imgscale = $this->iScale; - } - - if( $width=="" ) $width = $this->width; - if( $color=="" ) $color = $this->color; - if( $fcolor=="" ) $fcolor = $this->fill_color; - - } - else { - $fcolor = $this->fill_color; - $color = $this->color; - $width = $this->width; - $filename = $this->iFileName; - $imgscale = $this->iScale; - } - - if( $this->type == MARK_IMG || - ($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) || - $this->type >= MARK_IMG_PUSHPIN ) { - - // Note: For the builtin images we use the "filename" parameter - // to denote the color - $anchor_x = 0.5; - $anchor_y = 0.5; - switch( $this->type ) { - case MARK_FLAG1: - case MARK_FLAG2: - case MARK_FLAG3: - case MARK_FLAG4: - $this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename); - break; - - case MARK_IMG : - // Load an image and use that as a marker - // Small optimization, if we have already read an image don't - // waste time reading it again. - if( $this->markimg == '' || !($this->oldfilename === $filename) ) { - $this->markimg = Graph::LoadBkgImage('',$filename); - $this->oldfilename = $filename ; - } - break; - - case MARK_IMG_PUSHPIN: - case MARK_IMG_SPUSHPIN: - case MARK_IMG_LPUSHPIN: - if( $this->imgdata_pushpins == null ) { - require_once 'imgdata_pushpins.inc'; - $this->imgdata_pushpins = new ImgData_PushPins(); - } - $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename); - list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor(); - break; - - case MARK_IMG_SQUARE: - if( $this->imgdata_squares == null ) { - require_once 'imgdata_squares.inc'; - $this->imgdata_squares = new ImgData_Squares(); - } - $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename); - list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor(); - break; - - case MARK_IMG_STAR: - if( $this->imgdata_stars == null ) { - require_once 'imgdata_stars.inc'; - $this->imgdata_stars = new ImgData_Stars(); - } - $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename); - list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor(); - break; - - case MARK_IMG_BEVEL: - if( $this->imgdata_bevels == null ) { - require_once 'imgdata_bevels.inc'; - $this->imgdata_bevels = new ImgData_Bevels(); - } - $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename); - list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor(); - break; - - case MARK_IMG_DIAMOND: - if( $this->imgdata_diamonds == null ) { - require_once 'imgdata_diamonds.inc'; - $this->imgdata_diamonds = new ImgData_Diamonds(); - } - $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename); - list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor(); - break; - - case MARK_IMG_BALL: - case MARK_IMG_SBALL: - case MARK_IMG_MBALL: - case MARK_IMG_LBALL: - if( $this->imgdata_balls == null ) { - require_once 'imgdata_balls.inc'; - $this->imgdata_balls = new ImgData_Balls(); - } - $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename); - list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor(); - break; - } - - $w = $img->GetWidth($this->markimg); - $h = $img->GetHeight($this->markimg); - - $dw = round($imgscale * $w ); - $dh = round($imgscale * $h ); - - // Do potential rotation - list($x,$y) = $img->Rotate($x,$y); - - $dx = round($x-$dw*$anchor_x); - $dy = round($y-$dh*$anchor_y); - - $this->width = max($dx,$dy); - - $img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h); - if( !empty($this->csimtarget) ) { - $this->csimareas = "csimtarget."\""; - if( !empty($this->csimalt) ) { - $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); - $this->csimareas .= " title=\"$tmp\""; - } - $this->csimareas .= " alt=\"$tmp\" />\n"; - } - - // Stroke title - $this->title->Align("center","top"); - $this->title->Stroke($img,$x,$y+round($dh/2)); - return; - } - - $weight = $this->weight; - $dx=round($width/2,0); - $dy=round($width/2,0); - $pts=0; - - switch( $this->type ) { - case MARK_SQUARE: - $c[]=$x-$dx;$c[]=$y-$dy; - $c[]=$x+$dx;$c[]=$y-$dy; - $c[]=$x+$dx;$c[]=$y+$dy; - $c[]=$x-$dx;$c[]=$y+$dy; - $c[]=$x-$dx;$c[]=$y-$dy; - $pts=5; - break; - case MARK_UTRIANGLE: - ++$dx;++$dy; - $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx - $c[]=$x;$c[]=$y-0.87*$dy; - $c[]=$x+$dx;$c[]=$y+0.87*$dy; - $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx - $pts=4; - break; - case MARK_DTRIANGLE: - ++$dx;++$dy; - $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx - $c[]=$x-$dx;$c[]=$y-0.87*$dy; - $c[]=$x+$dx;$c[]=$y-0.87*$dy; - $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx - $pts=4; - break; - case MARK_DIAMOND: - $c[]=$x;$c[]=$y+$dy; - $c[]=$x-$dx;$c[]=$y; - $c[]=$x;$c[]=$y-$dy; - $c[]=$x+$dx;$c[]=$y; - $c[]=$x;$c[]=$y+$dy; - $pts=5; - break; - case MARK_LEFTTRIANGLE: - $c[]=$x;$c[]=$y; - $c[]=$x;$c[]=$y+2*$dy; - $c[]=$x+$dx*2;$c[]=$y; - $c[]=$x;$c[]=$y; - $pts=4; - break; - case MARK_RIGHTTRIANGLE: - $c[]=$x-$dx*2;$c[]=$y; - $c[]=$x;$c[]=$y+2*$dy; - $c[]=$x;$c[]=$y; - $c[]=$x-$dx*2;$c[]=$y; - $pts=4; - break; - case MARK_FLASH: - $dy *= 2; - $c[]=$x+$dx/2; $c[]=$y-$dy; - $c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$dy; - $c[]=$x+$dx/2; $c[]=$y+$dy*1.3-$dy; - $c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy; - $img->SetLineWeight($weight); - $img->SetColor($color); - $img->Polygon($c); - $img->SetLineWeight(1); - $this->AddCSIMPoly($c); - break; - } - - if( $pts>0 ) { - $this->AddCSIMPoly($c); - $img->SetLineWeight($weight); - $img->SetColor($fcolor); - $img->FilledPolygon($c); - $img->SetColor($color); - $img->Polygon($c); - $img->SetLineWeight(1); - } - elseif( $this->type==MARK_CIRCLE ) { - $img->SetColor($color); - $img->Circle($x,$y,$width); - $this->AddCSIMCircle($x,$y,$width); - } - elseif( $this->type==MARK_FILLEDCIRCLE ) { - $img->SetColor($fcolor); - $img->FilledCircle($x,$y,$width); - $img->SetColor($color); - $img->Circle($x,$y,$width); - $this->AddCSIMCircle($x,$y,$width); - } - elseif( $this->type==MARK_CROSS ) { - // Oversize by a pixel to match the X - $img->SetColor($color); - $img->SetLineWeight($weight); - $img->Line($x,$y+$dy+1,$x,$y-$dy-1); - $img->Line($x-$dx-1,$y,$x+$dx+1,$y); - $this->AddCSIMCircle($x,$y,$dx); - } - elseif( $this->type==MARK_X ) { - $img->SetColor($color); - $img->SetLineWeight($weight); - $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy); - $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy); - $this->AddCSIMCircle($x,$y,$dx+$dy); - } - elseif( $this->type==MARK_STAR ) { - $img->SetColor($color); - $img->SetLineWeight($weight); - $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy); - $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy); - // Oversize by a pixel to match the X - $img->Line($x,$y+$dy+1,$x,$y-$dy-1); - $img->Line($x-$dx-1,$y,$x+$dx+1,$y); - $this->AddCSIMCircle($x,$y,$dx+$dy); - } - - // Stroke title - $this->title->Align("center","center"); - $this->title->Stroke($img,$x,$y); - } -} // Class - - -?> diff --git a/web/public_php/admin/jpgraph/jpgraph_plotmark.inc.php b/web/public_php/admin/jpgraph/jpgraph_plotmark.inc.php new file mode 100644 index 000000000..29c4d0325 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_plotmark.inc.php @@ -0,0 +1,504 @@ +title = new Text(); + $this->title->Hide(); + $this->csimareas = ''; + $this->type=-1; + } + //--------------- + // PUBLIC METHODS + function SetType($aType,$aFileName='',$aScale=1.0) { + $this->type = $aType; + if( $aType == MARK_IMG && $aFileName=='' ) { + JpGraphError::RaiseL(23003);//('A filename must be specified if you set the mark type to MARK_IMG.'); + } + $this->iFileName = $aFileName; + $this->iScale = $aScale; + } + + function SetCallback($aFunc) { + $this->iFormatCallback = $aFunc; + } + + function SetCallbackYX($aFunc) { + $this->iFormatCallback2 = $aFunc; + } + + function GetType() { + return $this->type; + } + + function SetColor($aColor) { + $this->color=$aColor; + } + + function SetFillColor($aFillColor) { + $this->fill_color = $aFillColor; + } + + function SetWeight($aWeight) { + $this->weight = $aWeight; + } + + // Synonym for SetWidth() + function SetSize($aWidth) { + $this->width=$aWidth; + } + + function SetWidth($aWidth) { + $this->width=$aWidth; + } + + function SetDefaultWidth() { + switch( $this->type ) { + case MARK_CIRCLE: + case MARK_FILLEDCIRCLE: + $this->width=4; + break; + default: + $this->width=7; + } + } + + function GetWidth() { + return $this->width; + } + + function Hide($aHide=true) { + $this->show = !$aHide; + } + + function Show($aShow=true) { + $this->show = $aShow; + } + + function SetCSIMAltVal($aY,$aX='') { + $this->yvalue=$aY; + $this->xvalue=$aX; + } + + function SetCSIMTarget($aTarget,$aWinTarget='') { + $this->csimtarget=$aTarget; + $this->csimwintarget=$aWinTarget; + } + + function SetCSIMAlt($aAlt) { + $this->csimalt=$aAlt; + } + + function GetCSIMAreas(){ + return $this->csimareas; + } + + function AddCSIMPoly($aPts) { + $coords = round($aPts[0]).", ".round($aPts[1]); + $n = count($aPts)/2; + for( $i=1; $i < $n; ++$i){ + $coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]); + } + $this->csimareas=""; + if( !empty($this->csimtarget) ) { + $this->csimareas .= "csimtarget)."\""; + + if( !empty($this->csimwintarget) ) { + $this->csimareas .= " target=\"".$this->csimwintarget."\" "; + } + + if( !empty($this->csimalt) ) { + $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\""; + } + $this->csimareas .= " />\n"; + } + } + + function AddCSIMCircle($x,$y,$r) { + $x = round($x); $y=round($y); $r=round($r); + $this->csimareas=""; + if( !empty($this->csimtarget) ) { + $this->csimareas .= "csimtarget)."\""; + + if( !empty($this->csimwintarget) ) { + $this->csimareas .= " target=\"".$this->csimwintarget."\" "; + } + + if( !empty($this->csimalt) ) { + $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + } + + function Stroke($img,$x,$y) { + if( !$this->show ) return; + + if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) { + + if( $this->iFormatCallback != '' ) { + $f = $this->iFormatCallback; + list($width,$color,$fcolor) = call_user_func($f,$this->yvalue); + $filename = $this->iFileName; + $imgscale = $this->iScale; + } + else { + $f = $this->iFormatCallback2; + list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue); + if( $filename=="" ) $filename = $this->iFileName; + if( $imgscale=="" ) $imgscale = $this->iScale; + } + + if( $width=="" ) $width = $this->width; + if( $color=="" ) $color = $this->color; + if( $fcolor=="" ) $fcolor = $this->fill_color; + + } + else { + $fcolor = $this->fill_color; + $color = $this->color; + $width = $this->width; + $filename = $this->iFileName; + $imgscale = $this->iScale; + } + + if( $this->type == MARK_IMG || + ($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) || + $this->type >= MARK_IMG_PUSHPIN ) { + + // Note: For the builtin images we use the "filename" parameter + // to denote the color + $anchor_x = 0.5; + $anchor_y = 0.5; + switch( $this->type ) { + case MARK_FLAG1: + case MARK_FLAG2: + case MARK_FLAG3: + case MARK_FLAG4: + $this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename); + break; + + case MARK_IMG : + // Load an image and use that as a marker + // Small optimization, if we have already read an image don't + // waste time reading it again. + if( $this->markimg == '' || !($this->oldfilename === $filename) ) { + $this->markimg = Graph::LoadBkgImage('',$filename); + $this->oldfilename = $filename ; + } + break; + + case MARK_IMG_PUSHPIN: + case MARK_IMG_SPUSHPIN: + case MARK_IMG_LPUSHPIN: + if( $this->imgdata_pushpins == null ) { + require_once 'imgdata_pushpins.inc.php'; + $this->imgdata_pushpins = new ImgData_PushPins(); + } + $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename); + list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor(); + break; + + case MARK_IMG_SQUARE: + if( $this->imgdata_squares == null ) { + require_once 'imgdata_squares.inc.php'; + $this->imgdata_squares = new ImgData_Squares(); + } + $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename); + list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor(); + break; + + case MARK_IMG_STAR: + if( $this->imgdata_stars == null ) { + require_once 'imgdata_stars.inc.php'; + $this->imgdata_stars = new ImgData_Stars(); + } + $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename); + list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor(); + break; + + case MARK_IMG_BEVEL: + if( $this->imgdata_bevels == null ) { + require_once 'imgdata_bevels.inc.php'; + $this->imgdata_bevels = new ImgData_Bevels(); + } + $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename); + list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor(); + break; + + case MARK_IMG_DIAMOND: + if( $this->imgdata_diamonds == null ) { + require_once 'imgdata_diamonds.inc.php'; + $this->imgdata_diamonds = new ImgData_Diamonds(); + } + $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename); + list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor(); + break; + + case MARK_IMG_BALL: + case MARK_IMG_SBALL: + case MARK_IMG_MBALL: + case MARK_IMG_LBALL: + if( $this->imgdata_balls == null ) { + require_once 'imgdata_balls.inc.php'; + $this->imgdata_balls = new ImgData_Balls(); + } + $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename); + list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor(); + break; + } + + $w = $img->GetWidth($this->markimg); + $h = $img->GetHeight($this->markimg); + + $dw = round($imgscale * $w ); + $dh = round($imgscale * $h ); + + // Do potential rotation + list($x,$y) = $img->Rotate($x,$y); + + $dx = round($x-$dw*$anchor_x); + $dy = round($y-$dh*$anchor_y); + + $this->width = max($dx,$dy); + + $img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h); + if( !empty($this->csimtarget) ) { + $this->csimareas = "csimtarget)."\""; + + if( !empty($this->csimwintarget) ) { + $this->csimareas .= " target=\"".$this->csimwintarget."\" "; + } + + if( !empty($this->csimalt) ) { + $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); + $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; + } + $this->csimareas .= " />\n"; + } + + // Stroke title + $this->title->Align("center","top"); + $this->title->Stroke($img,$x,$y+round($dh/2)); + return; + } + + $weight = $this->weight; + $dx=round($width/2,0); + $dy=round($width/2,0); + $pts=0; + + switch( $this->type ) { + case MARK_SQUARE: + $c[]=$x-$dx;$c[]=$y-$dy; + $c[]=$x+$dx;$c[]=$y-$dy; + $c[]=$x+$dx;$c[]=$y+$dy; + $c[]=$x-$dx;$c[]=$y+$dy; + $c[]=$x-$dx;$c[]=$y-$dy; + $pts=5; + break; + case MARK_UTRIANGLE: + ++$dx;++$dy; + $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx + $c[]=$x;$c[]=$y-0.87*$dy; + $c[]=$x+$dx;$c[]=$y+0.87*$dy; + $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx + $pts=4; + break; + case MARK_DTRIANGLE: + ++$dx;++$dy; + $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx + $c[]=$x-$dx;$c[]=$y-0.87*$dy; + $c[]=$x+$dx;$c[]=$y-0.87*$dy; + $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx + $pts=4; + break; + case MARK_DIAMOND: + $c[]=$x;$c[]=$y+$dy; + $c[]=$x-$dx;$c[]=$y; + $c[]=$x;$c[]=$y-$dy; + $c[]=$x+$dx;$c[]=$y; + $c[]=$x;$c[]=$y+$dy; + $pts=5; + break; + case MARK_LEFTTRIANGLE: + $c[]=$x;$c[]=$y; + $c[]=$x;$c[]=$y+2*$dy; + $c[]=$x+$dx*2;$c[]=$y; + $c[]=$x;$c[]=$y; + $pts=4; + break; + case MARK_RIGHTTRIANGLE: + $c[]=$x-$dx*2;$c[]=$y; + $c[]=$x;$c[]=$y+2*$dy; + $c[]=$x;$c[]=$y; + $c[]=$x-$dx*2;$c[]=$y; + $pts=4; + break; + case MARK_FLASH: + $dy *= 2; + $c[]=$x+$dx/2; $c[]=$y-$dy; + $c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$dy; + $c[]=$x+$dx/2; $c[]=$y+$dy*1.3-$dy; + $c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy; + $img->SetLineWeight($weight); + $img->SetColor($color); + $img->Polygon($c); + $img->SetLineWeight(1); + $this->AddCSIMPoly($c); + break; + } + + if( $pts>0 ) { + $this->AddCSIMPoly($c); + $img->SetLineWeight($weight); + $img->SetColor($fcolor); + $img->FilledPolygon($c); + $img->SetColor($color); + $img->Polygon($c); + $img->SetLineWeight(1); + } + elseif( $this->type==MARK_CIRCLE ) { + $img->SetColor($color); + $img->Circle($x,$y,$width); + $this->AddCSIMCircle($x,$y,$width); + } + elseif( $this->type==MARK_FILLEDCIRCLE ) { + $img->SetColor($fcolor); + $img->FilledCircle($x,$y,$width); + $img->SetColor($color); + $img->Circle($x,$y,$width); + $this->AddCSIMCircle($x,$y,$width); + } + elseif( $this->type==MARK_CROSS ) { + // Oversize by a pixel to match the X + $img->SetColor($color); + $img->SetLineWeight($weight); + $img->Line($x,$y+$dy+1,$x,$y-$dy-1); + $img->Line($x-$dx-1,$y,$x+$dx+1,$y); + $this->AddCSIMCircle($x,$y,$dx); + } + elseif( $this->type==MARK_X ) { + $img->SetColor($color); + $img->SetLineWeight($weight); + $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy); + $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy); + $this->AddCSIMCircle($x,$y,$dx+$dy); + } + elseif( $this->type==MARK_STAR ) { + $img->SetColor($color); + $img->SetLineWeight($weight); + $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy); + $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy); + // Oversize by a pixel to match the X + $img->Line($x,$y+$dy+1,$x,$y-$dy-1); + $img->Line($x-$dx-1,$y,$x+$dx+1,$y); + $this->AddCSIMCircle($x,$y,$dx+$dy); + } + + // Stroke title + $this->title->Align("center","center"); + $this->title->Stroke($img,$x,$y); + } +} // Class + + + +//======================================================================== +// CLASS ImgData +// Description: Base class for all image data classes that contains the +// real image data. +//======================================================================== +class ImgData { + protected $name = ''; // Each subclass gives a name + protected $an = array(); // Data array names + protected $colors = array(); // Available colors + protected $index = array(); // Index for colors + protected $maxidx = 0 ; // Max color index + protected $anchor_x=0.5, $anchor_y=0.5 ; // Where is the center of the image + + function __construct() { + // Empty + } + + // Create a GD image from the data and return a GD handle + function GetImg($aMark,$aIdx) { + $n = $this->an[$aMark]; + if( is_string($aIdx) ) { + if( !in_array($aIdx,$this->colors) ) { + JpGraphError::RaiseL(23001,$this->name,$aIdx);//('This marker "'.($this->name).'" does not exist in color: '.$aIdx); + } + $idx = $this->index[$aIdx]; + } + elseif( !is_integer($aIdx) || + (is_integer($aIdx) && $aIdx > $this->maxidx ) ) { + JpGraphError::RaiseL(23002,$this->name);//('Mark color index too large for marker "'.($this->name).'"'); + } + else + $idx = $aIdx ; + return Image::CreateFromString(base64_decode($this->{$n}[$idx][1])); + } + + function GetAnchor() { + return array($this->anchor_x,$this->anchor_y); + } +} + + +// Keep a global flag cache to reduce memory usage +$_gFlagCache=array( +1 => null, +2 => null, +3 => null, +4 => null, +); +// Only supposed to b called as statics +class FlagCache { + + static function GetFlagImgByName($aSize,$aName) { + global $_gFlagCache; + require_once('jpgraph_flags.php'); + if( $_gFlagCache[$aSize] === null ) { + $_gFlagCache[$aSize] = new FlagImages($aSize); + } + $f = $_gFlagCache[$aSize]; + $idx = $f->GetIdxByName($aName,$aFullName); + return $f->GetImgByIdx($idx); + } +} + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_polar.php b/web/public_php/admin/jpgraph/jpgraph_polar.php index 1690fcb2a..df73828c1 100644 --- a/web/public_php/admin/jpgraph/jpgraph_polar.php +++ b/web/public_php/admin/jpgraph/jpgraph_polar.php @@ -1,845 +1,899 @@ -numpoints = $n/2; - $this->coord = $aData; - $this->mark = new PlotMark(); - } - - function SetWeight($aWeight) { - $this->iLineWeight = $aWeight; - } - - function SetColor($aColor){ - $this->iColor = $aColor; - } - - function SetFillColor($aColor){ - $this->iFillColor = $aColor; - } - - function Max() { - $m = $this->coord[1]; - $i=1; - while( $i < $this->numpoints ) { - $m = max($m,$this->coord[2*$i+1]); - ++$i; - } - return $m; - } - // Set href targets for CSIM - function SetCSIMTargets($aTargets,$aAlts=null) { - $this->csimtargets=$aTargets; - $this->csimalts=$aAlts; - } - - // Get all created areas - function GetCSIMareas() { - return $this->csimareas; - } - - function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") { - $this->legend = $aLegend; - $this->legendcsimtarget = $aCSIM; - $this->legendcsimalt = $aCSIMAlt; - } - - // Private methods - - function Legend(&$aGraph) { - $color = $this->iColor ; - if( $this->legend != "" ) { - if( $this->iFillColor!='' ) { - $color = $this->iFillColor; - $aGraph->legend->Add($this->legend,$color,$this->mark,0, - $this->legendcsimtarget,$this->legendcsimalt); - } - else { - $aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style, - $this->legendcsimtarget,$this->legendcsimalt); - } - } - } - - function Stroke(&$img,$scale) { - - $i=0; - $p=array(); - $this->csimareas=''; - while($i < $this->numpoints) { - list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]); - $p[2*$i] = $x1; - $p[2*$i+1] = $y1; - - if( isset($this->csimtargets[$i]) ) { - $this->mark->SetCSIMTarget($this->csimtargets[$i]); - $this->mark->SetCSIMAlt($this->csimalts[$i]); - $this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]); - $this->mark->Stroke($img,$x1,$y1); - $this->csimareas .= $this->mark->GetCSIMAreas(); - } - else - $this->mark->Stroke($img,$x1,$y1); - - ++$i; - } - - if( $this->iFillColor != '' ) { - $img->SetColor($this->iFillColor); - $img->FilledPolygon($p); - } - $img->SetLineWeight($this->iLineWeight); - $img->SetColor($this->iColor); - $img->Polygon($p,$this->iFillColor!=''); - } -} - -//-------------------------------------------------------------------------- -// class PolarAxis -//-------------------------------------------------------------------------- -class PolarAxis extends Axis { - var $angle_step=15,$angle_color='lightgray',$angle_label_color='black'; - var $angle_fontfam=FF_FONT1,$angle_fontstyle=FS_NORMAL,$angle_fontsize=10; - var $angle_fontcolor = 'navy'; - var $gridminor_color='lightgray',$gridmajor_color='lightgray'; - var $show_minor_grid = false, $show_major_grid = true ; - var $show_angle_mark=true, $show_angle_grid=true, $show_angle_label=true; - var $angle_tick_len=3, $angle_tick_len2=3, $angle_tick_color='black'; - var $show_angle_tick=true; - var $radius_tick_color='black'; - - function PolarAxis(&$img,&$aScale) { - parent::Axis($img,$aScale); - } - - function ShowAngleDegreeMark($aFlg=true) { - $this->show_angle_mark = $aFlg; - } - - function SetAngleStep($aStep) { - $this->angle_step=$aStep; - } - - function HideTicks($aFlg=true,$aAngleFlg=true) { - parent::HideTicks($aFlg,$aFlg); - $this->show_angle_tick = !$aAngleFlg; - } - - function ShowAngleLabel($aFlg=true) { - $this->show_angle_label = $aFlg; - } - - function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) { - $this->show_minor_grid = $aMinor; - $this->show_major_grid = $aMajor; - $this->show_angle_grid = $aAngle ; - } - - function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) { - $this->angle_fontfam = $aFontFam; - $this->angle_fontstyle = $aFontStyle; - $this->angle_fontsize = $aFontSize; - } - - function SetColor($aColor,$aRadColor='',$aAngleColor='') { - if( $aAngleColor == '' ) - $aAngleColor=$aColor; - parent::SetColor($aColor,$aRadColor); - $this->angle_fontcolor = $aAngleColor; - } - - function SetGridColor($aMajorColor,$aMinorColor='',$aAngleColor='') { - if( $aMinorColor == '' ) - $aMinorColor = $aMajorColor; - if( $aAngleColor == '' ) - $aAngleColor = $aMajorColor; - - $this->gridminor_color = $aMinorColor; - $this->gridmajor_color = $aMajorColor; - $this->angle_color = $aAngleColor; - } - - function SetTickColors($aRadColor,$aAngleColor='') { - $this->radius_tick_color = $aRadColor; - $this->angle_tick_color = $aAngleColor; - } - - // Private methods - function StrokeGrid($pos) { - $x = round($this->img->left_margin + $this->img->plotwidth/2); - $this->scale->ticks->Stroke($this->img,$this->scale,$pos); - - // Stroke the minor arcs - $pmin = array(); - $p = $this->scale->ticks->ticks_pos; - $n = count($p); - $i = 0; - $this->img->SetColor($this->gridminor_color); - while( $i < $n ) { - $r = $p[$i]-$x+1; - $pmin[]=$r; - if( $this->show_minor_grid ) { - $this->img->Circle($x,$pos,$r); - } - $i++; - } - - $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ; - while( $r < $limit ) { - $off = $r; - $i=1; - $r = $off + round($p[$i]-$x+1); - while( $r < $limit && $i < $n ) { - $r = $off+$p[$i]-$x; - $pmin[]=$r; - if( $this->show_minor_grid ) { - $this->img->Circle($x,$pos,$r); - } - $i++; - } - } - - // Stroke the major arcs - if( $this->show_major_grid ) { - // First determine how many minor step on - // every major step. We have recorded the minor radius - // in pmin and use these values. This is done in order - // to avoid rounding errors if we were to recalculate the - // different major radius. - $pmaj = $this->scale->ticks->maj_ticks_pos; - $p = $this->scale->ticks->ticks_pos; - if( $this->scale->name == 'lin' ) { - $step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0])); - } - else { - $step=9; - } - $n = round(count($pmin)/$step); - $i = 0; - $this->img->SetColor($this->gridmajor_color); - $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ; - $off = $r; - $i=0; - $r = $pmin[$i*$step]; - while( $r < $limit && $i < $n ) { - $r = $pmin[$i*$step]; - $this->img->Circle($x,$pos,$r); - $i++; - } - } - - // Draw angles - if( $this->show_angle_grid ) { - $this->img->SetColor($this->angle_color); - $d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ; - $a = 0; - $p = $this->scale->ticks->ticks_pos; - $start_radius = $p[1]-$x; - while( $a < 360 ) { - if( $a == 90 || $a == 270 ) { - // Make sure there are no rounding problem with - // exactly vertical lines - $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1, - $pos-$start_radius*sin($a/180*M_PI), - $x+$start_radius*cos($a/180*M_PI)+1, - $pos-$d*sin($a/180*M_PI)); - - } - else { - $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1, - $pos-$start_radius*sin($a/180*M_PI), - $x+$d*cos($a/180*M_PI), - $pos-$d*sin($a/180*M_PI)); - } - $a += $this->angle_step; - } - } - } - - function StrokeAngleLabels($pos,$type) { - - if( !$this->show_angle_label ) - return; - - $x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1; - - $d = max($this->img->plotwidth,$this->img->plotheight)*1.42; - $a = $this->angle_step; - $t = new Text(); - $t->SetColor($this->angle_fontcolor); - $t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize); - $xright = $this->img->width - $this->img->right_margin; - $ytop = $this->img->top_margin; - $xleft = $this->img->left_margin; - $ybottom = $this->img->height - $this->img->bottom_margin; - $ha = 'left'; - $va = 'center'; - $w = $this->img->plotwidth/2; - $h = $this->img->plotheight/2; - $xt = $x0; $yt = $pos; - $margin=5; - - $tl = $this->angle_tick_len ; // Outer len - $tl2 = $this->angle_tick_len2 ; // Interior len - - $this->img->SetColor($this->angle_tick_color); - $rot90 = $this->img->a == 90 ; - - if( $type == POLAR_360 ) { - $ca1 = atan($h/$w)/M_PI*180; - $ca2 = 180-$ca1; - $ca3 = $ca1+180; - $ca4 = 360-$ca1; - $end = 360; - while( $a < $end ) { - $ca = cos($a/180*M_PI); - $sa = sin($a/180*M_PI); - $x = $d*$ca; - $y = $d*$sa; - $xt=1000;$yt=1000; - if( $a <= $ca1 || $a >= $ca4 ) { - $yt = $pos - $w * $y/$x; - $xt = $xright + $margin; - if( $rot90 ) { - $ha = 'center'; - $va = 'top'; - } - else { - $ha = 'left'; - $va = 'center'; - } - $x1=$xright-$tl2; $x2=$xright+$tl; - $y1=$y2=$yt; - } - elseif( $a > $ca1 && $a < $ca2 ) { - $xt = $x0 + $h * $x/$y; - $yt = $ytop - $margin; - if( $rot90 ) { - $ha = 'left'; - $va = 'center'; - } - else { - $ha = 'center'; - $va = 'bottom'; - } - $y1=$ytop+$tl2;$y2=$ytop-$tl; - $x1=$x2=$xt; - } - elseif( $a >= $ca2 && $a <= $ca3 ) { - $yt = $pos + $w * $y/$x; - $xt = $xleft - $margin; - if( $rot90 ) { - $ha = 'center'; - $va = 'bottom'; - } - else { - $ha = 'right'; - $va = 'center'; - } - $x1=$xleft+$tl2;$x2=$xleft-$tl; - $y1=$y2=$yt; - } - else { - $xt = $x0 - $h * $x/$y; - $yt = $ybottom + $margin; - if( $rot90 ) { - $ha = 'right'; - $va = 'center'; - } - else { - $ha = 'center'; - $va = 'top'; - } - $y1=$ybottom-$tl2;$y2=$ybottom+$tl; - $x1=$x2=$xt; - } - if( $a != 0 && $a != 180 ) { - $t->Align($ha,$va); - if( $this->show_angle_mark ) - $a .= '°'; - $t->Set($a); - $t->Stroke($this->img,$xt,$yt); - if( $this->show_angle_tick ) - $this->img->Line($x1,$y1,$x2,$y2); - } - $a += $this->angle_step; - } - } - else { - // POLAR_HALF - $ca1 = atan($h/$w*2)/M_PI*180; - $ca2 = 180-$ca1; - $end = 180; - while( $a < $end ) { - $ca = cos($a/180*M_PI); - $sa = sin($a/180*M_PI); - $x = $d*$ca; - $y = $d*$sa; - if( $a <= $ca1 ) { - $yt = $pos - $w * $y/$x; - $xt = $xright + $margin; - if( $rot90 ) { - $ha = 'center'; - $va = 'top'; - } - else { - $ha = 'left'; - $va = 'center'; - } - $x1=$xright-$tl2; $x2=$xright+$tl; - $y1=$y2=$yt; - } - elseif( $a > $ca1 && $a < $ca2 ) { - $xt = $x0 + 2*$h * $x/$y; - $yt = $ytop - $margin; - if( $rot90 ) { - $ha = 'left'; - $va = 'center'; - } - else { - $ha = 'center'; - $va = 'bottom'; - } - $y1=$ytop+$tl2;$y2=$ytop-$tl; - $x1=$x2=$xt; - } - elseif( $a >= $ca2 ) { - $yt = $pos + $w * $y/$x; - $xt = $xleft - $margin; - if( $rot90 ) { - $ha = 'center'; - $va = 'bottom'; - } - else { - $ha = 'right'; - $va = 'center'; - } - $x1=$xleft+$tl2;$x2=$xleft-$tl; - $y1=$y2=$yt; - } - $t->Align($ha,$va); - if( $this->show_angle_mark ) - $a .= '°'; - $t->Set($a); - $t->Stroke($this->img,$xt,$yt); - if( $this->show_angle_tick ) - $this->img->Line($x1,$y1,$x2,$y2); - $a += $this->angle_step; - } - } - } - - function Stroke($pos) { - - $this->img->SetLineWeight($this->weight); - $this->img->SetColor($this->color); - $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); - if( !$this->hide_line ) - $this->img->FilledRectangle($this->img->left_margin,$pos, - $this->img->width-$this->img->right_margin,$pos+$this->weight-1); - $y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin; - if( $this->title_adjust=="high" ) - $this->title->Pos($this->img->width-$this->img->right_margin,$y,"right","top"); - elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" ) - $this->title->Pos(($this->img->width-$this->img->left_margin- - $this->img->right_margin)/2+$this->img->left_margin, - $y,"center","top"); - elseif($this->title_adjust=="low") - $this->title->Pos($this->img->left_margin,$y,"left","top"); - else { - JpGraphError::RaiseL(17002,$this->title_adjust); -//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')'); - } - - - if (!$this->hide_labels) { - $this->StrokeLabels($pos,false); - } - $this->img->SetColor($this->radius_tick_color); - $this->scale->ticks->Stroke($this->img,$this->scale,$pos); - - // - // Mirror the positions for the left side of the scale - // - $mid = 2*($this->img->left_margin+$this->img->plotwidth/2); - $n = count($this->scale->ticks->ticks_pos); - $i=0; - while( $i < $n ) { - $this->scale->ticks->ticks_pos[$i] = - $mid-$this->scale->ticks->ticks_pos[$i] ; - ++$i; - } - - $n = count($this->scale->ticks->maj_ticks_pos); - $i=0; - while( $i < $n ) { - $this->scale->ticks->maj_ticks_pos[$i] = - $mid-$this->scale->ticks->maj_ticks_pos[$i] ; - ++$i; - } - - $n = count($this->scale->ticks->maj_ticklabels_pos); - $i=1; - while( $i < $n ) { - $this->scale->ticks->maj_ticklabels_pos[$i] = - $mid-$this->scale->ticks->maj_ticklabels_pos[$i] ; - ++$i; - } - - // Draw the left side of the scale - $n = count($this->scale->ticks->ticks_pos); - $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize(); - - - // Minor ticks - if( ! $this->scale->ticks->supress_minor_tickmarks ) { - $i=1; - while( $i < $n/2 ) { - $x = round($this->scale->ticks->ticks_pos[$i]) ; - $this->img->Line($x,$pos,$x,$yu); - ++$i; - } - } - - $n = count($this->scale->ticks->maj_ticks_pos); - $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize(); - - - // Major ticks - if( ! $this->scale->ticks->supress_tickmarks ) { - $i=1; - while( $i < $n/2 ) { - $x = round($this->scale->ticks->maj_ticks_pos[$i]) ; - $this->img->Line($x,$pos,$x,$yu); - ++$i; - } - } - if (!$this->hide_labels) { - $this->StrokeLabels($pos,false); - } - $this->title->Stroke($this->img); - } -} - -class PolarScale extends LinearScale { - var $graph; - function PolarScale($aMax=0,&$graph) { - parent::LinearScale(0,$aMax,'x'); - $this->graph = &$graph; - } - - function _Translate($v) { - return parent::Translate($v); - } - - function PTranslate($aAngle,$aRad) { - - $m = $this->scale[1]; - $w = $this->graph->img->plotwidth/2; - $aRad = $aRad/$m*$w; - - $x = cos( $aAngle/180 * M_PI ) * $aRad; - $y = sin( $aAngle/180 * M_PI ) * $aRad; - - $x += $this->_Translate(0); - - if( $this->graph->iType == POLAR_360 ) { - $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y; - } - else { - $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y; - } - return array($x,$y); - } -} - -class PolarLogScale extends LogScale { - var $graph; - function PolarLogScale($aMax=1,&$graph) { - parent::LogScale(0,$aMax,'x'); - $this->graph = &$graph; - $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE); - - } - - function PTranslate($aAngle,$aRad) { - - if( $aRad == 0 ) - $aRad = 1; - $aRad = log10($aRad); - $m = $this->scale[1]; - $w = $this->graph->img->plotwidth/2; - $aRad = $aRad/$m*$w; - - $x = cos( $aAngle/180 * M_PI ) * $aRad; - $y = sin( $aAngle/180 * M_PI ) * $aRad; - - $x += $w+$this->graph->img->left_margin;//$this->_Translate(0); - if( $this->graph->iType == POLAR_360 ) { - $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y; - } - else { - $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y; - } - return array($x,$y); - } -} - -class PolarGraph extends Graph { - var $scale; - var $iType=POLAR_360; - var $axis; - - function PolarGraph($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) { - parent::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ; - $this->SetDensity(TICKD_DENSE); - $this->SetBox(); - $this->SetMarginColor('white'); - } - - function SetDensity($aDense) { - $this->SetTickDensity(TICKD_NORMAL,$aDense); - } - - function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) { - $adj = ($this->img->height - $this->img->width)/2; - $this->SetAngle(90); - $this->img->SetMargin($lm-$adj,$rm-$adj,$tm+$adj,$bm+$adj); - $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2)); - $this->axis->SetLabelAlign('right','center'); - //JpGraphError::Raise('Set90AndMargin() is not supported for polar graphs.'); - } - - function SetScale($aScale,$rmax=0) { - if( $aScale == 'lin' ) - $this->scale = new PolarScale($rmax,$this); - elseif( $aScale == 'log' ) { - $this->scale = new PolarLogScale($rmax,$this); - } - else { - JpGraphError::RaiseL(17004);//('Unknown scale type for polar graph. Must be "lin" or "log"'); - } - - $this->axis = new PolarAxis($this->img,$this->scale); - $this->SetMargin(40,40,50,40); - } - - function SetType($aType) { - $this->iType = $aType; - } - - function SetPlotSize($w,$h) { - $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2, - ($this->img->height-$h)/2,($this->img->height-$h)/2); - } - - // Private methods - function GetPlotsMax() { - $n = count($this->plots); - $m = $this->plots[0]->Max(); - $i=1; - while($i < $n) { - $m = max($this->plots[$i]->Max(),$m); - ++$i; - } - return $m; - } - - function Stroke($aStrokeFileName="") { - - // Start by adjusting the margin so that potential titles will fit. - $this->AdjustMarginsForTitles(); - - // If the filename is the predefined value = '_csim_special_' - // we assume that the call to stroke only needs to do enough - // to correctly generate the CSIM maps. - // We use this variable to skip things we don't strictly need - // to do to generate the image map to improve performance - // a best we can. Therefor you will see a lot of tests !$_csim in the - // code below. - $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); - - // We need to know if we have stroked the plot in the - // GetCSIMareas. Otherwise the CSIM hasn't been generated - // and in the case of GetCSIM called before stroke to generate - // CSIM without storing an image to disk GetCSIM must call Stroke. - $this->iHasStroked = true; - - //Check if we should autoscale axis - if( !$this->scale->IsSpecified() && count($this->plots)>0 ) { - $max = $this->GetPlotsMax(); - $t1 = $this->img->plotwidth; - $this->img->plotwidth /= 2; - $t2 = $this->img->left_margin; - $this->img->left_margin += $this->img->plotwidth+1; - $this->scale->AutoScale($this->img,0,$max, - $this->img->plotwidth/$this->xtick_factor/2); - $this->img->plotwidth = $t1; - $this->img->left_margin = $t2; - } - else { - // The tick calculation will use the user suplied min/max values to determine - // the ticks. If auto_ticks is false the exact user specifed min and max - // values will be used for the scale. - // If auto_ticks is true then the scale might be slightly adjusted - // so that the min and max values falls on an even major step. - //$min = 0; - $max = $this->scale->scale[1]; - $t1 = $this->img->plotwidth; - $this->img->plotwidth /= 2; - $t2 = $this->img->left_margin; - $this->img->left_margin += $this->img->plotwidth+1; - $this->scale->AutoScale($this->img,0,$max, - $this->img->plotwidth/$this->xtick_factor/2); - $this->img->plotwidth = $t1; - $this->img->left_margin = $t2; - } - - if( $this->iType == POLAR_180 ) - $pos = $this->img->height - $this->img->bottom_margin; - else - $pos = $this->img->plotheight/2 + $this->img->top_margin; - - - if( !$_csim ) { - $this->StrokePlotArea(); - } - - $this->iDoClipping = true; - - if( $this->iDoClipping ) { - $oldimage = $this->img->CloneCanvasH(); - } - - if( !$_csim ) { - $this->axis->StrokeGrid($pos); - } - - // Stroke all plots for Y1 axis - for($i=0; $i < count($this->plots); ++$i) { - $this->plots[$i]->Stroke($this->img,$this->scale); - } - - - if( $this->iDoClipping ) { - // Clipping only supports graphs at 0 and 90 degrees - if( $this->img->a == 0 ) { - $this->img->CopyCanvasH($oldimage,$this->img->img, - $this->img->left_margin,$this->img->top_margin, - $this->img->left_margin,$this->img->top_margin, - $this->img->plotwidth+1,$this->img->plotheight+1); - } - elseif( $this->img->a == 90 ) { - $adj = round(($this->img->height - $this->img->width)/2); - $this->img->CopyCanvasH($oldimage,$this->img->img, - $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, - $this->img->bottom_margin-$adj,$this->img->left_margin+$adj, - $this->img->plotheight,$this->img->plotwidth); - } - $this->img->Destroy(); - $this->img->SetCanvasH($oldimage); - } - - if( !$_csim ) { - $this->axis->Stroke($pos); - $this->axis->StrokeAngleLabels($pos,$this->iType); - } - - if( !$_csim ) { - $this->StrokePlotBox(); - $this->footer->Stroke($this->img); - - // The titles and legends never gets rotated so make sure - // that the angle is 0 before stroking them - $aa = $this->img->SetAngle(0); - $this->StrokeTitles(); - } - - for($i=0; $i < count($this->plots) ; ++$i ) { - $this->plots[$i]->Legend($this); - } - - $this->legend->Stroke($this->img); - - if( !$_csim ) { - - $this->StrokeTexts(); - $this->img->SetAngle($aa); - - // Draw an outline around the image map - if(_JPG_DEBUG) - $this->DisplayClientSideaImageMapAreas(); - - // Adjust the appearance of the image - $this->AdjustSaturationBrightnessContrast(); - - // If the filename is given as the special "__handle" - // then the image handler is returned and the image is NOT - // streamed back - if( $aStrokeFileName == _IMG_HANDLER ) { - return $this->img->img; - } - else { - // Finally stream the generated picture - $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, - $aStrokeFileName); - } - } - } -} - - - -?> +numpoints = $n/2; + $this->coord = $aData; + $this->mark = new PlotMark(); + } + + function SetWeight($aWeight) { + $this->iLineWeight = $aWeight; + } + + function SetColor($aColor){ + $this->iColor = $aColor; + } + + function SetFillColor($aColor){ + $this->iFillColor = $aColor; + } + + function Max() { + $m = $this->coord[1]; + $i=1; + while( $i < $this->numpoints ) { + $m = max($m,$this->coord[2*$i+1]); + ++$i; + } + return $m; + } + // Set href targets for CSIM + function SetCSIMTargets($aTargets,$aAlts=null) { + $this->csimtargets=$aTargets; + $this->csimalts=$aAlts; + } + + // Get all created areas + function GetCSIMareas() { + return $this->csimareas; + } + + function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") { + $this->legend = $aLegend; + $this->legendcsimtarget = $aCSIM; + $this->legendcsimalt = $aCSIMAlt; + } + + // Private methods + + function Legend($aGraph) { + $color = $this->iColor ; + if( $this->legend != "" ) { + if( $this->iFillColor!='' ) { + $color = $this->iFillColor; + $aGraph->legend->Add($this->legend,$color,$this->mark,0, + $this->legendcsimtarget,$this->legendcsimalt); + } + else { + $aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style, + $this->legendcsimtarget,$this->legendcsimalt); + } + } + } + + function Stroke($img,$scale) { + + $i=0; + $p=array(); + $this->csimareas=''; + while($i < $this->numpoints) { + list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]); + $p[2*$i] = $x1; + $p[2*$i+1] = $y1; + + if( isset($this->csimtargets[$i]) ) { + $this->mark->SetCSIMTarget($this->csimtargets[$i]); + $this->mark->SetCSIMAlt($this->csimalts[$i]); + $this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]); + $this->mark->Stroke($img,$x1,$y1); + $this->csimareas .= $this->mark->GetCSIMAreas(); + } + else { + $this->mark->Stroke($img,$x1,$y1); + } + + ++$i; + } + + if( $this->iFillColor != '' ) { + $img->SetColor($this->iFillColor); + $img->FilledPolygon($p); + } + $img->SetLineWeight($this->iLineWeight); + $img->SetColor($this->iColor); + $img->Polygon($p,$this->iFillColor!=''); + } +} + +//-------------------------------------------------------------------------- +// class PolarAxis +//-------------------------------------------------------------------------- +class PolarAxis extends Axis { + private $angle_step=15,$angle_color='lightgray',$angle_label_color='black'; + private $angle_fontfam=FF_FONT1,$angle_fontstyle=FS_NORMAL,$angle_fontsize=10; + private $angle_fontcolor = 'navy'; + private $gridminor_color='lightgray',$gridmajor_color='lightgray'; + private $show_minor_grid = false, $show_major_grid = true ; + private $show_angle_mark=true, $show_angle_grid=true, $show_angle_label=true; + private $angle_tick_len=3, $angle_tick_len2=3, $angle_tick_color='black'; + private $show_angle_tick=true; + private $radius_tick_color='black'; + + function __construct($img,$aScale) { + parent::__construct($img,$aScale); + } + + function ShowAngleDegreeMark($aFlg=true) { + $this->show_angle_mark = $aFlg; + } + + function SetAngleStep($aStep) { + $this->angle_step=$aStep; + } + + function HideTicks($aFlg=true,$aAngleFlg=true) { + parent::HideTicks($aFlg,$aFlg); + $this->show_angle_tick = !$aAngleFlg; + } + + function ShowAngleLabel($aFlg=true) { + $this->show_angle_label = $aFlg; + } + + function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) { + $this->show_minor_grid = $aMinor; + $this->show_major_grid = $aMajor; + $this->show_angle_grid = $aAngle ; + } + + function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->angle_fontfam = $aFontFam; + $this->angle_fontstyle = $aFontStyle; + $this->angle_fontsize = $aFontSize; + } + + function SetColor($aColor,$aRadColor='',$aAngleColor='') { + if( $aAngleColor == '' ) + $aAngleColor=$aColor; + parent::SetColor($aColor,$aRadColor); + $this->angle_fontcolor = $aAngleColor; + } + + function SetGridColor($aMajorColor,$aMinorColor='',$aAngleColor='') { + if( $aMinorColor == '' ) + $aMinorColor = $aMajorColor; + if( $aAngleColor == '' ) + $aAngleColor = $aMajorColor; + + $this->gridminor_color = $aMinorColor; + $this->gridmajor_color = $aMajorColor; + $this->angle_color = $aAngleColor; + } + + function SetTickColors($aRadColor,$aAngleColor='') { + $this->radius_tick_color = $aRadColor; + $this->angle_tick_color = $aAngleColor; + } + + // Private methods + function StrokeGrid($pos) { + $x = round($this->img->left_margin + $this->img->plotwidth/2); + $this->scale->ticks->Stroke($this->img,$this->scale,$pos); + + // Stroke the minor arcs + $pmin = array(); + $p = $this->scale->ticks->ticks_pos; + $n = count($p); + $i = 0; + $this->img->SetColor($this->gridminor_color); + while( $i < $n ) { + $r = $p[$i]-$x+1; + $pmin[]=$r; + if( $this->show_minor_grid ) { + $this->img->Circle($x,$pos,$r); + } + $i++; + } + + $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ; + while( $r < $limit ) { + $off = $r; + $i=1; + $r = $off + round($p[$i]-$x+1); + while( $r < $limit && $i < $n ) { + $r = $off+$p[$i]-$x; + $pmin[]=$r; + if( $this->show_minor_grid ) { + $this->img->Circle($x,$pos,$r); + } + $i++; + } + } + + // Stroke the major arcs + if( $this->show_major_grid ) { + // First determine how many minor step on + // every major step. We have recorded the minor radius + // in pmin and use these values. This is done in order + // to avoid rounding errors if we were to recalculate the + // different major radius. + $pmaj = $this->scale->ticks->maj_ticks_pos; + $p = $this->scale->ticks->ticks_pos; + if( $this->scale->name == 'lin' ) { + $step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0])); + } + else { + $step=9; + } + $n = round(count($pmin)/$step); + $i = 0; + $this->img->SetColor($this->gridmajor_color); + $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ; + $off = $r; + $i=0; + $r = $pmin[$i*$step]; + while( $r < $limit && $i < $n ) { + $r = $pmin[$i*$step]; + $this->img->Circle($x,$pos,$r); + $i++; + } + } + + // Draw angles + if( $this->show_angle_grid ) { + $this->img->SetColor($this->angle_color); + $d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ; + $a = 0; + $p = $this->scale->ticks->ticks_pos; + $start_radius = $p[1]-$x; + while( $a < 360 ) { + if( $a == 90 || $a == 270 ) { + // Make sure there are no rounding problem with + // exactly vertical lines + $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1, + $pos-$start_radius*sin($a/180*M_PI), + $x+$start_radius*cos($a/180*M_PI)+1, + $pos-$d*sin($a/180*M_PI)); + + } + else { + $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1, + $pos-$start_radius*sin($a/180*M_PI), + $x+$d*cos($a/180*M_PI), + $pos-$d*sin($a/180*M_PI)); + } + $a += $this->angle_step; + } + } + } + + function StrokeAngleLabels($pos,$type) { + + if( !$this->show_angle_label ) + return; + + $x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1; + + $d = max($this->img->plotwidth,$this->img->plotheight)*1.42; + $a = $this->angle_step; + $t = new Text(); + $t->SetColor($this->angle_fontcolor); + $t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize); + $xright = $this->img->width - $this->img->right_margin; + $ytop = $this->img->top_margin; + $xleft = $this->img->left_margin; + $ybottom = $this->img->height - $this->img->bottom_margin; + $ha = 'left'; + $va = 'center'; + $w = $this->img->plotwidth/2; + $h = $this->img->plotheight/2; + $xt = $x0; $yt = $pos; + $margin=5; + + $tl = $this->angle_tick_len ; // Outer len + $tl2 = $this->angle_tick_len2 ; // Interior len + + $this->img->SetColor($this->angle_tick_color); + $rot90 = $this->img->a == 90 ; + + if( $type == POLAR_360 ) { + + // Corner angles of the four corners + $ca1 = atan($h/$w)/M_PI*180; + $ca2 = 180-$ca1; + $ca3 = $ca1+180; + $ca4 = 360-$ca1; + $end = 360; + + while( $a < $end ) { + $ca = cos($a/180*M_PI); + $sa = sin($a/180*M_PI); + $x = $d*$ca; + $y = $d*$sa; + $xt=1000;$yt=1000; + if( $a <= $ca1 || $a >= $ca4 ) { + $yt = $pos - $w * $y/$x; + $xt = $xright + $margin; + if( $rot90 ) { + $ha = 'center'; + $va = 'top'; + } + else { + $ha = 'left'; + $va = 'center'; + } + $x1=$xright-$tl2; $x2=$xright+$tl; + $y1=$y2=$yt; + } + elseif( $a > $ca1 && $a < $ca2 ) { + $xt = $x0 + $h * $x/$y; + $yt = $ytop - $margin; + if( $rot90 ) { + $ha = 'left'; + $va = 'center'; + } + else { + $ha = 'center'; + $va = 'bottom'; + } + $y1=$ytop+$tl2;$y2=$ytop-$tl; + $x1=$x2=$xt; + } + elseif( $a >= $ca2 && $a <= $ca3 ) { + $yt = $pos + $w * $y/$x; + $xt = $xleft - $margin; + if( $rot90 ) { + $ha = 'center'; + $va = 'bottom'; + } + else { + $ha = 'right'; + $va = 'center'; + } + $x1=$xleft+$tl2;$x2=$xleft-$tl; + $y1=$y2=$yt; + } + else { + $xt = $x0 - $h * $x/$y; + $yt = $ybottom + $margin; + if( $rot90 ) { + $ha = 'right'; + $va = 'center'; + } + else { + $ha = 'center'; + $va = 'top'; + } + $y1=$ybottom-$tl2;$y2=$ybottom+$tl; + $x1=$x2=$xt; + } + if( $a != 0 && $a != 180 ) { + $t->Align($ha,$va); + if( $this->scale->clockwise ) { + $t->Set(360-$a); + } + else { + $t->Set($a); + } + if( $this->show_angle_mark && $t->font_family > 4 ) { + $a .= SymChar::Get('degree'); + } + $t->Stroke($this->img,$xt,$yt); + if( $this->show_angle_tick ) { + $this->img->Line($x1,$y1,$x2,$y2); + } + } + $a = (int) $a; + $a += $this->angle_step; + } + } + else { + // POLAR_HALF + $ca1 = atan($h/$w*2)/M_PI*180; + $ca2 = 180-$ca1; + $end = 180; + while( $a < $end ) { + $ca = cos($a/180*M_PI); + $sa = sin($a/180*M_PI); + $x = $d*$ca; + $y = $d*$sa; + if( $a <= $ca1 ) { + $yt = $pos - $w * $y/$x; + $xt = $xright + $margin; + if( $rot90 ) { + $ha = 'center'; + $va = 'top'; + } + else { + $ha = 'left'; + $va = 'center'; + } + $x1=$xright-$tl2; $x2=$xright+$tl; + $y1=$y2=$yt; + } + elseif( $a > $ca1 && $a < $ca2 ) { + $xt = $x0 + 2*$h * $x/$y; + $yt = $ytop - $margin; + if( $rot90 ) { + $ha = 'left'; + $va = 'center'; + } + else { + $ha = 'center'; + $va = 'bottom'; + } + $y1=$ytop+$tl2;$y2=$ytop-$tl; + $x1=$x2=$xt; + } + elseif( $a >= $ca2 ) { + $yt = $pos + $w * $y/$x; + $xt = $xleft - $margin; + if( $rot90 ) { + $ha = 'center'; + $va = 'bottom'; + } + else { + $ha = 'right'; + $va = 'center'; + } + $x1=$xleft+$tl2;$x2=$xleft-$tl; + $y1=$y2=$yt; + } + $t->Align($ha,$va); + if( $this->show_angle_mark && $t->font_family > 4 ) { + $a .= SymChar::Get('degree'); + } + $t->Set($a); + $t->Stroke($this->img,$xt,$yt); + if( $this->show_angle_tick ) { + $this->img->Line($x1,$y1,$x2,$y2); + } + $a = (int) $a; + $a += $this->angle_step; + } + } + } + + function Stroke($pos,$dummy=true) { + + $this->img->SetLineWeight($this->weight); + $this->img->SetColor($this->color); + $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); + if( !$this->hide_line ) { + $this->img->FilledRectangle($this->img->left_margin,$pos, + $this->img->width-$this->img->right_margin, + $pos+$this->weight-1); + } + $y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin; + if( $this->title_adjust=="high" ) { + $this->title->SetPos($this->img->width-$this->img->right_margin,$y,"right","top"); + } + elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" ) { + $this->title->SetPos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin, + $y,"center","top"); + } + elseif($this->title_adjust=="low") { + $this->title->SetPos($this->img->left_margin,$y,"left","top"); + } + else { + JpGraphError::RaiseL(17002,$this->title_adjust); + //('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')'); + } + + + if (!$this->hide_labels) { + $this->StrokeLabels($pos,false); + } + $this->img->SetColor($this->radius_tick_color); + $this->scale->ticks->Stroke($this->img,$this->scale,$pos); + + // + // Mirror the positions for the left side of the scale + // + $mid = 2*($this->img->left_margin+$this->img->plotwidth/2); + $n = count($this->scale->ticks->ticks_pos); + $i=0; + while( $i < $n ) { + $this->scale->ticks->ticks_pos[$i] = + $mid-$this->scale->ticks->ticks_pos[$i] ; + ++$i; + } + + $n = count($this->scale->ticks->maj_ticks_pos); + $i=0; + while( $i < $n ) { + $this->scale->ticks->maj_ticks_pos[$i] = + $mid-$this->scale->ticks->maj_ticks_pos[$i] ; + ++$i; + } + + $n = count($this->scale->ticks->maj_ticklabels_pos); + $i=1; + while( $i < $n ) { + $this->scale->ticks->maj_ticklabels_pos[$i] = + $mid-$this->scale->ticks->maj_ticklabels_pos[$i] ; + ++$i; + } + + // Draw the left side of the scale + $n = count($this->scale->ticks->ticks_pos); + $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize(); + + + // Minor ticks + if( ! $this->scale->ticks->supress_minor_tickmarks ) { + $i=1; + while( $i < $n/2 ) { + $x = round($this->scale->ticks->ticks_pos[$i]) ; + $this->img->Line($x,$pos,$x,$yu); + ++$i; + } + } + + $n = count($this->scale->ticks->maj_ticks_pos); + $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize(); + + + // Major ticks + if( ! $this->scale->ticks->supress_tickmarks ) { + $i=1; + while( $i < $n/2 ) { + $x = round($this->scale->ticks->maj_ticks_pos[$i]) ; + $this->img->Line($x,$pos,$x,$yu); + ++$i; + } + } + if (!$this->hide_labels) { + $this->StrokeLabels($pos,false); + } + $this->title->Stroke($this->img); + } +} + +class PolarScale extends LinearScale { + private $graph; + public $clockwise=false; + + function __construct($aMax,$graph,$aClockwise) { + parent::__construct(0,$aMax,'x'); + $this->graph = $graph; + $this->clockwise = $aClockwise; + } + + function SetClockwise($aFlg) { + $this->clockwise = $aFlg; + } + + function _Translate($v) { + return parent::Translate($v); + } + + function PTranslate($aAngle,$aRad) { + + $m = $this->scale[1]; + $w = $this->graph->img->plotwidth/2; + $aRad = $aRad/$m*$w; + + $a = $aAngle/180 * M_PI; + if( $this->clockwise ) { + $a = 2*M_PI-$a; + } + + $x = cos($a) * $aRad; + $y = sin($a) * $aRad; + + $x += $this->_Translate(0); + + if( $this->graph->iType == POLAR_360 ) { + $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y; + } + else { + $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y; + } + return array($x,$y); + } +} + +class PolarLogScale extends LogScale { + private $graph; + public $clockwise=false; + + function __construct($aMax,$graph,$aClockwise=false) { + parent::__construct(0,$aMax,'x'); + $this->graph = $graph; + $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE); + $this->clockwise = $aClockwise; + + } + + function SetClockwise($aFlg) { + $this->clockwise = $aFlg; + } + + function PTranslate($aAngle,$aRad) { + + if( $aRad == 0 ) + $aRad = 1; + $aRad = log10($aRad); + $m = $this->scale[1]; + $w = $this->graph->img->plotwidth/2; + $aRad = $aRad/$m*$w; + + $a = $aAngle/180 * M_PI; + if( $this->clockwise ) { + $a = 2*M_PI-$a; + } + + $x = cos( $a ) * $aRad; + $y = sin( $a ) * $aRad; + + $x += $w+$this->graph->img->left_margin;//$this->_Translate(0); + if( $this->graph->iType == POLAR_360 ) { + $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y; + } + else { + $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y; + } + return array($x,$y); + } +} + +class PolarGraph extends Graph { + public $scale; + public $axis; + public $iType=POLAR_360; + private $iClockwise=false; + + function __construct($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) { + parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ; + $this->SetDensity(TICKD_DENSE); + $this->SetBox(); + $this->SetMarginColor('white'); + } + + function SetDensity($aDense) { + $this->SetTickDensity(TICKD_NORMAL,$aDense); + } + + function SetClockwise($aFlg) { + $this->scale->SetClockwise($aFlg); + } + + function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) { + $adj = ($this->img->height - $this->img->width)/2; + $this->SetAngle(90); + $lm2 = -$adj + ($lm-$rm+$tm+$bm)/2; + $rm2 = -$adj + (-$lm+$rm+$tm+$bm)/2; + $tm2 = $adj + ($tm-$bm+$lm+$rm)/2; + $bm2 = $adj + (-$tm+$bm+$lm+$rm)/2; + $this->SetMargin($lm2, $rm2, $tm2, $bm2); + $this->axis->SetLabelAlign('right','center'); + } + + function SetScale($aScale,$rmax=0,$dummy1=1,$dummy2=1,$dummy3=1) { + if( $aScale == 'lin' ) { + $this->scale = new PolarScale($rmax,$this,$this->iClockwise); + } + elseif( $aScale == 'log' ) { + $this->scale = new PolarLogScale($rmax,$this,$this->iClockwise); + } + else { + JpGraphError::RaiseL(17004);//('Unknown scale type for polar graph. Must be "lin" or "log"'); + } + + $this->axis = new PolarAxis($this->img,$this->scale); + $this->SetMargin(40,40,50,40); + } + + function SetType($aType) { + $this->iType = $aType; + } + + function SetPlotSize($w,$h) { + $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2, + ($this->img->height-$h)/2,($this->img->height-$h)/2); + } + + // Private methods + function GetPlotsMax() { + $n = count($this->plots); + $m = $this->plots[0]->Max(); + $i=1; + while($i < $n) { + $m = max($this->plots[$i]->Max(),$m); + ++$i; + } + return $m; + } + + function Stroke($aStrokeFileName="") { + + // Start by adjusting the margin so that potential titles will fit. + $this->AdjustMarginsForTitles(); + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // a best we can. Therefor you will see a lot of tests !$_csim in the + // code below. + $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); + + // We need to know if we have stroked the plot in the + // GetCSIMareas. Otherwise the CSIM hasn't been generated + // and in the case of GetCSIM called before stroke to generate + // CSIM without storing an image to disk GetCSIM must call Stroke. + $this->iHasStroked = true; + + //Check if we should autoscale axis + if( !$this->scale->IsSpecified() && count($this->plots)>0 ) { + $max = $this->GetPlotsMax(); + $t1 = $this->img->plotwidth; + $this->img->plotwidth /= 2; + $t2 = $this->img->left_margin; + $this->img->left_margin += $this->img->plotwidth+1; + $this->scale->AutoScale($this->img,0,$max, + $this->img->plotwidth/$this->xtick_factor/2); + $this->img->plotwidth = $t1; + $this->img->left_margin = $t2; + } + else { + // The tick calculation will use the user suplied min/max values to determine + // the ticks. If auto_ticks is false the exact user specifed min and max + // values will be used for the scale. + // If auto_ticks is true then the scale might be slightly adjusted + // so that the min and max values falls on an even major step. + //$min = 0; + $max = $this->scale->scale[1]; + $t1 = $this->img->plotwidth; + $this->img->plotwidth /= 2; + $t2 = $this->img->left_margin; + $this->img->left_margin += $this->img->plotwidth+1; + $this->scale->AutoScale($this->img,0,$max, + $this->img->plotwidth/$this->xtick_factor/2); + $this->img->plotwidth = $t1; + $this->img->left_margin = $t2; + } + + if( $this->iType == POLAR_180 ) { + $pos = $this->img->height - $this->img->bottom_margin; + } + else { + $pos = $this->img->plotheight/2 + $this->img->top_margin; + } + + if( !$_csim ) { + $this->StrokePlotArea(); + } + + $this->iDoClipping = true; + + if( $this->iDoClipping ) { + $oldimage = $this->img->CloneCanvasH(); + } + + if( !$_csim ) { + $this->axis->StrokeGrid($pos); + } + + // Stroke all plots for Y1 axis + for($i=0; $i < count($this->plots); ++$i) { + $this->plots[$i]->Stroke($this->img,$this->scale); + } + + + if( $this->iDoClipping ) { + // Clipping only supports graphs at 0 and 90 degrees + if( $this->img->a == 0 ) { + $this->img->CopyCanvasH($oldimage,$this->img->img, + $this->img->left_margin,$this->img->top_margin, + $this->img->left_margin,$this->img->top_margin, + $this->img->plotwidth+1,$this->img->plotheight+1); + } + elseif( $this->img->a == 90 ) { + $adj1 = round(($this->img->height - $this->img->width)/2); + $adj2 = round(($this->img->width - $this->img->height)/2); + $lm = $this->img->left_margin; + $rm = $this->img->right_margin; + $tm = $this->img->top_margin; + $bm = $this->img->bottom_margin; + $this->img->CopyCanvasH($oldimage,$this->img->img, + $adj2 + round(($lm-$rm+$tm+$bm)/2), + $adj1 + round(($tm-$bm+$lm+$rm)/2), + $adj2 + round(($lm-$rm+$tm+$bm)/2), + $adj1 + round(($tm-$bm+$lm+$rm)/2), + $this->img->plotheight+1, + $this->img->plotwidth+1); + } + $this->img->Destroy(); + $this->img->SetCanvasH($oldimage); + } + + if( !$_csim ) { + $this->axis->Stroke($pos); + $this->axis->StrokeAngleLabels($pos,$this->iType); + } + + if( !$_csim ) { + $this->StrokePlotBox(); + $this->footer->Stroke($this->img); + + // The titles and legends never gets rotated so make sure + // that the angle is 0 before stroking them + $aa = $this->img->SetAngle(0); + $this->StrokeTitles(); + } + + for($i=0; $i < count($this->plots) ; ++$i ) { + $this->plots[$i]->Legend($this); + } + + $this->legend->Stroke($this->img); + + if( !$_csim ) { + + $this->StrokeTexts(); + $this->img->SetAngle($aa); + + // Draw an outline around the image map + if(_JPG_DEBUG) + $this->DisplayClientSideaImageMapAreas(); + + // If the filename is given as the special "__handle" + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); + } + } + } +} + + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_radar.php b/web/public_php/admin/jpgraph/jpgraph_radar.php index d08ca0d11..1d3de6286 100644 --- a/web/public_php/admin/jpgraph/jpgraph_radar.php +++ b/web/public_php/admin/jpgraph/jpgraph_radar.php @@ -1,647 +1,861 @@ -GetMinVal(); - $limit = $aScale->GetMaxVal(); - $nextMajor = 10*$start; - $step = $nextMajor / 10.0; - $count=1; - - $ticklen_maj=5; - $dx_maj=round(sin($aAxisAngle)*$ticklen_maj); - $dy_maj=round(cos($aAxisAngle)*$ticklen_maj); - $ticklen_min=3; - $dx_min=round(sin($aAxisAngle)*$ticklen_min); - $dy_min=round(cos($aAxisAngle)*$ticklen_min); - - $aMajPos=array(); - $aMajLabel=array(); - - if( $this->supress_first ) - $aMajLabel[]=""; - else - $aMajLabel[]=$start; - $yr=$aScale->RelTranslate($start); - $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; - $yt=$aPos-round($yr*sin($aAxisAngle)); - $aMajPos[]=$xt+2*$dx_maj; - $aMajPos[]=$yt-$aImg->GetFontheight()/2; - $grid[]=$xt; - $grid[]=$yt; - - $aImg->SetLineWeight($this->weight); - - for($y=$start; $y<=$limit; $y+=$step,++$count ) { - $yr=$aScale->RelTranslate($y); - $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; - $yt=$aPos-round($yr*sin($aAxisAngle)); - if( $count % 10 == 0 ) { - $grid[]=$xt; - $grid[]=$yt; - $aMajPos[]=$xt+2*$dx_maj; - $aMajPos[]=$yt-$aImg->GetFontheight()/2; - if( !$this->supress_tickmarks ) { - if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor); - $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj); - if( $this->majcolor!="" ) $aImg->PopColor(); - } - if( $this->label_formfunc != "" ) { - $f=$this->label_formfunc; - $l = call_user_func($f,$nextMajor); - } - else - $l = $nextMajor; - $aMajLabel[]=$l; - $nextMajor *= 10; - $step *= 10; - $count=1; - } - else - if( !$this->supress_minor_tickmarks ) { - if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor); - $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min); - if( $this->mincolor!="" ) $aImg->PopColor(); - } - } - } -} - -class RadarLinearTicks extends LinearTicks { -//--------------- -// CONSTRUCTOR - function RadarLinearTicks() { - // Empty - } - -//--------------- -// PUBLIC METHODS - - // TODO: Add argument grid - function Stroke(&$aImg,&$grid,$aPos,$aAxisAngle,&$aScale,&$aMajPos,&$aMajLabel) { - // Prepare to draw linear ticks - $maj_step_abs = abs($aScale->scale_factor*$this->major_step); - $min_step_abs = abs($aScale->scale_factor*$this->minor_step); - $nbrmaj = floor(($aScale->world_abs_size)/$maj_step_abs); - $nbrmin = floor(($aScale->world_abs_size)/$min_step_abs); - $skip = round($nbrmin/$nbrmaj); // Don't draw minor ontop of major - - // Draw major ticks - $ticklen2=$this->major_abs_size; - $dx=round(sin($aAxisAngle)*$ticklen2); - $dy=round(cos($aAxisAngle)*$ticklen2); - $label=$aScale->scale[0]+$this->major_step; - - $aImg->SetLineWeight($this->weight); - - for($i=1; $i<=$nbrmaj; ++$i) { - $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; - $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle)); - - if( $this->label_formfunc != "" ) { - $f=$this->label_formfunc; - $l = call_user_func($f,$label); - } - else - $l = $label; - - $aMajLabel[]=$l; - $label += $this->major_step; - $grid[]=$xt; - $grid[]=$yt; - $aMajPos[($i-1)*2]=$xt+2*$dx; - $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2; - if( !$this->supress_tickmarks ) { - if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor); - $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); - if( $this->majcolor!="" ) $aImg->PopColor(); - } - } - - // Draw minor ticks - $ticklen2=$this->minor_abs_size; - $dx=round(sin($aAxisAngle)*$ticklen2); - $dy=round(cos($aAxisAngle)*$ticklen2); - if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { - if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor); - for($i=1; $i<=$nbrmin; ++$i) { - if( ($i % $skip) == 0 ) continue; - $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; - $yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle)); - $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); - } - if( $this->mincolor!="" ) $aImg->PopColor(); - } - } -} - - - -//=================================================== -// CLASS RadarAxis -// Description: Implements axis for the radar graph -//=================================================== -class RadarAxis extends Axis { - var $title_color="navy"; - var $title=null; -//--------------- -// CONSTRUCTOR - function RadarAxis(&$img,&$aScale,$color=array(0,0,0)) { - parent::Axis($img,$aScale,$color); - $this->len=$img->plotheight; - $this->title = new Text(); - $this->title->SetFont(FF_FONT1,FS_BOLD); - $this->color = array(0,0,0); - } -//--------------- -// PUBLIC METHODS - function SetTickLabels($l) { - $this->ticks_label = $l; - } - - - // Stroke the axis - // $pos = Vertical position of axis - // $aAxisAngle = Axis angle - // $grid = Returns an array with positions used to draw the grid - // $lf = Label flag, TRUE if the axis should have labels - function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) { - $this->img->SetColor($this->color); - - // Determine end points for the axis - $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]); - $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle)); - - // Draw axis - $this->img->SetColor($this->color); - $this->img->SetLineWeight($this->weight); - if( !$this->hide ) - $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y); - - $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel); - - // Draw labels - if( $lf && !$this->hide ) { - $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); - $this->img->SetTextAlign("left","top"); - $this->img->SetColor($this->label_color); - - // majpos contains (x,y) coordinates for labels - if( ! $this->hide_labels ) { - $n = floor(count($majpos)/2); - for($i=0; $i < $n; ++$i) { - if( $this->ticks_label != null && isset($this->ticks_label[$i]) ) - $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]); - else - $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]); - } - } - } - $this->_StrokeAxisTitle($pos,$aAxisAngle,$title); - } -//--------------- -// PRIVATE METHODS - - function _StrokeAxisTitle($pos,$aAxisAngle,$title) { - $this->title->Set($title); - $marg=6+$this->title->margin; - $xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]); - $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle)); - - // Position the axis title. - // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text - // that intersects with the extension of the corresponding axis. The code looks a little - // bit messy but this is really the only way of having a reasonable position of the - // axis titles. - if( $this->title->iWordwrap > 0 ) { - $title = wordwrap($title,$this->title->iWordwrap,"\n"); - } - - $h=$this->img->GetTextHeight($title)*1.2; - $w=$this->img->GetTextWidth($title)*1.2; - while( $aAxisAngle > 2*M_PI ) $aAxisAngle -= 2*M_PI; - - if( $aAxisAngle>=7*M_PI/4 || $aAxisAngle <= M_PI/4 ) $dx=0; - if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI; - if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1; - if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dx=(1-($aAxisAngle-M_PI*5/4)*2/M_PI); - - if( $aAxisAngle>=7*M_PI/4 ) $dy=(($aAxisAngle-M_PI)-3*M_PI/4)*2/M_PI; - if( $aAxisAngle<=M_PI/4 ) $dy=(1-$aAxisAngle*2/M_PI); - if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1; - if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dy=(1-($aAxisAngle-3*M_PI/4)*2/M_PI); - if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0; - - if( !$this->hide ) { - $this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title); - } - } - - -} // Class - - -//=================================================== -// CLASS RadarGrid -// Description: Draws grid for the radar graph -//=================================================== -class RadarGrid extends Grid { -//------------ -// CONSTRUCTOR - function RadarGrid() { - } - -//---------------- -// PRIVATE METHODS - function Stroke(&$img,&$grid) { - if( !$this->show ) return; - $nbrticks = count($grid[0])/2; - $nbrpnts = count($grid); - $img->SetColor($this->grid_color); - $img->SetLineWeight($this->weight); - for($i=0; $i<$nbrticks; ++$i) { - for($j=0; $j<$nbrpnts; ++$j) { - $pnts[$j*2]=$grid[$j][$i*2]; - $pnts[$j*2+1]=$grid[$j][$i*2+1]; - } - for($k=0; $k<$nbrpnts; ++$k ){ - $l=($k+1)%$nbrpnts; - if( $this->type == "solid" ) - $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]); - elseif( $this->type == "dotted" ) - $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6); - elseif( $this->type == "dashed" ) - $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4); - elseif( $this->type == "longdashed" ) - $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6); - } - $pnts=array(); - } - } -} // Class - - -//=================================================== -// CLASS RadarPlot -// Description: Plot a radarplot -//=================================================== -class RadarPlot { - var $data=array(); - var $fill=false, $fill_color=array(200,170,180); - var $color=array(0,0,0); - var $legend=""; - var $weight=1; - var $linestyle='solid'; - var $mark=null; -//--------------- -// CONSTRUCTOR - function RadarPlot($data) { - $this->data = $data; - $this->mark = new PlotMark(); - } - -//--------------- -// PUBLIC METHODS - function Min() { - return Min($this->data); - } - - function Max() { - return Max($this->data); - } - - function SetLegend($legend) { - $this->legend=$legend; - } - - function SetLineStyle($aStyle) { - $this->linestyle=$aStyle; - } - - function SetLineWeight($w) { - $this->weight=$w; - } - - function SetFillColor($aColor) { - $this->fill_color = $aColor; - $this->fill = true; - } - - function SetFill($f=true) { - $this->fill = $f; - } - - function SetColor($aColor,$aFillColor=false) { - $this->color = $aColor; - if( $aFillColor ) { - $this->SetFillColor($aFillColor); - $this->fill = true; - } - } - - function GetCSIMareas() { - JpGraphError::RaiseL(18001); -//("Client side image maps not supported for RadarPlots."); - } - - function Stroke(&$img, $pos, &$scale, $startangle) { - $nbrpnts = count($this->data); - $astep=2*M_PI/$nbrpnts; - $a=$startangle; - - // Rotate each point to the correct axis-angle - // TODO: Update for LogScale - for($i=0; $i<$nbrpnts; ++$i) { - //$c=$this->data[$i]; - $cs=$scale->RelTranslate($this->data[$i]); - $x=round($cs*cos($a)+$scale->scale_abs[0]); - $y=round($pos-$cs*sin($a)); - /* - $c=log10($c); - $x=round(($c-$scale->scale[0])*$scale->scale_factor*cos($a)+$scale->scale_abs[0]); - $y=round($pos-($c-$scale->scale[0])*$scale->scale_factor*sin($a)); - */ - $pnts[$i*2]=$x; - $pnts[$i*2+1]=$y; - $a += $astep; - } - if( $this->fill ) { - $img->SetColor($this->fill_color); - $img->FilledPolygon($pnts); - } - $img->SetLineWeight($this->weight); - $img->SetColor($this->color); - $img->SetLineStyle($this->linestyle); - $pnts[]=$pnts[0]; - $pnts[]=$pnts[1]; - $img->Polygon($pnts); - $img->SetLineStyle('solid'); // Reset line style to default - // Add plotmarks on top - if( $this->mark->show ) { - for($i=0; $i < $nbrpnts; ++$i) { - $this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]); - } - } - - } - -//--------------- -// PRIVATE METHODS - function GetCount() { - return count($this->data); - } - - function Legend(&$graph) { - if( $this->legend=="" ) return; - if( $this->fill ) - $graph->legend->Add($this->legend,$this->fill_color,$this->mark); - else - $graph->legend->Add($this->legend,$this->color,$this->mark); - } - -} // Class - -//=================================================== -// CLASS RadarGraph -// Description: Main container for a radar graph -//=================================================== -class RadarGraph extends Graph { - var $posx; - var $posy; - var $len; - var $plots=null, $axis_title=null; - var $grid,$axis=null; -//--------------- -// CONSTRUCTOR - function RadarGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { - $this->Graph($width,$height,$cachedName,$timeout,$inline); - $this->posx=$width/2; - $this->posy=$height/2; - $this->len=min($width,$height)*0.35; - $this->SetColor(array(255,255,255)); - $this->SetTickDensity(TICKD_NORMAL); - $this->SetScale("lin"); - $this->SetGridDepth(DEPTH_FRONT); - - } - -//--------------- -// PUBLIC METHODS - function SupressTickMarks($f=true) { - if( ERR_DEPRECATED ) - JpGraphError::RaiseL(18002); -//('RadarGraph::SupressTickMarks() is deprecated. Use HideTickMarks() instead.'); - $this->axis->scale->ticks->SupressTickMarks($f); - } - - function HideTickMarks($aFlag=true) { - $this->axis->scale->ticks->SupressTickMarks($aFlag); - } - - function ShowMinorTickmarks($aFlag=true) { - $this->yscale->ticks->SupressMinorTickMarks(!$aFlag); - } - - function SetScale($axtype,$ymin=1,$ymax=1) { - if( $axtype != "lin" && $axtype != "log" ) { - JpGraphError::RaiseL(18003,$axtype); -//("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\""); - } - if( $axtype=="lin" ) { - $this->yscale = new LinearScale($ymin,$ymax); - $this->yscale->ticks = new RadarLinearTicks(); - $this->yscale->ticks->SupressMinorTickMarks(); - } - elseif( $axtype=="log" ) { - $this->yscale = new LogScale($ymin,$ymax); - $this->yscale->ticks = new RadarLogTicks(); - } - - $this->axis = new RadarAxis($this->img,$this->yscale); - $this->grid = new RadarGrid(); - } - - function SetSize($aSize) { - if( $aSize < 0.1 || $aSize>1 ) - JpGraphError::RaiseL(18004,$aSize); -//("Radar Plot size must be between 0.1 and 1. (Your value=$s)"); - $this->len=min($this->img->width,$this->img->height)*$aSize/2; - } - - function SetPlotSize($aSize) { - $this->SetSize($aSize); - } - - function SetTickDensity($densy=TICKD_NORMAL) { - $this->ytick_factor=25; - switch( $densy ) { - case TICKD_DENSE: - $this->ytick_factor=12; - break; - case TICKD_NORMAL: - $this->ytick_factor=25; - break; - case TICKD_SPARSE: - $this->ytick_factor=40; - break; - case TICKD_VERYSPARSE: - $this->ytick_factor=70; - break; - default: - JpGraphError::RaiseL(18005,$densy); -//("RadarPlot Unsupported Tick density: $densy"); - } - } - - function SetPos($px,$py=0.5) { - $this->SetCenter($px,$py); - } - - function SetCenter($px,$py=0.5) { - assert($px > 0 && $py > 0 ); - $this->posx=$this->img->width*$px; - $this->posy=$this->img->height*$py; - } - - function SetColor($c) { - $this->SetMarginColor($c); - } - - function SetTitles($title) { - $this->axis_title = $title; - } - - function Add(&$splot) { - $this->plots[]=$splot; - } - - function GetPlotsYMinMax() { - $min=$this->plots[0]->Min(); - $max=$this->plots[0]->Max(); - foreach( $this->plots as $p ) { - $max=max($max,$p->Max()); - $min=min($min,$p->Min()); - } - if( $min < 0 ) - JpGraphError::RaiseL(18006,$min); -//("Minimum data $min (Radar plots should only be used when all data points > 0)"); - return array($min,$max); - } - - // Stroke the Radar graph - function Stroke($aStrokeFileName="") { - $n = count($this->plots); - // Set Y-scale - if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) { - list($min,$max) = $this->GetPlotsYMinMax(); - $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor); - } - // Set start position end length of scale (in absolute pixels) - $this->yscale->SetConstants($this->posx,$this->len); - - // We need as many axis as there are data points - $nbrpnts=$this->plots[0]->GetCount(); - - // If we have no titles just number the axis 1,2,3,... - if( $this->axis_title==null ) { - for($i=0; $i < $nbrpnts; ++$i ) - $this->axis_title[$i] = $i+1; - } - elseif(count($this->axis_title)<$nbrpnts) - JpGraphError::RaiseL(18007); -//("Number of titles does not match number of points in plot."); - for($i=0; $i < $n; ++$i ) - if( $nbrpnts != $this->plots[$i]->GetCount() ) - JpGraphError::RaiseL(18008); -//("Each radar plot must have the same number of data points."); - - if( $this->background_image != "" ) { - $this->StrokeFrameBackground(); - } - else { - $this->StrokeFrame(); - } - $astep=2*M_PI/$nbrpnts; - - // Prepare legends - for($i=0; $i < $n; ++$i) - $this->plots[$i]->Legend($this); - $this->legend->Stroke($this->img); - $this->footer->Stroke($this->img); - - if( $this->grid_depth == DEPTH_BACK ) { - // Draw axis and grid - for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) { - $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0); - } - } - - // Plot points - $a=M_PI/2; - for($i=0; $i < $n; ++$i ) - $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a); - - if( $this->grid_depth != DEPTH_BACK ) { - // Draw axis and grid - for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) { - $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0); - } - } - $this->grid->Stroke($this->img,$grid); - $this->StrokeTitles(); - - // Stroke texts - if( $this->texts != null ) { - foreach( $this->texts as $t) - $t->Stroke($this->img); - } - - // Should we do any final image transformation - if( $this->iImgTrans ) { - if( !class_exists('ImgTrans') ) { - require_once('jpgraph_imgtrans.php'); - } - - $tform = new ImgTrans($this->img->img); - $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, - $this->iImgTransDirection,$this->iImgTransHighQ, - $this->iImgTransMinSize,$this->iImgTransFillColor, - $this->iImgTransBorder); - } - - // If the filename is given as the special "__handle" - // then the image handler is returned and the image is NOT - // streamed back - if( $aStrokeFileName == _IMG_HANDLER ) { - return $this->img->img; - } - else { - // Finally stream the generated picture - $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, - $aStrokeFileName); - } - } -} // Class - -/* EOF */ -?> +GetMinVal(); + $limit = $aScale->GetMaxVal(); + $nextMajor = 10*$start; + $step = $nextMajor / 10.0; + $count=1; + + $ticklen_maj=5; + $dx_maj=round(sin($aAxisAngle)*$ticklen_maj); + $dy_maj=round(cos($aAxisAngle)*$ticklen_maj); + $ticklen_min=3; + $dx_min=round(sin($aAxisAngle)*$ticklen_min); + $dy_min=round(cos($aAxisAngle)*$ticklen_min); + + $aMajPos=array(); + $aMajLabel=array(); + + if( $this->supress_first ) { + $aMajLabel[] = ''; + } + else { + $aMajLabel[]=$start; + } + + $yr=$aScale->RelTranslate($start); + $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; + $yt=$aPos-round($yr*sin($aAxisAngle)); + $aMajPos[]=$xt+2*$dx_maj; + $aMajPos[]=$yt-$aImg->GetFontheight()/2; + $grid[]=$xt; + $grid[]=$yt; + + $aImg->SetLineWeight($this->weight); + + for($y=$start; $y<=$limit; $y+=$step,++$count ) { + $yr=$aScale->RelTranslate($y); + $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; + $yt=$aPos-round($yr*sin($aAxisAngle)); + if( $count % 10 == 0 ) { + $grid[]=$xt; + $grid[]=$yt; + $aMajPos[]=$xt+2*$dx_maj; + $aMajPos[]=$yt-$aImg->GetFontheight()/2; + if( !$this->supress_tickmarks ) { + if( $this->majcolor != '' ) { + $aImg->PushColor($this->majcolor); + } + $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj); + if( $this->majcolor != '' ) { + $aImg->PopColor(); + } + } + if( $this->label_formfunc != '' ) { + $f=$this->label_formfunc; + $l = call_user_func($f,$nextMajor); + } + else { + $l = $nextMajor; + } + + $aMajLabel[]=$l; + $nextMajor *= 10; + $step *= 10; + $count=1; + } + else { + if( !$this->supress_minor_tickmarks ) { + if( $this->mincolor != '' ) { + $aImg->PushColor($this->mincolor); + } + $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min); + if( $this->mincolor != '' ) { + $aImg->PopColor(); + } + } + } + } + } +} + +//=================================================== +// CLASS RadarLinear +// Description: Linear ticks +//=================================================== +class RadarLinearTicks extends Ticks { + + private $minor_step=1, $major_step=2; + private $xlabel_offset=0,$xtick_offset=0; + + function __construct() { + // Empty + } + + // Return major step size in world coordinates + function GetMajor() { + return $this->major_step; + } + + // Return minor step size in world coordinates + function GetMinor() { + return $this->minor_step; + } + + // Set Minor and Major ticks (in world coordinates) + function Set($aMajStep,$aMinStep=false) { + if( $aMinStep==false ) { + $aMinStep=$aMajStep; + } + + if( $aMajStep <= 0 || $aMinStep <= 0 ) { + JpGraphError::RaiseL(25064); + //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."); + } + + $this->major_step=$aMajStep; + $this->minor_step=$aMinStep; + $this->is_set = true; + } + + function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) { + // Prepare to draw linear ticks + $maj_step_abs = abs($aScale->scale_factor*$this->major_step); + $min_step_abs = abs($aScale->scale_factor*$this->minor_step); + $nbrmaj = round($aScale->world_abs_size/$maj_step_abs); + $nbrmin = round($aScale->world_abs_size/$min_step_abs); + $skip = round($nbrmin/$nbrmaj); // Don't draw minor on top of major + + // Draw major ticks + $ticklen2=$this->major_abs_size; + $dx=round(sin($aAxisAngle)*$ticklen2); + $dy=round(cos($aAxisAngle)*$ticklen2); + $label=$aScale->scale[0]+$this->major_step; + + $aImg->SetLineWeight($this->weight); + + $aMajPos = array(); + $aMajLabel = array(); + + for($i=1; $i<=$nbrmaj; ++$i) { + $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; + $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle)); + + if( $this->label_formfunc != '' ) { + $f=$this->label_formfunc; + $l = call_user_func($f,$label); + } + else { + $l = $label; + } + + $aMajLabel[]=$l; + $label += $this->major_step; + $grid[]=$xt; + $grid[]=$yt; + $aMajPos[($i-1)*2]=$xt+2*$dx; + $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2; + if( !$this->supress_tickmarks ) { + if( $this->majcolor != '' ) { + $aImg->PushColor($this->majcolor); + } + $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); + if( $this->majcolor != '' ) { + $aImg->PopColor(); + } + } + } + + // Draw minor ticks + $ticklen2=$this->minor_abs_size; + $dx=round(sin($aAxisAngle)*$ticklen2); + $dy=round(cos($aAxisAngle)*$ticklen2); + if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { + if( $this->mincolor != '' ) { + $aImg->PushColor($this->mincolor); + } + for($i=1; $i<=$nbrmin; ++$i) { + if( ($i % $skip) == 0 ) { + continue; + } + $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; + $yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle)); + $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); + } + if( $this->mincolor != '' ) { + $aImg->PopColor(); + } + } + } +} + + +//=================================================== +// CLASS RadarAxis +// Description: Implements axis for the radar graph +//=================================================== +class RadarAxis extends AxisPrototype { + public $title=null; + private $title_color='navy'; + private $len=0; + + function __construct($img,$aScale,$color=array(0,0,0)) { + parent::__construct($img,$aScale,$color); + $this->len = $img->plotheight; + $this->title = new Text(); + $this->title->SetFont(FF_FONT1,FS_BOLD); + $this->color = array(0,0,0); + } + + // Stroke the axis + // $pos = Vertical position of axis + // $aAxisAngle = Axis angle + // $grid = Returns an array with positions used to draw the grid + // $lf = Label flag, TRUE if the axis should have labels + function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) { + $this->img->SetColor($this->color); + + // Determine end points for the axis + $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]); + $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle)); + + // Draw axis + $this->img->SetColor($this->color); + $this->img->SetLineWeight($this->weight); + if( !$this->hide ) { + $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y); + } + + $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel); + $ncolor=0; + if( isset($this->ticks_label_colors) ) { + $ncolor=count($this->ticks_label_colors); + } + + // Draw labels + if( $lf && !$this->hide ) { + $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); + $this->img->SetTextAlign('left','top'); + $this->img->SetColor($this->label_color); + + // majpos contains (x,y) coordinates for labels + if( ! $this->hide_labels ) { + $n = floor(count($majpos)/2); + for($i=0; $i < $n; ++$i) { + // Set specific label color if specified + if( $ncolor > 0 ) { + $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]); + } + + if( $this->ticks_label != null && isset($this->ticks_label[$i]) ) { + $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]); + } + else { + $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]); + } + } + } + } + $this->_StrokeAxisTitle($pos,$aAxisAngle,$title); + } + + function _StrokeAxisTitle($pos,$aAxisAngle,$title) { + $this->title->Set($title); + $marg=6+$this->title->margin; + $xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]); + $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle)); + + // Position the axis title. + // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text + // that intersects with the extension of the corresponding axis. The code looks a little + // bit messy but this is really the only way of having a reasonable position of the + // axis titles. + if( $this->title->iWordwrap > 0 ) { + $title = wordwrap($title,$this->title->iWordwrap,"\n"); + } + + $h=$this->img->GetTextHeight($title)*1.2; + $w=$this->img->GetTextWidth($title)*1.2; + + while( $aAxisAngle > 2*M_PI ) + $aAxisAngle -= 2*M_PI; + + // Around 3 a'clock + if( $aAxisAngle>=7*M_PI/4 || $aAxisAngle <= M_PI/4 ) $dx=-0.15; // Small trimming to make the dist to the axis more even + + // Around 12 a'clock + if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI; + + // Around 9 a'clock + if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1; + + // Around 6 a'clock + if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dx=(1-($aAxisAngle-M_PI*5/4)*2/M_PI); + + if( $aAxisAngle>=7*M_PI/4 ) $dy=(($aAxisAngle-M_PI)-3*M_PI/4)*2/M_PI; + if( $aAxisAngle<=M_PI/12 ) $dy=(0.5-$aAxisAngle*2/M_PI); + if( $aAxisAngle<=M_PI/4 && $aAxisAngle > M_PI/12) $dy=(1-$aAxisAngle*2/M_PI); + if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1; + if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dy=(1-($aAxisAngle-3*M_PI/4)*2/M_PI); + if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0; + + if( !$this->hide ) { + $this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title); + } + } + +} // Class + + +//=================================================== +// CLASS RadarGrid +// Description: Draws grid for the radar graph +//=================================================== +class RadarGrid { //extends Grid { + private $type='solid'; + private $grid_color='#DDDDDD'; + private $show=false, $weight=1; + + function __construct() { + // Empty + } + + function SetColor($aMajColor) { + $this->grid_color = $aMajColor; + } + + function SetWeight($aWeight) { + $this->weight=$aWeight; + } + + // Specify if grid should be dashed, dotted or solid + function SetLineStyle($aType) { + $this->type = $aType; + } + + // Decide if both major and minor grid should be displayed + function Show($aShowMajor=true) { + $this->show=$aShowMajor; + } + + function Stroke($img,$grid) { + if( !$this->show ) { + return; + } + + $nbrticks = count($grid[0])/2; + $nbrpnts = count($grid); + $img->SetColor($this->grid_color); + $img->SetLineWeight($this->weight); + + for($i=0; $i<$nbrticks; ++$i) { + for($j=0; $j<$nbrpnts; ++$j) { + $pnts[$j*2]=$grid[$j][$i*2]; + $pnts[$j*2+1]=$grid[$j][$i*2+1]; + } + for($k=0; $k<$nbrpnts; ++$k ){ + $l=($k+1)%$nbrpnts; + if( $this->type == 'solid' ) + $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]); + elseif( $this->type == 'dotted' ) + $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6); + elseif( $this->type == 'dashed' ) + $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4); + elseif( $this->type == 'longdashed' ) + $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6); + } + $pnts=array(); + } + } +} // Class + + +//=================================================== +// CLASS RadarPlot +// Description: Plot a radarplot +//=================================================== +class RadarPlot { + public $mark=null; + public $legend=''; + public $legendcsimtarget=''; + public $legendcsimalt=''; + public $csimtargets=array(); // Array of targets for CSIM + public $csimareas=""; // Resultant CSIM area tags + public $csimalts=null; // ALT:s for corresponding target + private $data=array(); + private $fill=false, $fill_color=array(200,170,180); + private $color=array(0,0,0); + private $weight=1; + private $linestyle='solid'; + + //--------------- + // CONSTRUCTOR + function __construct($data) { + $this->data = $data; + $this->mark = new PlotMark(); + } + + function Min() { + return Min($this->data); + } + + function Max() { + return Max($this->data); + } + + function SetLegend($legend) { + $this->legend=$legend; + } + + function SetLineStyle($aStyle) { + $this->linestyle=$aStyle; + } + + function SetLineWeight($w) { + $this->weight=$w; + } + + function SetFillColor($aColor) { + $this->fill_color = $aColor; + $this->fill = true; + } + + function SetFill($f=true) { + $this->fill = $f; + } + + function SetColor($aColor,$aFillColor=false) { + $this->color = $aColor; + if( $aFillColor ) { + $this->SetFillColor($aFillColor); + $this->fill = true; + } + } + + // Set href targets for CSIM + function SetCSIMTargets($aTargets,$aAlts=null) { + $this->csimtargets=$aTargets; + $this->csimalts=$aAlts; + } + + // Get all created areas + function GetCSIMareas() { + return $this->csimareas; + } + + function Stroke($img, $pos, $scale, $startangle) { + $nbrpnts = count($this->data); + $astep=2*M_PI/$nbrpnts; + $a=$startangle; + + for($i=0; $i<$nbrpnts; ++$i) { + + // Rotate each non null point to the correct axis-angle + $cs=$scale->RelTranslate($this->data[$i]); + $x=round($cs*cos($a)+$scale->scale_abs[0]); + $y=round($pos-$cs*sin($a)); + + $pnts[$i*2]=$x; + $pnts[$i*2+1]=$y; + + // If the next point is null then we draw this polygon segment + // to the center, skip the next and draw the next segment from + // the center up to the point on the axis with the first non-null + // value and continues from that point. Some additoinal logic is necessary + // to handle the boundary conditions + if( $i < $nbrpnts-1 ) { + if( is_null($this->data[$i+1]) ) { + $cs = 0; + $x=round($cs*cos($a)+$scale->scale_abs[0]); + $y=round($pos-$cs*sin($a)); + $pnts[$i*2]=$x; + $pnts[$i*2+1]=$y; + $a += $astep; + } + } + + $a += $astep; + } + + if( $this->fill ) { + $img->SetColor($this->fill_color); + $img->FilledPolygon($pnts); + } + + $img->SetLineWeight($this->weight); + $img->SetColor($this->color); + $img->SetLineStyle($this->linestyle); + $pnts[] = $pnts[0]; + $pnts[] = $pnts[1]; + $img->Polygon($pnts); + $img->SetLineStyle('solid'); // Reset line style to default + + // Add plotmarks on top + if( $this->mark->show ) { + for($i=0; $i < $nbrpnts; ++$i) { + if( isset($this->csimtargets[$i]) ) { + $this->mark->SetCSIMTarget($this->csimtargets[$i]); + $this->mark->SetCSIMAlt($this->csimalts[$i]); + $this->mark->SetCSIMAltVal($pnts[$i*2], $pnts[$i*2+1]); + $this->mark->Stroke($img, $pnts[$i*2], $pnts[$i*2+1]); + $this->csimareas .= $this->mark->GetCSIMAreas(); + } + else { + $this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]); + } + } + } + + } + + function GetCount() { + return count($this->data); + } + + function Legend($graph) { + if( $this->legend == '' ) { + return; + } + if( $this->fill ) { + $graph->legend->Add($this->legend,$this->fill_color,$this->mark); + } else { + $graph->legend->Add($this->legend,$this->color,$this->mark); + } + } + +} // Class + +//=================================================== +// CLASS RadarGraph +// Description: Main container for a radar graph +//=================================================== +class RadarGraph extends Graph { + public $grid,$axis=null; + private $posx,$posy; + private $len; + private $axis_title=null; + + function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { + parent::__construct($width,$height,$cachedName,$timeout,$inline); + $this->posx = $width/2; + $this->posy = $height/2; + $this->len = min($width,$height)*0.35; + $this->SetColor(array(255,255,255)); + $this->SetTickDensity(TICKD_NORMAL); + $this->SetScale('lin'); + $this->SetGridDepth(DEPTH_FRONT); + } + + function HideTickMarks($aFlag=true) { + $this->axis->scale->ticks->SupressTickMarks($aFlag); + } + + function ShowMinorTickmarks($aFlag=true) { + $this->yscale->ticks->SupressMinorTickMarks(!$aFlag); + } + + function SetScale($axtype,$ymin=1,$ymax=1,$dummy1=null,$dumy2=null) { + if( $axtype != 'lin' && $axtype != 'log' ) { + JpGraphError::RaiseL(18003,$axtype); + //("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\""); + } + if( $axtype == 'lin' ) { + $this->yscale = new LinearScale($ymin,$ymax); + $this->yscale->ticks = new RadarLinearTicks(); + $this->yscale->ticks->SupressMinorTickMarks(); + } + elseif( $axtype == 'log' ) { + $this->yscale = new LogScale($ymin,$ymax); + $this->yscale->ticks = new RadarLogTicks(); + } + + $this->axis = new RadarAxis($this->img,$this->yscale); + $this->grid = new RadarGrid(); + } + + function SetSize($aSize) { + if( $aSize < 0.1 || $aSize>1 ) { + JpGraphError::RaiseL(18004,$aSize); + //("Radar Plot size must be between 0.1 and 1. (Your value=$s)"); + } + $this->len=min($this->img->width,$this->img->height)*$aSize/2; + } + + function SetPlotSize($aSize) { + $this->SetSize($aSize); + } + + function SetTickDensity($densy=TICKD_NORMAL,$dummy1=null) { + $this->ytick_factor=25; + switch( $densy ) { + case TICKD_DENSE: + $this->ytick_factor=12; + break; + case TICKD_NORMAL: + $this->ytick_factor=25; + break; + case TICKD_SPARSE: + $this->ytick_factor=40; + break; + case TICKD_VERYSPARSE: + $this->ytick_factor=70; + break; + default: + JpGraphError::RaiseL(18005,$densy); + //("RadarPlot Unsupported Tick density: $densy"); + } + } + + function SetPos($px,$py=0.5) { + $this->SetCenter($px,$py); + } + + function SetCenter($px,$py=0.5) { + if( $px >= 0 && $px <= 1 ) { + $this->posx = $this->img->width*$px; + } + else { + $this->posx = $px; + } + if( $py >= 0 && $py <= 1 ) { + $this->posy = $this->img->height*$py; + } + else { + $this->posy = $py; + } + } + + function SetColor($aColor) { + $this->SetMarginColor($aColor); + } + + function SetTitles($aTitleArray) { + $this->axis_title = $aTitleArray; + } + + function Add($aPlot) { + if( $aPlot == null ) { + JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph."); + } + if( is_array($aPlot) && count($aPlot) > 0 ) { + $cl = $aPlot[0]; + } + else { + $cl = $aPlot; + } + + if( $cl instanceof Text ) $this->AddText($aPlot); + elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot); + else { + $this->plots[] = $aPlot; + } + } + + function GetPlotsYMinMax($aPlots) { + $min=$aPlots[0]->Min(); + $max=$aPlots[0]->Max(); + foreach( $this->plots as $p ) { + $max=max($max,$p->Max()); + $min=min($min,$p->Min()); + } + if( $min < 0 ) { + JpGraphError::RaiseL(18006,$min); + //("Minimum data $min (Radar plots should only be used when all data points > 0)"); + } + return array($min,$max); + } + + function StrokeIcons() { + if( $this->iIcons != null ) { + $n = count($this->iIcons); + for( $i=0; $i < $n; ++$i ) { + $this->iIcons[$i]->Stroke($this->img); + } + } + } + + function StrokeTexts() { + if( $this->texts != null ) { + $n = count($this->texts); + for( $i=0; $i < $n; ++$i ) { + $this->texts[$i]->Stroke($this->img); + } + } + } + + // Stroke the Radar graph + function Stroke($aStrokeFileName='') { + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // a best we can. Therefor you will see a lot of tests !$_csim in the + // code below. + $_csim = ( $aStrokeFileName === _CSIM_SPECIALFILE ); + + // We need to know if we have stroked the plot in the + // GetCSIMareas. Otherwise the CSIM hasn't been generated + // and in the case of GetCSIM called before stroke to generate + // CSIM without storing an image to disk GetCSIM must call Stroke. + $this->iHasStroked = true; + + $n = count($this->plots); + // Set Y-scale + + if( !$this->yscale->IsSpecified() && count($this->plots) > 0 ) { + list($min,$max) = $this->GetPlotsYMinMax($this->plots); + $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor); + } + elseif( $this->yscale->IsSpecified() && + ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) { + + // The tick calculation will use the user suplied min/max values to determine + // the ticks. If auto_ticks is false the exact user specifed min and max + // values will be used for the scale. + // If auto_ticks is true then the scale might be slightly adjusted + // so that the min and max values falls on an even major step. + $min = $this->yscale->scale[0]; + $max = $this->yscale->scale[1]; + $this->yscale->AutoScale($this->img,$min,$max, + $this->len/$this->ytick_factor, + $this->yscale->auto_ticks); + } + + // Set start position end length of scale (in absolute pixels) + $this->yscale->SetConstants($this->posx,$this->len); + + // We need as many axis as there are data points + $nbrpnts=$this->plots[0]->GetCount(); + + // If we have no titles just number the axis 1,2,3,... + if( $this->axis_title==null ) { + for($i=0; $i < $nbrpnts; ++$i ) { + $this->axis_title[$i] = $i+1; + } + } + elseif( count($this->axis_title) < $nbrpnts) { + JpGraphError::RaiseL(18007); + // ("Number of titles does not match number of points in plot."); + } + for( $i=0; $i < $n; ++$i ) { + if( $nbrpnts != $this->plots[$i]->GetCount() ) { + JpGraphError::RaiseL(18008); + //("Each radar plot must have the same number of data points."); + } + } + + if( !$_csim ) { + if( $this->background_image != '' ) { + $this->StrokeFrameBackground(); + } + else { + $this->StrokeFrame(); + $this->StrokeBackgroundGrad(); + } + } + $astep=2*M_PI/$nbrpnts; + + if( !$_csim ) { + if( $this->iIconDepth == DEPTH_BACK ) { + $this->StrokeIcons(); + } + + + // Prepare legends + for($i=0; $i < $n; ++$i) { + $this->plots[$i]->Legend($this); + } + $this->legend->Stroke($this->img); + $this->footer->Stroke($this->img); + } + + if( !$_csim ) { + if( $this->grid_depth == DEPTH_BACK ) { + // Draw axis and grid + for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) { + $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0); + } + $this->grid->Stroke($this->img,$grid); + } + if( $this->iIconDepth == DEPTH_BACK ) { + $this->StrokeIcons(); + } + + } + + // Plot points + $a=M_PI/2; + for($i=0; $i < $n; ++$i ) { + $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a); + } + + if( !$_csim ) { + if( $this->grid_depth != DEPTH_BACK ) { + // Draw axis and grid + for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) { + $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0); + } + $this->grid->Stroke($this->img,$grid); + } + + $this->StrokeTitles(); + $this->StrokeTexts(); + if( $this->iIconDepth == DEPTH_FRONT ) { + $this->StrokeIcons(); + } + } + + // Should we do any final image transformation + if( $this->iImgTrans && !$_csim ) { + if( !class_exists('ImgTrans',false) ) { + require_once('jpgraph_imgtrans.php'); + } + + $tform = new ImgTrans($this->img->img); + $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, + $this->iImgTransDirection,$this->iImgTransHighQ, + $this->iImgTransMinSize,$this->iImgTransFillColor, + $this->iImgTransBorder); + } + + if( !$_csim ) { + // If the filename is given as the special "__handle" + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); + } + } + } +} // Class + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_regstat.php b/web/public_php/admin/jpgraph/jpgraph_regstat.php index c0fe94754..0f6c96be7 100644 --- a/web/public_php/admin/jpgraph/jpgraph_regstat.php +++ b/web/public_php/admin/jpgraph/jpgraph_regstat.php @@ -1,202 +1,215 @@ -y2 = array(); - $this->xdata = $xdata; - $this->ydata = $ydata; - - $n = count($ydata); - $this->n = $n; - if( $this->n !== count($xdata) ) { - JpGraphError::RaiseL(19001); -//('Spline: Number of X and Y coordinates must be the same'); - } - - // Natural spline 2:derivate == 0 at endpoints - $this->y2[0] = 0.0; - $this->y2[$n-1] = 0.0; - $delta[0] = 0.0; - - // Calculate 2:nd derivate - for($i=1; $i < $n-1; ++$i) { - $d = ($xdata[$i+1]-$xdata[$i-1]); - if( $d == 0 ) { - JpGraphError::RaiseL(19002); -//('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.'); - } - $s = ($xdata[$i]-$xdata[$i-1])/$d; - $p = $s*$this->y2[$i-1]+2.0; - $this->y2[$i] = ($s-1.0)/$p; - $delta[$i] = ($ydata[$i+1]-$ydata[$i])/($xdata[$i+1]-$xdata[$i]) - - ($ydata[$i]-$ydata[$i-1])/($xdata[$i]-$xdata[$i-1]); - $delta[$i] = (6.0*$delta[$i]/($xdata[$i+1]-$xdata[$i-1])-$s*$delta[$i-1])/$p; - } - - // Backward substitution - for( $j=$n-2; $j >= 0; --$j ) { - $this->y2[$j] = $this->y2[$j]*$this->y2[$j+1] + $delta[$j]; - } - } - - // Return the two new data vectors - function Get($num=50) { - $n = $this->n ; - $step = ($this->xdata[$n-1]-$this->xdata[0]) / ($num-1); - $xnew=array(); - $ynew=array(); - $xnew[0] = $this->xdata[0]; - $ynew[0] = $this->ydata[0]; - for( $j=1; $j < $num; ++$j ) { - $xnew[$j] = $xnew[0]+$j*$step; - $ynew[$j] = $this->Interpolate($xnew[$j]); - } - return array($xnew,$ynew); - } - - // Return a single interpolated Y-value from an x value - function Interpolate($xpoint) { - - $max = $this->n-1; - $min = 0; - - // Binary search to find interval - while( $max-$min > 1 ) { - $k = ($max+$min) / 2; - if( $this->xdata[$k] > $xpoint ) - $max=$k; - else - $min=$k; - } - - // Each interval is interpolated by a 3:degree polynom function - $h = $this->xdata[$max]-$this->xdata[$min]; - - if( $h == 0 ) { - JpGraphError::RaiseL(19002); -//('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.'); - } - - - $a = ($this->xdata[$max]-$xpoint)/$h; - $b = ($xpoint-$this->xdata[$min])/$h; - return $a*$this->ydata[$min]+$b*$this->ydata[$max]+ - (($a*$a*$a-$a)*$this->y2[$min]+($b*$b*$b-$b)*$this->y2[$max])*($h*$h)/6.0; - } -} - -//------------------------------------------------------------------------ -// CLASS Bezier -// Create a new data array from a number of control points -//------------------------------------------------------------------------ -class Bezier { -/** - * @author Thomas Despoix, openXtrem company - * @license released under QPL - * @abstract Bezier interoplated point generation, - * computed from control points data sets, based on Paul Bourke algorithm : - * http://astronomy.swin.edu.au/~pbourke/curves/bezier/ - */ - var $datax = array(); - var $datay = array(); - var $n=0; - - function Bezier($datax, $datay, $attraction_factor = 1) { - // Adding control point multiple time will raise their attraction power over the curve - $this->n = count($datax); - if( $this->n !== count($datay) ) { - JpGraphError::RaiseL(19003); -//('Bezier: Number of X and Y coordinates must be the same'); - } - $idx=0; - foreach($datax as $datumx) { - for ($i = 0; $i < $attraction_factor; $i++) { - $this->datax[$idx++] = $datumx; - } - } - $idx=0; - foreach($datay as $datumy) { - for ($i = 0; $i < $attraction_factor; $i++) { - $this->datay[$idx++] = $datumy; - } - } - } - - function Get($steps) { - $datax = array(); - $datay = array(); - for ($i = 0; $i < $steps; $i++) { - list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps); - $datax[] = $datumx; - $datay[] = $datumy; - } - - $datax[] = end($this->datax); - $datay[] = end($this->datay); - - return array($datax, $datay); - } - - function GetPoint($mu) { - $n = $this->n - 1; - $k = 0; - $kn = 0; - $nn = 0; - $nkn = 0; - $blend = 0.0; - $newx = 0.0; - $newy = 0.0; - - $muk = 1.0; - $munk = (double) pow(1-$mu,(double) $n); - - for ($k = 0; $k <= $n; $k++) { - $nn = $n; - $kn = $k; - $nkn = $n - $k; - $blend = $muk * $munk; - $muk *= $mu; - $munk /= (1-$mu); - while ($nn >= 1) { - $blend *= $nn; - $nn--; - if ($kn > 1) { - $blend /= (double) $kn; - $kn--; - } - if ($nkn > 1) { - $blend /= (double) $nkn; - $nkn--; - } - } - $newx += $this->datax[$k] * $blend; - $newy += $this->datay[$k] * $blend; - } - - return array($newx, $newy); - } -} - -// EOF -?> +y2 = array(); + $this->xdata = $xdata; + $this->ydata = $ydata; + + $n = count($ydata); + $this->n = $n; + if( $this->n !== count($xdata) ) { + JpGraphError::RaiseL(19001); + //('Spline: Number of X and Y coordinates must be the same'); + } + + // Natural spline 2:derivate == 0 at endpoints + $this->y2[0] = 0.0; + $this->y2[$n-1] = 0.0; + $delta[0] = 0.0; + + // Calculate 2:nd derivate + for($i=1; $i < $n-1; ++$i) { + $d = ($xdata[$i+1]-$xdata[$i-1]); + if( $d == 0 ) { + JpGraphError::RaiseL(19002); + //('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.'); + } + $s = ($xdata[$i]-$xdata[$i-1])/$d; + $p = $s*$this->y2[$i-1]+2.0; + $this->y2[$i] = ($s-1.0)/$p; + $delta[$i] = ($ydata[$i+1]-$ydata[$i])/($xdata[$i+1]-$xdata[$i]) - + ($ydata[$i]-$ydata[$i-1])/($xdata[$i]-$xdata[$i-1]); + $delta[$i] = (6.0*$delta[$i]/($xdata[$i+1]-$xdata[$i-1])-$s*$delta[$i-1])/$p; + } + + // Backward substitution + for( $j=$n-2; $j >= 0; --$j ) { + $this->y2[$j] = $this->y2[$j]*$this->y2[$j+1] + $delta[$j]; + } + } + + // Return the two new data vectors + function Get($num=50) { + $n = $this->n ; + $step = ($this->xdata[$n-1]-$this->xdata[0]) / ($num-1); + $xnew=array(); + $ynew=array(); + $xnew[0] = $this->xdata[0]; + $ynew[0] = $this->ydata[0]; + for( $j=1; $j < $num; ++$j ) { + $xnew[$j] = $xnew[0]+$j*$step; + $ynew[$j] = $this->Interpolate($xnew[$j]); + } + return array($xnew,$ynew); + } + + // Return a single interpolated Y-value from an x value + function Interpolate($xpoint) { + + $max = $this->n-1; + $min = 0; + + // Binary search to find interval + while( $max-$min > 1 ) { + $k = ($max+$min) / 2; + if( $this->xdata[$k] > $xpoint ) + $max=$k; + else + $min=$k; + } + + // Each interval is interpolated by a 3:degree polynom function + $h = $this->xdata[$max]-$this->xdata[$min]; + + if( $h == 0 ) { + JpGraphError::RaiseL(19002); + //('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.'); + } + + + $a = ($this->xdata[$max]-$xpoint)/$h; + $b = ($xpoint-$this->xdata[$min])/$h; + return $a*$this->ydata[$min]+$b*$this->ydata[$max]+ + (($a*$a*$a-$a)*$this->y2[$min]+($b*$b*$b-$b)*$this->y2[$max])*($h*$h)/6.0; + } +} + +//------------------------------------------------------------------------ +// CLASS Bezier +// Create a new data array from a number of control points +//------------------------------------------------------------------------ +class Bezier { + /** + * @author Thomas Despoix, openXtrem company + * @license released under QPL + * @abstract Bezier interoplated point generation, + * computed from control points data sets, based on Paul Bourke algorithm : + * http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html + */ + private $datax = array(); + private $datay = array(); + private $n=0; + + function __construct($datax, $datay, $attraction_factor = 1) { + // Adding control point multiple time will raise their attraction power over the curve + $this->n = count($datax); + if( $this->n !== count($datay) ) { + JpGraphError::RaiseL(19003); + //('Bezier: Number of X and Y coordinates must be the same'); + } + $idx=0; + foreach($datax as $datumx) { + for ($i = 0; $i < $attraction_factor; $i++) { + $this->datax[$idx++] = $datumx; + } + } + $idx=0; + foreach($datay as $datumy) { + for ($i = 0; $i < $attraction_factor; $i++) { + $this->datay[$idx++] = $datumy; + } + } + $this->n *= $attraction_factor; + } + + /** + * Return a set of data points that specifies the bezier curve with $steps points + * @param $steps Number of new points to return + * @return array($datax, $datay) + */ + function Get($steps) { + $datax = array(); + $datay = array(); + for ($i = 0; $i < $steps; $i++) { + list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps); + $datax[$i] = $datumx; + $datay[$i] = $datumy; + } + + $datax[] = end($this->datax); + $datay[] = end($this->datay); + + return array($datax, $datay); + } + + /** + * Return one point on the bezier curve. $mu is the position on the curve where $mu is in the + * range 0 $mu < 1 where 0 is tha start point and 1 is the end point. Note that every newly computed + * point depends on all the existing points + * + * @param $mu Position on the bezier curve + * @return array($x, $y) + */ + function GetPoint($mu) { + $n = $this->n - 1; + $k = 0; + $kn = 0; + $nn = 0; + $nkn = 0; + $blend = 0.0; + $newx = 0.0; + $newy = 0.0; + + $muk = 1.0; + $munk = (double) pow(1-$mu,(double) $n); + + for ($k = 0; $k <= $n; $k++) { + $nn = $n; + $kn = $k; + $nkn = $n - $k; + $blend = $muk * $munk; + $muk *= $mu; + $munk /= (1-$mu); + while ($nn >= 1) { + $blend *= $nn; + $nn--; + if ($kn > 1) { + $blend /= (double) $kn; + $kn--; + } + if ($nkn > 1) { + $blend /= (double) $nkn; + $nkn--; + } + } + $newx += $this->datax[$k] * $blend; + $newy += $this->datay[$k] * $blend; + } + + return array($newx, $newy); + } +} + +// EOF +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_rgb.inc.php b/web/public_php/admin/jpgraph/jpgraph_rgb.inc.php new file mode 100644 index 000000000..53892611e --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_rgb.inc.php @@ -0,0 +1,615 @@ +img = $aImg; + + // Conversion array between color names and RGB + $this->rgb_table = array( + 'aqua'=> array(0,255,255), + 'lime'=> array(0,255,0), + 'teal'=> array(0,128,128), + 'whitesmoke'=>array(245,245,245), + 'gainsboro'=>array(220,220,220), + 'oldlace'=>array(253,245,230), + 'linen'=>array(250,240,230), + 'antiquewhite'=>array(250,235,215), + 'papayawhip'=>array(255,239,213), + 'blanchedalmond'=>array(255,235,205), + 'bisque'=>array(255,228,196), + 'peachpuff'=>array(255,218,185), + 'navajowhite'=>array(255,222,173), + 'moccasin'=>array(255,228,181), + 'cornsilk'=>array(255,248,220), + 'ivory'=>array(255,255,240), + 'lemonchiffon'=>array(255,250,205), + 'seashell'=>array(255,245,238), + 'mintcream'=>array(245,255,250), + 'azure'=>array(240,255,255), + 'aliceblue'=>array(240,248,255), + 'lavender'=>array(230,230,250), + 'lavenderblush'=>array(255,240,245), + 'mistyrose'=>array(255,228,225), + 'white'=>array(255,255,255), + 'black'=>array(0,0,0), + 'darkslategray'=>array(47,79,79), + 'dimgray'=>array(105,105,105), + 'slategray'=>array(112,128,144), + 'lightslategray'=>array(119,136,153), + 'gray'=>array(190,190,190), + 'lightgray'=>array(211,211,211), + 'midnightblue'=>array(25,25,112), + 'navy'=>array(0,0,128), + 'indigo'=>array(75,0,130), + 'electricindigo'=>array(102,0,255), + 'deepindigo'=>array(138,43,226), + 'pigmentindigo'=>array(75,0,130), + 'indigodye'=>array(0,65,106), + 'cornflowerblue'=>array(100,149,237), + 'darkslateblue'=>array(72,61,139), + 'slateblue'=>array(106,90,205), + 'mediumslateblue'=>array(123,104,238), + 'lightslateblue'=>array(132,112,255), + 'mediumblue'=>array(0,0,205), + 'royalblue'=>array(65,105,225), + 'blue'=>array(0,0,255), + 'dodgerblue'=>array(30,144,255), + 'deepskyblue'=>array(0,191,255), + 'skyblue'=>array(135,206,235), + 'lightskyblue'=>array(135,206,250), + 'steelblue'=>array(70,130,180), + 'lightred'=>array(211,167,168), + 'lightsteelblue'=>array(176,196,222), + 'lightblue'=>array(173,216,230), + 'powderblue'=>array(176,224,230), + 'paleturquoise'=>array(175,238,238), + 'darkturquoise'=>array(0,206,209), + 'mediumturquoise'=>array(72,209,204), + 'turquoise'=>array(64,224,208), + 'cyan'=>array(0,255,255), + 'lightcyan'=>array(224,255,255), + 'cadetblue'=>array(95,158,160), + 'mediumaquamarine'=>array(102,205,170), + 'aquamarine'=>array(127,255,212), + 'darkgreen'=>array(0,100,0), + 'darkolivegreen'=>array(85,107,47), + 'darkseagreen'=>array(143,188,143), + 'seagreen'=>array(46,139,87), + 'mediumseagreen'=>array(60,179,113), + 'lightseagreen'=>array(32,178,170), + 'palegreen'=>array(152,251,152), + 'springgreen'=>array(0,255,127), + 'lawngreen'=>array(124,252,0), + 'green'=>array(0,255,0), + 'chartreuse'=>array(127,255,0), + 'mediumspringgreen'=>array(0,250,154), + 'greenyellow'=>array(173,255,47), + 'limegreen'=>array(50,205,50), + 'yellowgreen'=>array(154,205,50), + 'forestgreen'=>array(34,139,34), + 'olivedrab'=>array(107,142,35), + 'darkkhaki'=>array(189,183,107), + 'khaki'=>array(240,230,140), + 'palegoldenrod'=>array(238,232,170), + 'lightgoldenrodyellow'=>array(250,250,210), + 'lightyellow'=>array(255,255,200), + 'yellow'=>array(255,255,0), + 'gold'=>array(255,215,0), + 'lightgoldenrod'=>array(238,221,130), + 'goldenrod'=>array(218,165,32), + 'darkgoldenrod'=>array(184,134,11), + 'rosybrown'=>array(188,143,143), + 'indianred'=>array(205,92,92), + 'saddlebrown'=>array(139,69,19), + 'sienna'=>array(160,82,45), + 'peru'=>array(205,133,63), + 'burlywood'=>array(222,184,135), + 'beige'=>array(245,245,220), + 'wheat'=>array(245,222,179), + 'sandybrown'=>array(244,164,96), + 'tan'=>array(210,180,140), + 'chocolate'=>array(210,105,30), + 'firebrick'=>array(178,34,34), + 'brown'=>array(165,42,42), + 'darksalmon'=>array(233,150,122), + 'salmon'=>array(250,128,114), + 'lightsalmon'=>array(255,160,122), + 'orange'=>array(255,165,0), + 'darkorange'=>array(255,140,0), + 'coral'=>array(255,127,80), + 'lightcoral'=>array(240,128,128), + 'tomato'=>array(255,99,71), + 'orangered'=>array(255,69,0), + 'red'=>array(255,0,0), + 'hotpink'=>array(255,105,180), + 'deeppink'=>array(255,20,147), + 'pink'=>array(255,192,203), + 'lightpink'=>array(255,182,193), + 'palevioletred'=>array(219,112,147), + 'maroon'=>array(176,48,96), + 'mediumvioletred'=>array(199,21,133), + 'violetred'=>array(208,32,144), + 'magenta'=>array(255,0,255), + 'violet'=>array(238,130,238), + 'plum'=>array(221,160,221), + 'orchid'=>array(218,112,214), + 'mediumorchid'=>array(186,85,211), + 'darkorchid'=>array(153,50,204), + 'darkviolet'=>array(148,0,211), + 'blueviolet'=>array(138,43,226), + 'purple'=>array(160,32,240), + 'mediumpurple'=>array(147,112,219), + 'thistle'=>array(216,191,216), + 'snow1'=>array(255,250,250), + 'snow2'=>array(238,233,233), + 'snow3'=>array(205,201,201), + 'snow4'=>array(139,137,137), + 'seashell1'=>array(255,245,238), + 'seashell2'=>array(238,229,222), + 'seashell3'=>array(205,197,191), + 'seashell4'=>array(139,134,130), + 'AntiqueWhite1'=>array(255,239,219), + 'AntiqueWhite2'=>array(238,223,204), + 'AntiqueWhite3'=>array(205,192,176), + 'AntiqueWhite4'=>array(139,131,120), + 'bisque1'=>array(255,228,196), + 'bisque2'=>array(238,213,183), + 'bisque3'=>array(205,183,158), + 'bisque4'=>array(139,125,107), + 'peachPuff1'=>array(255,218,185), + 'peachpuff2'=>array(238,203,173), + 'peachpuff3'=>array(205,175,149), + 'peachpuff4'=>array(139,119,101), + 'navajowhite1'=>array(255,222,173), + 'navajowhite2'=>array(238,207,161), + 'navajowhite3'=>array(205,179,139), + 'navajowhite4'=>array(139,121,94), + 'lemonchiffon1'=>array(255,250,205), + 'lemonchiffon2'=>array(238,233,191), + 'lemonchiffon3'=>array(205,201,165), + 'lemonchiffon4'=>array(139,137,112), + 'ivory1'=>array(255,255,240), + 'ivory2'=>array(238,238,224), + 'ivory3'=>array(205,205,193), + 'ivory4'=>array(139,139,131), + 'honeydew'=>array(193,205,193), + 'lavenderblush1'=>array(255,240,245), + 'lavenderblush2'=>array(238,224,229), + 'lavenderblush3'=>array(205,193,197), + 'lavenderblush4'=>array(139,131,134), + 'mistyrose1'=>array(255,228,225), + 'mistyrose2'=>array(238,213,210), + 'mistyrose3'=>array(205,183,181), + 'mistyrose4'=>array(139,125,123), + 'azure1'=>array(240,255,255), + 'azure2'=>array(224,238,238), + 'azure3'=>array(193,205,205), + 'azure4'=>array(131,139,139), + 'slateblue1'=>array(131,111,255), + 'slateblue2'=>array(122,103,238), + 'slateblue3'=>array(105,89,205), + 'slateblue4'=>array(71,60,139), + 'royalblue1'=>array(72,118,255), + 'royalblue2'=>array(67,110,238), + 'royalblue3'=>array(58,95,205), + 'royalblue4'=>array(39,64,139), + 'dodgerblue1'=>array(30,144,255), + 'dodgerblue2'=>array(28,134,238), + 'dodgerblue3'=>array(24,116,205), + 'dodgerblue4'=>array(16,78,139), + 'steelblue1'=>array(99,184,255), + 'steelblue2'=>array(92,172,238), + 'steelblue3'=>array(79,148,205), + 'steelblue4'=>array(54,100,139), + 'deepskyblue1'=>array(0,191,255), + 'deepskyblue2'=>array(0,178,238), + 'deepskyblue3'=>array(0,154,205), + 'deepskyblue4'=>array(0,104,139), + 'skyblue1'=>array(135,206,255), + 'skyblue2'=>array(126,192,238), + 'skyblue3'=>array(108,166,205), + 'skyblue4'=>array(74,112,139), + 'lightskyblue1'=>array(176,226,255), + 'lightskyblue2'=>array(164,211,238), + 'lightskyblue3'=>array(141,182,205), + 'lightskyblue4'=>array(96,123,139), + 'slategray1'=>array(198,226,255), + 'slategray2'=>array(185,211,238), + 'slategray3'=>array(159,182,205), + 'slategray4'=>array(108,123,139), + 'lightsteelblue1'=>array(202,225,255), + 'lightsteelblue2'=>array(188,210,238), + 'lightsteelblue3'=>array(162,181,205), + 'lightsteelblue4'=>array(110,123,139), + 'lightblue1'=>array(191,239,255), + 'lightblue2'=>array(178,223,238), + 'lightblue3'=>array(154,192,205), + 'lightblue4'=>array(104,131,139), + 'lightcyan1'=>array(224,255,255), + 'lightcyan2'=>array(209,238,238), + 'lightcyan3'=>array(180,205,205), + 'lightcyan4'=>array(122,139,139), + 'paleturquoise1'=>array(187,255,255), + 'paleturquoise2'=>array(174,238,238), + 'paleturquoise3'=>array(150,205,205), + 'paleturquoise4'=>array(102,139,139), + 'cadetblue1'=>array(152,245,255), + 'cadetblue2'=>array(142,229,238), + 'cadetblue3'=>array(122,197,205), + 'cadetblue4'=>array(83,134,139), + 'turquoise1'=>array(0,245,255), + 'turquoise2'=>array(0,229,238), + 'turquoise3'=>array(0,197,205), + 'turquoise4'=>array(0,134,139), + 'cyan1'=>array(0,255,255), + 'cyan2'=>array(0,238,238), + 'cyan3'=>array(0,205,205), + 'cyan4'=>array(0,139,139), + 'darkslategray1'=>array(151,255,255), + 'darkslategray2'=>array(141,238,238), + 'darkslategray3'=>array(121,205,205), + 'darkslategray4'=>array(82,139,139), + 'aquamarine1'=>array(127,255,212), + 'aquamarine2'=>array(118,238,198), + 'aquamarine3'=>array(102,205,170), + 'aquamarine4'=>array(69,139,116), + 'darkseagreen1'=>array(193,255,193), + 'darkseagreen2'=>array(180,238,180), + 'darkseagreen3'=>array(155,205,155), + 'darkseagreen4'=>array(105,139,105), + 'seagreen1'=>array(84,255,159), + 'seagreen2'=>array(78,238,148), + 'seagreen3'=>array(67,205,128), + 'seagreen4'=>array(46,139,87), + 'palegreen1'=>array(154,255,154), + 'palegreen2'=>array(144,238,144), + 'palegreen3'=>array(124,205,124), + 'palegreen4'=>array(84,139,84), + 'springgreen1'=>array(0,255,127), + 'springgreen2'=>array(0,238,118), + 'springgreen3'=>array(0,205,102), + 'springgreen4'=>array(0,139,69), + 'chartreuse1'=>array(127,255,0), + 'chartreuse2'=>array(118,238,0), + 'chartreuse3'=>array(102,205,0), + 'chartreuse4'=>array(69,139,0), + 'olivedrab1'=>array(192,255,62), + 'olivedrab2'=>array(179,238,58), + 'olivedrab3'=>array(154,205,50), + 'olivedrab4'=>array(105,139,34), + 'darkolivegreen1'=>array(202,255,112), + 'darkolivegreen2'=>array(188,238,104), + 'darkolivegreen3'=>array(162,205,90), + 'darkolivegreen4'=>array(110,139,61), + 'khaki1'=>array(255,246,143), + 'khaki2'=>array(238,230,133), + 'khaki3'=>array(205,198,115), + 'khaki4'=>array(139,134,78), + 'lightgoldenrod1'=>array(255,236,139), + 'lightgoldenrod2'=>array(238,220,130), + 'lightgoldenrod3'=>array(205,190,112), + 'lightgoldenrod4'=>array(139,129,76), + 'yellow1'=>array(255,255,0), + 'yellow2'=>array(238,238,0), + 'yellow3'=>array(205,205,0), + 'yellow4'=>array(139,139,0), + 'gold1'=>array(255,215,0), + 'gold2'=>array(238,201,0), + 'gold3'=>array(205,173,0), + 'gold4'=>array(139,117,0), + 'goldenrod1'=>array(255,193,37), + 'goldenrod2'=>array(238,180,34), + 'goldenrod3'=>array(205,155,29), + 'goldenrod4'=>array(139,105,20), + 'darkgoldenrod1'=>array(255,185,15), + 'darkgoldenrod2'=>array(238,173,14), + 'darkgoldenrod3'=>array(205,149,12), + 'darkgoldenrod4'=>array(139,101,8), + 'rosybrown1'=>array(255,193,193), + 'rosybrown2'=>array(238,180,180), + 'rosybrown3'=>array(205,155,155), + 'rosybrown4'=>array(139,105,105), + 'indianred1'=>array(255,106,106), + 'indianred2'=>array(238,99,99), + 'indianred3'=>array(205,85,85), + 'indianred4'=>array(139,58,58), + 'sienna1'=>array(255,130,71), + 'sienna2'=>array(238,121,66), + 'sienna3'=>array(205,104,57), + 'sienna4'=>array(139,71,38), + 'burlywood1'=>array(255,211,155), + 'burlywood2'=>array(238,197,145), + 'burlywood3'=>array(205,170,125), + 'burlywood4'=>array(139,115,85), + 'wheat1'=>array(255,231,186), + 'wheat2'=>array(238,216,174), + 'wheat3'=>array(205,186,150), + 'wheat4'=>array(139,126,102), + 'tan1'=>array(255,165,79), + 'tan2'=>array(238,154,73), + 'tan3'=>array(205,133,63), + 'tan4'=>array(139,90,43), + 'chocolate1'=>array(255,127,36), + 'chocolate2'=>array(238,118,33), + 'chocolate3'=>array(205,102,29), + 'chocolate4'=>array(139,69,19), + 'firebrick1'=>array(255,48,48), + 'firebrick2'=>array(238,44,44), + 'firebrick3'=>array(205,38,38), + 'firebrick4'=>array(139,26,26), + 'brown1'=>array(255,64,64), + 'brown2'=>array(238,59,59), + 'brown3'=>array(205,51,51), + 'brown4'=>array(139,35,35), + 'salmon1'=>array(255,140,105), + 'salmon2'=>array(238,130,98), + 'salmon3'=>array(205,112,84), + 'salmon4'=>array(139,76,57), + 'lightsalmon1'=>array(255,160,122), + 'lightsalmon2'=>array(238,149,114), + 'lightsalmon3'=>array(205,129,98), + 'lightsalmon4'=>array(139,87,66), + 'orange1'=>array(255,165,0), + 'orange2'=>array(238,154,0), + 'orange3'=>array(205,133,0), + 'orange4'=>array(139,90,0), + 'darkorange1'=>array(255,127,0), + 'darkorange2'=>array(238,118,0), + 'darkorange3'=>array(205,102,0), + 'darkorange4'=>array(139,69,0), + 'coral1'=>array(255,114,86), + 'coral2'=>array(238,106,80), + 'coral3'=>array(205,91,69), + 'coral4'=>array(139,62,47), + 'tomato1'=>array(255,99,71), + 'tomato2'=>array(238,92,66), + 'tomato3'=>array(205,79,57), + 'tomato4'=>array(139,54,38), + 'orangered1'=>array(255,69,0), + 'orangered2'=>array(238,64,0), + 'orangered3'=>array(205,55,0), + 'orangered4'=>array(139,37,0), + 'deeppink1'=>array(255,20,147), + 'deeppink2'=>array(238,18,137), + 'deeppink3'=>array(205,16,118), + 'deeppink4'=>array(139,10,80), + 'hotpink1'=>array(255,110,180), + 'hotpink2'=>array(238,106,167), + 'hotpink3'=>array(205,96,144), + 'hotpink4'=>array(139,58,98), + 'pink1'=>array(255,181,197), + 'pink2'=>array(238,169,184), + 'pink3'=>array(205,145,158), + 'pink4'=>array(139,99,108), + 'lightpink1'=>array(255,174,185), + 'lightpink2'=>array(238,162,173), + 'lightpink3'=>array(205,140,149), + 'lightpink4'=>array(139,95,101), + 'palevioletred1'=>array(255,130,171), + 'palevioletred2'=>array(238,121,159), + 'palevioletred3'=>array(205,104,137), + 'palevioletred4'=>array(139,71,93), + 'maroon1'=>array(255,52,179), + 'maroon2'=>array(238,48,167), + 'maroon3'=>array(205,41,144), + 'maroon4'=>array(139,28,98), + 'violetred1'=>array(255,62,150), + 'violetred2'=>array(238,58,140), + 'violetred3'=>array(205,50,120), + 'violetred4'=>array(139,34,82), + 'magenta1'=>array(255,0,255), + 'magenta2'=>array(238,0,238), + 'magenta3'=>array(205,0,205), + 'magenta4'=>array(139,0,139), + 'mediumred'=>array(140,34,34), + 'orchid1'=>array(255,131,250), + 'orchid2'=>array(238,122,233), + 'orchid3'=>array(205,105,201), + 'orchid4'=>array(139,71,137), + 'plum1'=>array(255,187,255), + 'plum2'=>array(238,174,238), + 'plum3'=>array(205,150,205), + 'plum4'=>array(139,102,139), + 'mediumorchid1'=>array(224,102,255), + 'mediumorchid2'=>array(209,95,238), + 'mediumorchid3'=>array(180,82,205), + 'mediumorchid4'=>array(122,55,139), + 'darkorchid1'=>array(191,62,255), + 'darkorchid2'=>array(178,58,238), + 'darkorchid3'=>array(154,50,205), + 'darkorchid4'=>array(104,34,139), + 'purple1'=>array(155,48,255), + 'purple2'=>array(145,44,238), + 'purple3'=>array(125,38,205), + 'purple4'=>array(85,26,139), + 'mediumpurple1'=>array(171,130,255), + 'mediumpurple2'=>array(159,121,238), + 'mediumpurple3'=>array(137,104,205), + 'mediumpurple4'=>array(93,71,139), + 'thistle1'=>array(255,225,255), + 'thistle2'=>array(238,210,238), + 'thistle3'=>array(205,181,205), + 'thistle4'=>array(139,123,139), + 'gray1'=>array(10,10,10), + 'gray2'=>array(40,40,30), + 'gray3'=>array(70,70,70), + 'gray4'=>array(100,100,100), + 'gray5'=>array(130,130,130), + 'gray6'=>array(160,160,160), + 'gray7'=>array(190,190,190), + 'gray8'=>array(210,210,210), + 'gray9'=>array(240,240,240), + 'darkgray'=>array(100,100,100), + 'darkblue'=>array(0,0,139), + 'darkcyan'=>array(0,139,139), + 'darkmagenta'=>array(139,0,139), + 'darkred'=>array(139,0,0), + 'silver'=>array(192, 192, 192), + 'eggplant'=>array(144,176,168), + 'lightgreen'=>array(144,238,144)); + } + + + //---------------- + // PUBLIC METHODS + // Colors can be specified as either + // 1. #xxxxxx HTML style + // 2. "colorname" as a named color + // 3. array(r,g,b) RGB triple + // This function translates this to a native RGB format and returns an + // RGB triple. + + function Color($aColor) { + if (is_string($aColor)) { + $matches = array(); + // this regex will parse a color string and fill the $matches array as such: + // 0: the full match if any + // 1: a hex string preceded by a hash, can be 3 characters (#fff) or 6 (#ffffff) (4 or 5 also accepted but...) + // 2,3,4: r,g,b values in hex if the first character of the string is # + // 5: all alpha-numeric characters at the beginning of the string if string does not start with # + // 6: alpha value prefixed by @ if supplied + // 7: alpha value with @ stripped + // 8: adjust value prefixed with : if supplied + // 9: adjust value with : stripped + $regex = '/(#([0-9a-fA-F]{1,2})([0-9a-fA-F]{1,2})([0-9a-fA-F]{1,2}))?([\w]+)?(@([\d\.,]+))?(:([\d\.,]+))?/'; + if(!preg_match($regex, $aColor, $matches)) { + JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor"); + } + if(empty($matches[5])) { + $r = strlen($matches[2]) == 1 ? $matches[2].$matches[2] : $matches[2]; + $g = strlen($matches[3]) == 1 ? $matches[3].$matches[3] : $matches[3]; + $b = strlen($matches[4]) == 1 ? $matches[4].$matches[4] : $matches[4]; + $r = hexdec($r); + $g = hexdec($g); + $b = hexdec($b); + }else { + if(!isset($this->rgb_table[$matches[5]]) ) { + JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor"); + } + $r = $this->rgb_table[$matches[5]][0]; + $g = $this->rgb_table[$matches[5]][1]; + $b = $this->rgb_table[$matches[5]][2]; + } + $alpha = isset($matches[7]) ? str_replace(',','.',$matches[7]) : 0; + $adj = isset($matches[9]) ? str_replace(',','.',$matches[9]) : 1.0; + + if( $adj < 0 ) { + JpGraphError::RaiseL(25077);//('Adjustment factor for color must be > 0'); + } + + // Scale adj so that an adj=2 always + // makes the color 100% white (i.e. 255,255,255. + // and adj=1 neutral and adj=0 black. + if( $adj == 1) { + return array($r,$g,$b,$alpha); + } + elseif( $adj > 1 ) { + $m = ($adj-1.0)*(255-min(255,min($r,min($g,$b)))); + return array(min(255,$r+$m), min(255,$g+$m), min(255,$b+$m),$alpha); + } + elseif( $adj < 1 ) { + $m = ($adj-1.0)*max(255,max($r,max($g,$b))); + return array(max(0,$r+$m), max(0,$g+$m), max(0,$b+$m),$alpha); + } + } elseif( is_array($aColor) ) { + if(!isset($aColor[3])) $aColor[3] = 0; + return $aColor; + } + else { + JpGraphError::RaiseL(25079,$aColor,count($aColor));//(" Unknown color specification: $aColor , size=".count($aColor)); + } + } + + // Compare two colors + // return true if equal + function Equal($aCol1,$aCol2) { + $c1 = $this->Color($aCol1); + $c2 = $this->Color($aCol2); + return $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] ; + } + + // Allocate a new color in the current image + // Return new color index, -1 if no more colors could be allocated + function Allocate($aColor,$aAlpha=0.0) { + list ($r, $g, $b, $a) = $this->color($aColor); + // If alpha is specified in the color string then this + // takes precedence over the second argument + if( $a > 0 ) { + $aAlpha = $a; + } + if( $aAlpha < 0 || $aAlpha > 1 ) { + JpGraphError::RaiseL(25080);//('Alpha parameter for color must be between 0.0 and 1.0'); + } + return imagecolorresolvealpha($this->img, $r, $g, $b, round($aAlpha * 127)); + } + + // Try to convert an array with three valid numbers to the corresponding hex array + // This is currenly only used in processing the colors for barplots in order to be able + // to handle the case where the color might be specified as an array of colros as well. + // In that case we must be able to find out if an array of values should be interpretated as + // a single color (specifeid as an RGB triple) + static function tryHexConversion($aColor) { + if( is_array( $aColor ) ) { + if( count( $aColor ) == 3 ) { + if( is_numeric($aColor[0]) && is_numeric($aColor[1]) && is_numeric($aColor[2]) ) { + if( ($aColor[0] >= 0 && $aColor[0] <= 255) && + ($aColor[1] >= 0 && $aColor[1] <= 255) && + ($aColor[2] >= 0 && $aColor[2] <= 255) ) { + return sprintf('#%02x%02x%02x',$aColor[0],$aColor[1],$aColor[2]); + } + } + } + } + return $aColor; + } + + // Return a RGB tripple corresponding to a position in the normal light spectrum + // The argumen values is in the range [0, 1] where a value of 0 correponds to blue and + // a value of 1 corresponds to red. Values in betwen is mapped to a linear interpolation + // of the constituting colors in the visible color spectra. + // The $aDynamicRange specified how much of the dynamic range we shold use + // a value of 1.0 give the full dyanmic range and a lower value give more dark + // colors. In the extreme of 0.0 then all colors will be black. + static function GetSpectrum($aVal,$aDynamicRange=1.0) { + if( $aVal < 0 || $aVal > 1.0001 ) { + return array(0,0,0); // Invalid case - just return black + } + + $sat = round(255*$aDynamicRange); + $a = 0.25; + if( $aVal <= 0.25 ) { + return array(0, round($sat*$aVal/$a), $sat); + } + elseif( $aVal <= 0.5 ) { + return array(0, $sat, round($sat-$sat*($aVal-0.25)/$a)); + } + elseif( $aVal <= 0.75 ) { + return array(round($sat*($aVal-0.5)/$a), $sat, 0); + } + else { + return array($sat, round($sat-$sat*($aVal-0.75)/$a), 0); + } + } + +} // Class + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_scatter.php b/web/public_php/admin/jpgraph/jpgraph_scatter.php index 1a21fccfa..7c99d39fa 100644 --- a/web/public_php/admin/jpgraph/jpgraph_scatter.php +++ b/web/public_php/admin/jpgraph/jpgraph_scatter.php @@ -1,225 +1,242 @@ -iSize = $aSize; - $this->iArrowSize = $aArrowSize; - } - - function SetColor($aColor) { - $this->iColor = $aColor; - } - - function Stroke(&$aImg,$x,$y,$a) { - // First rotate the center coordinates - list($x,$y) = $aImg->Rotate($x,$y); - - $old_origin = $aImg->SetCenter($x,$y); - $old_a = $aImg->a; - $aImg->SetAngle(-$a+$old_a); - - $dx = round($this->iSize/2); - $c = array($x-$dx,$y,$x+$dx,$y); - $x += $dx; - - list($dx,$dy) = $this->isizespec[$this->iArrowSize]; - $ca = array($x,$y,$x-$dx,$y-$dy,$x-$dx,$y+$dy,$x,$y); - - $aImg->SetColor($this->iColor); - $aImg->Polygon($c); - $aImg->FilledPolygon($ca); - - $aImg->SetCenter($old_origin[0],$old_origin[1]); - $aImg->SetAngle($old_a); - } -} - -//=================================================== -// CLASS FieldPlot -// Description: Render a field plot -//=================================================== -class FieldPlot extends Plot { - var $iAngles; - var $iCallback=''; - function FieldPlot($datay,$datax,$angles) { - if( (count($datax) != count($datay)) ) - JpGraphError::RaiseL(20001);//("Fieldplots must have equal number of X and Y points."); - if( (count($datax) != count($angles)) ) - JpGraphError::RaiseL(20002);//("Fieldplots must have an angle specified for each X and Y points."); - - $this->iAngles = $angles; - - $this->Plot($datay,$datax); - $this->value->SetAlign('center','center'); - $this->value->SetMargin(15); - - $this->arrow = new FieldArrow(); - } - - function SetCallback($aFunc) { - $this->iCallback = $aFunc; - } - - function Stroke(&$img,&$xscale,&$yscale) { - - // Remeber base color and size - $bc = $this->arrow->iColor; - $bs = $this->arrow->iSize; - $bas = $this->arrow->iArrowSize; - - for( $i=0; $i<$this->numpoints; ++$i ) { - // Skip null values - if( $this->coords[0][$i]==="" ) - continue; - - $f = $this->iCallback; - if( $f != "" ) { - list($cc,$cs,$cas) = call_user_func($f,$this->coords[1][$i],$this->coords[0][$i],$this->iAngles[$i]); - // Fall back on global data if the callback isn't set - if( $cc == "" ) $cc = $bc; - if( $cs == "" ) $cs = $bs; - if( $cas == "" ) $cas = $bas; - //echo "f=$f, cc=$cc, cs=$cs, cas=$cas
"; - $this->arrow->SetColor($cc); - $this->arrow->SetSize($cs,$cas); - } - - $xt = $xscale->Translate($this->coords[1][$i]); - $yt = $yscale->Translate($this->coords[0][$i]); - - $this->arrow->Stroke($img,$xt,$yt,$this->iAngles[$i]); - $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt); - } - } - - // Framework function - function Legend(&$aGraph) { - if( $this->legend != "" ) { - $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0, - $this->legendcsimtarget,$this->legendcsimalt); - } - } -} - -//=================================================== -// CLASS ScatterPlot -// Description: Render X and Y plots -//=================================================== -class ScatterPlot extends Plot { - var $impuls = false; - var $linkpoints = false, $linkpointweight=1, $linkpointcolor="black"; -//--------------- -// CONSTRUCTOR - function ScatterPlot($datay,$datax=false) { - if( (count($datax) != count($datay)) && is_array($datax)) - JpGraphError::RaiseL(20003);//("Scatterplot must have equal number of X and Y points."); - $this->Plot($datay,$datax); - $this->mark = new PlotMark(); - $this->mark->SetType(MARK_SQUARE); - $this->mark->SetColor($this->color); - $this->value->SetAlign('center','center'); - $this->value->SetMargin(0); - } - -//--------------- -// PUBLIC METHODS - function SetImpuls($f=true) { - $this->impuls = $f; - } - - // Combine the scatter plot points with a line - function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1) { - $this->linkpoints=$aFlag; - $this->linkpointcolor=$aColor; - $this->linkpointweight=$aWeight; - } - - function Stroke(&$img,&$xscale,&$yscale) { - - $ymin=$yscale->scale_abs[0]; - if( $yscale->scale[0] < 0 ) - $yzero=$yscale->Translate(0); - else - $yzero=$yscale->scale_abs[0]; - - $this->csimareas = ''; - for( $i=0; $i<$this->numpoints; ++$i ) { - - // Skip null values - if( $this->coords[0][$i]==="" || $this->coords[0][$i]==='-' || $this->coords[0][$i]==='x') - continue; - - if( isset($this->coords[1]) ) - $xt = $xscale->Translate($this->coords[1][$i]); - else - $xt = $xscale->Translate($i); - $yt = $yscale->Translate($this->coords[0][$i]); - - - if( $this->linkpoints && isset($yt_old) ) { - $img->SetColor($this->linkpointcolor); - $img->SetLineWeight($this->linkpointweight); - $img->Line($xt_old,$yt_old,$xt,$yt); - } - - if( $this->impuls ) { - $img->SetColor($this->color); - $img->SetLineWeight($this->weight); - $img->Line($xt,$yzero,$xt,$yt); - } - - if( !empty($this->csimtargets[$i]) ) { - $this->mark->SetCSIMTarget($this->csimtargets[$i]); - $this->mark->SetCSIMAlt($this->csimalts[$i]); - } - - if( isset($this->coords[1]) ) { - $this->mark->SetCSIMAltVal($this->coords[0][$i],$this->coords[1][$i]); - } - else { - $this->mark->SetCSIMAltVal($this->coords[0][$i],$i); - } - - $this->mark->Stroke($img,$xt,$yt); - - $this->csimareas .= $this->mark->GetCSIMAreas(); - $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt); - - $xt_old = $xt; - $yt_old = $yt; - } - } - - // Framework function - function Legend(&$aGraph) { - if( $this->legend != "" ) { - $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0, - $this->legendcsimtarget,$this->legendcsimalt); - } - } -} // Class -/* EOF */ -?> \ No newline at end of file +iSize = $aSize; + $this->iArrowSize = $aArrowSize; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function Stroke($aImg,$x,$y,$a) { + // First rotate the center coordinates + list($x,$y) = $aImg->Rotate($x,$y); + + $old_origin = $aImg->SetCenter($x,$y); + $old_a = $aImg->a; + $aImg->SetAngle(-$a+$old_a); + + $dx = round($this->iSize/2); + $c = array($x-$dx,$y,$x+$dx,$y); + $x += $dx; + + list($dx,$dy) = $this->isizespec[$this->iArrowSize]; + $ca = array($x,$y,$x-$dx,$y-$dy,$x-$dx,$y+$dy,$x,$y); + + $aImg->SetColor($this->iColor); + $aImg->Polygon($c); + $aImg->FilledPolygon($ca); + + $aImg->SetCenter($old_origin[0],$old_origin[1]); + $aImg->SetAngle($old_a); + } +} + +//=================================================== +// CLASS FieldPlot +// Description: Render a field plot +//=================================================== +class FieldPlot extends Plot { + public $arrow = ''; + private $iAngles = array(); + private $iCallback = ''; + + function __construct($datay,$datax,$angles) { + if( (count($datax) != count($datay)) ) + JpGraphError::RaiseL(20001);//("Fieldplots must have equal number of X and Y points."); + if( (count($datax) != count($angles)) ) + JpGraphError::RaiseL(20002);//("Fieldplots must have an angle specified for each X and Y points."); + + $this->iAngles = $angles; + + parent::__construct($datay,$datax); + $this->value->SetAlign('center','center'); + $this->value->SetMargin(15); + + $this->arrow = new FieldArrow(); + } + + function SetCallback($aFunc) { + $this->iCallback = $aFunc; + } + + function Stroke($img,$xscale,$yscale) { + + // Remeber base color and size + $bc = $this->arrow->iColor; + $bs = $this->arrow->iSize; + $bas = $this->arrow->iArrowSize; + + for( $i=0; $i<$this->numpoints; ++$i ) { + // Skip null values + if( $this->coords[0][$i]==="" ) + continue; + + $f = $this->iCallback; + if( $f != "" ) { + list($cc,$cs,$cas) = call_user_func($f,$this->coords[1][$i],$this->coords[0][$i],$this->iAngles[$i]); + // Fall back on global data if the callback isn't set + if( $cc == "" ) $cc = $bc; + if( $cs == "" ) $cs = $bs; + if( $cas == "" ) $cas = $bas; + $this->arrow->SetColor($cc); + $this->arrow->SetSize($cs,$cas); + } + + $xt = $xscale->Translate($this->coords[1][$i]); + $yt = $yscale->Translate($this->coords[0][$i]); + + $this->arrow->Stroke($img,$xt,$yt,$this->iAngles[$i]); + $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt); + } + } + + // Framework function + function Legend($aGraph) { + if( $this->legend != "" ) { + $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } +} + +//=================================================== +// CLASS ScatterPlot +// Description: Render X and Y plots +//=================================================== +class ScatterPlot extends Plot { + public $mark,$link; + private $impuls = false; + //--------------- + // CONSTRUCTOR + function __construct($datay,$datax=false) { + if( is_array($datax) && (count($datax) != count($datay)) ) { + JpGraphError::RaiseL(20003);//("Scatterplot must have equal number of X and Y points."); + } + parent::__construct($datay,$datax); + $this->mark = new PlotMark(); + $this->mark->SetType(MARK_SQUARE); + $this->mark->SetColor($this->color); + $this->value->SetAlign('center','center'); + $this->value->SetMargin(0); + $this->link = new LineProperty(1,'black','solid'); + $this->link->iShow = false; + } + + //--------------- + // PUBLIC METHODS + function SetImpuls($f=true) { + $this->impuls = $f; + } + + function SetStem($f=true) { + $this->impuls = $f; + } + + // Combine the scatter plot points with a line + function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1,$aStyle='solid') { + $this->link->iShow = $aFlag; + $this->link->iColor = $aColor; + $this->link->iWeight = $aWeight; + $this->link->iStyle = $aStyle; + } + + function Stroke($img,$xscale,$yscale) { + + $ymin=$yscale->scale_abs[0]; + if( $yscale->scale[0] < 0 ) + $yzero=$yscale->Translate(0); + else + $yzero=$yscale->scale_abs[0]; + + $this->csimareas = ''; + for( $i=0; $i<$this->numpoints; ++$i ) { + + // Skip null values + if( $this->coords[0][$i]==='' || $this->coords[0][$i]==='-' || $this->coords[0][$i]==='x') + continue; + + if( isset($this->coords[1]) ) + $xt = $xscale->Translate($this->coords[1][$i]); + else + $xt = $xscale->Translate($i); + $yt = $yscale->Translate($this->coords[0][$i]); + + + if( $this->link->iShow && isset($yt_old) ) { + $img->SetColor($this->link->iColor); + $img->SetLineWeight($this->link->iWeight); + $old = $img->SetLineStyle($this->link->iStyle); + $img->StyleLine($xt_old,$yt_old,$xt,$yt); + $img->SetLineStyle($old); + } + + if( $this->impuls ) { + $img->SetColor($this->color); + $img->SetLineWeight($this->weight); + $img->Line($xt,$yzero,$xt,$yt); + } + + if( !empty($this->csimtargets[$i]) ) { + if( !empty($this->csimwintargets[$i]) ) { + $this->mark->SetCSIMTarget($this->csimtargets[$i],$this->csimwintargets[$i]); + } + else { + $this->mark->SetCSIMTarget($this->csimtargets[$i]); + } + $this->mark->SetCSIMAlt($this->csimalts[$i]); + } + + if( isset($this->coords[1]) ) { + $this->mark->SetCSIMAltVal($this->coords[0][$i],$this->coords[1][$i]); + } + else { + $this->mark->SetCSIMAltVal($this->coords[0][$i],$i); + } + + $this->mark->Stroke($img,$xt,$yt); + + $this->csimareas .= $this->mark->GetCSIMAreas(); + $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt); + + $xt_old = $xt; + $yt_old = $yt; + } + } + + // Framework function + function Legend($aGraph) { + if( $this->legend != "" ) { + $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } +} // Class +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_stock.php b/web/public_php/admin/jpgraph/jpgraph_stock.php index 019694fc4..88c420848 100644 --- a/web/public_php/admin/jpgraph/jpgraph_stock.php +++ b/web/public_php/admin/jpgraph/jpgraph_stock.php @@ -1,183 +1,198 @@ -iTupleSize ) { - JpGraphError::RaiseL(21001,$this->iTupleSize);//('Data values for Stock charts must contain an even multiple of '.$this->iTupleSize.' data points.'); - } - $this->Plot($datay,$datax); - $this->numpoints /= $this->iTupleSize; - } -//--------------- -// PUBLIC METHODS - - function SetColor($aColor,$aColor1='white',$aColor2='darkred',$aColor3='darkred') { - $this->color = $aColor; - $this->iStockColor1 = $aColor1; - $this->iStockColor2 = $aColor2; - $this->iStockColor3 = $aColor3; - } - - function SetWidth($aWidth) { - // Make sure it's odd - $this->iWidth = 2*floor($aWidth/2)+1; - } - - function HideEndLines($aHide=true) { - $this->iEndLines = !$aHide; - } - - // Gets called before any axis are stroked - function PreStrokeAdjust(&$graph) { - if( $this->center ) { - $a=0.5; $b=0.5; - $this->numpoints++; - } else { - $a=0; $b=0; - } - $graph->xaxis->scale->ticks->SetXLabelOffset($a); - $graph->SetTextScaleOff($b); - } - - // Stroke stock plot - function Stroke(&$img,$xscale,$yscale) { - $n=$this->numpoints; - if( $this->center ) $n--; - if( isset($this->coords[1]) ) { - if( count($this->coords[1])!=$n ) - JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); -//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints"); - else - $exist_x = true; - } - else - $exist_x = false; - - if( $exist_x ) - $xs=$this->coords[1][0]; - else - $xs=0; - - $ts = $this->iTupleSize; - $this->csimareas = ''; - for( $i=0; $i<$n; ++$i) { - - //If value is NULL, then don't draw a bar at all - if ($this->coords[0][$i] === null) continue; - - if( $exist_x ) $x=$this->coords[1][$i]; - else $x=$i; - $xt = $xscale->Translate($x); - - $neg = $this->coords[0][$i*$ts] > $this->coords[0][$i*$ts+1] ; - $yopen = $yscale->Translate($this->coords[0][$i*$ts]); - $yclose = $yscale->Translate($this->coords[0][$i*$ts+1]); - $ymin = $yscale->Translate($this->coords[0][$i*$ts+2]); - $ymax = $yscale->Translate($this->coords[0][$i*$ts+3]); - - $dx = floor($this->iWidth/2); - $xl = $xt - $dx; - $xr = $xt + $dx; - - if( $neg ) - $img->SetColor($this->iStockColor3); - else - $img->SetColor($this->iStockColor1); - $img->FilledRectangle($xl,$yopen,$xr,$yclose); - $img->SetLineWeight($this->weight); - if( $neg ) - $img->SetColor($this->iStockColor2); - else - $img->SetColor($this->color); - - $img->Rectangle($xl,$yopen,$xr,$yclose); - - if( $yopen < $yclose ) { - $ytop = $yopen ; - $ybottom = $yclose ; - } - else { - $ytop = $yclose ; - $ybottom = $yopen ; - } - $img->SetColor($this->color); - $img->Line($xt,$ytop,$xt,$ymax); - $img->Line($xt,$ybottom,$xt,$ymin); - - if( $this->iEndLines ) { - $img->Line($xl,$ymax,$xr,$ymax); - $img->Line($xl,$ymin,$xr,$ymin); - } - - // A chance for subclasses to add things to the bar - // for data point i - $this->ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg); - - // Setup image maps - if( !empty($this->csimtargets[$i]) ) { - $this->csimareas.= 'csimareas .= ' href="'.$this->csimtargets[$i].'"'; - if( !empty($this->csimalts[$i]) ) { - $sval=$this->csimalts[$i]; - $this->csimareas .= " title=\"$sval\" "; - } - $this->csimareas.= " alt=\"$sval\" />\n"; - } - } - return true; - } - - // A hook for subclasses to modify the plot - function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {} - -} // Class - -//=================================================== -// CLASS BoxPlot -//=================================================== -class BoxPlot extends StockPlot { - var $iPColor='black',$iNColor='white'; - function BoxPlot($datay,$datax=false) { - $this->iTupleSize=5; - parent::StockPlot($datay,$datax); - } - - function SetMedianColor($aPos,$aNeg) { - $this->iPColor = $aPos; - $this->iNColor = $aNeg; - } - - function ModBox(&$img,$xscale,$yscale,$i,$xl,$xr,$neg) { - if( $neg ) - $img->SetColor($this->iNColor); - else - $img->SetColor($this->iPColor); - - $y = $yscale->Translate($this->coords[0][$i*5+4]); - $img->Line($xl,$y,$xr,$y); - } -} - -/* EOF */ -?> \ No newline at end of file +iTupleSize ) { + JpGraphError::RaiseL(21001,$this->iTupleSize); + //('Data values for Stock charts must contain an even multiple of '.$this->iTupleSize.' data points.'); + } + parent::__construct($datay,$datax); + $this->numpoints /= $this->iTupleSize; + } + //--------------- + // PUBLIC METHODS + + function SetColor($aColor,$aColor1='white',$aColor2='darkred',$aColor3='darkred') { + $this->color = $aColor; + $this->iStockColor1 = $aColor1; + $this->iStockColor2 = $aColor2; + $this->iStockColor3 = $aColor3; + } + + function SetWidth($aWidth) { + // Make sure it's odd + $this->iWidth = 2*floor($aWidth/2)+1; + } + + function HideEndLines($aHide=true) { + $this->iEndLines = !$aHide; + } + + // Gets called before any axis are stroked + function PreStrokeAdjust($graph) { + if( $this->center ) { + $a=0.5; $b=0.5; + $this->numpoints++; + } else { + $a=0; $b=0; + } + $graph->xaxis->scale->ticks->SetXLabelOffset($a); + $graph->SetTextScaleOff($b); + } + + // Method description + function Stroke($img,$xscale,$yscale) { + $n=$this->numpoints; + if( $this->center ) $n--; + if( isset($this->coords[1]) ) { + if( count($this->coords[1])!=$n ) { + JpGraphError::RaiseL(2003,count($this->coords[1]),$n); + // ("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints"); + } + else { + $exist_x = true; + } + } + else { + $exist_x = false; + } + + if( $exist_x ) { + $xs=$this->coords[1][0]; + } + else { + $xs=0; + } + + $ts = $this->iTupleSize; + $this->csimareas = ''; + for( $i=0; $i<$n; ++$i) { + + //If value is NULL, then don't draw a bar at all + if ($this->coords[0][$i*$ts] === null) continue; + + if( $exist_x ) { + $x=$this->coords[1][$i]; + if ($x === null) continue; + } + else { + $x=$i; + } + $xt = $xscale->Translate($x); + + $neg = $this->coords[0][$i*$ts] > $this->coords[0][$i*$ts+1] ; + $yopen = $yscale->Translate($this->coords[0][$i*$ts]); + $yclose = $yscale->Translate($this->coords[0][$i*$ts+1]); + $ymin = $yscale->Translate($this->coords[0][$i*$ts+2]); + $ymax = $yscale->Translate($this->coords[0][$i*$ts+3]); + + $dx = floor($this->iWidth/2); + $xl = $xt - $dx; + $xr = $xt + $dx; + + if( $neg ) { + $img->SetColor($this->iStockColor3); + } + else { + $img->SetColor($this->iStockColor1); + } + $img->FilledRectangle($xl,$yopen,$xr,$yclose); + $img->SetLineWeight($this->weight); + if( $neg ) { + $img->SetColor($this->iStockColor2); + } + else { + $img->SetColor($this->color); + } + + $img->Rectangle($xl,$yopen,$xr,$yclose); + + if( $yopen < $yclose ) { + $ytop = $yopen ; + $ybottom = $yclose ; + } + else { + $ytop = $yclose ; + $ybottom = $yopen ; + } + $img->SetColor($this->color); + $img->Line($xt,$ytop,$xt,$ymax); + $img->Line($xt,$ybottom,$xt,$ymin); + + if( $this->iEndLines ) { + $img->Line($xl,$ymax,$xr,$ymax); + $img->Line($xl,$ymin,$xr,$ymin); + } + + // A chance for subclasses to add things to the bar + // for data point i + $this->ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg); + + // Setup image maps + if( !empty($this->csimtargets[$i]) ) { + $this->csimareas.= 'csimareas .= ' href="'.$this->csimtargets[$i].'"'; + if( !empty($this->csimalts[$i]) ) { + $sval=$this->csimalts[$i]; + $this->csimareas .= " title=\"$sval\" alt=\"$sval\" "; + } + $this->csimareas.= " />\n"; + } + } + return true; + } + + // A hook for subclasses to modify the plot + function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {} + +} // Class + +//=================================================== +// CLASS BoxPlot +//=================================================== +class BoxPlot extends StockPlot { + private $iPColor='black',$iNColor='white'; + + function __construct($datay,$datax=false) { + $this->iTupleSize=5; + parent::__construct($datay,$datax); + } + + function SetMedianColor($aPos,$aNeg) { + $this->iPColor = $aPos; + $this->iNColor = $aNeg; + } + + function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) { + if( $neg ) + $img->SetColor($this->iNColor); + else + $img->SetColor($this->iPColor); + + $y = $yscale->Translate($this->coords[0][$i*5+4]); + $img->Line($xl,$y,$xr,$y); + } +} + +/* EOF */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_table.php b/web/public_php/admin/jpgraph/jpgraph_table.php new file mode 100644 index 000000000..7f55cc1de --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_table.php @@ -0,0 +1,1331 @@ +iVal = new Text($aVal); + $this->iRow = $aRow; + $this->iCol = $aCol; + $this->iPRow = $aRow; // Initialiy each cell is its own parent + $this->iPCol = $aCol; + $this->iIconConstrain = array(-1,-1); + } + + function Init($aTable) { + $this->iTable = $aTable; + } + + function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') { + $this->iCSIMtarget = $aTarget; + $this->iCSIMwintarget = $aWinTarget; + $this->iCSIMalt = $aAlt; + } + + function GetCSIMArea() { + if( $this->iCSIMtarget !== '' ) + return $this->iCSIMArea; + else + return ''; + } + + function SetImageConstrain($aType,$aVal) { + if( !in_array($aType,array(TIMG_WIDTH, TIMG_HEIGHT)) ) { + JpGraphError::RaiseL(27015); + } + $this->iIconConstrain = array($aType,$aVal); + } + + function SetCountryFlag($aFlag,$aScale=1.0,$aMix=100,$aStdSize=3) { + $this->iIcon = new IconPlot(); + $this->iIcon->SetCountryFlag($aFlag,0,0,$aScale,$aMix,$aStdSize); + } + + function SetImage($aFile,$aScale=1.0,$aMix=100) { + $this->iIcon = new IconPlot($aFile,0,0,$aScale,$aMix); + } + + function SetImageFromString($aStr,$aScale=1.0,$aMix=100) { + $this->iIcon = new IconPlot("",0,0,$aScale,$aMix); + $this->iIcon->CreateFromString($aStr); + } + + function SetRowColSpan($aRowSpan,$aColSpan) { + $this->iRowSpan = $aRowSpan; + $this->iColSpan = $aColSpan; + $this->iMerged = true; + } + + function SetMerged($aPRow,$aPCol,$aFlg=true) { + $this->iMerged = $aFlg; + $this->iPRow=$aPRow; + $this->iPCol=$aPCol; + } + + function IsMerged() { + return $this->iMerged; + } + + function SetNumberFormat($aF) { + $this->iNumberFormat = $aF; + } + + function Set($aTxt) { + $this->iVal->Set($aTxt); + } + + function SetFont($aFF,$aFS,$aFSize) { + $this->iFF = $aFF; + $this->iFS = $aFS; + $this->iFSize = $aFSize; + $this->iVal->SetFont($aFF,$aFS,$aFSize); + } + + function SetFillColor($aColor) { + $this->iBGColor=$aColor; + } + + function SetFontColor($aColor) { + $this->iFontColor=$aColor; + } + + function SetGridColor($aLeft,$aTop=null,$aBottom=null,$aRight=null) { + if( $aLeft !== null ) $this->iGridColor[0] = $aLeft; + if( $aTop !== null ) $this->iGridColor[1] = $aTop; + if( $aBottom !== null ) $this->iGridColor[2] = $aBottom; + if( $aRight !== null )$this->iGridColor[3] = $aRight; + } + + function SetGridStyle($aLeft,$aTop=null,$aBottom=null,$aRight=null) { + if( $aLeft !== null ) $this->iGridStyle[0] = $aLeft; + if( $aTop !== null ) $this->iGridStyle[1] = $aTop; + if( $aBottom !== null ) $this->iGridStyle[2] = $aBottom; + if( $aRight !== null )$this->iGridStyle[3] = $aRight; + } + + function SetGridWeight($aLeft=null,$aTop=null,$aBottom=null,$aRight=null) { + $weight_arr = array($aLeft, $aTop, $aBottom, $aRight); + for ($i = 0; $i < count($weight_arr); $i++) { + if ($weight_arr[$i] === "") { + $weight_arr[$i] = 0; + } + } + if( $aLeft !== null ) $this->iGridWeight[0] = $weight_arr[0]; + if( $aTop !== null ) $this->iGridWeight[1] = $weight_arr[1]; + if( $aBottom !== null ) $this->iGridWeight[2] = $weight_arr[2]; + if( $aRight !== null ) $this->iGridWeight[3] = $weight_arr[3]; + } + + function SetMargin($aLeft,$aRight,$aTop,$aBottom) { + $this->iMarginLeft=$aLeft; + $this->iMarginRight=$aRight; + $this->iMarginTop=$aTop; + $this->iMarginBottom=$aBottom; + } + + function GetWidth($aImg) { + if( $this->iIcon !== null ) { + if( $this->iIconConstrain[0] == TIMG_WIDTH ) { + $this->iIcon->SetScale(1); + $tmp = $this->iIcon->GetWidthHeight(); + $this->iIcon->SetScale($this->iIconConstrain[1]/$tmp[0]); + } + elseif( $this->iIconConstrain[0] == TIMG_HEIGHT ) { + $this->iIcon->SetScale(1); + $tmp = $this->iIcon->GetWidthHeight(); + $this->iIcon->SetScale($this->iIconConstrain[1]/$tmp[1]); + } + $tmp = $this->iIcon->GetWidthHeight(); + $iwidth = $tmp[0]; + } + else { + $iwidth=0; + } + if( $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->dir == 0 ) { + $pwidth = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetWidth($aImg); + } + elseif( $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->dir == 90 ) { + $pwidth = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetFontHeight($aImg)+2; + } + else { + $pwidth = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetWidth($aImg)+2; + } + + $pcolspan = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iColSpan; + return round(max($iwidth,$pwidth)/$pcolspan) + $this->iMarginLeft + $this->iMarginRight; + } + + function GetHeight($aImg) { + if( $this->iIcon !== null ) { + if( $this->iIconConstrain[0] == TIMG_WIDTH ) { + $this->iIcon->SetScale(1); + $tmp = $this->iIcon->GetWidthHeight(); + $this->iIcon->SetScale($this->iIconConstrain[1]/$tmp[0]); + } + elseif( $this->iIconConstrain[0] == TIMG_HEIGHT ) { + $this->iIcon->SetScale(1); + $tmp = $this->iIcon->GetWidthHeight(); + $this->iIcon->SetScale($this->iIconConstrain[1]/$tmp[1]); + } + $tmp = $this->iIcon->GetWidthHeight(); + $iheight = $tmp[1]; + } + else { + $iheight = 0; + } + if( $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->dir == 0 ) { + $pheight = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetHeight($aImg); + } + else { + $pheight = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetHeight($aImg)+1; + } + $prowspan = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iRowSpan; + return round(max($iheight,$pheight)/$prowspan) + $this->iMarginTop + $this->iMarginBottom; + } + + function SetAlign($aHorAlign='left',$aVertAlign='bottom') { + $aHorAlign = strtolower($aHorAlign); + $aVertAlign = strtolower($aVertAlign); + $chk = array('left','right','center','bottom','top','middle'); + if( !in_array($aHorAlign,$chk) || !in_array($aVertAlign,$chk) ) { + JpGraphError::RaiseL(27011,$aHorAlign,$aVertAlign); + } + $this->iVertAlign = $aVertAlign; + $this->iHorAlign = $aHorAlign; + } + + function AdjustMarginsForGrid() { + if( $this->iCol > 0 ) { + switch( $this->iGridStyle[0] ) { + case TGRID_SINGLE: $wf=1; break; + case TGRID_DOUBLE: $wf=3; break; + case TGRID_DOUBLE2: $wf=4; break; + } + $this->iMarginLeft += $this->iGridWeight[0]*$wf; + } + if( $this->iRow > 0 ) { + switch( $this->iGridStyle[1] ) { + case TGRID_SINGLE: $wf=1; break; + case TGRID_DOUBLE: $wf=3; break; + case TGRID_DOUBLE2: $wf=4; break; + } + $this->iMarginTop += $this->iGridWeight[1]*$wf; + } + if( $this->iRow+$this->iRowSpan-1 < $this->iTable->iSize[0]-1 ) { + switch( $this->iGridStyle[2] ) { + case TGRID_SINGLE: $wf=1; break; + case TGRID_DOUBLE: $wf=3; break; + case TGRID_DOUBLE2: $wf=4; break; + } + $this->iMarginBottom += $this->iGridWeight[2]*$wf; + } + if( $this->iCol+$this->iColSpan-1 < $this->iTable->iSize[1]-1 ) { + switch( $this->iGridStyle[3] ) { + case TGRID_SINGLE: $wf=1; break; + case TGRID_DOUBLE: $wf=3; break; + case TGRID_DOUBLE2: $wf=4; break; + } + $this->iMarginRight += $this->iGridWeight[3]*$wf; + } + } + + function StrokeVGrid($aImg,$aX,$aY,$aWidth,$aHeight,$aDir=1) { + // Left or right grid line + // For the right we increase the X-pos and for the right we decrease it. This is + // determined by the direction argument. + $idx = $aDir==1 ? 0 : 3; + + // We don't stroke the grid lines that are on the edge of the table since this is + // the place of the border. + if( ( ($this->iCol > 0 && $idx==0) || ($this->iCol+$this->iColSpan-1 < $this->iTable->iSize[1]-1 && $idx==3) ) + && $this->iGridWeight[$idx] > 0 ) { + $x = $aDir==1 ? $aX : $aX + $aWidth-1; + $y = $aY+$aHeight-1; + $aImg->SetColor($this->iGridColor[$idx]); + switch( $this->iGridStyle[$idx] ) { + case TGRID_SINGLE: + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($x+$i*$aDir,$aY, $x+$i*$aDir,$y); + break; + + case TGRID_DOUBLE: + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($x+$i*$aDir,$aY, $x+$i*$aDir,$y); + $x += $this->iGridWeight[$idx]*2; + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($x+$i*$aDir,$aY, $x+$i*$aDir,$y); + break; + + case TGRID_DOUBLE2: + for( $i=0; $i < $this->iGridWeight[$idx]*2; ++$i ) + $aImg->Line($x+$i*$aDir,$aY,$x+$i*$aDir,$y); + $x += $this->iGridWeight[$idx]*3; + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($x+$i*$aDir,$aY, $x+$i*$aDir,$y); + break; + } + } + } + + function StrokeHGrid($aImg,$aX,$aY,$aWidth,$aHeight,$aDir=1) { + // Top or bottom grid line + // For the left we increase the X-pos and for the right we decrease it. This is + // determined by the direction argument. + $idx = $aDir==1 ? 1 : 2; + + // We don't stroke the grid lines that are on the edge of the table since this is + // the place of the border. + if( ( ($this->iRow > 0 && $idx==1) || ($this->iRow+$this->iRowSpan-1 < $this->iTable->iSize[0]-1 && $idx==2) ) + && $this->iGridWeight[$idx] > 0) { + $y = $aDir==1 ? $aY : $aY+$aHeight-1; + $x = $aX+$aWidth-1; + $aImg->SetColor($this->iGridColor[$idx]); + switch( $this->iGridStyle[$idx] ) { + case TGRID_SINGLE: + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($aX,$y+$i, $x,$y+$i); + break; + + case TGRID_DOUBLE: + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($aX,$y+$i, $x,$y+$i); + $y += $this->iGridWeight[$idx]*2; + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($aX,$y+$i, $x,$y+$i); + break; + + case TGRID_DOUBLE2: + for( $i=0; $i < $this->iGridWeight[$idx]*2; ++$i ) + $aImg->Line($aX,$y+$i, $x,$y+$i); + $y += $this->iGridWeight[$idx]*3; + for( $i=0; $i < $this->iGridWeight[$idx]; ++$i ) + $aImg->Line($aX,$y+$i, $x,$y+$i); + break; + } + } + } + + function Stroke($aImg,$aX,$aY,$aWidth,$aHeight) { + // If this is a merged cell we only stroke if it is the parent cell. + // The parent cell holds the merged cell block + if( $this->iMerged && ($this->iRow != $this->iPRow || $this->iCol != $this->iPCol) ) { + return; + } + + if( $this->iBGColor != '' ) { + $aImg->SetColor($this->iBGColor); + $aImg->FilledRectangle($aX,$aY,$aX+$aWidth-1,$aY+$aHeight-1); + } + + $coords = $aX.','.$aY.','.($aX+$aWidth-1).','.$aY.','.($aX+$aWidth-1).','.($aY+$aHeight-1).','.$aX.','.($aY+$aHeight-1); + if( ! empty($this->iCSIMtarget) ) { + $this->iCSIMArea = 'iCSIMwintarget) ) { + $this->iCSIMArea .= " target=\"".$this->iCSIMwintarget."\""; + } + if( ! empty($this->iCSIMalt) ) { + $this->iCSIMArea .= ' alt="'.$this->iCSIMalt.'" title="'.$this->iCSIMalt."\" "; + } + $this->iCSIMArea .= " />\n"; + } + + $this->StrokeVGrid($aImg,$aX,$aY,$aWidth,$aHeight); + $this->StrokeVGrid($aImg,$aX,$aY,$aWidth,$aHeight,-1); + $this->StrokeHGrid($aImg,$aX,$aY,$aWidth,$aHeight); + $this->StrokeHGrid($aImg,$aX,$aY,$aWidth,$aHeight,-1); + + if( $this->iIcon !== null ) { + switch( $this->iHorAlign ) { + case 'left': + $x = $aX+$this->iMarginLeft; + $hanchor='left'; + break; + case 'center': + case 'middle': + $x = $aX+$this->iMarginLeft+round(($aWidth-$this->iMarginLeft-$this->iMarginRight)/2); + $hanchor='center'; + break; + case 'right': + $x = $aX+$aWidth-$this->iMarginRight-1; + $hanchor='right'; + break; + default: + JpGraphError::RaiseL(27012,$this->iHorAlign); + } + + switch( $this->iVertAlign ) { + case 'top': + $y = $aY+$this->iMarginTop; + $vanchor='top'; + break; + case 'center': + case 'middle': + $y = $aY+$this->iMarginTop+round(($aHeight-$this->iMarginTop-$this->iMarginBottom)/2); + $vanchor='center'; + break; + case 'bottom': + $y = $aY+$aHeight-1-$this->iMarginBottom; + $vanchor='bottom'; + break; + default: + JpGraphError::RaiseL(27012,$this->iVertAlign); + } + $this->iIcon->SetAnchor($hanchor,$vanchor); + $this->iIcon->_Stroke($aImg,$x,$y); + } + $this->iVal->SetColor($this->iFontColor); + $this->iVal->SetFont($this->iFF,$this->iFS,$this->iFSize); + switch( $this->iHorAlign ) { + case 'left': + $x = $aX+$this->iMarginLeft; + break; + case 'center': + case 'middle': + $x = $aX+$this->iMarginLeft+round(($aWidth-$this->iMarginLeft-$this->iMarginRight)/2); + break; + case 'right': + $x = $aX+$aWidth-$this->iMarginRight-1; + break; + default: + JpGraphError::RaiseL(27012,$this->iHorAlign); + } + // A workaround for the shortcomings in the TTF font handling in GD + // The anchor position for rotated text (=90) is to "short" so we add + // an offset based on the actual font size + if( $this->iVal->dir != 0 && $this->iVal->font_family >= 10 ) { + $aY += 4 + round($this->iVal->font_size*0.8); + } + switch( $this->iVertAlign ) { + case 'top': + $y = $aY+$this->iMarginTop; + break; + case 'center': + case 'middle': + $y = $aY+$this->iMarginTop+round(($aHeight-$this->iMarginTop-$this->iMarginBottom)/2); + //$y -= round($this->iVal->GetFontHeight($aImg)/2); + $y -= round($this->iVal->GetHeight($aImg)/2); + break; + case 'bottom': + //$y = $aY+$aHeight-1-$this->iMarginBottom-$this->iVal->GetFontHeight($aImg); + $y = $aY+$aHeight-$this->iMarginBottom-$this->iVal->GetHeight($aImg); + break; + default: + JpGraphError::RaiseL(27012,$this->iVertAlign); + } + $this->iVal->SetAlign($this->iHorAlign,'top'); + if( $this->iNumberFormat !== null && is_numeric($this->iVal->t) ) { + $this->iVal->t = sprintf($this->iNumberFormat,$this->iVal->t); + } + $this->iVal->Stroke($aImg,$x,$y); + } +} + +//--------------------------------------------------------------------- +// CLASS GTextTable +// Description: +// Graphic text table +//--------------------------------------------------------------------- +class GTextTable { + public $iCells = array(), $iSize=array(0,0); // Need to be public since they are used by the cell + private $iWidth=0, $iHeight=0; + private $iColWidth=NULL,$iRowHeight=NULL; + private $iImg=NULL; + private $iXPos=0, $iYPos=0; + private $iScaleXPos=null,$iScaleYPos=null; + private $iBGColor=''; + private $iBorderColor='black',$iBorderWeight=1; + private $iInit=false; + private $iYAnchor='top',$iXAnchor='left'; + /*----------------------------------------------------------------- + * First and second phase constructors + *----------------------------------------------------------------- + */ + function __construct() { + // Empty + } + + function Init($aRows=0,$aCols=0,$aFillText='') { + $this->iSize[0] = $aRows; + $this->iSize[1] = $aCols; + for($i=0; $i < $this->iSize[0]; ++$i) { + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$i][$j] = new GTextTableCell($aFillText,$i,$j); + $this->iCells[$i][$j]->Init($this); + } + } + $this->iInit=true; + } + + /*----------------------------------------------------------------- + * Outer border of table + *----------------------------------------------------------------- + */ + function SetBorder($aWeight=1,$aColor='black') { + $this->iBorderColor=$aColor; + $this->iBorderWeight = $aWeight; + } + + + /*----------------------------------------------------------------- + * Position in graph of table + *----------------------------------------------------------------- + */ + function SetPos($aX,$aY) { + $this->iXPos = $aX; + $this->iYPos = $aY; + } + + function SetScalePos($aX,$aY) { + $this->iScaleXPos = $aX; + $this->iScaleYPos = $aY; + } + + function SetAnchorPos($aXAnchor,$aYAnchor='top') { + $this->iXAnchor = $aXAnchor; + $this->iYAnchor = $aYAnchor; + } + + /*----------------------------------------------------------------- + * Setup country flag in a cell + *----------------------------------------------------------------- + */ + function SetCellCountryFlag($aRow,$aCol,$aFlag,$aScale=1.0,$aMix=100,$aStdSize=3) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetCountryFlag($aFlag,$aScale,$aMix,$aStdSize); + + } + + /*----------------------------------------------------------------- + * Setup image in a cell + *----------------------------------------------------------------- + */ + function SetCellImage($aRow,$aCol,$aFile,$aScale=1.0,$aMix=100) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetImage($aFile,$aScale,$aMix); + } + + function SetRowImage($aRow,$aFile,$aScale=1.0,$aMix=100) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetImage($aFile,$aScale,$aMix); + } + } + + function SetColImage($aCol,$aFile,$aScale=1.0,$aMix=100) { + $this->_chkC($aCol); + for($j=0; $j < $this->iSize[0]; ++$j) { + $this->iCells[$j][$aCol]->SetImage($aFile,$aScale,$aMix); + } + } + + function SetImage($aFileR1,$aScaleC1=null,$aMixR2=null,$aC2=null,$aFile=null,$aScale=1.0,$aMix=100) { + if( $aScaleC1 !== null && $aMixR2!==null && $aC2!==null && $aFile!==null ) { + $this->_chkR($aArgR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + } + else { + if( $aScaleC1 !== null ) $aScale = $aScaleC1; + if( $aMixR2 !== null ) $aMix = $aMixR2; + $aFile = $aFileR1; + $aMixR2 = $this->iSize[0]-1; $aFileR1 = 0; + $aC2 = $this->iSize[1]-1; $aScaleC1 = 0; + } + for($i=$aArgR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetImage($aFile,$aScale,$aMix); + } + } + } + + function SetCellImageConstrain($aRow,$aCol,$aType,$aVal) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetImageConstrain($aType,$aVal); + } + + /*----------------------------------------------------------------- + * Generate a HTML version of the table + *----------------------------------------------------------------- + */ + function toString() { + $t = ''; + for($i=0; $i < $this->iSize[0]; ++$i) { + $t .= ''; + for($j=0; $j < $this->iSize[1]; ++$j) { + $t .= ''; + } + $t .= ''; + } + $t .= '
'; + if( $this->iCells[$i][$j]->iMerged ) + $t .= 'M '; + $t .= 'val='.$this->iCells[$i][$j]->iVal->t; + $t .= ' (cs='.$this->iCells[$i][$j]->iColSpan. + ', rs='.$this->iCells[$i][$j]->iRowSpan.')'; + $t .= '
'; + return $t; + } + + /*----------------------------------------------------------------- + * Specify data for table + *----------------------------------------------------------------- + */ + function Set($aArg1,$aArg2=NULL,$aArg3=NULL) { + if( $aArg2===NULL && $aArg3===NULL ) { + if( is_array($aArg1) ) { + if( is_array($aArg1[0]) ) { + $m = count($aArg1); + // Find the longest row + $n=0; + for($i=0; $i < $m; ++$i) + $n = max(count($aArg1[$i]),$n); + for($i=0; $i < $m; ++$i) { + for($j=0; $j < $n; ++$j) { + if( isset($aArg1[$i][$j]) ){ + $this->_setcell($i,$j,(string)$aArg1[$i][$j]); + } + else { + $this->_setcell($i,$j); + } + } + } + $this->iSize[0] = $m; + $this->iSize[1] = $n; + $this->iInit=true; + } + else { + JpGraphError::RaiseL(27001); + //('Illegal argument to GTextTable::Set(). Array must be 2 dimensional'); + } + } + else { + JpGraphError::RaiseL(27002); + //('Illegal argument to GTextTable::Set()'); + } + } + else { + // Must be in the form (row,col,val) + $this->_chkR($aArg1); + $this->_chkC($aArg2); + $this->_setcell($aArg1,$aArg2,(string)$aArg3); + } + } + + /*--------------------------------------------------------------------- + * Cell margin setting + *--------------------------------------------------------------------- + */ + function SetPadding($aArgR1,$aC1=null,$aR2=null,$aC2=null,$aPad=null) { + if( $aC1 !== null && $aR2!==null && $aC2!==null && $aPad!==null ) { + $this->_chkR($aArgR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + } + else { + $aPad = $aArgR1; + $aR2 = $this->iSize[0]-1; $aArgR1 = 0; + $aC2 = $this->iSize[1]-1; $aC1 = 0; + } + for($i=$aArgR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetMargin($aPad,$aPad,$aPad,$aPad); + } + } + } + + function SetRowPadding($aRow,$aPad) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetMargin($aPad,$aPad,$aPad,$aPad); + } + } + + function SetColPadding($aCol,$aPad) { + $this->_chkC($aCol); + for($j=0; $j < $this->iSize[0]; ++$j) { + $this->iCells[$j][$aCol]->SetMargin($aPad,$aPad,$aPad,$aPad); + } + } + + function SetCellPadding($aRow,$aCol,$aPad) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetMargin($aPad,$aPad,$aPad,$aPad); + } + + + /*--------------------------------------------------------------------- + * Cell text orientation setting + *--------------------------------------------------------------------- + */ + function SetTextOrientation($aArgR1,$aC1=null,$aR2=null,$aC2=null,$aO=null) { + if( $aC1 !== null && $aR2!==null && $aC2!==null && $aPad!==null ) { + $this->_chkR($aArgR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + } + else { + $aO = $aArgR1; + $aR2 = $this->iSize[0]-1; $aArgR1 = 0; + $aC2 = $this->iSize[1]-1; $aC1 = 0; + } + for($i=$aArgR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->iVal->SetOrientation($aO); + } + } + } + + function SetRowTextOrientation($aRow,$aO) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->iVal->SetOrientation($aO); + } + } + + function SetColTextOrientation($aCol,$aO) { + $this->_chkC($aCol); + for($j=0; $j < $this->iSize[0]; ++$j) { + $this->iCells[$j][$aCol]->iVal->SetOrientation($aO); + } + } + + function SetCellTextOrientation($aRow,$aCol,$aO) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->iVal->SetOrientation($aO); + } + + + + + /*--------------------------------------------------------------------- + * Font color setting + *--------------------------------------------------------------------- + */ + + function SetColor($aArgR1,$aC1=null,$aR2=null,$aC2=null,$aArg=null) { + if( $aC1 !== null && $aR2!==null && $aC2!==null && $aArg!==null ) { + $this->_chkR($aArgR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + } + else { + $aArg = $aArgR1; + $aR2 = $this->iSize[0]-1; $aArgR1 = 0; + $aC2 = $this->iSize[1]-1; $aC1 = 0; + } + for($i=$aArgR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetFontColor($aArg); + } + } + } + + function SetRowColor($aRow,$aColor) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetFontColor($aColor); + } + } + + function SetColColor($aCol,$aColor) { + $this->_chkC($aCol); + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iCells[$i][$aCol]->SetFontColor($aColor); + } + } + + function SetCellColor($aRow,$aCol,$aColor) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetFontColor($aColor); + } + + /*--------------------------------------------------------------------- + * Fill color settings + *--------------------------------------------------------------------- + */ + + function SetFillColor($aArgR1,$aC1=null,$aR2=null,$aC2=null,$aArg=null) { + if( $aC1 !== null && $aR2!==null && $aC2!==null && $aArg!==null ) { + $this->_chkR($aArgR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + for($i=$aArgR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetFillColor($aArg); + } + } + } + else { + $this->iBGColor = $aArgR1; + } + } + + function SetRowFillColor($aRow,$aColor) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetFillColor($aColor); + } + } + + function SetColFillColor($aCol,$aColor) { + $this->_chkC($aCol); + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iCells[$i][$aCol]->SetFillColor($aColor); + } + } + + function SetCellFillColor($aRow,$aCol,$aColor) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetFillColor($aColor); + } + + /*--------------------------------------------------------------------- + * Font family setting + *--------------------------------------------------------------------- + */ + function SetFont() { + $numargs = func_num_args(); + if( $numargs == 2 || $numargs == 3 ) { + $aFF = func_get_arg(0); + $aFS = func_get_arg(1); + if( $numargs == 3 ) + $aFSize=func_get_arg(2); + else + $aFSize=10; + $aR2 = $this->iSize[0]-1; $aR1 = 0; + $aC2 = $this->iSize[1]-1; $aC1 = 0; + + } + elseif($numargs == 6 || $numargs == 7 ) { + $aR1 = func_get_arg(0); $aC1 = func_get_arg(1); + $aR2 = func_get_arg(2); $aC2 = func_get_arg(3); + $aFF = func_get_arg(4); $aFS = func_get_arg(5); + if( $numargs == 7 ) + $aFSize=func_get_arg(6); + else + $aFSize=10; + } + else { + JpGraphError::RaiseL(27003); + //('Wrong number of arguments to GTextTable::SetColor()'); + } + $this->_chkR($aR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + for($i=$aR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetFont($aFF,$aFS,$aFSize); + } + } + } + + function SetRowFont($aRow,$aFF,$aFS,$aFSize=10) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetFont($aFF,$aFS,$aFSize); + } + } + + function SetColFont($aCol,$aFF,$aFS,$aFSize=10) { + $this->_chkC($aCol); + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iCells[$i][$aCol]->SetFont($aFF,$aFS,$aFSize); + } + } + + function SetCellFont($aRow,$aCol,$aFF,$aFS,$aFSize=10) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetFont($aFF,$aFS,$aFSize); + } + + /*--------------------------------------------------------------------- + * Cell align settings + *--------------------------------------------------------------------- + */ + + function SetAlign($aR1HAlign=null,$aC1VAlign=null,$aR2=null,$aC2=null,$aHArg=null,$aVArg='center') { + if( $aC1VAlign !== null && $aR2!==null && $aC2!==null && $aHArg!==null ) { + $this->_chkR($aR1HAlign); $this->_chkC($aC1VAlign); + $this->_chkR($aR2); $this->_chkC($aC2); + } + else { + if( $aR1HAlign === null ) { + JpGraphError::RaiseL(27010); + } + if( $aC1VAlign === null ) { + $aC1VAlign = 'center'; + } + $aHArg = $aR1HAlign; + $aVArg = $aC1VAlign === null ? 'center' : $aC1VAlign ; + $aR2 = $this->iSize[0]-1; $aR1HAlign = 0; + $aC2 = $this->iSize[1]-1; $aC1VAlign = 0; + } + for($i=$aR1HAlign; $i <= $aR2; ++$i) { + for($j=$aC1VAlign; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetAlign($aHArg,$aVArg); + } + } + } + + function SetCellAlign($aRow,$aCol,$aHorAlign,$aVertAlign='bottom') { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetAlign($aHorAlign,$aVertAlign); + } + + function SetRowAlign($aRow,$aHorAlign,$aVertAlign='bottom') { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetAlign($aHorAlign,$aVertAlign); + } + } + + function SetColAlign($aCol,$aHorAlign,$aVertAlign='bottom') { + $this->_chkC($aCol); + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iCells[$i][$aCol]->SetAlign($aHorAlign,$aVertAlign); + } + } + + /*--------------------------------------------------------------------- + * Cell number format + *--------------------------------------------------------------------- + */ + + function SetNumberFormat($aArgR1,$aC1=null,$aR2=null,$aC2=null,$aArg=null) { + if( $aC1 !== null && $aR2!==null && $aC2!==null && $aArg!==null ) { + $this->_chkR($aArgR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + } + else { + $aArg = $aArgR1; + $aR2 = $this->iSize[0]-1; $aArgR1 = 0; + $aC2 = $this->iSize[1]-1; $aC1 = 0; + } + if( !is_string($aArg) ) { + JpGraphError::RaiseL(27013); // argument must be a string + } + for($i=$aArgR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + $this->iCells[$i][$j]->SetNumberFormat($aArg); + } + } + } + + function SetRowNumberFormat($aRow,$aF) { + $this->_chkR($aRow); + if( !is_string($aF) ) { + JpGraphError::RaiseL(27013); // argument must be a string + } + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetNumberFormat($aF); + } + } + + function SetColNumberFormat($aCol,$aF) { + $this->_chkC($aCol); + if( !is_string($aF) ) { + JpGraphError::RaiseL(27013); // argument must be a string + } + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iCells[$i][$aCol]->SetNumberFormat($aF); + } + } + + function SetCellNumberFormat($aRow,$aCol,$aF) { + $this->_chkR($aRow); $this->_chkC($aCol); + if( !is_string($aF) ) { + JpGraphError::RaiseL(27013); // argument must be a string + } + $this->iCells[$aRow][$aCol]->SetNumberFormat($aF); + } + + /*--------------------------------------------------------------------- + * Set row and column min size + *--------------------------------------------------------------------- + */ + + function SetMinColWidth($aColWidth,$aWidth=null) { + // If there is only one argument this means that all + // columns get set to the same width + if( $aWidth===null ) { + for($i=0; $i < $this->iSize[1]; ++$i) { + $this->iColWidth[$i] = $aColWidth; + } + } + else { + $this->_chkC($aColWidth); + $this->iColWidth[$aColWidth] = $aWidth; + } + } + + function SetMinRowHeight($aRowHeight,$aHeight=null) { + // If there is only one argument this means that all + // rows get set to the same height + if( $aHeight===null ) { + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iRowHeight[$i] = $aRowHeight; + } + } + else { + $this->_chkR($aRowHeight); + $this->iRowHeight[$aRowHeight] = $aHeight; + } + } + + /*--------------------------------------------------------------------- + * Grid line settings + *--------------------------------------------------------------------- + */ + + function SetGrid($aWeight=1,$aColor='black',$aStyle=TGRID_SINGLE) { + $rc = $this->iSize[0]; + $cc = $this->iSize[1]; + for($i=0; $i < $rc; ++$i) { + for($j=0; $j < $cc; ++$j) { + $this->iCells[$i][$j]->SetGridColor($aColor,$aColor); + $this->iCells[$i][$j]->SetGridWeight($aWeight,$aWeight); + $this->iCells[$i][$j]->SetGridStyle($aStyle); + } + } + } + + function SetColGrid($aCol,$aWeight=1,$aColor='black',$aStyle=TGRID_SINGLE) { + $this->_chkC($aCol); + for($i=0; $i < $this->iSize[0]; ++$i) { + $this->iCells[$i][$aCol]->SetGridWeight($aWeight); + $this->iCells[$i][$aCol]->SetGridColor($aColor); + $this->iCells[$i][$aCol]->SetGridStyle($aStyle); + } + } + + function SetRowGrid($aRow,$aWeight=1,$aColor='black',$aStyle=TGRID_SINGLE) { + $this->_chkR($aRow); + for($j=0; $j < $this->iSize[1]; ++$j) { + $this->iCells[$aRow][$j]->SetGridWeight(NULL,$aWeight); + $this->iCells[$aRow][$j]->SetGridColor(NULL,$aColor); + $this->iCells[$aRow][$j]->SetGridStyle(NULL,$aStyle); + } + } + + /*--------------------------------------------------------------------- + * Merge cells + *--------------------------------------------------------------------- + */ + + function MergeRow($aRow,$aHAlign='center',$aVAlign='center') { + $this->_chkR($aRow); + $this->MergeCells($aRow,0,$aRow,$this->iSize[1]-1,$aHAlign,$aVAlign); + } + + function MergeCol($aCol,$aHAlign='center',$aVAlign='center') { + $this->_chkC($aCol); + $this->MergeCells(0,$aCol,$this->iSize[0]-1,$aCol,$aHAlign,$aVAlign); + } + + function MergeCells($aR1,$aC1,$aR2,$aC2,$aHAlign='center',$aVAlign='center') { + if( $aR1 > $aR2 || $aC1 > $aC2 ) { + JpGraphError::RaiseL(27004); + //('GTextTable::MergeCells(). Specified cell range to be merged is not valid.'); + } + $this->_chkR($aR1); $this->_chkC($aC1); + $this->_chkR($aR2); $this->_chkC($aC2); + $rspan = $aR2-$aR1+1; + $cspan = $aC2-$aC1+1; + // Setup the parent cell for this merged group + if( $this->iCells[$aR1][$aC1]->IsMerged() ) { + JpGraphError::RaiseL(27005,$aR1,$aC1,$aR2,$aC2); + //("Cannot merge already merged cells in the range ($aR1,$aC1), ($aR2,$aC2)"); + } + $this->iCells[$aR1][$aC1]->SetRowColSpan($rspan,$cspan); + $this->iCells[$aR1][$aC1]->SetAlign($aHAlign,$aVAlign); + for($i=$aR1; $i <= $aR2; ++$i) { + for($j=$aC1; $j <= $aC2; ++$j) { + if( ! ($i == $aR1 && $j == $aC1) ) { + if( $this->iCells[$i][$j]->IsMerged() ) { + JpGraphError::RaiseL(27005,$aR1,$aC1,$aR2,$aC2); + //("Cannot merge already merged cells in the range ($aR1,$aC1), ($aR2,$aC2)"); + } + $this->iCells[$i][$j]->SetMerged($aR1,$aC1,true); + } + } + } + } + + + /*--------------------------------------------------------------------- + * CSIM methods + *--------------------------------------------------------------------- + */ + + function SetCSIMTarget($aTarget,$aAlt=null,$aAutoTarget=false) { + $m = $this->iSize[0]; + $n = $this->iSize[1]; + $csim = ''; + for($i=0; $i < $m; ++$i) { + for($j=0; $j < $n; ++$j) { + if( $aAutoTarget ) + $t = $aTarget."?row=$i&col=$j"; + else + $t = $aTarget; + $this->iCells[$i][$j]->SetCSIMTarget($t,$aAlt); + } + } + } + + function SetCellCSIMTarget($aRow,$aCol,$aTarget,$aAlt=null) { + $this->_chkR($aRow); + $this->_chkC($aCol); + $this->iCells[$aRow][$aCol]->SetCSIMTarget($aTarget,$aAlt); + } + + /*--------------------------------------------------------------------- + * Private methods + *--------------------------------------------------------------------- + */ + + function GetCSIMAreas() { + $m = $this->iSize[0]; + $n = $this->iSize[1]; + $csim = ''; + for($i=0; $i < $m; ++$i) { + for($j=0; $j < $n; ++$j) { + $csim .= $this->iCells[$i][$j]->GetCSIMArea(); + } + } + return $csim; + } + + function _chkC($aCol) { + if( ! $this->iInit ) { + JpGraphError::Raise(27014); // Table not initialized + } + if( $aCol < 0 || $aCol >= $this->iSize[1] ) + JpGraphError::RaiseL(27006,$aCol); + //("GTextTable:\nColumn argument ($aCol) is outside specified table size."); + } + + function _chkR($aRow) { + if( ! $this->iInit ) { + JpGraphError::Raise(27014); // Table not initialized + } + if( $aRow < 0 || $aRow >= $this->iSize[0] ) + JpGraphError::RaiseL(27007,$aRow); + //("GTextTable:\nRow argument ($aRow) is outside specified table size."); + } + + function _getScalePos() { + if( $this->iScaleXPos === null || $this->iScaleYPos === null ) { + return false; + } + return array($this->iScaleXPos, $this->iScaleYPos); + } + + function _autoSizeTable($aImg) { + // Get maximum column width and row height + $m = $this->iSize[0]; + $n = $this->iSize[1]; + $w=1;$h=1; + + // Get maximum row height per row + for($i=0; $i < $m; ++$i) { + $h=0; + for($j=0; $j < $n; ++$j) { + $h = max($h,$this->iCells[$i][$j]->GetHeight($aImg)); + } + if( isset($this->iRowHeight[$i]) ) { + $this->iRowHeight[$i] = max($h,$this->iRowHeight[$i]); + } + else + $this->iRowHeight[$i] = $h; + } + + // Get maximum col width per columns + for($j=0; $j < $n; ++$j) { + $w=0; + for($i=0; $i < $m; ++$i) { + $w = max($w,$this->iCells[$i][$j]->GetWidth($aImg)); + } + if( isset($this->iColWidth[$j]) ) { + $this->iColWidth[$j] = max($w,$this->iColWidth[$j]); + } + else + $this->iColWidth[$j] = $w; + } + } + + function _setcell($aRow,$aCol,$aVal='') { + if( isset($this->iCells[$aRow][$aCol]) ) { + $this->iCells[$aRow][$aCol]->Set($aVal); + } + else { + $this->iCells[$aRow][$aCol] = new GTextTableCell((string)$aVal,$aRow,$aCol); + $this->iCells[$aRow][$aCol]->Init($this); + } + } + + function StrokeWithScale($aImg,$aXScale,$aYScale) { + if( is_numeric($this->iScaleXPos) && is_numeric($this->iScaleYPos) ) { + $x = round($aXScale->Translate($this->iScaleXPos)); + $y = round($aYScale->Translate($this->iScaleYPos)); + $this->Stroke($aImg,$x,$y); + } + else { + $this->Stroke($aImg); + } + } + + function Stroke($aImg,$aX=NULL,$aY=NULL) { + if( $aX !== NULL && $aY !== NULL ) { + $this->iXPos = $aX; + $this->iYPos = $aY; + } + + $rc = $this->iSize[0]; // row count + $cc = $this->iSize[1]; // column count + + if( $rc == 0 || $cc == 0 ) { + JpGraphError::RaiseL(27009); + } + + // Adjust margins of each cell based on the weight of the grid. Each table grid line + // is actually occupying the left side and top part of each cell. + for($j=0; $j < $cc; ++$j) { + $this->iCells[0][$j]->iMarginTop += $this->iBorderWeight; + } + for($i=0; $i < $rc; ++$i) { + $this->iCells[$i][0]->iMarginLeft += $this->iBorderWeight; + } + for($i=0; $i < $rc; ++$i) { + for($j=0; $j < $cc; ++$j) { + $this->iCells[$i][$j]->AdjustMarginsForGrid(); + } + } + + // adjust row and column size depending on cell content + $this->_autoSizeTable($aImg); + + if( $this->iSize[1] != count($this->iColWidth) || $this->iSize[0] != count($this->iRowHeight) ) { + JpGraphError::RaiseL(27008); + //('Column and row size arrays must match the dimesnions of the table'); + } + + // Find out overall table size + $width=0; + for($i=0; $i < $cc; ++$i) { + $width += $this->iColWidth[$i]; + } + $height=0; + for($i=0; $i < $rc; ++$i) { + $height += $this->iRowHeight[$i]; + } + + // Adjust the X,Y position to alway be at the top left corner + // The anchor position, i.e. how the client want to interpret the specified + // x and y coordinate must be taken into account + switch( strtolower($this->iXAnchor) ) { + case 'left' : + break; + case 'center': + $this->iXPos -= round($width/2); + break; + case 'right': + $this->iXPos -= $width; + break; + } + switch( strtolower($this->iYAnchor) ) { + case 'top' : + break; + case 'center': + case 'middle': + $this->iYPos -= round($height/2); + break; + case 'bottom': + $this->iYPos -= $height; + break; + } + + // Set the overall background color of the table if set + if( $this->iBGColor !== '' ) { + $aImg->SetColor($this->iBGColor); + $aImg->FilledRectangle($this->iXPos,$this->iYPos,$this->iXPos+$width,$this->iYPos+$height); + } + + // Stroke all cells + $rpos=$this->iYPos; + for($i=0; $i < $rc; ++$i) { + $cpos=$this->iXPos; + for($j=0; $j < $cc; ++$j) { + // Calculate width and height of this cell if it is spanning + // more than one column or row + $cwidth=0; + for( $k=0; $k < $this->iCells[$i][$j]->iColSpan; ++$k ) { + $cwidth += $this->iColWidth[$j+$k]; + } + $cheight=0; + for( $k=0; $k < $this->iCells[$i][$j]->iRowSpan; ++$k ) { + $cheight += $this->iRowHeight[$i+$k]; + } + + $this->iCells[$i][$j]->Stroke($aImg,$cpos,$rpos,$cwidth,$cheight); + $cpos += $this->iColWidth[$j]; + } + $rpos += $this->iRowHeight[$i]; + } + + // Stroke outer border + $aImg->SetColor($this->iBorderColor); + if( $this->iBorderWeight == 1 ) + $aImg->Rectangle($this->iXPos,$this->iYPos,$this->iXPos+$width,$this->iYPos+$height); + else { + for( $i=0; $i < $this->iBorderWeight; ++$i ) + $aImg->Rectangle($this->iXPos+$i,$this->iYPos+$i, + $this->iXPos+$width-1+$this->iBorderWeight-$i, + $this->iYPos+$height-1+$this->iBorderWeight-$i); + } + } +} + +/* + EOF + */ +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_text.inc.php b/web/public_php/admin/jpgraph/jpgraph_text.inc.php new file mode 100644 index 000000000..7d0f6687f --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_text.inc.php @@ -0,0 +1,327 @@ +t = $aTxt; + $this->x = round($aXAbsPos); + $this->y = round($aYAbsPos); + $this->margin = 0; + } + //--------------- + // PUBLIC METHODS + // Set the string in the text object + function Set($aTxt) { + $this->t = $aTxt; + } + + // Alias for Pos() + function SetPos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") { + //$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign); + $this->x = $aXAbsPos; + $this->y = $aYAbsPos; + $this->halign = $aHAlign; + $this->valign = $aVAlign; + } + + function SetScalePos($aX,$aY) { + $this->iScalePosX = $aX; + $this->iScalePosY = $aY; + } + + // Specify alignment for the text + function Align($aHAlign,$aVAlign="top",$aParagraphAlign="") { + $this->halign = $aHAlign; + $this->valign = $aVAlign; + if( $aParagraphAlign != "" ) + $this->paragraph_align = $aParagraphAlign; + } + + // Alias + function SetAlign($aHAlign,$aVAlign="top",$aParagraphAlign="") { + $this->Align($aHAlign,$aVAlign,$aParagraphAlign); + } + + // Specifies the alignment for a multi line text + function ParagraphAlign($aAlign) { + $this->paragraph_align = $aAlign; + } + + // Specifies the alignment for a multi line text + function SetParagraphAlign($aAlign) { + $this->paragraph_align = $aAlign; + } + + function SetShadow($aShadowColor='gray',$aShadowWidth=3) { + $this->ishadowwidth=$aShadowWidth; + $this->shadow=$aShadowColor; + $this->boxed=true; + } + + function SetWordWrap($aCol) { + $this->iWordwrap = $aCol ; + } + + // Specify that the text should be boxed. fcolor=frame color, bcolor=border color, + // $shadow=drop shadow should be added around the text. + function SetBox($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) { + if( $aFrameColor === false ) { + $this->boxed=false; + } + else { + $this->boxed=true; + } + $this->fcolor=$aFrameColor; + $this->bcolor=$aBorderColor; + // For backwards compatibility when shadow was just true or false + if( $aShadowColor === true ) { + $aShadowColor = 'gray'; + } + $this->shadow=$aShadowColor; + $this->icornerradius=$aCornerRadius; + $this->ishadowwidth=$aShadowWidth; + } + + function SetBox2($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) { + $this->iBoxType=2; + $this->SetBox($aFrameColor,$aBorderColor,$aShadowColor,$aCornerRadius,$aShadowWidth); + } + + // Hide the text + function Hide($aHide=true) { + $this->hide=$aHide; + } + + // This looks ugly since it's not a very orthogonal design + // but I added this "inverse" of Hide() to harmonize + // with some classes which I designed more recently (especially) + // jpgraph_gantt + function Show($aShow=true) { + $this->hide=!$aShow; + } + + // Specify font + function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { + $this->font_family=$aFamily; + $this->font_style=$aStyle; + $this->font_size=$aSize; + } + + // Center the text between $left and $right coordinates + function Center($aLeft,$aRight,$aYAbsPos=false) { + $this->x = $aLeft + ($aRight-$aLeft )/2; + $this->halign = "center"; + if( is_numeric($aYAbsPos) ) + $this->y = $aYAbsPos; + } + + // Set text color + function SetColor($aColor) { + $this->color = $aColor; + } + + function SetAngle($aAngle) { + $this->SetOrientation($aAngle); + } + + // Orientation of text. Note only TTF fonts can have an arbitrary angle + function SetOrientation($aDirection=0) { + if( is_numeric($aDirection) ) + $this->dir=$aDirection; + elseif( $aDirection=="h" ) + $this->dir = 0; + elseif( $aDirection=="v" ) + $this->dir = 90; + else + JpGraphError::RaiseL(25051);//(" Invalid direction specified for text."); + } + + // Total width of text + function GetWidth($aImg) { + $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size); + $w = $aImg->GetTextWidth($this->t,$this->dir); + return $w; + } + + // Hight of font + function GetFontHeight($aImg) { + $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size); + $h = $aImg->GetFontHeight(); + return $h; + + } + + function GetTextHeight($aImg) { + $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size); + $h = $aImg->GetTextHeight($this->t,$this->dir); + return $h; + } + + function GetHeight($aImg) { + // Synonym for GetTextHeight() + $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size); + $h = $aImg->GetTextHeight($this->t,$this->dir); + return $h; + } + + // Set the margin which will be interpretated differently depending + // on the context. + function SetMargin($aMarg) { + $this->margin = $aMarg; + } + + function StrokeWithScale($aImg,$axscale,$ayscale) { + if( $this->iScalePosX === null || $this->iScalePosY === null ) { + $this->Stroke($aImg); + } + else { + $this->Stroke($aImg, + round($axscale->Translate($this->iScalePosX)), + round($ayscale->Translate($this->iScalePosY))); + } + } + + function SetCSIMTarget($aURITarget,$aAlt='',$aWinTarget='') { + $this->iCSIMtarget = $aURITarget; + $this->iCSIMalt = $aAlt; + $this->iCSIMWinTarget = $aWinTarget; + } + + function GetCSIMareas() { + if( $this->iCSIMtarget !== '' ) { + return $this->iCSIMarea; + } + else { + return ''; + } + } + + // Display text in image + function Stroke($aImg,$x=null,$y=null) { + + if( $x !== null ) $this->x = round($x); + if( $y !== null ) $this->y = round($y); + + // Insert newlines + if( $this->iWordwrap > 0 ) { + $this->t = wordwrap($this->t,$this->iWordwrap,"\n"); + } + + // If position been given as a fraction of the image size + // calculate the absolute position + if( $this->x < 1 && $this->x > 0 ) $this->x *= $aImg->width; + if( $this->y < 1 && $this->y > 0 ) $this->y *= $aImg->height; + + $aImg->PushColor($this->color); + $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size); + $aImg->SetTextAlign($this->halign,$this->valign); + + if( $this->boxed ) { + if( $this->fcolor=="nofill" ) { + $this->fcolor=false; + } + + $oldweight=$aImg->SetLineWeight(1); + + if( $this->iBoxType == 2 && $this->font_family > FF_FONT2+2 ) { + + $bbox = $aImg->StrokeBoxedText2($this->x, $this->y, + $this->t, $this->dir, + $this->fcolor, + $this->bcolor, + $this->shadow, + $this->paragraph_align, + 2,4, + $this->icornerradius, + $this->ishadowwidth); + } + else { + $bbox = $aImg->StrokeBoxedText($this->x,$this->y,$this->t, + $this->dir,$this->fcolor,$this->bcolor,$this->shadow, + $this->paragraph_align,3,3,$this->icornerradius, + $this->ishadowwidth); + } + + $aImg->SetLineWeight($oldweight); + } + else { + $debug=false; + $bbox = $aImg->StrokeText($this->x,$this->y,$this->t,$this->dir,$this->paragraph_align,$debug); + } + + // Create CSIM targets + $coords = $bbox[0].','.$bbox[1].','.$bbox[2].','.$bbox[3].','.$bbox[4].','.$bbox[5].','.$bbox[6].','.$bbox[7]; + $this->iCSIMarea = "iCSIMtarget)."\" "; + if( trim($this->iCSIMalt) != '' ) { + $this->iCSIMarea .= " alt=\"".$this->iCSIMalt."\" "; + $this->iCSIMarea .= " title=\"".$this->iCSIMalt."\" "; + } + if( trim($this->iCSIMWinTarget) != '' ) { + $this->iCSIMarea .= " target=\"".$this->iCSIMWinTarget."\" "; + } + $this->iCSIMarea .= " />\n"; + + $aImg->PopColor($this->color); + } + + function __get($name) { + + if (strpos($name, 'raw_') !== false) { + // if $name == 'raw_left_margin' , return $this->_left_margin; + $variable_name = '_' . str_replace('raw_', '', $name); + return $this->$variable_name; + } + + $variable_name = '_' . $name; + + if (isset($this->$variable_name)) { + return $this->$variable_name * SUPERSAMPLING_SCALE; + } else { + JpGraphError::RaiseL('25132', $name); + } + } + + function __set($name, $value) { + $this->{'_'.$name} = $value; + } +} // Class + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_theme.inc.php b/web/public_php/admin/jpgraph/jpgraph_theme.inc.php new file mode 100644 index 000000000..0cc54c476 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_theme.inc.php @@ -0,0 +1,136 @@ +color_index = 0; + } + /** + * + */ + abstract function GetColorList(); + + /** + * + */ + abstract function ApplyPlot($plot); + + + /** + * + */ + function SetupPlot($plot) { + if (is_array($plot)) { + foreach ($plot as $obj) { + $this->ApplyPlot($obj); + } + } else { + $this->ApplyPlot($plot); + } + } + + /** + * + */ + function ApplyGraph($graph) { + + $this->graph = $graph; + $method_name = ''; + + if (get_class($graph) == 'Graph') { + $method_name = 'SetupGraph'; + } else { + $method_name = 'Setup' . get_class($graph); + } + + if (method_exists($this, $method_name)) { + $this->$method_name($graph); + } else { + JpGraphError::RaiseL(30001, $method_name, $method_name); //Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs. + } + } + + /** + * + */ + function PreStrokeApply($graph) { + } + + /** + * + */ + function GetThemeColors($num = 30) { + $result_list = array(); + + $old_index = $this->color_index; + $this->color_index = 0; + $count = 0; + + $i = 0; + while (true) { + for ($j = 0; $j < count($this->GetColorList()); $j++) { + if (++$count > $num) { + break 2; + } + $result_list[] = $this->GetNextColor(); + } + $i++; + } + + $this->color_index = $old_index; + + return $result_list; + } + + /** + * + */ + function GetNextColor() { + $color_list = $this->GetColorList(); + + $color = null; + if (isset($color_list[$this->color_index])) { + $color = $color_list[$this->color_index]; + } else { + $color_count = count($color_list); + if ($color_count <= $this->color_index) { + $color_tmp = $color_list[$this->color_index % $color_count]; + $brightness = 1.0 - intval($this->color_index / $color_count) * 0.2; + $rgb = new RGB(); + $color = $color_tmp . ':' . $brightness; + $color = $rgb->Color($color); + $alpha = array_pop($color); + $color = $rgb->tryHexConversion($color); + if ($alpha) { + $color .= '@' . $alpha; + } + } + } + + $this->color_index++; + + return $color; + } + +} // Class + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_ttf.inc.php b/web/public_php/admin/jpgraph/jpgraph_ttf.inc.php new file mode 100644 index 000000000..5a1bc3e23 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_ttf.inc.php @@ -0,0 +1,631 @@ +g2312 == null ) { + include_once 'jpgraph_gb2312.php' ; + $this->g2312 = new GB2312toUTF8(); + } + return $this->g2312->gb2utf8($aTxt); + } + elseif( $aFF === FF_BIG5 ) { + if( !function_exists('iconv') ) { + JpGraphError::RaiseL(25006); + //('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).'); + } + return iconv('BIG5','UTF-8',$aTxt); + } + elseif( ASSUME_EUCJP_ENCODING && + ($aFF == FF_MINCHO || $aFF == FF_GOTHIC || $aFF == FF_PMINCHO || $aFF == FF_PGOTHIC) ) { + if( !function_exists('mb_convert_encoding') ) { + JpGraphError::RaiseL(25127); + } + return mb_convert_encoding($aTxt, 'UTF-8','EUC-JP'); + } + elseif( $aFF == FF_DAVID || $aFF == FF_MIRIAM || $aFF == FF_AHRON ) { + return LanguageConv::heb_iso2uni($aTxt); + } + else + return $aTxt; + } + + // Translate iso encoding to unicode + public static function iso2uni ($isoline){ + $uniline=''; + for ($i=0; $i < strlen($isoline); $i++){ + $thischar=substr($isoline,$i,1); + $charcode=ord($thischar); + $uniline.=($charcode>175) ? "&#" . (1040+($charcode-176)). ";" : $thischar; + } + return $uniline; + } + + // Translate greek iso encoding to unicode + public static function gr_iso2uni ($isoline) { + $uniline=''; + for ($i=0; $i < strlen($isoline); $i++) { + $thischar=substr($isoline,$i,1); + $charcode=ord($thischar); + $uniline.=($charcode>179 && $charcode!=183 && $charcode!=187 && $charcode!=189) ? "&#" . (900+($charcode-180)). ";" : $thischar; + } + return $uniline; + } + + // Translate greek win encoding to unicode + public static function gr_win2uni ($winline) { + $uniline=''; + for ($i=0; $i < strlen($winline); $i++) { + $thischar=substr($winline,$i,1); + $charcode=ord($thischar); + if ($charcode==161 || $charcode==162) { + $uniline.="&#" . (740+$charcode). ";"; + } + else { + $uniline.=(($charcode>183 && $charcode!=187 && $charcode!=189) || $charcode==180) ? "&#" . (900+($charcode-180)). ";" : $thischar; + } + } + return $uniline; + } + + public static function heb_iso2uni($isoline) { + $isoline = hebrev($isoline); + $o = ''; + + $n = strlen($isoline); + for($i=0; $i < $n; $i++) { + $c=ord( substr($isoline,$i,1) ); + $o .= ($c > 223) && ($c < 251) ? '&#'.(1264+$c).';' : chr($c); + } + return utf8_encode($o); + } +} + +//============================================================= +// CLASS TTF +// Description: Handle TTF font names and mapping and loading of +// font files +//============================================================= +class TTF { + private $font_files,$style_names; + + function __construct() { + + // String names for font styles to be used in error messages + $this->style_names=array( + FS_NORMAL =>'normal', + FS_BOLD =>'bold', + FS_ITALIC =>'italic', + FS_BOLDITALIC =>'bolditalic'); + + // File names for available fonts + $this->font_files=array( + FF_COURIER => array(FS_NORMAL =>'cour.ttf', + FS_BOLD =>'courbd.ttf', + FS_ITALIC =>'couri.ttf', + FS_BOLDITALIC =>'courbi.ttf' ), + FF_GEORGIA => array(FS_NORMAL =>'georgia.ttf', + FS_BOLD =>'georgiab.ttf', + FS_ITALIC =>'georgiai.ttf', + FS_BOLDITALIC =>'' ), + FF_TREBUCHE =>array(FS_NORMAL =>'trebuc.ttf', + FS_BOLD =>'trebucbd.ttf', + FS_ITALIC =>'trebucit.ttf', + FS_BOLDITALIC =>'trebucbi.ttf' ), + FF_VERDANA => array(FS_NORMAL =>'verdana.ttf', + FS_BOLD =>'verdanab.ttf', + FS_ITALIC =>'verdanai.ttf', + FS_BOLDITALIC =>'' ), + FF_TIMES => array(FS_NORMAL =>'times.ttf', + FS_BOLD =>'timesbd.ttf', + FS_ITALIC =>'timesi.ttf', + FS_BOLDITALIC =>'timesbi.ttf' ), + FF_COMIC => array(FS_NORMAL =>'comic.ttf', + FS_BOLD =>'comicbd.ttf', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + FF_ARIAL => array(FS_NORMAL =>'arial.ttf', + FS_BOLD =>'arialbd.ttf', + FS_ITALIC =>'ariali.ttf', + FS_BOLDITALIC =>'arialbi.ttf' ) , + FF_VERA => array(FS_NORMAL =>'Vera.ttf', + FS_BOLD =>'VeraBd.ttf', + FS_ITALIC =>'VeraIt.ttf', + FS_BOLDITALIC =>'VeraBI.ttf' ), + FF_VERAMONO => array(FS_NORMAL =>'VeraMono.ttf', + FS_BOLD =>'VeraMoBd.ttf', + FS_ITALIC =>'VeraMoIt.ttf', + FS_BOLDITALIC =>'VeraMoBI.ttf' ), + FF_VERASERIF=> array(FS_NORMAL =>'VeraSe.ttf', + FS_BOLD =>'VeraSeBd.ttf', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ) , + + /* Chinese fonts */ + FF_SIMSUN => array( + FS_NORMAL =>'simsun.ttc', + FS_BOLD =>'simhei.ttf', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + FF_CHINESE => array( + FS_NORMAL =>CHINESE_TTF_FONT, + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + FF_BIG5 => array( + FS_NORMAL =>CHINESE_TTF_FONT, + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + /* Japanese fonts */ + FF_MINCHO => array( + FS_NORMAL =>MINCHO_TTF_FONT, + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_PMINCHO => array( + FS_NORMAL =>PMINCHO_TTF_FONT, + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_GOTHIC => array( + FS_NORMAL =>GOTHIC_TTF_FONT, + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_PGOTHIC => array( + FS_NORMAL =>PGOTHIC_TTF_FONT, + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + /* Hebrew fonts */ + FF_DAVID => array( + FS_NORMAL =>'DAVIDNEW.TTF', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_MIRIAM => array( + FS_NORMAL =>'MRIAMY.TTF', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_AHRON => array( + FS_NORMAL =>'ahronbd.ttf', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + /* Misc fonts */ + FF_DIGITAL => array( + FS_NORMAL =>'DIGIRU__.TTF', + FS_BOLD =>'Digirtu_.ttf', + FS_ITALIC =>'Digir___.ttf', + FS_BOLDITALIC =>'DIGIRT__.TTF' ), + + /* This is an experimental font for the speedometer development + FF_SPEEDO => array( + FS_NORMAL =>'Speedo.ttf', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + */ + + FF_COMPUTER => array( + FS_NORMAL =>'COMPUTER.TTF', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_CALCULATOR => array( + FS_NORMAL =>'Triad_xs.ttf', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + /* Dejavu fonts */ + FF_DV_SANSSERIF => array( + FS_NORMAL =>array('DejaVuSans.ttf'), + FS_BOLD =>array('DejaVuSans-Bold.ttf','DejaVuSansBold.ttf'), + FS_ITALIC =>array('DejaVuSans-Oblique.ttf','DejaVuSansOblique.ttf'), + FS_BOLDITALIC =>array('DejaVuSans-BoldOblique.ttf','DejaVuSansBoldOblique.ttf') ), + + FF_DV_SANSSERIFMONO => array( + FS_NORMAL =>array('DejaVuSansMono.ttf','DejaVuMonoSans.ttf'), + FS_BOLD =>array('DejaVuSansMono-Bold.ttf','DejaVuMonoSansBold.ttf'), + FS_ITALIC =>array('DejaVuSansMono-Oblique.ttf','DejaVuMonoSansOblique.ttf'), + FS_BOLDITALIC =>array('DejaVuSansMono-BoldOblique.ttf','DejaVuMonoSansBoldOblique.ttf') ), + + FF_DV_SANSSERIFCOND => array( + FS_NORMAL =>array('DejaVuSansCondensed.ttf','DejaVuCondensedSans.ttf'), + FS_BOLD =>array('DejaVuSansCondensed-Bold.ttf','DejaVuCondensedSansBold.ttf'), + FS_ITALIC =>array('DejaVuSansCondensed-Oblique.ttf','DejaVuCondensedSansOblique.ttf'), + FS_BOLDITALIC =>array('DejaVuSansCondensed-BoldOblique.ttf','DejaVuCondensedSansBoldOblique.ttf') ), + + FF_DV_SERIF => array( + FS_NORMAL =>array('DejaVuSerif.ttf'), + FS_BOLD =>array('DejaVuSerif-Bold.ttf','DejaVuSerifBold.ttf'), + FS_ITALIC =>array('DejaVuSerif-Italic.ttf','DejaVuSerifItalic.ttf'), + FS_BOLDITALIC =>array('DejaVuSerif-BoldItalic.ttf','DejaVuSerifBoldItalic.ttf') ), + + FF_DV_SERIFCOND => array( + FS_NORMAL =>array('DejaVuSerifCondensed.ttf','DejaVuCondensedSerif.ttf'), + FS_BOLD =>array('DejaVuSerifCondensed-Bold.ttf','DejaVuCondensedSerifBold.ttf'), + FS_ITALIC =>array('DejaVuSerifCondensed-Italic.ttf','DejaVuCondensedSerifItalic.ttf'), + FS_BOLDITALIC =>array('DejaVuSerifCondensed-BoldItalic.ttf','DejaVuCondensedSerifBoldItalic.ttf') ), + + + /* Placeholders for defined fonts */ + FF_USERFONT1 => array( + FS_NORMAL =>'', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_USERFONT2 => array( + FS_NORMAL =>'', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + FF_USERFONT3 => array( + FS_NORMAL =>'', + FS_BOLD =>'', + FS_ITALIC =>'', + FS_BOLDITALIC =>'' ), + + ); + } + + //--------------- + // PUBLIC METHODS + // Create the TTF file from the font specification + function File($family,$style=FS_NORMAL) { + $fam = @$this->font_files[$family]; + if( !$fam ) { + 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/"); + } + $ff = @$fam[$style]; + + // There are several optional file names. They are tried in order + // and the first one found is used + if( !is_array($ff) ) { + $ff = array($ff); + } + + $jpgraph_font_dir = dirname(__FILE__).'/fonts/'; + + foreach ($ff as $font_file) { + // All font families are guaranteed to have the normal style + + if( $font_file==='' ) + 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].'.'); + if( !$font_file ) { + JpGraphError::RaiseL(25048,$fam);//("Unknown font style specification [$fam]."); + } + + // check jpgraph/src/fonts dir + $jpgraph_font_file = $jpgraph_font_dir . $font_file; + if (file_exists($jpgraph_font_file) === true && is_readable($jpgraph_font_file) === true) { + $font_file = $jpgraph_font_file; + break; + } + + // check OS font dir + if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) { + $font_file = MBTTF_DIR.$font_file; + } else { + $font_file = TTF_DIR.$font_file; + } + if (file_exists($font_file) === true && is_readable($font_file) === true) { + break; + } + } + + if( !file_exists($font_file) ) { + JpGraphError::RaiseL(25049,$font_file);//("Font file \"$font_file\" is not readable or does not exist."); + } + + return $font_file; + } + + function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->font_files[FF_USERFONT] = + array(FS_NORMAL => $aNormal, + FS_BOLD => $aBold, + FS_ITALIC => $aItalic, + FS_BOLDITALIC => $aBoldIt ) ; + } + + function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->font_files[FF_USERFONT1] = + array(FS_NORMAL => $aNormal, + FS_BOLD => $aBold, + FS_ITALIC => $aItalic, + FS_BOLDITALIC => $aBoldIt ) ; + } + + function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->font_files[FF_USERFONT2] = + array(FS_NORMAL => $aNormal, + FS_BOLD => $aBold, + FS_ITALIC => $aItalic, + FS_BOLDITALIC => $aBoldIt ) ; + } + + function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') { + $this->font_files[FF_USERFONT3] = + array(FS_NORMAL => $aNormal, + FS_BOLD => $aBold, + FS_ITALIC => $aItalic, + FS_BOLDITALIC => $aBoldIt ) ; + } + +} // Class + + +//============================================================================= +// CLASS SymChar +// Description: Code values for some commonly used characters that +// normally isn't available directly on the keyboard, for example +// mathematical and greek symbols. +//============================================================================= +class SymChar { + static function Get($aSymb,$aCapital=FALSE) { + $iSymbols = array( + /* Greek */ + array('alpha','03B1','0391'), + array('beta','03B2','0392'), + array('gamma','03B3','0393'), + array('delta','03B4','0394'), + array('epsilon','03B5','0395'), + array('zeta','03B6','0396'), + array('ny','03B7','0397'), + array('eta','03B8','0398'), + array('theta','03B8','0398'), + array('iota','03B9','0399'), + array('kappa','03BA','039A'), + array('lambda','03BB','039B'), + array('mu','03BC','039C'), + array('nu','03BD','039D'), + array('xi','03BE','039E'), + array('omicron','03BF','039F'), + array('pi','03C0','03A0'), + array('rho','03C1','03A1'), + array('sigma','03C3','03A3'), + array('tau','03C4','03A4'), + array('upsilon','03C5','03A5'), + array('phi','03C6','03A6'), + array('chi','03C7','03A7'), + array('psi','03C8','03A8'), + array('omega','03C9','03A9'), + /* Money */ + array('euro','20AC'), + array('yen','00A5'), + array('pound','20A4'), + /* Math */ + array('approx','2248'), + array('neq','2260'), + array('not','2310'), + array('def','2261'), + array('inf','221E'), + array('sqrt','221A'), + array('int','222B'), + /* Misc */ + array('copy','00A9'), + array('para','00A7'), + array('tm','2122'), /* Trademark symbol */ + array('rtm','00AE'), /* Registered trademark */ + array('degree','00b0'), + array('lte','2264'), /* Less than or equal */ + array('gte','2265'), /* Greater than or equal */ + + ); + + $n = count($iSymbols); + $i=0; + $found = false; + $aSymb = strtolower($aSymb); + while( $i < $n && !$found ) { + $found = $aSymb === $iSymbols[$i++][0]; + } + if( $found ) { + $ca = $iSymbols[--$i]; + if( $aCapital && count($ca)==3 ) + $s = $ca[2]; + else + $s = $ca[1]; + return sprintf('&#%04d;',hexdec($s)); + } + else + return ''; + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_utils.inc b/web/public_php/admin/jpgraph/jpgraph_utils.inc deleted file mode 100644 index 401a7431d..000000000 --- a/web/public_php/admin/jpgraph/jpgraph_utils.inc +++ /dev/null @@ -1,251 +0,0 @@ -iFunc = $aFunc; - $this->iXFunc = $aXFunc; - } - - function E($aXMin,$aXMax,$aSteps=50) { - $this->iMin = $aXMin; - $this->iMax = $aXMax; - $this->iStepSize = ($aXMax-$aXMin)/$aSteps; - - if( $this->iXFunc != '' ) - $t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}'; - elseif( $this->iFunc != '' ) - $t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;'; - else - JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. '); - - @eval($t); - - // If there is an error in the function specifcation this is the only - // way we can discover that. - if( empty($xa) || empty($ya) ) - JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification '); - - return array($xa,$ya); - } -} - -//============================================================================= -// CLASS SymChar -// Description: Code values for some commonly used characters that -// normally isn't available directly on the keyboard, for example -// mathematical and greek symbols. -//============================================================================= -class SymChar { - function Get($aSymb,$aCapital=FALSE) { - static $iSymbols = array( - /* Greek */ - array('alpha','03B1','0391'), - array('beta','03B2','0392'), - array('gamma','03B3','0393'), - array('delta','03B4','0394'), - array('epsilon','03B5','0395'), - array('zeta','03B6','0396'), - array('ny','03B7','0397'), - array('eta','03B8','0398'), - array('theta','03B8','0398'), - array('iota','03B9','0399'), - array('kappa','03BA','039A'), - array('lambda','03BB','039B'), - array('mu','03BC','039C'), - array('nu','03BD','039D'), - array('xi','03BE','039E'), - array('omicron','03BF','039F'), - array('pi','03C0','03A0'), - array('rho','03C1','03A1'), - array('sigma','03C3','03A3'), - array('tau','03C4','03A4'), - array('upsilon','03C5','03A5'), - array('phi','03C6','03A6'), - array('chi','03C7','03A7'), - array('psi','03C8','03A8'), - array('omega','03C9','03A9'), - /* Money */ - array('euro','20AC'), - array('yen','00A5'), - array('pound','20A4'), - /* Math */ - array('approx','2248'), - array('neq','2260'), - array('not','2310'), - array('def','2261'), - array('inf','221E'), - array('sqrt','221A'), - array('int','222B'), - /* Misc */ - array('copy','00A9'), - array('para','00A7')); - - $n = count($iSymbols); - $i=0; - $found = false; - $aSymb = strtolower($aSymb); - while( $i < $n && !$found ) { - $found = $aSymb === $iSymbols[$i++][0]; - } - if( $found ) { - $ca = $iSymbols[--$i]; - if( $aCapital && count($ca)==3 ) - $s = $ca[2]; - else - $s = $ca[1]; - return sprintf('&#%04d;',hexdec($s)); - } - else - return ''; - } -} - - -//============================================================================= -// CLASS DateScaleUtils -// Description: Help to create a manual date scale -//============================================================================= -DEFINE('DSUTILS_MONTH1',1); // Major and minor ticks on a monthly basis - -class DateScaleUtils { - - function GetTicks($aData,$aType=1) { - - // - // Find out the range of the data in order to get the limits for the loops - // that creates the position for the labels. This code is generic and can be - // used for any ranges of the data. - // - $n = count($aData); - $startmonth = date('n',$aData[0]); - $startday = date('j',$aData[0]); - $startyear = date('Y',$aData[0]); - $endmonth = date('n',$aData[$n-1]); - $endyear = date('Y',$aData[$n-1]); - $endday = date('j',$aData[$n-1]); - - // - // Now create the positions for all the ticks. In this example we - // put a tick at the start of every month and also on the very - // first and last X-position. - // - $tickPositions = array(); - $minTickPositions = array(); - $i=0;$j=0; - - // Uncomment this line to put a label at the very left data pos - // $tickPositions[$i++] = $datax[0]; - - $m = $startmonth; - $y = $startyear; - // Skip the first month label if it is before the startdate - if( $startday == 1 ) { - $tickPositions[$i++] = mktime(0,0,0,$m,1,$y); - } - if( $startday < 15 ) { - $minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); - } - ++$m; - - // Loop through all the years included in the scale - for($y=$startyear; $y <= $endyear; ++$y ) { - // Loop through all the months. There are three cases to consider: - // 1. We are in the first year and must start with the startmonth - // 2. We are in the end year and we must stop at last month of the scale - // 3. A year in between where we run through all the 12 months - $stopmonth = $y == $endyear ? $endmonth : 12; - while( $m <= $stopmonth ) { - switch( $aType ) { - case 1: - // Set minor tick at the middle of the month - if( $m <= $stopmonth ) { - if( !($y==$endyear && $m==$stopmonth && $endday < 15) ) - $minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); - } - // Major at month - // Get timestamp of first hour of first day in each month - $tickPositions[$i++] = mktime(0,0,0,$m,1,$y); - - break; - } - ++$m; - } - $m=1; - } - - // For the case where all dates are within the same month - // we want to make sure we have at least two ticks on the scale - // since the scale want work properly otherwise - if($startmonth == $endmonth && $startyear == $endyear && $aType==1 ) { - $tickPositions[$i++] = mktime(0 ,0 ,0, $startmonth + 1, 1, $startyear); - } - - // Uncomment this line to put a label at the very right data pos - // $tickPositions[$i] = $datax[$n-1]; - - return array($tickPositions,$minTickPositions); - } - -} - -//============================================================================= -// Class ReadFileData -//============================================================================= -Class ReadFileData { - - //---------------------------------------------------------------------------- - // Desciption: - // Read numeric data from a file. - // Each value should be separated by either a new line or by a specified - // separator character (default is ','). - // Before returning the data each value is converted to a proper float - // value. The routine is robust in the sense that non numeric data in the - // file will be discarded. - // - // Returns: - // The number of data values read on success, FALSE on failure - //---------------------------------------------------------------------------- - function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) { - $rh = fopen($aFile,'r'); - if( $rh === false ) - return false; - $tmp = array(); - $lineofdata = fgetcsv($rh, 1000, ','); - while ( $lineofdata !== FALSE) { - $tmp = array_merge($tmp,$lineofdata); - $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar); - } - fclose($rh); - - // Now make sure that all data is numeric. By default - // all data is read as strings - $n = count($tmp); - $aData = array(); - $cnt=0; - for($i=0; $i < $n; ++$i) { - if( $tmp[$i] !== "" ) { - $aData[$cnt++] = floatval($tmp[$i]); - } - } - return $cnt; - } -} - -?> \ No newline at end of file diff --git a/web/public_php/admin/jpgraph/jpgraph_utils.inc.php b/web/public_php/admin/jpgraph/jpgraph_utils.inc.php new file mode 100644 index 000000000..f0d002c14 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_utils.inc.php @@ -0,0 +1,685 @@ +iFunc = $aFunc; + $this->iXFunc = $aXFunc; + } + + function E($aXMin,$aXMax,$aSteps=50) { + $this->iMin = $aXMin; + $this->iMax = $aXMax; + $this->iStepSize = ($aXMax-$aXMin)/$aSteps; + + if( $this->iXFunc != '' ) + $t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}'; + elseif( $this->iFunc != '' ) + $t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;'; + else + JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. '); + + @eval($t); + + // If there is an error in the function specifcation this is the only + // way we can discover that. + if( empty($xa) || empty($ya) ) + JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification '); + + return array($xa,$ya); + } +} + + +//============================================================================= +// CLASS DateScaleUtils +// Description: Help to create a manual date scale +//============================================================================= +define('DSUTILS_MONTH',1); // Major and minor ticks on a monthly basis +define('DSUTILS_MONTH1',1); // Major and minor ticks on a monthly basis +define('DSUTILS_MONTH2',2); // Major ticks on a bi-monthly basis +define('DSUTILS_MONTH3',3); // Major icks on a tri-monthly basis +define('DSUTILS_MONTH6',4); // Major on a six-monthly basis +define('DSUTILS_WEEK1',5); // Major ticks on a weekly basis +define('DSUTILS_WEEK2',6); // Major ticks on a bi-weekly basis +define('DSUTILS_WEEK4',7); // Major ticks on a quod-weekly basis +define('DSUTILS_DAY1',8); // Major ticks on a daily basis +define('DSUTILS_DAY2',9); // Major ticks on a bi-daily basis +define('DSUTILS_DAY4',10); // Major ticks on a qoud-daily basis +define('DSUTILS_YEAR1',11); // Major ticks on a yearly basis +define('DSUTILS_YEAR2',12); // Major ticks on a bi-yearly basis +define('DSUTILS_YEAR5',13); // Major ticks on a five-yearly basis + + +class DateScaleUtils { + public static $iMin=0, $iMax=0; + + private static $starthour,$startmonth, $startday, $startyear; + private static $endmonth, $endyear, $endday; + private static $tickPositions=array(),$minTickPositions=array(); + private static $iUseWeeks = true; + + static function UseWeekFormat($aFlg) { + self::$iUseWeeks = $aFlg; + } + + static function doYearly($aType,$aMinor=false) { + $i=0; $j=0; + $m = self::$startmonth; + $y = self::$startyear; + + if( self::$startday == 1 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); + } + ++$m; + + + switch( $aType ) { + case DSUTILS_YEAR1: + for($y=self::$startyear; $y <= self::$endyear; ++$y ) { + if( $aMinor ) { + while( $m <= 12 ) { + if( !($y == self::$endyear && $m > self::$endmonth) ) { + self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); + } + ++$m; + } + $m=1; + } + self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y); + } + break; + case DSUTILS_YEAR2: + $y=self::$startyear; + while( $y <= self::$endyear ) { + self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y); + for($k=0; $k < 1; ++$k ) { + ++$y; + if( $aMinor ) { + self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y); + } + } + ++$y; + } + break; + case DSUTILS_YEAR5: + $y=self::$startyear; + while( $y <= self::$endyear ) { + self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y); + for($k=0; $k < 4; ++$k ) { + ++$y; + if( $aMinor ) { + self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y); + } + } + ++$y; + } + break; + } + } + + static function doDaily($aType,$aMinor=false) { + $m = self::$startmonth; + $y = self::$startyear; + $d = self::$startday; + $h = self::$starthour; + $i=0;$j=0; + + if( $h == 0 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y); + } + $t = mktime(0,0,0,$m,$d,$y); + + switch($aType) { + case DSUTILS_DAY1: + while( $t <= self::$iMax ) { + $t = strtotime('+1 day',$t); + self::$tickPositions[$i++] = $t; + if( $aMinor ) { + self::$minTickPositions[$j++] = strtotime('+12 hours',$t); + } + } + break; + case DSUTILS_DAY2: + while( $t <= self::$iMax ) { + $t = strtotime('+1 day',$t); + if( $aMinor ) { + self::$minTickPositions[$j++] = $t; + } + $t = strtotime('+1 day',$t); + self::$tickPositions[$i++] = $t; + } + break; + case DSUTILS_DAY4: + while( $t <= self::$iMax ) { + for($k=0; $k < 3; ++$k ) { + $t = strtotime('+1 day',$t); + if( $aMinor ) { + self::$minTickPositions[$j++] = $t; + } + } + $t = strtotime('+1 day',$t); + self::$tickPositions[$i++] = $t; + } + break; + } + } + + static function doWeekly($aType,$aMinor=false) { + $hpd = 3600*24; + $hpw = 3600*24*7; + // Find out week number of min date + $thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7); + $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7; + $daynumber = date('w',self::$iMin); + if( $daynumber == 0 ) $daynumber = 7; + $m = self::$startmonth; + $y = self::$startyear; + $d = self::$startday; + $i=0;$j=0; + // The assumption is that the weeks start on Monday. If the first day + // is later in the week then the first week tick has to be on the following + // week. + if( $daynumber == 1 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y); + $t = mktime(0,0,0,$m,$d,$y) + $hpw; + } + else { + $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber); + } + + switch($aType) { + case DSUTILS_WEEK1: + $cnt=0; + break; + case DSUTILS_WEEK2: + $cnt=1; + break; + case DSUTILS_WEEK4: + $cnt=3; + break; + } + while( $t <= self::$iMax ) { + self::$tickPositions[$i++] = $t; + for($k=0; $k < $cnt; ++$k ) { + $t += $hpw; + if( $aMinor ) { + self::$minTickPositions[$j++] = $t; + } + } + $t += $hpw; + } + } + + static function doMonthly($aType,$aMinor=false) { + $monthcount=0; + $m = self::$startmonth; + $y = self::$startyear; + $i=0; $j=0; + + // Skip the first month label if it is before the startdate + if( self::$startday == 1 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); + $monthcount=1; + } + if( $aType == 1 ) { + if( self::$startday < 15 ) { + self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); + } + } + ++$m; + + // Loop through all the years included in the scale + for($y=self::$startyear; $y <= self::$endyear; ++$y ) { + // Loop through all the months. There are three cases to consider: + // 1. We are in the first year and must start with the startmonth + // 2. We are in the end year and we must stop at last month of the scale + // 3. A year in between where we run through all the 12 months + $stopmonth = $y == self::$endyear ? self::$endmonth : 12; + while( $m <= $stopmonth ) { + switch( $aType ) { + case DSUTILS_MONTH1: + // Set minor tick at the middle of the month + if( $aMinor ) { + if( $m <= $stopmonth ) { + if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) ) + self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); + } + } + // Major at month + // Get timestamp of first hour of first day in each month + self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); + + break; + case DSUTILS_MONTH2: + if( $aMinor ) { + // Set minor tick at start of each month + self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); + } + + // Major at every second month + // Get timestamp of first hour of first day in each month + if( $monthcount % 2 == 0 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); + } + break; + case DSUTILS_MONTH3: + if( $aMinor ) { + // Set minor tick at start of each month + self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); + } + // Major at every third month + // Get timestamp of first hour of first day in each month + if( $monthcount % 3 == 0 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); + } + break; + case DSUTILS_MONTH6: + if( $aMinor ) { + // Set minor tick at start of each month + self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); + } + // Major at every third month + // Get timestamp of first hour of first day in each month + if( $monthcount % 6 == 0 ) { + self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); + } + break; + } + ++$m; + ++$monthcount; + } + $m=1; + } + + // For the case where all dates are within the same month + // we want to make sure we have at least two ticks on the scale + // since the scale want work properly otherwise + if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) { + self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear); + } + + return array(self::$tickPositions,self::$minTickPositions); + } + + static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) { + $n = count($aData); + return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints); + } + + static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) { + $diff = $aMax - $aMin; + $spd = 3600*24; + $spw = $spd*7; + $spm = $spd*30; + $spy = $spd*352; + + if( self::$iUseWeeks ) + $w = 'W'; + else + $w = 'd M'; + + // Decision table for suitable scales + // First value: Main decision point + // Second value: Array of formatting depending on divisor for wanted max number of ticks. ,.. + $tt = array( + array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')), + 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)), + 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')), + 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'))); + + $ntt = count($tt); + $nd = floor($diff/$spd); + for($i=0; $i < $ntt; ++$i ) { + if( $diff <= $tt[$i][0] || $i==$ntt-1) { + $t = $tt[$i][1]; + $n = count($t)/3; + for( $j=0; $j < $n; ++$j ) { + if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) { + $type = $t[3*$j+1]; + $fs = $t[3*$j+2]; + list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor); + return array($fs,$tickPositions,$minTickPositions,$type); + } + } + } + } + } + + static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) { + self::$starthour = date('G',$aMin); + self::$startmonth = date('n',$aMin); + self::$startday = date('j',$aMin); + self::$startyear = date('Y',$aMin); + self::$endmonth = date('n',$aMax); + self::$endyear = date('Y',$aMax); + self::$endday = date('j',$aMax); + self::$iMin = $aMin; + self::$iMax = $aMax; + + if( $aType <= DSUTILS_MONTH6 ) { + self::doMonthly($aType,$aMinor); + } + elseif( $aType <= DSUTILS_WEEK4 ) { + self::doWeekly($aType,$aMinor); + } + elseif( $aType <= DSUTILS_DAY4 ) { + self::doDaily($aType,$aMinor); + } + elseif( $aType <= DSUTILS_YEAR5 ) { + self::doYearly($aType,$aMinor); + } + else { + JpGraphError::RaiseL(24003); + } + // put a label at the very left data pos + if( $aEndPoints ) { + $tickPositions[$i++] = $aData[0]; + } + + // put a label at the very right data pos + if( $aEndPoints ) { + $tickPositions[$i] = $aData[$n-1]; + } + + return array(self::$tickPositions,self::$minTickPositions); + } +} + +//============================================================================= +// Class ReadFileData +//============================================================================= +Class ReadFileData { + //---------------------------------------------------------------------------- + // Desciption: + // Read numeric data from a file. + // Each value should be separated by either a new line or by a specified + // separator character (default is ','). + // Before returning the data each value is converted to a proper float + // value. The routine is robust in the sense that non numeric data in the + // file will be discarded. + // + // Returns: + // The number of data values read on success, FALSE on failure + //---------------------------------------------------------------------------- + static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) { + $rh = @fopen($aFile,'r'); + if( $rh === false ) { + return false; + } + $tmp = array(); + $lineofdata = fgetcsv($rh, 1000, ','); + while ( $lineofdata !== FALSE) { + $tmp = array_merge($tmp,$lineofdata); + $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar); + } + fclose($rh); + + // Now make sure that all data is numeric. By default + // all data is read as strings + $n = count($tmp); + $aData = array(); + $cnt=0; + for($i=0; $i < $n; ++$i) { + if( $tmp[$i] !== "" ) { + $aData[$cnt++] = floatval($tmp[$i]); + } + } + return $cnt; + } + + //---------------------------------------------------------------------------- + // Desciption: + // Read numeric data from a file. + // Each value should be separated by either a new line or by a specified + // separator character (default is ','). + // Before returning the data each value is converted to a proper float + // value. The routine is robust in the sense that non numeric data in the + // file will be discarded. + // + // Options: + // 'separator' => ',', + // 'enclosure' => '"', + // 'readlength' => 1024, + // 'ignore_first' => false, + // 'first_as_key' => false + // 'escape' => '\', # PHP >= 5.3 only + // + // Returns: + // The number of lines read on success, FALSE on failure + //---------------------------------------------------------------------------- + static function FromCSV2($aFile, &$aData, $aOptions = array()) { + $aDefaults = array( + 'separator' => ',', + 'enclosure' => chr(34), + 'escape' => chr(92), + 'readlength' => 1024, + 'ignore_first' => false, + 'first_as_key' => false + ); + + $aOptions = array_merge( + $aDefaults, is_array($aOptions) ? $aOptions : array()); + + if( $aOptions['first_as_key'] ) { + $aOptions['ignore_first'] = true; + } + + $rh = @fopen($aFile, 'r'); + + if( $rh === false ) { + return false; + } + + $aData = array(); + $aLine = fgetcsv($rh, + $aOptions['readlength'], + $aOptions['separator'], + $aOptions['enclosure'] + /*, $aOptions['escape'] # PHP >= 5.3 only */ + ); + + // Use numeric array keys for the columns by default + // If specified use first lines values as assoc keys instead + $keys = array_keys($aLine); + if( $aOptions['first_as_key'] ) { + $keys = array_values($aLine); + } + + $num_lines = 0; + $num_cols = count($aLine); + + while ($aLine !== false) { + if( is_array($aLine) && count($aLine) != $num_cols ) { + JpGraphError::RaiseL(24004); + // 'ReadCSV2: Column count mismatch in %s line %d' + } + + // fgetcsv returns NULL for empty lines + if( !is_null($aLine) ) { + $num_lines++; + + if( !($aOptions['ignore_first'] && $num_lines == 1) && is_numeric($aLine[0]) ) { + for( $i = 0; $i < $num_cols; $i++ ) { + $aData[ $keys[$i] ][] = floatval($aLine[$i]); + } + } + } + + $aLine = fgetcsv($rh, + $aOptions['readlength'], + $aOptions['separator'], + $aOptions['enclosure'] + /*, $aOptions['escape'] # PHP >= 5.3 only*/ + ); + } + + fclose($rh); + + if( $aOptions['ignore_first'] ) { + $num_lines--; + } + + return $num_lines; + } + + // Read data from two columns in a plain text file + static function From2Col($aFile, $aCol1, $aCol2, $aSepChar=' ') { + $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); + if( $lines === false ) { + return false; + } + $s = '/[\s]+/'; + if( $aSepChar == ',' ) { + $s = '/[\s]*,[\s]*/'; + } + elseif( $aSepChar == ';' ) { + $s = '/[\s]*;[\s]*/'; + } + foreach( $lines as $line => $datarow ) { + $split = preg_split($s,$datarow); + $aCol1[] = floatval(trim($split[0])); + $aCol2[] = floatval(trim($split[1])); + } + + return count($lines); + } + + // Read data from one columns in a plain text file + static function From1Col($aFile, $aCol1) { + $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); + if( $lines === false ) { + return false; + } + foreach( $lines as $line => $datarow ) { + $aCol1[] = floatval(trim($datarow)); + } + + return count($lines); + } + + static function FromMatrix($aFile,$aSepChar=' ') { + $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); + if( $lines === false ) { + return false; + } + $mat = array(); + $reg = '/'.$aSepChar.'/'; + foreach( $lines as $line => $datarow ) { + $row = preg_split($reg,trim($datarow)); + foreach ($row as $key => $cell ) { + $row[$key] = floatval(trim($cell)); + } + $mat[] = $row; + } + return $mat; + } + + +} + +define('__LR_EPSILON', 1.0e-8); +//============================================================================= +// Class LinearRegression +//============================================================================= +class LinearRegression { + private $ix=array(),$iy=array(); + private $ib=0, $ia=0; + private $icalculated=false; + public $iDet=0, $iCorr=0, $iStdErr=0; + + public function __construct($aDataX,$aDataY) { + if( count($aDataX) !== count($aDataY) ) { + JpGraph::Raise('LinearRegression: X and Y data array must be of equal length.'); + } + $this->ix = $aDataX; + $this->iy = $aDataY; + } + + public function Calc() { + + $this->icalculated = true; + + $n = count($this->ix); + $sx2 = 0 ; + $sy2 = 0 ; + $sxy = 0 ; + $sx = 0 ; + $sy = 0 ; + + for( $i=0; $i < $n; ++$i ) { + $sx2 += $this->ix[$i] * $this->ix[$i]; + $sy2 += $this->iy[$i] * $this->iy[$i]; + $sxy += $this->ix[$i] * $this->iy[$i]; + $sx += $this->ix[$i]; + $sy += $this->iy[$i]; + } + + if( $n*$sx2 - $sx*$sx > __LR_EPSILON ) { + $this->ib = ($n*$sxy - $sx*$sy) / ( $n*$sx2 - $sx*$sx ); + $this->ia = ( $sy - $this->ib*$sx ) / $n; + + $sx = $this->ib * ( $sxy - $sx*$sy/$n ); + $sy2 = $sy2 - $sy*$sy/$n; + $sy = $sy2 - $sx; + + $this->iDet = $sx / $sy2; + $this->iCorr = sqrt($this->iDet); + if( $n > 2 ) { + $this->iStdErr = sqrt( $sy / ($n-2) ); + } + else { + $this->iStdErr = NAN ; + } + } + else { + $this->ib = 0; + $this->ia = 0; + } + + } + + public function GetAB() { + if( $this->icalculated == false ) + $this->Calc(); + return array($this->ia, $this->ib); + } + + public function GetStat() { + if( $this->icalculated == false ) + $this->Calc(); + return array($this->iStdErr, $this->iCorr, $this->iDet); + } + + public function GetY($aMinX, $aMaxX, $aStep=1) { + if( $this->icalculated == false ) + $this->Calc(); + + $yy = array(); + $i = 0; + for( $x=$aMinX; $x <= $aMaxX; $x += $aStep ) { + $xx[$i ] = $x; + $yy[$i++] = $this->ia + $this->ib * $x; + } + + return array($xx,$yy); + } + +} + +?> diff --git a/web/public_php/admin/jpgraph/jpgraph_windrose.php b/web/public_php/admin/jpgraph/jpgraph_windrose.php new file mode 100644 index 000000000..8eef2cbe4 --- /dev/null +++ b/web/public_php/admin/jpgraph/jpgraph_windrose.php @@ -0,0 +1,1566 @@ +iZeroSum=0; + foreach( $aData as $idx => $legdata ) { + $legsum = array_sum($legdata); + $maxnum = max($maxnum,count($legdata)-1); + $max = max($legsum-$legdata[0],$max); + $totlegsum += $legsum; + $this->iZeroSum += $legdata[0] ; + } + if( round($totlegsum) > 100 ) { + JpGraphError::RaiseL(22001,$legsum); + //("Total percentage for all windrose legs in a windrose plot can not exceed 100% !\n(Current max is: ".$legsum.')'); + } + $this->iMax = $max ; + $this->iMaxNum = $maxnum; + $this->iNumCirc = $this->GetNumCirc(); + $this->iMaxVal = $this->iNumCirc * $this->iDelta ; + } + + // Return number of grid circles + function GetNumCirc() { + // Never return less than 1 circles + $num = ceil($this->iMax / $this->iDelta); + return max(1,$num) ; + } + + function SetMaxValue($aMax) { + $this->iMax = $aMax; + $this->iNumCirc = $this->GetNumCirc(); + $this->iMaxVal = $this->iNumCirc * $this->iDelta ; + } + + // Set step size for circular grid + function Set($aMax,$aDelta=null) { + if( $aDelta==null ) { + $this->SetMaxValue($aMax); + return; + } + $this->iDelta = $aDelta; + $this->iNumCirc = ceil($aMax/$aDelta); //$this->GetNumCirc(); + $this->iMaxVal = $this->iNumCirc * $this->iDelta ; + $this->iMax=$aMax; + // Remember that user has specified interval so don't + // do autoscaling + $this->iManualScale = true; + } + + function AutoScale($aRadius,$aMinDist=30) { + + if( $this->iManualScale ) return; + + // Make sure distance (in pixels) between two circles + // is never less than $aMinDist pixels + $tst = ceil($aRadius / $this->iNumCirc) ; + + while( $tst <= $aMinDist && $this->iDelta < 100 ) { + $this->iDelta += 5; + $tst = ceil($aRadius / $this->GetNumCirc()) ; + } + + if( $this->iDelta >= 100 ) { + JpGraphError::RaiseL(22002);//('Graph is too small to have a scale. Please make the graph larger.'); + } + + // If the distance is to large try with multiples of 2 instead + if( $tst > $aMinDist * 3 ) { + $this->iDelta = 2; + $tst = ceil($aRadius / $this->iNumCirc) ; + + while( $tst <= $aMinDist && $this->iDelta < 100 ) { + $this->iDelta += 2; + $tst = ceil($aRadius / $this->GetNumCirc()) ; + } + + if( $this->iDelta >= 100 ) { + JpGraphError::RaiseL(22002); //('Graph is too small to have a scale. Please make the graph larger.'); + } + } + + $this->iNumCirc = $this->GetNumCirc(); + $this->iMaxVal = $this->iNumCirc * $this->iDelta ; + } + + // Return max of all leg values + function GetMax() { + return $this->iMax; + } + + function Hide($aFlg=true) { + $this->iHideLabels = $aFlg; + } + + function SetAngle($aAngle) { + $this->iAngle = $aAngle ; + } + + // Translate a Leg value to radius distance + function RelTranslate($aVal,$r,$ri) { + $tv = round($aVal/$this->iMaxVal*($r-$ri)); + return $tv ; + } + + function SetLabelAlign($aAlign) { + $this->iLblAlign = $aAlign ; + } + + function SetLabelFormat($aFmt) { + $this->iLblFmt = $aFmt ; + } + + function SetLabelFillColor($aBkgColor,$aBorderColor=false) { + + $this->iFontBkgColor = $aBkgColor; + if( $aBorderColor === false ) { + $this->iFontFrameColor = $aBkgColor; + } + else { + $this->iFontFrameColor = $aBorderColor; + } + } + + function SetFontColor($aColor) { + $this->iFontColor = $aColor ; + $this->iZFontColor = $aColor ; + } + + function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->iFontFamily = $aFontFamily ; + $this->iFontStyle = $aFontStyle ; + $this->iFontSize = $aFontSize ; + $this->SetZFont($aFontFamily,$aFontStyle,$aFontSize); + } + + function SetZFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->iZFontFamily = $aFontFamily ; + $this->iZFontStyle = $aFontStyle ; + $this->iZFontSize = $aFontSize ; + } + + function SetZeroLabel($aTxt) { + $this->iLblZeroTxt = $aTxt ; + } + + function SetZFontColor($aColor) { + $this->iZFontColor = $aColor ; + } + + function StrokeLabels($aImg,$xc,$yc,$ri,$rr) { + + if( $this->iHideLabels ) return; + + // Setup some convinient vairables + $a = $this->iAngle * M_PI/180.0; + $n = $this->iNumCirc; + $d = $this->iDelta; + + // Setup the font and font color + $val = new Text(); + $val->SetFont($this->iFontFamily,$this->iFontStyle,$this->iFontSize); + $val->SetColor($this->iFontColor); + + if( $this->iFontBkgColor !== false ) { + $val->SetBox($this->iFontBkgColor,$this->iFontFrameColor); + } + + // Position the labels relative to the radiant circles + if( $this->iLblAlign == LBLALIGN_TOP ) { + if( $a > 0 && $a <= M_PI/2 ) { + $val->SetAlign('left','bottom'); + } + elseif( $a > M_PI/2 && $a <= M_PI ) { + $val->SetAlign('right','bottom'); + } + } + elseif( $this->iLblAlign == LBLALIGN_CENTER ) { + $val->SetAlign('center','center'); + } + + // Stroke the labels close to each circle + $v = $d ; + $si = sin($a); + $co = cos($a); + for( $i=0; $i < $n; ++$i, $v += $d ) { + $r = $ri + ($i+1) * $rr; + $x = $xc + $co * $r; + $y = $yc - $si * $r; + $val->Set(sprintf($this->iLblFmt,$v)); + $val->Stroke($aImg,$x,$y); + } + + // Print the text in the zero circle + if( $this->iLblZeroTxt === null ) { + $this->iLblZeroTxt = sprintf($this->iLblFmt,$this->iZeroSum); + } + else { + $this->iLblZeroTxt = sprintf($this->iLblZeroTxt,$this->iZeroSum); + } + + $val->Set($this->iLblZeroTxt); + $val->SetAlign('center','center'); + $val->SetParagraphAlign('center'); + $val->SetColor($this->iZFontColor); + $val->SetFont($this->iZFontFamily,$this->iZFontStyle,$this->iZFontSize); + $val->Stroke($aImg,$xc,$yc); + } +} + +//=================================================== +// CLASS LegendStyle +//=================================================== +class LegendStyle { + public $iLength = 40, $iMargin = 20 , $iBottomMargin=5; + public $iCircleWeight=2, $iCircleRadius = 18, $iCircleColor='black'; + public $iTxtFontFamily=FF_VERDANA,$iTxtFontStyle=FS_NORMAL,$iTxtFontSize=8; + public $iLblFontFamily=FF_VERDANA,$iLblFontStyle=FS_NORMAL,$iLblFontSize=8; + public $iCircleFontFamily=FF_VERDANA,$iCircleFontStyle=FS_NORMAL,$iCircleFontSize=8; + public $iLblFontColor='black',$iTxtFontColor='black',$iCircleFontColor='black'; + public $iShow=true; + public $iFormatString='%.1f'; + public $iTxtMargin=6, $iTxt=''; + public $iZCircleTxt='Calm'; + + function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->iLblFontFamily = $aFontFamily ; + $this->iLblFontStyle = $aFontStyle ; + $this->iLblFontSize = $aFontSize ; + $this->iTxtFontFamily = $aFontFamily ; + $this->iTxtFontStyle = $aFontStyle ; + $this->iTxtFontSize = $aFontSize ; + $this->iCircleFontFamily = $aFontFamily ; + $this->iCircleFontStyle = $aFontStyle ; + $this->iCircleFontSize = $aFontSize ; + } + + function SetLFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->iLblFontFamily = $aFontFamily ; + $this->iLblFontStyle = $aFontStyle ; + $this->iLblFontSize = $aFontSize ; + } + + function SetTFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->iTxtFontFamily = $aFontFamily ; + $this->iTxtFontStyle = $aFontStyle ; + $this->iTxtFontSize = $aFontSize ; + } + + function SetCFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { + $this->iCircleFontFamily = $aFontFamily ; + $this->iCircleFontStyle = $aFontStyle ; + $this->iCircleFontSize = $aFontSize ; + } + + + function SetFontColor($aColor) { + $this->iTxtFontColor = $aColor ; + $this->iLblFontColor = $aColor ; + $this->iCircleFontColor = $aColor ; + } + + function SetTFontColor($aColor) { + $this->iTxtFontColor = $aColor ; + } + + function SetLFontColor($aColor) { + $this->iLblFontColor = $aColor ; + } + + function SetCFontColor($aColor) { + $this->iCircleFontColor = $aColor ; + } + + function SetCircleWeight($aWeight) { + $this->iCircleWeight = $aWeight; + } + + function SetCircleRadius($aRadius) { + $this->iCircleRadius = $aRadius; + } + + function SetCircleColor($aColor) { + $this->iCircleColor = $aColor ; + } + + function SetCircleText($aTxt) { + $this->iZCircleTxt = $aTxt; + } + + function SetMargin($aMarg,$aBottomMargin=5) { + $this->iMargin=$aMarg; + $this->iBottomMargin=$aBottomMargin; + } + + function SetLength($aLength) { + $this->iLength = $aLength ; + } + + function Show($aFlg=true) { + $this->iShow = $aFlg; + } + + function Hide($aFlg=true) { + $this->iShow = ! $aFlg; + } + + function SetFormat($aFmt) { + $this->iFormatString=$aFmt; + } + + function SetText($aTxt) { + $this->iTxt = $aTxt ; + } + +} + +define('RANGE_OVERLAPPING',0); +define('RANGE_DISCRETE',1); + +//=================================================== +// CLASS WindrosePlot +//=================================================== +class WindrosePlot { + private $iAntiAlias=true; + private $iData=array(); + public $iX=0.5,$iY=0.5; + public $iSize=0.55; + private $iGridColor1='gray',$iGridColor2='darkgreen'; + private $iRadialColorArray=array(); + private $iRadialWeightArray=array(); + private $iRadialStyleArray=array(); + private $iRanges = array(1,2,3,5,6,10,13.5,99.0); + private $iRangeStyle = RANGE_OVERLAPPING ; + public $iCenterSize=60; + private $iType = WINDROSE_TYPE16; + public $iFontFamily=FF_VERDANA,$iFontStyle=FS_NORMAL,$iFontSize=10; + public $iFontColor='darkgray'; + private $iRadialGridStyle='longdashed'; + private $iAllDirectionLabels = array('E','ENE','NE','NNE','N','NNW','NW','WNW','W','WSW','SW','SSW','S','SSE','SE','ESE'); + private $iStandardDirections = array(); + private $iCircGridWeight=3, $iRadialGridWeight=1; + private $iLabelMargin=12; + private $iLegweights = array(2,4,6,8,10,12,14,16,18,20); + private $iLegColors = array('orange','black','blue','red','green','purple','navy','yellow','brown'); + private $iLabelFormatString='', $iLabels=array(); + private $iLabelPositioning = LBLPOSITION_EDGE; + private $iColor='white'; + private $iShowBox=false, $iBoxColor='black',$iBoxWeight=1,$iBoxStyle='solid'; + private $iOrdinalEncoding=KEYENCODING_ANTICLOCKWISE; + public $legend=null; + + function __construct($aData) { + $this->iData = $aData; + $this->legend = new LegendStyle(); + + // Setup the scale + $this->scale = new WindrosePlotScale($this->iData); + + // default label for free type i agle and a degree sign + $this->iLabelFormatString = '%.1f'.SymChar::Get('degree'); + + $delta = 2*M_PI/16; + for( $i=0, $a=0; $i < 16; ++$i, $a += $delta ) { + $this->iStandardDirections[$this->iAllDirectionLabels[$i]] = $a; + } + } + + // Dummy method to make window plots have the same signature as the + // layout classes since windrose plots are "leaf" classes in the hierarchy + function LayoutSize() { + return 1; + } + + function SetSize($aSize) { + $this->iSize = $aSize; + } + + function SetDataKeyEncoding($aEncoding) { + $this->iOrdinalEncoding = $aEncoding; + } + + function SetColor($aColor) { + $this->iColor = $aColor; + } + + function SetRadialColors($aColors) { + $this->iRadialColorArray = $aColors; + } + + function SetRadialWeights($aWeights) { + $this->iRadialWeightArray = $aWeights; + } + + function SetRadialStyles($aStyles) { + $this->iRadialStyleArray = $aStyles; + } + + function SetBox($aColor='black',$aWeight=1, $aStyle='solid', $aShow=true) { + $this->iShowBox = $aShow ; + $this->iBoxColor = $aColor ; + $this->iBoxWeight = $aWeight ; + $this->iBoxStyle = $aStyle; + } + + function SetLabels($aLabels) { + $this->iLabels = $aLabels ; + } + + function SetLabelMargin($aMarg) { + $this->iLabelMargin = $aMarg ; + } + + function SetLabelFormat($aLblFormat) { + $this->iLabelFormatString = $aLblFormat ; + } + + function SetCompassLabels($aLabels) { + if( count($aLabels) != 16 ) { + JpgraphError::RaiseL(22004); //('Label specification for windrose directions must have 16 values (one for each compass direction).'); + } + $this->iAllDirectionLabels = $aLabels ; + + $delta = 2*M_PI/16; + for( $i=0, $a=0; $i < 16; ++$i, $a += $delta ) { + $this->iStandardDirections[$this->iAllDirectionLabels[$i]] = $a; + } + + } + + function SetCenterSize($aSize) { + $this->iCenterSize = $aSize; + } + // Alias for SetCenterSize + function SetZCircleSize($aSize) { + $this->iCenterSize = $aSize; + } + + function SetFont($aFFam,$aFStyle=FS_NORMAL,$aFSize=10) { + $this->iFontFamily = $aFFam ; + $this->iFontStyle = $aFStyle ; + $this->iFontSize = $aFSize ; + } + + function SetFontColor($aColor) { + $this->iFontColor=$aColor; + } + + function SetGridColor($aColor1,$aColor2) { + $this->iGridColor1 = $aColor1; + $this->iGridColor2 = $aColor2; + } + + function SetGridWeight($aGrid1=1,$aGrid2=2) { + $this->iCircGridWeight = $aGrid1 ; + $this->iRadialGridWeight = $aGrid2 ; + } + + function SetRadialGridStyle($aStyle) { + $aStyle = strtolower($aStyle); + if( !in_array($aStyle,array('solid','dotted','dashed','longdashed')) ) { + JpGraphError::RaiseL(22005); //("Line style for radial lines must be on of ('solid','dotted','dashed','longdashed') "); + } + $this->iRadialGridStyle=$aStyle; + } + + function SetRanges($aRanges) { + $this->iRanges = $aRanges; + } + + function SetRangeStyle($aStyle) { + $this->iRangeStyle = $aStyle; + } + + function SetRangeColors($aLegColors) { + $this->iLegColors = $aLegColors; + } + + function SetRangeWeights($aWeights) { + $n=count($aWeights); + for($i=0; $i< $n; ++$i ) { + $aWeights[$i] = floor($aWeights[$i]/2); + } + $this->iLegweights = $aWeights; + + } + + function SetType($aType) { + if( $aType < WINDROSE_TYPE4 || $aType > WINDROSE_TYPEFREE ) { + JpGraphError::RaiseL(22006); //('Illegal windrose type specified.'); + } + $this->iType = $aType; + } + + // Alias for SetPos() + function SetCenterPos($aX,$aY) { + $this->iX = $aX; + $this->iY = $aY; + } + + function SetPos($aX,$aY) { + $this->iX = $aX; + $this->iY = $aY; + } + + function SetAntiAlias($aFlag) { + $this->iAntiAlias = $aFlag ; + if( ! $aFlag ) + $this->iCircGridWeight = 1; + } + + function _ThickCircle($aImg,$aXC,$aYC,$aRad,$aWeight=2,$aColor) { + + $aImg->SetColor($aColor); + $aRad *= 2 ; + $aImg->Ellipse($aXC,$aYC,$aRad,$aRad); + if( $aWeight > 1 ) { + $aImg->Ellipse($aXC,$aYC,$aRad+1,$aRad+1); + $aImg->Ellipse($aXC,$aYC,$aRad+2,$aRad+2); + if( $aWeight > 2 ) { + $aImg->Ellipse($aXC,$aYC,$aRad+3,$aRad+3); + $aImg->Ellipse($aXC,$aYC,$aRad+3,$aRad+4); + $aImg->Ellipse($aXC,$aYC,$aRad+4,$aRad+3); + } + } + } + + function _StrokeWindLeg($aImg,$xc,$yc,$a,$ri,$r,$weight,$color) { + + // If less than 1 px long then we assume this has been caused by rounding problems + // and should not be stroked + if( $r < 1 ) return; + + $xt = $xc + cos($a)*$ri; + $yt = $yc - sin($a)*$ri; + $xxt = $xc + cos($a)*($ri+$r); + $yyt = $yc - sin($a)*($ri+$r); + + $x1 = $xt - $weight*sin($a); + $y1 = $yt - $weight*cos($a); + $x2 = $xxt - $weight*sin($a); + $y2 = $yyt - $weight*cos($a); + + $x3 = $xxt + $weight*sin($a); + $y3 = $yyt + $weight*cos($a); + $x4 = $xt + $weight*sin($a); + $y4 = $yt + $weight*cos($a); + + $pts = array($x1,$y1,$x2,$y2,$x3,$y3,$x4,$y4); + $aImg->SetColor($color); + $aImg->FilledPolygon($pts); + + } + + function _StrokeLegend($aImg,$x,$y,$scaling=1,$aReturnWidth=false) { + + if( ! $this->legend->iShow ) return 0; + + $nlc = count($this->iLegColors); + $nlw = count($this->iLegweights); + + // Setup font for ranges + $value = new Text(); + $value->SetAlign('center','bottom'); + $value->SetFont($this->legend->iLblFontFamily, + $this->legend->iLblFontStyle, + $this->legend->iLblFontSize*$scaling); + $value->SetColor($this->legend->iLblFontColor); + + // Remember x-center + $xcenter = $x ; + + // Construct format string + $fmt = $this->legend->iFormatString.'-'.$this->legend->iFormatString; + + // Make sure that the length of each range is enough to cover the + // size of the labels + $tst = sprintf($fmt,$this->iRanges[0],$this->iRanges[1]); + $value->Set($tst); + $w = $value->GetWidth($aImg); + $l = round(max($this->legend->iLength * $scaling,$w*1.5)); + + $r = $this->legend->iCircleRadius * $scaling ; + $len = 2*$r + $this->scale->iMaxNum * $l; + + // We are called just to find out the width + if( $aReturnWidth ) return $len; + + $x -= round($len/2); + $x += $r; + + // 4 pixels extra vertical margin since the circle sometimes is +/- 1 pixel of the + // theorethical radius due to imperfection in the GD library + //$y -= round(max($r,$scaling*$this->iLegweights[($this->scale->iMaxNum-1) % $nlw])+4*$scaling); + $y -= ($this->legend->iCircleRadius + 2)*$scaling+$this->legend->iBottomMargin*$scaling; + + // Adjust for bottom text + if( $this->legend->iTxt != '' ) { + // Setup font for text + $value->Set($this->legend->iTxt); + $y -= /*$this->legend->iTxtMargin + */ $value->GetHeight($aImg); + } + + // Stroke 0-circle + $this->_ThickCircle($aImg,$x,$y,$r,$this->legend->iCircleWeight, + $this->legend->iCircleColor); + + // Remember the center of the circe + $xc=$x; $yc=$y; + + $value->SetAlign('center','bottom'); + $x += $r+1; + + // Stroke all used ranges + $txty = $y - + round($this->iLegweights[($this->scale->iMaxNum-1)%$nlw]*$scaling) - 4*$scaling; + if( $this->scale->iMaxNum >= count($this->iRanges) ) { + JpGraphError::RaiseL(22007); //('To few values for the range legend.'); + } + $i=0;$idx=0; + while( $i < $this->scale->iMaxNum ) { + $y1 = $y - round($this->iLegweights[$i % $nlw]*$scaling); + $y2 = $y + round($this->iLegweights[$i % $nlw]*$scaling); + $x2 = $x + $l ; + $aImg->SetColor($this->iLegColors[$i % $nlc]); + $aImg->FilledRectangle($x,$y1,$x2,$y2); + if( $this->iRangeStyle == RANGE_OVERLAPPING ) { + $lbl = sprintf($fmt,$this->iRanges[$idx],$this->iRanges[$idx+1]); + } + else { + $lbl = sprintf($fmt,$this->iRanges[$idx],$this->iRanges[$idx+1]); + ++$idx; + } + $value->Set($lbl); + $value->Stroke($aImg,$x+$l/2,$txty); + $x = $x2; + ++$i;++$idx; + } + + // Setup circle font + $value->SetFont($this->legend->iCircleFontFamily, + $this->legend->iCircleFontStyle, + $this->legend->iCircleFontSize*$scaling); + $value->SetColor($this->legend->iCircleFontColor); + + // Stroke 0-circle text + $value->Set($this->legend->iZCircleTxt); + $value->SetAlign('center','center'); + $value->ParagraphAlign('center'); + $value->Stroke($aImg,$xc,$yc); + + // Setup circle font + $value->SetFont($this->legend->iTxtFontFamily, + $this->legend->iTxtFontStyle, + $this->legend->iTxtFontSize*$scaling); + $value->SetColor($this->legend->iTxtFontColor); + + // Draw the text under the legend + $value->Set($this->legend->iTxt); + $value->SetAlign('center','top'); + $value->SetParagraphAlign('center'); + $value->Stroke($aImg,$xcenter,$y2+$this->legend->iTxtMargin*$scaling); + } + + function SetAutoScaleAngle($aIsRegRose=true) { + + // If the user already has manually set an angle don't + // trye to find a position + if( is_numeric($this->scale->iAngle) ) + return; + + if( $aIsRegRose ) { + + // Create a complete data for all directions + // and translate string directions to ordinal values. + // This will much simplify the logic below + for( $i=0; $i < 16; ++$i ) { + $dtxt = $this->iAllDirectionLabels[$i]; + if( !empty($this->iData[$dtxt]) ) { + $data[$i] = $this->iData[$dtxt]; + } + elseif( !empty($this->iData[strtolower($dtxt)]) ) { + $data[$i] = $this->iData[strtolower($dtxt)]; + } + elseif( !empty($this->iData[$i]) ) { + $data[$i] = $this->iData[$i]; + } + else { + $data[$i] = array(); + } + } + + // Find the leg which has the lowest weighted sum of number of data around it + $c0 = array_sum($data[0]); + $c1 = array_sum($data[1]); + $found = 1; + $min = $c0+$c1*100; // Initialize to a high value + for( $i=1; $i < 15; ++$i ) { + $c2 = array_sum($data[$i+1]); + + // Weight the leg we will use more to give preference + // to a short middle leg even if the 3 way sum is similair + $w = $c0 + 3*$c1 + $c2 ; + if( $w < $min ) { + $min = $w; + $found = $i; + } + $c0 = $c1; + $c1 = $c2; + } + $this->scale->iAngle = $found*22.5; + } + else { + $n = count($this->iData); + foreach( $this->iData as $dir => $leg ) { + if( !is_numeric($dir) ) { + $pos = array_search(strtoupper($dir),$this->iAllDirectionLabels); + if( $pos !== false ) { + $dir = $pos*22.5; + } + } + $data[round($dir)] = $leg; + } + + // Get all the angles for the data and sort it + $keys = array_keys($data); + sort($keys, SORT_NUMERIC); + + $n = count($data); + $found = false; + $max = 0 ; + for( $i=0; $i < 15; ++$i ) { + $try_a = round(22.5*$i); + + if( $try_a > $keys[$n-1] ) break; + + if( in_array($try_a,$keys) ) continue; + + // Find the angle just lower than this + $j=0; + while( $j < $n && $keys[$j] <= $try_a ) ++$j; + if( $j == 0 ) { + $kj = 0; $keys[$n-1]; + $d1 = 0; abs($kj-$try_a); + } + else { + --$j; + $kj = $keys[$j]; + $d1 = abs($kj-$try_a); + } + + // Find the angle just larger than this + $l=$n-1; + while( $l >= 0 && $keys[$l] >= $try_a ) --$l; + if( $l == $n-1) { + $kl = $keys[0]; + $d2 = abs($kl-$try_a); + } + else { + ++$l; + $kl = $keys[$l]; + $d2 = abs($kl-$try_a); + } + + // Weight the distance so that legs with large spread + // gets a better weight + $w = $d1 + $d2; + if( $i == 0 ) { + $w = round(1.4 * $w); + } + $diff = abs($d1 - $d2); + $w *= (360-$diff); + if( $w > $max ) { + $found = $i; + $max = $w; + } + } + + $a = $found*22.5; + + // Some heuristics to have some preferred positions + if( $keys[$n-1] < 25 ) $a = 45; + elseif( $keys[0] > 60 ) $a = 45; + elseif( $keys[0] > 25 && $keys[$n-1] < 340 ) $a = 0; + elseif( $keys[$n-1] < 75 ) $a = 90; + elseif( $keys[$n-1] < 120 ) $a = 135; + elseif( $keys[$n-1] < 160 ) $a = 180; + + $this->scale->iAngle = $a ; + } + } + + function NormAngle($a) { + while( $a > 360 ) { + $a -= 360; + } + return $a; + } + + function SetLabelPosition($aPos) { + $this->iLabelPositioning = $aPos ; + } + + function _StrokeFreeRose($dblImg,$value,$scaling,$xc,$yc,$r,$ri) { + + // Plot radial grid lines and remember the end position + // and the angle for later use when plotting the labels + if( $this->iType != WINDROSE_TYPEFREE ) { + JpGraphError::RaiseL(22008); //('Internal error: Trying to plot free Windrose even though type is not a free windorose'); + } + + // Check if we should auto-position the angle for the + // labels. Basically we try to find a firection with smallest + // (or none) data. + $this->SetAutoScaleAngle(false); + + $nlc = count($this->iLegColors); + $nlw = count($this->iLegweights); + + // Stroke grid lines for directions and remember the + // position for the labels + $txtpos=array(); + $num = count($this->iData); + + $keys = array_keys($this->iData); + + foreach( $this->iData as $dir => $legdata ) { + if( in_array($dir,$this->iAllDirectionLabels,true) === true) { + $a = $this->iStandardDirections[strtoupper($dir)]; + if( in_array($a*180/M_PI,$keys) ) { + JpGraphError::RaiseL(22009,round($a*180/M_PI)); + //('You have specified the same direction twice, once with an angle and once with a compass direction ('.$a*180/M_PI.' degrees.)'); + } + } + elseif( is_numeric($dir) ) { + $this->NormAngle($dir); + + if( $this->iOrdinalEncoding == KEYENCODING_CLOCKWISE ) { + $dir = 360-$dir; + } + + $a = $dir * M_PI/180; + } + else { + JpGraphError::RaiseL(22010);//('Direction must either be a numeric value or one of the 16 compass directions'); + } + + $xxc = round($xc + cos($a)*$ri); + $yyc = round($yc - sin($a)*$ri); + $x = round($xc + cos($a)*$r); + $y = round($yc - sin($a)*$r); + if( empty($this->iRadialColorArray[$dir]) ) { + $dblImg->SetColor($this->iGridColor2); + } + else { + $dblImg->SetColor($this->iRadialColorArray[$dir]); + } + if( empty($this->iRadialWeightArray[$dir]) ) { + $dblImg->SetLineWeight($this->iRadialGridWeight); + } + else { + $dblImg->SetLineWeight($this->iRadialWeightArray[$dir]); + } + if( empty($this->iRadialStyleArray[$dir]) ) { + $dblImg->SetLineStyle($this->iRadialGridStyle); + } + else { + $dblImg->SetLineStyle($this->iRadialStyleArray[$dir]); + } + $dblImg->StyleLine($xxc,$yyc,$x,$y); + $txtpos[] = array($x,$y,$a); + } + $dblImg->SetLineWeight(1); + + // Setup labels + $lr = $scaling * $this->iLabelMargin; + + if( $this->iLabelPositioning == LBLPOSITION_EDGE ) { + $value->SetAlign('left','top'); + } + else { + $value->SetAlign('center','center'); + $value->SetMargin(0); + } + + for($i=0; $i < $num; ++$i ) { + + list($x,$y,$a) = $txtpos[$i]; + + // Determine the label + + $da = $a*180/M_PI; + if( $this->iOrdinalEncoding == KEYENCODING_CLOCKWISE ) { + $da = 360 - $da; + } + + //$da = 360-$da; + + if( !empty($this->iLabels[$keys[$i]]) ) { + $lbl = $this->iLabels[$keys[$i]]; + } + else { + $lbl = sprintf($this->iLabelFormatString,$da); + } + + if( $this->iLabelPositioning == LBLPOSITION_CENTER ) { + $dx = $dy = 0; + } + else { + // LBLPOSIITON_EDGE + if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); + + if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; + if( $a<=M_PI/4 ) $dy=(0.5+$a*2/M_PI); + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; + } + + $value->Set($lbl); + $th = $value->GetHeight($dblImg); + $tw = $value->GetWidth($dblImg); + $xt=round($lr*cos($a)+$x) - $dx*$tw; + $yt=round($y-$lr*sin($a)) - $dy*$th; + + $value->Stroke($dblImg,$xt,$yt); + } + + if( __DEBUG ) { + $dblImg->SetColor('red'); + $dblImg->Circle($xc,$yc,$lr+$r); + } + + // Stroke all the legs + reset($this->iData); + $i=0; + foreach($this->iData as $dir => $legdata) { + $legdata = array_slice($legdata,1); + $nn = count($legdata); + + $a = $txtpos[$i][2]; + $rri = $ri/$scaling; + for( $j=0; $j < $nn; ++$j ) { + // We want the non scaled original radius + $legr = $this->scale->RelTranslate($legdata[$j],$r/$scaling,$ri/$scaling) ; + $this->_StrokeWindLeg($dblImg, $xc, $yc, $a, + $rri *$scaling, + $legr *$scaling, + $this->iLegweights[$j % $nlw] * $scaling, + $this->iLegColors[$j % $nlc]); + $rri += $legr; + } + ++$i; + } + } + + // Translate potential string specified compass labels to their + // corresponding index. + function FixupIndexes($aDataArray,$num) { + $ret = array(); + $keys = array_keys($aDataArray); + foreach($aDataArray as $idx => $data) { + if( is_string($idx) ) { + $idx = strtoupper($idx); + $res = array_search($idx,$this->iAllDirectionLabels); + if( $res === false ) { + JpGraphError::RaiseL(22011,$idx); //('Windrose index must be numeric or direction label. You have specified index='.$idx); + } + $idx = $res; + if( $idx % (16 / $num) !== 0 ) { + JpGraphError::RaiseL(22012); //('Windrose radial axis specification contains a direction which is not enabled.'); + } + $idx /= (16/$num) ; + + if( in_array($idx,$keys,1) ) { + JpgraphError::RaiseL(22013,$idx); //('You have specified the look&feel for the same compass direction twice, once with text and once with index (Index='.$idx.')'); + } + } + if( $idx < 0 || $idx > 15 ) { + JpgraphError::RaiseL(22014); //('Index for copmass direction must be between 0 and 15.'); + } + $ret[$idx] = $data; + } + return $ret; + } + + function _StrokeRegularRose($dblImg,$value,$scaling,$xc,$yc,$r,$ri) { + // _StrokeRegularRose($dblImg,$xc,$yc,$r,$ri) + // Plot radial grid lines and remember the end position + // and the angle for later use when plotting the labels + switch( $this->iType ) { + case WINDROSE_TYPE4: + $num = 4; break; + case WINDROSE_TYPE8: + $num = 8; break; + case WINDROSE_TYPE16: + $num = 16; break; + default: + JpGraphError::RaiseL(22015);//('You have specified an undefined Windrose plot type.'); + } + + // Check if we should auto-position the angle for the + // labels. Basically we try to find a firection with smallest + // (or none) data. + $this->SetAutoScaleAngle(true); + + $nlc = count($this->iLegColors); + $nlw = count($this->iLegweights); + + $this->iRadialColorArray = $this->FixupIndexes($this->iRadialColorArray,$num); + $this->iRadialWeightArray = $this->FixupIndexes($this->iRadialWeightArray,$num); + $this->iRadialStyleArray = $this->FixupIndexes($this->iRadialStyleArray,$num); + + $txtpos=array(); + $a = 2*M_PI/$num; + $dblImg->SetColor($this->iGridColor2); + $dblImg->SetLineStyle($this->iRadialGridStyle); + $dblImg->SetLineWeight($this->iRadialGridWeight); + + // Translate any name specified directions to the index + // so we can easily use it in the loop below + for($i=0; $i < $num; ++$i ) { + $xxc = round($xc + cos($a*$i)*$ri); + $yyc = round($yc - sin($a*$i)*$ri); + $x = round($xc + cos($a*$i)*$r); + $y = round($yc - sin($a*$i)*$r); + if( empty($this->iRadialColorArray[$i]) ) { + $dblImg->SetColor($this->iGridColor2); + } + else { + $dblImg->SetColor($this->iRadialColorArray[$i]); + } + if( empty($this->iRadialWeightArray[$i]) ) { + $dblImg->SetLineWeight($this->iRadialGridWeight); + } + else { + $dblImg->SetLineWeight($this->iRadialWeightArray[$i]); + } + if( empty($this->iRadialStyleArray[$i]) ) { + $dblImg->SetLineStyle($this->iRadialGridStyle); + } + else { + $dblImg->SetLineStyle($this->iRadialStyleArray[$i]); + } + + $dblImg->StyleLine($xxc,$yyc,$x,$y); + $txtpos[] = array($x,$y,$a*$i); + } + $dblImg->SetLineWeight(1); + + $lr = $scaling * $this->iLabelMargin; + if( $this->iLabelPositioning == LBLPOSITION_CENTER ) { + $value->SetAlign('center','center'); + } + else { + $value->SetAlign('left','top'); + $value->SetMargin(0); + $lr /= 2 ; + } + + for($i=0; $i < $num; ++$i ) { + list($x,$y,$a) = $txtpos[$i]; + + // Set the position of the label + if( $this->iLabelPositioning == LBLPOSITION_CENTER ) { + $dx = $dy = 0; + } + else { + // LBLPOSIITON_EDGE + if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); + + if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; + if( $a<=M_PI/4 ) $dy=(0.5+$a*2/M_PI); + if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; + if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); + if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; + } + + $value->Set($this->iAllDirectionLabels[$i*(16/$num)]); + $th = $value->GetHeight($dblImg); + $tw = $value->GetWidth($dblImg); + $xt=round($lr*cos($a)+$x) - $dx*$tw; + $yt=round($y-$lr*sin($a)) - $dy*$th; + + $value->Stroke($dblImg,$xt,$yt); + } + + if( __DEBUG ) { + $dblImg->SetColor("red"); + $dblImg->Circle($xc,$yc,$lr+$r); + } + + // Stroke all the legs + reset($this->iData); + $keys = array_keys($this->iData); + foreach($this->iData as $idx => $legdata) { + $legdata = array_slice($legdata,1); + $nn = count($legdata); + if( is_string($idx) ) { + $idx = strtoupper($idx); + $idx = array_search($idx,$this->iAllDirectionLabels); + if( $idx === false ) { + JpGraphError::RaiseL(22016);//('Windrose leg index must be numeric or direction label.'); + } + if( $idx % (16 / $num) !== 0 ) { + JpGraphError::RaiseL(22017);//('Windrose data contains a direction which is not enabled. Please adjust what labels are displayed.'); + } + $idx /= (16/$num) ; + + if( in_array($idx,$keys,1) ) { + JpgraphError::RaiseL(22018,$idx);//('You have specified data for the same compass direction twice, once with text and once with index (Index='.$idx.')'); + + } + } + if( $idx < 0 || $idx > 15 ) { + JpgraphError::RaiseL(22019);//('Index for direction must be between 0 and 15. You can\'t specify angles for a Regular Windplot, only index and compass directions.'); + } + $a = $idx * (360 / $num) ; + $a *= M_PI/180.0; + $rri = $ri/$scaling; + for( $j=0; $j < $nn; ++$j ) { + // We want the non scaled original radius + $legr = $this->scale->RelTranslate($legdata[$j], $r/$scaling,$ri/$scaling) ; + $this->_StrokeWindLeg($dblImg, $xc, $yc, $a, + $rri *$scaling, + $legr *$scaling, + $this->iLegweights[$j % $nlw] * $scaling, + $this->iLegColors[$j % $nlc]); + $rri += $legr; + } + } + } + + + function getWidth($aImg) { + + $scaling = 1;//$this->iAntiAlias ? 2 : 1 ; + if( $this->iSize > 0 && $this->iSize < 1 ) { + $this->iSize *= min($aImg->width,$aImg->height); + } + + + $value = new Text(); + $value->SetFont($this->iFontFamily,$this->iFontStyle,$this->iFontSize*$scaling); + $value->SetColor($this->iFontColor); + // Setup extra size around the graph needed so that the labels + // doesn't get cut. For this we need to find the largest label. + // The code below gives a possible a little to large margin. The + // really, really proper way would be to account for what angle + // the label are at + $n = count($this->iLabels); + if( $n > 0 ) { + $maxh=0;$maxw=0; + foreach($this->iLabels as $key => $lbl) { + $value->Set($lbl); + $maxw = max($maxw,$value->GetWidth($aImg)); + } + } + else { + $value->Set('888.888'); // Dummy value to get width/height + $maxw = $value->GetWidth($aImg); + } + // Add an extra margin of 50% the font size + $maxw += round($this->iFontSize*$scaling * 0.4) ; + + $valxmarg = 1.5*$maxw+2*$this->iLabelMargin*$scaling; + $w = round($this->iSize*$scaling + $valxmarg); + + // Make sure that the width of the legend fits + $legendwidth = $this->_StrokeLegend($aImg,0,0,$scaling,true)+10*$scaling; + $w = max($w,$legendwidth); + + return $w; + } + + function getHeight($aImg) { + + $scaling = 1;//$this->iAntiAlias ? 2 : 1 ; + if( $this->iSize > 0 && $this->iSize < 1 ) { + $this->iSize *= min($aImg->width,$aImg->height); + } + + $value = new Text(); + $value->SetFont($this->iFontFamily,$this->iFontStyle,$this->iFontSize*$scaling); + $value->SetColor($this->iFontColor); + // Setup extra size around the graph needed so that the labels + // doesn't get cut. For this we need to find the largest label. + // The code below gives a possible a little to large margin. The + // really, really proper way would be to account for what angle + // the label are at + $n = count($this->iLabels); + if( $n > 0 ) { + $maxh=0;$maxw=0; + foreach($this->iLabels as $key => $lbl) { + $value->Set($lbl); + $maxh = max($maxh,$value->GetHeight($aImg)); + } + } + else { + $value->Set('180.8'); // Dummy value to get width/height + $maxh = $value->GetHeight($aImg); + } + // Add an extra margin of 50% the font size + //$maxh += round($this->iFontSize*$scaling * 0.5) ; + $valymarg = 2*$maxh+2*$this->iLabelMargin*$scaling; + + $legendheight = round($this->legend->iShow ? 1 : 0); + $legendheight *= max($this->legend->iCircleRadius*2,$this->legend->iTxtFontSize*2)+ + $this->legend->iMargin + $this->legend->iBottomMargin + 2; + $legendheight *= $scaling; + $h = round($this->iSize*$scaling + $valymarg) + $legendheight ; + + return $h; + } + + function Stroke($aGraph) { + + $aImg = $aGraph->img; + + if( $this->iX > 0 && $this->iX < 1 ) { + $this->iX = round( $aImg->width * $this->iX ) ; + } + + if( $this->iY > 0 && $this->iY < 1 ) { + $this->iY = round( $aImg->height * $this->iY ) ; + } + + if( $this->iSize > 0 && $this->iSize < 1 ) { + $this->iSize *= min($aImg->width,$aImg->height); + } + + if( $this->iCenterSize > 0 && $this->iCenterSize < 1 ) { + $this->iCenterSize *= $this->iSize; + } + + $this->scale->AutoScale(($this->iSize - $this->iCenterSize)/2, round(2.5*$this->scale->iFontSize)); + + $scaling = $this->iAntiAlias ? 2 : 1 ; + + $value = new Text(); + $value->SetFont($this->iFontFamily,$this->iFontStyle,$this->iFontSize*$scaling); + $value->SetColor($this->iFontColor); + + $legendheight = round($this->legend->iShow ? 1 : 0); + $legendheight *= max($this->legend->iCircleRadius*2,$this->legend->iTxtFontSize*2)+ + $this->legend->iMargin + $this->legend->iBottomMargin + 2; + $legendheight *= $scaling; + + $w = $scaling*$this->getWidth($aImg); + $h = $scaling*$this->getHeight($aImg); + + // Copy back the double buffered image to the proper canvas + $ww = $w / $scaling ; + $hh = $h / $scaling ; + + // Create the double buffer + if( $this->iAntiAlias ) { + $dblImg = new RotImage($w,$h); + // Set the background color + $dblImg->SetColor($this->iColor); + $dblImg->FilledRectangle(0,0,$w,$h); + } + else { + $dblImg = $aImg ; + // Make sure the ix and it coordinates correpond to the new top left center + $dblImg->SetTranslation($this->iX-$w/2, $this->iY-$h/2); + } + + if( __DEBUG ) { + $dblImg->SetColor('red'); + $dblImg->Rectangle(0,0,$w-1,$h-1); + } + + $dblImg->SetColor('black'); + + if( $this->iShowBox ) { + $dblImg->SetColor($this->iBoxColor); + $old = $dblImg->SetLineWeight($this->iBoxWeight); + $dblImg->SetLineStyle($this->iBoxStyle); + $dblImg->Rectangle(0,0,$w-1,$h-1); + $dblImg->SetLineWeight($old); + } + + $xc = round($w/2); + $yc = round(($h-$legendheight)/2); + + if( __DEBUG ) { + $dblImg->SetColor('red'); + $old = $dblImg->SetLineWeight(2); + $dblImg->Line($xc-5,$yc-5,$xc+5,$yc+5); + $dblImg->Line($xc+5,$yc-5,$xc-5,$yc+5); + $dblImg->SetLineWeight($old); + } + + $this->iSize *= $scaling; + + // Inner circle size + $ri = $this->iCenterSize/2 ; + + // Full circle radius + $r = round( $this->iSize/2 ); + + // Get number of grid circles + $n = $this->scale->GetNumCirc(); + + // Plot circle grids + $ri *= $scaling ; + $rr = round(($r-$ri)/$n); + for( $i = 1; $i <= $n; ++$i ) { + $this->_ThickCircle($dblImg,$xc,$yc,$rr*$i+$ri, + $this->iCircGridWeight,$this->iGridColor1); + } + + $num = 0 ; + + if( $this->iType == WINDROSE_TYPEFREE ) { + $this->_StrokeFreeRose($dblImg,$value,$scaling,$xc,$yc,$r,$ri); + } + else { + // Check if we need to re-code the interpretation of the ordinal + // number in the data. Internally ordinal value 0 is East and then + // counted anti-clockwise. The user might choose an encoding + // that have 0 being the first axis to the right of the "N" axis and then + // counted clock-wise + if( $this->iOrdinalEncoding == KEYENCODING_CLOCKWISE ) { + if( $this->iType == WINDROSE_TYPE16 ) { + $const1 = 19; $const2 = 16; + } + elseif( $this->iType == WINDROSE_TYPE8 ) { + $const1 = 9; $const2 = 8; + } + else { + $const1 = 4; $const2 = 4; + } + $tmp = array(); + $n=count($this->iData); + foreach( $this->iData as $key => $val ) { + if( is_numeric($key) ) { + $key = ($const1 - $key) % $const2 ; + } + $tmp[$key] = $val; + } + $this->iData = $tmp; + } + $this->_StrokeRegularRose($dblImg,$value,$scaling,$xc,$yc,$r,$ri); + } + + // Stroke the labels + $this->scale->iFontSize *= $scaling; + $this->scale->iZFontSize *= $scaling; + $this->scale->StrokeLabels($dblImg,$xc,$yc,$ri,$rr); + + // Stroke the inner circle again since the legs + // might have written over it + $this->_ThickCircle($dblImg,$xc,$yc,$ri,$this->iCircGridWeight,$this->iGridColor1); + + if( $ww > $aImg->width ) { + JpgraphError::RaiseL(22020); + //('Windrose plot is too large to fit the specified Graph size. Please use WindrosePlot::SetSize() to make the plot smaller or increase the size of the Graph in the initial WindroseGraph() call.'); + } + + $x = $xc; + $y = $h; + $this->_StrokeLegend($dblImg,$x,$y,$scaling); + + if( $this->iAntiAlias ) { + $aImg->Copy($dblImg->img, $this->iX-$ww/2, $this->iY-$hh/2, 0, 0, $ww,$hh, $w,$h); + } + + // We need to restore the translation matrix + $aImg->SetTranslation(0,0); + + } + +} + +//============================================================ +// CLASS WindroseGraph +//============================================================ +class WindroseGraph extends Graph { + private $posx, $posy; + public $plots=array(); + + function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { + parent::__construct($width,$height,$cachedName,$timeout,$inline); + $this->posx=$width/2; + $this->posy=$height/2; + $this->SetColor('white'); + $this->title->SetFont(FF_VERDANA,FS_NORMAL,12); + $this->title->SetMargin(8); + $this->subtitle->SetFont(FF_VERDANA,FS_NORMAL,10); + $this->subtitle->SetMargin(0); + $this->subsubtitle->SetFont(FF_VERDANA,FS_NORMAL,8); + $this->subsubtitle->SetMargin(0); + } + + function StrokeTexts() { + if( $this->texts != null ) { + $n = count($this->texts); + for($i=0; $i < $n; ++$i ) { + $this->texts[$i]->Stroke($this->img); + } + } + } + + function StrokeIcons() { + if( $this->iIcons != null ) { + $n = count($this->iIcons); + for( $i=0; $i < $n; ++$i ) { + // Since Windrose graphs doesn't have any linear scale the position of + // each icon has to be given as absolute coordinates + $this->iIcons[$i]->_Stroke($this->img); + } + } + } + + //--------------- + // PUBLIC METHODS + function Add($aObj) { + if( is_array($aObj) && count($aObj) > 0 ) { + $cl = $aObj[0]; + } + else { + $cl = $aObj; + } + if( $cl instanceof Text ) { + $this->AddText($aObj); + } + elseif( $cl instanceof IconPlot ) { + $this->AddIcon($aObj); + } + elseif( ($cl instanceof WindrosePlot) || ($cl instanceof LayoutRect) || ($cl instanceof LayoutHor)) { + $this->plots[] = $aObj; + } + else { + JpgraphError::RaiseL(22021); + } + } + + function AddText($aTxt,$aToY2=false) { + parent::AddText($aTxt); + } + + function SetColor($c) { + $this->SetMarginColor($c); + } + + // Method description + function Stroke($aStrokeFileName="") { + + // If the filename is the predefined value = '_csim_special_' + // we assume that the call to stroke only needs to do enough + // to correctly generate the CSIM maps. + // We use this variable to skip things we don't strictly need + // to do to generate the image map to improve performance + // as best we can. Therefore you will see a lot of tests !$_csim in the + // code below. + $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); + + // We need to know if we have stroked the plot in the + // GetCSIMareas. Otherwise the CSIM hasn't been generated + // and in the case of GetCSIM called before stroke to generate + // CSIM without storing an image to disk GetCSIM must call Stroke. + $this->iHasStroked = true; + + if( $this->background_image != "" || $this->background_cflag != "" ) { + $this->StrokeFrameBackground(); + } + else { + $this->StrokeFrame(); + } + + // n holds number of plots + $n = count($this->plots); + for($i=0; $i < $n ; ++$i) { + $this->plots[$i]->Stroke($this); + } + + $this->footer->Stroke($this->img); + $this->StrokeIcons(); + $this->StrokeTexts(); + $this->StrokeTitles(); + + // If the filename is given as the special "__handle" + // then the image handler is returned and the image is NOT + // streamed back + if( $aStrokeFileName == _IMG_HANDLER ) { + return $this->img->img; + } + else { + // Finally stream the generated picture + $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, + $aStrokeFileName); + } + } + +} // Class + +?> diff --git a/web/public_php/admin/jpgraph/lang/de.inc.php b/web/public_php/admin/jpgraph/lang/de.inc.php new file mode 100644 index 000000000..37ba264f4 --- /dev/null +++ b/web/public_php/admin/jpgraph/lang/de.inc.php @@ -0,0 +1,552 @@ +,) +$_jpg_messages = array( + +/* +** Headers wurden bereits gesendet - Fehler. Dies wird als HTML formatiert, weil es direkt als text zurueckgesendet wird +*/ +10 => array('
JpGraph Fehler: +HTTP header wurden bereits gesendet.
Fehler in der Datei %s in der Zeile %d.
Erklärung:
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).

Wahrscheinlich steht Text im Skript bevor Graph::Stroke() 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.

Zum Beispiel ist ein oft auftretender Fehler, eine Leerzeile am Anfang der Datei oder vor Graph::Stroke() zu lassen."<?php".

',2), + +/* +** Setup Fehler +*/ +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), +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), +13 => array('The installed PHP version (%s) is not compatible with this release of the library. The library requires at least PHP version %s',2), + +/* +** jpgraph_bar +*/ + +2001 => array('Die Anzahl der Farben ist nicht gleich der Anzahl der Vorlagen in BarPlot::SetPattern().',0), +2002 => array('Unbekannte Vorlage im Aufruf von BarPlot::SetPattern().',0), +2003 => array('Anzahl der X- und Y-Koordinaten sind nicht identisch. Anzahl der X-Koordinaten: %d; Anzahl der Y-Koordinaten: %d.',2), +2004 => array('Alle Werte für ein Balkendiagramm (barplot) müssen numerisch sein. Du hast den Wert nr [%d] == %s angegeben.',2), +2005 => array('Du hast einen leeren Vektor für die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0), +2006 => array('Unbekannte Position für die Werte der Balken: %s.',1), +2007 => array('Kann GroupBarPlot nicht aus einem leeren Vektor erzeugen.',0), +2008 => array('GroupBarPlot Element nbr %d wurde nicht definiert oder ist leer.',0), +2009 => array('Eins der Objekte, das an GroupBar weitergegeben wurde ist kein Balkendiagramm (BarPlot). Versichere Dich, dass Du den GroupBarPlot aus einem Vektor von Balkendiagrammen (barplot) oder AccBarPlot-Objekten erzeugst. (Class = %s)',1), +2010 => array('Kann AccBarPlot nicht aus einem leeren Vektor erzeugen.',0), +2011 => array('AccBarPlot-Element nbr %d wurde nicht definiert oder ist leer.',1), +2012 => 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), +2013 => array('Du hast einen leeren Vektor für die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0), +2014 => array('Die Anzahl der Datenpunkte jeder Datenreihe in AccBarPlot muss gleich sein.',0), +2015 => array('Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-coordinates',0), + + +/* +** jpgraph_date +*/ + +3001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0), + +/* +** jpgraph_error +*/ + +4002 => array('Fehler bei den Eingabedaten von LineErrorPlot. Die Anzahl der Datenpunkte mus ein Mehrfaches von drei sein!',0), + +/* +** jpgraph_flags +*/ + +5001 => array('Unbekannte Flaggen-Größe (%d).',1), +5002 => array('Der Flaggen-Index %s existiert nicht.',1), +5003 => array('Es wurde eine ungültige Ordnungszahl (%d) für den Flaggen-Index angegeben.',1), +5004 => 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), + + +/* +** jpgraph_gantt +*/ + +6001 => array('Interner Fehler. Die Höhe für ActivityTitles ist < 0.',0), +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), +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), +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), +6005 => array('SetScale() ist nicht sinnvoll bei Gantt-Diagrammen.',0), +6006 => array('Das Gantt-Diagramm kann nicht automatisch skaliert werden. Es existieren keine Aktivitäten mit Termin. [GetBarMinMax() start >= n]',0), +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), +6008 => array('Du hast eine Bedingung angegeben von Reihe=%d bis Reihe=%d, die keine Aktivität hat.',2), +6009 => array('Unbekannter Bedingungstyp von Reihe=%d bis Reihe=%d',2), +6010 => array('Ungültiger Icon-Index für das eingebaute Gantt-Icon [%d]',1), +6011 => array('Argument für IconImage muss entweder ein String oder ein Integer sein.',0), +6012 => array('Unbekannter Typ bei der Gantt-Objekt-Title-Definition.',0), +6015 => array('Ungültige vertikale Position %d',1), +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), +6017 => array('Unbekannter Datumstyp in GanttScale (%s).',1), +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), +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), +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), +6021 => array('Unbekanntes Format für die Woche.',0), +6022 => array('Die Gantt-Skala wurde nicht eingegeben.',0), +6023 => 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), +6024 => array('Das CSIM-Ziel muss als String angegeben werden. Der Start des Ziels ist: %d',1), +6025 => array('Der CSIM-Alt-Text muss als String angegeben werden. Der Beginn des Alt-Textes ist: %d',1), +6027 => array('Der Fortschrittswert muss im Bereich [0, 1] liegen.',0), +6028 => array('Die eingegebene Höhe (%d) für GanttBar ist nicht im zulässigen Bereich.',1), +6029 => array('Der Offset für die vertikale Linie muss im Bereich [0,1] sein.',0), +6030 => array('Unbekannte Pfeilrichtung für eine Verbindung.',0), +6031 => array('Unbekannter Pfeiltyp für eine Verbindung.',0), +6032 => array('Interner Fehler: Unbekannter Pfadtyp (=%d) für eine Verbindung.',1), +6033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0), + +/* +** jpgraph_gradient +*/ + +7001 => array('Unbekannter Gradiententyp (=%d).',1), + +/* +** jpgraph_iconplot +*/ + +8001 => array('Der Mix-Wert für das Icon muss zwischen 0 und 100 sein.',0), +8002 => array('Die Ankerposition für Icons muss entweder "top", "bottom", "left", "right" oder "center" sein.',0), +8003 => array('Es ist nicht möglich, gleichzeitig ein Bild und eine Landesflagge für dasselbe Icon zu definieren',0), +8004 => array('Wenn Du Landesflaggen benutzen willst, musst Du die Datei "jpgraph_flags.php" hinzufügen (per include).',0), + +/* +** jpgraph_imgtrans +*/ + +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), + +/* +** jpgraph_lineplot +*/ + +10001 => array('Die Methode LinePlot::SetFilled() sollte nicht mehr benutzt werden. Benutze lieber SetFillColor()',0), +10002 => array('Der Plot ist zu kompliziert für FastLineStroke. Benutze lieber den StandardStroke()',0), +10003 => array('Each plot in an accumulated lineplot must have the same number of data points.',0), +/* +** jpgraph_log +*/ + +11001 => array('Deine Daten enthalten nicht-numerische Werte.',0), +11002 => array('Negative Werte können nicht für logarithmische Achsen verwendet werden.',0), +11003 => array('Deine Daten enthalten nicht-numerische Werte.',0), +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), +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), + +/* +** jpgraph_mgraph +*/ + +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), +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), +12003 => array('Unbekannte Dateierweiterung (%s) in MGraph::SetBackgroundImage() für Dateiname: %s',2), +12004 => array('Das Bildformat des Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',1), +12005 => array('Das Hintergrundbild kann nicht gelesen werden: %s',1), +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), +12007 => array('Das Argument für MGraph::Add() ist nicht gültig für GD.',0), +12008 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Bildformate zu unterstützen.',0), +12009 => array('Deine PHP-Installation unterstützt das gewählte Bildformat nicht: %s',1), +12010 => array('Es konnte kein Bild als Datei %s erzeugt werden. Überprüfe, ob Du die entsprechenden Schreibrechte im aktuellen Verzeichnis hast.',1), +12011 => array('Es konnte kein Truecolor-Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0), +12012 => array('Es konnte kein Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0), + +/* +** jpgraph_pie3d +*/ + +14001 => array('Pie3D::ShowBorder(). Missbilligte Funktion. Benutze Pie3D::SetEdge(), um die Ecken der Tortenstücke zu kontrollieren.',0), +14002 => array('PiePlot3D::SetAngle() 3D-Torten-Projektionswinkel muss zwischen 5 und 85 Grad sein.',0), +14003 => array('Interne Festlegung schlug fehl. Pie3D::Pie3DSlice',0), +14004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',0), +14005 => array('Pie3D Interner Fehler: Versuch, zweimal zu umhüllen bei der Suche nach dem Startindex.',0,), +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), +14007 => array('Die Breite für das 3D-Tortendiagramm ist 0. Gib eine Breite > 0 an.',0), + +/* +** jpgraph_pie +*/ + +15001 => array('PiePLot::SetTheme() Unbekannter Stil: %s',1), +15002 => array('Argument für PiePlot::ExplodeSlice() muss ein Integer-Wert sein',0), +15003 => array('Argument für PiePlot::Explode() muss ein Vektor mit Integer-Werten sein.',0), +15004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',0), +15005 => array('PiePlot::SetFont() sollte nicht mehr verwendet werden. Benutze stattdessen PiePlot->value->SetFont().',0), +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), +15007 => array('PiePlot::SetFontColor() sollte nicht mehr verwendet werden. Benutze stattdessen PiePlot->value->SetColor()..',0), +15008 => array('PiePlot::SetLabelType() der Typ für Tortendiagramme muss entweder 0 or 1 sein (nicht %d).',1), +15009 => array('Ungültiges Tortendiagramm. Die Summe aller Daten ist Null.',0), +15010 => array('Die Summe aller Daten ist Null.',0), +15011 => array('Um Bildtransformationen benutzen zu können, muss die Datei jpgraph_imgtrans.php eingefügt werden (per include).',0), // @todo translate into German +15012 => array('PiePlot::SetTheme() is no longer recommended. Use PieGraph::SetTheme()',0), + +/* +** jpgraph_plotband +*/ + +16001 => array('Die Dichte für das Pattern muss zwischen 1 und 100 sein. (Du hast %f eingegeben)',1), +16002 => array('Es wurde keine Position für das Pattern angegeben.',0), +16003 => array('Unbekannte Pattern-Definition (%d)',0), +16004 => array('Der Mindeswert für das PlotBand ist größer als der Maximalwert. Bitte korrigiere dies!',0), + + +/* +** jpgraph_polar +*/ + +17001 => array('PolarPlots müssen eine gerade Anzahl von Datenpunkten haben. Jeder Datenpunkt ist ein Tupel (Winkel, Radius).',0), +17002 => array('Unbekannte Ausrichtung für X-Achsen-Titel. (%s)',1), +//17003 => array('Set90AndMargin() wird für PolarGraph nicht unterstützt.',0), +17004 => array('Unbekannter Achsentyp für PolarGraph. Er muss entweder \'lin\' oder \'log\' sein.',0), + +/* +** jpgraph_radar +*/ + +18001 => array('ClientSideImageMaps werden für RadarPlots nicht unterstützt.',0), +18002 => array('RadarGraph::SupressTickMarks() sollte nicht mehr verwendet werden. Benutze stattdessen HideTickMarks().',0), +18003 => array('Ungültiger Achsentyp für RadarPlot (%s). Er muss entweder \'lin\' oder \'log\' sein.',1), +18004 => array('Die RadarPlot-Größe muss zwischen 0.1 und 1 sein. (Dein Wert=%f)',1), +18005 => array('RadarPlot: nicht unterstützte Tick-Dichte: %d',1), +18006 => array('Minimum Daten %f (RadarPlots sollten nur verwendet werden, wenn alle Datenpunkte einen Wert > 0 haben).',1), +18007 => array('Die Anzahl der Titel entspricht nicht der Anzahl der Datenpunkte.',0), +18008 => array('Jeder RadarPlot muss die gleiche Anzahl von Datenpunkten haben.',0), + +/* +** jpgraph_regstat +*/ + +19001 => array('Spline: Anzahl der X- und Y-Koordinaten muss gleich sein.',0), +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), +19003 => array('Bezier: Anzahl der X- und Y-Koordinaten muss gleich sein.',0), + +/* +** jpgraph_scatter +*/ + +20001 => array('Fieldplots müssen die gleiche Anzahl von X und Y Datenpunkten haben.',0), +20002 => array('Bei Fieldplots muss ein Winkel für jeden X und Y Datenpunkt angegeben werden.',0), +20003 => array('Scatterplots müssen die gleiche Anzahl von X- und Y-Datenpunkten haben.',0), + +/* +** jpgraph_stock +*/ + +21001 => array('Die Anzahl der Datenwerte für Stock-Charts müssen ein Mehrfaches von %d Datenpunkten sein.',1), + +/* +** jpgraph_plotmark +*/ + +23001 => array('Der Marker "%s" existiert nicht in der Farbe: %d',2), +23002 => array('Der Farb-Index ist zu hoch für den Marker "%s"',1), +23003 => array('Ein Dateiname muss angegeben werden, wenn Du den Marker-Typ auf MARK_IMG setzt.',0), + +/* +** jpgraph_utils +*/ + +24001 => array('FuncGenerator : Keine Funktion definiert. ',0), +24002 => array('FuncGenerator : Syntax-Fehler in der Funktionsdefinition ',0), +24003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0), +24004 => array('ReadCSV2: Die anzahl der spalten fehler in %s reihe %d',2), +/* +** jpgraph +*/ + +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), +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), +25003 => array('Genereller PHP Fehler : Bei %s:%d : %s',3), +25004 => array('Genereller PHP Fehler : %s ',1), +25005 => 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), +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), +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), +25008 => array('Die Bild-Breite und Höhe in Graph::Graph() müssen numerisch sein',0), +25009 => array('Die Skalierung der Achsen muss angegeben werden mit Graph::SetScale()',0), + +25010 => array('Graph::Add() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0), +25011 => array('Graph::AddY2() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0), +25012 => array('Graph::AddYN() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0), +25013 => array('Es können nur Standard-Plots zu multiplen Y-Achsen hinzugefügt werden',0), +25014 => array('Graph::AddText() Du hast versucht, einen leeren Text zum Graph hinzuzufügen.',0), +25015 => array('Graph::AddLine() Du hast versucht, eine leere Linie zum Graph hinzuzufügen.',0), +25016 => array('Graph::AddBand() Du hast versucht, ein leeres Band zum Graph hinzuzufügen.',0), +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), +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), +25019 => array('Unbekannte Dateinamenerweiterung (%s) in Graph::SetBackgroundImage() für Dateiname: "%s"',2), + +25020 => array('Graph::SetScale(): Dar Maximalwert muss größer sein als der Mindestwert.',0), +25021 => array('Unbekannte Achsendefinition für die Y-Achse. (%s)',1), +25022 => array('Unbekannte Achsendefinition für die X-Achse. (%s)',1), +25023 => array('Nicht unterstützter Y2-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1), +25024 => array('Nicht unterstützter X-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1), +25025 => array('Nicht unterstützte Tick-Dichte: %d',1), +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), +25027 => array('Kann cached CSIM "%s" zum Lesen nicht öffnen.',1), +25028 => array('Apache/PHP hat keine Schreibrechte, in das CSIM-Cache-Verzeichnis (%s) zu schreiben. Überprüfe die Rechte.',1), +25029 => array('Kann nicht in das CSIM "%s" schreiben. Überprüfe die Schreibrechte und den freien Speicherplatz.',1), + +25030 => array('Fehlender Skriptname für StrokeCSIM(). Der Name des aktuellen Skriptes muss als erster Parameter von StrokeCSIM() angegeben werden.',0), +25031 => array('Der Achsentyp muss mittels Graph::SetScale() angegeben werden.',0), +25032 => array('Es existieren keine Plots für die Y-Achse nbr:%d',1), +25033 => array('',0), +25034 => array('Undefinierte X-Achse kann nicht gezeichnet werden. Es wurden keine Plots definiert.',0), +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), +25036 => array('Unbekannter Achsentyp AxisStyle() : %s',1), +25037 => array('Das Bildformat Deines Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',1), +25038 => array('Das Hintergrundbild scheint von einem anderen Typ (unterschiedliche Dateierweiterung) zu sein als der angegebene Typ. Angegebenen: %s; Datei: %s',2), +25039 => array('Hintergrundbild kann nicht gelesen werden: "%s"',1), + +25040 => array('Es ist nicht möglich, sowohl ein Hintergrundbild als auch eine Hintergrund-Landesflagge anzugeben.',0), +25041 => array('Um Landesflaggen als Hintergrund benutzen zu können, muss die Datei "jpgraph_flags.php" eingefügt werden (per include).',0), +25042 => array('Unbekanntes Hintergrundbild-Layout',0), +25043 => array('Unbekannter Titelhintergrund-Stil.',0), +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), +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), +25046 => 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), +25047 => array('Stil %s ist nicht verfügbar für Schriftfamilie %s',2), +25048 => array('Unbekannte Schriftstildefinition [%s].',1), +25049 => array('Schriftdatei "%s" ist nicht lesbar oder existiert nicht.',1), + +25050 => array('Erstes Argument für Text::Text() muss ein String sein.',0), +25051 => array('Ungültige Richtung angegeben für Text.',0), +25052 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte vertikale Ausrichtung für Text.',0), +25053 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte horizontale Ausrichtung für Text.',0), +25054 => array('Interner Fehler: Unbekannte Grid-Achse %s',1), +25055 => array('Axis::SetTickDirection() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetTickSide().',0), +25056 => array('SetTickLabelMargin() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetLabelMargin().',0), +25057 => array('SetTextTicks() sollte nicht mehr verwendet werden. Benutze stattdessen SetTextTickInterval().',0), +25058 => array('TextLabelIntevall >= 1 muss angegeben werden.',0), +25059 => array('SetLabelPos() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetLabelSide().',0), + +25060 => array('Unbekannte Ausrichtung angegeben für X-Achsentitel (%s).',1), +25061 => array('Unbekannte Ausrichtung angegeben für Y-Achsentitel (%s).',1), +25062 => array('Label unter einem Winkel werden für die Y-Achse nicht unterstützt.',0), +25063 => array('Ticks::SetPrecision() sollte nicht mehr verwendet werden. Benutze stattdessen Ticks::SetLabelFormat() (oder Ticks::SetFormatCallback()).',0), +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), +25065 => array('Tick-Positionen müssen als array() angegeben werden',0), +25066 => array('Wenn die Tick-Positionen und -Label von Hand eingegeben werden, muss die Anzahl der Ticks und der Label gleich sein.',0), +25067 => array('Deine von Hand eingegebene Achse und Ticks sind nicht korrekt. Die Skala scheint zu klein zu sein für den Tickabstand.',0), +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), +25069 => array('Grace muss größer sein als 0',0), + +25070 => array('Deine Daten enthalten nicht-numerische Werte.',0), +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), +25072 => array('Du hast mit SetAutoMax() einen Maximalwert angegeben, der kleiner ist als der Minimalwert der Achse. Dies ist nicht möglich.',0), +25073 => array('Interner Fehler. Der Integer-Skalierungs-Algorithmus-Vergleich ist außerhalb der Grenzen (r=%f).',1), +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), +25075 => array('Die automatischen Ticks können nicht gesetzt werden, weil min==max.',0), +25077 => array('Einstellfaktor für die Farbe muss größer sein als 0',0), +25078 => array('Unbekannte Farbe: %s',1), +25079 => array('Unbekannte Farbdefinition: %s, Größe=%d',2), + +25080 => array('Der Alpha-Parameter für Farben muss zwischen 0.0 und 1.0 liegen.',0), +25081 => array('Das ausgewählte Grafikformat wird entweder nicht unterstützt oder ist unbekannt [%s]',1), +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), +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), +25084 => array('Fehler beim Erstellen eines temporären GD-Canvas. Möglicherweise liegt ein Arbeitsspeicherproblem vor.',0), +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), +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), +25087 => array('Diese PHP-Version wurde ohne TTF-Unterstützung konfiguriert. PHP muss mit TTF-Unterstützung neu kompiliert und installiert werden.',0), +25088 => array('Die GD-Schriftunterstützung wurde falsch konfiguriert. Der Aufruf von imagefontwidth() ist fehlerhaft.',0), +25089 => array('Die GD-Schriftunterstützung wurde falsch konfiguriert. Der Aufruf von imagefontheight() ist fehlerhaft.',0), + +25090 => array('Unbekannte Richtung angegeben im Aufruf von StrokeBoxedText() [%s].',1), +25091 => array('Die interne Schrift untestützt das Schreiben von Text in einem beliebigen Winkel nicht. Benutze stattdessen TTF-Schriften.',0), +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), +25093 => 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), +25094 => array('Die Textrichtung muss in einem Winkel zwischen 0 und 90 engegeben werden.',0), +25095 => array('Unbekannte Schriftfamilien-Definition. ',0), +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), +25097 => array('Eine Farbe wurde als leerer String im Aufruf von PushColor() angegegeben.',0), +25098 => array('Negativer Farbindex. Unpassender Aufruf von PopColor().',0), +25099 => array('Die Parameter für Helligkeit und Kontrast sind außerhalb des zulässigen Bereichs [-1,1]',0), + +25100 => 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), +25101 => array('Ungültiges numerisches Argument für SetLineStyle(): (%d)',1), +25102 => array('Ungültiges String-Argument für SetLineStyle(): %s',1), +25103 => array('Ungültiges Argument für SetLineStyle %s',1), +25104 => array('Unbekannter Linientyp: %s',1), +25105 => array('Es wurden NULL-Daten für ein gefülltes Polygon angegeben. Sorge dafür, dass keine NULL-Daten angegeben werden.',0), +25106 => array('Image::FillToBorder : es können keine weiteren Farben zugewiesen werden.',0), +25107 => array('In Datei "%s" kann nicht geschrieben werden. Überprüfe die aktuellen Schreibrechte.',1), +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), +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), + +25110 => array('Dein PHP-Installation unterstützt das gewählte Grafikformat nicht: %s',1), +25111 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1), +25112 => array('Das Datum der gecacheten Datei (%s) liegt in der Zukunft.',1), +25113 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1), +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), +25115 => array('Berechtigung für gecachetes Bild %s kann nicht gesetzt werden. Problem mit den Rechten?',1), +25116 => array('Datei kann nicht aus dem Cache %s geöffnet werden',1), +25117 => array('Gecachetes Bild %s kann nicht zum Lesen geöffnet werden.',1), +25118 => array('Verzeichnis %s kann nicht angelegt werden. Versichere Dich, dass PHP die Schreibrechte in diesem Verzeichnis hat.',1), +25119 => array('Rechte für Datei %s können nicht gesetzt werden. Problem mit den Rechten?',1), + +25120 => array('Die Position für die Legende muss als Prozentwert im Bereich 0-1 angegeben werden.',0), +25121 => array('Eine leerer Datenvektor wurde für den Plot eingegeben. Es muss wenigstens ein Datenpunkt vorliegen.',0), +25122 => array('Stroke() muss als Subklasse der Klasse Plot definiert sein.',0), +25123 => array('Du kannst keine Text-X-Achse mit X-Koordinaten verwenden. Benutze stattdessen eine "int" oder "lin" Achse.',0), +25124 => array('Der Eingabedatenvektor mus aufeinanderfolgende Werte von 0 aufwärts beinhalten. Der angegebene Y-Vektor beginnt mit leeren Werten (NULL).',0), +25125 => array('Ungültige Richtung für statische Linie.',0), +25126 => array('Es kann kein TrueColor-Bild erzeugt werden. Überprüfe, ob die GD2-Bibliothek und PHP korrekt aufgesetzt wurden.',0), +25127 => 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), +25128 => 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), +25129 => array('Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.',0), +25130 => array('Too small plot area. (%d x %d). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.',2), + +25131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0), +25132 => array('Undefined property %s.',1), // @todo translate +25133 => array('Use Graph::SetTheme() after Graph::SetScale().',0), // @todo translate + +/* +** jpgraph_led +*/ + +25500 => array('Multibyte strings must be enabled in the PHP installation in order to run the LED module so that the function mb_strlen() is available. See PHP documentation for more information.',0), + + +/* +**--------------------------------------------------------------------------------------------- +** Pro-version strings +**--------------------------------------------------------------------------------------------- +*/ + +/* +** jpgraph_table +*/ + +27001 => array('GTextTable: Ungültiges Argument für Set(). Das Array-Argument muss 2-- dimensional sein.',0), +27002 => array('GTextTable: Ungültiges Argument für Set()',0), +27003 => array('GTextTable: Falsche Anzahl von Argumenten für GTextTable::SetColor()',0), +27004 => array('GTextTable: Angegebener Zellenbereich, der verschmolzen werden soll, ist ungültig.',0), +27005 => array('GTextTable: Bereits verschmolzene Zellen im Bereich (%d,%d) bis (%d,%d) können nicht ein weiteres Mal verschmolzen werden.',4), +27006 => array('GTextTable: Spalten-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1), +27007 => array('GTextTable: Zeilen-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1), +27008 => array('GTextTable: Spalten- und Zeilengröße müssen zu den Dimensionen der Tabelle passen.',0), +27009 => array('GTextTable: Die Anzahl der Tabellenspalten oder -zeilen ist 0. Versichere Dich, dass die Methoden Init() oder Set() aufgerufen werden.',0), +27010 => array('GTextTable: Es wurde keine Ausrichtung beim Aufruf von SetAlign() angegeben.',0), +27011 => array('GTextTable: Es wurde eine unbekannte Ausrichtung beim Aufruf von SetAlign() abgegeben. Horizontal=%s, Vertikal=%s',2), +27012 => array('GTextTable: Interner Fehler. Es wurde ein ungültiges Argument festgeleget %s',1), +27013 => array('GTextTable: Das Argument für FormatNumber() muss ein String sein.',0), +27014 => array('GTextTable: Die Tabelle wurde weder mit einem Aufruf von Set() noch von Init() initialisiert.',0), +27015 => array('GTextTable: Der Zellenbildbedingungstyp muss entweder TIMG_WIDTH oder TIMG_HEIGHT sein.',0), + +/* +** jpgraph_windrose +*/ + +22001 => array('Die Gesamtsumme der prozentualen Anteile aller Windrosenarme darf 100%% nicht überschreiten!\n(Aktuell max: %d)',1), +22002 => array('Das Bild ist zu klein für eine Skala. Bitte vergrößere das Bild.',0), +22004 => array('Die Etikettendefinition für Windrosenrichtungen müssen 16 Werte haben (eine für jede Kompassrichtung).',0), +22005 => array('Der Linientyp für radiale Linien muss einer von ("solid","dotted","dashed","longdashed") sein.',0), +22006 => array('Es wurde ein ungültiger Windrosentyp angegeben.',0), +22007 => array('Es wurden zu wenig Werte für die Bereichslegende angegeben.',0), +22008 => array('Interner Fehler: Versuch, eine freie Windrose zu plotten, obwohl der Typ keine freie Windrose ist.',0), +22009 => array('Du hast die gleiche Richtung zweimal angegeben, einmal mit einem Winkel und einmal mit einer Kompassrichtung (%f Grad).',0), +22010 => array('Die Richtung muss entweder ein numerischer Wert sein oder eine der 16 Kompassrichtungen',0), +22011 => array('Der Windrosenindex muss ein numerischer oder Richtungswert sein. Du hast angegeben Index=%d',1), +22012 => array('Die radiale Achsendefinition für die Windrose enthält eine nicht aktivierte Richtung.',0), +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), +22014 => array('Der Index für eine Kompassrichtung muss zwischen 0 und 15 sein.',0), +22015 => array('Du hast einen unbekannten Windrosenplottyp angegeben.',0), +22016 => array('Der Windrosenarmindex muss ein numerischer oder ein Richtungswert sein.',0), +22017 => array('Die Windrosendaten enthalten eine Richtung, die nicht aktiviert ist. Bitte berichtige, welche Label angezeigt werden sollen.',0), +22018 => array('Du hast für dieselbe Kompassrichtung zweimal Daten angegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1), +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), +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), +22021 => array('It is only possible to add Text, IconPlot or WindrosePlot to a Windrose Graph',0), + +/* +** jpgraph_odometer +*/ + +13001 => array('Unbekannter Nadeltypstil (%d).',1), +13002 => array('Ein Wert für das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3), + +/* +** jpgraph_barcode +*/ + +1001 => array('Unbekannte Kodier-Specifikation: %s',1), +1002 => array('datenvalidierung schlug fehl. [%s] kann nicht mittels der Kodierung "%s" kodiert werden',2), +1003 => array('Interner Kodierfehler. Kodieren von %s ist nicht möglich in Code 128',1), +1004 => array('Interner barcode Fehler. Unbekannter UPC-E Kodiertyp: %s',1), +1005 => array('Interner Fehler. Das Textzeichen-Tupel (%s, %s) kann nicht im Code-128 Zeichensatz C kodiert werden.',2), +1006 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, CTRL in CHARSET != A zu kodieren.',0), +1007 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, DEL in CHARSET != B zu kodieren.',0), +1008 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, kleine Buchstaben in CHARSET != B zu kodieren.',0), +1009 => array('Kodieren mittels CODE 93 wird noch nicht unterstützt.',0), +1010 => array('Kodieren mittels POSTNET wird noch nicht unterstützt.',0), +1011 => array('Nicht untrstütztes Barcode-Backend für den Typ %s',1), + +/* +** PDF417 +*/ + +26000 => array('PDF417: The PDF417 module requires that the PHP installation must support the function bcmod(). This is normally enabled at compile time. See documentation for more information.',0), +26001 => array('PDF417: Die Anzahl der Spalten muss zwischen 1 und 30 sein.',0), +26002 => array('PDF417: Der Fehler-Level muss zwischen 0 und 8 sein.',0), +26003 => array('PDF417: Ungültiges Format für Eingabedaten, um sie mit PDF417 zu kodieren.',0), +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), +26005 => array('PDF417: Die Datei "%s" kann nicht zum Schreiben geöffnet werden.',1), +26006 => array('PDF417: Interner Fehler. Die Eingabedatendatei für PDF417-Cluster %d ist fehlerhaft.',1), +26007 => array('PDF417: Interner Fehler. GetPattern: Ungültiger Code-Wert %d (Zeile %d)',2), +26008 => array('PDF417: Interner Fehler. Modus wurde nicht in der Modusliste!! Modus %d',1), +26009 => array('PDF417: Kodierfehler: Ungültiges Zeichen. Zeichen kann nicht mit ASCII-Code %d kodiert werden.',1), +26010 => array('PDF417: Interner Fehler: Keine Eingabedaten beim Dekodieren.',0), +26011 => array('PDF417: Kodierfehler. Numerisches Kodieren bei nicht-numerischen Daten nicht möglich.',0), +26012 => array('PDF417: Interner Fehler. Es wurden für den Binary-Kompressor keine Daten zum Dekodieren eingegeben.',0), +26013 => array('PDF417: Interner Fehler. Checksum Fehler. Koeffiziententabellen sind fehlerhaft.',0), +26014 => array('PDF417: Interner Fehler. Es wurden keine Daten zum Berechnen von Kodewörtern eingegeben.',0), +26015 => array('PDF417: Interner Fehler. Ein Eintrag 0 in die Statusübertragungstabellen ist nicht NULL. Eintrag 1 = (%s)',1), +26016 => array('PDF417: Interner Fehler: Nichtregistrierter Statusübertragungsmodus beim Dekodieren.',0), + + +/* +** jpgraph_contour +*/ + +28001 => array('Dritten parameter fur Contour muss ein vector der fargen sind.',0), +28002 => array('Die anzahlen der farges jeder isobar linien muss gleich sein.',0), +28003 => array('ContourPlot Interner Fehler: isobarHCrossing: Spalten index ist zu hoch (%d)',1), +28004 => array('ContourPlot Interner Fehler: isobarHCrossing: Reihe index ist zu hoch (%d)',1), +28005 => array('ContourPlot Interner Fehler: isobarVCrossing: Reihe index ist zu hoch (%d)',1), +28006 => array('ContourPlot Interner Fehler: isobarVCrossing: Spalten index ist zu hoch (%d)',1), +28007 => array('ContourPlot. Interpolation faktor ist zu hoch (>5)',0), + + +/* + * jpgraph_matrix and colormap +*/ +29201 => array('Min range value must be less or equal to max range value for colormaps',0), +29202 => array('The distance between min and max value is too small for numerical precision',0), +29203 => array('Number of color quantification level must be at least %d',1), +29204 => array('Number of colors (%d) is invalid for this colormap. It must be a number that can be written as: %d + k*%d',3), +29205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1), +29206 => array('Invalid object added to MatrixGraph',0), +29207 => array('Empty input data specified for MatrixPlot',0), +29208 => array('Unknown side specifiction for matrix labels "%s"',1), +29209 => array('CSIM Target matrix must be the same size as the data matrix (csim=%d x %d, data=%d x %d)',4), +29210 => array('CSIM Target for matrix labels does not match the number of labels (csim=%d, labels=%d)',2), + + +/* +* jpgraph_theme +*/ +30001 => array("Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs.",2), + + +); + +?> diff --git a/web/public_php/admin/jpgraph/lang/en.inc.php b/web/public_php/admin/jpgraph/lang/en.inc.php index cfb916060..101e8bd82 100644 --- a/web/public_php/admin/jpgraph/lang/en.inc.php +++ b/web/public_php/admin/jpgraph/lang/en.inc.php @@ -1,495 +1,545 @@ -,) -$_jpg_messages = array( - -/* -** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text -*/ -10 => array('
JpGraph Error: -HTTP headers have already been sent.
Caused by output from file %s at line %d.
Explanation:
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).

Most likely you have some text in your script before the call to Graph::Stroke(). 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.

For example it is a common mistake to leave a blank line before the opening "<?php".

',2), - -/* -** Setup errors -*/ -11 => array('No path specified for CACHE_DIR. Please specify CACHE_DIR manually in jpg-config.inc',0), -12 => array('No path specified for TTF_DIR and path can not be determined automatically. Please specify TTF_DIR manually (in jpg-config.inc).',0), - -/* -** jpgraph_bar -*/ - -2001 => array('Number of colors is not the same as the number of patterns in BarPlot::SetPattern()',0), -2002 => array('Unknown pattern specified in call to BarPlot::SetPattern()',0), -2003 => array('Number of X and Y points are not equal. Number of X-points: %d Number of Y-points: %d',2), -2004 => array('All values for a barplot must be numeric. You have specified value nr [%d] == %s',2), -2005 => array('You have specified an empty array for shadow colors in the bar plot.',0), -2006 => array('Unknown position for values on bars : %s',1), -2007 => array('Cannot create GroupBarPlot from empty plot array.',0), -2008 => array('Group bar plot element nbr %d is undefined or empty.',0), -2009 => array('One of the objects submitted to GroupBar is not a BarPlot. Make sure that you create the GroupBar plot from an array of BarPlot or AccBarPlot objects. (Class = %s)',1), -2010 => array('Cannot create AccBarPlot from empty plot array.',0), -2011 => array('Acc bar plot element nbr %d is undefined or empty.',1), -2012 => array('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=%s)',1), -2013 => array('You have specified an empty array for shadow colors in the bar plot.',0), -2014 => array('Number of datapoints for each data set in accbarplot must be the same',0), - - -/* -** jpgraph_date -*/ - -3001 => array('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both',0), - -/* -** jpgraph_error -*/ - -4002 => array('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3',0), - -/* -** jpgraph_flags -*/ - -5001 => array('Unknown flag size (%d).',1), -5002 => array('Flag index %s does not exist.',1), -5003 => array('Invalid ordinal number (%d) specified for flag index.',1), -5004 => array('The (partial) country name %s does not have a corresponding flag image. The flag may still exist but under another name, e.g. instead of "usa" try "united states".',1), - - -/* -** jpgraph_gantt -*/ - -6001 => array('Internal error. Height for ActivityTitles is < 0',0), -6002 => 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), -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), -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), -6005 => array('SetScale() is not meaningful with Gantt charts.',0), -6006 => array('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]',0), -6007 => array('Sanity check for automatic Gantt chart size failed. Either the width (=%d) or height (=%d) is larger than MAX_GANTTIMG_SIZE. This could potentially be caused by a wrong date in one of the activities.',2), -6008 => array('You have specified a constrain from row=%d to row=%d which does not have any activity',2), -6009 => array('Unknown constrain type specified from row=%d to row=%d',2), -6010 => array('Illegal icon index for Gantt builtin icon [%d]',1), -6011 => array('Argument to IconImage must be string or integer',0), -6012 => array('Unknown type in Gantt object title specification',0), -6015 => array('Illegal vertical position %d',1), -6016 => array('Date string (%s) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30',1), -6017 => array('Unknown date format in GanttScale (%s).',1), -6018 => array('Interval for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an interval of %d minutes.',1), -6019 => array('The available width (%d) for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.',1), -6020 => array('Interval for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an interval of %d',1), -6021 => array('Unknown formatting style for week.',0), -6022 => array('Gantt scale has not been specified.',0), -6023 => array('If you display both hour and minutes the hour interval must be 1 (Otherwise it doesn\'t make sense to display minutes).',0), -6024 => array('CSIM Target must be specified as a string. Start of target is: %d',1), -6025 => array('CSIM Alt text must be specified as a string. Start of alt text is: %d',1), -6027 => array('Progress value must in range [0, 1]',0), -6028 => array('Specified height (%d) for gantt bar is out of range.',1), -6029 => array('Offset for vertical line must be in range [0,1]',0), -6030 => array('Unknown arrow direction for link.',0), -6031 => array('Unknown arrow type for link.',0), -6032 => array('Internal error: Unknown path type (=%d) specified for link.',1), - -/* -** jpgraph_gradient -*/ - -7001 => array('Unknown gradient style (=%d).',1), - -/* -** jpgraph_iconplot -*/ - -8001 => array('Mix value for icon must be between 0 and 100.',0), -8002 => array('Anchor position for icons must be one of "top", "bottom", "left", "right" or "center"',0), -8003 => array('It is not possible to specify both an image file and a country flag for the same icon.',0), -8004 => array('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.',0), - -/* -** jpgraph_imgtrans -*/ - -9001 => array('Value for image transformation out of bounds. Vanishing point on horizon must be specified as a value between 0 and 1.',0), - -/* -** jpgraph_lineplot -*/ - -10001 => array('LinePlot::SetFilled() is deprecated. Use SetFillColor()',0), -10002 => array('Plot too complicated for fast line Stroke. Use standard Stroke()',0), - -/* -** jpgraph_log -*/ - -11001 => array('Your data contains non-numeric values.',0), -11002 => array('Negative data values can not be used in a log scale.',0), -11003 => array('Your data contains non-numeric values.',0), -11004 => array('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.',0), -11005 => array('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.',0), - -/* -** jpgraph_mgraph -*/ - -12001 => 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), -12002 => array('Incorrect file name for MGraph::SetBackgroundImage() : %s Must have a valid image extension (jpg,gif,png) when using auto detection of image type',1), -12003 => array('Unknown file extension (%s) in MGraph::SetBackgroundImage() for filename: %s',2), -12004 => array('The image format of your background image (%s) is not supported in your system configuration. ',1), -12005 => array('Can\'t read background image: %s',1), -12006 => array('Illegal sizes specified for width or height when creating an image, (width=%d, height=%d)',2), -12007 => array('Argument to MGraph::Add() is not a valid GD image handle.',0), -12008 => array('Your PHP (and GD-lib) installation does not appear to support any known graphic formats.',0), -12009 => array('Your PHP installation does not support the chosen graphic format: %s',1), -12010 => array('Can\'t create or stream image to file %s Check that PHP has enough permission to write a file to the current directory.',1), -12011 => array('Can\'t create truecolor image. Check that you really have GD2 library installed.',0), -12012 => array('Can\'t create image. Check that you really have GD2 library installed.',0), - -/* -** jpgraph_pie3d -*/ - -14001 => array('Pie3D::ShowBorder() . Deprecated function. Use Pie3D::SetEdge() to control the edges around slices.',0), -14002 => array('PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.',0), -14003 => array('Internal assertion failed. Pie3D::Pie3DSlice',0), -14004 => array('Slice start angle must be between 0 and 360 degrees.',0), -14005 => array('Pie3D Internal error: Trying to wrap twice when looking for start index',0,), -14006 => array('Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.',0), -14007 => array('Width for 3D Pie is 0. Specify a size > 0',0), - -/* -** jpgraph_pie -*/ - -15001 => array('PiePLot::SetTheme() Unknown theme: %s',1), -15002 => array('Argument to PiePlot::ExplodeSlice() must be an integer',0), -15003 => array('Argument to PiePlot::Explode() must be an array with integer distances.',0), -15004 => array('Slice start angle must be between 0 and 360 degrees.',0), -15005 => array('PiePlot::SetFont() is deprecated. Use PiePlot->value->SetFont() instead.',0), -15006 => array('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]',0), -15007 => array('PiePlot::SetFontColor() is deprecated. Use PiePlot->value->SetColor() instead.',0), -15008 => array('PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not %d).',1), -15009 => array('Illegal pie plot. Sum of all data is zero for Pie Plot',0), -15010 => array('Sum of all data is 0 for Pie.',0), -15011 => array('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.',0), - -/* -** jpgraph_plotband -*/ - -16001 => array('Density for pattern must be between 1 and 100. (You tried %f)',1), -16002 => array('No positions specified for pattern.',0), -16003 => array('Unknown pattern specification (%d)',0), -16004 => array('Min value for plotband is larger than specified max value. Please correct.',0), - - -/* -** jpgraph_polar -*/ - -17001 => array('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).',0), -17002 => array('Unknown alignment specified for X-axis title. (%s)',1), -//17003 => array('Set90AndMargin() is not supported for polar graphs.',0), -17004 => array('Unknown scale type for polar graph. Must be "lin" or "log"',0), - -/* -** jpgraph_radar -*/ - -18001 => array('Client side image maps not supported for RadarPlots.',0), -18002 => array('RadarGraph::SupressTickMarks() is deprecated. Use HideTickMarks() instead.',0), -18003 => array('Illegal scale for radarplot (%s). Must be \'lin\' or \'log\'',1), -18004 => array('Radar Plot size must be between 0.1 and 1. (Your value=%f)',1), -18005 => array('RadarPlot Unsupported Tick density: %d',1), -18006 => array('Minimum data %f (Radar plots should only be used when all data points > 0)',1), -18007 => array('Number of titles does not match number of points in plot.',0), -18008 => array('Each radar plot must have the same number of data points.',0), - -/* -** jpgraph_regstat -*/ - -19001 => array('Spline: Number of X and Y coordinates must be the same',0), -19002 => array('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.',0), -19003 => array('Bezier: Number of X and Y coordinates must be the same',0), - -/* -** jpgraph_scatter -*/ - -20001 => array('Fieldplots must have equal number of X and Y points.',0), -20002 => array('Fieldplots must have an angle specified for each X and Y points.',0), -20003 => array('Scatterplot must have equal number of X and Y points.',0), - -/* -** jpgraph_stock -*/ - -21001 => array('Data values for Stock charts must contain an even multiple of %d data points.',1), - -/* -** jpgraph_plotmark -*/ - -23001 => array('This marker "%s" does not exist in color with index: %d',2), -23002 => array('Mark color index too large for marker "%s"',1), -23003 => array('A filename must be specified if you set the mark type to MARK_IMG.',0), - -/* -** jpgraph_utils -*/ - -24001 => array('FuncGenerator : No function specified. ',0), -24002 => array('FuncGenerator : Syntax error in function specification ',0), - -/* -** jpgraph -*/ - -25001 => array('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)',0), -25002 => array('Your PHP installation does not seem to have the required GD library. Please see the PHP documentation on how to install and enable the GD library.',0), -25003 => array('General PHP error : At %s:%d : %s',3), -25004 => array('General PHP error : %s ',1), -25005 => array('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.',0), -25006 => array('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).',0), -25007 => array('You are trying to use the locale (%s) which your PHP installation does not support. Hint: Use \'\' to indicate the default locale for this geographic region.',1), -25008 => array('Image width/height argument in Graph::Graph() must be numeric',0), -25009 => array('You must specify what scale to use with a call to Graph::SetScale()',0), - -25010 => array('Graph::Add() You tried to add a null plot to the graph.',0), -25011 => array('Graph::AddY2() You tried to add a null plot to the graph.',0), -25012 => array('Graph::AddYN() You tried to add a null plot to the graph.',0), -25013 => array('You can only add standard plots to multiple Y-axis',0), -25014 => array('Graph::AddText() You tried to add a null text to the graph.',0), -25015 => array('Graph::AddLine() You tried to add a null line to the graph.',0), -25016 => array('Graph::AddBand() You tried to add a null band to the graph.',0), -25017 => 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), -25018 => array('Incorrect file name for Graph::SetBackgroundImage() : "%s" Must have a valid image extension (jpg,gif,png) when using auto detection of image type',1), -25019 => array('Unknown file extension (%s) in Graph::SetBackgroundImage() for filename: "%s"',2), - -25020 => array('Graph::SetScale(): Specified Max value must be larger than the specified Min value.',0), -25021 => array('Unknown scale specification for Y-scale. (%s)',1), -25022 => array('Unknown scale specification for X-scale. (%s)',1), -25023 => array('Unsupported Y2 axis type: "%s" Must be one of (lin,log,int)',1), -25024 => array('Unsupported Y axis type: "%s" Must be one of (lin,log,int)',1), -25025 => array('Unsupported Tick density: %d',1), -25026 => array('Can\'t draw unspecified Y-scale. You have either: 1. Specified an Y axis for auto scaling but have not supplied any plots. 2. Specified a scale manually but have forgot to specify the tick steps',0), -25027 => array('Can\'t open cached CSIM "%s" for reading.',1), -25028 => array('Apache/PHP does not have permission to write to the CSIM cache directory (%s). Check permissions.',1), -25029 => array('Can\'t write CSIM "%s" for writing. Check free space and permissions.',1), - -25030 => array('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().',0), -25031 => array('You must specify what scale to use with a call to Graph::SetScale().',0), -25032 => array('No plots for Y-axis nbr:%d',1), -25033 => array('',0), -25034 => array('Can\'t draw unspecified X-scale. No plots specified.',0), -25035 => array('You have enabled clipping. Clipping is only supported for graphs at 0 or 90 degrees rotation. Please adjust you current angle (=%d degrees) or disable clipping.',1), -25036 => array('Unknown AxisStyle() : %s',1), -25037 => array('The image format of your background image (%s) is not supported in your system configuration. ',1), -25038 => array('Background image seems to be of different type (has different file extension) than specified imagetype. Specified: %s File: %s',2), -25039 => array('Can\'t read background image: "%s"',1), - -25040 => array('It is not possible to specify both a background image and a background country flag.',0), -25041 => array('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.',0), -25042 => array('Unknown background image layout',0), -25043 => array('Unknown title background style.',0), -25044 => array('Cannot use auto scaling since it is impossible to determine a valid min/max value of the Y-axis (only null values).',0), -25045 => array('Font families FF_HANDWRT and FF_BOOK are no longer available due to copyright problem with these fonts. Fonts can no longer be distributed with JpGraph. Please download fonts from http://corefonts.sourceforge.net/',0), -25046 => array('Specified TTF font family (id=%d) 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/',1), -25047 => array('Style %s is not available for font family %s',2), -25048 => array('Unknown font style specification [%s].',1), -25049 => array('Font file "%s" is not readable or does not exist.',1), - -25050 => array('First argument to Text::Text() must be a string.',0), -25051 => array('Invalid direction specified for text.',0), -25052 => array('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text',0), -25053 => array('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text',0), -25054 => array('Internal error: Unknown grid axis %s',1), -25055 => array('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead',0), -25056 => array('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.',0), -25057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0), -25058 => array('Text label interval must be specified >= 1.',0), -25059 => array('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.',0), - -25060 => array('Unknown alignment specified for X-axis title. (%s)',1), -25061 => array('Unknown alignment specified for Y-axis title. (%s)',1), -25062 => array('Labels at an angle are not supported on Y-axis',0), -25063 => array('Ticks::SetPrecision() is deprecated. Use Ticks::SetLabelFormat() (or Ticks::SetFormatCallback()) instead',0), -25064 => array('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',0), -25065 => array('Tick positions must be specified as an array()',0), -25066 => array('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.',0), -25067 => array('Your manually specified scale and ticks is not correct. The scale seems to be too small to hold any of the specified tick marks.',0), -25068 => array('A plot has an illegal scale. This could for example be that you are trying to use text auto scaling 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\')',0), -25069 => array('Grace must be larger then 0',0), - -25070 => array('Your data contains non-numeric values.',0), -25071 => array('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.',0), -25072 => array('You have specified a max value with SetAutoMax() which is smaller than the minimum value used for the scale. This is not possible.',0), -25073 => array('Internal error. Integer scale algorithm comparison out of bound (r=%f)',1), -25074 => array('Internal error. The scale range is negative (%f) [for %s scale] 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 auto scaling to fail.',2), -25075 => array('Can\'t automatically determine ticks since min==max.',0), -25077 => array('Adjustment factor for color must be > 0',0), -25078 => array('Unknown color: %s',1), -25079 => array('Unknown color specification: %s, size=%d',2), - -25080 => array('Alpha parameter for color must be between 0.0 and 1.0',0), -25081 => array('Selected graphic format is either not supported or unknown [%s]',1), -25082 => array('Illegal sizes specified for width or height when creating an image, (width=%d, height=%d)',2), -25083 => array('Illegal image size when copying image. Size for copied to image is 1 pixel or less.',0), -25084 => array('Failed to create temporary GD canvas. Possible Out of memory problem.',0), -25085 => array('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.',0), -25086 => array('You only seem to have GD 1.x installed. To enable Alphablending requires GD 2.x or higher. Please install GD or make sure the constant USE_GD2 is specified correctly to reflect your installation. By default it tries to auto detect what version of GD you have installed. On some very rare occasions it may falsely detect GD2 where only GD1 is installed. You must then set USE_GD2 to false.',0), -25087 => array('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.',0), -25088 => array('You have a misconfigured GD font support. The call to imagefontwidth() fails.',0), -25089 => array('You have a misconfigured GD font support. The call to imagefontheight() fails.',0), - -25090 => array('Unknown direction specified in call to StrokeBoxedText() [%s]',1), -25091 => array('Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.',0), -25092 => array('There is either a configuration problem with TrueType or a problem reading font file "%s" 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 upgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.',1), -25093 => array('Can not read font file "%s" 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.',1), -25094 => array('Direction for text most be given as an angle between 0 and 90.',0), -25095 => array('Unknown font font family specification. ',0), -25096 => array('Can\'t allocate any more colors in palette image. Image has already allocated maximum of %d colors and the palette is now full. Change to a truecolor image instead',0), -25097 => array('Color specified as empty string in PushColor().',0), -25098 => array('Negative Color stack index. Unmatched call to PopColor()',0), -25099 => array('Parameters for brightness and Contrast out of range [-1,1]',0), - -25100 => 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), -25101 => array('Illegal numeric argument to SetLineStyle(): (%d)',1), -25102 => array('Illegal string argument to SetLineStyle(): %s',1), -25103 => array('Illegal argument to SetLineStyle %s',1), -25104 => array('Unknown line style: %s',1), -25105 => array('NULL data specified for a filled polygon. Check that your data is not NULL.',0), -25106 => array('Image::FillToBorder : Can not allocate more colors',0), -25107 => array('Can\'t write to file "%s". Check that the process running PHP has enough permission.',1), -25108 => array('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.',0), -25109 => array('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.',0), - -25110 => array('Your PHP installation does not support the chosen graphic format: %s',1), -25111 => array('Can\'t delete cached image %s. Permission problem?',1), -25112 => array('Cached imagefile (%s) has file date in the future.',1), -25113 => array('Can\'t delete cached image "%s". Permission problem?',1), -25114 => 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), -25115 => array('Can\'t set permission for cached image "%s". Permission problem?',1), -25116 => array('Cant open file from cache "%s"',1), -25117 => array('Can\'t open cached image "%s" for reading.',1), -25118 => array('Can\'t create directory "%s". Make sure PHP has write permission to this directory.',1), -25119 => array('Can\'t set permissions for "%s". Permission problems?',1), - -25120 => array('Position for legend must be given as percentage in range 0-1',0), -25121 => array('Empty input data array specified for plot. Must have at least one data point.',0), -25122 => array('Stroke() must be implemented by concrete subclass to class Plot',0), -25123 => array('You can\'t use a text X-scale with specified X-coords. Use a "int" or "lin" scale instead.',0), -25124 => array('The input data array must have consecutive values from position 0 and forward. The given y-array starts with empty values (NULL)',0), -25125 => array('Illegal direction for static line',0), -25126 => array('Can\'t create truecolor image. Check that the GD2 library is properly setup with PHP.',0), - -/* -**--------------------------------------------------------------------------------------------- -** Pro-version strings -**--------------------------------------------------------------------------------------------- -*/ - -/* -** jpgraph_table -*/ - -24001 => array('GTextTable: Invalid argument to Set(). Array argument must be 2 dimensional',0), -24002 => array('GTextTable: Invalid argument to Set()',0), -24003 => array('GTextTable: Wrong number of arguments to GTextTable::SetColor()',0), -24004 => array('GTextTable: Specified cell range to be merged is not valid.',0), -24005 => array('GTextTable: Cannot merge already merged cells in the range: (%d,%d) to (%d,%d)',4), -24006 => array('GTextTable: Column argument = %d is outside specified table size.',1), -24007 => array('GTextTable: Row argument = %d is outside specified table size.',1), -24008 => array('GTextTable: Column and row size arrays must match the dimensions of the table',0), -24009 => array('GTextTable: Number of table columns or rows are 0. Make sure Init() or Set() is called.',0), -24010 => array('GTextTable: No alignment specified in call to SetAlign()',0), -24011 => array('GTextTable: Unknown alignment specified in SetAlign(). Horizontal=%s, Vertical=%s',2), -24012 => array('GTextTable: Internal error. Invalid alignment specified =%s',1), -24013 => array('GTextTable: Argument to FormatNumber() must be a string.',0), -24014 => array('GTextTable: Table is not initilaized with either a call to Set() or Init()',0), -24015 => array('GTextTable: Cell image constrain type must be TIMG_WIDTH or TIMG_HEIGHT',0), - -/* -** jpgraph_windrose -*/ - -22001 => array('Total percentage for all windrose legs in a windrose plot can not exceed 100% !\n(Current max is: %d)',1), -22002 => array('Graph is too small to have a scale. Please make the graph larger.',0), -22004 => array('Label specification for windrose directions must have 16 values (one for each compass direction).',0), -22005 => array('Line style for radial lines must be on of ("solid","dotted","dashed","longdashed") ',0), -22006 => array('Illegal windrose type specified.',0), -22007 => array('To few values for the range legend.',0), -22008 => array('Internal error: Trying to plot free Windrose even though type is not a free windrose',0), -22009 => array('You have specified the same direction twice, once with an angle and once with a compass direction (%f degrees)',0), -22010 => array('Direction must either be a numeric value or one of the 16 compass directions',0), -22011 => array('Windrose index must be numeric or direction label. You have specified index=%d',1), -22012 => array('Windrose radial axis specification contains a direction which is not enabled.',0), -22013 => array('You have specified the look&feel for the same compass direction twice, once with text and once with index (Index=%d)',1), -22014 => array('Index for compass direction must be between 0 and 15.',0), -22015 => array('You have specified an undefined Windrose plot type.',0), -22016 => array('Windrose leg index must be numeric or direction label.',0), -22017 => array('Windrose data contains a direction which is not enabled. Please adjust what labels are displayed.',0), -22018 => array('You have specified data for the same compass direction twice, once with text and once with index (Index=%d)',1), -22019 => array('Index for direction must be between 0 and 15. You can\'t specify angles for a Regular Windplot, only index and compass directions.',0), -22020 => array('Windrose plot is too large to fit the specified Graph size. Please use WindrosePlot::SetSize() to make the plot smaller or increase the size of the Graph in the initial WindroseGraph() call.',0), - -/* -** jpgraph_odometer -*/ - -13001 => array('Unknown needle style (%d).',1), -13002 => array('Value for odometer (%f) is outside specified scale [%f,%f]',3), - -/* -** jpgraph_barcode -*/ - -1001 => array('Unknown encoder specification: %s',1), -1002 => array('Data validation failed. Can\'t encode [%s] using encoding "%s"',2), -1003 => array('Internal encoding error. Trying to encode %s is not possible in Code 128',1), -1004 => array('Internal barcode error. Unknown UPC-E encoding type: %s',1), -1005 => array('Internal error. Can\'t encode character tuple (%s, %s) in Code-128 charset C',2), -1006 => array('Internal encoding error for CODE 128. Trying to encode control character in CHARSET != A',0), -1007 => array('Internal encoding error for CODE 128. Trying to encode DEL in CHARSET != B',0), -1008 => array('Internal encoding error for CODE 128. Trying to encode small letters in CHARSET != B',0), -1009 => array('Encoding using CODE 93 is not yet supported.',0), -1010 => array('Encoding using POSTNET is not yet supported.',0), -1011 => array('Non supported barcode backend for type %s',1), - -/* -** PDF417 -*/ - -26001 => array('PDF417: Number of Columns must be >= 1 and <= 30',0), -26002 => array('PDF417: Error level must be between 0 and 8',0), -26003 => array('PDF417: Invalid format for input data to encode with PDF417',0), -26004 => array('PDF417: Can\'t encode given data with error level %d and %d columns since it results in too many symbols or more than 90 rows.',2), -26005 => array('PDF417: Can\'t open file "%s" for writing',1), -26006 => array('PDF417: Internal error. Data files for PDF417 cluster %d is corrupted.',1), -26007 => array('PDF417: Internal error. GetPattern: Illegal Code Value = %d (row=%d)',2), -26008 => array('PDF417: Internal error. Mode not found in mode list!! mode=%d',1), -26009 => array('PDF417: Encode error: Illegal character. Can\'t encode character with ASCII code=%d',1), -26010 => array('PDF417: Internal error: No input data in decode.',0), -26011 => array('PDF417: Encoding error. Can\'t use numeric encoding on non-numeric data.',0), -26012 => array('PDF417: Internal error. No input data to decode for Binary compressor.',0), -26013 => array('PDF417: Internal error. Checksum error. Coefficient tables corrupted.',0), -26014 => array('PDF417: Internal error. No data to calculate codewords on.',0), -26015 => array('PDF417: Internal error. State transition table entry 0 is NULL. Entry 1 = (%s)',1), -26016 => array('PDF417: Internal error: Unrecognized state transition mode in decode.',0), - - -); - -?> +,) +$_jpg_messages = array( + +/* +** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text +*/ +10 => array('
JpGraph Error: +HTTP headers have already been sent.
Caused by output from file %s at line %d.
Explanation:
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).

Most likely you have some text in your script before the call to Graph::Stroke(). 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.

For example it is a common mistake to leave a blank line before the opening "<?php".

',2), + +/* +** Setup errors +*/ +11 => array('No path specified for CACHE_DIR. Please specify CACHE_DIR manually in jpg-config.inc',0), +12 => array('No path specified for TTF_DIR and path can not be determined automatically. Please specify TTF_DIR manually (in jpg-config.inc).',0), +13 => array('The installed PHP version (%s) is not compatible with this release of the library. The library requires at least PHP version %s',2), + + +/* +** jpgraph_bar +*/ + +2001 => array('Number of colors is not the same as the number of patterns in BarPlot::SetPattern()',0), +2002 => array('Unknown pattern specified in call to BarPlot::SetPattern()',0), +2003 => array('Number of X and Y points are not equal. Number of X-points: %d Number of Y-points: %d',2), +2004 => array('All values for a barplot must be numeric. You have specified value nr [%d] == %s',2), +2005 => array('You have specified an empty array for shadow colors in the bar plot.',0), +2006 => array('Unknown position for values on bars : %s',1), +2007 => array('Cannot create GroupBarPlot from empty plot array.',0), +2008 => array('Group bar plot element nbr %d is undefined or empty.',0), +2009 => array('One of the objects submitted to GroupBar is not a BarPlot. Make sure that you create the GroupBar plot from an array of BarPlot or AccBarPlot objects. (Class = %s)',1), +2010 => array('Cannot create AccBarPlot from empty plot array.',0), +2011 => array('Acc bar plot element nbr %d is undefined or empty.',1), +2012 => array('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=%s)',1), +2013 => array('You have specified an empty array for shadow colors in the bar plot.',0), +2014 => array('Number of datapoints for each data set in accbarplot must be the same',0), +2015 => array('Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-coordinates',0), + + +/* +** jpgraph_date +*/ + +3001 => array('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both',0), + +/* +** jpgraph_error +*/ + +4002 => array('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3',0), + +/* +** jpgraph_flags +*/ + +5001 => array('Unknown flag size (%d).',1), +5002 => array('Flag index %s does not exist.',1), +5003 => array('Invalid ordinal number (%d) specified for flag index.',1), +5004 => array('The (partial) country name %s does not have a corresponding flag image. The flag may still exist but under another name, e.g. instead of "usa" try "united states".',1), + + +/* +** jpgraph_gantt +*/ + +6001 => array('Internal error. Height for ActivityTitles is < 0',0), +6002 => 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), +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), +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), +6005 => array('SetScale() is not meaningful with Gantt charts.',0), +6006 => array('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]',0), +6007 => array('Sanity check for automatic Gantt chart size failed. Either the width (=%d) or height (=%d) is larger than MAX_GANTTIMG_SIZE. This could potentially be caused by a wrong date in one of the activities.',2), +6008 => array('You have specified a constrain from row=%d to row=%d which does not have any activity',2), +6009 => array('Unknown constrain type specified from row=%d to row=%d',2), +6010 => array('Illegal icon index for Gantt builtin icon [%d]',1), +6011 => array('Argument to IconImage must be string or integer',0), +6012 => array('Unknown type in Gantt object title specification',0), +6015 => array('Illegal vertical position %d',1), +6016 => array('Date string (%s) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30',1), +6017 => array('Unknown date format in GanttScale (%s).',1), +6018 => array('Interval for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an interval of %d minutes.',1), +6019 => array('The available width (%d) for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.',1), +6020 => array('Interval for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an interval of %d',1), +6021 => array('Unknown formatting style for week.',0), +6022 => array('Gantt scale has not been specified.',0), +6023 => array('If you display both hour and minutes the hour interval must be 1 (Otherwise it doesn\'t make sense to display minutes).',0), +6024 => array('CSIM Target must be specified as a string. Start of target is: %d',1), +6025 => array('CSIM Alt text must be specified as a string. Start of alt text is: %d',1), +6027 => array('Progress value must in range [0, 1]',0), +6028 => array('Specified height (%d) for gantt bar is out of range.',1), +6029 => array('Offset for vertical line must be in range [0,1]',0), +6030 => array('Unknown arrow direction for link.',0), +6031 => array('Unknown arrow type for link.',0), +6032 => array('Internal error: Unknown path type (=%d) specified for link.',1), +6033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0), + +/* +** jpgraph_gradient +*/ + +7001 => array('Unknown gradient style (=%d).',1), + +/* +** jpgraph_iconplot +*/ + +8001 => array('Mix value for icon must be between 0 and 100.',0), +8002 => array('Anchor position for icons must be one of "top", "bottom", "left", "right" or "center"',0), +8003 => array('It is not possible to specify both an image file and a country flag for the same icon.',0), +8004 => array('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.',0), + +/* +** jpgraph_imgtrans +*/ + +9001 => array('Value for image transformation out of bounds. Vanishing point on horizon must be specified as a value between 0 and 1.',0), + +/* +** jpgraph_lineplot +*/ + +10001 => array('LinePlot::SetFilled() is deprecated. Use SetFillColor()',0), +10002 => array('Plot too complicated for fast line Stroke. Use standard Stroke()',0), +10003 => array('Each plot in an accumulated lineplot must have the same number of data points.',0), + +/* +** jpgraph_log +*/ + +11001 => array('Your data contains non-numeric values.',0), +11002 => array('Negative data values can not be used in a log scale.',0), +11003 => array('Your data contains non-numeric values.',0), +11004 => array('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.',0), +11005 => array('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.',0), + +/* +** jpgraph_mgraph +*/ + +12001 => 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), +12002 => array('Incorrect file name for MGraph::SetBackgroundImage() : %s Must have a valid image extension (jpg,gif,png) when using auto detection of image type',1), +12003 => array('Unknown file extension (%s) in MGraph::SetBackgroundImage() for filename: %s',2), +12004 => array('The image format of your background image (%s) is not supported in your system configuration. ',1), +12005 => array('Can\'t read background image: %s',1), +12006 => array('Illegal sizes specified for width or height when creating an image, (width=%d, height=%d)',2), +12007 => array('Argument to MGraph::Add() is not a valid GD image handle.',0), +12008 => array('Your PHP (and GD-lib) installation does not appear to support any known graphic formats.',0), +12009 => array('Your PHP installation does not support the chosen graphic format: %s',1), +12010 => array('Can\'t create or stream image to file %s Check that PHP has enough permission to write a file to the current directory.',1), +12011 => array('Can\'t create truecolor image. Check that you really have GD2 library installed.',0), +12012 => array('Can\'t create image. Check that you really have GD2 library installed.',0), + +/* +** jpgraph_pie3d +*/ + +14001 => array('Pie3D::ShowBorder() . Deprecated function. Use Pie3D::SetEdge() to control the edges around slices.',0), +14002 => array('PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.',0), +14003 => array('Internal assertion failed. Pie3D::Pie3DSlice',0), +14004 => array('Slice start angle must be between 0 and 360 degrees.',0), +14005 => array('Pie3D Internal error: Trying to wrap twice when looking for start index',0,), +14006 => array('Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.',0), +14007 => array('Width for 3D Pie is 0. Specify a size > 0',0), + +/* +** jpgraph_pie +*/ + +15001 => array('PiePLot::SetTheme() Unknown theme: %s',1), +15002 => array('Argument to PiePlot::ExplodeSlice() must be an integer',0), +15003 => array('Argument to PiePlot::Explode() must be an array with integer distances.',0), +15004 => array('Slice start angle must be between 0 and 360 degrees.',0), +15005 => array('PiePlot::SetFont() is deprecated. Use PiePlot->value->SetFont() instead.',0), +15006 => array('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]',0), +15007 => array('PiePlot::SetFontColor() is deprecated. Use PiePlot->value->SetColor() instead.',0), +15008 => array('PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not %d).',1), +15009 => array('Illegal pie plot. Sum of all data is zero for Pie Plot',0), +15010 => array('Sum of all data is 0 for Pie.',0), +15011 => array('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.',0), +15012 => array('PiePlot::SetTheme() is no longer supported. Use PieGraph::SetTheme()',0), + +/* +** jpgraph_plotband +*/ + +16001 => array('Density for pattern must be between 1 and 100. (You tried %f)',1), +16002 => array('No positions specified for pattern.',0), +16003 => array('Unknown pattern specification (%d)',0), +16004 => array('Min value for plotband is larger than specified max value. Please correct.',0), + + +/* +** jpgraph_polar +*/ + +17001 => array('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).',0), +17002 => array('Unknown alignment specified for X-axis title. (%s)',1), +//17003 => array('Set90AndMargin() is not supported for polar graphs.',0), +17004 => array('Unknown scale type for polar graph. Must be "lin" or "log"',0), + +/* +** jpgraph_radar +*/ + +18001 => array('Client side image maps not supported for RadarPlots.',0), +18002 => array('RadarGraph::SupressTickMarks() is deprecated. Use HideTickMarks() instead.',0), +18003 => array('Illegal scale for radarplot (%s). Must be \'lin\' or \'log\'',1), +18004 => array('Radar Plot size must be between 0.1 and 1. (Your value=%f)',1), +18005 => array('RadarPlot Unsupported Tick density: %d',1), +18006 => array('Minimum data %f (Radar plots should only be used when all data points > 0)',1), +18007 => array('Number of titles does not match number of points in plot.',0), +18008 => array('Each radar plot must have the same number of data points.',0), + +/* +** jpgraph_regstat +*/ + +19001 => array('Spline: Number of X and Y coordinates must be the same',0), +19002 => array('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.',0), +19003 => array('Bezier: Number of X and Y coordinates must be the same',0), + +/* +** jpgraph_scatter +*/ + +20001 => array('Fieldplots must have equal number of X and Y points.',0), +20002 => array('Fieldplots must have an angle specified for each X and Y points.',0), +20003 => array('Scatterplot must have equal number of X and Y points.',0), + +/* +** jpgraph_stock +*/ + +21001 => array('Data values for Stock charts must contain an even multiple of %d data points.',1), + +/* +** jpgraph_plotmark +*/ + +23001 => array('This marker "%s" does not exist in color with index: %d',2), +23002 => array('Mark color index too large for marker "%s"',1), +23003 => array('A filename must be specified if you set the mark type to MARK_IMG.',0), + +/* +** jpgraph_utils +*/ + +24001 => array('FuncGenerator : No function specified. ',0), +24002 => array('FuncGenerator : Syntax error in function specification ',0), +24003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0), +24004 => array('ReadCSV2: Column count mismatch in %s line %d',2), +/* +** jpgraph +*/ + +25001 => array('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)',0), +25002 => array('Your PHP installation does not seem to have the required GD library. Please see the PHP documentation on how to install and enable the GD library.',0), +25003 => array('General PHP error : At %s:%d : %s',3), +25004 => array('General PHP error : %s ',1), +25005 => array('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.',0), +25006 => array('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).',0), +25007 => array('You are trying to use the locale (%s) which your PHP installation does not support. Hint: Use \'\' to indicate the default locale for this geographic region.',1), +25008 => array('Image width/height argument in Graph::Graph() must be numeric',0), +25009 => array('You must specify what scale to use with a call to Graph::SetScale()',0), + +25010 => array('Graph::Add() You tried to add a null plot to the graph.',0), +25011 => array('Graph::AddY2() You tried to add a null plot to the graph.',0), +25012 => array('Graph::AddYN() You tried to add a null plot to the graph.',0), +25013 => array('You can only add standard plots to multiple Y-axis',0), +25014 => array('Graph::AddText() You tried to add a null text to the graph.',0), +25015 => array('Graph::AddLine() You tried to add a null line to the graph.',0), +25016 => array('Graph::AddBand() You tried to add a null band to the graph.',0), +25017 => 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), +25018 => array('Incorrect file name for Graph::SetBackgroundImage() : "%s" Must have a valid image extension (jpg,gif,png) when using auto detection of image type',1), +25019 => array('Unknown file extension (%s) in Graph::SetBackgroundImage() for filename: "%s"',2), + +25020 => array('Graph::SetScale(): Specified Max value must be larger than the specified Min value.',0), +25021 => array('Unknown scale specification for Y-scale. (%s)',1), +25022 => array('Unknown scale specification for X-scale. (%s)',1), +25023 => array('Unsupported Y2 axis type: "%s" Must be one of (lin,log,int)',1), +25024 => array('Unsupported Y axis type: "%s" Must be one of (lin,log,int)',1), +25025 => array('Unsupported Tick density: %d',1), +25026 => array('Can\'t draw unspecified Y-scale. You have either: 1. Specified an Y axis for auto scaling but have not supplied any plots. 2. Specified a scale manually but have forgot to specify the tick steps',0), +25027 => array('Can\'t open cached CSIM "%s" for reading.',1), +25028 => array('Apache/PHP does not have permission to write to the CSIM cache directory (%s). Check permissions.',1), +25029 => array('Can\'t write CSIM "%s" for writing. Check free space and permissions.',1), + +25030 => array('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().',0), +25031 => array('You must specify what scale to use with a call to Graph::SetScale().',0), +25032 => array('No plots for Y-axis nbr:%d',1), +25033 => array('',0), +25034 => array('Can\'t draw unspecified X-scale. No plots specified.',0), +25035 => array('You have enabled clipping. Clipping is only supported for graphs at 0 or 90 degrees rotation. Please adjust you current angle (=%d degrees) or disable clipping.',1), +25036 => array('Unknown AxisStyle() : %s',1), +25037 => array('The image format of your background image (%s) is not supported in your system configuration. ',1), +25038 => array('Background image seems to be of different type (has different file extension) than specified imagetype. Specified: %s File: %s',2), +25039 => array('Can\'t read background image: "%s"',1), + +25040 => array('It is not possible to specify both a background image and a background country flag.',0), +25041 => array('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.',0), +25042 => array('Unknown background image layout',0), +25043 => array('Unknown title background style.',0), +25044 => array('Cannot use auto scaling since it is impossible to determine a valid min/max value of the Y-axis (only null values).',0), +25045 => array('Font families FF_HANDWRT and FF_BOOK are no longer available due to copyright problem with these fonts. Fonts can no longer be distributed with JpGraph. Please download fonts from http://corefonts.sourceforge.net/',0), +25046 => array('Specified TTF font family (id=%d) 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/',1), +25047 => array('Style %s is not available for font family %s',2), +25048 => array('Unknown font style specification [%s].',1), +25049 => array('Font file "%s" is not readable or does not exist.',1), + +25050 => array('First argument to Text::Text() must be a string.',0), +25051 => array('Invalid direction specified for text.',0), +25052 => array('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text',0), +25053 => array('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text',0), +25054 => array('Internal error: Unknown grid axis %s',1), +25055 => array('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead',0), +25056 => array('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.',0), +25057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0), +25058 => array('Text label interval must be specified >= 1.',0), +25059 => array('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.',0), + +25060 => array('Unknown alignment specified for X-axis title. (%s)',1), +25061 => array('Unknown alignment specified for Y-axis title. (%s)',1), +25062 => array('Labels at an angle are not supported on Y-axis',0), +25063 => array('Ticks::SetPrecision() is deprecated. Use Ticks::SetLabelFormat() (or Ticks::SetFormatCallback()) instead',0), +25064 => array('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',0), +25065 => array('Tick positions must be specified as an array()',0), +25066 => array('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.',0), +25067 => array('Your manually specified scale and ticks is not correct. The scale seems to be too small to hold any of the specified tick marks.',0), +25068 => array('A plot has an illegal scale. This could for example be that you are trying to use text auto scaling 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\')',0), +25069 => array('Grace must be larger then 0',0), +25070 => array('Either X or Y data arrays contains non-numeric values. Check that the data is really specified as numeric data and not as strings. It is an error to specify data for example as \'-2345.2\' (using quotes).',0), +25071 => array('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.',0), +25072 => array('You have specified a max value with SetAutoMax() which is smaller than the minimum value used for the scale. This is not possible.',0), +25073 => array('Internal error. Integer scale algorithm comparison out of bound (r=%f)',1), +25074 => array('Internal error. The scale range is negative (%f) [for %s scale] 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 auto scaling to fail.',2), +25075 => array('Can\'t automatically determine ticks since min==max.',0), +25077 => array('Adjustment factor for color must be > 0',0), +25078 => array('Unknown color: %s',1), +25079 => array('Unknown color specification: %s, size=%d',2), + +25080 => array('Alpha parameter for color must be between 0.0 and 1.0',0), +25081 => array('Selected graphic format is either not supported or unknown [%s]',1), +25082 => array('Illegal sizes specified for width or height when creating an image, (width=%d, height=%d)',2), +25083 => array('Illegal image size when copying image. Size for copied to image is 1 pixel or less.',0), +25084 => array('Failed to create temporary GD canvas. Possible Out of memory problem.',0), +25085 => array('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.',0), +25086 => array('You only seem to have GD 1.x installed. To enable Alphablending requires GD 2.x or higher. Please install GD or make sure the constant USE_GD2 is specified correctly to reflect your installation. By default it tries to auto detect what version of GD you have installed. On some very rare occasions it may falsely detect GD2 where only GD1 is installed. You must then set USE_GD2 to false.',0), +25087 => array('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.',0), +25088 => array('You have a misconfigured GD font support. The call to imagefontwidth() fails.',0), +25089 => array('You have a misconfigured GD font support. The call to imagefontheight() fails.',0), + +25090 => array('Unknown direction specified in call to StrokeBoxedText() [%s]',1), +25091 => array('Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.',0), +25092 => array('There is either a configuration problem with TrueType or a problem reading font file "%s" 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 upgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.',1), +25093 => array('Can not read font file "%s" 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.',1), +25094 => array('Direction for text most be given as an angle between 0 and 90.',0), +25095 => array('Unknown font font family specification. ',0), +25096 => array('Can\'t allocate any more colors in palette image. Image has already allocated maximum of %d colors and the palette is now full. Change to a truecolor image instead',0), +25097 => array('Color specified as empty string in PushColor().',0), +25098 => array('Negative Color stack index. Unmatched call to PopColor()',0), +25099 => array('Parameters for brightness and Contrast out of range [-1,1]',0), + +25100 => 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), +25101 => array('Illegal numeric argument to SetLineStyle(): (%d)',1), +25102 => array('Illegal string argument to SetLineStyle(): %s',1), +25103 => array('Illegal argument to SetLineStyle %s',1), +25104 => array('Unknown line style: %s',1), +25105 => array('NULL data specified for a filled polygon. Check that your data is not NULL.',0), +25106 => array('Image::FillToBorder : Can not allocate more colors',0), +25107 => array('Can\'t write to file "%s". Check that the process running PHP has enough permission.',1), +25108 => array('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.',0), +25109 => array('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.',0), + +25110 => array('Your PHP installation does not support the chosen graphic format: %s',1), +25111 => array('Can\'t delete cached image %s. Permission problem?',1), +25112 => array('Cached imagefile (%s) has file date in the future.',1), +25113 => array('Can\'t delete cached image "%s". Permission problem?',1), +25114 => 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), +25115 => array('Can\'t set permission for cached image "%s". Permission problem?',1), +25116 => array('Cant open file from cache "%s"',1), +25117 => array('Can\'t open cached image "%s" for reading.',1), +25118 => array('Can\'t create directory "%s". Make sure PHP has write permission to this directory.',1), +25119 => array('Can\'t set permissions for "%s". Permission problems?',1), + +25120 => array('Position for legend must be given as percentage in range 0-1',0), +25121 => array('Empty input data array specified for plot. Must have at least one data point.',0), +25122 => array('Stroke() must be implemented by concrete subclass to class Plot',0), +25123 => array('You can\'t use a text X-scale with specified X-coords. Use a "int" or "lin" scale instead.',0), +25124 => array('The input data array must have consecutive values from position 0 and forward. The given y-array starts with empty values (NULL)',0), +25125 => array('Illegal direction for static line',0), +25126 => array('Can\'t create truecolor image. Check that the GD2 library is properly setup with PHP.',0), +25127 => 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), +25128 => 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), +25129 => array('Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.',0), +25130 => array('Too small plot area. (%d x %d). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.',2), + +25131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0), +25132 => array('Undefined property %s.',1), +25133 => array('Use Graph::SetTheme() after Graph::SetScale().',0), + +/* +** jpgraph_led +*/ + +25500 => array('Multibyte strings must be enabled in the PHP installation in order to run the LED module so that the function mb_strlen() is available. See PHP documentation for more information.',0), + +/* +**--------------------------------------------------------------------------------------------- +** Pro-version strings +**--------------------------------------------------------------------------------------------- +*/ + +/* +** jpgraph_table +*/ + +27001 => array('GTextTable: Invalid argument to Set(). Array argument must be 2 dimensional',0), +27002 => array('GTextTable: Invalid argument to Set()',0), +27003 => array('GTextTable: Wrong number of arguments to GTextTable::SetColor()',0), +27004 => array('GTextTable: Specified cell range to be merged is not valid.',0), +27005 => array('GTextTable: Cannot merge already merged cells in the range: (%d,%d) to (%d,%d)',4), +27006 => array('GTextTable: Column argument = %d is outside specified table size.',1), +27007 => array('GTextTable: Row argument = %d is outside specified table size.',1), +27008 => array('GTextTable: Column and row size arrays must match the dimensions of the table',0), +27009 => array('GTextTable: Number of table columns or rows are 0. Make sure Init() or Set() is called.',0), +27010 => array('GTextTable: No alignment specified in call to SetAlign()',0), +27011 => array('GTextTable: Unknown alignment specified in SetAlign(). Horizontal=%s, Vertical=%s',2), +27012 => array('GTextTable: Internal error. Invalid alignment specified =%s',1), +27013 => array('GTextTable: Argument to FormatNumber() must be a string.',0), +27014 => array('GTextTable: Table is not initilaized with either a call to Set() or Init()',0), +27015 => array('GTextTable: Cell image constrain type must be TIMG_WIDTH or TIMG_HEIGHT',0), + +/* +** jpgraph_windrose +*/ + +22001 => array('Total percentage for all windrose legs in a windrose plot can not exceed 100%% !\n(Current max is: %d)',1), +22002 => array('Graph is too small to have a scale. Please make the graph larger.',0), +22004 => array('Label specification for windrose directions must have 16 values (one for each compass direction).',0), +22005 => array('Line style for radial lines must be on of ("solid","dotted","dashed","longdashed") ',0), +22006 => array('Illegal windrose type specified.',0), +22007 => array('To few values for the range legend.',0), +22008 => array('Internal error: Trying to plot free Windrose even though type is not a free windrose',0), +22009 => array('You have specified the same direction twice, once with an angle and once with a compass direction (%f degrees)',0), +22010 => array('Direction must either be a numeric value or one of the 16 compass directions',0), +22011 => array('Windrose index must be numeric or direction label. You have specified index=%d',1), +22012 => array('Windrose radial axis specification contains a direction which is not enabled.',0), +22013 => array('You have specified the look&feel for the same compass direction twice, once with text and once with index (Index=%d)',1), +22014 => array('Index for compass direction must be between 0 and 15.',0), +22015 => array('You have specified an undefined Windrose plot type.',0), +22016 => array('Windrose leg index must be numeric or direction label.',0), +22017 => array('Windrose data contains a direction which is not enabled. Please adjust what labels are displayed.',0), +22018 => array('You have specified data for the same compass direction twice, once with text and once with index (Index=%d)',1), +22019 => array('Index for direction must be between 0 and 15. You can\'t specify angles for a Regular Windplot, only index and compass directions.',0), +22020 => array('Windrose plot is too large to fit the specified Graph size. Please use WindrosePlot::SetSize() to make the plot smaller or increase the size of the Graph in the initial WindroseGraph() call.',0), +22021 => array('It is only possible to add Text, IconPlot or WindrosePlot to a Windrose Graph',0), +/* +** jpgraph_odometer +*/ + +13001 => array('Unknown needle style (%d).',1), +13002 => array('Value for odometer (%f) is outside specified scale [%f,%f]',3), + +/* +** jpgraph_barcode +*/ + +1001 => array('Unknown encoder specification: %s',1), +1002 => array('Data validation failed. Can\'t encode [%s] using encoding "%s"',2), +1003 => array('Internal encoding error. Trying to encode %s is not possible in Code 128',1), +1004 => array('Internal barcode error. Unknown UPC-E encoding type: %s',1), +1005 => array('Internal error. Can\'t encode character tuple (%s, %s) in Code-128 charset C',2), +1006 => array('Internal encoding error for CODE 128. Trying to encode control character in CHARSET != A',0), +1007 => array('Internal encoding error for CODE 128. Trying to encode DEL in CHARSET != B',0), +1008 => array('Internal encoding error for CODE 128. Trying to encode small letters in CHARSET != B',0), +1009 => array('Encoding using CODE 93 is not yet supported.',0), +1010 => array('Encoding using POSTNET is not yet supported.',0), +1011 => array('Non supported barcode backend for type %s',1), + +/* +** PDF417 +*/ +26000 => array('PDF417: The PDF417 module requires that the PHP installation must support the function bcmod(). This is normally enabled at compile time. See documentation for more information.',0), +26001 => array('PDF417: Number of Columns must be >= 1 and <= 30',0), +26002 => array('PDF417: Error level must be between 0 and 8',0), +26003 => array('PDF417: Invalid format for input data to encode with PDF417',0), +26004 => array('PDF417: Can\'t encode given data with error level %d and %d columns since it results in too many symbols or more than 90 rows.',2), +26005 => array('PDF417: Can\'t open file "%s" for writing',1), +26006 => array('PDF417: Internal error. Data files for PDF417 cluster %d is corrupted.',1), +26007 => array('PDF417: Internal error. GetPattern: Illegal Code Value = %d (row=%d)',2), +26008 => array('PDF417: Internal error. Mode not found in mode list!! mode=%d',1), +26009 => array('PDF417: Encode error: Illegal character. Can\'t encode character with ASCII code=%d',1), +26010 => array('PDF417: Internal error: No input data in decode.',0), +26011 => array('PDF417: Encoding error. Can\'t use numeric encoding on non-numeric data.',0), +26012 => array('PDF417: Internal error. No input data to decode for Binary compressor.',0), +26013 => array('PDF417: Internal error. Checksum error. Coefficient tables corrupted.',0), +26014 => array('PDF417: Internal error. No data to calculate codewords on.',0), +26015 => array('PDF417: Internal error. State transition table entry 0 is NULL. Entry 1 = (%s)',1), +26016 => array('PDF417: Internal error: Unrecognized state transition mode in decode.',0), + +/* +** jpgraph_contour +*/ + +28001 => array('Third argument to Contour must be an array of colors.',0), +28002 => array('Number of colors must equal the number of isobar lines specified',0), +28003 => array('ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)',1), +28004 => array('ContourPlot Internal Error: isobarHCrossing: Row index too large (%d)',1), +28005 => array('ContourPlot Internal Error: isobarVCrossing: Row index too large (%d)',1), +28006 => array('ContourPlot Internal Error: isobarVCrossing: Col index too large (%d)',1), +28007 => array('ContourPlot interpolation factor is too large (>5)',0), + +/* + * jpgraph_matrix and colormap +*/ +29201 => array('Min range value must be less or equal to max range value for colormaps',0), +29202 => array('The distance between min and max value is too small for numerical precision',0), +29203 => array('Number of color quantification level must be at least %d',1), +29204 => array('Number of colors (%d) is invalid for this colormap. It must be a number that can be written as: %d + k*%d',3), +29205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1), +29206 => array('Invalid object added to MatrixGraph',0), +29207 => array('Empty input data specified for MatrixPlot',0), +29208 => array('Unknown side specifiction for matrix labels "%s"',1), +29209 => array('CSIM Target matrix must be the same size as the data matrix (csim=%d x %d, data=%d x %d)',4), +29210 => array('CSIM Target for matrix labels does not match the number of labels (csim=%d, labels=%d)',2), + + +/* +* jpgraph_theme +*/ +30001 => array("Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs.",2), + +); + +?> diff --git a/web/public_php/admin/jpgraph/lang/prod.inc.php b/web/public_php/admin/jpgraph/lang/prod.inc.php new file mode 100644 index 000000000..c34c2b3bc --- /dev/null +++ b/web/public_php/admin/jpgraph/lang/prod.inc.php @@ -0,0 +1,386 @@ +,) +$_jpg_messages = array( + +/* +** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text +*/ +10 => array('
JpGraph Error: +HTTP headers have already been sent.
Caused by output from file %s at line %d.
Explanation:
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).

Most likely you have some text in your script before the call to Graph::Stroke(). 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.

For example it is a common mistake to leave a blank line before the opening "<?php".

',2), + + +11 => array(DEFAULT_ERROR_MESSAGE.'11',0), +12 => array(DEFAULT_ERROR_MESSAGE.'12',0), +13 => array(DEFAULT_ERROR_MESSAGE.'13',0), +2001 => array(DEFAULT_ERROR_MESSAGE.'2001',0), +2002 => array(DEFAULT_ERROR_MESSAGE.'2002',0), +2003 => array(DEFAULT_ERROR_MESSAGE.'2003',0), +2004 => array(DEFAULT_ERROR_MESSAGE.'2004',0), +2005 => array(DEFAULT_ERROR_MESSAGE.'2005',0), +2006 => array(DEFAULT_ERROR_MESSAGE.'2006',0), +2007 => array(DEFAULT_ERROR_MESSAGE.'2007',0), +2008 => array(DEFAULT_ERROR_MESSAGE.'2008',0), +2009 => array(DEFAULT_ERROR_MESSAGE.'2009',0), +2010 => array(DEFAULT_ERROR_MESSAGE.'2010',0), +2011 => array(DEFAULT_ERROR_MESSAGE.'2011',0), +2012 => array(DEFAULT_ERROR_MESSAGE.'2012',0), +2013 => array(DEFAULT_ERROR_MESSAGE.'2013',0), +2014 => array(DEFAULT_ERROR_MESSAGE.'2014',0), +3001 => array(DEFAULT_ERROR_MESSAGE.'3001',0), +4002 => array(DEFAULT_ERROR_MESSAGE.'4002',0), +5001 => array(DEFAULT_ERROR_MESSAGE.'5001',0), +5002 => array(DEFAULT_ERROR_MESSAGE.'5002',0), +5003 => array(DEFAULT_ERROR_MESSAGE.'5003',0), +5004 => array(DEFAULT_ERROR_MESSAGE.'5004',0), +6001 => array(DEFAULT_ERROR_MESSAGE.'6001',0), +6002 => array(DEFAULT_ERROR_MESSAGE.'6002',0), +6003 => array(DEFAULT_ERROR_MESSAGE.'6003',0), +6004 => array(DEFAULT_ERROR_MESSAGE.'6004',0), +6005 => array(DEFAULT_ERROR_MESSAGE.'6005',0), +6006 => array(DEFAULT_ERROR_MESSAGE.'6006',0), +6007 => array(DEFAULT_ERROR_MESSAGE.'6007',0), +6008 => array(DEFAULT_ERROR_MESSAGE.'6008',0), +6009 => array(DEFAULT_ERROR_MESSAGE.'6009',0), +6010 => array(DEFAULT_ERROR_MESSAGE.'6010',0), +6011 => array(DEFAULT_ERROR_MESSAGE.'6011',0), +6012 => array(DEFAULT_ERROR_MESSAGE.'6012',0), +6015 => array(DEFAULT_ERROR_MESSAGE.'6015',0), +6016 => array(DEFAULT_ERROR_MESSAGE.'6016',0), +6017 => array(DEFAULT_ERROR_MESSAGE.'6017',0), +6018 => array(DEFAULT_ERROR_MESSAGE.'6018',0), +6019 => array(DEFAULT_ERROR_MESSAGE.'6019',0), +6020 => array(DEFAULT_ERROR_MESSAGE.'6020',0), +6021 => array(DEFAULT_ERROR_MESSAGE.'6021',0), +6022 => array(DEFAULT_ERROR_MESSAGE.'6022',0), +6023 => array(DEFAULT_ERROR_MESSAGE.'6023',0), +6024 => array(DEFAULT_ERROR_MESSAGE.'6024',0), +6025 => array(DEFAULT_ERROR_MESSAGE.'6025',0), +6027 => array(DEFAULT_ERROR_MESSAGE.'6027',0), +6028 => array(DEFAULT_ERROR_MESSAGE.'6028',0), +6029 => array(DEFAULT_ERROR_MESSAGE.'6029',0), +6030 => array(DEFAULT_ERROR_MESSAGE.'6030',0), +6031 => array(DEFAULT_ERROR_MESSAGE.'6031',0), +6032 => array(DEFAULT_ERROR_MESSAGE.'6032',0), +6033 => array(DEFAULT_ERROR_MESSAGE.'6033',0), +7001 => array(DEFAULT_ERROR_MESSAGE.'7001',0), +8001 => array(DEFAULT_ERROR_MESSAGE.'8001',0), +8002 => array(DEFAULT_ERROR_MESSAGE.'8002',0), +8003 => array(DEFAULT_ERROR_MESSAGE.'8003',0), +8004 => array(DEFAULT_ERROR_MESSAGE.'8004',0), +9001 => array(DEFAULT_ERROR_MESSAGE.'9001',0), +10001 => array(DEFAULT_ERROR_MESSAGE.'10001',0), +10002 => array(DEFAULT_ERROR_MESSAGE.'10002',0), +10003 => array(DEFAULT_ERROR_MESSAGE.'10003',0), +11001 => array(DEFAULT_ERROR_MESSAGE.'11001',0), +11002 => array(DEFAULT_ERROR_MESSAGE.'11002',0), +11003 => array(DEFAULT_ERROR_MESSAGE.'11003',0), +11004 => array(DEFAULT_ERROR_MESSAGE.'11004',0), +11005 => array(DEFAULT_ERROR_MESSAGE.'11005',0), +12001 => array(DEFAULT_ERROR_MESSAGE.'12001',0), +12002 => array(DEFAULT_ERROR_MESSAGE.'12002',0), +12003 => array(DEFAULT_ERROR_MESSAGE.'12003',0), +12004 => array(DEFAULT_ERROR_MESSAGE.'12004',0), +12005 => array(DEFAULT_ERROR_MESSAGE.'12005',0), +12006 => array(DEFAULT_ERROR_MESSAGE.'12006',0), +12007 => array(DEFAULT_ERROR_MESSAGE.'12007',0), +12008 => array(DEFAULT_ERROR_MESSAGE.'12008',0), +12009 => array(DEFAULT_ERROR_MESSAGE.'12009',0), +12010 => array(DEFAULT_ERROR_MESSAGE.'12010',0), +12011 => array(DEFAULT_ERROR_MESSAGE.'12011',0), +12012 => array(DEFAULT_ERROR_MESSAGE.'12012',0), +14001 => array(DEFAULT_ERROR_MESSAGE.'14001',0), +14002 => array(DEFAULT_ERROR_MESSAGE.'14002',0), +14003 => array(DEFAULT_ERROR_MESSAGE.'14003',0), +14004 => array(DEFAULT_ERROR_MESSAGE.'14004',0), +14005 => array(DEFAULT_ERROR_MESSAGE.'14005',0), +14006 => array(DEFAULT_ERROR_MESSAGE.'14006',0), +14007 => array(DEFAULT_ERROR_MESSAGE.'14007',0), +15001 => array(DEFAULT_ERROR_MESSAGE.'15001',0), +15002 => array(DEFAULT_ERROR_MESSAGE.'15002',0), +15003 => array(DEFAULT_ERROR_MESSAGE.'15003',0), +15004 => array(DEFAULT_ERROR_MESSAGE.'15004',0), +15005 => array(DEFAULT_ERROR_MESSAGE.'15005',0), +15006 => array(DEFAULT_ERROR_MESSAGE.'15006',0), +15007 => array(DEFAULT_ERROR_MESSAGE.'15007',0), +15008 => array(DEFAULT_ERROR_MESSAGE.'15008',0), +15009 => array(DEFAULT_ERROR_MESSAGE.'15009',0), +15010 => array(DEFAULT_ERROR_MESSAGE.'15010',0), +15011 => array(DEFAULT_ERROR_MESSAGE.'15011',0), +15012 => array(DEFAULT_ERROR_MESSAGE.'15012',0), +16001 => array(DEFAULT_ERROR_MESSAGE.'16001',0), +16002 => array(DEFAULT_ERROR_MESSAGE.'16002',0), +16003 => array(DEFAULT_ERROR_MESSAGE.'16003',0), +16004 => array(DEFAULT_ERROR_MESSAGE.'16004',0), +17001 => array(DEFAULT_ERROR_MESSAGE.'17001',0), +17002 => array(DEFAULT_ERROR_MESSAGE.'17002',0), +17004 => array(DEFAULT_ERROR_MESSAGE.'17004',0), +18001 => array(DEFAULT_ERROR_MESSAGE.'18001',0), +18002 => array(DEFAULT_ERROR_MESSAGE.'18002',0), +18003 => array(DEFAULT_ERROR_MESSAGE.'18003',0), +18004 => array(DEFAULT_ERROR_MESSAGE.'18004',0), +18005 => array(DEFAULT_ERROR_MESSAGE.'18005',0), +18006 => array(DEFAULT_ERROR_MESSAGE.'18006',0), +18007 => array(DEFAULT_ERROR_MESSAGE.'18007',0), +18008 => array(DEFAULT_ERROR_MESSAGE.'18008',0), +19001 => array(DEFAULT_ERROR_MESSAGE.'19001',0), +19002 => array(DEFAULT_ERROR_MESSAGE.'19002',0), +19003 => array(DEFAULT_ERROR_MESSAGE.'19003',0), +20001 => array(DEFAULT_ERROR_MESSAGE.'20001',0), +20002 => array(DEFAULT_ERROR_MESSAGE.'20002',0), +20003 => array(DEFAULT_ERROR_MESSAGE.'20003',0), +21001 => array(DEFAULT_ERROR_MESSAGE.'21001',0), +23001 => array(DEFAULT_ERROR_MESSAGE.'23001',0), +23002 => array(DEFAULT_ERROR_MESSAGE.'23002',0), +23003 => array(DEFAULT_ERROR_MESSAGE.'23003',0), +24001 => array(DEFAULT_ERROR_MESSAGE.'24001',0), +24002 => array(DEFAULT_ERROR_MESSAGE.'24002',0), +24003 => array(DEFAULT_ERROR_MESSAGE.'24003',0), +24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0), +25001 => array(DEFAULT_ERROR_MESSAGE.'25001',0), +25002 => array(DEFAULT_ERROR_MESSAGE.'25002',0), +25003 => array(DEFAULT_ERROR_MESSAGE.'25003',0), +25004 => array(DEFAULT_ERROR_MESSAGE.'25004',0), +25005 => array(DEFAULT_ERROR_MESSAGE.'25005',0), +25006 => array(DEFAULT_ERROR_MESSAGE.'25006',0), +25007 => array(DEFAULT_ERROR_MESSAGE.'25007',0), +25008 => array(DEFAULT_ERROR_MESSAGE.'25008',0), +25009 => array(DEFAULT_ERROR_MESSAGE.'25009',0), +25010 => array(DEFAULT_ERROR_MESSAGE.'25010',0), +25011 => array(DEFAULT_ERROR_MESSAGE.'25011',0), +25012 => array(DEFAULT_ERROR_MESSAGE.'25012',0), +25013 => array(DEFAULT_ERROR_MESSAGE.'25013',0), +25014 => array(DEFAULT_ERROR_MESSAGE.'25014',0), +25015 => array(DEFAULT_ERROR_MESSAGE.'25015',0), +25016 => array(DEFAULT_ERROR_MESSAGE.'25016',0), +25017 => array(DEFAULT_ERROR_MESSAGE.'25017',0), +25018 => array(DEFAULT_ERROR_MESSAGE.'25018',0), +25019 => array(DEFAULT_ERROR_MESSAGE.'25019',0), +25020 => array(DEFAULT_ERROR_MESSAGE.'25020',0), +25021 => array(DEFAULT_ERROR_MESSAGE.'25021',0), +25022 => array(DEFAULT_ERROR_MESSAGE.'25022',0), +25023 => array(DEFAULT_ERROR_MESSAGE.'25023',0), +25024 => array(DEFAULT_ERROR_MESSAGE.'25024',0), +25025 => array(DEFAULT_ERROR_MESSAGE.'25025',0), +25026 => array(DEFAULT_ERROR_MESSAGE.'25026',0), +25027 => array(DEFAULT_ERROR_MESSAGE.'25027',0), +25028 => array(DEFAULT_ERROR_MESSAGE.'25028',0), +25029 => array(DEFAULT_ERROR_MESSAGE.'25029',0), +25030 => array(DEFAULT_ERROR_MESSAGE.'25030',0), +25031 => array(DEFAULT_ERROR_MESSAGE.'25031',0), +25032 => array(DEFAULT_ERROR_MESSAGE.'25032',0), +25033 => array(DEFAULT_ERROR_MESSAGE.'25033',0), +25034 => array(DEFAULT_ERROR_MESSAGE.'25034',0), +25035 => array(DEFAULT_ERROR_MESSAGE.'25035',0), +25036 => array(DEFAULT_ERROR_MESSAGE.'25036',0), +25037 => array(DEFAULT_ERROR_MESSAGE.'25037',0), +25038 => array(DEFAULT_ERROR_MESSAGE.'25038',0), +25039 => array(DEFAULT_ERROR_MESSAGE.'25039',0), +25040 => array(DEFAULT_ERROR_MESSAGE.'25040',0), +25041 => array(DEFAULT_ERROR_MESSAGE.'25041',0), +25042 => array(DEFAULT_ERROR_MESSAGE.'25042',0), +25043 => array(DEFAULT_ERROR_MESSAGE.'25043',0), +25044 => array(DEFAULT_ERROR_MESSAGE.'25044',0), +25045 => array(DEFAULT_ERROR_MESSAGE.'25045',0), +25046 => array(DEFAULT_ERROR_MESSAGE.'25046',0), +25047 => array(DEFAULT_ERROR_MESSAGE.'25047',0), +25048 => array(DEFAULT_ERROR_MESSAGE.'25048',0), +25049 => array(DEFAULT_ERROR_MESSAGE.'25049',0), +25050 => array(DEFAULT_ERROR_MESSAGE.'25050',0), +25051 => array(DEFAULT_ERROR_MESSAGE.'25051',0), +25052 => array(DEFAULT_ERROR_MESSAGE.'25052',0), +25053 => array(DEFAULT_ERROR_MESSAGE.'25053',0), +25054 => array(DEFAULT_ERROR_MESSAGE.'25054',0), +25055 => array(DEFAULT_ERROR_MESSAGE.'25055',0), +25056 => array(DEFAULT_ERROR_MESSAGE.'25056',0), +25057 => array(DEFAULT_ERROR_MESSAGE.'25057',0), +25058 => array(DEFAULT_ERROR_MESSAGE.'25058',0), +25059 => array(DEFAULT_ERROR_MESSAGE.'25059',0), +25060 => array(DEFAULT_ERROR_MESSAGE.'25060',0), +25061 => array(DEFAULT_ERROR_MESSAGE.'25061',0), +25062 => array(DEFAULT_ERROR_MESSAGE.'25062',0), +25063 => array(DEFAULT_ERROR_MESSAGE.'25063',0), +25064 => array(DEFAULT_ERROR_MESSAGE.'25064',0), +25065 => array(DEFAULT_ERROR_MESSAGE.'25065',0), +25066 => array(DEFAULT_ERROR_MESSAGE.'25066',0), +25067 => array(DEFAULT_ERROR_MESSAGE.'25067',0), +25068 => array(DEFAULT_ERROR_MESSAGE.'25068',0), +25069 => array(DEFAULT_ERROR_MESSAGE.'25069',0), +25070 => array(DEFAULT_ERROR_MESSAGE.'25070',0), +25071 => array(DEFAULT_ERROR_MESSAGE.'25071',0), +25072 => array(DEFAULT_ERROR_MESSAGE.'25072',0), +25073 => array(DEFAULT_ERROR_MESSAGE.'25073',0), +25074 => array(DEFAULT_ERROR_MESSAGE.'25074',0), +25075 => array(DEFAULT_ERROR_MESSAGE.'25075',0), +25077 => array(DEFAULT_ERROR_MESSAGE.'25077',0), +25078 => array(DEFAULT_ERROR_MESSAGE.'25078',0), +25079 => array(DEFAULT_ERROR_MESSAGE.'25079',0), +25080 => array(DEFAULT_ERROR_MESSAGE.'25080',0), +25081 => array(DEFAULT_ERROR_MESSAGE.'25081',0), +25082 => array(DEFAULT_ERROR_MESSAGE.'25082',0), +25083 => array(DEFAULT_ERROR_MESSAGE.'25083',0), +25084 => array(DEFAULT_ERROR_MESSAGE.'25084',0), +25085 => array(DEFAULT_ERROR_MESSAGE.'25085',0), +25086 => array(DEFAULT_ERROR_MESSAGE.'25086',0), +25087 => array(DEFAULT_ERROR_MESSAGE.'25087',0), +25088 => array(DEFAULT_ERROR_MESSAGE.'25088',0), +25089 => array(DEFAULT_ERROR_MESSAGE.'25089',0), +25090 => array(DEFAULT_ERROR_MESSAGE.'25090',0), +25091 => array(DEFAULT_ERROR_MESSAGE.'25091',0), +25092 => array(DEFAULT_ERROR_MESSAGE.'25092',0), +25093 => array(DEFAULT_ERROR_MESSAGE.'25093',0), +25094 => array(DEFAULT_ERROR_MESSAGE.'25094',0), +25095 => array(DEFAULT_ERROR_MESSAGE.'25095',0), +25096 => array(DEFAULT_ERROR_MESSAGE.'25096',0), +25097 => array(DEFAULT_ERROR_MESSAGE.'25097',0), +25098 => array(DEFAULT_ERROR_MESSAGE.'25098',0), +25099 => array(DEFAULT_ERROR_MESSAGE.'25099',0), +25100 => array(DEFAULT_ERROR_MESSAGE.'25100',0), +25101 => array(DEFAULT_ERROR_MESSAGE.'25101',0), +25102 => array(DEFAULT_ERROR_MESSAGE.'25102',0), +25103 => array(DEFAULT_ERROR_MESSAGE.'25103',0), +25104 => array(DEFAULT_ERROR_MESSAGE.'25104',0), +25105 => array(DEFAULT_ERROR_MESSAGE.'25105',0), +25106 => array(DEFAULT_ERROR_MESSAGE.'25106',0), +25107 => array(DEFAULT_ERROR_MESSAGE.'25107',0), +25108 => array(DEFAULT_ERROR_MESSAGE.'25108',0), +25109 => array(DEFAULT_ERROR_MESSAGE.'25109',0), +25110 => array(DEFAULT_ERROR_MESSAGE.'25110',0), +25111 => array(DEFAULT_ERROR_MESSAGE.'25111',0), +25112 => array(DEFAULT_ERROR_MESSAGE.'25112',0), +25113 => array(DEFAULT_ERROR_MESSAGE.'25113',0), +25114 => array(DEFAULT_ERROR_MESSAGE.'25114',0), +25115 => array(DEFAULT_ERROR_MESSAGE.'25115',0), +25116 => array(DEFAULT_ERROR_MESSAGE.'25116',0), +25117 => array(DEFAULT_ERROR_MESSAGE.'25117',0), +25118 => array(DEFAULT_ERROR_MESSAGE.'25118',0), +25119 => array(DEFAULT_ERROR_MESSAGE.'25119',0), +25120 => array(DEFAULT_ERROR_MESSAGE.'25120',0), +25121 => array(DEFAULT_ERROR_MESSAGE.'25121',0), +25122 => array(DEFAULT_ERROR_MESSAGE.'25122',0), +25123 => array(DEFAULT_ERROR_MESSAGE.'25123',0), +25124 => array(DEFAULT_ERROR_MESSAGE.'25124',0), +25125 => array(DEFAULT_ERROR_MESSAGE.'25125',0), +25126 => array(DEFAULT_ERROR_MESSAGE.'25126',0), +25127 => array(DEFAULT_ERROR_MESSAGE.'25127',0), +25128 => array(DEFAULT_ERROR_MESSAGE.'25128',0), +25129 => array(DEFAULT_ERROR_MESSAGE.'25129',0), +25130 => array(DEFAULT_ERROR_MESSAGE.'25130',0), +25131 => array(DEFAULT_ERROR_MESSAGE.'25131',0), +25132 => array(DEFAULT_ERROR_MESSAGE.'25132',0), +25133 => array(DEFAULT_ERROR_MESSAGE.'25133',0), +25500 => array(DEFAULT_ERROR_MESSAGE.'25500',0), +24003 => array(DEFAULT_ERROR_MESSAGE.'24003',0), +24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0), +24005 => array(DEFAULT_ERROR_MESSAGE.'24005',0), +24006 => array(DEFAULT_ERROR_MESSAGE.'24006',0), +24007 => array(DEFAULT_ERROR_MESSAGE.'24007',0), +24008 => array(DEFAULT_ERROR_MESSAGE.'24008',0), +24009 => array(DEFAULT_ERROR_MESSAGE.'24009',0), +24010 => array(DEFAULT_ERROR_MESSAGE.'24010',0), +24011 => array(DEFAULT_ERROR_MESSAGE.'24011',0), +24012 => array(DEFAULT_ERROR_MESSAGE.'24012',0), +24013 => array(DEFAULT_ERROR_MESSAGE.'24013',0), +24014 => array(DEFAULT_ERROR_MESSAGE.'24014',0), +24015 => array(DEFAULT_ERROR_MESSAGE.'24015',0), +22001 => array(DEFAULT_ERROR_MESSAGE.'22001',0), +22002 => array(DEFAULT_ERROR_MESSAGE.'22002',0), +22004 => array(DEFAULT_ERROR_MESSAGE.'22004',0), +22005 => array(DEFAULT_ERROR_MESSAGE.'22005',0), +22006 => array(DEFAULT_ERROR_MESSAGE.'22006',0), +22007 => array(DEFAULT_ERROR_MESSAGE.'22007',0), +22008 => array(DEFAULT_ERROR_MESSAGE.'22008',0), +22009 => array(DEFAULT_ERROR_MESSAGE.'22009',0), +22010 => array(DEFAULT_ERROR_MESSAGE.'22010',0), +22011 => array(DEFAULT_ERROR_MESSAGE.'22011',0), +22012 => array(DEFAULT_ERROR_MESSAGE.'22012',0), +22013 => array(DEFAULT_ERROR_MESSAGE.'22013',0), +22014 => array(DEFAULT_ERROR_MESSAGE.'22014',0), +22015 => array(DEFAULT_ERROR_MESSAGE.'22015',0), +22016 => array(DEFAULT_ERROR_MESSAGE.'22016',0), +22017 => array(DEFAULT_ERROR_MESSAGE.'22017',0), +22018 => array(DEFAULT_ERROR_MESSAGE.'22018',0), +22019 => array(DEFAULT_ERROR_MESSAGE.'22019',0), +22020 => array(DEFAULT_ERROR_MESSAGE.'22020',0), +13001 => array(DEFAULT_ERROR_MESSAGE.'13001',0), +13002 => array(DEFAULT_ERROR_MESSAGE.'13002',0), +1001 => array(DEFAULT_ERROR_MESSAGE.'1001',0), +1002 => array(DEFAULT_ERROR_MESSAGE.'1002',0), +1003 => array(DEFAULT_ERROR_MESSAGE.'1003',0), +1004 => array(DEFAULT_ERROR_MESSAGE.'1004',0), +1005 => array(DEFAULT_ERROR_MESSAGE.'1005',0), +1006 => array(DEFAULT_ERROR_MESSAGE.'1006',0), +1007 => array(DEFAULT_ERROR_MESSAGE.'1007',0), +1008 => array(DEFAULT_ERROR_MESSAGE.'1008',0), +1009 => array(DEFAULT_ERROR_MESSAGE.'1009',0), +1010 => array(DEFAULT_ERROR_MESSAGE.'1010',0), +1011 => array(DEFAULT_ERROR_MESSAGE.'1011',0), +26000 => array(DEFAULT_ERROR_MESSAGE.'26000',0), +26001 => array(DEFAULT_ERROR_MESSAGE.'26001',0), +26002 => array(DEFAULT_ERROR_MESSAGE.'26002',0), +26003 => array(DEFAULT_ERROR_MESSAGE.'26003',0), +26004 => array(DEFAULT_ERROR_MESSAGE.'26004',0), +26005 => array(DEFAULT_ERROR_MESSAGE.'26005',0), +26006 => array(DEFAULT_ERROR_MESSAGE.'26006',0), +26007 => array(DEFAULT_ERROR_MESSAGE.'26007',0), +26008 => array(DEFAULT_ERROR_MESSAGE.'26008',0), +26009 => array(DEFAULT_ERROR_MESSAGE.'26009',0), +26010 => array(DEFAULT_ERROR_MESSAGE.'26010',0), +26011 => array(DEFAULT_ERROR_MESSAGE.'26011',0), +26012 => array(DEFAULT_ERROR_MESSAGE.'26012',0), +26013 => array(DEFAULT_ERROR_MESSAGE.'26013',0), +26014 => array(DEFAULT_ERROR_MESSAGE.'26014',0), +26015 => array(DEFAULT_ERROR_MESSAGE.'26015',0), +26016 => array(DEFAULT_ERROR_MESSAGE.'26016',0), + +27001 => array(DEFAULT_ERROR_MESSAGE.'27001',0), +27002 => array(DEFAULT_ERROR_MESSAGE.'27002',0), +27003 => array(DEFAULT_ERROR_MESSAGE.'27003',0), +27004 => array(DEFAULT_ERROR_MESSAGE.'27004',0), +27005 => array(DEFAULT_ERROR_MESSAGE.'27005',0), +27006 => array(DEFAULT_ERROR_MESSAGE.'27006',0), +27007 => array(DEFAULT_ERROR_MESSAGE.'27007',0), +27008 => array(DEFAULT_ERROR_MESSAGE.'27008',0), +27009 => array(DEFAULT_ERROR_MESSAGE.'27009',0), +27010 => array(DEFAULT_ERROR_MESSAGE.'27010',0), +27011 => array(DEFAULT_ERROR_MESSAGE.'27011',0), +27012 => array(DEFAULT_ERROR_MESSAGE.'27012',0), +27013 => array(DEFAULT_ERROR_MESSAGE.'27013',0), +27014 => array(DEFAULT_ERROR_MESSAGE.'27014',0), +27015 => array(DEFAULT_ERROR_MESSAGE.'27015',0), + +28001 => array(DEFAULT_ERROR_MESSAGE.'28001',0), +28002 => array(DEFAULT_ERROR_MESSAGE.'28002',0), +28003 => array(DEFAULT_ERROR_MESSAGE.'28003',0), +28004 => array(DEFAULT_ERROR_MESSAGE.'28004',0), +28005 => array(DEFAULT_ERROR_MESSAGE.'28005',0), +28006 => array(DEFAULT_ERROR_MESSAGE.'28006',0), +28007 => array(DEFAULT_ERROR_MESSAGE.'28007',0), + +29201 => array(DEFAULT_ERROR_MESSAGE.'28001',0), +29202 => array(DEFAULT_ERROR_MESSAGE.'28002',0), +29203 => array(DEFAULT_ERROR_MESSAGE.'28003',0), +29204 => array(DEFAULT_ERROR_MESSAGE.'28004',0), +29205 => array(DEFAULT_ERROR_MESSAGE.'28005',0), +29206 => array(DEFAULT_ERROR_MESSAGE.'28006',0), +29207 => array(DEFAULT_ERROR_MESSAGE.'28007',0), +29208 => array(DEFAULT_ERROR_MESSAGE.'28008',0), +29209 => array(DEFAULT_ERROR_MESSAGE.'28009',0), +29210 => array(DEFAULT_ERROR_MESSAGE.'28010',0), + +); + +?> diff --git a/web/public_php/admin/jpgraph/themes/AquaTheme.class.php b/web/public_php/admin/jpgraph/themes/AquaTheme.class.php new file mode 100644 index 000000000..1593b7f6b --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/AquaTheme.class.php @@ -0,0 +1,201 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.80, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(4); + + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + //$plot->SetShadow(); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + $plot->SetColor($this->GetNextColor()); + $plot->SetWeight(2); +// $plot->SetBarCenter(); + break; + } + + case 'PiePlot': + { + $plot->SetCenter(0.5, 0.45); + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/GreenTheme.class.php b/web/public_php/admin/jpgraph/themes/GreenTheme.class.php new file mode 100644 index 000000000..ffd285446 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/GreenTheme.class.php @@ -0,0 +1,182 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + /* + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + */ + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + + $plot->SetColor($this->GetNextColor().'@0.4'); + $plot->SetWeight(2); + break; + } + + case 'PiePlot': + { + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/OceanTheme.class.php b/web/public_php/admin/jpgraph/themes/OceanTheme.class.php new file mode 100644 index 000000000..1fd9ecea9 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/OceanTheme.class.php @@ -0,0 +1,184 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + /* + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + */ + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + + $plot->SetColor($this->GetNextColor()); + $plot->SetWeight(2); + break; + } + + case 'PiePlot': + { + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/OrangeTheme.class.php b/web/public_php/admin/jpgraph/themes/OrangeTheme.class.php new file mode 100644 index 000000000..f5e4a26b3 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/OrangeTheme.class.php @@ -0,0 +1,184 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + /* + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + */ + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + + $plot->SetColor($this->GetNextColor().'@0.4'); + $plot->SetWeight(2); + break; + } + + case 'PiePlot': + { + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/PastelTheme.class.php b/web/public_php/admin/jpgraph/themes/PastelTheme.class.php new file mode 100644 index 000000000..97ac61b3a --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/PastelTheme.class.php @@ -0,0 +1,179 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.80, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(4); + + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + $plot->SetColor($this->GetNextColor().'@0.4'); + $plot->SetWeight(2); +// $plot->SetBarCenter(); + break; + } + + case 'PiePlot': + { + $plot->SetCenter(0.5, 0.45); + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/RoseTheme.class.php b/web/public_php/admin/jpgraph/themes/RoseTheme.class.php new file mode 100644 index 000000000..066a93e73 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/RoseTheme.class.php @@ -0,0 +1,184 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + /* + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + */ + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + + $plot->SetColor($this->GetNextColor().'@0.4'); + $plot->SetWeight(2); + break; + } + + case 'PiePlot': + { + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/SoftyTheme.class.php b/web/public_php/admin/jpgraph/themes/SoftyTheme.class.php new file mode 100644 index 000000000..327453ee5 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/SoftyTheme.class.php @@ -0,0 +1,213 @@ +SetFrame(false); + $graph->SetMarginColor('white'); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // y2~ + if (isset($graph->y2axis)) { + $graph->y2axis->title->SetColor($this->font_color); + $graph->y2axis->SetColor($this->axis_color, $this->font_color); + $graph->y2axis->SetTickSide(SIDE_LEFT); + $graph->y2axis->SetLabelMargin(8); + $graph->y2axis->HideLine(); + $graph->y2axis->HideTicks(); + } + + // yn + if (isset($graph->y2axis)) { + foreach ($graph->ynaxis as $axis) { + $axis->title->SetColor($this->font_color); + $axis->SetColor($this->axis_color, $this->font_color); + $axis->SetTickSide(SIDE_LEFT); + $axis->SetLabelMargin(8); + $axis->HideLine(); + $axis->HideTicks(); + } + } + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + $graph->ygrid->SetFill(true, '#FFFFFF', $this->background_color); + $graph->xgrid->Show(); + $graph->xgrid->SetColor($this->grid_color); + $graph->xgrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + $plot->value->SetAlign('center', 'center'); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + + $plot->SetColor($this->GetNextColor()); + $plot->SetWeight(2); +// $plot->SetBarCenter(); + break; + } + + case 'PiePlot': + { + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + $plot->value->SetAlign('center', 'center'); + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + $_plot->SetValuePos('center'); + } + break; + } + + case 'ScatterPlot': + { + break; + } + + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/UniversalTheme.class.php b/web/public_php/admin/jpgraph/themes/UniversalTheme.class.php new file mode 100644 index 000000000..62ef6a213 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/UniversalTheme.class.php @@ -0,0 +1,187 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBox(true, '#DADADA'); +// $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + $graph->xaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + //$graph->xaxis->SetLabelMargin(30); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); +// $graph->yaxis->SetTickPositions(array(50, 100, 150)); +// $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetFill(true, '#FFFFFF', $this->background_color); + // $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.80, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(4); + + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + $plot->SetColor($this->GetNextColor().'@0.4'); + $plot->SetWeight(2); + break; + } + + case 'PiePlot': + { + $plot->SetCenter(0.5, 0.45); + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?> diff --git a/web/public_php/admin/jpgraph/themes/VividTheme.class.php b/web/public_php/admin/jpgraph/themes/VividTheme.class.php new file mode 100644 index 000000000..b31c6cdc9 --- /dev/null +++ b/web/public_php/admin/jpgraph/themes/VividTheme.class.php @@ -0,0 +1,179 @@ +img; + $height = $img->height; + $graph->SetMargin($img->left_margin, $img->right_margin, $img->top_margin, $height * 0.25); + */ + $graph->SetFrame(false); + $graph->SetMarginColor('white'); + $graph->SetBackgroundGradient($this->background_color, '#FFFFFF', GRAD_HOR, BGRAD_PLOT); + + // legend + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.85, 'center', 'top'); + $graph->legend->SetFillColor('white'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(3); + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // xaxis + $graph->xaxis->title->SetColor($this->font_color); + $graph->xaxis->SetColor($this->axis_color, $this->font_color); + $graph->xaxis->SetTickSide(SIDE_BOTTOM); + $graph->xaxis->SetLabelMargin(10); + + // yaxis + $graph->yaxis->title->SetColor($this->font_color); + $graph->yaxis->SetColor($this->axis_color, $this->font_color); + $graph->yaxis->SetTickSide(SIDE_LEFT); + $graph->yaxis->SetLabelMargin(8); + $graph->yaxis->HideLine(); + $graph->yaxis->HideTicks(); + $graph->xaxis->SetTitleMargin(15); + + // grid + $graph->ygrid->SetColor($this->grid_color); + $graph->ygrid->SetLineStyle('dotted'); + + + // font + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + +// $graph->img->SetAntiAliasing(); + } + + + function SetupPieGraph($graph) { + + // graph + $graph->SetFrame(false); + + // legend + $graph->legend->SetFillColor('white'); + + $graph->legend->SetFrameWeight(0); + $graph->legend->Pos(0.5, 0.80, 'center', 'top'); + $graph->legend->SetLayout(LEGEND_HOR); + $graph->legend->SetColumns(4); + + $graph->legend->SetShadow(false); + $graph->legend->SetMarkAbsSize(5); + + // title + $graph->title->SetColor($this->font_color); + $graph->subtitle->SetColor($this->font_color); + $graph->subsubtitle->SetColor($this->font_color); + + $graph->SetAntiAliasing(); + } + + + function PreStrokeApply($graph) { + if ($graph->legend->HasItems()) { + $img = $graph->img; + $graph->SetMargin( + $img->raw_left_margin, + $img->raw_right_margin, + $img->raw_top_margin, + is_numeric($img->raw_bottom_margin) ? $img->raw_bottom_margin : $img->height * 0.25 + ); + } + } + + function ApplyPlot($plot) { + + switch (get_class($plot)) + { + case 'GroupBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'AccBarPlot': + { + foreach ($plot->plots as $_plot) { + $this->ApplyPlot($_plot); + } + break; + } + + case 'BarPlot': + { + $plot->Clear(); + + $color = $this->GetNextColor(); + $plot->SetColor($color); + $plot->SetFillColor($color); + $plot->SetShadow('red', 3, 4, false); + break; + } + + case 'LinePlot': + { + $plot->Clear(); + $plot->SetColor($this->GetNextColor().'@0.4'); + $plot->SetWeight(2); +// $plot->SetBarCenter(); + break; + } + + case 'PiePlot': + { + $plot->SetCenter(0.5, 0.45); + $plot->ShowBorder(false); + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + case 'PiePlot3D': + { + $plot->SetSliceColors($this->GetThemeColors()); + break; + } + + default: + { + } + } + } +} + + +?>

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 literal 0 HcmV?d00001 diff --git a/web/public_php/admin/jpgraph/fonts/DejaVuSans-BoldOblique.ttf b/web/public_php/admin/jpgraph/fonts/DejaVuSans-BoldOblique.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c818ae6e7c2480231dc41baa3b8908ad0be45282 GIT binary patch literal 574636 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