add amendments metric
add amendments metric

file:a/about.php -> file:b/about.php
<?php <?php
include('./lib/common.inc.php'); include('./lib/common.inc.php');
include_header("Map"); include_header("Map");
?> ?>
<div class="msg_list"> <div class="msg_list">
<p class="msg_head">Header-1 </p> <p class="msg_head">Header-1 </p>
<div class="msg_body"> <div class="msg_body">
orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit
</div> </div>
<p class="msg_head">Header-2</p> <p class="msg_head">Header-2</p>
<div class="msg_body"> <div class="msg_body">
orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit
</div> </div>
<p class="msg_head">Header-3</p> <p class="msg_head">Header-3</p>
<div class="msg_body"> <div class="msg_body">
orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit orem ipsum dolor sit amet, consectetuer adipiscing elit
</div> </div>
</div> </div>
sourced from austender sourced from austender
Government Agency Information (2009-07-10): National Archives of Australia, http://www.naa.gov.au under Creative Commons - Attribution 2.5 Australia (CC-BY) Government Agency Information (2009-07-10): National Archives of Australia, http://www.naa.gov.au under Creative Commons - Attribution 2.5 Australia (CC-BY)
jpgraph for php jpgraph for php
ABR ABR
Redhat Liberation fonts Redhat Liberation fonts
<?php <?php
include_once("./lib/common.inc.php"); include_once("./lib/common.inc.php");
$query = "SELECT DATE(importDate) as importday, count(*) as count, min(publishDate) as start, max(publishDate) as end $query = "SELECT DATE(importDate) as importday, count(*) as count, min(publishDate) as start, max(publishDate) as end
FROM `contractnotice` WHERE childCN = 0 AND parentCN = 0 AND DATE(importDate) in (select * from (SELECT DATE(importDate) FROM `contractnotice` WHERE childCN = 0 AND parentCN = 0 AND DATE(importDate) in (select * from (SELECT DATE(importDate)
FROM `contractnotice` ORDER BY `importDate` DESC limit 1) alias)"; FROM `contractnotice` ORDER BY `importDate` DESC limit 1) alias)";
$result = mysql_query($query); $result = mysql_query($query);
echo "<div>"; echo "<div>";
$stats = mysql_fetch_array($result, MYSQL_BOTH); $stats = mysql_fetch_array($result, MYSQL_BOTH);
echo $stats["count"] . " new records in period " . $stats["start"] . " to " . $stats["end"] ."<br>"; echo $stats["count"] . " new records in period " . $stats["start"] . " to " . $stats["end"] ."<br>";
$query = "SELECT DATE(importDate) as importday, count(*) as count, min(publishDate) as start, max(publishDate) as end $query = "SELECT DATE(importDate) as importday, count(*) as count, min(publishDate) as start, max(publishDate) as end
FROM `contractnotice` WHERE (childCN != 0 OR parentCN != 0) AND DATE(importDate) in (select * from (SELECT DATE(importDate) FROM `contractnotice` WHERE (childCN != 0 OR parentCN != 0) AND DATE(importDate) in (select * from (SELECT DATE(importDate)
FROM `contractnotice` ORDER BY `importDate` DESC limit 1) alias)"; FROM `contractnotice` ORDER BY `importDate` DESC limit 1) alias)";
$result = mysql_query($query); $result = mysql_query($query);
echo "<div>"; echo "<div>";
$stats = mysql_fetch_array($result, MYSQL_BOTH); $stats = mysql_fetch_array($result, MYSQL_BOTH);
echo $stats["count"] . " updated records in period " . $stats["start"] . " to " . $stats["end"] ."<br>"; echo $stats["count"] . " updated records in period " . $stats["start"] . " to " . $stats["end"] ."<br>";
echo "Last updated: ". $stats["importday"]."<br>"; echo "Last updated: ". $stats["importday"]."<br>";
/* Check for null Procurement method and 0 ABN when not ABN exempt */ /* Check for null Procurement method and 0 ABN when not ABN exempt */
include_footer(); include_footer();
?> ?>
<?PHP <?PHP
//System Configurations //System Configurations
$config_http_script_dir = "http://localhost/contractDashboard/cutenews"; $config_http_script_dir = "http://localhost/contractDashboard/cutenews";
$config_skin = "default"; $config_skin = "default";
$config_date_adjust = "0"; $config_date_adjust = "0";
$config_smilies = "smile,wink,wassat,tongue,laughing,sad,angry,crying"; $config_smilies = "smile,wink,wassat,tongue,laughing,sad,angry,crying";
$config_auto_archive = "no"; $config_auto_archive = "no";
$config_allow_registration = "no"; $config_allow_registration = "no";
$config_registration_level = "4"; $config_registration_level = "4";
$config_use_avatar = "no"; $config_use_avatar = "no";
$config_use_wysiwyg = "no"; $config_use_wysiwyg = "no";
$config_reverse_active = "no"; $config_reverse_active = "no";
$config_timestamp_active = "d M Y"; $config_timestamp_active = "d M Y";
$config_full_popup = "no"; $config_full_popup = "no";
$config_full_popup_string = "HEIGHT=400,WIDTH=650,resizable=yes,scrollbars=yes"; $config_full_popup_string = "HEIGHT=400,WIDTH=650,resizable=yes,scrollbars=yes";
$config_show_comments_with_full = "yes"; $config_show_comments_with_full = "yes";
$config_auto_wrap = "44"; $config_auto_wrap = "44";
$config_reverse_comments = "no"; $config_reverse_comments = "no";
$config_flood_time = "15"; $config_flood_time = "15";
$config_comment_max_long = "1500"; $config_comment_max_long = "1500";
$config_comments_per_page = "50"; $config_comments_per_page = "50";
$config_only_registered_comment = "no"; $config_only_registered_comment = "no";
$config_allow_url_instead_mail = "yes"; $config_allow_url_instead_mail = "yes";
$config_timestamp_comment = "d M Y h:i a"; $config_timestamp_comment = "d M Y h:i a";
$config_comments_popup = "no"; $config_comments_popup = "no";
$config_comments_popup_string = "HEIGHT=400,WIDTH=650,resizable=yes,scrollbars=yes"; $config_comments_popup_string = "HEIGHT=400,WIDTH=650,resizable=yes,scrollbars=yes";
$config_show_full_with_comments = "yes"; $config_show_full_with_comments = "yes";
$config_notify_email = "govhack@lambdacomplex.org"; $config_notify_email = "govhack@lambdacomplex.org";
$config_notify_status = "disabled"; $config_notify_status = "disabled";
$config_notify_registration = "no"; $config_notify_registration = "no";
$config_notify_comment = "no"; $config_notify_comment = "no";
$config_notify_unapproved = "no"; $config_notify_unapproved = "no";
$config_notify_archive = "no"; $config_notify_archive = "no";
$config_notify_postponed = "no"; $config_notify_postponed = "no";
?> ?>
<?PHP die("You don't have access to open this file !!!"); ?> <?PHP die("You don't have access to open this file !!!"); ?>
1259446539|1|maxious|9c1cfbdadde1e4c9c5d301f57848bf38|cD team|govhack@lambdacomplex.org|0|0||1259446557|| 1259446539|1|maxious|9c1cfbdadde1e4c9c5d301f57848bf38|cD team|govhack@lambdacomplex.org|0|0||1259446557||
   
<html> <html>
<head><title>Example1</title></head> <head><title>Example1</title></head>
<body> <body>
<a href="?go=news">news</a> || <a href="?go=news">news</a> ||
<a href="?go=headlines">headlines</a> || <a href="?go=headlines">headlines</a> ||
<a href="?go=archives">arhcives</a> || <a href="?go=archives">arhcives</a> ||
<a href="?go=search">search</a> || <a href="?go=search">search</a> ||
<a style="font-size:120%" href="example2.php">See Advanced Example >></a> <a style="font-size:120%" href="example2.php">See Advanced Example >></a>
<hr> <hr>
<?PHP <?PHP
error_reporting (E_ALL ^ E_NOTICE); error_reporting (E_ALL ^ E_NOTICE);
if($_GET['go'] == "" or $_GET['go'] == "news"){ if($_GET['go'] == "" or $_GET['go'] == "news"){
include("show_news.php"); include("show_news.php");
} }
elseif($_GET['go'] == "headlines"){ elseif($_GET['go'] == "headlines"){
$template = "Headlines"; $template = "Headlines";
include("show_news.php"); include("show_news.php");
} }
elseif($_GET['go'] == "archives"){ elseif($_GET['go'] == "archives"){
include("show_archives.php"); include("show_archives.php");
} }
elseif($_GET['go'] == "search"){ elseif($_GET['go'] == "search"){
include("search.php"); include("search.php");
} }
?> ?>
</body> </body>
</html> </html>
<?PHP <?PHP
?> ?>
<html> <html>
<head> <head>
<title>Example</title> <title>Example</title>
<style> <style>
<!-- <!--
A { color: #003366; text-decoration: none; } A { color: #003366; text-decoration: none; }
A:link { color: #003366; text-decoration: none; } A:link { color: #003366; text-decoration: none; }
A:visited { color: #003366; text-decoration: none; } A:visited { color: #003366; text-decoration: none; }
A:active { color: #54622D; } A:active { color: #54622D; }
A:hover { color: #54622D; } A:hover { color: #54622D; }
BODY,TD,TR{ BODY,TD,TR{
font-family: verdana, arial, sans-serif; font-family: verdana, arial, sans-serif;
color:#000; color:#000;
font-size:11; font-size:11;
font-weight:normal; font-weight:normal;
} }
.banner { .banner {
font-family: georgia, verdana, arial, sans-serif; font-family: georgia, verdana, arial, sans-serif;
color:white; color:white;
font-size:x-large; font-size:x-large;
font-weight:bold; font-weight:bold;
border-left:1px solid #FFF; border-left:1px solid #FFF;
border-right:1px solid #FFF; border-right:1px solid #FFF;
border-top:1px solid #FFF; border-top:1px solid #FFF;
background:#003366; background:#003366;
padding:7px; padding:7px;
} }
.description{ .description{
font-family:verdana, arial, sans-serif; font-family:verdana, arial, sans-serif;
font-size:x-small; font-size:x-small;
font-weight:bold; font-weight:bold;
} }
//--> //-->
</style> </style>
</head> </head>
<body bgcolor="#ffffff"> <body bgcolor="#ffffff">
<div align="center"><center> <div align="center"><center>
<table border="0" width="700" cellspacing="0" cellpadding="0"> <table border="0" width="700" cellspacing="0" cellpadding="0">
<tr> <tr>
<td class=banner > <td class=banner >
Put here your title<br> Put here your title<br>
<span class="description">and this is your description</span> <span class="description">and this is your description</span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
&nbsp; &nbsp;
</center> </center>
<table border="0" width="100%" cellspacing="0" cellpadding="6"> <table border="0" width="100%" cellspacing="0" cellpadding="6">
<tr> <tr>
<td width="180" valign=top style="border-right: 1px dotted #000000;"><table border="0" width=93% cellspacing="0" cellpadding="0"> <td width="180" valign=top style="border-right: 1px dotted #000000;"><table border="0" width=93% cellspacing="0" cellpadding="0">
<tr> <tr>
<td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26"> <td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26">
<p align="left">&nbsp;<b><font color="#003366">Navigation</font></b></p> <p align="left">&nbsp;<b><font color="#003366">Navigation</font></b></p>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="?">main page</a> &nbsp;<a href="?">main page</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="?do=archives">archives</a> &nbsp;<a href="?do=archives">archives</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="?do=stats">statistic</a> &nbsp;<a href="?do=stats">statistic</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="?">other link</a> &nbsp;<a href="?">other link</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="?">other link</a> &nbsp;<a href="?">other link</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26"> <td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26">
<p align="left">&nbsp;<font color="#003366"><b>Quick search</b></font></p> <p align="left">&nbsp;<font color="#003366"><b>Quick search</b></font></p>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
</td> </td>
</tr> </tr>
<tr> <tr>
<!-- The Quick Search Form --> <!-- The Quick Search Form -->
<form method="post"> <form method="post">
<td width="100%" align="center">&nbsp;<br> <td width="100%" align="center">&nbsp;<br>
<input type="text" name="story" size="14"> <input type="text" name="story" size="14">
<input type="hidden" name="do" value="search"> <input type="hidden" name="do" value="search">
</td> </td>
</form> </form>
<!-- End of the Search Form --> <!-- End of the Search Form -->
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26"> <td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26">
<p align="left">&nbsp;<b><font color="#003366">banners/sponsors</font></b></p> <p align="left">&nbsp;<b><font color="#003366">banners/sponsors</font></b></p>
</td> </td>
</tr> </tr>
<center> <center>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;put some banners here &nbsp;put some banners here
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;and another banners here &nbsp;and another banners here
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26"> <td width="100%" style="border-top: 1 solid #000000; border-bottom: 1 solid #000000" bgcolor="#F3F4F5" height="26">
<p align="left">&nbsp;<font color="#003366"><b>Friends</b></font></p> <p align="left">&nbsp;<font color="#003366"><b>Friends</b></font></p>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="http://cutephp.com" title="PHP News Content Management System" target="_blank">CutePHP Scripts</a> &nbsp;<a href="http://cutephp.com" title="PHP News Content Management System" target="_blank">CutePHP Scripts</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="http://news.google.com" target="_blank">Google News</a> &nbsp;<a href="http://news.google.com" target="_blank">Google News</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="100%"> <td width="100%">
&nbsp;<a href="http://mozilla.org" target="_blank">Mozilla.org</a> &nbsp;<a href="http://mozilla.org" target="_blank">Mozilla.org</a>
</td> </td>
</tr> </tr>
</table> </table>
<p align="center"><br><br> <p align="center"><br><br>
<br> <br>
<br> <br>
<br> <br>
</center> </center>
</td> </td>
<td width="520" valign="top" align="center"> <td width="520" valign="top" align="center">
<table border="0" width="453" cellspacing="1" cellpadding="3"> <table border="0" width="453" cellspacing="1" cellpadding="3">
<tr> <tr>
<td width="441"> <td width="441">
<?PHP <?PHP
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here we decide what page to include Here we decide what page to include
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if($_POST['do'] == "search" or $_GET['dosearch'] == "yes"){ $subaction = "search"; $dosearch = "yes"; include("./search.php"); } if($_POST['do'] == "search" or $_GET['dosearch'] == "yes"){ $subaction = "search"; $dosearch = "yes"; include("./search.php"); }
elseif($_GET['do'] == "archives"){ include("./show_archives.php"); } elseif($_GET['do'] == "archives"){ include("./show_archives.php"); }
elseif($_GET['do'] == "stats"){ echo"You can download the stats addon and include it here to show how many news, comments ... you have"; /* include("$path/stats.php"); */ } elseif($_GET['do'] == "stats"){ echo"You can download the stats addon and include it here to show how many news, comments ... you have"; /* include("$path/stats.php"); */ }
else{ include("./show_news.php"); } else{ include("./show_news.php"); }
?> ?>
</td> </td>
</tr> </tr>
</table> </table>
</td> </td>
</tr> </tr>
</table> </table>
</td> </td>
</tr> </tr>
</table><br><br><center> </table><br><br><center>
<table border=0 width=700 style="border-top: 1px dotted #000000;"> <table border=0 width=700 style="border-top: 1px dotted #000000;">
<tr><td> <tr><td>
<p align="center">put your footer and copyright here <p align="center">put your footer and copyright here
</td></tr></table> </td></tr></table>
</body> </body>
</html> </html>
<?PHP <?PHP
// bad practice, i know // bad practice, i know
if ($HTTP_SESSION_VARS) {extract($HTTP_SESSION_VARS, EXTR_SKIP);} if ($HTTP_SESSION_VARS) {extract($HTTP_SESSION_VARS, EXTR_SKIP);}
if ($_SESSION) {extract($_SESSION, EXTR_SKIP);} if ($_SESSION) {extract($_SESSION, EXTR_SKIP);}
if ($HTTP_COOKIE_VARS) {extract($HTTP_COOKIE_VARS, EXTR_SKIP);} if ($HTTP_COOKIE_VARS) {extract($HTTP_COOKIE_VARS, EXTR_SKIP);}
if ($_COOKIE) {extract($_COOKIE, EXTR_SKIP);} if ($_COOKIE) {extract($_COOKIE, EXTR_SKIP);}
if ($HTTP_POST_VARS) {extract($HTTP_POST_VARS, EXTR_SKIP);} if ($HTTP_POST_VARS) {extract($HTTP_POST_VARS, EXTR_SKIP);}
if ($_POST) {extract($_POST, EXTR_SKIP);} if ($_POST) {extract($_POST, EXTR_SKIP);}
if ($HTTP_GET_VARS) {extract($HTTP_GET_VARS, EXTR_SKIP);} if ($HTTP_GET_VARS) {extract($HTTP_GET_VARS, EXTR_SKIP);}
if ($_GET) {extract($_GET, EXTR_SKIP);} if ($_GET) {extract($_GET, EXTR_SKIP);}
if ($HTTP_ENV_VARS) {extract($HTTP_ENV_VARS, EXTR_SKIP);} if ($HTTP_ENV_VARS) {extract($HTTP_ENV_VARS, EXTR_SKIP);}
if ($_ENV) {extract($_ENV, EXTR_SKIP);} if ($_ENV) {extract($_ENV, EXTR_SKIP);}
//---------------------------------- //----------------------------------
// Sanitize Variables // Sanitize Variables
//---------------------------------- //----------------------------------
if( isset($template) and $template != "" and !eregi("^[_a-zA-Z0-9-]{1,}$", $template)){ die("invalid template characters"); } if( isset($template) and $template != "" and !eregi("^[_a-zA-Z0-9-]{1,}$", $template)){ die("invalid template characters"); }
if( isset($archive) and $archive != "" and !eregi("^[_a-zA-Z0-9-]{1,}$", $archive)){ die("invalid archive characters"); } if( isset($archive) and $archive != "" and !eregi("^[_a-zA-Z0-9-]{1,}$", $archive)){ die("invalid archive characters"); }
if($PHP_SELF == ""){ $PHP_SELF = $_SERVER["PHP_SELF"]; } if($PHP_SELF == ""){ $PHP_SELF = $_SERVER["PHP_SELF"]; }
$phpversion = @phpversion(); $phpversion = @phpversion();
$a7f89abdcf9324b3 = ""; $a7f89abdcf9324b3 = "";
$comm_start_from = htmlspecialchars($comm_start_from); $comm_start_from = htmlspecialchars($comm_start_from);
$start_from = htmlspecialchars($start_from); $start_from = htmlspecialchars($start_from);
$archive = htmlspecialchars($archive); $archive = htmlspecialchars($archive);
$subaction = htmlspecialchars($subaction); $subaction = htmlspecialchars($subaction);
$id = htmlspecialchars($id); $id = htmlspecialchars($id);
$ucat = htmlspecialchars($ucat); $ucat = htmlspecialchars($ucat);
if(is_array($category)){ foreach($category as $ckey=>$cvalue){ $category[$ckey] = htmlspecialchars($category[$ckey]);} } if(is_array($category)){ foreach($category as $ckey=>$cvalue){ $category[$ckey] = htmlspecialchars($category[$ckey]);} }
else{ $category = htmlspecialchars($category); } else{ $category = htmlspecialchars($category); }
$number = htmlspecialchars($number); $number = htmlspecialchars($number);
$template = htmlspecialchars($template); $template = htmlspecialchars($template);
$show = htmlspecialchars($show); $show = htmlspecialchars($show);
$config_version_name = "CuteNews v1.4.6"; $config_version_name = "CuteNews v1.4.6";
$config_version_id = 186; $config_version_id = 186;
//---------------------------------- //----------------------------------
// Some Special Chars // Some Special Chars
//---------------------------------- //----------------------------------
$HTML_SPECIAL_CHARS = Array ( // Master array replaced ALWAYS !!! $HTML_SPECIAL_CHARS = Array ( // Master array replaced ALWAYS !!!
); );
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: ResynchronizeAutoArchive // Function: ResynchronizeAutoArchive
// Description: Auto-Archives News // Description: Auto-Archives News
function ResynchronizeAutoArchive(){ function ResynchronizeAutoArchive(){
global $cutepath, $config_auto_archive, $config_notify_email,$config_notify_archive,$config_notify_status; global $cutepath, $config_auto_archive, $config_notify_email,$config_notify_archive,$config_notify_status;
$count_news = count(file("$cutepath/data/news.txt")); $count_news = count(file("$cutepath/data/news.txt"));
if($count_news > 1){ if($count_news > 1){
if($config_auto_archive == "yes"){ if($config_auto_archive == "yes"){
$now[year] = date("Y"); $now[year] = date("Y");
$now[month] = date("n"); $now[month] = date("n");
$db_content = file("$cutepath/data/auto_archive.db.php"); $db_content = file("$cutepath/data/auto_archive.db.php");
list($last_archived[year], $last_archived[month]) = split("\|", $db_content[0] ); list($last_archived[year], $last_archived[month]) = split("\|", $db_content[0] );
$tmp_now_sum = $now[year] . sprintf("%02d", $now[month]) ; $tmp_now_sum = $now[year] . sprintf("%02d", $now[month]) ;
$tmp_last_sum = (int)$last_archived[year] . sprintf("%02d", (int)$last_archived[month]) ; $tmp_last_sum = (int)$last_archived[year] . sprintf("%02d", (int)$last_archived[month]) ;
if($tmp_now_sum > $tmp_last_sum){ if($tmp_now_sum > $tmp_last_sum){
$error = FALSE; $error = FALSE;
$arch_name = time(); $arch_name = time();
if(!@copy("$cutepath/data/news.txt","$cutepath/data/archives/$arch_name.news.arch")) { $error = "Can not copy news.txt from data/ to data/archives"; } if(!@copy("$cutepath/data/news.txt","$cutepath/data/archives/$arch_name.news.arch")) { $error = "Can not copy news.txt from data/ to data/archives"; }
if(!@copy("$cutepath/data/comments.txt","$cutepath/data/archives/$arch_name.comments.arch")) { $error = "Can not copy comments.txt from data/ to data/archives"; } if(!@copy("$cutepath/data/comments.txt","$cutepath/data/archives/$arch_name.comments.arch")) { $error = "Can not copy comments.txt from data/ to data/archives"; }
$handle = fopen("$cutepath/data/news.txt","w") or $error = "Can not open news.txt"; $handle = fopen("$cutepath/data/news.txt","w") or $error = "Can not open news.txt";
fclose($handle); fclose($handle);
$handle = fopen("$cutepath/data/comments.txt","w") or $error = "Can not open comments.txt"; $handle = fopen("$cutepath/data/comments.txt","w") or $error = "Can not open comments.txt";
fclose($handle); fclose($handle);
$fp = @fopen("$cutepath/data/auto_archive.db.php", "w"); $fp = @fopen("$cutepath/data/auto_archive.db.php", "w");
@flock ($fp,2); @flock ($fp,2);
if(!$errors){ fwrite($fp, $now[year]."|".$now[month]."\n"); } if(!$errors){ fwrite($fp, $now[year]."|".$now[month]."\n"); }
else{ fwrite($fp, "0|0|$error\n"); } else{ fwrite($fp, "0|0|$error\n"); }
foreach($db_content as $line){ foreach($db_content as $line){
@fwrite($fp, $line); @fwrite($fp, $line);
} }
@flock ($fp,3); @flock ($fp,3);
@fclose($fp); @fclose($fp);
if($config_notify_archive == "yes" and $config_notify_status == "active"){ if($config_notify_archive == "yes" and $config_notify_status == "active"){
send_mail("$config_notify_email", "CuteNews - AutoArchive was Performed", "CuteNews has performed the AutoArchive function.\n$count_news News Articles were archived.\n$error"); send_mail("$config_notify_email", "CuteNews - AutoArchive was Performed", "CuteNews has performed the AutoArchive function.\n$count_news News Articles were archived.\n$error");
} }
} }
} }
} }
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: ResynchronizePostponed // Function: ResynchronizePostponed
// Description: Refreshes the Postponed News file. // Description: Refreshes the Postponed News file.
function ResynchronizePostponed(){ function ResynchronizePostponed(){
global $cutepath,$config_notify_postponed,$config_notify_status,$config_notify_email; global $cutepath,$config_notify_postponed,$config_notify_status,$config_notify_email;
$all_postponed_db = file("$cutepath/data/postponed_news.txt"); $all_postponed_db = file("$cutepath/data/postponed_news.txt");
if(!empty($all_postponed_db)){ if(!empty($all_postponed_db)){
$new_postponed_db = fopen("$cutepath/data/postponed_news.txt", w); $new_postponed_db = fopen("$cutepath/data/postponed_news.txt", w);
@flock ($new_postponed_db,2); @flock ($new_postponed_db,2);
$now_date = time(); $now_date = time();
foreach ($all_postponed_db as $p_line){ foreach ($all_postponed_db as $p_line){
$p_item_db = explode("|",$p_line); $p_item_db = explode("|",$p_line);
if($p_item_db[0] <= $now_date){ if($p_item_db[0] <= $now_date){
// Item is old and must be Activated, add it to news.txt // Item is old and must be Activated, add it to news.txt
$all_active_db = file("$cutepath/data/news.txt"); $all_active_db = file("$cutepath/data/news.txt");
$active_news_file = fopen("$cutepath/data/news.txt", "w"); $active_news_file = fopen("$cutepath/data/news.txt", "w");
@flock ($active_news_file,2); @flock ($active_news_file,2);
fwrite($active_news_file,"$p_line"); fwrite($active_news_file,"$p_line");
foreach ($all_active_db as $active_line){ fwrite($active_news_file, "$active_line");} foreach ($all_active_db as $active_line){ fwrite($active_news_file, "$active_line");}
@flock ($active_news_file,3); @flock ($active_news_file,3);
fclose($active_news_file); fclose($active_news_file);
if($config_notify_postponed == "yes" and $config_notify_status == "active"){ if($config_notify_postponed == "yes" and $config_notify_status == "active"){
send_mail("$config_notify_email", "CuteNews - Postponed article was Activated", "CuteNews has activated the article '$p_item_db[2]'"); send_mail("$config_notify_email", "CuteNews - Postponed article was Activated", "CuteNews has activated the article '$p_item_db[2]'");
} }
}else{ }else{
// Item is still postponed // Item is still postponed
fwrite($new_postponed_db,"$p_line"); fwrite($new_postponed_db,"$p_line");
} }
} }
@flock ($new_postponed_db,3); @flock ($new_postponed_db,3);
fclose($new_postponed_db); fclose($new_postponed_db);
} }
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: send_mail // Function: send_mail
// Description: sends mail ... huh :) // Description: sends mail ... huh :)
function send_mail($to, $subject, $message){ function send_mail($to, $subject, $message){
if(!isset($to) or !$to or $to == ''){ }else{ if(!isset($to) or !$to or $to == ''){ }else{
$tos = FALSE; $tos = FALSE;
$to = str_replace(' ', '', $to); $to = str_replace(' ', '', $to);
if(eregi(',', '')){ if(eregi(',', '')){
$tos = explode(',', $to); $tos = explode(',', $to);
} }
$from = 'CuteNews@' . $_SERVER['SERVER_NAME']; $from = 'CuteNews@' . $_SERVER['SERVER_NAME'];
$headers = ''; $headers = '';
$headers .= "From: $from\n"; $headers .= "From: $from\n";
$headers .= "Reply-to: $from\n"; $headers .= "Reply-to: $from\n";
$headers .= "Return-Path: $from\n"; $headers .= "Return-Path: $from\n";
$headers .= "Message-ID: <" . md5(uniqid(time())) . "@" . $_SERVER['SERVER_NAME'] . ">\n"; $headers .= "Message-ID: <" . md5(uniqid(time())) . "@" . $_SERVER['SERVER_NAME'] . ">\n";
$headers .= "MIME-Version: 1.0\n"; $headers .= "MIME-Version: 1.0\n";
$headers .= "Content-type: text/plain;\n"; $headers .= "Content-type: text/plain;\n";
$headers .= "Date: " . date('r', time()) . "\n"; $headers .= "Date: " . date('r', time()) . "\n";
if($tos){ if($tos){
foreach($tos as $my_to){ foreach($tos as $my_to){
@mail($my_to,$subject,$message,$headers); @mail($my_to,$subject,$message,$headers);
} }
}else{ @mail($to,$subject,$message,$headers); } }else{ @mail($to,$subject,$message,$headers); }
} }
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: formatsize // Function: formatsize
// Description: Format the size of given file // Description: Format the size of given file
function formatsize($file_size){ function formatsize($file_size){
if($file_size >= 1073741824) if($file_size >= 1073741824)
{$file_size = round($file_size / 1073741824 * 100) / 100 . "Gb";} {$file_size = round($file_size / 1073741824 * 100) / 100 . "Gb";}
elseif($file_size >= 1048576) elseif($file_size >= 1048576)
{$file_size = round($file_size / 1048576 * 100) / 100 . "Mb";} {$file_size = round($file_size / 1048576 * 100) / 100 . "Mb";}
elseif($file_size >= 1024) elseif($file_size >= 1024)
{$file_size = round($file_size / 1024 * 100) / 100 . "Kb";} {$file_size = round($file_size / 1024 * 100) / 100 . "Kb";}
else{$file_size = $file_size . "b";} else{$file_size = $file_size . "b";}
return $file_size; return $file_size;
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Class: microTimer // Class: microTimer
// Description: calculates the micro time // Description: calculates the micro time
class microTimer { class microTimer {
function start() { function start() {
global $starttime; global $starttime;
$mtime = microtime (); $mtime = microtime ();
$mtime = explode (' ', $mtime); $mtime = explode (' ', $mtime);
$mtime = $mtime[1] + $mtime[0]; $mtime = $mtime[1] + $mtime[0];
$starttime = $mtime; $starttime = $mtime;
} }
function stop() { function stop() {
global $starttime; global $starttime;
$mtime = microtime (); $mtime = microtime ();
$mtime = explode (' ', $mtime); $mtime = explode (' ', $mtime);
$mtime = $mtime[1] + $mtime[0]; $mtime = $mtime[1] + $mtime[0];
$endtime = $mtime; $endtime = $mtime;
$totaltime = round (($endtime - $starttime), 5); $totaltime = round (($endtime - $starttime), 5);
return $totaltime; return $totaltime;
} }
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: check_login // Function: check_login
// Description: Check login information // Description: Check login information
function check_login($username, $md5_password){ function check_login($username, $md5_password){
$result = FALSE; $result = FALSE;
$full_member_db = file("./data/users.db.php"); $full_member_db = file("./data/users.db.php");
global $member_db; global $member_db;
foreach($full_member_db as $member_db_line) foreach($full_member_db as $member_db_line)
{ {
if(!eregi("<\?",$member_db_line)){ if(!eregi("<\?",$member_db_line)){
$member_db = explode("|",$member_db_line); $member_db = explode("|",$member_db_line);
if(strtolower($member_db[2]) == strtolower($username) && $member_db[3] == $md5_password) if(strtolower($member_db[2]) == strtolower($username) && $member_db[3] == $md5_password)
{ {
$result = TRUE; $result = TRUE;
break; break;
} }
} }
} }
return $result; return $result;
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: cute_query_string // Function: cute_query_string
// Description: Format the Query_String for CuteNews purpuses index.php? // Description: Format the Query_String for CuteNews purpuses index.php?
function cute_query_string($q_string, $strips, $type="get"){ function cute_query_string($q_string, $strips, $type="get"){
foreach($strips as $key){ foreach($strips as $key){
$strips[$key] = TRUE; $strips[$key] = TRUE;
} }
$var_value = explode("&", $q_string); $var_value = explode("&", $q_string);
foreach($var_value as $var_peace){ foreach($var_value as $var_peace){
$parts = explode("=", $var_peace); $parts = explode("=", $var_peace);
if($strips[$parts[0]] != TRUE and $parts[0] != ""){ if($strips[$parts[0]] != TRUE and $parts[0] != ""){
if($type == "post"){ if($type == "post"){
$my_q .= "<input type=\"hidden\" name=\"".@htmlspecialchars($parts[0])."\" value=\"".@htmlspecialchars($parts[1])."\" />\n"; $my_q .= "<input type=\"hidden\" name=\"".@htmlspecialchars($parts[0])."\" value=\"".@htmlspecialchars($parts[1])."\" />\n";
}else{ }else{
$my_q .= "$var_peace&amp;"; $my_q .= "$var_peace&amp;";
} }
} }
} }
if( substr($my_q, -5) == "&amp;" ){ $my_q = substr($my_q, 0, -5); } if( substr($my_q, -5) == "&amp;" ){ $my_q = substr($my_q, 0, -5); }
return $my_q; return $my_q;
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: Flooder // Function: Flooder
// Description: Flood Protection Function // Description: Flood Protection Function
function flooder($ip, $comid){ function flooder($ip, $comid){
global $cutepath, $config_flood_time; global $cutepath, $config_flood_time;
$old_db = file("$cutepath/data/flood.db.php"); $old_db = file("$cutepath/data/flood.db.php");
$new_db = fopen("$cutepath/data/flood.db.php", w); $new_db = fopen("$cutepath/data/flood.db.php", w);
$result = FALSE; $result = FALSE;
foreach($old_db as $old_db_line){ foreach($old_db as $old_db_line){
$old_db_arr = explode("|", $old_db_line); $old_db_arr = explode("|", $old_db_line);
if(($old_db_arr[0] + $config_flood_time) > time() ){ if(($old_db_arr[0] + $config_flood_time) > time() ){
fwrite($new_db, $old_db_line); fwrite($new_db, $old_db_line);
if($old_db_arr[1] == $ip and $old_db_arr[2] == $comid) if($old_db_arr[1] == $ip and $old_db_arr[2] == $comid)
{ $result = TRUE; } { $result = TRUE; }
} }
} }
fclose($new_db); fclose($new_db);
return $result; return $result;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: msg // Function: msg
// Description: Displays message to user // Description: Displays message to user
function msg($type, $title, $text, $back=FALSE){ function msg($type, $title, $text, $back=FALSE){
echoheader($type, $title); echoheader($type, $title);
global $lang; global $lang;
echo"<table border=0 cellpading=0 cellspacing=0 width=100% height=100%><tr><td >$text"; echo"<table border=0 cellpading=0 cellspacing=0 width=100% height=100%><tr><td >$text";
if($back){ if($back){
echo"<br /><br> <a href=\"$back\">go back</a>"; echo"<br /><br> <a href=\"$back\">go back</a>";
} }
echo"</td></tr></table>"; echo"</td></tr></table>";
echofooter(); echofooter();
exit(); exit();
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: echoheader // Function: echoheader
// Description: Displays header skin // Description: Displays header skin
function echoheader($image, $header_text){ function echoheader($image, $header_text){
global $PHP_SELF, $is_loged_in, $config_skin, $skin_header, $lang_content_type, $skin_menu, $skin_prefix, $config_version_name; global $PHP_SELF, $is_loged_in, $config_skin, $skin_header, $lang_content_type, $skin_menu, $skin_prefix, $config_version_name;
if($is_loged_in == TRUE){ $skin_header = preg_replace("/{menu}/", "$skin_menu", "$skin_header"); } if($is_loged_in == TRUE){ $skin_header = preg_replace("/{menu}/", "$skin_menu", "$skin_header"); }
else { $skin_header = preg_replace("/{menu}/", " &nbsp; $config_version_name", "$skin_header"); } else { $skin_header = preg_replace("/{menu}/", " &nbsp; $config_version_name", "$skin_header"); }
$skin_header = get_skin($skin_header); $skin_header = get_skin($skin_header);
$skin_header = preg_replace("/{image-name}/", "${skin_prefix}${image}", $skin_header); $skin_header = preg_replace("/{image-name}/", "${skin_prefix}${image}", $skin_header);
$skin_header = preg_replace("/{header-text}/", $header_text, $skin_header); $skin_header = preg_replace("/{header-text}/", $header_text, $skin_header);
$skin_header = preg_replace("/{content-type}/", $lang_content_type, $skin_header); $skin_header = preg_replace("/{content-type}/", $lang_content_type, $skin_header);
echo $skin_header; echo $skin_header;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: echofooter // Function: echofooter
// Description: Displays footer skin // Description: Displays footer skin
function echofooter(){ function echofooter(){
global $PHP_SELF, $is_loged_in, $config_skin, $skin_footer, $lang_content_type, $skin_menu, $skin_prefix, $config_version_name; global $PHP_SELF, $is_loged_in, $config_skin, $skin_footer, $lang_content_type, $skin_menu, $skin_prefix, $config_version_name;
if($is_loged_in == TRUE){ $skin_footer = preg_replace("/{menu}/", "$skin_menu", "$skin_footer"); } if($is_loged_in == TRUE){ $skin_footer = preg_replace("/{menu}/", "$skin_menu", "$skin_footer"); }
else { $skin_footer = preg_replace("/{menu}/", " &nbsp; $config_version_name", "$skin_footer"); } else { $skin_footer = preg_replace("/{menu}/", " &nbsp; $config_version_name", "$skin_footer"); }
$skin_footer = get_skin($skin_footer); $skin_footer = get_skin($skin_footer);
$skin_footer = preg_replace("/{image-name}/", "${skin_prefix}${image}", $skin_footer); $skin_footer = preg_replace("/{image-name}/", "${skin_prefix}${image}", $skin_footer);
$skin_footer = preg_replace("/{header-text}/", $header_text, $skin_footer); $skin_footer = preg_replace("/{header-text}/", $header_text, $skin_footer);
$skin_footer = preg_replace("/{content-type}/", $lang_content_type, $skin_footer); $skin_footer = preg_replace("/{content-type}/", $lang_content_type, $skin_footer);
// Do not remove the Copyrights! // Do not remove the Copyrights!
echo $skin_footer; echo $skin_footer;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: b64dck // Function: b64dck
// Description: And the duck fly away. // Description: And the duck fly away.
function b64dck(){ function b64dck(){
$cr = bd_config('e2NvcHlyaWdodHN9');$shder = bd_config('c2tpbl9oZWFkZXI=');$sfter = bd_config('c2tpbl9mb290ZXI='); $cr = bd_config('e2NvcHlyaWdodHN9');$shder = bd_config('c2tpbl9oZWFkZXI=');$sfter = bd_config('c2tpbl9mb290ZXI=');
global $$shder,$$sfter; global $$shder,$$sfter;
$HDpnlty = bd_config('PGNlbnRlcj48aDE+Q3V0ZU5ld3M8L2gxPjxhIGhyZWY9Imh0dHA6Ly9jdXRlcGhwLmNvbSI+Q3V0ZVBIUC5jb208L2E+PC9jZW50ZXI+PGJyPg=='); $HDpnlty = bd_config('PGNlbnRlcj48aDE+Q3V0ZU5ld3M8L2gxPjxhIGhyZWY9Imh0dHA6Ly9jdXRlcGhwLmNvbSI+Q3V0ZVBIUC5jb208L2E+PC9jZW50ZXI+PGJyPg==');
$FTpnlty = bd_config('PGNlbnRlcj48ZGl2IGRpc3BsYXk9aW5saW5lIHN0eWxlPVwnZm9udC1zaXplOiAxMXB4XCc+UG93ZXJlZCBieSA8YSBzdHlsZT1cJ2ZvbnQtc2l6ZTogMTFweFwnIGhyZWY9XCJodHRwOi8vY3V0ZXBocC5jb20vY3V0ZW5ld3MvXCIgdGFyZ2V0PV9ibGFuaz5DdXRlTmV3czwvYT4gqSAyMDA1ICA8YSBzdHlsZT1cJ2ZvbnQtc2l6ZTogMTFweFwnIGhyZWY9XCJodHRwOi8vY3V0ZXBocC5jb20vXCIgdGFyZ2V0PV9ibGFuaz5DdXRlUEhQPC9hPi48L2Rpdj48L2NlbnRlcj4='); $FTpnlty = bd_config('PGNlbnRlcj48ZGl2IGRpc3BsYXk9aW5saW5lIHN0eWxlPVwnZm9udC1zaXplOiAxMXB4XCc+UG93ZXJlZCBieSA8YSBzdHlsZT1cJ2ZvbnQtc2l6ZTogMTFweFwnIGhyZWY9XCJodHRwOi8vY3V0ZXBocC5jb20vY3V0ZW5ld3MvXCIgdGFyZ2V0PV9ibGFuaz5DdXRlTmV3czwvYT4gqSAyMDA1ICA8YSBzdHlsZT1cJ2ZvbnQtc2l6ZTogMTFweFwnIGhyZWY9XCJodHRwOi8vY3V0ZXBocC5jb20vXCIgdGFyZ2V0PV9ibGFuaz5DdXRlUEhQPC9hPi48L2Rpdj48L2NlbnRlcj4=');
if(!stristr($$shder,$cr) and !stristr($$sfter,$cr)){ $$shder = $HDpnlty.$$shder; $$sfter = $$sfter.$FTpnlty; } if(!stristr($$shder,$cr) and !stristr($$sfter,$cr)){ $$shder = $HDpnlty.$$shder; $$sfter = $$sfter.$FTpnlty; }
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: CountComments // Function: CountComments
// Description: Count How Many Comments Have a Specific Article // Description: Count How Many Comments Have a Specific Article
function CountComments($id, $archive = FALSE){ function CountComments($id, $archive = FALSE){
global $cutepath; global $cutepath;
if($cutepath == ""){ $cutepath = "."; } if($cutepath == ""){ $cutepath = "."; }
$result = "0"; $result = "0";
if($archive and ($archive != "postponed" and $archive != "unapproved")){ $all_comments = file("$cutepath/data/archives/${archive}.comments.arch"); } if($archive and ($archive != "postponed" and $archive != "unapproved")){ $all_comments = file("$cutepath/data/archives/${archive}.comments.arch"); }
else{ $all_comments = file("$cutepath/data/comments.txt"); } else{ $all_comments = file("$cutepath/data/comments.txt"); }
foreach($all_comments as $comment_line) foreach($all_comments as $comment_line)
{ {
$comment_arr_1 = explode("|>|", $comment_line); $comment_arr_1 = explode("|>|", $comment_line);
if($comment_arr_1[0] == $id) if($comment_arr_1[0] == $id)
{ {
$comment_arr_2 = explode("||", $comment_arr_1[1]); $comment_arr_2 = explode("||", $comment_arr_1[1]);
$result = count($comment_arr_2)-1; $result = count($comment_arr_2)-1;
} }
} }
return $result; return $result;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: insertSmilies // Function: insertSmilies
// Description: insert smilies for adding into news/comments // Description: insert smilies for adding into news/comments
function insertSmilies($insert_location, $break_location = FALSE, $admincp = FALSE, $wysiwyg = FALSE) function insertSmilies($insert_location, $break_location = FALSE, $admincp = FALSE, $wysiwyg = FALSE)
{ {
global $config_http_script_dir, $config_smilies; global $config_http_script_dir, $config_smilies;
$smilies = explode(",", $config_smilies); $smilies = explode(",", $config_smilies);
foreach($smilies as $smile) foreach($smilies as $smile)
{ {
$i++; $smile = trim($smile); $i++; $smile = trim($smile);
if($admincp){ if($admincp){
if($wysiwyg){ if($wysiwyg){
// $advanced_smile = "&lt;img alt=\':$smile:\' src=\'data/emoticons/$smile.gif\' /&gt;"; // $advanced_smile = "&lt;img alt=\':$smile:\' src=\'data/emoticons/$smile.gif\' /&gt;";
// $output .= "<a href=# onclick=\"javascript:InsertIntoArea('$insert_location','$advanced_smile'); return false;\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>"; // $output .= "<a href=# onclick=\"javascript:InsertIntoArea('$insert_location','$advanced_smile'); return false;\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>";
$output .= "<a href=# onclick=\"document.getElementById('$insert_location').contentWindow.document.execCommand('InsertImage', false, '$config_http_script_dir/data/emoticons/$smile.gif'); return false;\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>"; $output .= "<a href=# onclick=\"document.getElementById('$insert_location').contentWindow.document.execCommand('InsertImage', false, '$config_http_script_dir/data/emoticons/$smile.gif'); return false;\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>";
} }
else{ $output .= "<a href=# onclick=\"javascript:document.getElementById('$insert_location').value += ' :$smile:'; return false;\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>"; } else{ $output .= "<a href=# onclick=\"javascript:document.getElementById('$insert_location').value += ' :$smile:'; return false;\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>"; }
}else{ }else{
$output .= "<a href=\"javascript:insertext(':$smile:','$insert_location')\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>"; $output .= "<a href=\"javascript:insertext(':$smile:','$insert_location')\"><img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" /></a>";
}; };
if( isset($break_location) && (int)$break_location > 0 && $i%$break_location == 0 ) if( isset($break_location) && (int)$break_location > 0 && $i%$break_location == 0 )
{ {
$output .= "<br />"; $output .= "<br />";
}else{ $output .= "&nbsp;"; } }else{ $output .= "&nbsp;"; }
} }
return $output; return $output;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: replace_comments // Function: replace_comments
// Description: Replaces comments charactars // Description: Replaces comments charactars
function replace_comment($way, $sourse){ function replace_comment($way, $sourse){
global $HTML_SPECIAL_CHARS, $config_allow_html_in_news, $config_allow_html_in_comments, $config_http_script_dir, $config_smilies; global $HTML_SPECIAL_CHARS, $config_allow_html_in_news, $config_allow_html_in_comments, $config_http_script_dir, $config_smilies;
$sourse = stripslashes(trim($sourse)); $sourse = stripslashes(trim($sourse));
if($way == "add"){ if($way == "add"){
$find = array( $find = array(
"'\"'", "'\"'",
"'\''", "'\''",
"'<'", "'<'",
"'>'", "'>'",
"'\|'", "'\|'",
"'\n'", "'\n'",
"'\r'", "'\r'",
); );
$replace = array( $replace = array(
"&quot;", "&quot;",
"&#039;", "&#039;",
"&lt;", "&lt;",
"&gt;", "&gt;",
"&#124;", "&#124;",
" <br />", " <br />",
"", "",
); );
} }
elseif($way == "show"){ elseif($way == "show"){
$find = array( $find = array(
"'\[b\](.*?)\[/b\]'i", "'\[b\](.*?)\[/b\]'i",
"'\[i\](.*?)\[/i\]'i", "'\[i\](.*?)\[/i\]'i",
"'\[u\](.*?)\[/u\]'i", "'\[u\](.*?)\[/u\]'i",
"'\[link\](.*?)\[/link\]'i", "'\[link\](.*?)\[/link\]'i",
"'\[link=(.*?)\](.*?)\[/link\]'i", "'\[link=(.*?)\](.*?)\[/link\]'i",
"'\[quote=(.*?)\](.*?)\[/quote\]'", "'\[quote=(.*?)\](.*?)\[/quote\]'",
"'\[quote\](.*?)\[/quote\]'", "'\[quote\](.*?)\[/quote\]'",
); );
$replace = array( $replace = array(
"<strong>\\1</strong>", "<strong>\\1</strong>",
"<em>\\1</em>", "<em>\\1</em>",
"<span style=\"text-decoration: underline;\">\\1</span>", "<span style=\"text-decoration: underline;\">\\1</span>",
"<a href=\"\\1\">\\1</a>", "<a href=\"\\1\">\\1</a>",
"<a href=\"\\1\">\\2</a>", "<a href=\"\\1\">\\2</a>",
"<blockquote><div style=\"font-size: 13px;\">quote (\\1):</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\2</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>", "<blockquote><div style=\"font-size: 13px;\">quote (\\1):</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\2</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>",
"<blockquote><div style=\"font-size: 13px;\">quote:</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\1</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>", "<blockquote><div style=\"font-size: 13px;\">quote:</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\1</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>",
); );
$smilies_arr = explode(",", $config_smilies); $smilies_arr = explode(",", $config_smilies);
foreach($smilies_arr as $smile){ foreach($smilies_arr as $smile){
$smile = trim($smile); $smile = trim($smile);
$find[] = "':$smile:'"; $find[] = "':$smile:'";
$replace[] = "<img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" />"; $replace[] = "<img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" />";
} }
} }
$sourse = preg_replace($find,$replace,$sourse); $sourse = preg_replace($find,$replace,$sourse);
foreach ( $HTML_SPECIAL_CHARS as $key=>$value ){ foreach ( $HTML_SPECIAL_CHARS as $key=>$value ){
$sourse = str_replace($key,$value,$sourse); $sourse = str_replace($key,$value,$sourse);
} }
return $sourse; return $sourse;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: rteSafe // Function: rteSafe
// Description: safe data for the RTE // Description: safe data for the RTE
function rteSafe($strText) { function rteSafe($strText) {
//returns safe code for preloading in the RTE //returns safe code for preloading in the RTE
$tmpString = $strText; $tmpString = $strText;
//convert all types of single quotes //convert all types of single quotes
$tmpString = str_replace(chr(145), chr(39), $tmpString); $tmpString = str_replace(chr(145), chr(39), $tmpString);
$tmpString = str_replace(chr(146), chr(39), $tmpString); $tmpString = str_replace(chr(146), chr(39), $tmpString);
$tmpString = str_replace("'", "&#39;", $tmpString); $tmpString = str_replace("'", "&#39;", $tmpString);
//convert all types of double quotes //convert all types of double quotes
$tmpString = str_replace(chr(147), chr(34), $tmpString); $tmpString = str_replace(chr(147), chr(34), $tmpString);
$tmpString = str_replace(chr(148), chr(34), $tmpString); $tmpString = str_replace(chr(148), chr(34), $tmpString);
// $tmpString = str_replace("\"", "&quot;", $tmpString); // we are pasting the content within '' quotes so " are valid // $tmpString = str_replace("\"", "&quot;", $tmpString); // we are pasting the content within '' quotes so " are valid
//replace carriage returns & line feeds //replace carriage returns & line feeds
$tmpString = str_replace(chr(10), " ", $tmpString); $tmpString = str_replace(chr(10), " ", $tmpString);
$tmpString = str_replace(chr(13), " ", $tmpString); $tmpString = str_replace(chr(13), " ", $tmpString);
return $tmpString; return $tmpString;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: get_skin // Function: get_skin
// Description: Hello skin! // Description: Hello skin!
function get_skin($skin){ function get_skin($skin){
if(!file_exists('./data/reg.php')){ $stts = base64_decode('KHVucmVnaXN0ZXJlZCk='); } if(!file_exists('./data/reg.php')){ $stts = base64_decode('KHVucmVnaXN0ZXJlZCk='); }
else{ else{
include('./data/reg.php'); include('./data/reg.php');
if(preg_match('/\\A(\\w{6})-\\w{6}-\\w{6}\\z/', $reg_site_key, $mmbrid)){ if(preg_match('/\\A(\\w{6})-\\w{6}-\\w{6}\\z/', $reg_site_key, $mmbrid)){
if(!isset($reg_display_name) or !$reg_display_name or $reg_display_name == ''){ if(!isset($reg_display_name) or !$reg_display_name or $reg_display_name == ''){
$stts = "<!-- (-$mmbrid[1]-) -->"; $stts = "<!-- (-$mmbrid[1]-) -->";
}else{ }else{
$stts = "<label title='(-$mmbrid[1]-)'>". base64_decode('TGljZW5zZWQgdG86IA==').$reg_display_name.'</label>'; $stts = "<label title='(-$mmbrid[1]-)'>". base64_decode('TGljZW5zZWQgdG86IA==').$reg_display_name.'</label>';
} }
} }
else{ $stts = '!'.base64_decode('KHVucmVnaXN0ZXJlZCk=').'!'; } else{ $stts = '!'.base64_decode('KHVucmVnaXN0ZXJlZCk=').'!'; }
} }
$msn = bd_config('c2tpbg=='); $msn = bd_config('c2tpbg==');
$cr = bd_config('e2NvcHlyaWdodHN9'); $cr = bd_config('e2NvcHlyaWdodHN9');
$lct = bd_config('PGRpdiBzdHlsZT0nZm9udC1zaXplOiA5cHgnPlBvd2VyZWQgYnkgPGEgc3R5bGU9J2ZvbnQtc2l6ZTogOXB4JyBocmVmPSJodHRwOi8vY3V0ZXBocC5jb20vY3V0ZW5ld3MvIiB0YXJnZXQ9Il9ibGFuayI+Q3V0ZU5ld3MgMS40LjY8L2E+ICZjb3B5OyAyMDA4IDxhIHN0eWxlPSdmb250LXNpemU6IDlweCcgaHJlZj0iaHR0cDovL2N1dGVwaHAuY29tLyIgdGFyZ2V0PSJfYmxhbmsiPkN1dGVQSFA8L2E+Ljxicj57bC1zdGF0dXN9PC9kaXY+'); $lct = bd_config('PGRpdiBzdHlsZT0nZm9udC1zaXplOiA5cHgnPlBvd2VyZWQgYnkgPGEgc3R5bGU9J2ZvbnQtc2l6ZTogOXB4JyBocmVmPSJodHRwOi8vY3V0ZXBocC5jb20vY3V0ZW5ld3MvIiB0YXJnZXQ9Il9ibGFuayI+Q3V0ZU5ld3MgMS40LjY8L2E+ICZjb3B5OyAyMDA4IDxhIHN0eWxlPSdmb250LXNpemU6IDlweCcgaHJlZj0iaHR0cDovL2N1dGVwaHAuY29tLyIgdGFyZ2V0PSJfYmxhbmsiPkN1dGVQSFA8L2E+Ljxicj57bC1zdGF0dXN9PC9kaXY+');
$lct = preg_replace("/{l-status}/", $stts, $lct); $lct = preg_replace("/{l-status}/", $stts, $lct);
$$msn = preg_replace("/$cr/", $lct, $$msn); $$msn = preg_replace("/$cr/", $lct, $$msn);
return $$msn; return $$msn;
} }
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Function: replace_news // Function: replace_news
// Description: Replaces news charactars // Description: Replaces news charactars
function replace_news($way, $sourse, $replce_n_to_br=TRUE, $use_html=TRUE){ function replace_news($way, $sourse, $replce_n_to_br=TRUE, $use_html=TRUE){
global $HTML_SPECIAL_CHARS, $config_allow_html_in_news, $config_allow_html_in_comments, $config_http_script_dir, $config_smilies; global $HTML_SPECIAL_CHARS, $config_allow_html_in_news, $config_allow_html_in_comments, $config_http_script_dir, $config_smilies;
$sourse = stripslashes($sourse); $sourse = stripslashes($sourse);
if($way == "show") if($way == "show")
{ {
$find= array( $find= array(
/* 1 */ "'\[upimage=([^\]]*?) ([^\]]*?)\]'i", /* 1 */ "'\[upimage=([^\]]*?) ([^\]]*?)\]'i",
/* 2 */ "'\[upimage=(.*?)\]'i", /* 2 */ "'\[upimage=(.*?)\]'i",
/* 3 */ "'\[b\](.*?)\[/b\]'i", /* 3 */ "'\[b\](.*?)\[/b\]'i",
/* 4 */ "'\[i\](.*?)\[/i\]'i", /* 4 */ "'\[i\](.*?)\[/i\]'i",
/* 5 */ "'\[u\](.*?)\[/u\]'i", /* 5 */ "'\[u\](.*?)\[/u\]'i",
/* 6 */ "'\[link\](.*?)\[/link\]'i", /* 6 */ "'\[link\](.*?)\[/link\]'i",
/* 7 */ "'\[color=(.*?)\](.*?)\[/color\]'i", /* 7 */ "'\[color=(.*?)\](.*?)\[/color\]'i",
/* 8 */ "'\[size=(.*?)\](.*?)\[/size\]'i", /* 8 */ "'\[size=(.*?)\](.*?)\[/size\]'i",
/* 9 */ "'\[font=(.*?)\](.*?)\[/font\]'i", /* 9 */ "'\[font=(.*?)\](.*?)\[/font\]'i",
/* 10 */ "'\[align=(.*?)\](.*?)\[/align\]'i", /* 10 */ "'\[align=(.*?)\](.*?)\[/align\]'i",
/* 12 */ "'\[image=(.*?)\]'i", /* 12 */ "'\[image=(.*?)\]'i",
/* 13 */ "'\[link=(.*?)\](.*?)\[/link\]'i", /* 13 */ "'\[link=(.*?)\](.*?)\[/link\]'i",
/* 14 */ "'\[quote=(.*?)\](.*?)\[/quote\]'i", /* 14 */ "'\[quote=(.*?)\](.*?)\[/quote\]'i",
/* 15 */ "'\[quote\](.*?)\[/quote\]'i", /* 15 */ "'\[quote\](.*?)\[/quote\]'i",
/* 16 */ "'\[list\]'i", /* 16 */ "'\[list\]'i",
/* 17 */ "'\[/list\]'i", /* 17 */ "'\[/list\]'i",
/* 18 */ "'\[\*\]'i", /* 18 */ "'\[\*\]'i",
"'{nl}'", "'{nl}'",
); );
$replace=array( $replace=array(
/* 1 */ "<img \\2 src=\"${config_http_script_dir}/skins/images/upskins/images/\\1\" style=\"border: none;\" alt=\"\" />", /* 1 */ "<img \\2 src=\"${config_http_script_dir}/skins/images/upskins/images/\\1\" style=\"border: none;\" alt=\"\" />",
/* 2 */ "<img src=\"${config_http_script_dir}/skins/images/upskins/images/\\1\" style=\"border: none;\" alt=\"\" />", /* 2 */ "<img src=\"${config_http_script_dir}/skins/images/upskins/images/\\1\" style=\"border: none;\" alt=\"\" />",
/* 3 */ "<strong>\\1</strong>", /* 3 */ "<strong>\\1</strong>",
/* 4 */ "<em>\\1</em>", /* 4 */ "<em>\\1</em>",
/* 5 */ "<span style=\"text-decoration: underline;\">\\1</span>", /* 5 */ "<span style=\"text-decoration: underline;\">\\1</span>",
/* 6 */ "<a href=\"\\1\">\\1</a>", /* 6 */ "<a href=\"\\1\">\\1</a>",
/* 7 */ "<span style=\"color: \\1;\">\\2</span>", /* 7 */ "<span style=\"color: \\1;\">\\2</span>",
/* 8 */ "<span style=\"font-size: \\1pt;\">\\2</span>", /* 8 */ "<span style=\"font-size: \\1pt;\">\\2</span>",
/* 9 */ "<span style=\"font-family: \\1;\">\\2</span>", /* 9 */ "<span style=\"font-family: \\1;\">\\2</span>",
/* 10 */ "<div style=\"text-align: \\1;\">\\2</div>", /* 10 */ "<div style=\"text-align: \\1;\">\\2</div>",
/* 12 */ "<img src=\"\\1\" style=\"border: none;\" alt=\"\" />", /* 12 */ "<img src=\"\\1\" style=\"border: none;\" alt=\"\" />",
/* 13 */ "<a href=\"\\1\">\\2</a>", /* 13 */ "<a href=\"\\1\">\\2</a>",
/* 14 */ "<blockquote><div style=\"font-size: 13px;\">quote (\\1):</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\2</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>", /* 14 */ "<blockquote><div style=\"font-size: 13px;\">quote (\\1):</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\2</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>",
/* 15 */ "<blockquote><div style=\"font-size: 13px;\">quote:</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\1</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>", /* 15 */ "<blockquote><div style=\"font-size: 13px;\">quote:</div><hr style=\"border: 1px solid #ACA899;\" /><div>\\1</div><hr style=\"border: 1px solid #ACA899;\" /></blockquote>",
/* 16 */ "<ul>", /* 16 */ "<ul>",
/* 17 */ "</ul>", /* 17 */ "</ul>",
/* 18 */ "<li>", /* 18 */ "<li>",
"\n", "\n",
); );
$smilies_arr = explode(",", $config_smilies); $smilies_arr = explode(",", $config_smilies);
foreach($smilies_arr as $smile){ foreach($smilies_arr as $smile){
$smile = trim($smile); $smile = trim($smile);
$find[] = "':$smile:'"; $find[] = "':$smile:'";
$replace[] = "<img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" />"; $replace[] = "<img style=\"border: none;\" alt=\"$smile\" src=\"$config_http_script_dir/data/emoticons/$smile.gif\" />";
} }
} }
elseif($way == "add"){ elseif($way == "add"){
$find = array( $find = array(
"'\|'", "'\|'",
"'\r'", "'\r'",
); );
$replace = array( $replace = array(
"&#124;", "&#124;",
"", "",
); );
if($use_html != TRUE){ if($use_html != TRUE){
$find[] = "'<'"; $find[] = "'<'";
$find[] = "'>'"; $find[] = "'>'";
$replace[] = "&lt;"; $replace[] = "&lt;";
$replace[] = "&gt;"; $replace[] = "&gt;";
} }
if($replce_n_to_br == TRUE){ if($replce_n_to_br == TRUE){
$find[] = "'\n'"; $find[] = "'\n'";
$replace[] = "<br />"; $replace[] = "<br />";
}else{ }else{
$find[] = "'\n'"; $find[] = "'\n'";
$replace[] = "{nl}"; $replace[] = "{nl}";
} }
} }
elseif($way == "admin"){ elseif($way == "admin"){
$find = array( $find = array(
"''", "''",
"'{nl}'", "'{nl}'",
); );
$replace = array( $replace = array(
"", "",
"\n", "\n",
); );
//this is for 'edit news' section when we use WYSIWYG //this is for 'edit news' section when we use WYSIWYG
if(!$replce_n_to_br){$find[] = "'<br />'"; } if(!$replce_n_to_br){$find[] = "'<br />'"; }
if(!$replce_n_to_br){$replace[] = "\n"; } if(!$replce_n_to_br){$replace[] = "\n"; }
} }
$sourse = preg_replace($find,$replace,$sourse); $sourse = preg_replace($find,$replace,$sourse);
foreach ( $HTML_SPECIAL_CHARS as $key=>$value ){ foreach ( $HTML_SPECIAL_CHARS as $key=>$value ){
$sourse = str_replace($key,$value,$sourse); $sourse = str_replace($key,$value,$sourse);
} }
return $sourse; return $sourse;
} }
function bd_config($str){ function bd_config($str){
return base64_decode($str); return base64_decode($str);
} }
?> ?>
<?PHP <?PHP
do{ // Used if we want to display some error to the user and halt the rest of the script do{ // Used if we want to display some error to the user and halt the rest of the script
$user_query = cute_query_string($QUERY_STRING, array( "comm_start_from","start_from", "archive", "subaction", "id", "ucat")); $user_query = cute_query_string($QUERY_STRING, array( "comm_start_from","start_from", "archive", "subaction", "id", "ucat"));
$user_post_query = cute_query_string($QUERY_STRING, array( "comm_start_from", "start_from", "archive", "subaction", "id", "ucat"), "post"); $user_post_query = cute_query_string($QUERY_STRING, array( "comm_start_from", "start_from", "archive", "subaction", "id", "ucat"), "post");
//#################################################################################################################### //####################################################################################################################
// Define Categories // Define Categories
//#################################################################################################################### //####################################################################################################################
$cat_lines = file("$cutepath/data/category.db.php"); $cat_lines = file("$cutepath/data/category.db.php");
foreach($cat_lines as $single_line){ foreach($cat_lines as $single_line){
$cat_arr = explode("|", $single_line); $cat_arr = explode("|", $single_line);
$cat[$cat_arr[0]] = $cat_arr[1]; $cat[$cat_arr[0]] = $cat_arr[1];
$cat_icon[$cat_arr[0]]=$cat_arr[2]; $cat_icon[$cat_arr[0]]=$cat_arr[2];
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// Function: Category ID to Name // Function: Category ID to Name
// Description: convert to category name from ID // Description: convert to category name from ID
if ( !function_exists('catid2name') ) if ( !function_exists('catid2name') )
{ {
function catid2name($thecat){ function catid2name($thecat){
global $cat; global $cat;
if(strstr($thecat,',')){ if(strstr($thecat,',')){
$thecat_arr = explode(',',$thecat); $thecat_arr = explode(',',$thecat);
foreach($thecat_arr as $single_thecat){ foreach($thecat_arr as $single_thecat){
if($thecat_not_first){ $thecat_str .= ', '. $cat[$single_thecat]; } if($thecat_not_first){ $thecat_str .= ', '. $cat[$single_thecat]; }
else{ $thecat_str .= $cat[$single_thecat]; } else{ $thecat_str .= $cat[$single_thecat]; }
$thecat_not_first = TRUE; $thecat_not_first = TRUE;
} }
return $thecat_str; return $thecat_str;
}else{ }else{
return $cat[$thecat]; return $cat[$thecat];
} }
} }
} }
//#################################################################################################################### //####################################################################################################################
// Define Users // Define Users
//#################################################################################################################### //####################################################################################################################
$all_users = file("$cutepath/data/users.db.php"); $all_users = file("$cutepath/data/users.db.php");
foreach($all_users as $user) foreach($all_users as $user)
{ {
if(!eregi("<\?",$member_db_line)){ if(!eregi("<\?",$member_db_line)){
$user_arr = explode("|",$user); $user_arr = explode("|",$user);
if($user_arr[4] != "") if($user_arr[4] != "")
{ {
if($user_arr[7] != 1 and $user_arr[5] != ""){ $my_names[$user_arr[2]] = "<a href=\"mailto:$user_arr[5]\">$user_arr[4]</a>"; } if($user_arr[7] != 1 and $user_arr[5] != ""){ $my_names[$user_arr[2]] = "<a href=\"mailto:$user_arr[5]\">$user_arr[4]</a>"; }
else{ $my_names[$user_arr[2]] = "$user_arr[4]"; } else{ $my_names[$user_arr[2]] = "$user_arr[4]"; }
$name_to_nick[$user_arr[2]] = $user_arr[4]; $name_to_nick[$user_arr[2]] = $user_arr[4];
} }
else else
{ {
if($user_arr[7] != 1 and $user_arr[5] != ""){ $my_names[$user_arr[2]] = "<a href=\"mailto:$user_arr[5]\">$user_arr[2]</a>"; } if($user_arr[7] != 1 and $user_arr[5] != ""){ $my_names[$user_arr[2]] = "<a href=\"mailto:$user_arr[5]\">$user_arr[2]</a>"; }
else{ $my_names[$user_arr[2]] = "$user_arr[2]"; } else{ $my_names[$user_arr[2]] = "$user_arr[2]"; }
$name_to_nick[$user_arr[2]] = $user_arr[2]; $name_to_nick[$user_arr[2]] = $user_arr[2];
} }
if($user_arr[7] != 1){ $my_mails[$user_arr[2]] = $user_arr[5]; } if($user_arr[7] != 1){ $my_mails[$user_arr[2]] = $user_arr[5]; }
else{ $my_mails[$user_arr[2]] = ""; } else{ $my_mails[$user_arr[2]] = ""; }
$my_passwords[$user_arr[2]] = $user_arr[3]; $my_passwords[$user_arr[2]] = $user_arr[3];
$my_users[] = $user_arr[2]; $my_users[] = $user_arr[2];
} }
} }
//#################################################################################################################### //####################################################################################################################
// Activate Postponed Articles // Activate Postponed Articles
//#################################################################################################################### //####################################################################################################################
ResynchronizePostponed(); ResynchronizePostponed();
//#################################################################################################################### //####################################################################################################################
// Auto-Archive Function // Auto-Archive Function
//#################################################################################################################### //####################################################################################################################
if($config_auto_archive == "yes"){ if($config_auto_archive == "yes"){
ResynchronizeAutoArchive(); ResynchronizeAutoArchive();
} }
//#################################################################################################################### //####################################################################################################################
// Add Comment // Add Comment
//#################################################################################################################### //####################################################################################################################
if($allow_add_comment){ if($allow_add_comment){
$name = trim($name); $name = trim($name);
$mail = trim($mail); $mail = trim($mail);
$id = (int) $id; // Yes it's stupid how I didn't thought about this :/ $id = (int) $id; // Yes it's stupid how I didn't thought about this :/
//---------------------------------- //----------------------------------
// Check the lenght of comment, include name + mail // Check the lenght of comment, include name + mail
//---------------------------------- //----------------------------------
if( strlen($name) > 50 ){ if( strlen($name) > 50 ){
echo"<div style=\"text-align: center;\">Your name is too long!</div>"; echo"<div style=\"text-align: center;\">Your name is too long!</div>";
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
if( strlen($mail) > 50){ if( strlen($mail) > 50){
echo"<div style=\"text-align: center;\">Your e-mail is too long!</div>"; echo"<div style=\"text-align: center;\">Your e-mail is too long!</div>";
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
if( strlen($comments) > $config_comment_max_long and $config_comment_max_long != "" and $config_comment_max_long != "0"){ if( strlen($comments) > $config_comment_max_long and $config_comment_max_long != "" and $config_comment_max_long != "0"){
echo"<div style=\"text-align: center;\">Your comment is too long!</div>"; echo"<div style=\"text-align: center;\">Your comment is too long!</div>";
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
//---------------------------------- //----------------------------------
// Get the IP // Get the IP
//---------------------------------- //----------------------------------
$foundip = TRUE; $foundip = TRUE;
if (getenv("HTTP_CLIENT_IP")) $ip = getenv("HTTP_CLIENT_IP"); if (getenv("HTTP_CLIENT_IP")) $ip = getenv("HTTP_CLIENT_IP");
else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR"); else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR");
else if(getenv("HTTP_X_FORWARDED_FOR")) $ip = getenv("HTTP_X_FORWARDED_FOR"); else if(getenv("HTTP_X_FORWARDED_FOR")) $ip = getenv("HTTP_X_FORWARDED_FOR");
else {$ip = "not detected"; $foundip = FALSE;} else {$ip = "not detected"; $foundip = FALSE;}
if( !$foundip or !preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", "$ip") ){ $ip = "not detected"; $foundip = FALSE;} //ensure that what we have is a real IP if( !$foundip or !preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", "$ip") ){ $ip = "not detected"; $foundip = FALSE;} //ensure that what we have is a real IP
//---------------------------------- //----------------------------------
// Flood Protection // Flood Protection
//---------------------------------- //----------------------------------
if($config_flood_time != 0 and $config_flood_time != "" ){ if($config_flood_time != 0 and $config_flood_time != "" ){
if(flooder($ip, $id) == TRUE ){ if(flooder($ip, $id) == TRUE ){
echo("<div style=\"text-align: center;\">Flood protection activated !!!<br />you have to wait $config_flood_time seconds after your last comment before posting again at this article.</div>"); echo("<div style=\"text-align: center;\">Flood protection activated !!!<br />you have to wait $config_flood_time seconds after your last comment before posting again at this article.</div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
} }
//---------------------------------- //----------------------------------
// Check if IP is blocked // Check if IP is blocked
//---------------------------------- //----------------------------------
$blockip = FALSE; $blockip = FALSE;
$old_ips = file("$cutepath/data/ipban.db.php"); $old_ips = file("$cutepath/data/ipban.db.php");
$new_ips = fopen("$cutepath/data/ipban.db.php", "w"); $new_ips = fopen("$cutepath/data/ipban.db.php", "w");
@flock ($new_ips,2); @flock ($new_ips,2);
foreach($old_ips as $old_ip_line){ foreach($old_ips as $old_ip_line){
$ip_arr = explode("|", $old_ip_line); $ip_arr = explode("|", $old_ip_line);
//implemented wildcard match //implemented wildcard match
$ip_check_matches = 0; $ip_check_matches = 0;
$db_ip_split = explode(".", $ip_arr[0]); $db_ip_split = explode(".", $ip_arr[0]);
$this_ip_split = explode(".", $ip); $this_ip_split = explode(".", $ip);
for($i_i=0;$i_i<4;$i_i++){ for($i_i=0;$i_i<4;$i_i++){
// echo"IF $this_ip_split[$i_i] == $db_ip_split[$i_i] or $db_ip_split[$i_i] == '*'<br>"; // echo"IF $this_ip_split[$i_i] == $db_ip_split[$i_i] or $db_ip_split[$i_i] == '*'<br>";
if ($this_ip_split[$i_i] == $db_ip_split[$i_i] or $db_ip_split[$i_i] == '*') { if ($this_ip_split[$i_i] == $db_ip_split[$i_i] or $db_ip_split[$i_i] == '*') {
$ip_check_matches += 1; $ip_check_matches += 1;
} }
} }
if ($ip_check_matches == 4) { if ($ip_check_matches == 4) {
$countblocks = $ip_arr[1] = $ip_arr[1] + 1; $countblocks = $ip_arr[1] = $ip_arr[1] + 1;
fwrite($new_ips, "$ip_arr[0]|$countblocks||\n"); $blockip = TRUE; fwrite($new_ips, "$ip_arr[0]|$countblocks||\n"); $blockip = TRUE;
} else { } else {
fwrite($new_ips, $old_ip_line); fwrite($new_ips, $old_ip_line);
} }
} }
@flock ($new_ips,3); @flock ($new_ips,3);
fclose($new_ips); fclose($new_ips);
if($blockip){ if($blockip){
echo("<div style=\"text-align: center;\">Sorry but you have been blocked from posting comments</div>"); echo("<div style=\"text-align: center;\">Sorry but you have been blocked from posting comments</div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
//---------------------------------- //----------------------------------
// Check if the name is protected // Check if the name is protected
//---------------------------------- //----------------------------------
$is_member = FALSE; $is_member = FALSE;
foreach($all_users as $member_db_line) foreach($all_users as $member_db_line)
{ {
if(!eregi("<\?",$member_db_line) and $member_db_line != ""){ if(!eregi("<\?",$member_db_line) and $member_db_line != ""){
$user_arr = explode("|",$member_db_line); $user_arr = explode("|",$member_db_line);
//if the name is protected //if the name is protected
if((strtolower($user_arr[2]) == strtolower($name) or strtolower($user_arr[4]) == strtolower($name)) and ($user_arr[3] != $CNpass and $user_arr[3] != md5($password)) and $name != "") if((strtolower($user_arr[2]) == strtolower($name) or strtolower($user_arr[4]) == strtolower($name)) and ($user_arr[3] != $CNpass and $user_arr[3] != md5($password)) and $name != "")
{ {
//$comments = replace_comment("add", $comments); //commented because will mess up the <br /> //$comments = replace_comment("add", $comments); //commented because will mess up the <br />
$comments = preg_replace(array("'\"'", "'\''", "''"), array("&quot;", "&#039;", ""), $comments); $comments = preg_replace(array("'\"'", "'\''", "''"), array("&quot;", "&#039;", ""), $comments);
$name = replace_comment("add", preg_replace("/\n/", "",$name)); $name = replace_comment("add", preg_replace("/\n/", "",$name));
$mail = replace_comment("add", preg_replace("/\n/", "",$mail)); $mail = replace_comment("add", preg_replace("/\n/", "",$mail));
echo"<div style=\"text-align: center;\">This name is owned by a registered user and you must enter password to use it<br /> echo"<div style=\"text-align: center;\">This name is owned by a registered user and you must enter password to use it<br />
<form name=passwordForm id=passwordForm method=\"post\" action=\"\"> <form name=passwordForm id=passwordForm method=\"post\" action=\"\">
Password: <input type=\"password\" name=\"password\" /> Password: <input type=\"password\" name=\"password\" />
<input type=\"hidden\" name=\"name\" value=\"$name\" /> <input type=\"hidden\" name=\"name\" value=\"$name\" />
<input type=\"hidden\" name=\"comments\" value=\"$comments\" /> <input type=\"hidden\" name=\"comments\" value=\"$comments\" />
<input type=\"hidden\" name=\"mail\" value=\"$mail\" /> <input type=\"hidden\" name=\"mail\" value=\"$mail\" />
<input type=\"hidden\" name=\"ip\" value=\"$ip\" /> <input type=\"hidden\" name=\"ip\" value=\"$ip\" />
<input type=\"hidden\" name=\"subaction\" value=\"addcomment\" /> <input type=\"hidden\" name=\"subaction\" value=\"addcomment\" />
<input type=\"hidden\" name=\"show\" value=\"$show\" /> <input type=\"hidden\" name=\"show\" value=\"$show\" />
<input type=\"hidden\" name=\"ucat\" value=\"$ucat\" /> <input type=\"hidden\" name=\"ucat\" value=\"$ucat\" />
$user_post_query $user_post_query
<input type=\"submit\" /> \n <br> <input type=\"submit\" /> \n <br>
<input type=\"checkbox\" name=\"CNrememberPass\" value=1 /> Remember password in cookie (md5 format) <input type=\"checkbox\" name=\"CNrememberPass\" value=1 /> Remember password in cookie (md5 format)
</form> </form>
</div>"; </div>";
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 2; break 2;
} }
if(strtolower($user_arr[2]) == strtolower($name)) $is_member = TRUE; if(strtolower($user_arr[2]) == strtolower($name)) $is_member = TRUE;
//---------------------------------- //----------------------------------
// Member wants to save his pass in cookie ? // Member wants to save his pass in cookie ?
//---------------------------------- //----------------------------------
if($CNrememberPass == 1){ if($CNrememberPass == 1){
if(file_exists("$cutepath/remember.js")){ if(file_exists("$cutepath/remember.js")){
echo"<script type=\"text/javascript\" src=\"$config_http_script_dir/remember.js\"></script>"; echo"<script type=\"text/javascript\" src=\"$config_http_script_dir/remember.js\"></script>";
echo"<script>CNRememberPass('".md5($password)."')</script>"; echo"<script>CNRememberPass('".md5($password)."')</script>";
} }
} }
} }
} }
//---------------------------------- //----------------------------------
// Check if only members can comment // Check if only members can comment
//---------------------------------- //----------------------------------
if($config_only_registered_comment == "yes" and !$is_member){ if($config_only_registered_comment == "yes" and !$is_member){
echo"<div style=\"text-align: center;\">Sorry but only registered users can post comments, and '".htmlspecialchars($name)."' is not recognized as valid member.</div>"; echo"<div style=\"text-align: center;\">Sorry but only registered users can post comments, and '".htmlspecialchars($name)."' is not recognized as valid member.</div>";
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
//---------------------------------- //----------------------------------
// Wrap the long words // Wrap the long words
//---------------------------------- //----------------------------------
if($config_auto_wrap > 1){ if($config_auto_wrap > 1){
$comments_arr = explode("\n", $comments); $comments_arr = explode("\n", $comments);
foreach($comments_arr as $line){ foreach($comments_arr as $line){
$wraped_comm .= ereg_replace("([^ \/\/]{".$config_auto_wrap."})","\\1\n", $line) ."\n"; $wraped_comm .= ereg_replace("([^ \/\/]{".$config_auto_wrap."})","\\1\n", $line) ."\n";
} }
if(strlen($name) > $config_auto_wrap){ $name = substr($name, 0, $config_auto_wrap)." ..."; } if(strlen($name) > $config_auto_wrap){ $name = substr($name, 0, $config_auto_wrap)." ..."; }
$comments = $wraped_comm; $comments = $wraped_comm;
} }
//---------------------------------- //----------------------------------
// Do some validation check 4 name, mail.. // Do some validation check 4 name, mail..
//---------------------------------- //----------------------------------
$comments = replace_comment("add", $comments); $comments = replace_comment("add", $comments);
$name = replace_comment("add", preg_replace("/\n/", "",$name)); $name = replace_comment("add", preg_replace("/\n/", "",$name));
$mail = replace_comment("add", preg_replace("/\n/", "",$mail)); $mail = replace_comment("add", preg_replace("/\n/", "",$mail));
if($name == " " or $name == ""){ if($name == " " or $name == ""){
echo("<div style=\"text-align: center;\">You must enter name.<br /><a href=\"javascript:history.go(-1)\">go back</a></div>"); echo("<div style=\"text-align: center;\">You must enter name.<br /><a href=\"javascript:history.go(-1)\">go back</a></div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
if($mail == " " or $mail == ""){ $mail = "none"; } if($mail == " " or $mail == ""){ $mail = "none"; }
else{ $ok = FALSE; else{ $ok = FALSE;
if(preg_match("/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $mail)) $ok = TRUE; if(preg_match("/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $mail)) $ok = TRUE;
elseif($config_allow_url_instead_mail == "yes" and preg_match("/((http(s?):\/\/)|(www\.))([\w\.]+)([\/\w+\.-?]+)/", $mail)) $ok = TRUE; elseif($config_allow_url_instead_mail == "yes" and preg_match("/((http(s?):\/\/)|(www\.))([\w\.]+)([\/\w+\.-?]+)/", $mail)) $ok = TRUE;
elseif($config_allow_url_instead_mail != "yes"){ elseif($config_allow_url_instead_mail != "yes"){
echo("<div style=\"text-align: center;\">This is not a valid e-mail<br /><a href=\"javascript:history.go(-1)\">go back</a></div>"); echo("<div style=\"text-align: center;\">This is not a valid e-mail<br /><a href=\"javascript:history.go(-1)\">go back</a></div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
else{ else{
echo("<div style=\"text-align: center;\">This is not a valid e-mail or site URL<br /><a href=\"javascript:history.go(-1)\">go back</a></div>"); echo("<div style=\"text-align: center;\">This is not a valid e-mail or site URL<br /><a href=\"javascript:history.go(-1)\">go back</a></div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
} }
if($comments == ""){ if($comments == ""){
echo("<div style=\"text-align: center;\">Sorry but the comment can not be blank<br /><a href=\"javascript:history.go(-1)\">go back</a></div>"); echo("<div style=\"text-align: center;\">Sorry but the comment can not be blank<br /><a href=\"javascript:history.go(-1)\">go back</a></div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
$time = time()+($config_date_adjust*60); $time = time()+($config_date_adjust*60);
//---------------------------------- //----------------------------------
// Add The Comment ... Go Go GO! // Add The Comment ... Go Go GO!
//---------------------------------- //----------------------------------
$old_comments = file("$comm_file"); $old_comments = file("$comm_file");
$new_comments = fopen("$comm_file", "w"); $new_comments = fopen("$comm_file", "w");
@flock ($new_comments,2); @flock ($new_comments,2);
$found = FALSE; $found = FALSE;
foreach($old_comments as $old_comments_line) foreach($old_comments as $old_comments_line)
{ {
$old_comments_arr = explode("|>|", $old_comments_line); $old_comments_arr = explode("|>|", $old_comments_line);
if($old_comments_arr[0] == $id) if($old_comments_arr[0] == $id)
{ {
$old_comments_arr[1] = trim($old_comments_arr[1]); $old_comments_arr[1] = trim($old_comments_arr[1]);
fwrite($new_comments, "$old_comments_arr[0]|>|$old_comments_arr[1]$time|$name|$mail|$ip|$comments||\n"); fwrite($new_comments, "$old_comments_arr[0]|>|$old_comments_arr[1]$time|$name|$mail|$ip|$comments||\n");
$found = TRUE; $found = TRUE;
}else{ }else{
fwrite($new_comments, $old_comments_line); fwrite($new_comments, $old_comments_line);
//if we do not have the news ID in the comments.txt we are not doing anything (see comment below) (must make sure the news ID is valid) //if we do not have the news ID in the comments.txt we are not doing anything (see comment below) (must make sure the news ID is valid)
} }
} }
if(!$found){ if(!$found){
/* // do not add comment if News ID is not found \\ fwrite($new_comments, "$id|>|$time|$name|$mail|$ip|$comments||\n");*/ /* // do not add comment if News ID is not found \\ fwrite($new_comments, "$id|>|$time|$name|$mail|$ip|$comments||\n");*/
echo("<div style=\"text-align: center;\">CuteNews did not added your comment because there is some problem with the comments database.<br /><a href=\"javascript:history.go(-1)\">go back</a></div>"); echo("<div style=\"text-align: center;\">CuteNews did not added your comment because there is some problem with the comments database.<br /><a href=\"javascript:history.go(-1)\">go back</a></div>");
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
@flock ($new_comments,3); @flock ($new_comments,3);
fclose($new_comments); fclose($new_comments);
//---------------------------------- //----------------------------------
// Sign this comment in the Flood Protection // Sign this comment in the Flood Protection
//---------------------------------- //----------------------------------
if($config_flood_time != "0" and $config_flood_time != "" ){ if($config_flood_time != "0" and $config_flood_time != "" ){
$flood_file = fopen("$cutepath/data/flood.db.php", "a"); $flood_file = fopen("$cutepath/data/flood.db.php", "a");
@flock ($flood_file,2); @flock ($flood_file,2);
fwrite($flood_file, time()."|$ip|$id|\n"); fwrite($flood_file, time()."|$ip|$id|\n");
@flock ($flood_file,3); @flock ($flood_file,3);
fclose($flood_file); fclose($flood_file);
} }
//---------------------------------- //----------------------------------
// Notify for New Comment ? // Notify for New Comment ?
//---------------------------------- //----------------------------------
if($config_notify_comment == "yes" and $config_notify_status == "active"){ if($config_notify_comment == "yes" and $config_notify_status == "active"){
send_mail("$config_notify_email", "CuteNews - New Comment Added", "New Comment was added by $name:\n--------------------------$comments"); send_mail("$config_notify_email", "CuteNews - New Comment Added", "New Comment was added by $name:\n--------------------------$comments");
} }
echo "<script type=\"text/javascript\">window.location=\"$PHP_SELF?subaction=showfull&id=$id&ucat=$ucat&archive=$archive&start_from=$start_from&$user_query\";</script>"; echo "<script type=\"text/javascript\">window.location=\"$PHP_SELF?subaction=showfull&id=$id&ucat=$ucat&archive=$archive&start_from=$start_from&$user_query\";</script>";
} }
//#################################################################################################################### //####################################################################################################################
// Show Full Story // Show Full Story
//#################################################################################################################### //####################################################################################################################
if($allow_full_story){ if($allow_full_story){
if(!file_exists($news_file)){ die("Error!<br>news file does not exists!"); } if(!file_exists($news_file)){ die("Error!<br>news file does not exists!"); }
$all_active_news = file("$news_file"); $all_active_news = file("$news_file");
foreach($all_active_news as $active_news) foreach($all_active_news as $active_news)
{ {
$news_arr = explode("|", $active_news); $news_arr = explode("|", $active_news);
if($news_arr[0] == $id and (!$catid or $catid == $news_arr[6])) if($news_arr[0] == $id and (!$catid or $catid == $news_arr[6]))
{ {
$found = TRUE; $found = TRUE;
if($news_arr[4] == "" and (!eregi("\{short-story\}", $template_full)) ){ $news_arr[4] = $news_arr[3]; } if($news_arr[4] == "" and (!eregi("\{short-story\}", $template_full)) ){ $news_arr[4] = $news_arr[3]; }
if($my_names[$news_arr[1]]){ $my_author = $my_names[$news_arr[1]]; } if($my_names[$news_arr[1]]){ $my_author = $my_names[$news_arr[1]]; }
else{ $my_author = $news_arr[1]; } else{ $my_author = $news_arr[1]; }
$output = str_replace("{title}", $news_arr[2], $template_full); $output = str_replace("{title}", $news_arr[2], $template_full);
$output = str_replace("{date}", date($config_timestamp_active, $news_arr[0]), $output); $output = str_replace("{date}", date($config_timestamp_active, $news_arr[0]), $output);
$output = str_replace("{author}", $my_author, $output); $output = str_replace("{author}", $my_author, $output);
$output = str_replace("{short-story}", $news_arr[3], $output); $output = str_replace("{short-story}", $news_arr[3], $output);
$output = str_replace("{full-story}", $news_arr[4], $output); $output = str_replace("{full-story}", $news_arr[4], $output);
if($news_arr[5] != ""){$output = str_replace("{avatar}", "<img alt=\"\" src=\"$news_arr[5]\" style=\"border: none;\" />", $output); } if($news_arr[5] != ""){$output = str_replace("{avatar}", "<img alt=\"\" src=\"$news_arr[5]\" style=\"border: none;\" />", $output); }
else{ $output = str_replace("{avatar}", "", $output); } else{ $output = str_replace("{avatar}", "", $output); }
$output = str_replace("{avatar-url}", "$news_arr[5]", $output); $output = str_replace("{avatar-url}", "$news_arr[5]", $output);
$output = str_replace("{comments-num}", countComments($news_arr[0], $archive), $output); $output = str_replace("{comments-num}", countComments($news_arr[0], $archive), $output);
$output = str_replace("{category}", catid2name($news_arr[6]), $output); $output = str_replace("{category}", catid2name($news_arr[6]), $output);
$output = str_replace("{category-id}", $news_arr[6], $output); $output = str_replace("{category-id}", $news_arr[6], $output);
if($cat_icon[$news_arr[6]] != ""){ $output = str_replace("{category-icon}", "<img style=\"border: none;\" alt=\"".$cat[$news_arr[6]]." icon\" src=\"".$cat_icon[$news_arr[6]]."\" />", $output); } if($cat_icon[$news_arr[6]] != ""){ $output = str_replace("{category-icon}", "<img style=\"border: none;\" alt=\"".$cat[$news_arr[6]]." icon\" src=\"".$cat_icon[$news_arr[6]]."\" />", $output); }
else{ $output = str_replace("{category-icon}", "", $output); } else{ $output = str_replace("{category-icon}", "", $output); }
if($config_comments_popup == "yes"){ if($config_comments_popup == "yes"){
$output = str_replace("[com-link]","<a href=\"#\" onclick=\"window.open('$config_http_script_dir/show_news.php?subaction=showcomments&amp;template=$template&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]', '_News', '$config_comments_popup_string');return false;\">", $output); $output = str_replace("[com-link]","<a href=\"#\" onclick=\"window.open('$config_http_script_dir/show_news.php?subaction=showcomments&amp;template=$template&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]', '_News', '$config_comments_popup_string');return false;\">", $output);
}else{ }else{
$output = str_replace("[com-link]","<a href=\"$PHP_SELF?subaction=showcomments&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output); $output = str_replace("[com-link]","<a href=\"$PHP_SELF?subaction=showcomments&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output);
} }
$output = str_replace("[/com-link]","</a>", $output); $output = str_replace("[/com-link]","</a>", $output);
$output = str_replace("{author-name}", $name_to_nick[$news_arr[1]], $output); $output = str_replace("{author-name}", $name_to_nick[$news_arr[1]], $output);
if($my_mails[$news_arr[1]] != ""){ if($my_mails[$news_arr[1]] != ""){
$output = str_replace("[mail]","<a href=\"mailto:".$my_mails[$news_arr[1]]."\">", $output); $output = str_replace("[mail]","<a href=\"mailto:".$my_mails[$news_arr[1]]."\">", $output);
$output = str_replace("[/mail]","</a>", $output); $output = str_replace("[/mail]","</a>", $output);
}else{ }else{
$output = str_replace("[mail]","", $output); $output = str_replace("[mail]","", $output);
$output = str_replace("[/mail]","", $output); $output = str_replace("[/mail]","", $output);
} }
$output = str_replace("{news-id}", $news_arr[0], $output); $output = str_replace("{news-id}", $news_arr[0], $output);
$output = str_replace("{archive-id}", $archive, $output); $output = str_replace("{archive-id}", $archive, $output);
$output = str_replace("{php-self}", $PHP_SELF, $output); $output = str_replace("{php-self}", $PHP_SELF, $output);
$output = str_replace("{cute-http-path}", $config_http_script_dir, $output); $output = str_replace("{cute-http-path}", $config_http_script_dir, $output);
$output = replace_news("show", $output); $output = replace_news("show", $output);
echo $output; echo $output;
} }
} }
if(!$found){ if(!$found){
// //
// Article ID was not found, if we have not specified an archive -> try to find the article in some archive. // Article ID was not found, if we have not specified an archive -> try to find the article in some archive.
// //
// Auto-Find ID In archives // Auto-Find ID In archives
//---------------------------------------------------------------------- //----------------------------------------------------------------------
if(!$archive or $archive == ''){ if(!$archive or $archive == ''){
//get all archives. (if any) and fit our lost id in the most propper archive. //get all archives. (if any) and fit our lost id in the most propper archive.
$lost_id = $id; $lost_id = $id;
$all_archives = FALSE; $all_archives = FALSE;
$hope_archive = FALSE; $hope_archive = FALSE;
if(!$handle = opendir("$cutepath/data/archives")){ echo("<!-- Can not open directory $cutepath/data/archives --> "); } if(!$handle = opendir("$cutepath/data/archives")){ echo("<!-- Can not open directory $cutepath/data/archives --> "); }
while (false !== ($file = readdir($handle))) while (false !== ($file = readdir($handle)))
{ {
if($file != "." and $file != ".." and !is_dir("./data/archives/$file") and eregi("news.arch", $file)) if($file != "." and $file != ".." and !is_dir("./data/archives/$file") and eregi("news.arch", $file))
{ {
$file_arr = explode(".", $file); $file_arr = explode(".", $file);
$all_archives[] = $file_arr[0]; $all_archives[] = $file_arr[0];
} }
} }
closedir($handle); closedir($handle);
if($all_archives){ if($all_archives){
sort($all_archives); sort($all_archives);
if(isset($all_archives[1])){ if(isset($all_archives[1])){
foreach($all_archives as $this_archive){ foreach($all_archives as $this_archive){
if($this_archive > $lost_id){ $hope_archive = $this_archive; break;} if($this_archive > $lost_id){ $hope_archive = $this_archive; break;}
} }
}else{ }else{
if($all_archives[0] > $lost_id){ $hope_archive = $all_archives[0]; break;} if($all_archives[0] > $lost_id){ $hope_archive = $all_archives[0]; break;}
} }
} }
} }
if($hope_archive){ if($hope_archive){
echo" echo"
<center>You are now being redirected to the article in our archives<br>if the redirection fails, please <a href=\"$PHP_SELF?start_from=$start_from&ucat=$ucat&subaction=$subaction&id=$id&archive=$hope_archive&$user_query\">click here</a></center> <center>You are now being redirected to the article in our archives<br>if the redirection fails, please <a href=\"$PHP_SELF?start_from=$start_from&ucat=$ucat&subaction=$subaction&id=$id&archive=$hope_archive&$user_query\">click here</a></center>
<SCRIPT LANGUAGE=\"JavaScript\"> <SCRIPT LANGUAGE=\"JavaScript\">
<!-- Lets hope the archive id is correct. <!-- Lets hope the archive id is correct.
window.location=\"$PHP_SELF?start_from=$start_from&ucat=$ucat&subaction=$subaction&id=$id&archive=$hope_archive&$user_query\"; window.location=\"$PHP_SELF?start_from=$start_from&ucat=$ucat&subaction=$subaction&id=$id&archive=$hope_archive&$user_query\";
// --> // -->
</script>"; </script>";
}else{ }else{
echo("<div style=\"text-align: center;\">Can not find an article with id: <strong>". @(int) htmlspecialchars($id)."</strong></div>"); echo("<div style=\"text-align: center;\">Can not find an article with id: <strong>". @(int) htmlspecialchars($id)."</strong></div>");
} }
$CN_HALT = TRUE; $CN_HALT = TRUE;
break 1; break 1;
} }
} }
//#################################################################################################################### //####################################################################################################################
// Show Comments // Show Comments
//#################################################################################################################### //####################################################################################################################
if($allow_comments){ if($allow_comments){
$comm_per_page = $config_comments_per_page; $comm_per_page = $config_comments_per_page;
$total_comments = 0; $total_comments = 0;
$showed_comments = 0; $showed_comments = 0;
$comment_number = 0; $comment_number = 0;
$showed = 0; $showed = 0;
$all_comments = file("$comm_file"); $all_comments = file("$comm_file");
foreach($all_comments as $comment_line) foreach($all_comments as $comment_line)
{ {
$comment_line = trim($comment_line); $comment_line = trim($comment_line);
$comment_line_arr = explode("|>|", $comment_line); $comment_line_arr = explode("|>|", $comment_line);
if($id == $comment_line_arr[0]) if($id == $comment_line_arr[0])
{ {
$individual_comments = explode("||", $comment_line_arr[1]); $individual_comments = explode("||", $comment_line_arr[1]);
$total_comments = @count($individual_comments) - 1; $total_comments = @count($individual_comments) - 1;
//show the page with our new comment, if we just added one //show the page with our new comment, if we just added one
/* causes some problems, will be updated !!! /* causes some problems, will be updated !!!
if($allow_add_comment and true){ if($allow_add_comment and true){
$comm_start_from = $total_comments-1; $comm_start_from = $total_comments-1;
if($config_reverse_comments == "yes"){ if($config_reverse_comments == "yes"){
$comm_start_from = 0; $comm_start_from = 0;
} }
} }
*/ */
$iteration = 0; $iteration = 0;
if($config_reverse_comments == "yes"){$iteration = count($individual_comments)+1; $individual_comments = array_reverse($individual_comments); } if($config_reverse_comments == "yes"){$iteration = count($individual_comments)+1; $individual_comments = array_reverse($individual_comments); }
foreach($individual_comments as $comment) foreach($individual_comments as $comment)
{ {
if($config_reverse_comments == "yes") { $iteration --; } if($config_reverse_comments == "yes") { $iteration --; }
else{ $iteration ++; } else{ $iteration ++; }
$comment_arr = explode("|", $comment); $comment_arr = explode("|", $comment);
if($comment_arr[0] != "") if($comment_arr[0] != "")
{ {
if(isset($comm_start_from) and $comm_start_from != ""){ if(isset($comm_start_from) and $comm_start_from != ""){
if($comment_number < $comm_start_from){ $comment_number++; continue; } if($comment_number < $comm_start_from){ $comment_number++; continue; }
elseif($showed_comments == $comm_per_page){ break; } elseif($showed_comments == $comm_per_page){ break; }
} }
$comment_number ++; $comment_number ++;
$comment_arr[4] = stripslashes(rtrim($comment_arr[4])); $comment_arr[4] = stripslashes(rtrim($comment_arr[4]));
if($comment_arr[2] != "none"){ if($comment_arr[2] != "none"){
if( preg_match("/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $comment_arr[2])){ $url_target = "";$mail_or_url = "mailto:"; } if( preg_match("/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $comment_arr[2])){ $url_target = "";$mail_or_url = "mailto:"; }
else{ else{
$url_target = "target=\"_blank\""; $url_target = "target=\"_blank\"";
$mail_or_url = ""; $mail_or_url = "";
if(substr($comment_arr[2],0,3) == "www"){ $mail_or_url = "http://"; } if(substr($comment_arr[2],0,3) == "www"){ $mail_or_url = "http://"; }
} }
$output = str_replace("{author}", "<a $url_target href=\"$mail_or_url".stripslashes($comment_arr[2])."\">".stripslashes($comment_arr[1])."</a>", $template_comment); $output = str_replace("{author}", "<a $url_target href=\"$mail_or_url".stripslashes($comment_arr[2])."\">".stripslashes($comment_arr[1])."</a>", $template_comment);
} }
else{ $output = str_replace("{author}", $comment_arr[1], $template_comment); } else{ $output = str_replace("{author}", $comment_arr[1], $template_comment); }
$comment_arr[4] = preg_replace("/\b((http(s?):\/\/)|(www\.))([\w\.]+)([&-~\%\/\w+\.-?]+)\b/i", "<a href=\"http$3://$4$5$6\" target=\"_blank\">$2$4$5$6</a>", $comment_arr[4]); $comment_arr[4] = preg_replace("/\b((http(s?):\/\/)|(www\.))([\w\.]+)([&-~\%\/\w+\.-?]+)\b/i", "<a href=\"http$3://$4$5$6\" target=\"_blank\">$2$4$5$6</a>", $comment_arr[4]);
$comment_arr[4] = preg_replace("/([\w\.]+)(@)([-\w\.]+)/i", "<a href=\"mailto:$0\">$0</a>", $comment_arr[4]); $comment_arr[4] = preg_replace("/([\w\.]+)(@)([-\w\.]+)/i", "<a href=\"mailto:$0\">$0</a>", $comment_arr[4]);
$output = str_replace("{mail}", "$comment_arr[2]",$output); $output = str_replace("{mail}", "$comment_arr[2]",$output);
$output = str_replace("{date}", date($config_timestamp_comment, $comment_arr[0]),$output); $output = str_replace("{date}", date($config_timestamp_comment, $comment_arr[0]),$output);
$output = str_replace("{comment-id}", $comment_arr[0],$output); $output = str_replace("{comment-id}", $comment_arr[0],$output);
$output = str_replace("{comment}", "<a name=\"".$comment_arr[0]."\"></a>$comment_arr[4]",$output); $output = str_replace("{comment}", "<a name=\"".$comment_arr[0]."\"></a>$comment_arr[4]",$output);
$output = str_replace("{comment-iteration}", $iteration ,$output); $output = str_replace("{comment-iteration}", $iteration ,$output);
$output = replace_comment("show", $output); $output = replace_comment("show", $output);
echo $output; echo $output;
$showed_comments++; $showed_comments++;
if($comm_per_page != 0 and $comm_per_page == $showed_comments){ break; } if($comm_per_page != 0 and $comm_per_page == $showed_comments){ break; }
} }
} }
} }
} }
//---------------------------------- //----------------------------------
// Prepare the Comment Pagination // Prepare the Comment Pagination
//---------------------------------- //----------------------------------
$prev_next_msg = $template_comments_prev_next; $prev_next_msg = $template_comments_prev_next;
// Previous link // Previous link
if(isset($comm_start_from) and $comm_start_from != "" and $comm_start_from > 0){ if(isset($comm_start_from) and $comm_start_from != "" and $comm_start_from > 0){
$prev = $comm_start_from - $comm_per_page; $prev = $comm_start_from - $comm_per_page;
$prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "<a href=\"$PHP_SELF?comm_start_from=$prev&amp;archive=$archive&amp;subaction=showcomments&amp;id=$id&amp;ucat=$ucat&amp;$user_query\">\\1</a>", $prev_next_msg); $prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "<a href=\"$PHP_SELF?comm_start_from=$prev&amp;archive=$archive&amp;subaction=showcomments&amp;id=$id&amp;ucat=$ucat&amp;$user_query\">\\1</a>", $prev_next_msg);
}else{ $prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "\\1", $prev_next_msg); $no_prev = TRUE; } }else{ $prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "\\1", $prev_next_msg); $no_prev = TRUE; }
// Pages // Pages
if($comm_per_page){ if($comm_per_page){
$pages_count = @ceil($total_comments/$comm_per_page); $pages_count = @ceil($total_comments/$comm_per_page);
$pages_start_from = 0; $pages_start_from = 0;
$pages = ""; $pages = "";
for($j=1;$j<=$pages_count;$j++){ for($j=1;$j<=$pages_count;$j++){
if($pages_start_from != $comm_start_from){ $pages .= "<a href=\"$PHP_SELF?comm_start_from=$pages_start_from&amp;archive=$archive&amp;subaction=showcomments&amp;id=$id&amp;ucat=$ucat&amp;$user_query\">$j</a> "; } if($pages_start_from != $comm_start_from){ $pages .= "<a href=\"$PHP_SELF?comm_start_from=$pages_start_from&amp;archive=$archive&amp;subaction=showcomments&amp;id=$id&amp;ucat=$ucat&amp;$user_query\">$j</a> "; }
else{ $pages .= " <strong>$j</strong> "; } else{ $pages .= " <strong>$j</strong> "; }
$pages_start_from += $comm_per_page; $pages_start_from += $comm_per_page;
} }
$prev_next_msg = str_replace("{pages}", $pages, $prev_next_msg); $prev_next_msg = str_replace("{pages}", $pages, $prev_next_msg);
} }
// Next link // Next link
if($comm_per_page < $total_comments and $comment_number < $total_comments){ if($comm_per_page < $total_comments and $comment_number < $total_comments){
$prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "<a href=\"$PHP_SELF?comm_start_from=$comment_number&amp;archive=$archive&amp;subaction=showcomments&amp;id=$id&amp;ucat=$ucat&amp;$user_query\">\\1</a>", $prev_next_msg); $prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "<a href=\"$PHP_SELF?comm_start_from=$comment_number&amp;archive=$archive&amp;subaction=showcomments&amp;id=$id&amp;ucat=$ucat&amp;$user_query\">\\1</a>", $prev_next_msg);
}else{ $prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "\\1", $prev_next_msg); $no_next = TRUE;} }else{ $prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "\\1", $prev_next_msg); $no_next = TRUE;}
if (!$no_prev or !$no_next){ if (!$no_prev or !$no_next){
echo $prev_next_msg; echo $prev_next_msg;
} }
$template_form = str_replace("{config_http_script_dir}", "$config_http_script_dir", $template_form); $template_form = str_replace("{config_http_script_dir}", "$config_http_script_dir", $template_form);
//---------------------------------- //----------------------------------
// Check if the remember script exists // Check if the remember script exists
//---------------------------------- //----------------------------------
$CN_remember_include = ''; $CN_remember_include = '';
$CN_remember_form = ''; $CN_remember_form = '';
if(file_exists("$cutepath/remember.js")){ if(file_exists("$cutepath/remember.js")){
$CN_remember_include = "<script type=\"text/javascript\" src=\"$config_http_script_dir/remember.js\"></script><script>CNreadCookie();</script>"; $CN_remember_include = "<script type=\"text/javascript\" src=\"$config_http_script_dir/remember.js\"></script><script>CNreadCookie();</script>";
$CN_remember_form = "onsubmit=\"return CNSubmitComment()\""; $CN_remember_form = "onsubmit=\"return CNSubmitComment()\"";
} }
$smilies_form = "\n<script type=\"text/javascript\"> $smilies_form = "\n<script type=\"text/javascript\">
//<![CDATA[ //<![CDATA[
function insertext(text){ function insertext(text){
document.comment.comments.value+=\" \"+ text; document.comment.comments.value+=\" \"+ text;
document.comment.comments.focus(); document.comment.comments.focus();
} }
//]]></script> //]]></script>
<noscript>Your browser is not Javascript enable or you have turn it off. We recommend you to activate, otherwise you will have to enter the emoticons representations manually. <noscript>Your browser is not Javascript enable or you have turn it off. We recommend you to activate, otherwise you will have to enter the emoticons representations manually.
</noscript>".insertSmilies('short', FALSE); </noscript>".insertSmilies('short', FALSE);
$template_form = str_replace("{smilies}", $smilies_form, $template_form); $template_form = str_replace("{smilies}", $smilies_form, $template_form);
echo"<form $CN_remember_form method=\"post\" name=\"comment\" id=\"comment\" action=\"\">".$template_form."<div><input type=\"hidden\" name=\"subaction\" value=\"addcomment\" /><input type=\"hidden\" name=\"ucat\" value=\"$ucat\" /><input type=\"hidden\" name=\"show\" value=\"$show\" />$user_post_query</div></form> echo"<form $CN_remember_form method=\"post\" name=\"comment\" id=\"comment\" action=\"\">".$template_form."<div><input type=\"hidden\" name=\"subaction\" value=\"addcomment\" /><input type=\"hidden\" name=\"ucat\" value=\"$ucat\" /><input type=\"hidden\" name=\"show\" value=\"$show\" />$user_post_query</div></form>
\n $CN_remember_include"; \n $CN_remember_include";
} }
//#################################################################################################################### //####################################################################################################################
// Active News // Active News
//#################################################################################################################### //####################################################################################################################
if($allow_active_news){ if($allow_active_news){
$all_news = file("$news_file"); $all_news = file("$news_file");
if($reverse == TRUE){ $all_news = array_reverse($all_news); } if($reverse == TRUE){ $all_news = array_reverse($all_news); }
$count_all = 0; $count_all = 0;
if(isset($category) and $category != ""){ if(isset($category) and $category != ""){
foreach($all_news as $news_line){ foreach($all_news as $news_line){
$news_arr = explode("|", $news_line); $news_arr = explode("|", $news_line);
$is_in_cat = FALSE; $is_in_cat = FALSE;
if(strstr($news_arr[6],',')){ //if the article is in multiple categories if(strstr($news_arr[6],',')){ //if the article is in multiple categories
// echo"<br>$news_arr[0] item is multy<br>"; // echo"<br>$news_arr[0] item is multy<br>";
$this_cats_arr = explode(',',$news_arr[6]); $this_cats_arr = explode(',',$news_arr[6]);
foreach($this_cats_arr as $this_single_cat){ foreach($this_cats_arr as $this_single_cat){
// echo"<br>if we want $this_single_cat "; // echo"<br>if we want $this_single_cat ";
if($requested_cats and $requested_cats[$this_single_cat] == TRUE){ $is_in_cat=TRUE;} if($requested_cats and $requested_cats[$this_single_cat] == TRUE){ $is_in_cat=TRUE;}
} }
}else{ }else{
// echo"<br>$news_arr[0] item is single<br>"; // echo"<br>$news_arr[0] item is single<br>";
// echo"<br>if we want $news_arr[6] "; // echo"<br>if we want $news_arr[6] ";
if($requested_cats and $requested_cats[$news_arr[6]] == TRUE){ $is_in_cat=TRUE;} if($requested_cats and $requested_cats[$news_arr[6]] == TRUE){ $is_in_cat=TRUE;}
} }
if($is_in_cat){ $count_all ++; } if($is_in_cat){ $count_all ++; }
else{ continue; } else{ continue; }
} }
}else{ $count_all = count($all_news); } }else{ $count_all = count($all_news); }
$i = 0; $i = 0;
$showed = 0; $showed = 0;
$repeat = TRUE; $repeat = TRUE;
$url_archive = $archive; $url_archive = $archive;
while($repeat != FALSE){ while($repeat != FALSE){
foreach($all_news as $news_line){ foreach($all_news as $news_line){
$news_arr = explode("|", $news_line); $news_arr = explode("|", $news_line);
$is_in_cat = FALSE; $is_in_cat = FALSE;
if(strstr($news_arr[6],',')){ //if the article is in multiple categories if(strstr($news_arr[6],',')){ //if the article is in multiple categories
$this_cats_arr = explode(',',$news_arr[6]); $this_cats_arr = explode(',',$news_arr[6]);
foreach($this_cats_arr as $this_single_cat){ foreach($this_cats_arr as $this_single_cat){
if($requested_cats and $requested_cats[$this_single_cat] == TRUE){ $is_in_cat=TRUE;} if($requested_cats and $requested_cats[$this_single_cat] == TRUE){ $is_in_cat=TRUE;}
} }
}else{ }else{
if($requested_cats and $requested_cats[$news_arr[6]] == TRUE){ $is_in_cat=TRUE;} if($requested_cats and $requested_cats[$news_arr[6]] == TRUE){ $is_in_cat=TRUE;}
} }
if(!$is_in_cat and $category != '' and isset($category)){ continue; } if(!$is_in_cat and $category != '' and isset($category)){ continue; }
if(isset($start_from) and $start_from != ""){ if(isset($start_from) and $start_from != ""){
if($i < $start_from){ $i++; continue; } if($i < $start_from){ $i++; continue; }
elseif($showed == $number){ break; } elseif($showed == $number){ break; }
} }
if($my_names[$news_arr[1]]){ $my_author = $my_names[$news_arr[1]]; } if($my_names[$news_arr[1]]){ $my_author = $my_names[$news_arr[1]]; }
else{ $my_author = $news_arr[1]; } else{ $my_author = $news_arr[1]; }
$output = $template_active; $output = $template_active;
$output = str_replace("{title}", $news_arr[2], $output); $output = str_replace("{title}", $news_arr[2], $output);
$output = str_replace("{author}", $my_author, $output); $output = str_replace("{author}", $my_author, $output);
if($news_arr[5] != ""){$output = str_replace("{avatar}", "<img alt=\"\" src=\"$news_arr[5]\" style=\"border: none;\" />", $output); } if($news_arr[5] != ""){$output = str_replace("{avatar}", "<img alt=\"\" src=\"$news_arr[5]\" style=\"border: none;\" />", $output); }
else{ $output = str_replace("{avatar}", "", $output); } else{ $output = str_replace("{avatar}", "", $output); }
$output = str_replace("{avatar-url}", "$news_arr[5]", $output); $output = str_replace("{avatar-url}", "$news_arr[5]", $output);
$output = str_replace("[link]","<a href=\"$PHP_SELF?subaction=showfull&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output); $output = str_replace("[link]","<a href=\"$PHP_SELF?subaction=showfull&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output);
$output = str_replace("[/link]","</a>", $output); $output = str_replace("[/link]","</a>", $output);
$output = str_replace("{comments-num}", countComments($news_arr[0], $archive), $output); $output = str_replace("{comments-num}", countComments($news_arr[0], $archive), $output);
$output = str_replace("{short-story}", $news_arr[3], $output); $output = str_replace("{short-story}", $news_arr[3], $output);
$output = str_replace("{full-story}", $news_arr[4], $output); $output = str_replace("{full-story}", $news_arr[4], $output);
$output = str_replace("{category}", catid2name($news_arr[6]), $output); $output = str_replace("{category}", catid2name($news_arr[6]), $output);
$output = str_replace("{category-id}", $news_arr[6], $output); $output = str_replace("{category-id}", $news_arr[6], $output);
if($cat_icon[$news_arr[6]] != ""){ $output = str_replace("{category-icon}", "<img alt=\"".$cat[$news_arr[6]]." icon\" style=\"border: none;\" src=\"".$cat_icon[$news_arr[6]]."\" />", $output); } if($cat_icon[$news_arr[6]] != ""){ $output = str_replace("{category-icon}", "<img alt=\"".$cat[$news_arr[6]]." icon\" style=\"border: none;\" src=\"".$cat_icon[$news_arr[6]]."\" />", $output); }
else{ $output = str_replace("{category-icon}", "", $output); } else{ $output = str_replace("{category-icon}", "", $output); }
$output = str_replace("{author-name}", $name_to_nick[$news_arr[1]], $output); $output = str_replace("{author-name}", $name_to_nick[$news_arr[1]], $output);
if($my_mails[$news_arr[1]] != ""){ if($my_mails[$news_arr[1]] != ""){
$output = str_replace("[mail]","<a href=\"mailto:".$my_mails[$news_arr[1]]."\">", $output); $output = str_replace("[mail]","<a href=\"mailto:".$my_mails[$news_arr[1]]."\">", $output);
$output = str_replace("[/mail]","</a>", $output); $output = str_replace("[/mail]","</a>", $output);
}else{ }else{
$output = str_replace("[mail]","", $output); $output = str_replace("[mail]","", $output);
$output = str_replace("[/mail]","", $output); $output = str_replace("[/mail]","", $output);
} }
$output = str_replace("{news-id}", $news_arr[0], $output); $output = str_replace("{news-id}", $news_arr[0], $output);
$output = str_replace("{archive-id}", $archive, $output); $output = str_replace("{archive-id}", $archive, $output);
$output = str_replace("{php-self}", $PHP_SELF, $output); $output = str_replace("{php-self}", $PHP_SELF, $output);
$output = str_replace("{cute-http-path}", $config_http_script_dir, $output); $output = str_replace("{cute-http-path}", $config_http_script_dir, $output);
//if we are showing the RSS feed, add some need variables. //if we are showing the RSS feed, add some need variables.
if($template == 'rss'){ if($template == 'rss'){
$output = str_replace("{date}", date("r", $news_arr[0]), $output); // in RSS we need the date in specific format $output = str_replace("{date}", date("r", $news_arr[0]), $output); // in RSS we need the date in specific format
if($rss_news_include_url == '' or !$rss_news_include_url){ $rss_news_include_url = '$config_http_script_dir/show_news.php'; } if($rss_news_include_url == '' or !$rss_news_include_url){ $rss_news_include_url = '$config_http_script_dir/show_news.php'; }
$output = str_replace("{rss-news-include-url}", $rss_news_include_url, $output); $output = str_replace("{rss-news-include-url}", $rss_news_include_url, $output);
}else{ }else{
//normally display the date in the format that user wants it. //normally display the date in the format that user wants it.
$output = str_replace("{date}", date($config_timestamp_active, $news_arr[0]), $output); $output = str_replace("{date}", date($config_timestamp_active, $news_arr[0]), $output);
} }
$output = replace_news("show", $output); $output = replace_news("show", $output);
if($news_arr[4] != "" or $action == "showheadlines"){//if full story if($news_arr[4] != "" or $action == "showheadlines"){//if full story
if($config_full_popup == "yes"){ if($config_full_popup == "yes"){
$output = preg_replace("/\\[full-link\\]/","<a href=\"#\" onclick=\"window.open('$config_http_script_dir/show_news.php?subaction=showfull&amp;id=$news_arr[0]&amp;archive=$archive&amp;template=$template', '_News', '$config_full_popup_string');return false;\">", $output); $output = preg_replace("/\\[full-link\\]/","<a href=\"#\" onclick=\"window.open('$config_http_script_dir/show_news.php?subaction=showfull&amp;id=$news_arr[0]&amp;archive=$archive&amp;template=$template', '_News', '$config_full_popup_string');return false;\">", $output);
}else{ }else{
$output = str_replace("[full-link]","<a href=\"$PHP_SELF?subaction=showfull&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output); $output = str_replace("[full-link]","<a href=\"$PHP_SELF?subaction=showfull&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output);
} }
$output = str_replace("[/full-link]","</a>", $output); $output = str_replace("[/full-link]","</a>", $output);
}else{ }else{
$output = preg_replace("'\\[full-link\\].*?\\[/full-link\\]'si","<!-- no full story-->", $output); $output = preg_replace("'\\[full-link\\].*?\\[/full-link\\]'si","<!-- no full story-->", $output);
} }
if($config_comments_popup == "yes"){ if($config_comments_popup == "yes"){
$output = str_replace("[com-link]","<a href=\"#\" onclick=\"window.open('$config_http_script_dir/show_news.php?subaction=showcomments&amp;template=$template&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]', '_News', '$config_comments_popup_string');return false;\">", $output); $output = str_replace("[com-link]","<a href=\"#\" onclick=\"window.open('$config_http_script_dir/show_news.php?subaction=showcomments&amp;template=$template&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]', '_News', '$config_comments_popup_string');return false;\">", $output);
}else{ }else{
$output = str_replace("[com-link]","<a href=\"$PHP_SELF?subaction=showcomments&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output); $output = str_replace("[com-link]","<a href=\"$PHP_SELF?subaction=showcomments&amp;id=$news_arr[0]&amp;archive=$archive&amp;start_from=$my_start_from&amp;ucat=$news_arr[6]&amp;$user_query\">", $output);
} }
$output = str_replace("[/com-link]","</a>", $output); $output = str_replace("[/com-link]","</a>", $output);
echo $output; echo $output;
$showed++; $showed++;
$i++; $i++;
if($number != 0 and $number == $i){ break; } if($number != 0 and $number == $i){ break; }
} }
$used_archives[$archive] = TRUE; $used_archives[$archive] = TRUE;
// Archives Looop // Archives Looop
if($i < $number and $only_active != TRUE){ if($i < $number and $only_active != TRUE){
if(!$handle = opendir("$cutepath/data/archives")){ die("<div style=\"text-align: center;\">Can not open directory $cutepath/data/archives</div>"); } if(!$handle = opendir("$cutepath/data/archives")){ die("<div style=\"text-align: center;\">Can not open directory $cutepath/data/archives</div>"); }
while (false !== ($file = readdir($handle))) while (false !== ($file = readdir($handle)))
{ {
if($file != "." and $file != ".." and eregi("news.arch", $file)) if($file != "." and $file != ".." and eregi("news.arch", $file))
{ {
$file_arr = explode(".",$file); $file_arr = explode(".",$file);
$archives_arr[$file_arr[0]] = $file_arr[0]; $archives_arr[$file_arr[0]] = $file_arr[0];
} }
} }
closedir($handle); closedir($handle);
$archives_arr[$in_use]=""; $archives_arr[$in_use]="";
$in_use = max($archives_arr); $in_use = max($archives_arr);
if($in_use != "" and !$used_archives[$in_use]){ if($in_use != "" and !$used_archives[$in_use]){
$all_news = file("$cutepath/data/archives/$in_use.news.arch"); $all_news = file("$cutepath/data/archives/$in_use.news.arch");
$archive = $in_use; $archive = $in_use;
$used_archives[$in_use] = TRUE; $used_archives[$in_use] = TRUE;
}else{ $repeat = FALSE; } }else{ $repeat = FALSE; }
}else{ $repeat = FALSE; } }else{ $repeat = FALSE; }
} }
// << Previous & Next >> // << Previous & Next >>
$prev_next_msg = $template_prev_next; $prev_next_msg = $template_prev_next;
//---------------------------------- //----------------------------------
// Previous link // Previous link
//---------------------------------- //----------------------------------
if(isset($start_from) and $start_from != "" and $start_from > 0){ if(isset($start_from) and $start_from != "" and $start_from > 0){
$prev = $start_from - $number; $prev = $start_from - $number;
$prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "<a href=\"$PHP_SELF?start_from=$prev&amp;ucat=$ucat&amp;archive=$url_archive&amp;subaction=$subaction&amp;id=$id&amp;$user_query\">\\1</a>", $prev_next_msg); $prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "<a href=\"$PHP_SELF?start_from=$prev&amp;ucat=$ucat&amp;archive=$url_archive&amp;subaction=$subaction&amp;id=$id&amp;$user_query\">\\1</a>", $prev_next_msg);
}else{ $prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "\\1", $prev_next_msg); $no_prev = TRUE; } }else{ $prev_next_msg = preg_replace("'\[prev-link\](.*?)\[/prev-link\]'si", "\\1", $prev_next_msg); $no_prev = TRUE; }
//---------------------------------- //----------------------------------
// Pages // Pages
//---------------------------------- //----------------------------------
if($number){ if($number){
$pages_count = @ceil($count_all/$number); $pages_count = @ceil($count_all/$number);
$pages_start_from = 0; $pages_start_from = 0;
$pages = ""; $pages = "";
for($j=1;$j<=$pages_count;$j++){ for($j=1;$j<=$pages_count;$j++){
if($pages_start_from != $start_from){ $pages .= "<a href=\"$PHP_SELF?start_from=$pages_start_from&amp;ucat=$ucat&amp;archive=$url_archive&amp;subaction=$subaction&amp;id=$id&amp;$user_query\">$j</a> "; } if($pages_start_from != $start_from){ $pages .= "<a href=\"$PHP_SELF?start_from=$pages_start_from&amp;ucat=$ucat&amp;archive=$url_archive&amp;subaction=$subaction&amp;id=$id&amp;$user_query\">$j</a> "; }
else{ $pages .= " <strong>$j</strong> "; } else{ $pages .= " <strong>$j</strong> "; }
$pages_start_from += $number; $pages_start_from += $number;
} }
$prev_next_msg = str_replace("{pages}", $pages, $prev_next_msg); $prev_next_msg = str_replace("{pages}", $pages, $prev_next_msg);
} }
//---------------------------------- //----------------------------------
// Next link (typo here ... typo there... typos everywhere !) // Next link (typo here ... typo there... typos everywhere !)
//---------------------------------- //----------------------------------
if($number < $count_all and $i < $count_all){ if($number < $count_all and $i < $count_all){
$prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "<a href=\"$PHP_SELF?start_from=$i&amp;ucat=$ucat&amp;archive=$url_archive&amp;subaction=$subaction&amp;id=$id&amp;$user_query\">\\1</a>", $prev_next_msg); $prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "<a href=\"$PHP_SELF?start_from=$i&amp;ucat=$ucat&amp;archive=$url_archive&amp;subaction=$subaction&amp;id=$id&amp;$user_query\">\\1</a>", $prev_next_msg);
}else{ $prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "\\1", $prev_next_msg); $no_next = TRUE;} }else{ $prev_next_msg = preg_replace("'\[next-link\](.*?)\[/next-link\]'si", "\\1", $prev_next_msg); $no_next = TRUE;}
if (!$no_prev or !$no_next){ echo $prev_next_msg; } if (!$no_prev or !$no_next){ echo $prev_next_msg; }
} }
}while(0); }while(0);
if((!isset($count_cute_news_includes) or !$count_cute_news_includes) and $template != 'rss'){ if((!isset($count_cute_news_includes) or !$count_cute_news_includes) and $template != 'rss'){
/// ///
/// Removing the "P0wered By..." line is NOT allowed by the CuteNews License, only registered users are alowed to do so. /// Removing the "P0wered By..." line is NOT allowed by the CuteNews License, only registered users are alowed to do so.
/// ///
if(!file_exists("$cutepath/data/reg.php")){ echo base64_decode('PGRpdiBzdHlsZT0ibWFyZ2luLXRvcDoxNXB4O3dpZHRoOjEwMCU7dGV4dC1hbGlnbjpjZW50ZXI7Zm9udDo5cHggVmVyZGFuYTsiPkNvbnRlbnQgTWFuYWdlbWVudCBQb3dlcmVkIGJ5IDxhIGhyZWY9Imh0dHA6Ly9jdXRlcGhwLmNvbS8iIHRpdGxlPSJDdXRlTmV3cyAtIFBIUCBOZXdzIE1hbmFnZW1lbnQgU3lzdGVtIj5DdXRlTmV3czwvYT48L2Rpdj4='); } if(!file_exists("$cutepath/data/reg.php")){ echo base64_decode('PGRpdiBzdHlsZT0ibWFyZ2luLXRvcDoxNXB4O3dpZHRoOjEwMCU7dGV4dC1hbGlnbjpjZW50ZXI7Zm9udDo5cHggVmVyZGFuYTsiPkNvbnRlbnQgTWFuYWdlbWVudCBQb3dlcmVkIGJ5IDxhIGhyZWY9Imh0dHA6Ly9jdXRlcGhwLmNvbS8iIHRpdGxlPSJDdXRlTmV3cyAtIFBIUCBOZXdzIE1hbmFnZW1lbnQgU3lzdGVtIj5DdXRlTmV3czwvYT48L2Rpdj4='); }
else{ else{
include("$cutepath/data/reg.php"); include("$cutepath/data/reg.php");
if(preg_match('/\\A(\\w{6})-\\w{6}-\\w{6}\\z/', $reg_site_key, $mmbrid)){ if(preg_match('/\\A(\\w{6})-\\w{6}-\\w{6}\\z/', $reg_site_key, $mmbrid)){
}else{ }else{
echo base64_decode('PGRpdiBzdHlsZT0ibWFyZ2luLXRvcDoxNXB4O3dpZHRoOjEwMCU7dGV4dC1hbGlnbjpjZW50ZXI7Zm9udDo5cHggVmVyZGFuYTsiPkNvbnRlbnQgTWFuYWdlbWVudCBQb3dlcmVkIGJ5IDxhIGhyZWY9Imh0dHA6Ly9jdXRlcGhwLmNvbS8iIHRpdGxlPSJDdXRlTmV3cyAtIFBIUCBOZXdzIE1hbmFnZW1lbnQgU3lzdGVtIj5DdXRlTmV3czwvYT48L2Rpdj4='); echo base64_decode('PGRpdiBzdHlsZT0ibWFyZ2luLXRvcDoxNXB4O3dpZHRoOjEwMCU7dGV4dC1hbGlnbjpjZW50ZXI7Zm9udDo5cHggVmVyZGFuYTsiPkNvbnRlbnQgTWFuYWdlbWVudCBQb3dlcmVkIGJ5IDxhIGhyZWY9Imh0dHA6Ly9jdXRlcGhwLmNvbS8iIHRpdGxlPSJDdXRlTmV3cyAtIFBIUCBOZXdzIE1hbmFnZW1lbnQgU3lzdGVtIj5DdXRlTmV3czwvYT48L2Rpdj4=');
} }
} }
} }
$count_cute_news_includes++; $count_cute_news_includes++;
?> ?>
<?PHP <?PHP
/*************************************************************************** /***************************************************************************
CuteNews CutePHP.com CuteNews CutePHP.com
Copyright (C) 2005 Georgi Avramov (flexer@cutephp.com) Copyright (C) 2005 Georgi Avramov (flexer@cutephp.com)
****************************************************************************/ ****************************************************************************/
error_reporting (E_ALL ^ E_NOTICE); error_reporting (E_ALL ^ E_NOTICE);
require_once("./inc/functions.inc.php"); require_once("./inc/functions.inc.php");
//################# //#################
$PHP_SELF = "index.php"; $PHP_SELF = "index.php";
$cutepath = "."; $cutepath = ".";
$config_path_image_upload = "./data/upimages"; $config_path_image_upload = "./data/upimages";
$config_use_cookies = TRUE; // Use Cookies When Checking Authorization $config_use_cookies = TRUE; // Use Cookies When Checking Authorization
$config_use_sessions = FALSE; // Use Sessions When Checking Authorization $config_use_sessions = FALSE; // Use Sessions When Checking Authorization
$config_check_referer = TRUE; // Set to TRUE for more seciruty $config_check_referer = TRUE; // Set to TRUE for more seciruty
//################# //#################
$Timer = new microTimer; $Timer = new microTimer;
$Timer->start(); $Timer->start();
// Check if CuteNews is not installed // Check if CuteNews is not installed
$all_users_db = file("./data/users.db.php"); $all_users_db = file("./data/users.db.php");
$check_users = $all_users_db; $check_users = $all_users_db;
$check_users[1] = trim($check_users[1]); $check_users[1] = trim($check_users[1]);
$check_users[2] = trim($check_users[2]); $check_users[2] = trim($check_users[2]);
if((!$check_users[2] or $check_users[2] == "") and (!$check_users[1] or $check_users[1] == "")){ if((!$check_users[2] or $check_users[2] == "") and (!$check_users[1] or $check_users[1] == "")){
if(!file_exists("./inc/install.mdu")){ die('<h2>Error!</h2>CuteNews detected that you do not have users in your users.db.php file and wants to run the install module.<br> if(!file_exists("./inc/install.mdu")){ die('<h2>Error!</h2>CuteNews detected that you do not have users in your users.db.php file and wants to run the install module.<br>
However, the install module (<b>./inc/install.mdu</b>) can not be located, please reupload this file and make sure you set the proper permissions so the installation can continue.'); } However, the install module (<b>./inc/install.mdu</b>) can not be located, please reupload this file and make sure you set the proper permissions so the installation can continue.'); }
require("./inc/install.mdu"); require("./inc/install.mdu");
die(); die();
} }
require_once("./data/config.php"); require_once("./data/config.php");
if(isset($config_skin) and $config_skin != "" and file_exists("./skins/${config_skin}.skin.php")){ if(isset($config_skin) and $config_skin != "" and file_exists("./skins/${config_skin}.skin.php")){
require_once("./skins/${config_skin}.skin.php"); require_once("./skins/${config_skin}.skin.php");
}else{ }else{
$using_safe_skin = true; $using_safe_skin = true;
require_once("./skins/default.skin.php"); require_once("./skins/default.skin.php");
} }
b64dck(); b64dck();
if($config_use_sessions){ if($config_use_sessions){
@session_start(); @session_start();
@header("Cache-control: private"); @header("Cache-control: private");
} }
if($action == "logout") if($action == "logout")
{ {
setcookie("md5_password",""); setcookie("md5_password","");
setcookie("username",""); setcookie("username","");
setcookie("login_referer",""); setcookie("login_referer","");
if($config_use_sessions){ if($config_use_sessions){
@session_destroy(); @session_destroy();
@session_unset(); @session_unset();
setcookie(session_name(),""); setcookie(session_name(),"");
} }
msg("info", "Logout", "You are now logged out, <a href=\"$PHP_SELF\">login</a><br /><br>"); msg("info", "Logout", "You are now logged out, <a href=\"$PHP_SELF\">login</a><br /><br>");
} }
$is_loged_in = FALSE; $is_loged_in = FALSE;
$cookie_logged = FALSE; $cookie_logged = FALSE;
$session_logged = FALSE; $session_logged = FALSE;
$temp_arr = explode("?", $HTTP_REFERER); $temp_arr = explode("?", $HTTP_REFERER);
$HTTP_REFERER = $temp_arr[0]; $HTTP_REFERER = $temp_arr[0];
if(substr($HTTP_REFERER, -1) == "/"){ $HTTP_REFERER.= "index.php"; } if(substr($HTTP_REFERER, -1) == "/"){ $HTTP_REFERER.= "index.php"; }
// Check if The User is Identified // Check if The User is Identified
if($config_use_cookies == TRUE){ if($config_use_cookies == TRUE){
/* Login Authorization using COOKIES */ /* Login Authorization using COOKIES */
if(isset($username)) if(isset($username))
{ {
if(isset($HTTP_COOKIE_VARS["md5_password"])){ $cmd5_password = $HTTP_COOKIE_VARS["md5_password"]; } if(isset($HTTP_COOKIE_VARS["md5_password"])){ $cmd5_password = $HTTP_COOKIE_VARS["md5_password"]; }
elseif(isset($_COOKIE["md5_password"])){ $cmd5_password = $_COOKIE["md5_password"]; } elseif(isset($_COOKIE["md5_password"])){ $cmd5_password = $_COOKIE["md5_password"]; }
else{ $cmd5_password = md5($password); } else{ $cmd5_password = md5($password); }
// Do we have correct username and password ? // Do we have correct username and password ?
if(check_login($username, $cmd5_password)) if(check_login($username, $cmd5_password))
{ {
if($action == 'dologin'){ if($action == 'dologin'){
setcookie("lastusername", $username, time()+1012324305); setcookie("lastusername", $username, time()+1012324305);
if($rememberme == 'yes'){ if($rememberme == 'yes'){
setcookie("username", $username, time()+60*60*24*30); setcookie("username", $username, time()+60*60*24*30);
setcookie("md5_password", $cmd5_password, time()+60*60*24*30); setcookie("md5_password", $cmd5_password, time()+60*60*24*30);
} }
else{ else{
setcookie("username", $username); setcookie("username", $username);
setcookie("md5_password", $cmd5_password); setcookie("md5_password", $cmd5_password);
} }
} }
$cookie_logged = TRUE; $cookie_logged = TRUE;
}else{ }else{
setcookie("username", FALSE); setcookie("username", FALSE);
setcookie("md5_password", FALSE); setcookie("md5_password", FALSE);
$result = "<font color=red>Wrong username or password</font>"; $result = "<font color=red>Wrong username or password</font>";
$cookie_logged = FALSE; $cookie_logged = FALSE;
} }
} }
/* END Login Authorization using COOKIES */ /* END Login Authorization using COOKIES */
} }
if($config_use_sessions == TRUE){ if($config_use_sessions == TRUE){
/* Login Authorization using SESSIONS */ /* Login Authorization using SESSIONS */
if(isset($HTTP_X_FORWARDED_FOR)){ $ip = $HTTP_X_FORWARDED_FOR; } if(isset($HTTP_X_FORWARDED_FOR)){ $ip = $HTTP_X_FORWARDED_FOR; }
elseif(isset($HTTP_CLIENT_IP)) { $ip = $HTTP_CLIENT_IP; } elseif(isset($HTTP_CLIENT_IP)) { $ip = $HTTP_CLIENT_IP; }
if($ip == "") { $ip = $REMOTE_ADDR; } if($ip == "") { $ip = $REMOTE_ADDR; }
if($ip == "") { $ip = "not detected";} if($ip == "") { $ip = "not detected";}
if($action == "dologin") if($action == "dologin")
{ {
$md5_password = md5($password); $md5_password = md5($password);
if(check_login($username, $md5_password)){ if(check_login($username, $md5_password)){
$session_logged = TRUE; $session_logged = TRUE;
@session_register('username'); @session_register('username');
@session_register('md5_password'); @session_register('md5_password');
@session_register('ip'); @session_register('ip');
@session_register('login_referer'); @session_register('login_referer');
$_SESSION['username'] = "$username"; $_SESSION['username'] = "$username";
$_SESSION['md5_password'] = "$md5_password"; $_SESSION['md5_password'] = "$md5_password";
$_SESSION['ip'] = "$ip"; $_SESSION['ip'] = "$ip";
$_SESSION['login_referer'] = "$HTTP_REFERER"; $_SESSION['login_referer'] = "$HTTP_REFERER";
}else{ }else{
$result = "<font color=red>Wrong username and/or password</font>"; $result = "<font color=red>Wrong username and/or password</font>";
$session_logged = FALSE; $session_logged = FALSE;
} }
}elseif(isset($_SESSION['username'])){ // Check the if member is using valid username/password }elseif(isset($_SESSION['username'])){ // Check the if member is using valid username/password
if(check_login($_SESSION['username'], $_SESSION['md5_password'])){ if(check_login($_SESSION['username'], $_SESSION['md5_password'])){
if($_SESSION['ip'] != $ip){ $session_logged = FALSE; $result = "The IP in the session doesn not match with your IP"; } if($_SESSION['ip'] != $ip){ $session_logged = FALSE; $result = "The IP in the session doesn not match with your IP"; }
else{ $session_logged = TRUE; } else{ $session_logged = TRUE; }
}else{ }else{
$result = "<font color=red>Wrong username and/or password !!!</font>"; $result = "<font color=red>Wrong username and/or password !!!</font>";
$session_logged = FALSE; $session_logged = FALSE;
} }
} }
if(!$username){ $username = $_SESSION['username']; } if(!$username){ $username = $_SESSION['username']; }
/* END Login Authorization using SESSIONS */ /* END Login Authorization using SESSIONS */
} }
########################### ###########################
if($session_logged == TRUE or $cookie_logged == TRUE){ if($session_logged == TRUE or $cookie_logged == TRUE){
if($action == 'dologin'){ if($action == 'dologin'){
//------------------------------------------- //-------------------------------------------
// Modify the Last Login Date of the user // Modify the Last Login Date of the user
//------------------------------------------- //-------------------------------------------
$old_users_db = $all_users_db; $old_users_db = $all_users_db;
$modified_users = fopen("./data/users.db.php", "w"); $modified_users = fopen("./data/users.db.php", "w");
foreach($old_users_db as $old_users_db_line){ foreach($old_users_db as $old_users_db_line){
$old_users_db_arr = explode("|", $old_users_db_line); $old_users_db_arr = explode("|", $old_users_db_line);
if($member_db[0] != $old_users_db_arr[0]){ if($member_db[0] != $old_users_db_arr[0]){
fwrite($modified_users, "$old_users_db_line"); fwrite($modified_users, "$old_users_db_line");
}else{ }else{
fwrite($modified_users, "$old_users_db_arr[0]|$old_users_db_arr[1]|$old_users_db_arr[2]|$old_users_db_arr[3]|$old_users_db_arr[4]|$old_users_db_arr[5]|$old_users_db_arr[6]|$old_users_db_arr[7]|$old_users_db_arr[8]|".time()."||\n"); fwrite($modified_users, "$old_users_db_arr[0]|$old_users_db_arr[1]|$old_users_db_arr[2]|$old_users_db_arr[3]|$old_users_db_arr[4]|$old_users_db_arr[5]|$old_users_db_arr[6]|$old_users_db_arr[7]|$old_users_db_arr[8]|".time()."||\n");
} }
} }
fclose($modified_users); fclose($modified_users);
} }
$is_loged_in = TRUE; $is_loged_in = TRUE;
} }
########################### ###########################
// If User is Not Logged In, Display The Login Page // If User is Not Logged In, Display The Login Page
if($is_loged_in == FALSE) if($is_loged_in == FALSE)
{ {
if($config_use_sessions){ if($config_use_sessions){
@session_destroy(); @session_destroy();
@session_unset(); @session_unset();
} }
// setcookie("username",""); // setcookie("username","");
// setcookie("password",""); // setcookie("password","");
// setcookie("md5_password",""); // setcookie("md5_password","");
// setcookie("login_referer",""); // setcookie("login_referer","");
echoheader("user","Please Login"); echoheader("user","Please Login");
if($config_allow_registration == "yes"){ $allow_reg_status = "<a href='register.php'>(register)</a> "; }else{ $allow_reg_status = ""; } if($config_allow_registration == "yes"){ $allow_reg_status = "<a href='register.php'>(register)</a> "; }else{ $allow_reg_status = ""; }
echo " echo "
<table width=\"100%\" border=0 cellpadding=1 cellspacing=0> <table width=\"100%\" border=0 cellpadding=1 cellspacing=0>
<form name=login action='$PHP_SELF' method=post> <form name=login action='$PHP_SELF' method=post>
<tr> <tr>
<td width=80>Username: </td> <td width=80>Username: </td>
<td width='160'><input tabindex=1 type=text name=username value='$lastusername' style='width:150;'></td> <td width='160'><input tabindex=1 type=text name=username value='$lastusername' style='width:150;'></td>
<td>&nbsp;$allow_reg_status</a></td> <td>&nbsp;$allow_reg_status</a></td>
</tr> </tr>
<tr> <tr>
<td>Password: </td> <td>Password: </td>
<td><input type=password name=password style='width:150'></td> <td><input type=password name=password style='width:150'></td>
<td>&nbsp;<a href='register.php?action=lostpass'>(lost password)</a> </td> <td>&nbsp;<a href='register.php?action=lostpass'>(lost password)</a> </td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td style='text-align:left'> <td style='text-align:left'>
<input accesskey='s' type=submit style=\"width:150; background-color: #F3F3F3;\" value=' Login... '><br/> <input accesskey='s' type=submit style=\"width:150; background-color: #F3F3F3;\" value=' Login... '><br/>
</td> </td>
<td style='text-align:left'><label for=rememberme title='Remmber me for 30 days, Do not use on Public-Terminals!'> <td style='text-align:left'><label for=rememberme title='Remmber me for 30 days, Do not use on Public-Terminals!'>
<input id=rememberme type=checkbox value=yes style=\"border:0px;\" name=rememberme> <input id=rememberme type=checkbox value=yes style=\"border:0px;\" name=rememberme>
Remember Me</label> </td> Remember Me</label> </td>
</tr> </tr>
<tr> <tr>
<td align=center colspan=4 style='text-align:left;'>$result</td> <td align=center colspan=4 style='text-align:left;'>$result</td>
</tr> </tr>
<input type=hidden name=action value=dologin> <input type=hidden name=action value=dologin>
</form> </form>
</table>"; </table>";
echofooter(); echofooter();
} }
elseif($is_loged_in == TRUE) elseif($is_loged_in == TRUE)
{ {
//---------------------------------- //----------------------------------
// Check Referer // Check Referer
//---------------------------------- //----------------------------------
if($config_check_referer == TRUE){ if($config_check_referer == TRUE){
$self = $_SERVER["SCRIPT_NAME"]; $self = $_SERVER["SCRIPT_NAME"];
if($self == ""){ $self = $_SERVER["REDIRECT_URL"]; } if($self == ""){ $self = $_SERVER["REDIRECT_URL"]; }
if($self == ""){ $self = "index.php"; } if($self == ""){ $self = "index.php"; }
if(!eregi("$self",$HTTP_REFERER) and $HTTP_REFERER != ""){ if(!eregi("$self",$HTTP_REFERER) and $HTTP_REFERER != ""){
die("<h2>Sorry but your access to this page was denied !</h2><br>try to <a href=\"?action=logout\">logout</a> and then login again<br>To turn off this security check, change \$config_check_referer in index.php to FALSE"); die("<h2>Sorry but your access to this page was denied !</h2><br>try to <a href=\"?action=logout\">logout</a> and then login again<br>To turn off this security check, change \$config_check_referer in index.php to FALSE");
} }
} }
// ******************************************************************************** // ********************************************************************************
// Include System Module // Include System Module
// ******************************************************************************** // ********************************************************************************
if($_SERVER['QUERY_STRING'] == "debug"){ debug(); } if($_SERVER['QUERY_STRING'] == "debug"){ debug(); }
//name of mod //access //name of mod //access
$system_modules = array('addnews' => 'user', $system_modules = array('addnews' => 'user',
'editnews' => 'user', 'editnews' => 'user',
'main' => 'user', 'main' => 'user',
'options' => 'user', 'options' => 'user',
'images' => 'user', 'images' => 'user',
'editusers' => 'admin', 'editusers' => 'admin',
'editcomments' => 'admin', 'editcomments' => 'admin',
'tools' => 'admin', 'tools' => 'admin',
'ipban' => 'admin', 'ipban' => 'admin',
'about' => 'user', 'about' => 'user',
'preview' => 'user', 'preview' => 'user',
'categories' => 'admin', 'categories' => 'admin',
'massactions' => 'user', 'massactions' => 'user',
'help' => 'user', 'help' => 'user',
'snr' => 'admin', 'snr' => 'admin',
'debug' => 'admin', 'debug' => 'admin',
'wizards' => 'admin', 'wizards' => 'admin',
); );
if($mod == ""){ require("./inc/main.mdu"); } if($mod == ""){ require("./inc/main.mdu"); }
elseif( $system_modules[$mod] ) elseif( $system_modules[$mod] )
{ {
if( $member_db[1] == 4 and $mod != 'options'){ msg('error', 'Error!', 'Access Denied for your user-level (commenter)'); } if( $member_db[1] == 4 and $mod != 'options'){ msg('error', 'Error!', 'Access Denied for your user-level (commenter)'); }
elseif( $system_modules[$mod] == "user"){ require("./inc/". $mod . ".mdu"); } elseif( $system_modules[$mod] == "user"){ require("./inc/". $mod . ".mdu"); }
elseif( $system_modules[$mod] == "admin" and $member_db[1] == 1){ require("./inc/". $mod . ".mdu"); } elseif( $system_modules[$mod] == "admin" and $member_db[1] == 1){ require("./inc/". $mod . ".mdu"); }
elseif( $system_modules[$mod] == "admin" and $member_db[1] != 1){ msg("error", "Access denied", "Only admin can access this module"); exit; } elseif( $system_modules[$mod] == "admin" and $member_db[1] != 1){ msg("error", "Access denied", "Only admin can access this module"); exit; }
else{ die("Module access must be set to <b>user</b> or <b>admin</b>"); } else{ die("Module access must be set to <b>user</b> or <b>admin</b>"); }
} }
else{ die("$mod is NOT a valid module"); } else{ die("$mod is NOT a valid module"); }
} }
echo"<!-- execution time: ".$Timer->stop()." -->"; echo"<!-- execution time: ".$Timer->stop()." -->";
?> ?>
<?PHP <?PHP
error_reporting (E_ALL ^E_NOTICE); error_reporting (E_ALL ^E_NOTICE);
require_once("./inc/functions.inc.php"); require_once("./inc/functions.inc.php");
require_once("./data/config.php"); require_once("./data/config.php");
require_once("./skins/${config_skin}.skin.php"); require_once("./skins/${config_skin}.skin.php");
// Check if CuteNews is not installed // Check if CuteNews is not installed
$all_users_db = file("./data/users.db.php"); $all_users_db = file("./data/users.db.php");
$check_users = $all_users_db; $check_users = $all_users_db;
$check_users[1] = trim($check_users[1]); $check_users[1] = trim($check_users[1]);
$check_users[2] = trim($check_users[2]); $check_users[2] = trim($check_users[2]);
if((!$check_users[2] or $check_users[2] == "") and (!$check_users[1] or $check_users[1] == "")){ if((!$check_users[2] or $check_users[2] == "") and (!$check_users[1] or $check_users[1] == "")){
if(!file_exists("./inc/install.mdu")){ die('<h2>Error!</h2>CuteNews detected that you do not have users in your users.db.php file and wants to run the install module.<br> if(!file_exists("./inc/install.mdu")){ die('<h2>Error!</h2>CuteNews detected that you do not have users in your users.db.php file and wants to run the install module.<br>
However, the install module (<b>./inc/install.mdu</b>) can not be located, please reupload this file and make sure you set the proper permissions so the installation can continue.'); } However, the install module (<b>./inc/install.mdu</b>) can not be located, please reupload this file and make sure you set the proper permissions so the installation can continue.'); }
msg("info", "CuteNews Not Installed", "CuteNews is not properly installed (users missing) <a href=index.php>go to index.php</a>"); msg("info", "CuteNews Not Installed", "CuteNews is not properly installed (users missing) <a href=index.php>go to index.php</a>");
} }
$register_level = $config_registration_level; $register_level = $config_registration_level;
if($action == "doregister"){ if($action == "doregister"){
if($config_allow_registration != "yes"){ msg("error","Error", "User registration is Disabled"); } if($config_allow_registration != "yes"){ msg("error","Error", "User registration is Disabled"); }
if(!$regusername){ msg("error","Error !!!", "Username can not be blank"); } if(!$regusername){ msg("error","Error !!!", "Username can not be blank"); }
if(!$regpassword){ msg("error","Error !!!", "Password can not be blank"); } if(!$regpassword){ msg("error","Error !!!", "Password can not be blank"); }
if(!$regemail) { msg("error","Error !!!", "Email can not be blank"); } if(!$regemail) { msg("error","Error !!!", "Email can not be blank"); }
$regusername = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regusername); $regusername = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regusername);
$regnickname = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regnickname); $regnickname = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regnickname);
$regemail = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regemail); $regemail = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regemail);
$regpassword = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regpassword); $regpassword = preg_replace( array("'<'", "'>'", "'\n'", "'\r'", "'\|'"), array("", "", "", "", ""), $regpassword);
if(!preg_match("/^[\.A-z0-9_\-]{1,15}$/i", $regusername)){ msg("error","Error !!!", "$regusername Your username must only contain valid characters, numbers and the symbol '_'"); } if(!preg_match("/^[\.A-z0-9_\-]{1,15}$/i", $regusername)){ msg("error","Error !!!", "$regusername Your username must only contain valid characters, numbers and the symbol '_'"); }
if(!preg_match("/^[\.A-z0-9_\-]{1,15}$/i", $regnickname)){ msg("error","Error !!!", "Your nickname must only contain valid characters, numbers and the symbol '_'"); } if(!preg_match("/^[\.A-z0-9_\-]{1,15}$/i", $regnickname)){ msg("error","Error !!!", "Your nickname must only contain valid characters, numbers and the symbol '_'"); }
if(!preg_match("/^[\.A-z0-9_\-]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $regemail)){ msg("error","Error !!!", "Not valid Email."); } if(!preg_match("/^[\.A-z0-9_\-]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $regemail)){ msg("error","Error !!!", "Not valid Email."); }
if(!preg_match("/^[\.A-z0-9_\-]{1,15}$/i", $regpassword)){ msg("error","Error !!!", "Your password must conatain only valid characters and numbers"); } if(!preg_match("/^[\.A-z0-9_\-]{1,15}$/i", $regpassword)){ msg("error","Error !!!", "Your password must conatain only valid characters and numbers"); }
$all_users = file("./data/users.db.php"); $all_users = file("./data/users.db.php");
foreach($all_users as $user_line) foreach($all_users as $user_line)
{ {
$user_arr = explode("|", $user_line); $user_arr = explode("|", $user_line);
if($user_arr[2] == $regusername){ msg("error", "Error", "This username is already taken"); } if($user_arr[2] == $regusername){ msg("error", "Error", "This username is already taken"); }
} }
$add_time = time()+($config_date_adjust*60); $add_time = time()+($config_date_adjust*60);
$regpassword = md5($regpassword); $regpassword = md5($regpassword);
$old_users_file = file("./data/users.db.php"); $old_users_file = file("./data/users.db.php");
$new_users_file = fopen("./data/users.db.php", "a"); $new_users_file = fopen("./data/users.db.php", "a");
fwrite($new_users_file, "$add_time|$register_level|$regusername|$regpassword|$regnickname|$regemail|0|0||||\n"); fwrite($new_users_file, "$add_time|$register_level|$regusername|$regpassword|$regnickname|$regemail|0|0||||\n");
fclose($new_users_file); fclose($new_users_file);
if($config_notify_registration == "yes" and $config_notify_status == "active"){ if($config_notify_registration == "yes" and $config_notify_status == "active"){
send_mail("$config_notify_email", "CuteNews - New User Registered", "New user ($regusername) has just registered:\nUsername: $regusername\nNickname: $regnickname\nEmail: $regemail\n "); send_mail("$config_notify_email", "CuteNews - New User Registered", "New user ($regusername) has just registered:\nUsername: $regusername\nNickname: $regnickname\nEmail: $regemail\n ");
} }
msg("user", "User Added", "You were successfully added to users database.<br>You can now login <a href=index.php>here</a>"); msg("user", "User Added", "You were successfully added to users database.<br>You can now login <a href=index.php>here</a>");
}elseif($action == "lostpass"){ }elseif($action == "lostpass"){
echoheader("user","Lost Password"); echoheader("user","Lost Password");
echo"<form method=post action=\"$PHP_SELF\"><table border=0 cellpading=0 cellspacing=0 width=\"654\" height=\"59\" > echo"<form method=post action=\"$PHP_SELF\"><table border=0 cellpading=0 cellspacing=0 width=\"654\" height=\"59\" >
<td width=\"18\" height=\"11\"> <td width=\"18\" height=\"11\">
<td width=\"71\" height=\"11\" align=\"left\"> <td width=\"71\" height=\"11\" align=\"left\">
Username<td width=\"203\" height=\"11\" align=\"left\"> Username<td width=\"203\" height=\"11\" align=\"left\">
<input type=text name=user seize=20> <input type=text name=user seize=20>
<td width=\"350\" height=\"26\" align=\"left\" rowspan=\"2\" valign=\"middle\"> <td width=\"350\" height=\"26\" align=\"left\" rowspan=\"2\" valign=\"middle\">
If the username and email match in our users database,<br> and email with furher instructions will be sent to you. If the username and email match in our users database,<br> and email with furher instructions will be sent to you.
<tr> <tr>
<td width=\"18\" valign=\"top\" height=\"15\"> <td width=\"18\" valign=\"top\" height=\"15\">
<td width=\"71\" height=\"15\" align=\"left\"> <td width=\"71\" height=\"15\" align=\"left\">
Email Email
<td width=\"203\" height=\"15\" align=\"left\"> <td width=\"203\" height=\"15\" align=\"left\">
<input type=text name=email size=\"20\"> <input type=text name=email size=\"20\">
</tr> </tr>
<tr> <tr>
<td width=\"18\" valign=\"top\" height=\"15\"> <td width=\"18\" valign=\"top\" height=\"15\">
<td width=\"628\" height=\"15\" align=\"left\" colspan=\"3\"> <td width=\"628\" height=\"15\" align=\"left\" colspan=\"3\">
&nbsp; &nbsp;
</tr> </tr>
<tr> <tr>
<td width=\"18\" valign=\"top\" height=\"15\"> <td width=\"18\" valign=\"top\" height=\"15\">
<td width=\"628\" height=\"15\" align=\"left\" colspan=\"3\"> <td width=\"628\" height=\"15\" align=\"left\" colspan=\"3\">
<input type=submit value=\"Send me the Confirmation\"> <input type=submit value=\"Send me the Confirmation\">
</tr> </tr>
<input type=hidden name=action value=validate> <input type=hidden name=action value=validate>
<input type=hidden name=mod value=lostpass> <input type=hidden name=mod value=lostpass>
<tr> <tr>
<td width=\"18\" height=\"27\"> <td width=\"18\" height=\"27\">
<td width=\"632\" height=\"27\" colspan=\"3\"> <td width=\"632\" height=\"27\" colspan=\"3\">
</tr></table></form>"; </tr></table></form>";
echofooter(); echofooter();
}elseif($action == "validate"){ }elseif($action == "validate"){
if(!isset($user) or !$user or $user == '' or !isset($email) or !$email or $email == ''){ msg("error", "Error !!!", "All the fields are required"); } if(!isset($user) or !$user or $user == '' or !isset($email) or !$email or $email == ''){ msg("error", "Error !!!", "All the fields are required"); }
$found = FALSE; $found = FALSE;
$all_users = file("./data/users.db.php"); $all_users = file("./data/users.db.php");
foreach($all_users as $user_line){ foreach($all_users as $user_line){
$user_arr = explode("|", $user_line); $user_arr = explode("|", $user_line);
if($user_arr[2] == $user and $user_arr[5] == $email){ $sstring = "${user_arr[0]}${user_arr[3]}"; $found = TRUE; break;} if($user_arr[2] == $user and $user_arr[5] == $email){ $sstring = "${user_arr[0]}${user_arr[3]}"; $found = TRUE; break;}
} }
if(!$found){ msg("error", "Error !!!", "The username/email you enter did not match in our users database"); } if(!$found){ msg("error", "Error !!!", "The username/email you enter did not match in our users database"); }
else{ else{
$confirm_url = "$config_http_script_dir/register.php?a=dsp&s=$sstring"; $confirm_url = "$config_http_script_dir/register.php?a=dsp&s=$sstring";
$message = "Hi,\n Someone requested your password to be changed, if this is the desired action and you want to change your password please follow this link: $confirm_url ."; $message = "Hi,\n Someone requested your password to be changed, if this is the desired action and you want to change your password please follow this link: $confirm_url .";
mail("$email", "Confirmation ( New Password for CuteNews )", $message, mail("$email", "Confirmation ( New Password for CuteNews )", $message,
"From: no-reply@$SERVER_NAME\r\n" "From: no-reply@$SERVER_NAME\r\n"
."X-Mailer: PHP/" . phpversion()) or die("can not send mail"); ."X-Mailer: PHP/" . phpversion()) or die("can not send mail");
msg('info','Confirmation Email',"A confirmation email was sent, please check your inbox for further details."); msg('info','Confirmation Email',"A confirmation email was sent, please check your inbox for further details.");
} }
//Do Send Password //Do Send Password
}elseif($a == "dsp"){ }elseif($a == "dsp"){
if($s == "" or !$s){ msg("error", "Error !!!", "All fields are required"); } if($s == "" or !$s){ msg("error", "Error !!!", "All fields are required"); }
$found = FALSE; $found = FALSE;
$all_users = file("./data/users.db.php"); $all_users = file("./data/users.db.php");
foreach($all_users as $user_line){ foreach($all_users as $user_line){
$user_arr = explode("|", $user_line); $user_arr = explode("|", $user_line);
if($s == "${user_arr[0]}${user_arr[3]}"){ $found = TRUE; break;} if($s == "${user_arr[0]}${user_arr[3]}"){ $found = TRUE; break;}
} }
if(!$found){ msg("error", "Error !!!", "invalid string"); } if(!$found){ msg("error", "Error !!!", "invalid string"); }
else{ else{
$salt = "abchefghjkmnpqrstuvwxyz0123456789"; $salt = "abchefghjkmnpqrstuvwxyz0123456789";
srand((double)microtime()*1000000); srand((double)microtime()*1000000);
for($i=0;$i<9;$i++){ for($i=0;$i<9;$i++){
$new_pass .= $salt{rand(0,33)}; $new_pass .= $salt{rand(0,33)};
} }
$md5_pass = md5($new_pass); $md5_pass = md5($new_pass);
$old_db = file("./data/users.db.php"); $old_db = file("./data/users.db.php");
$new_db = fopen("./data/users.db.php", w); $new_db = fopen("./data/users.db.php", w);
foreach($old_db as $old_db_line){ foreach($old_db as $old_db_line){
$old_db_arr = explode("|", $old_db_line); $old_db_arr = explode("|", $old_db_line);
if($s != "${old_db_arr[0]}${old_db_arr[3]}"){ if($s != "${old_db_arr[0]}${old_db_arr[3]}"){
fwrite($new_db,"$old_db_line"); fwrite($new_db,"$old_db_line");
}else{ }else{
fwrite($new_db,"$old_db_arr[0]|$old_db_arr[1]|$old_db_arr[2]|$md5_pass|$old_db_arr[4]|$old_db_arr[5]|$old_db_arr[6]|$old_db_arr[7]|||\n"); fwrite($new_db,"$old_db_arr[0]|$old_db_arr[1]|$old_db_arr[2]|$md5_pass|$old_db_arr[4]|$old_db_arr[5]|$old_db_arr[6]|$old_db_arr[7]|||\n");
} }
} }
fclose($new_db); fclose($new_db);
$message = "Hi $user_arr[2],\n Your new password for CuteNews is $new_pass, please after you login change this password."; $message = "Hi $user_arr[2],\n Your new password for CuteNews is $new_pass, please after you login change this password.";
mail("$user_arr[5]", "Your New Password for CuteNews", $message, mail("$user_arr[5]", "Your New Password for CuteNews", $message,
"From: no-reply@$SERVER_NAME\r\n" "From: no-reply@$SERVER_NAME\r\n"
."X-Mailer: PHP/" . phpversion()) or die("can not send mail"); ."X-Mailer: PHP/" . phpversion()) or die("can not send mail");
msg("info", "Password Sent", "The new password for <b> $user_arr[2]</b> was sent to the email."); msg("info", "Password Sent", "The new password for <b> $user_arr[2]</b> was sent to the email.");
} }
}else{ }else{
if($config_allow_registration != "yes"){ msg("error","Error", "User registration is Disabled"); } if($config_allow_registration != "yes"){ msg("error","Error", "User registration is Disabled"); }
echoheader("user", "User Registration"); echoheader("user", "User Registration");
echo<<<HTML echo<<<HTML
<table leftmargin=0 marginheight=0 marginwidth=0 topmargin=0 border=0 height=100% cellspacing=0> <table leftmargin=0 marginheight=0 marginwidth=0 topmargin=0 border=0 height=100% cellspacing=0>
<form name=login action="$PHP_SELF" method=post> <form name=login action="$PHP_SELF" method=post>
<tr> <tr>
<td width=80>Username: </td> <td width=80>Username: </td>
<td><input tabindex=1 type=text name=regusername style="width:134" size="20"></td> <td><input tabindex=1 type=text name=regusername style="width:134" size="20"></td>
</tr> </tr>
<tr> <tr>
<td width=80>Nickname: </td> <td width=80>Nickname: </td>
<td><input tabindex=1 type=text name=regnickname style="width:134" size="20"></td> <td><input tabindex=1 type=text name=regnickname style="width:134" size="20"></td>
</tr> </tr>
<tr> <tr>
<td width=80>Password: </td> <td width=80>Password: </td>
<td><input tabindex=1 type=text name=regpassword style="width:134" size="20"></td> <td><input tabindex=1 type=text name=regpassword style="width:134" size="20"></td>
</tr> </tr>
<tr> <tr>
<td width=80>Email: </td> <td width=80>Email: </td>
<td><input tabindex=1 type=text name=regemail style="width:134" size="20"></td> <td><input tabindex=1 type=text name=regemail style="width:134" size="20"></td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td ><input accesskey="s" type=submit style="background-color: #F3F3F3;" value='Register'></td> <td ><input accesskey="s" type=submit style="background-color: #F3F3F3;" value='Register'></td>
</tr> </tr>
<tr> <tr>
<td align=center colspan=2>$result</td> <td align=center colspan=2>$result</td>
</tr> </tr>
<input type=hidden name=action value=doregister> <input type=hidden name=action value=doregister>
</form> </form>
</table> </table>
HTML; HTML;
echofooter(); echofooter();
} }
?> ?>
<?PHP <?PHP
include('./data/rss_config.php'); include('./data/rss_config.php');
if(!isset($rss_news_include_url) or !$rss_news_include_url or $rss_news_include_url == ''){ if(!isset($rss_news_include_url) or !$rss_news_include_url or $rss_news_include_url == ''){
die("The RSS is not configured.<br>Please do this from: <strong>CuteNews > Options > Implementation Wizards > RSS</strong>"); die("The RSS is not configured.<br>Please do this from: <strong>CuteNews > Options > Implementation Wizards > RSS</strong>");
} }
header("Content-type: text/xml"); header("Content-type: text/xml");
echo"<?xml version=\"1.0\" encoding=\"$rss_encoding\" ?> echo"<?xml version=\"1.0\" encoding=\"$rss_encoding\" ?>
<?xml-stylesheet type=\"text/css\" href=\"skins/rss_style.css\" ?> <?xml-stylesheet type=\"text/css\" href=\"skins/rss_style.css\" ?>
<rss version=\"2.0\" > <rss version=\"2.0\" >
<channel> <channel>
<title>$rss_title</title> <title>$rss_title</title>
<link>$rss_news_include_url</link> <link>$rss_news_include_url</link>
<language>$rss_language</language> <language>$rss_language</language>
<description></description> <description></description>
<!-- <docs>This is an RSS 2.0 file intended to be viewed in a newsreader or syndicated to another site. For more information on RSS check : http://www.feedburner.com/fb/a/aboutrss</docs> --> <!-- <docs>This is an RSS 2.0 file intended to be viewed in a newsreader or syndicated to another site. For more information on RSS check : http://www.feedburner.com/fb/a/aboutrss</docs> -->
<generator>CuteNews</generator> <generator>CuteNews</generator>
"; ";
if(!$_GET[number] or $_GET[number] == ''){ $number = 10;}else{ $number = $_GET[number];} if(!$_GET[number] or $_GET[number] == ''){ $number = 10;}else{ $number = $_GET[number];}
if(!$_GET[only_active] or $_GET[only_active] == ''){ $only_active = TRUE;}else{ $only_active = $_GET[only_active];} if(!$_GET[only_active] or $_GET[only_active] == ''){ $only_active = TRUE;}else{ $only_active = $_GET[only_active];}
$template="rss"; $template="rss";
include("show_news.php"); include("show_news.php");
echo"</channel></rss>"; echo"</channel></rss>";
?> ?>
<?php <?php
error_reporting (E_ALL ^ E_NOTICE); error_reporting (E_ALL ^ E_NOTICE);
$cutepath = __FILE__; $cutepath = __FILE__;
$cutepath = preg_replace( "'\\\search\.php'", "", $cutepath); $cutepath = preg_replace( "'\\\search\.php'", "", $cutepath);
$cutepath = preg_replace( "'/search\.php'", "", $cutepath); $cutepath = preg_replace( "'/search\.php'", "", $cutepath);
$files_arch = array(); $files_arch = array();
require_once("$cutepath/inc/functions.inc.php"); require_once("$cutepath/inc/functions.inc.php");
//check for bad _GET and _POST //check for bad _GET and _POST
if($dosearch == "yes"){ if($dosearch == "yes"){
$check_params = array_merge($_GET, $_POST); $check_params = array_merge($_GET, $_POST);
foreach($check_params as $param_key=>$param_val){ foreach($check_params as $param_key=>$param_val){
if( !empty($param_val) && !preg_match('/^[a-zA-Z0-9\- ]{0,255}$/', $param_val) ){ if( !empty($param_val) && !preg_match('/^[a-zA-Z0-9\- ]{0,255}$/', $param_val) ){
die("Error! the parameter '$param_key' contains illigal characters"); die("Error! the parameter '$param_key' contains illigal characters");
} }
} }
} }
$user_query = cute_query_string($QUERY_STRING, array("search_in_archives", "start_from", "archive", "subaction", "id", "cnshow", $user_query = cute_query_string($QUERY_STRING, array("search_in_archives", "start_from", "archive", "subaction", "id", "cnshow",
"ucat","dosearch", "story", "title", "user", "from_date_day", "from_date_month", "from_date_year", "to_date_day", "to_date_month", "to_date_year")); "ucat","dosearch", "story", "title", "user", "from_date_day", "from_date_month", "from_date_year", "to_date_day", "to_date_month", "to_date_year"));
$user_post_query = cute_query_string($QUERY_STRING, array("search_in_archives", "start_from", "archive", "subaction", "id", "cnshow", $user_post_query = cute_query_string($QUERY_STRING, array("search_in_archives", "start_from", "archive", "subaction", "id", "cnshow",
"ucat","dosearch", "story", "title", "user", "from_date_day", "from_date_month", "from_date_year", "to_date_day", "to_date_month", "to_date_year"), "post"); "ucat","dosearch", "story", "title", "user", "from_date_day", "from_date_month", "from_date_year", "to_date_day", "to_date_month", "to_date_year"), "post");
// Define Users // Define Users
$all_users = file("$cutepath/data/users.db.php"); $all_users = file("$cutepath/data/users.db.php");
$my_names = array(); $my_names = array();
foreach($all_users as $my_user) foreach($all_users as $my_user)
{ {
if(!eregi("<\?",$member_db_line)){ if(!eregi("<\?",$member_db_line)){
$user_arr = explode("|",$my_user); $user_arr = explode("|",$my_user);
if($user_arr[4] != ""){ $my_names[$user_arr[2]] = "$user_arr[4]"; } if($user_arr[4] != ""){ $my_names[$user_arr[2]] = "$user_arr[4]"; }
else{ $my_names[$user_arr[2]] = "$user_arr[2]"; } else{ $my_names[$user_arr[2]] = "$user_arr[2]"; }
} }
} }
// Show Search Form // Show Search Form
echo<<<HTML echo<<<HTML
<script language='javascript' type="text/javascript"> <script language='javascript' type="text/javascript">
function mySelect(form){ function mySelect(form){
form.select(); form.select();
} }
function ShowOrHide(d1, d2) { function ShowOrHide(d1, d2) {
if (d1 != '') DoDiv(d1); if (d1 != '') DoDiv(d1);
if (d2 != '') DoDiv(d2); if (d2 != '') DoDiv(d2);
} }
function DoDiv(id) { function DoDiv(id) {
var item = null; var item = null;
if (document.getElementById) { if (document.getElementById) {
item = document.getElementById(id); item = document.getElementById(id);
} else if (document.all){ } else if (document.all){
item = document.all[id]; item = document.all[id];
} else if (document.layers){ } else if (document.layers){
item = document.layers[id]; item = document.layers[id];
} }
if (!item) { if (!item) {
} }
else if (item.style) { else if (item.style) {
if (item.style.display == "none"){ item.style.display = ""; } if (item.style.display == "none"){ item.style.display = ""; }
else {item.style.display = "none"; } else {item.style.display = "none"; }
}else{ item.visibility = "show"; } }else{ item.visibility = "show"; }
} }
</script> </script>
<form method=GET action="$PHP_SELF?subaction=search"> <form method=GET action="$PHP_SELF?subaction=search">
<input type=hidden name=dosearch value=yes> <input type=hidden name=dosearch value=yes>
<div align="center"> <div align="center">
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<tr> <tr>
<td><table width="100%" cellspacing="0" cellpadding="0"> <td><table width="100%" cellspacing="0" cellpadding="0">
<td width="100%"> <td width="100%">
<p align="right">News <input type=text value="$story" name=story size="24"> <p align="right">News <input type=text value="$story" name=story size="24">
</table></td> </table></td>
</tr> </tr>
<tr> <tr>
<td> <td>
<div id='advanced' style='display:none;z-index:1;'> <div id='advanced' style='display:none;z-index:1;'>
<table width="100%" cellspacing="0" cellpadding="0"> <table width="100%" cellspacing="0" cellpadding="0">
<td width="100%" align="right"> <td width="100%" align="right">
<p align="right">Title&nbsp;<input type=text value="$title" name=title size="24"> <p align="right">Title&nbsp;<input type=text value="$title" name=title size="24">
<tr> <tr>
<td width="100%" align="right">Author&nbsp;<input type=text value="$user" name=user size="24"> <td width="100%" align="right">Author&nbsp;<input type=text value="$user" name=user size="24">
</tr> </tr>
<tr> <tr>
<td width="100%" align="right">From date <td width="100%" align="right">From date
<select name=from_date_day> <select name=from_date_day>
<option value=""> </option> <option value=""> </option>
HTML; HTML;
for($i=1;$i<32;$i++){ for($i=1;$i<32;$i++){
if($from_date_day == $i){ echo"<option selected value=$i>$i</option>"; } if($from_date_day == $i){ echo"<option selected value=$i>$i</option>"; }
else{ echo"<option value=$i>$i</option>"; } else{ echo"<option value=$i>$i</option>"; }
} }
echo"</select><select name=from_date_month> <option value=\"\"> </option>"; echo"</select><select name=from_date_month> <option value=\"\"> </option>";
for($i=1;$i<13;$i++){ for($i=1;$i<13;$i++){
$timestamp = mktime(0,0,0,$i,1,2003); $timestamp = mktime(0,0,0,$i,1,2003);
if($from_date_month == $i){ echo"<option selected value=$i>". date("M", $timestamp) ."</option>"; } if($from_date_month == $i){ echo"<option selected value=$i>". date("M", $timestamp) ."</option>"; }
else{ echo"<option value=$i>". date("M", $timestamp) ."</option>"; } else{ echo"<option value=$i>". date("M", $timestamp) ."</option>"; }
} }
echo"</select><select name=from_date_year> <option value=\"\"> </option>"; echo"</select><select name=from_date_year> <option value=\"\"> </option>";
for($i=2003;$i<2011;$i++){ for($i=2003;$i<2011;$i++){
if($from_date_year == $i){ echo"<option selected value=$i>$i</option>"; } if($from_date_year == $i){ echo"<option selected value=$i>$i</option>"; }
else{ echo"<option value=$i>$i</option>"; } else{ echo"<option value=$i>$i</option>"; }
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
echo<<<HTML echo<<<HTML
</tr> </tr>
<tr> <tr>
<td width="100%" align="right">To date <td width="100%" align="right">To date
<select name=to_date_day> <select name=to_date_day>
<option value=""> </option> <option value=""> </option>
HTML; HTML;
for($i=1;$i<32;$i++){ for($i=1;$i<32;$i++){
if($to_date_day == $i){ echo"<option selected value=$i>$i</option>"; } if($to_date_day == $i){ echo"<option selected value=$i>$i</option>"; }
else{ echo"<option value=$i>$i</option>"; } else{ echo"<option value=$i>$i</option>"; }
} }
echo"</select><select name=to_date_month><option value=\"\"> </option>"; echo"</select><select name=to_date_month><option value=\"\"> </option>";
for($i=1;$i<13;$i++){ for($i=1;$i<13;$i++){
$timestamp = mktime(0,0,0,$i,1,2003); $timestamp = mktime(0,0,0,$i,1,2003);
if($to_date_month == $i){ echo"<option selected value=$i>". date("M", $timestamp) ."</option>"; } if($to_date_month == $i){ echo"<option selected value=$i>". date("M", $timestamp) ."</option>"; }
else{ echo"<option value=$i>". date("M", $timestamp) ."</option>"; } else{ echo"<option value=$i>". date("M", $timestamp) ."</option>"; }
} }
echo"</select><select name=to_date_year><option value=\"\"> </option>"; echo"</select><select name=to_date_year><option value=\"\"> </option>";
for($i=2003;$i<2011;$i++){ for($i=2003;$i<2011;$i++){
if($to_date_year == $i){ echo"<option selected value=$i>$i</option>"; } if($to_date_year == $i){ echo"<option selected value=$i>$i</option>"; }
else{ echo"<option value=$i>$i</option>"; } else{ echo"<option value=$i>$i</option>"; }
} }
if($search_in_archives){ $selected_search_arch = "checked=\"checked\""; } if($search_in_archives){ $selected_search_arch = "checked=\"checked\""; }
echo<<<HTML echo<<<HTML
</select> </select>
</tr> </tr>
<tr> <tr>
<td width="100%" align="right"> <td width="100%" align="right">
<p align="right"><label>Search and archives <p align="right"><label>Search and archives
<input type=checkbox $selected_search_arch name="search_in_archives" value="TRUE"></label> <input type=checkbox $selected_search_arch name="search_in_archives" value="TRUE"></label>
</tr> </tr>
</table> </table>
</div> </div>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
<p align="right">&nbsp; <p align="right">&nbsp;
<a href="javascript:ShowOrHide('advanced','')">advanced</a>&nbsp;&nbsp; <input type=submit value=Search> <a href="javascript:ShowOrHide('advanced','')">advanced</a>&nbsp;&nbsp; <input type=submit value=Search>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
$user_post_query $user_post_query
</form> </form>
<center> <center>
HTML; HTML;
// Don't edit below this line unless you know what you are doing !!! // Don't edit below this line unless you know what you are doing !!!
if($dosearch == "yes") if($dosearch == "yes")
{ {
if( $from_date_day != "" and $from_date_month != "" and $from_date_year != "" and $to_date_day != "" and $to_date_month != "" and $to_date_year != "" ) if( $from_date_day != "" and $from_date_month != "" and $from_date_year != "" and $to_date_day != "" and $to_date_month != "" and $to_date_year != "" )
{ {
$date_from = mktime(0,0,0,$from_date_month,$from_date_day,$from_date_year); $date_from = mktime(0,0,0,$from_date_month,$from_date_day,$from_date_year);
$date_to = mktime(0,0,0,$to_date_month,$to_date_day,$to_date_year); $date_to = mktime(0,0,0,$to_date_month,$to_date_day,$to_date_year);
$do_date = TRUE; $do_date = TRUE;
} }
$story = trim($story); $story = trim($story);
if($search_in_archives){ if($search_in_archives){
if(!$handle = opendir("$cutepath/data/archives")){ die("<center>Can not open directory $cutepath/data/archives "); } if(!$handle = opendir("$cutepath/data/archives")){ die("<center>Can not open directory $cutepath/data/archives "); }
while (false !== ($file = readdir($handle))) while (false !== ($file = readdir($handle)))
{ {
if($file != "." and $file != ".." and eregi("news", $file)) if($file != "." and $file != ".." and eregi("news", $file))
{ {
$files_arch[] = "$cutepath/data/archives/$file"; $files_arch[] = "$cutepath/data/archives/$file";
} }
} }
} }
$files_arch[] = "$cutepath/data/news.txt"; $files_arch[] = "$cutepath/data/news.txt";
foreach($files_arch as $file) foreach($files_arch as $file)
{ {
$archive = FALSE; $archive = FALSE;
if(ereg("([[:digit:]]{0,})\.news\.arch", $file, $regs)){ $archive = $regs[1]; } if(ereg("([[:digit:]]{0,})\.news\.arch", $file, $regs)){ $archive = $regs[1]; }
$all_news_db = file("$file"); $all_news_db = file("$file");
foreach($all_news_db as $news_line){ foreach($all_news_db as $news_line){
$news_db_arr = explode("|",$news_line); $news_db_arr = explode("|",$news_line);
$found = 0; $found = 0;
$fuser = FALSE; $fuser = FALSE;
$ftitle = FALSE; $ftitle = FALSE;
$fstory = FALSE; $fstory = FALSE;
if($title and @preg_match("/$title/i", "$news_db_arr[2]")){ $ftitle = TRUE; } if($title and @preg_match("/$title/i", "$news_db_arr[2]")){ $ftitle = TRUE; }
if($user and @preg_match("/\b$user\b/i", "$news_db_arr[1]")){ $fuser = TRUE; } if($user and @preg_match("/\b$user\b/i", "$news_db_arr[1]")){ $fuser = TRUE; }
if($story and (@preg_match("/$story/i", "$news_db_arr[4]") or @preg_match("/$story/i", "$news_db_arr[3]"))){ $fstory = TRUE;} if($story and (@preg_match("/$story/i", "$news_db_arr[4]") or @preg_match("/$story/i", "$news_db_arr[3]"))){ $fstory = TRUE;}
if($title and $ftitle){ $ftitle = TRUE; }elseif(!$title){ $ftitle = TRUE; }else{ $ftitle = FALSE; } if($title and $ftitle){ $ftitle = TRUE; }elseif(!$title){ $ftitle = TRUE; }else{ $ftitle = FALSE; }
if($story and $fstory){ $fstory = TRUE; }elseif(!$story){ $fstory = TRUE; }else{ $fstory = FALSE; } if($story and $fstory){ $fstory = TRUE; }elseif(!$story){ $fstory = TRUE; }else{ $fstory = FALSE; }
if($user and $fuser) { $fuser = TRUE; }elseif(!$user) { $fuser = TRUE; }else{ $fuser = FALSE; } if($user and $fuser) { $fuser = TRUE; }elseif(!$user) { $fuser = TRUE; }else{ $fuser = FALSE; }
if($do_date) if($do_date)
{ {
if($date_from < $news_db_arr[0] and $news_db_arr[0] < $date_to){ $fdate = TRUE; }else{ $fdate = FALSE; } if($date_from < $news_db_arr[0] and $news_db_arr[0] < $date_to){ $fdate = TRUE; }else{ $fdate = FALSE; }
}else{ $fdate = TRUE; } }else{ $fdate = TRUE; }
if($fdate and $ftitle and $fuser and $fstory){ $found_arr[$news_db_arr[0]] = $archive; } if($fdate and $ftitle and $fuser and $fstory){ $found_arr[$news_db_arr[0]] = $archive; }
}//foreach news line }//foreach news line
} }
echo"<br /><b>Founded News articles [". count($found_arr)."]:</b><br />"; echo"<br /><b>Founded News articles [". count($found_arr)."]:</b><br />";
if($do_date){echo"from ".@date("d F Y",$date_from)." to ".@date("d F Y",$date_to)."<br />";} if($do_date){echo"from ".@date("d F Y",$date_from)." to ".@date("d F Y",$date_to)."<br />";}
// Display Search Results // Display Search Results
if(is_array($found_arr)){ if(is_array($found_arr)){
foreach($found_arr as $news_id => $archive) foreach($found_arr as $news_id => $archive)
{ {
if($archive){$all_news = file("$cutepath/data/archives/$archive.news.arch");} if($archive){$all_news = file("$cutepath/data/archives/$archive.news.arch");}
else{ $all_news = file("$cutepath/data/news.txt"); } else{ $all_news = file("$cutepath/data/news.txt"); }
foreach($all_news as $single_line) foreach($all_news as $single_line)
{ {
$item_arr = explode("|",$single_line); $item_arr = explode("|",$single_line);
$local_id = $item_arr[0]; $local_id = $item_arr[0];
if($local_id == $news_id){ if($local_id == $news_id){
////////// Showing Result ////////// Showing Result
echo"<br /><b><a href=\"$PHP_SELF?misc=search&subaction=showfull&id=$local_id&archive=$archive&cnshow=news&ucat=$item_arr[6]&start_from=&$user_query\">$item_arr[2]</a></b> (". date("d F, Y", $item_arr[0]) .")"; echo"<br /><b><a href=\"$PHP_SELF?misc=search&subaction=showfull&id=$local_id&archive=$archive&cnshow=news&ucat=$item_arr[6]&start_from=&$user_query\">$item_arr[2]</a></b> (". date("d F, Y", $item_arr[0]) .")";
////////// End Showing Result ////////// End Showing Result
} }
} }
} }
}else{ echo"There are no news matching your search criteria"; } }else{ echo"There are no news matching your search criteria"; }
}//if user wants to search }//if user wants to search
elseif( ($misc == "search") and ($subaction == "showfull" or $subaction == "showcomments" or $_POST["subaction"] == "addcomment" or $subaction == "addcomment")){ elseif( ($misc == "search") and ($subaction == "showfull" or $subaction == "showcomments" or $_POST["subaction"] == "addcomment" or $subaction == "addcomment")){
require_once("$cutepath/show_news.php"); require_once("$cutepath/show_news.php");
unset($action,$subaction); unset($action,$subaction);
} }
?> ?>
<?PHP <?PHP
error_reporting (E_ALL ^ E_NOTICE); error_reporting (E_ALL ^ E_NOTICE);
$cutepath = __FILE__; $cutepath = __FILE__;
$cutepath = preg_replace( "'\\\show_archives\.php'", "", $cutepath); $cutepath = preg_replace( "'\\\show_archives\.php'", "", $cutepath);
$cutepath = preg_replace( "'/show_archives\.php'", "", $cutepath); $cutepath = preg_replace( "'/show_archives\.php'", "", $cutepath);
require_once("$cutepath/inc/functions.inc.php"); require_once("$cutepath/inc/functions.inc.php");
require_once("$cutepath/data/config.php"); require_once("$cutepath/data/config.php");
if(!isset($template) or $template == "" or strtolower($template) == "default"){ require_once("$cutepath/data/Default.tpl"); } if(!isset($template) or $template == "" or strtolower($template) == "default"){ require_once("$cutepath/data/Default.tpl"); }
else{ else{
if(file_exists("$cutepath/data/${template}.tpl")){ require("$cutepath/data/${template}.tpl"); } if(file_exists("$cutepath/data/${template}.tpl")){ require("$cutepath/data/${template}.tpl"); }
else{ die("Error!<br>the template <b>".htmlspecialchars($template)."</b> does not exists, note that templates are case sensetive and you must write the name exactly as it is"); } else{ die("Error!<br>the template <b>".htmlspecialchars($template)."</b> does not exists, note that templates are case sensetive and you must write the name exactly as it is"); }
} }
// Prepare requested categories // Prepare requested categories
if(eregi("[a-z]", $category)){ if(eregi("[a-z]", $category)){
die("<b>Error</b>!<br>CuteNews has detected that you use \$category = \"".htmlspecialchars($category)."\"; but you can call the categories only with their <b>ID</b> numbers and not with names<br> die("<b>Error</b>!<br>CuteNews has detected that you use \$category = \"".htmlspecialchars($category)."\"; but you can call the categories only with their <b>ID</b> numbers and not with names<br>
example:<br><blockquote>&lt;?PHP<br>\$category = \"1\";<br>include(\"path/to/show_archives.php\");<br>?&gt;</blockquote>"); example:<br><blockquote>&lt;?PHP<br>\$category = \"1\";<br>include(\"path/to/show_archives.php\");<br>?&gt;</blockquote>");
} }
$category = preg_replace("/ /", "", $category); $category = preg_replace("/ /", "", $category);
$tmp_cats_arr = explode(",", $category); $tmp_cats_arr = explode(",", $category);
foreach($tmp_cats_arr as $key=>$value){ foreach($tmp_cats_arr as $key=>$value){
if($value != ""){ $requested_cats[$value] = TRUE; } if($value != ""){ $requested_cats[$value] = TRUE; }
} }
if($archive == "" or !$archive){ if($archive == "" or !$archive){
$news_file = "$cutepath/data/news.txt"; $news_file = "$cutepath/data/news.txt";
$comm_file = "$cutepath/data/comments.txt"; $comm_file = "$cutepath/data/comments.txt";
}elseif(is_numeric($archive)){ }elseif(is_numeric($archive)){
$news_file = "$cutepath/data/archives/$archive.news.arch"; $news_file = "$cutepath/data/archives/$archive.news.arch";
$comm_file = "$cutepath/data/archives/$archive.comments.arch"; $comm_file = "$cutepath/data/archives/$archive.comments.arch";
}else{ }else{
die("Archive varialbe is invalid"); die("Archive varialbe is invalid");
} }
if($subaction == "" or !isset($subaction)){ if($subaction == "" or !isset($subaction)){
$user_query = cute_query_string($QUERY_STRING, array("start_from", "archive", "subaction", "id", "ucat")); $user_query = cute_query_string($QUERY_STRING, array("start_from", "archive", "subaction", "id", "ucat"));
if(!$handle = opendir("$cutepath/data/archives")){ die("<center>Can not open directory $cutepath/data/archives "); } if(!$handle = opendir("$cutepath/data/archives")){ die("<center>Can not open directory $cutepath/data/archives "); }
while (false !== ($file = readdir($handle))) { while (false !== ($file = readdir($handle))) {
$file_arr = explode(".",$file); $file_arr = explode(".",$file);
if($file != "." and $file != ".." and $file_arr[1] == "news"){ if($file != "." and $file != ".." and $file_arr[1] == "news"){
$arch_arr[] = $file_arr[0]; $arch_arr[] = $file_arr[0];
} }
} }
closedir($handle); closedir($handle);
if(is_array($arch_arr)){ if(is_array($arch_arr)){
$arch_arr = array_reverse($arch_arr); $arch_arr = array_reverse($arch_arr);
foreach($arch_arr as $arch_file){ foreach($arch_arr as $arch_file){
$news_lines = file("$cutepath/data/archives/$arch_file.news.arch"); $news_lines = file("$cutepath/data/archives/$arch_file.news.arch");
$count = count($news_lines); $count = count($news_lines);
$last = $count-1; $last = $count-1;
$first_news_arr = explode("|", $news_lines[$last]); $first_news_arr = explode("|", $news_lines[$last]);
$last_news_arr = explode("|", $news_lines[0]); $last_news_arr = explode("|", $news_lines[0]);
$first_timestamp = $first_news_arr[0]; $first_timestamp = $first_news_arr[0];
$last_timestamp = $last_news_arr[0]; $last_timestamp = $last_news_arr[0];
echo"<a href=\"$PHP_SELF?archive=$arch_file&subaction=list-archive&$user_query\">".date("d M Y",$first_timestamp) ." - ". date("d M Y",$last_timestamp).", (<b>$count</b>)</a><br />"; echo"<a href=\"$PHP_SELF?archive=$arch_file&subaction=list-archive&$user_query\">".date("d M Y",$first_timestamp) ." - ". date("d M Y",$last_timestamp).", (<b>$count</b>)</a><br />";
} }
} }
} }
else{ else{
if( $CN_HALT != TRUE and $static != TRUE and ($subaction == "showcomments" or $subaction == "showfull" or $subaction == "addcomment") and ((!isset($category) or $category == "") or $requested_cats[$ucat] == TRUE) ){ if( $CN_HALT != TRUE and $static != TRUE and ($subaction == "showcomments" or $subaction == "showfull" or $subaction == "addcomment") and ((!isset($category) or $category == "") or $requested_cats[$ucat] == TRUE) ){
if($subaction == "addcomment"){ $allow_add_comment = TRUE; $allow_comments = TRUE; } if($subaction == "addcomment"){ $allow_add_comment = TRUE; $allow_comments = TRUE; }
if($subaction == "showcomments") $allow_comments = TRUE; if($subaction == "showcomments") $allow_comments = TRUE;
if(($subaction == "showcomments" or $allow_comments == TRUE) and $config_show_full_with_comments == "yes") $allow_full_story = TRUE; if(($subaction == "showcomments" or $allow_comments == TRUE) and $config_show_full_with_comments == "yes") $allow_full_story = TRUE;
if($subaction == "showfull") $allow_full_story = TRUE; if($subaction == "showfull") $allow_full_story = TRUE;
if($subaction == "showfull" and $config_show_comments_with_full == "yes") $allow_comments = TRUE; if($subaction == "showfull" and $config_show_comments_with_full == "yes") $allow_comments = TRUE;
} }
else{ else{
if($config_reverse_active == "yes"){ $reverse = TRUE; } if($config_reverse_active == "yes"){ $reverse = TRUE; }
$allow_active_news = TRUE; $allow_active_news = TRUE;
} }
require("$cutepath/inc/shows.inc.php"); require("$cutepath/inc/shows.inc.php");
} }
unset($template, $requested_cats, $reverse, $in_use, $archive, $archives_arr, $number, $no_prev, $no_next, $i, $showed, $prev, $used_archives); unset($template, $requested_cats, $reverse, $in_use, $archive, $archives_arr, $number, $no_prev, $no_next, $i, $showed, $prev, $used_archives);
?> ?>
<!-- News Powered by CuteNews: http://cutephp.com/ --> <!-- News Powered by CuteNews: http://cutephp.com/ -->
<?PHP <?PHP
error_reporting (E_ALL ^ E_NOTICE); error_reporting (E_ALL ^ E_NOTICE);
$cutepath = __FILE__; $cutepath = __FILE__;
$cutepath = preg_replace( "'\\\show_news\.php'", "", $cutepath); $cutepath = preg_replace( "'\\\show_news\.php'", "", $cutepath);
$cutepath = preg_replace( "'/show_news\.php'", "", $cutepath); $cutepath = preg_replace( "'/show_news\.php'", "", $cutepath);
require_once("$cutepath/inc/functions.inc.php"); require_once("$cutepath/inc/functions.inc.php");
require_once("$cutepath/data/config.php"); require_once("$cutepath/data/config.php");
// If we are showing RSS, include some need variables. // If we are showing RSS, include some need variables.
if($template == 'rss'){ if($template == 'rss'){
include("$cutepath/data/rss_config.php"); include("$cutepath/data/rss_config.php");
} }
//---------------------------------- //----------------------------------
// Check if we are included by PATH // Check if we are included by PATH
//---------------------------------- //----------------------------------
if($_SERVER["HTTP_ACCEPT"] or $_SERVER["HTTP_ACCEPT_CHARSET"] or $_SERVER["HTTP_ACCEPT_ENCODING"] or $_SERVER["HTTP_CONNECTION"]){ /* do nothing */ } if($_SERVER["HTTP_ACCEPT"] or $_SERVER["HTTP_ACCEPT_CHARSET"] or $_SERVER["HTTP_ACCEPT_ENCODING"] or $_SERVER["HTTP_CONNECTION"]){ /* do nothing */ }
elseif(eregi("show_news.php", $PHP_SELF)){ elseif(eregi("show_news.php", $PHP_SELF)){
die("<h4>CuteNews has detected that you are including show_news.php using the URL to this file.<br> die("<h4>CuteNews has detected that you are including show_news.php using the URL to this file.<br>
This is incorrect and you must include it using the PATH to show_news.php</h4><br>Example:<br> This is incorrect and you must include it using the PATH to show_news.php</h4><br>Example:<br>
this is <font color=red>WRONG</font> :&nbsp;&nbsp; &lt;?PHP include(\"http://yoursite.com/cutenews/show_news.php\"); ?&gt;<br> this is <font color=red>WRONG</font> :&nbsp;&nbsp; &lt;?PHP include(\"http://yoursite.com/cutenews/show_news.php\"); ?&gt;<br>
this is <font color=green>CORRECT</font>:&nbsp;&nbsp; &lt;?PHP include(\"cutenews/show_news.php\"); ?&gt;<br> this is <font color=green>CORRECT</font>:&nbsp;&nbsp; &lt;?PHP include(\"cutenews/show_news.php\"); ?&gt;<br>
<br><BR>// <font size=2>if you think this message shouldn't be shown, open show_news.php and delete it from there</font>"); <br><BR>// <font size=2>if you think this message shouldn't be shown, open show_news.php and delete it from there</font>");
} }
//---------------------------------- //----------------------------------
// End of the check // End of the check
//---------------------------------- //----------------------------------
if(!isset($subaction) or $subaction == ""){ $subaction = $POST["subaction"]; } if(!isset($subaction) or $subaction == ""){ $subaction = $POST["subaction"]; }
if(!isset($template) or $template == "" or strtolower($template) == "default"){ require_once("$cutepath/data/Default.tpl"); } if(!isset($template) or $template == "" or strtolower($template) == "default"){ require_once("$cutepath/data/Default.tpl"); }
else{ else{
if(file_exists("$cutepath/data/${template}.tpl")){ require("$cutepath/data/${template}.tpl"); } if(file_exists("$cutepath/data/${template}.tpl")){ require("$cutepath/data/${template}.tpl"); }
else{ die("Error!<br>the template <b>".htmlspecialchars($template)."</b> does not exists, note that templates are case sensetive and you must write the name exactly as it is"); } else{ die("Error!<br>the template <b>".htmlspecialchars($template)."</b> does not exists, note that templates are case sensetive and you must write the name exactly as it is"); }
} }
// Prepare requested categories // Prepare requested categories
if(eregi("[a-z]", $category)){ if(eregi("[a-z]", $category)){
die("<b>Error</b>!<br>CuteNews has detected that you use \$category = \"".htmlspecialchars($category)."\"; but you can call the categories only with their <b>ID</b> numbers and not with names<br> die("<b>Error</b>!<br>CuteNews has detected that you use \$category = \"".htmlspecialchars($category)."\"; but you can call the categories only with their <b>ID</b> numbers and not with names<br>
example:<br><blockquote>&lt;?PHP<br>\$category = \"1\";<br>include(\"path/to/show_news.php\");<br>?&gt;</blockquote>"); example:<br><blockquote>&lt;?PHP<br>\$category = \"1\";<br>include(\"path/to/show_news.php\");<br>?&gt;</blockquote>");
} }
$category = preg_replace("/ /", "", $category); $category = preg_replace("/ /", "", $category);
$tmp_cats_arr = explode(",", $category); $tmp_cats_arr = explode(",", $category);
foreach($tmp_cats_arr as $key=>$value){ foreach($tmp_cats_arr as $key=>$value){
if($value != ""){ $requested_cats[$value] = TRUE; } if($value != ""){ $requested_cats[$value] = TRUE; }
} }
if($archive == ""){ if($archive == ""){
$news_file = "$cutepath/data/news.txt"; $news_file = "$cutepath/data/news.txt";
$comm_file = "$cutepath/data/comments.txt"; $comm_file = "$cutepath/data/comments.txt";
}else{ }else{
$news_file = "$cutepath/data/archives/$archive.news.arch"; $news_file = "$cutepath/data/archives/$archive.news.arch";
$comm_file = "$cutepath/data/archives/$archive.comments.arch"; $comm_file = "$cutepath/data/archives/$archive.comments.arch";
} }
$allow_add_comment = FALSE; $allow_add_comment = FALSE;
$allow_full_story = FALSE; $allow_full_story = FALSE;
$allow_active_news = FALSE; $allow_active_news = FALSE;
$allow_comments = FALSE; $allow_comments = FALSE;
//<<<------------ Detarime what user want to do //<<<------------ Detarime what user want to do
if( $CN_HALT != TRUE and $static != TRUE and ($subaction == "showcomments" or $subaction == "showfull" or $subaction == "addcomment") and ((!isset($category) or $category == "") or ($requested_cats[$ucat] == TRUE ) ) ){ if( $CN_HALT != TRUE and $static != TRUE and ($subaction == "showcomments" or $subaction == "showfull" or $subaction == "addcomment") and ((!isset($category) or $category == "") or ($requested_cats[$ucat] == TRUE ) ) ){
if($subaction == "addcomment"){ $allow_add_comment = TRUE; $allow_comments = TRUE; } if($subaction == "addcomment"){ $allow_add_comment = TRUE; $allow_comments = TRUE; }
if($subaction == "showcomments"){ $allow_comments = TRUE; } if($subaction == "showcomments"){ $allow_comments = TRUE; }
if(($subaction == "showcomments" or $allow_comments == TRUE) and $config_show_full_with_comments == "yes"){$allow_full_story = TRUE; } if(($subaction == "showcomments" or $allow_comments == TRUE) and $config_show_full_with_comments == "yes"){$allow_full_story = TRUE; }
if($subaction == "showfull") $allow_full_story = TRUE; if($subaction == "showfull") $allow_full_story = TRUE;
if($subaction == "showfull" and $config_show_comments_with_full == "yes") $allow_comments = TRUE; if($subaction == "showfull" and $config_show_comments_with_full == "yes") $allow_comments = TRUE;
} }
else{ else{
if($config_reverse_active == "yes"){ $reverse = TRUE; } if($config_reverse_active == "yes"){ $reverse = TRUE; }
$allow_active_news = TRUE; $allow_active_news = TRUE;
} }
//----------->>> Detarime what user want to do //----------->>> Detarime what user want to do
require("$cutepath/inc/shows.inc.php"); require("$cutepath/inc/shows.inc.php");
if($_GET['archive'] and $_GET['archive'] != ''){ $archive = $_GET['archive']; } // stupid fix ? if($_GET['archive'] and $_GET['archive'] != ''){ $archive = $_GET['archive']; } // stupid fix ?
unset($static, $template, $requested_cats, $category, $catid, $cat,$reverse, $in_use, $archives_arr, $number, $no_prev, $no_next, $i, $showed, $prev, $used_archives); unset($static, $template, $requested_cats, $category, $catid, $cat,$reverse, $in_use, $archives_arr, $number, $no_prev, $no_next, $i, $showed, $prev, $used_archives);
?> ?>
<!-- News Powered by CuteNews: http://cutephp.com/ --> <!-- News Powered by CuteNews: http://cutephp.com/ -->
<?PHP <?PHP
$skin_prefix = ""; $skin_prefix = "";
// ********* // *********
// Skin MENU // Skin MENU
// ********* // *********
$skin_menu = <<<HTML $skin_menu = <<<HTML
<table cellpadding=8 cellspacing=4 border=0> <table cellpadding=8 cellspacing=4 border=0>
<tr> <tr>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=main">Home</a> <a class="nav" href="$PHP_SELF?mod=main">Home</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=addnews&action=addnews">Add News</a> <a class="nav" href="$PHP_SELF?mod=addnews&action=addnews">Add News</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=editnews&action=list">Edit News</a> <a class="nav" href="$PHP_SELF?mod=editnews&action=list">Edit News</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=options&action=options">Options</a> <a class="nav" href="$PHP_SELF?mod=options&action=options">Options</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=about&action=about">Help/About</a> <a class="nav" href="$PHP_SELF?mod=about&action=about">Help/About</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?action=logout">Logout</a> <a class="nav" href="$PHP_SELF?action=logout">Logout</a>
</td> </td>
</tr> </tr>
</table> </table>
HTML; HTML;
// ******************* // *******************
// Template -> Header // Template -> Header
// ******************* // *******************
$skin_header=<<<HTML $skin_header=<<<HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<script type="text/javascript" src="skins/cute.js"></script> <script type="text/javascript" src="skins/cute.js"></script>
<style type="text/css"> <style type="text/css">
<!-- <!--
SELECT, option, textarea, input { SELECT, option, textarea, input {
BORDER: #000000 1px solid; BORDER: #000000 1px solid;
COLOR: #000000; COLOR: #000000;
FONT-SIZE: 11px; FONT-SIZE: 11px;
FONT-FAMILY: Verdana; BACKGROUND-COLOR: #ffffff FONT-FAMILY: Verdana; BACKGROUND-COLOR: #ffffff
} }
BODY {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;} BODY {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;}
TD {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;} TD {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;}
a:active,a:visited,a:link {color: #446488; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;} a:active,a:visited,a:link {color: #446488; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;}
a:hover {color: #00004F; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;} a:hover {color: #00004F; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;}
a.nav { padding-top:3px; padding-bottom:3px; padding:2px;} a.nav { padding-top:3px; padding-bottom:3px; padding:2px;}
a.nav:active, a.nav:visited, a.nav:link { color: #000000; font-size : 10px; font-weight: bold; font-family: verdana; text-decoration: none;} a.nav:active, a.nav:visited, a.nav:link { color: #000000; font-size : 10px; font-weight: bold; font-family: verdana; text-decoration: none;}
a.nav:hover { font-size : 10px; font-weight: bold; color: black; font-family: verdana; background-color:000000; color:FFFFFF} a.nav:hover { font-size : 10px; font-weight: bold; color: black; font-family: verdana; background-color:000000; color:FFFFFF}
.bborder { background-color: #FFFFFF; border: 1px #000000 solid; } .bborder { background-color: #FFFFFF; border: 1px #000000 solid; }
.panel {-moz-border-radius: .3em .3em .3em .3em; border: 1px dotted #B4D2E7; background-color: #ECF4F9;} .panel {-moz-border-radius: .3em .3em .3em .3em; border: 1px dotted #B4D2E7; background-color: #ECF4F9;}
BODY, TD, TR {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; cursor: default;} BODY, TD, TR {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; cursor: default;}
input[type=submit]:hover, input[type=button]:hover{ input[type=submit]:hover, input[type=button]:hover{
background-color:#E0EDF3 !important; background-color:#E0EDF3 !important;
} }
--> -->
</style> </style>
<title>CuteNews</title> <title>CuteNews</title>
</head> </head>
<body bgcolor="#A5CBDE"> <body bgcolor="#A5CBDE">
<center> <center>
<table width="565" border="0" cellspacing="0" cellpadding="2"> <table width="565" border="0" cellspacing="0" cellpadding="2">
<tr> <tr>
<td class="bborder" bgcolor="#FFFFFF" width="777"> <td class="bborder" bgcolor="#FFFFFF" width="777">
<table border=0 cellpadding=0 cellspacing=0 bgcolor="#ffffff" width="645" > <table border=0 cellpadding=0 cellspacing=0 bgcolor="#ffffff" width="645" >
<tr> <tr>
<td width="645" align="center"> <td width="645" align="center">
{menu} {menu}
</td> </td>
</tr> </tr>
<tr> <tr>
<td bgcolor="#000000" width="802" height="1"><img src="skins/images/blank.gif" width=1 height=1></td> <td bgcolor="#000000" width="802" height="1"><img src="skins/images/blank.gif" width=1 height=1></td>
</tr> </tr>
<tr><td bgcolor="#FFFFFF" width="802" height="9"><img src="skins/images/blank.gif" width=1 height=5></td></tr> <tr><td bgcolor="#FFFFFF" width="802" height="9"><img src="skins/images/blank.gif" width=1 height=5></td></tr>
<tr> <tr>
<td width="802" height="42"> <td width="802" height="42">
</center> </center>
<table border=0 cellpading=0 cellspacing=10 width="100%" height="100%" > <table border=0 cellpading=0 cellspacing=10 width="100%" height="100%" >
<tr> <tr>
<td width="98%" height="46%"> <td width="98%" height="46%">
<!--MAIN area--> <!--MAIN area-->
HTML; HTML;
// ******************************************************************************** // ********************************************************************************
// Template -> Footer // Template -> Footer
// ******************************************************************************** // ********************************************************************************
$skin_footer=<<<HTML $skin_footer=<<<HTML
<!--MAIN area--> <!--MAIN area-->
</tr> </tr>
</table> </table>
</td> </td>
</tr></table></td></tr></table> </tr></table></td></tr></table>
<br /><center>{copyrights} <br /><center>{copyrights}
</body></html> </body></html>
HTML; HTML;
?> ?>
<?PHP <?PHP
$skin_prefix = ""; $skin_prefix = "";
// ******************************************************************************** // ********************************************************************************
// Skin MENU // Skin MENU
// ******************************************************************************** // ********************************************************************************
$skin_menu = <<<HTML $skin_menu = <<<HTML
<table cellpadding=5 cellspacing=4 border=0> <table cellpadding=5 cellspacing=4 border=0>
<tr> <tr>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=main">Home</a> <a class="nav" href="$PHP_SELF?mod=main">Home</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=addnews&action=addnews" accesskey="a">Add News</a> <a class="nav" href="$PHP_SELF?mod=addnews&action=addnews" accesskey="a">Add News</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=editnews&action=list">Edit News</a> <a class="nav" href="$PHP_SELF?mod=editnews&action=list">Edit News</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=options&action=options">Options</a> <a class="nav" href="$PHP_SELF?mod=options&action=options">Options</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=about&action=about">Help/About</a> <a class="nav" href="$PHP_SELF?mod=about&action=about">Help/About</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?action=logout">Logout</a> <a class="nav" href="$PHP_SELF?action=logout">Logout</a>
</td> </td>
</tr> </tr>
</table> </table>
HTML; HTML;
// ******************************************************************************** // ********************************************************************************
// Skin HEADER // Skin HEADER
// ******************************************************************************** // ********************************************************************************
$skin_header = <<<HTML $skin_header = <<<HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<script type="text/javascript" src="skins/cute.js"></script> <script type="text/javascript" src="skins/cute.js"></script>
<style type="text/css"> <style type="text/css">
<!-- <!--
select, textarea, input { select, textarea, input {
border: #808080 1px solid; border: #808080 1px solid;
color: #000000; color: #000000;
font-size: 11px; font-size: 11px;
font-family: Verdana; BACKGROUND-COLOR: #ffffff } font-family: Verdana; BACKGROUND-COLOR: #ffffff }
input[type=submit]:hover, input[type=button]:hover{ input[type=submit]:hover, input[type=button]:hover{
background-color:#EBEBEB !important; background-color:#EBEBEB !important;
} }
a:active,a:visited,a:link {color: #446488; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;} a:active,a:visited,a:link {color: #446488; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;}
a:hover {color: #00004F; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; } a:hover {color: #00004F; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; }
a.nav { padding-top:10px; padding-bottom:10px; padding:9px;} a.nav { padding-top:10px; padding-bottom:10px; padding:9px;}
a.nav:active, a.nav:visited, a.nav:link { color: #000000; font-size : 10px; font-weight: bold; font-family: verdana; text-decoration: none;} a.nav:active, a.nav:visited, a.nav:link { color: #000000; font-size : 10px; font-weight: bold; font-family: verdana; text-decoration: none;}
a.nav:hover { font-size : 10px; font-weight: bold; color: black; font-family: verdana; text-decoration: underline; } a.nav:hover { font-size : 10px; font-weight: bold; color: black; font-family: verdana; text-decoration: underline; }
.header { font-size : 16px; font-weight: bold; color: #808080; font-family: verdana; text-decoration: none; } .header { font-size : 16px; font-weight: bold; color: #808080; font-family: verdana; text-decoration: none; }
.bborder { background-color: #FFFFFF; border: 1px #A7A6B4 solid; } .bborder { background-color: #FFFFFF; border: 1px #A7A6B4 solid; }
.panel {-moz-border-radius: .3em .3em .3em .3em; border: 1px solid silver; background-color: #F7F6F4;} .panel {-moz-border-radius: .3em .3em .3em .3em; border: 1px solid silver; background-color: #F7F6F4;}
BODY, TD, TR {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; cursor: default;} BODY, TD, TR {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; cursor: default;}
--> -->
</style> </style>
<title>CuteNews</title> <title>CuteNews</title>
</head> </head>
<body BgColor=white> <body BgColor=white>
<center> <center>
<table border="0" cellspacing="0" cellpadding="2" > <table border="0" cellspacing="0" cellpadding="2" >
<tr> <tr>
<td class="bborder" bgcolor="#FFFFFF" style="-moz-border-radius: .8em .8em .8em .8em;"> <td class="bborder" bgcolor="#FFFFFF" style="-moz-border-radius: .8em .8em .8em .8em;">
<table border=0 cellpadding=0 cellspacing=0 bgcolor="#ffffff" width="745" > <table border=0 cellpadding=0 cellspacing=0 bgcolor="#ffffff" width="745" >
<tr> <tr>
<td bgcolor="#FFFFFF" >&nbsp;</td> <td bgcolor="#FFFFFF" >&nbsp;</td>
</tr> </tr>
<tr> <tr>
<td bgcolor="#000000" ><img src="skins/images/blank.gif" width=1 height=1></td> <td bgcolor="#000000" ><img src="skins/images/blank.gif" width=1 height=1></td>
</tr> </tr>
<tr> <tr>
<td bgcolor="#F7F6F4" > <td bgcolor="#F7F6F4" >
{menu} {menu}
</td> </td>
</tr> </tr>
<tr> <tr>
<td bgcolor="#000000" ><img src="skins/images/blank.gif" width=1 height=1></td> <td bgcolor="#000000" ><img src="skins/images/blank.gif" width=1 height=1></td>
</tr> </tr>
<tr><td bgcolor="#FFFFFF" ><img src="skins/images/blank.gif" width=1 height=5></td></tr> <tr><td bgcolor="#FFFFFF" ><img src="skins/images/blank.gif" width=1 height=5></td></tr>
<tr> <tr>
<td > <td >
</center> </center>
<!--SELF--> <!--SELF-->
<table border=0 cellpading=0 cellspacing=0 width="100%" height="100%" > <table border=0 cellpading=0 cellspacing=0 width="100%" height="100%" >
<td width="13%" height="55%"> <td width="13%" height="55%">
<p align="center"><br /><img border="0" src="skins/images/{image-name}.gif" > <p align="center"><br /><img border="0" src="skins/images/{image-name}.gif" >
<td width="87%" height="20%"> <td width="87%" height="20%">
<div class=header>{header-text}</div> <div class=header>{header-text}</div>
<tr> <tr>
<td width="13%" height="26%"> <td width="13%" height="26%">
<td width="87%" height="46%"> <td width="87%" height="46%">
<!--MAIN area--> <!--MAIN area-->
HTML; HTML;
// ******************************************************************************** // ********************************************************************************
// Skin FOOTER // Skin FOOTER
// ******************************************************************************** // ********************************************************************************
$skin_footer = <<<HTML $skin_footer = <<<HTML
<!--MAIN area--> <!--MAIN area-->
<img border=0 height=10 src="skins/images/blank.gif"></tr> <img border=0 height=10 src="skins/images/blank.gif"></tr>
</table> </table>
<!--/SELF--> <!--/SELF-->
</td> </td>
</tr></table></td></tr></table> </tr></table></td></tr></table>
<br /><center>{copyrights} <br /><center>{copyrights}
</body></html> </body></html>
HTML; HTML;
?> ?>
<?PHP <?PHP
$skin_prefix = ""; $skin_prefix = "";
// ******************************************************************************** // ********************************************************************************
// Skin MENU // Skin MENU
// ******************************************************************************** // ********************************************************************************
$skin_menu = <<<HTML $skin_menu = <<<HTML
<a class="nav" href="$PHP_SELF?mod=main">Home</a> <a class="nav" href="$PHP_SELF?mod=main">Home</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=addnews&action=addnews" accesskey="a">Add News</a> <a class="nav" href="$PHP_SELF?mod=addnews&action=addnews" accesskey="a">Add News</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=editnews&action=list">Edit News</a> <a class="nav" href="$PHP_SELF?mod=editnews&action=list">Edit News</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=options&action=options">Control Panel</a> <a class="nav" href="$PHP_SELF?mod=options&action=options">Control Panel</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?mod=about&action=about">Help</a> <a class="nav" href="$PHP_SELF?mod=about&action=about">Help</a>
</td> </td>
<td>|</td> <td>|</td>
<td> <td>
<a class="nav" href="$PHP_SELF?action=logout">Exit</a> <a class="nav" href="$PHP_SELF?action=logout">Exit</a>
HTML; HTML;
// *********** // ***********
// Skin HEADER // Skin HEADER
// *********** // ***********
$skin_header = <<<HTML $skin_header = <<<HTML
<html> <html>
<head> <head>
<title>CuteNews</title> <title>CuteNews</title>
<script type="text/javascript" src="skins/cute.js"></script> <script type="text/javascript" src="skins/cute.js"></script>
<style type='text/css'> <style type='text/css'>
<!-- <!--
select, option, textarea, input { select, option, textarea, input {
BORDER: #808080 1px solid; BORDER: #808080 1px solid;
COLOR: #000000; COLOR: #000000;
FONT-SIZE: 11px; FONT-SIZE: 11px;
FONT-FAMILY: Verdana; BACKGROUND-COLOR: #ffffff FONT-FAMILY: Verdana; BACKGROUND-COLOR: #ffffff
} }
input[type=submit]:hover, input[type=button]:hover{ input[type=submit]:hover, input[type=button]:hover{
background-color:#EBEBEB !important; background-color:#EBEBEB !important;
} }
a:active,a:visited,a:link {color: #446488; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;} a:active,a:visited,a:link {color: #446488; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt;}
a:hover {color: #00004F; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; } a:hover {color: #00004F; text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; }
a.nav:active, a.nav:visited, a.nav:link { color: #000000; font-size : 10px; font-weight: bold; font-family: verdana; text-decoration: none;} a.nav:active, a.nav:visited, a.nav:link { color: #000000; font-size : 10px; font-weight: bold; font-family: verdana; text-decoration: none;}
a.nav:hover { font-size : 10px; font-weight: bold; color: black; font-family: verdana; text-decoration: underline; } a.nav:hover { font-size : 10px; font-weight: bold; color: black; font-family: verdana; text-decoration: underline; }
.bborder { background-color: #FFFFFF; } .bborder { background-color: #FFFFFF; }
.panel {-moz-border-radius: .3em .3em .3em .3em; border: 1px dotted silver; background-color: #F7F6F4;} .panel {-moz-border-radius: .3em .3em .3em .3em; border: 1px dotted silver; background-color: #F7F6F4;}
BODY, TD, TR {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; cursor: default;} BODY, TD, TR {text-decoration: none; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; cursor: default;}
--> -->
</style> </style>
</head> </head>
<body bgcolor=white marginwidth='0' leftmargin='0'> <body bgcolor=white marginwidth='0' leftmargin='0'>
<center> <center>
<table border="0" cellspacing="0" cellpadding="2"> <table border="0" cellspacing="0" cellpadding="2">
<tr> <tr>
<td class="bborder" bgcolor="#FFFFFF" > <td class="bborder" bgcolor="#FFFFFF" >
<table border=0 cellpadding=0 cellspacing=0 bgcolor="#ffffff" width="685" > <table border=0 cellpadding=0 cellspacing=0 bgcolor="#ffffff" width="685" >
<tr> <tr>
<td bgcolor="#F7F6F4" align="center" height="24" style="-moz-border-radius: 3em 3em 0em 0em; border-left: 1px transparent; border-top: 1px transparent; border-right: 1px transparent; border-bottom: #808080 1px solid;"> <td bgcolor="#F7F6F4" align="center" height="24" style="-moz-border-radius: 3em 3em 0em 0em; border-left: 1px transparent; border-top: 1px transparent; border-right: 1px transparent; border-bottom: #808080 1px solid;">
<table cellpadding=5 cellspacing=0 border=0> <table cellpadding=5 cellspacing=0 border=0>
<tr> <tr>
<td> <td>
{menu} {menu}
</td> </td>
</tr> </tr>
</table> </table>
</td> </td>
</tr> </tr>
<tr> <tr>
<td height="19"> <td height="19">
</center> </center>
<!--SELF--> <!--SELF-->
<table border=0 cellpading=0 cellspacing=15 width="100%" height="100%" > <table border=0 cellpading=0 cellspacing=15 width="100%" height="100%" >
<tr> <tr>
<td width="100%" height="100%" > <td width="100%" height="100%" >
<!--MAIN area--> <!--MAIN area-->
HTML; HTML;
// *********** // ***********
// Skin FOOTER // Skin FOOTER
// *********** // ***********
$skin_footer = <<<HTML $skin_footer = <<<HTML
<!--/MAIN area--> <!--/MAIN area-->
</tr> </tr>
</table> </table>
</td> </td>
</tr> </tr>
<tr > <tr >
<td bgcolor="#F7F6F4" height="24" align="center" style="-moz-border-radius: .0em .0em 3em 3em; border-left: 1px transparent; border-bottom: 1px transparent; border-right: 1px transparent; border-top: 1px solid #808080; "> <td bgcolor="#F7F6F4" height="24" align="center" style="-moz-border-radius: .0em .0em 3em 3em; border-left: 1px transparent; border-bottom: 1px transparent; border-right: 1px transparent; border-top: 1px solid #808080; ">
{copyrights} {copyrights}
</td> </td>
</tr> </tr>
</center> </center>
</table></td></tr></table> </table></td></tr></table>
&nbsp; &nbsp;
</body></html> </body></html>
HTML; HTML;
?> ?>
<?php <?php
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
if ($_REQUEST['agency']) { if ($_REQUEST['agency']) {
include_header("Agency"); include_header("Agency");
$agency = htmlentities(strip_tags($_REQUEST['agency'])); $agency = htmlentities(strip_tags($_REQUEST['agency']));
echo '<img src="graphs/displayMethodCountGraph.php?agency=' . stripslashes($agency) . '">'; echo '<img src="graphs/displayMethodCountGraph.php?agency=' . stripslashes($agency) . '">';
echo '<img src="graphs/displayCnCGraph.php?agency=' . stripslashes($agency) . '">'; echo '<img src="graphs/displayCnCGraph.php?agency=' . stripslashes($agency) . '">';
echo '<img src="graphs/displayMethodValueGraph.php?agency=' . stripslashes($agency) . '">'; echo '<img src="graphs/displayMethodValueGraph.php?agency=' . stripslashes($agency) . '">';
/*biggest contracts /*biggest contracts
spending by year spending by year
spending by industry/category spending by industry/category
spending by supplier spending by supplier
spread procurement methods (stacked bar graph) spread procurement methods (stacked bar graph)
+ percent consultancies + percent confidential (bar graph) + percent consultancies + percent confidential (bar graph)
Average value by procurement type Average value by procurement type
--- info --- info
website, procurement plan, annual reports website, procurement plan, annual reports
  Breakdown of divisions/branches
Breakdown percentage,number,value by procurement type Breakdown percentage,number,value by procurement type
Histograph, overlaying number value reported per week over X years Histograph, overlaying number value reported per week over X years
Compliance statistics: amendments, delay in reporting average and number completely late*/ Compliance statistics: amendments, delay in reporting average and number completely late*/
} else { } else {
/* /*
split by portfolio split by portfolio
*/ */
include_header("Agencies"); include_header("Agencies");
$query = "SELECT SUM(value), agencyName $query = "SELECT SUM(value), agencyName
FROM `contractnotice` FROM `contractnotice`
WHERE childCN = 0 WHERE childCN = 0
GROUP BY agencyName "; GROUP BY agencyName ";
$result = mysql_query($query); $result = mysql_query($query);
echo "<table>"; echo "<table>";
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row[0]) , 2); $value = number_format(doubleval($row[0]) , 2);
$agency = stripslashes($row[1]); $agency = stripslashes($row[1]);
echo ("<tr><td><b><a href=\"displayAgency.php?agency={$agency}\">{$agency}</a></b></td><td>\$$value</td></tr>\n"); echo ("<tr><td><b><a href=\"displayAgency.php?agency={$agency}\">{$agency}</a></b></td><td>\$$value</td></tr>\n");
} }
echo "</table>"; echo "</table>";
mysql_free_result($result); mysql_free_result($result);
} }
include_footer(); include_footer();
?> ?>
   
  <?php
  include_once ("./lib/common.inc.php");
  include_header("Amendments");
  $query = "select CNID, description, value, pvalue, (value - pvalue) as diff from contractnotice, (SELECT CNID as cn, childCN as ccn, value as pvalue FROM contractnotice where childCN > 0) a where CNID = ccn order by diff DESC";
  $result = mysql_query($query);
  echo "<table>";
  while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
  setlocale(LC_MONETARY, 'en_US');
  $value = number_format(doubleval($row['value']) , 2);
  $pvalue = number_format(doubleval($row['pvalue']) , 2);
  $diff = number_format(doubleval($row['diff']) , 2);
  echo ("<tr>");
  echo "<td><A href=\"displayContract.php?CNID={$row['CNID']}\"><b>{$row['description']}</b></a></td>";
  echo "<td>\$$pvalue</td><td>\$$value</td><td>\$$diff</td></tr>";
  }
  echo "</table>";
  mysql_free_result($result);
  include_footer();
  ?>
 
<?php <?php
include_once("./lib/common.inc.php"); include_once("./lib/common.inc.php");
   
  include_header("Months and Years");
   
  if ($_REQUEST['category']) {
  echo "<center><h1>".$_REQUEST['category']."</h1></center>";
  $query = "SELECT CNID, description, value, agencyName, category, contractStart, supplierName
  FROM `contractnotice`
  WHERE childCN = 0
  AND category = '" . $_REQUEST['category'] . "'
  ORDER BY value DESC";
  $result = mysql_query($query);
  echo "<table>";
  while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
  setlocale(LC_MONETARY, 'en_US');
  $value = number_format(doubleval($row['value']) , 2);
  echo ("<tr>
  <td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td>
  <td><b>{$row['description']}</b></a></td>
  <td>\$$value</td><td>{$row['agencyName']}</td>
  <td>{$row['contractStart']}</td>
  <td>{$row['supplierName']}</td>
  </tr>");
  }
  echo "</table>";
  mysql_free_result($result);
  } else {
/* /*
split by year split by year
*/  
/*  
todo: todo:
Year/Month drilldown - largest contracts, agencies, suppliers Year/Month drilldown - largest contracts, agencies, suppliers
big picture graphs?*/ big picture graphs?*/
include_header("Months and Years");  
$query = "SELECT YEAR(contractStart), MONTH(contractStart), $query = "SELECT YEAR(contractStart), MONTH(contractStart),
value FROM `contractnotice` WHERE childCN = 0 GROUP BY MONTH(contractStart), YEAR(contractStart) ORDER BY YEAR(contractStart), MONTH(contractStart) "; value FROM `contractnotice` WHERE childCN = 0 GROUP BY MONTH(contractStart), YEAR(contractStart) ORDER BY YEAR(contractStart), MONTH(contractStart) ";
$result = mysql_query($query); $result = mysql_query($query);
echo "<table>"; echo "<table>";
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row["value"]),2); $value = number_format(doubleval($row["value"]),2);
$month_name = date( 'F', mktime(0, 0, 0, $row[1]) ); $month_name = date( 'F', mktime(0, 0, 0, $row[1]) );
echo ("<tr><td><b>$month_name {$row[0]}</b></td><td>\$$value</td></tr>"); echo ("<tr><td><b>$month_name {$row[0]}</b></td><td>\$$value</td></tr>");
} }
echo "</table>"; echo "</table>";
mysql_free_result($result); mysql_free_result($result);
  }
include_footer(); include_footer();
?> ?>
<?php <?php
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
if ($_REQUEST['category']) { if ($_REQUEST['category']) {
include_header("Category"); include_header("Category");
echo "<center><h1>".$_REQUEST['category']."</h1></center>"; echo "<center><h1>".$_REQUEST['category']."</h1></center>";
$query = "SELECT CNID, description, value, agencyName, category, contractStart, supplierName $query = "SELECT CNID, description, value, agencyName, category, contractStart, supplierName
FROM `contractnotice` FROM `contractnotice`
WHERE childCN = 0 WHERE childCN = 0
AND category = '" . $_REQUEST['category'] . "' AND category = '" . $_REQUEST['category'] . "'
ORDER BY value DESC"; ORDER BY value DESC";
$result = mysql_query($query); $result = mysql_query($query);
echo "<table>"; echo "<table>";
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row['value']) , 2); $value = number_format(doubleval($row['value']) , 2);
echo ("<tr> echo ("<tr>
<td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td> <td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td>
<td><b>{$row['description']}</b></a></td> <td><b>{$row['description']}</b></a></td>
<td>\$$value</td><td>{$row['agencyName']}</td> <td>\$$value</td><td>{$row['agencyName']}</td>
<td>{$row['contractStart']}</td> <td>{$row['contractStart']}</td>
<td>{$row['supplierName']}</td> <td>{$row['supplierName']}</td>
</tr>"); </tr>");
} }
echo "</table>"; echo "</table>";
mysql_free_result($result); mysql_free_result($result);
} else { } else {
/* /*
split by main categories split by main categories
*/ */
include_header("Categories"); include_header("Categories");
$query = "SELECT sum(value), category $query = "SELECT sum(value), category
FROM `contractnotice` FROM `contractnotice`
WHERE childCN = 0 WHERE childCN = 0
GROUP BY category ORDER BY sum(value) DESC "; GROUP BY category ORDER BY sum(value) DESC ";
$result = mysql_query($query); $result = mysql_query($query);
echo "<table>"; echo "<table>";
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row[0]) , 2); $value = number_format(doubleval($row[0]) , 2);
echo ("<tr><td><A href=\"displayCategory.php?category={$row[1]}\"><b>{$row[1]}</b></a></td><td>\$$value</td></tr>"); echo ("<tr><td><A href=\"displayCategory.php?category={$row[1]}\"><b>{$row[1]}</b></a></td><td>\$$value</td></tr>");
} }
echo "</table>"; echo "</table>";
mysql_free_result($result); mysql_free_result($result);
} }
include_footer(); include_footer();
?> ?>
agencies that use alot of consultacies <?php
   
  include_once("./lib/common.inc.php");
  /*
   
   
  agencies that use alot of Confidentialities
suppliers that provide alot suppliers that provide alot
how much is spent overall per year how much is spent overall per year
  */
   
  include_header("Confidentialities");
  $query = "SELECT value, procurementMethod
  FROM `contractnotice`
  GROUP BY procurementMethod ";
   
  $result = mysql_query($query);
   
  echo "<table>";
  while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
  setlocale(LC_MONETARY, 'en_US');
  $value = number_format(doubleval($row[0]),2);
  echo ("<tr><td><b>{$row[1]}</b></td><td>\$$value</td></tr>");
  }
  echo "</table>";
  mysql_free_result($result);
  include_footer();
  ?>
   
   
   
  <?php
   
  include_once("./lib/common.inc.php");
  /*
   
   
agencies that use alot of consultacies agencies that use alot of consultacies
suppliers that provide alot suppliers that provide alot
how much is spent overall per year how much is spent overall per year
  */
   
  include_header("Consultancies");
  $query = "SELECT value, procurementMethod
  FROM `contractnotice`
  GROUP BY procurementMethod ";
   
  $result = mysql_query($query);
   
  echo "<table>";
  while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
  setlocale(LC_MONETARY, 'en_US');
  $value = number_format(doubleval($row[0]),2);
  echo ("<tr><td><b>{$row[1]}</b></td><td>\$$value</td></tr>");
  }
  echo "</table>";
  mysql_free_result($result);
  include_footer();
  ?>
   
   
   
<?php <?php
include_once("./lib/common.inc.php"); include_once("./lib/common.inc.php");
include_header("Contract"); include_header("Contract");
$query = sprintf("SELECT * $query = sprintf("SELECT *
FROM `contractnotice` FROM `contractnotice`
WHERE CNID = '%d'", mysql_real_escape_string($_REQUEST['CNID'])); WHERE CNID = '%d'", mysql_real_escape_string($_REQUEST['CNID']));
$result = mysql_query($query); $result = mysql_query($query);
echo "<pre>"; echo "<pre>";
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row['value']),2); $value = number_format(doubleval($row['value']),2);
echo(print_r(array_filter($row),true)); echo(print_r(array_filter($row),true));
} }
echo "</pre>"; echo "</pre>";
echo '<a href="https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN'.$_REQUEST['CNID'].'"> View original record @ tenders.gov.au</a>'; echo '<a href="https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN'.$_REQUEST['CNID'].'"> View original record @ tenders.gov.au</a>';
mysql_free_result($result); mysql_free_result($result);
include_footer(); include_footer();
?> ?>
<?php <?php
include('./lib/common.inc.php'); include('./lib/common.inc.php');
include_header("Map"); include_header("Map");
echo '<center><img src="graphs/displayHeatmap.php"/></center>'; echo '<center><img src="graphs/displayHeatmap.php"/></center>';
include_footer(); include_footer();
?> ?>
<?php <?php
include_once("./lib/common.inc.php"); include_once("./lib/common.inc.php");
/* /*
biggest suppliers in each method biggest suppliers in each method
biggest agencies in each method (weighted for size? percentage of total expenditure) biggest agencies in each method (weighted for size? percentage of total expenditure)
largest Average value by procurement type? largest Average value by procurement type?
*/ */
include_header("Procurement Methods"); include_header("Procurement Methods");
$query = "SELECT value, procurementMethod $query = "SELECT value, procurementMethod
FROM `contractnotice` FROM `contractnotice`
GROUP BY procurementMethod "; GROUP BY procurementMethod ";
$result = mysql_query($query); $result = mysql_query($query);
echo "<table>"; echo "<table>";
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row[0]),2); $value = number_format(doubleval($row[0]),2);
echo ("<tr><td><b>{$row[1]}</b></td><td>\$$value</td></tr>"); echo ("<tr><td><b>{$row[1]}</b></td><td>\$$value</td></tr>");
} }
echo "</table>"; echo "</table>";
mysql_free_result($result); mysql_free_result($result);
include_footer(); include_footer();
?> ?>
   
<?php <?php
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
if ($_REQUEST['supplier']) { if ($_REQUEST['supplier']) {
include_header("Supplier"); include_header("Supplier");
$supplier = htmlentities(strip_tags($_REQUEST['supplier'])); $supplier = htmlentities(strip_tags($_REQUEST['supplier']));
echo '<img src="graphs/displayMethodCountGraph.php?supplier=' . stripslashes($supplier) . '">'; echo '<img src="graphs/displayMethodCountGraph.php?supplier=' . stripslashes($supplier) . '">';
echo '<img src="graphs/displayCnCGraph.php?supplier=' . stripslashes($supplier) . '">'; echo '<img src="graphs/displayCnCGraph.php?supplier=' . stripslashes($supplier) . '">';
echo '<img src="graphs/displayMethodValueGraph.php?supplier=' . stripslashes($supplier) . '">'; echo '<img src="graphs/displayMethodValueGraph.php?supplier=' . stripslashes($supplier) . '">';
/*lobbyist ties /*lobbyist ties
  links to ABR/ASIC/Google News/ASX/Court records
total value to various agencies (bar graph) total value to various agencies (bar graph)
spread procurement methods + percent consultancies + percent confidential (bar graph) spread procurement methods + percent consultancies + percent confidential (bar graph)
spread of contract values spread of contract values
spread of industries (textual?)*/ spread of industries (textual?)*/
} else { } else {
  /*
  histograph of supplier size/value
  */
include_header("Suppliers"); include_header("Suppliers");
$query = "SELECT SUM(value) as val, supplierName, supplierABN $query = "SELECT SUM(value) as val, supplierName, supplierABN
FROM `contractnotice` FROM `contractnotice`
WHERE childCN = 0 WHERE childCN = 0
GROUP BY supplierName GROUP BY supplierName
ORDER BY val DESC ORDER BY val DESC
LIMIT 100"; LIMIT 100";
$result = mysql_query($query); $result = mysql_query($query);
echo "<table>"; echo "<table>";
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row['val']) , 2); $value = number_format(doubleval($row['val']) , 2);
$supplier = stripslashes($row['supplierABN'].'-'.$row['supplierName']); $supplier = stripslashes($row['supplierABN'].'-'.$row['supplierName']);
echo ("<tr><td><b><a href=\"displaySupplier.php?supplier={$supplier}\">".ucsmart($row['supplierName'])."</a></b></td><td>\$$value</td></tr>\n"); echo ("<tr><td><b><a href=\"displaySupplier.php?supplier={$supplier}\">".ucsmart($row['supplierName'])."</a></b></td><td>\$$value</td></tr>\n");
} }
echo "</table>"; echo "</table>";
mysql_free_result($result); mysql_free_result($result);
} }
include_footer(); include_footer();
?> ?>
<?php <?php
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
include_header("Agency"); include_header("Agency");
include("/var/www/contractDashboard/cutenews/show_news.php"); include("/var/www/contractDashboard/cutenews/show_news.php");
include_footer(); include_footer();
?> ?>
   
   
<?php <?php
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
$topX = 15; $topX = 15;
$startYear = 2007; $startYear = 2007;
$query = "SELECT SUM(value) as val, agencyName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0 $query = "SELECT SUM(value) as val, agencyName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0
GROUP BY agencyName ORDER BY val DESC limit $topX"; GROUP BY agencyName ORDER BY val DESC limit $topX";
$result = mysql_query($query); $result = mysql_query($query);
$agencies = Array(); $agencies = Array();
$values = Array(); $values = Array();
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$agencies[] = $row['agencyName']; $agencies[] = $row['agencyName'];
$values[] = doubleval($row["val"]); $values[] = doubleval($row["val"]);
} }
mysql_free_result($result); mysql_free_result($result);
   
$query = "SELECT sum(a.val) as value, count(1) as count from (SELECT SUM(value) as val, agencyName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0 $query = "SELECT sum(a.val) as value, count(1) as count from (SELECT SUM(value) as val, agencyName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0
GROUP BY agencyName ORDER BY val DESC LIMIT 18446744073709551610 OFFSET $topX) as a"; GROUP BY agencyName ORDER BY val DESC LIMIT 18446744073709551610 OFFSET $topX) as a";
$result = mysql_query($query); $result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$agencies[] = $row['count'] . " other agencies"; $agencies[] = $row['count'] . " other agencies";
$values[] = doubleval($row[0]); $values[] = doubleval($row[0]);
} }
mysql_free_result($result); mysql_free_result($result);
   
// Width and height of the graph // Width and height of the graph
$width = 800; $width = 800;
$height = 800; $height = 800;
// Create a graph instance // Create a graph instance
$graph = new PieGraph($width, $height); $graph = new PieGraph($width, $height);
$pieplot = new PiePlot($values); $pieplot = new PiePlot($values);
$pieplot->SetCenter(400, 300); $pieplot->SetCenter(400, 300);
$pieplot->SetGuideLines(true, false); $pieplot->SetGuideLines(true, false);
$pieplot->SetLegends($agencies); $pieplot->SetLegends($agencies);
// Add the plot to the graph // Add the plot to the graph
$graph->Add($pieplot); $graph->Add($pieplot);
$graph->legend->SetPos(0.01, 0.97, 'left', 'bottom'); $graph->legend->SetPos(0.01, 0.97, 'left', 'bottom');
$graph->legend->SetColumns(2); $graph->legend->SetColumns(2);
// Display the graph // Display the graph
$graph->Stroke(); $graph->Stroke();
?> ?>
<?php <?php
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
$agency = "AusAid"; $agency = "AusAid";
$topX = 15; $topX = 15;
$startYear = 2007; $startYear = 2007;
$query = "SELECT SUM(value) as val, supplierName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0 AND agencyName = '$agency' $query = "SELECT SUM(value) as val, supplierName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0 AND agencyName = '$agency'
GROUP BY lower(supplierName) ORDER BY val DESC limit $topX"; GROUP BY lower(supplierName) ORDER BY val DESC limit $topX";
$result = mysql_query($query); $result = mysql_query($query);
$suppliers = Array(); $suppliers = Array();
$values = Array(); $values = Array();
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$suppliers[] = ucsmart($row['supplierName']); $suppliers[] = ucsmart($row['supplierName']);
$values[] = doubleval($row["val"]); $values[] = doubleval($row["val"]);
} }
mysql_free_result($result); mysql_free_result($result);
$query = "SELECT sum(a.val) as value, count(1) as count from (SELECT SUM(value) as val, supplierName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0 and agencyName = '$agency' $query = "SELECT sum(a.val) as value, count(1) as count from (SELECT SUM(value) as val, supplierName FROM `contractnotice` WHERE (YEAR(contractStart) >= $startYear) AND childCN = 0 and agencyName = '$agency'
GROUP BY lower(supplierName) ORDER BY val DESC LIMIT 18446744073709551610 OFFSET $topX) as a"; GROUP BY lower(supplierName) ORDER BY val DESC LIMIT 18446744073709551610 OFFSET $topX) as a";
$result = mysql_query($query); $result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
if ($row['count'] > 0) { if ($row['count'] > 0) {
$suppliers[] = $row['count'] . " other suppliers"; $suppliers[] = $row['count'] . " other suppliers";
$values[] = doubleval($row[0]); $values[] = doubleval($row[0]);
} }
} }
mysql_free_result($result); mysql_free_result($result);
// Width and height of the graph // Width and height of the graph
$width = 800; $width = 800;
$height = 800; $height = 800;
// Create a graph instance // Create a graph instance
$graph = new PieGraph($width, $height); $graph = new PieGraph($width, $height);
$pieplot = new PiePlot($values); $pieplot = new PiePlot($values);
$pieplot->SetCenter(400, 300); $pieplot->SetCenter(400, 300);
$pieplot->SetGuideLines(true, false); $pieplot->SetGuideLines(true, false);
$pieplot->SetLegends($suppliers); $pieplot->SetLegends($suppliers);
// Add the plot to the graph // Add the plot to the graph
$graph->Add($pieplot); $graph->Add($pieplot);
$graph->legend->SetPos(0.01, 0.97, 'left', 'bottom'); $graph->legend->SetPos(0.01, 0.97, 'left', 'bottom');
$graph->legend->SetColumns(2); $graph->legend->SetColumns(2);
// Display the graph // Display the graph
$graph->Stroke(); $graph->Stroke();
?> ?>
<?php <?php
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
// Width and height of the graph // Width and height of the graph
$width = 800; $width = 800;
$height = 300; $height = 300;
$query = "select procurementMethod, count(1) as count, value, MONTH(contractStart) as month, YEAR(contractStart) as year from `contractnotice` $query = "select procurementMethod, count(1) as count, value, MONTH(contractStart) as month, YEAR(contractStart) as year from `contractnotice`
where $agencyQ $supplierQ childCN = 0 AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2009 group by procurementMethod,year,month order by procurementMethod,year,month"; where $agencyQ $supplierQ childCN = 0 AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2009 group by procurementMethod,year,month order by procurementMethod,year,month";
$result = mysql_query($query); $result = mysql_query($query);
$methods = Array("Direct","Open","Select"); $methods = Array("Direct","Open","Select");
$dates = Array(); $dates = Array();
$methodCountsP = Array(); $methodCountsP = Array();
$methodCounts = Array(); $methodCounts = Array();
$maxValue = 0; $maxValue = 0;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
if ($row['value'] > $maxValue) $maxValue = $row['value']; if ($row['value'] > $maxValue) $maxValue = $row['value'];
$date = date( 'F ', mktime(0, 0, 0, $row["month"]) ). $row["year"]; $date = date( 'F ', mktime(0, 0, 0, $row["month"]) ). $row["year"];
if (array_search($date,$dates) === false ) { if (array_search($date,$dates) === false ) {
$dates[$row["year"]*100 + $row["month"]] = $date; $dates[$row["year"]*100 + $row["month"]] = $date;
ksort($dates); ksort($dates);
} }
$methodCountsP[$row["procurementMethod"]][$date] = $row["count"]; $methodCountsP[$row["procurementMethod"]][$date] = $row["count"];
} }
foreach ($methods as $method) { foreach ($methods as $method) {
foreach($dates as $date) { foreach($dates as $date) {
if ($methodCountsP[$method][$date] > 0) $methodCounts[$method][] = $methodCountsP[$method][$date]; if ($methodCountsP[$method][$date] > 0) $methodCounts[$method][] = $methodCountsP[$method][$date];
else $methodCounts[$method][] = 0; else $methodCounts[$method][] = 0;
} }
} }
$dates = array_values($dates); $dates = array_values($dates);
$totalRecords = array_sum_all($methodCounts); $totalRecords = array_sum_all($methodCounts);
mysql_free_result($result); mysql_free_result($result);
function formatCallback($aVal) { function formatCallback($aVal) {
global $totalRecords; global $totalRecords;
return percent($aVal, $totalRecords) . "%"; return percent($aVal, $totalRecords) . "%";
} }
$attributes = Array(); $attributes = Array();
$attributeNames = Array( $attributeNames = Array(
"Consultancies", "Consultancies",
"Confidentialities" "Confidentialities"
); );
$query = "SELECT 'consultancy', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ consultancy='Yes' AND childCN = 0;"; $query = "SELECT 'consultancy', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ consultancy='Yes' AND childCN = 0;";
$result = mysql_query($query); $result = mysql_query($query);
$row = mysql_fetch_array($result, MYSQL_BOTH); $row = mysql_fetch_array($result, MYSQL_BOTH);
$attributes[0] = $row[1]; $attributes[0] = $row[1];
$query = "SELECT 'confidentiality', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ (confidentialityContract='Yes' OR confidentialityOutputs='Yes') AND childCN = 0;"; $query = "SELECT 'confidentiality', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ (confidentialityContract='Yes' OR confidentialityOutputs='Yes') AND childCN = 0;";
$result = mysql_query($query); $result = mysql_query($query);
$row = mysql_fetch_array($result, MYSQL_BOTH); $row = mysql_fetch_array($result, MYSQL_BOTH);
$attributes[1] = $row[1]; $attributes[1] = $row[1];
mysql_free_result($result); mysql_free_result($result);
// Create a graph instance // Create a graph instance
$graph2 = new Graph($width, $height); $graph2 = new Graph($width, $height);
$graph2->SetScale('textlin',0,$totalRecords); $graph2->SetScale('textlin',0,$totalRecords);
$graph2->Set90AndMargin(105, 45, 45, 45); $graph2->Set90AndMargin(105, 45, 45, 45);
// Setup a title for the graph // Setup a title for the graph
$graph2->title->Set($agency); $graph2->title->Set($agency);
$graph2->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf"); $graph2->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf");
$graph2->title->SetFont(FF_USERFONT, FS_NORMAL, 12); $graph2->title->SetFont(FF_USERFONT, FS_NORMAL, 12);
// Setup font for axis // Setup font for axis
$graph2->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10); $graph2->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10);
$graph2->xaxis->SetTickLabels($attributeNames); $graph2->xaxis->SetTickLabels($attributeNames);
$graph2->yaxis->hide(); $graph2->yaxis->hide();
$attb1plot = new BarPlot($attributes); $attb1plot = new BarPlot($attributes);
$attb1plot->value->Show(); $attb1plot->value->Show();
$attb1plot->SetValuePos('top'); $attb1plot->SetValuePos('top');
$attb1plot->value->SetFont(FF_USERFONT, FS_NORMAL, 12); $attb1plot->value->SetFont(FF_USERFONT, FS_NORMAL, 12);
$attb1plot->value->SetAngle(45); $attb1plot->value->SetAngle(45);
$attb1plot->value->SetFormatCallback("formatCallback"); $attb1plot->value->SetFormatCallback("formatCallback");
$attb1plot->SetFillColor("orange"); $attb1plot->SetFillColor("orange");
// ...and add it to the graPH // ...and add it to the graPH
$graph2->Add($attb1plot); $graph2->Add($attb1plot);
$graph2->Stroke(); $graph2->Stroke();
?> ?>
   
<?php <?php
include_once("../lib/common.inc.php"); include_once("../lib/common.inc.php");
$query = "SELECT YEAR(publishDate), MONTH(publishDate), $query = "SELECT YEAR(publishDate), MONTH(publishDate),
value, count(1) as count FROM `contractnotice` value, count(1) as count FROM `contractnotice`
WHERE (YEAR(publishDate) >= 2008) WHERE (YEAR(publishDate) >= 2008)
AND childCN = 0 AND childCN = 0
GROUP BY MONTH(publishDate), YEAR(publishDate) GROUP BY MONTH(publishDate), YEAR(publishDate)
ORDER BY YEAR(publishDate), MONTH(publishDate)"; ORDER BY YEAR(publishDate), MONTH(publishDate)";
$result = mysql_query($query); $result = mysql_query($query);
$dates = Array(); $dates = Array();
$values = Array(); $values = Array();
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row["value"]),2); $value = number_format(doubleval($row["value"]),2);
$month_name = date( 'F', mktime(0, 0, 0, $row[1]) ); $month_name = date( 'F', mktime(0, 0, 0, $row[1]) );
$dates[] = $month_name." {$row[0]}"; $dates[] = $month_name." {$row[0]}";
$counts[] = doubleval($row["count"]); $counts[] = doubleval($row["count"]);
$values[] = doubleval($row["value"]); $values[] = doubleval($row["value"]);
} }
mysql_free_result($result); mysql_free_result($result);
// Width and height of the graph // Width and height of the graph
$width = 1000; $height = 400; $width = 1000; $height = 400;
// Create a graph instance // Create a graph instance
$graph = new Graph($width,$height); $graph = new Graph($width,$height);
$graph->SetMargin(85,45,45,115); $graph->SetMargin(85,45,45,115);
// Specify what scale we want to use, // Specify what scale we want to use,
$graph->SetScale('textlog'); $graph->SetScale('textlog');
// Setup a title for the graph // Setup a title for the graph
$graph->title->Set('Contracts Starting - All Agencies since July 2008'); $graph->title->Set('Contracts Starting - All Agencies since July 2008');
$graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf"); $graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf");
$graph->title->SetFont(FF_USERFONT,FS_NORMAL,12); $graph->title->SetFont(FF_USERFONT,FS_NORMAL,12);
// Setup font for axis // Setup font for axis
$graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,10); $graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,10);
$graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,10); $graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,10);
// Setup titles and X-axis labels // Setup titles and X-axis labels
$graph->xaxis->SetTickLabels($dates); $graph->xaxis->SetTickLabels($dates);
$graph->xaxis->SetLabelAngle(50); $graph->xaxis->SetLabelAngle(50);
// Create the linear plot // Create the linear plot
$valueplot=new LinePlot($values); $valueplot=new LinePlot($values);
$valueplot->SetFillColor('orange@0.5'); $valueplot->SetFillColor('orange@0.5');
$valueplot->SetLegend("Total Value"); $valueplot->SetLegend("Total Value");
$countplot=new LinePlot($counts); $countplot=new LinePlot($counts);
$countplot->SetFillColor('red@0.5'); $countplot->SetFillColor('red@0.5');
$countplot->SetLegend("Number of Contracts"); $countplot->SetLegend("Number of Contracts");
// Add the plot to the graph // Add the plot to the graph
$graph->Add($valueplot); $graph->Add($valueplot);
$graph->SetYScale(0,'lin'); $graph->SetYScale(0,'lin');
$graph->ynaxis[0]->SetColor('red'); $graph->ynaxis[0]->SetColor('red');
$graph->AddY(0,$countplot); $graph->AddY(0,$countplot);
// Display the graph // Display the graph
$graph->Stroke(); $graph->Stroke();
?> ?>
   
<?php <?php
include_once("../lib/common.inc.php"); include_once("../lib/common.inc.php");
$query = "SELECT YEAR(contractStart), MONTH(contractStart), $query = "SELECT YEAR(contractStart), MONTH(contractStart),
value, count(1) as count FROM `contractnotice` value, count(1) as count FROM `contractnotice`
WHERE (YEAR(contractStart) >= 2008) WHERE (YEAR(contractStart) >= 2008)
AND childCN = 0 AND childCN = 0
GROUP BY MONTH(contractStart), YEAR(contractStart) GROUP BY MONTH(contractStart), YEAR(contractStart)
ORDER BY YEAR(contractStart), MONTH(contractStart)"; ORDER BY YEAR(contractStart), MONTH(contractStart)";
$result = mysql_query($query); $result = mysql_query($query);
$dates = Array(); $dates = Array();
$values = Array(); $values = Array();
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row["value"]),2); $value = number_format(doubleval($row["value"]),2);
$month_name = date( 'F', mktime(0, 0, 0, $row[1]) ); $month_name = date( 'F', mktime(0, 0, 0, $row[1]) );
$dates[] = $month_name." {$row[0]}"; $dates[] = $month_name." {$row[0]}";
$counts[] = doubleval($row["count"]); $counts[] = doubleval($row["count"]);
$values[] = doubleval($row["value"]); $values[] = doubleval($row["value"]);
} }
mysql_free_result($result); mysql_free_result($result);
// Width and height of the graph // Width and height of the graph
$width = 1000; $height = 400; $width = 1000; $height = 400;
// Create a graph instance // Create a graph instance
$graph = new Graph($width,$height); $graph = new Graph($width,$height);
$graph->SetMargin(85,45,45,115); $graph->SetMargin(85,45,45,115);
// Specify what scale we want to use, // Specify what scale we want to use,
$graph->SetScale('textlog'); $graph->SetScale('textlog');
// Setup a title for the graph // Setup a title for the graph
$graph->title->Set('Contracts Starting - All Agencies since July 2008'); $graph->title->Set('Contracts Starting - All Agencies since July 2008');
$graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf"); $graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf");
$graph->title->SetFont(FF_USERFONT,FS_NORMAL,12); $graph->title->SetFont(FF_USERFONT,FS_NORMAL,12);
// Setup font for axis // Setup font for axis
$graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,10); $graph->xaxis->SetFont(FF_USERFONT,FS_NORMAL,10);
$graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,10); $graph->yaxis->SetFont(FF_USERFONT,FS_NORMAL,10);
// Setup titles and X-axis labels // Setup titles and X-axis labels
$graph->xaxis->SetTickLabels($dates); $graph->xaxis->SetTickLabels($dates);
$graph->xaxis->SetLabelAngle(50); $graph->xaxis->SetLabelAngle(50);
// Create the linear plot // Create the linear plot
$valueplot=new LinePlot($values); $valueplot=new LinePlot($values);
$valueplot->SetFillColor('orange@0.5'); $valueplot->SetFillColor('orange@0.5');
$valueplot->SetLegend("Total Value"); $valueplot->SetLegend("Total Value");
$countplot=new LinePlot($counts); $countplot=new LinePlot($counts);
$countplot->SetFillColor('red@0.5'); $countplot->SetFillColor('red@0.5');
$countplot->SetLegend("Number of Contracts"); $countplot->SetLegend("Number of Contracts");
// Add the plot to the graph // Add the plot to the graph
$graph->Add($valueplot); $graph->Add($valueplot);
$graph->SetYScale(0,'lin'); $graph->SetYScale(0,'lin');
$graph->ynaxis[0]->SetColor('red'); $graph->ynaxis[0]->SetColor('red');
$graph->AddY(0,$countplot); $graph->AddY(0,$countplot);
// Display the graph // Display the graph
$graph->Stroke(); $graph->Stroke();
?> ?>
   
<?php <?php
include('../lib/common.inc.php'); include('../lib/common.inc.php');
$year = 2006; $year = 2006;
$ZeroX = 112.5; $ZeroX = 112.5;
$MaxX = 157; $MaxX = 157;
$ZeroY = -9; $ZeroY = -9;
$MaxY = -45; $MaxY = -45;
$XRange = $MaxX - $ZeroX; $XRange = $MaxX - $ZeroX;
$YRange = abs($MaxY) - abs($ZeroY); $YRange = abs($MaxY) - abs($ZeroY);
$xdivs = 250; $xdivs = 250;
$xdivlength = $XRange / $xdivs; $xdivlength = $XRange / $xdivs;
$ydivs = 250; $ydivs = 250;
$ydivheight = $YRange / $ydivs; $ydivheight = $YRange / $ydivs;
$borderLeft = 100; $borderLeft = 100;
$borderTop = 35; $borderTop = 35;
$width = 497; $width = 497;
$height = 457; $height = 457;
//echo "http://dev.openstreetmap.org/~pafciu17/?module=map&bbox=".$ZeroX.",".$ZeroY.",".$MaxX.",".$MaxY."&width=".$width."&height=".$height; //echo "http://dev.openstreetmap.org/~pafciu17/?module=map&bbox=".$ZeroX.",".$ZeroY.",".$MaxX.",".$MaxY."&width=".$width."&height=".$height;
//$handle = ImageCreate ($width, $height) or die ("Cannot Create image"); //$handle = ImageCreate ($width, $height) or die ("Cannot Create image");
$handle = imagecreatefrompng('../images/australia.png'); $handle = imagecreatefrompng('../images/australia.png');
$white = imagecolorallocate($handle, 0, 0, 0); $white = imagecolorallocate($handle, 0, 0, 0);
imagecolortransparent($handle, $white); imagecolortransparent($handle, $white);
$query = "SELECT supplierPostcode, sum(value) as value, lat, lon FROM `contractnotice`,`postcodes` where childCN = 0 AND supplierCountry = 'Australia' AND YEAR(contractStart) >= '$year' AND supplierPostcode = postcode GROUP BY supplierPostcode"; $query = "SELECT supplierPostcode, sum(value) as value, lat, lon FROM `contractnotice`,`postcodes` where childCN = 0 AND supplierCountry = 'Australia' AND YEAR(contractStart) >= '$year' AND supplierPostcode = postcode GROUP BY supplierPostcode";
$result = mysql_query($query); $result = mysql_query($query);
$left = "FFFF50"; $left = "FFFF50";
$right= "EF0050"; $right= "EF0050";
$leftR = hexdec(substr($left,0,2)); $leftR = hexdec(substr($left,0,2));
$leftG = hexdec(substr($left,2,2)); $leftG = hexdec(substr($left,2,2));
$leftB = hexdec(substr($left,4,2)); $leftB = hexdec(substr($left,4,2));
$rightR = hexdec(substr($right,0,2)); $rightR = hexdec(substr($right,0,2));
$rightG = hexdec(substr($right,2,2)); $rightG = hexdec(substr($right,2,2));
$rightB = hexdec(substr($right,4,2)); $rightB = hexdec(substr($right,4,2));
for($i=0;$i<250;$i++) { for($i=0;$i<250;$i++) {
$colorset[$i] = imagecolorallocatealpha($handle, $leftR + ($i*(($rightR-$leftR)/250)), $leftG + ($i*(($rightG-$leftG)/250)), $leftB + ($i*(($rightB-$leftB)/250)),117 - ($i/250)*40); $colorset[$i] = imagecolorallocatealpha($handle, $leftR + ($i*(($rightR-$leftR)/250)), $leftG + ($i*(($rightG-$leftG)/250)), $leftB + ($i*(($rightB-$leftB)/250)),117 - ($i/250)*40);
} }
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) while ($row = mysql_fetch_array($result, MYSQL_BOTH))
{ {
$xpage = round((($XRange - ($MaxX - $row['lon'])) / $xdivlength)); $xpage = round((($XRange - ($MaxX - $row['lon'])) / $xdivlength));
if ($row['lat'] < -40.25) $row['lat']-= 0.75; if ($row['lat'] < -40.25) $row['lat']-= 0.75;
$ypage = round(($YRange - (abs($MaxY) - abs($row['lat']))) / $ydivheight); $ypage = round(($YRange - (abs($MaxY) - abs($row['lat']))) / $ydivheight);
@$pagevalues[$xpage][$ypage] += $row['value']; @$pagevalues[$xpage][$ypage] += $row['value'];
//echo $ypage." ".$xpage."<br>"; //echo $ypage." ".$xpage."<br>";
} }
$max = 0; $max = 0;
$min = 0; $min = 0;
for ($i = 0;$i < $xdivs; $i++ ) { for ($i = 0;$i < $xdivs; $i++ ) {
for ($j = 0;$j < $ydivs; $j++ ) { for ($j = 0;$j < $ydivs; $j++ ) {
if (@$pagevalues[$i][$j]) if (@$pagevalues[$i][$j])
{ {
if (@$pagevalues[$i][$j] > $max) $max = @$pagevalues[$i][$j]; if (@$pagevalues[$i][$j] > $max) $max = @$pagevalues[$i][$j];
if ($min == 0 || @$pagevalues[$i][$j] < $min) $min = @$pagevalues[$i][$j]; if ($min == 0 || @$pagevalues[$i][$j] < $min) $min = @$pagevalues[$i][$j];
} else { } else {
@$pagevalues[$i][$j] = ((@$pagevalues[$i][$j] + (@$pagevalues[$i+1][$j] + @$pagevalues[$i][$j+1] @$pagevalues[$i][$j] = ((@$pagevalues[$i][$j] + (@$pagevalues[$i+1][$j] + @$pagevalues[$i][$j+1]
+ @$pagevalues[$i-1][$j] + @$pagevalues[$i][$j-1])/4) /2)-9; + @$pagevalues[$i-1][$j] + @$pagevalues[$i][$j-1])/4) /2)-9;
@$pagevalues[$i-1][$j] = ((@$pagevalues[$i-1][$j] + (@$pagevalues[$i][$j] + @$pagevalues[$i-1][$j+1] @$pagevalues[$i-1][$j] = ((@$pagevalues[$i-1][$j] + (@$pagevalues[$i][$j] + @$pagevalues[$i-1][$j+1]
+ @$pagevalues[$i-2][$j] + @$pagevalues[$i-1][$j-1])/4) /2)-9; + @$pagevalues[$i-2][$j] + @$pagevalues[$i-1][$j-1])/4) /2)-9;
@$pagevalues[$i][$j-1] = ((@$pagevalues[$i][$j-1] + (@$pagevalues[$i+1][$j-1] + @$pagevalues[$i][$j] @$pagevalues[$i][$j-1] = ((@$pagevalues[$i][$j-1] + (@$pagevalues[$i+1][$j-1] + @$pagevalues[$i][$j]
+ @$pagevalues[$i-1][$j-1] + @$pagevalues[$i][$j-2])/4) /2)-9; + @$pagevalues[$i-1][$j-1] + @$pagevalues[$i][$j-2])/4) /2)-9;
} }
} }
} }
//echo $max." ".$min; //echo $max." ".$min;
//echo "<table width='100%'>"; //echo "<table width='100%'>";
for ($i = 0;$i < $xdivs; $i++ ) { for ($i = 0;$i < $xdivs; $i++ ) {
// echo "<tr>"; // echo "<tr>";
for ($j = 0; $j < $ydivs; $j++ ) { for ($j = 0; $j < $ydivs; $j++ ) {
// echo ("<td>". log10(@$pagevalues[$i][$j])/log10($max) ."</td>"); // echo ("<td>". log10(@$pagevalues[$i][$j])/log10($max) ."</td>");
if ((@$pagevalues[$i][$j]) > $min) { if ((@$pagevalues[$i][$j]) > $min) {
$x = $i*($width/$xdivs); $x = $i*($width/$xdivs);
$x1 = $borderLeft + $x -($width/$xdivs); $x1 = $borderLeft + $x -($width/$xdivs);
$x2 = $borderLeft + $x +($width/$xdivs); $x2 = $borderLeft + $x +($width/$xdivs);
$y = $j*($height/$ydivs); $y = $j*($height/$ydivs);
$y1 = $borderTop + $y - ($height/$ydivs); $y1 = $borderTop + $y - ($height/$ydivs);
$y2 = $borderTop + $y + ($height/$ydivs); $y2 = $borderTop + $y + ($height/$ydivs);
imagefilledrectangle ($handle, $x1, $y1, $x2, $y2, $colorset[(int)((log10(@$pagevalues[$i][$j])/log10($max))*249)]); imagefilledrectangle ($handle, $x1, $y1, $x2, $y2, $colorset[(int)((log10(@$pagevalues[$i][$j])/log10($max))*249)]);
} }
} }
//echo "</tr>"; //echo "</tr>";
} }
//echo "</table>" //echo "</table>"
header ("Content-type: image/png"); header ("Content-type: image/png");
ImagePng ($handle); ImagePng ($handle);
?> ?>
<?php <?php
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
// Width and height of the graph // Width and height of the graph
$width = 800; $width = 800;
$height = 300; $height = 300;
$query = "select procurementMethod, count(1) as count, value, MONTH(contractStart) as month, YEAR(contractStart) as year from `contractnotice` $query = "select procurementMethod, count(1) as count, value, MONTH(contractStart) as month, YEAR(contractStart) as year from `contractnotice`
where $agencyQ $supplierQ childCN = 0 AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2009 group by procurementMethod,year,month order by procurementMethod,year,month"; where $agencyQ $supplierQ childCN = 0 AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2009 group by procurementMethod,year,month order by procurementMethod,year,month";
$result = mysql_query($query); $result = mysql_query($query);
$methods = Array("Direct","Open","Select"); $methods = Array("Direct","Open","Select");
$dates = Array(); $dates = Array();
$methodCountsP = Array(); $methodCountsP = Array();
$methodCounts = Array(); $methodCounts = Array();
$maxValue = 0; $maxValue = 0;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
if ($row['value'] > $maxValue) $maxValue = $row['value']; if ($row['value'] > $maxValue) $maxValue = $row['value'];
$date = date( 'F ', mktime(0, 0, 0, $row["month"]) ). $row["year"]; $date = date( 'F ', mktime(0, 0, 0, $row["month"]) ). $row["year"];
if (array_search($date,$dates) === false ) { if (array_search($date,$dates) === false ) {
$dates[$row["year"]*100 + $row["month"]] = $date; $dates[$row["year"]*100 + $row["month"]] = $date;
ksort($dates); ksort($dates);
} }
$methodCountsP[$row["procurementMethod"]][$date] = $row["count"]; $methodCountsP[$row["procurementMethod"]][$date] = $row["count"];
} }
foreach ($methods as $method) { foreach ($methods as $method) {
foreach($dates as $date) { foreach($dates as $date) {
if ($methodCountsP[$method][$date] > 0) $methodCounts[$method][] = $methodCountsP[$method][$date]; if ($methodCountsP[$method][$date] > 0) $methodCounts[$method][] = $methodCountsP[$method][$date];
else $methodCounts[$method][] = 0; else $methodCounts[$method][] = 0;
} }
} }
$dates = array_values($dates); $dates = array_values($dates);
$totalRecords = array_sum_all($methodCounts); $totalRecords = array_sum_all($methodCounts);
mysql_free_result($result); mysql_free_result($result);
// Create a graph instance // Create a graph instance
$graph = new Graph($width, $height); $graph = new Graph($width, $height);
$graph->SetScale('datint'); $graph->SetScale('datint');
$graph->SetMargin(95, 145, 45, 100); $graph->SetMargin(95, 145, 45, 100);
// Setup a title for the graph // Setup a title for the graph
$graph->title->Set($agencyQ.$supplierQ); $graph->title->Set($agencyQ.$supplierQ);
$graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf"); $graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf");
$graph->title->SetFont(FF_USERFONT, FS_NORMAL, 12); $graph->title->SetFont(FF_USERFONT, FS_NORMAL, 12);
// Setup font for axis // Setup font for axis
$graph->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10); $graph->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10);
$graph->xaxis->SetTickLabels($dates); $graph->xaxis->SetTickLabels($dates);
$graph->xaxis->SetLabelAngle(50); $graph->xaxis->SetLabelAngle(50);
$colors = Array ("orange","red","blue"); $colors = Array ("orange","red","blue");
for ($i = 0; $i <= 2;$i++) { for ($i = 0; $i <= 2;$i++) {
$lplot[$i] = new LinePlot($methodCounts[$methods[$i]]); $lplot[$i] = new LinePlot($methodCounts[$methods[$i]]);
$lplot[$i]->SetLegend($methods[$i]); $lplot[$i]->SetLegend($methods[$i]);
$lplot[$i]->SetFillColor($colors[$i]); $lplot[$i]->SetFillColor($colors[$i]);
} }
// Create the grouped bar plot // Create the grouped bar plot
$alplot = new AccLinePlot($lplot); $alplot = new AccLinePlot($lplot);
// ...and add it to the graPH // ...and add it to the graPH
$graph->Add($alplot); $graph->Add($alplot);
$graph->Stroke(); $graph->Stroke();
function formatCallback($aVal) { function formatCallback($aVal) {
global $totalRecords; global $totalRecords;
return percent($aVal, $totalRecords) . "%"; return percent($aVal, $totalRecords) . "%";
} }
$attributes = Array(); $attributes = Array();
$attributeNames = Array( $attributeNames = Array(
"Consultancies", "Consultancies",
"Confidentialities" "Confidentialities"
); );
$query = "SELECT 'consultancy', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ consultancy='Yes' AND childCN = 0;"; $query = "SELECT 'consultancy', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ consultancy='Yes' AND childCN = 0;";
$result = mysql_query($query); $result = mysql_query($query);
$row = mysql_fetch_array($result, MYSQL_BOTH); $row = mysql_fetch_array($result, MYSQL_BOTH);
$attributes[0] = $row[1]; $attributes[0] = $row[1];
$query = "SELECT 'confidentiality', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ (confidentialityContract='Yes' OR confidentialityOutputs='Yes') AND childCN = 0;"; $query = "SELECT 'confidentiality', count(1) FROM `contractnotice` WHERE $agencyQ $supplierQ (confidentialityContract='Yes' OR confidentialityOutputs='Yes') AND childCN = 0;";
$result = mysql_query($query); $result = mysql_query($query);
$row = mysql_fetch_array($result, MYSQL_BOTH); $row = mysql_fetch_array($result, MYSQL_BOTH);
$attributes[1] = $row[1]; $attributes[1] = $row[1];
mysql_free_result($result); mysql_free_result($result);
// Create a graph instance // Create a graph instance
$graph2 = new Graph($width, $height); $graph2 = new Graph($width, $height);
$graph2->SetScale('textlin',0,$totalRecords); $graph2->SetScale('textlin',0,$totalRecords);
$graph2->Set90AndMargin(105, 45, 45, 45); $graph2->Set90AndMargin(105, 45, 45, 45);
// Setup a title for the graph // Setup a title for the graph
$graph2->title->Set($agency); $graph2->title->Set($agency);
$graph2->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf"); $graph2->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf");
$graph2->title->SetFont(FF_USERFONT, FS_NORMAL, 12); $graph2->title->SetFont(FF_USERFONT, FS_NORMAL, 12);
// Setup font for axis // Setup font for axis
$graph2->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10); $graph2->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10);
$graph2->xaxis->SetTickLabels($attributeNames); $graph2->xaxis->SetTickLabels($attributeNames);
$graph2->yaxis->hide(); $graph2->yaxis->hide();
$attb1plot = new BarPlot($attributes); $attb1plot = new BarPlot($attributes);
$attb1plot->value->Show(); $attb1plot->value->Show();
$attb1plot->SetValuePos('top'); $attb1plot->SetValuePos('top');
$attb1plot->value->SetFont(FF_USERFONT, FS_NORMAL, 12); $attb1plot->value->SetFont(FF_USERFONT, FS_NORMAL, 12);
$attb1plot->value->SetAngle(45); $attb1plot->value->SetAngle(45);
$attb1plot->value->SetFormatCallback("formatCallback"); $attb1plot->value->SetFormatCallback("formatCallback");
$attb1plot->SetFillColor("orange"); $attb1plot->SetFillColor("orange");
// ...and add it to the graPH // ...and add it to the graPH
$graph2->Add($attb1plot); $graph2->Add($attb1plot);
//----------------------- //-----------------------
// Create a multigraph // Create a multigraph
//---------------------- //----------------------
$mgraph = new MGraph(); $mgraph = new MGraph();
$mgraph->SetMargin(2, 2, 2, 2); $mgraph->SetMargin(2, 2, 2, 2);
$mgraph->Add($graph, 0, 0); $mgraph->Add($graph, 0, 0);
$mgraph->Add($graph2, 0, ($height) + 5); $mgraph->Add($graph2, 0, ($height) + 5);
$mgraph->Stroke(); $mgraph->Stroke();
?> ?>
   
<?php <?php
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
// Width and height of the graph // Width and height of the graph
$width = 800; $width = 800;
$height = 300; $height = 300;
$query = "select procurementMethod, value, MONTH(contractStart) as month, YEAR(contractStart) as year from `contractnotice` $query = "select procurementMethod, value, MONTH(contractStart) as month, YEAR(contractStart) as year from `contractnotice`
where $agencyQ $supplierQ childCN = 0 AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2009 group by procurementMethod,year,month order by procurementMethod,year,month"; where $agencyQ $supplierQ childCN = 0 AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2009 group by procurementMethod,year,month order by procurementMethod,year,month";
$result = mysql_query($query); $result = mysql_query($query);
$methods = Array("Direct","Open","Select"); $methods = Array("Direct","Open","Select");
$dates = Array(); $dates = Array();
$methodValuesP = Array(); $methodValuesP = Array();
$methodValues = Array(); $methodValues = Array();
$maxValue = 0; $maxValue = 0;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
if ($row['value'] > $maxValue) $maxValue = $row['value']; if ($row['value'] > $maxValue) $maxValue = $row['value'];
$date = date( 'F ', mktime(0, 0, 0, $row["month"]) ). $row["year"]; $date = date( 'F ', mktime(0, 0, 0, $row["month"]) ). $row["year"];
if (array_search($date,$dates) === false ) { if (array_search($date,$dates) === false ) {
$dates[$row["year"]*100 + $row["month"]] = $date; $dates[$row["year"]*100 + $row["month"]] = $date;
ksort($dates); ksort($dates);
} }
$methodValuesP[$row["procurementMethod"]][$date] = $row["value"]; $methodValuesP[$row["procurementMethod"]][$date] = $row["value"];
} }
foreach ($methods as $method) { foreach ($methods as $method) {
foreach($dates as $date) { foreach($dates as $date) {
if ($methodValuesP[$method][$date] > 0) $methodValues[$method][] = $methodValuesP[$method][$date]; if ($methodValuesP[$method][$date] > 0) $methodValues[$method][] = $methodValuesP[$method][$date];
else $methodValues[$method][] = 0; else $methodValues[$method][] = 0;
} }
} }
$dates = array_values($dates); $dates = array_values($dates);
$totalRecords = array_sum_all($methodValues); $totalRecords = array_sum_all($methodValues);
mysql_free_result($result); mysql_free_result($result);
// Create a graph instance // Create a graph instance
$graph = new Graph($width, $height); $graph = new Graph($width, $height);
$graph->SetScale('datint'); $graph->SetScale('datint');
$graph->SetMargin(95, 145, 45, 100); $graph->SetMargin(95, 145, 45, 100);
// Setup a title for the graph // Setup a title for the graph
$graph->title->Set($agencyQ.$supplierQ); $graph->title->Set($agencyQ.$supplierQ);
$graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf"); $graph->SetUserFont("ttf-liberation/LiberationSans-Regular.ttf");
$graph->title->SetFont(FF_USERFONT, FS_NORMAL, 12); $graph->title->SetFont(FF_USERFONT, FS_NORMAL, 12);
// Setup font for axis // Setup font for axis
$graph->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10); $graph->xaxis->SetFont(FF_USERFONT, FS_NORMAL, 10);
$graph->xaxis->SetTickLabels($dates); $graph->xaxis->SetTickLabels($dates);
$graph->xaxis->SetLabelAngle(50); $graph->xaxis->SetLabelAngle(50);
$colors = Array ("orange","red","blue"); $colors = Array ("orange","red","blue");
for ($i = 0; $i <= 2;$i++) { for ($i = 0; $i <= 2;$i++) {
$lplot[$i] = new LinePlot($methodValues[$methods[$i]]); $lplot[$i] = new LinePlot($methodValues[$methods[$i]]);
$lplot[$i]->SetLegend($methods[$i]); $lplot[$i]->SetLegend($methods[$i]);
$lplot[$i]->SetFillColor($colors[$i]); $lplot[$i]->SetFillColor($colors[$i]);
} }
// Create the grouped bar plot // Create the grouped bar plot
$alplot = new AccLinePlot($lplot); $alplot = new AccLinePlot($lplot);
// ...and add it to the graPH // ...and add it to the graPH
$graph->Add($alplot); $graph->Add($alplot);
$graph->Stroke(); $graph->Stroke();
?> ?>
   
<?php <?php
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
$topX = 10; $topX = 10;
$query = "SELECT value, supplierName $query = "SELECT value, supplierName
FROM `contractnotice` WHERE (YEAR(contractStart) >= 2009) AND childCN = 0 FROM `contractnotice` WHERE (YEAR(contractStart) >= 2009) AND childCN = 0
GROUP BY supplierABN ORDER BY value DESC limit $topX"; GROUP BY supplierABN ORDER BY value DESC limit $topX";
$result = mysql_query($query); $result = mysql_query($query);
$suppliers = Array(); $suppliers = Array();
$values = Array(); $values = Array();
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
// $value = number_format(doubleval($row["value"]) , 2); // $value = number_format(doubleval($row["value"]) , 2);
$suppliers[] = ucsmart($row[1]); $suppliers[] = ucsmart($row[1]);
$values[] = doubleval($row["value"]); $values[] = doubleval($row["value"]);
} }
mysql_free_result($result); mysql_free_result($result);
$query = "SELECT sum(a.value) as val, supplierCountry from (SELECT value, supplierName, supplierCountry $query = "SELECT sum(a.value) as val, supplierCountry from (SELECT value, supplierName, supplierCountry
FROM `contractnotice` WHERE (YEAR(contractStart) >= 2009) AND childCN = 0 FROM `contractnotice` WHERE (YEAR(contractStart) >= 2009) AND childCN = 0
GROUP BY supplierName ORDER BY value LIMIT 18446744073709551610 OFFSET $topX) as a group by supplierCountry order by val DESC limit 5 offset 1"; GROUP BY supplierName ORDER BY value LIMIT 18446744073709551610 OFFSET $topX) as a group by supplierCountry order by val DESC limit 5 offset 1";
$result = mysql_query($query); $result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$suppliers[] = "Other suppliers in ".ucsmart($row["supplierCountry"]); $suppliers[] = "Other suppliers in ".ucsmart($row["supplierCountry"]);
$values[] = doubleval($row[0]); $values[] = doubleval($row[0]);
} }
mysql_free_result($result); mysql_free_result($result);
$query = "SELECT sum(a.value) as val, TRUNCATE(supplierPostcode,-2) as postcode from (SELECT value, supplierName, supplierPostcode, supplierCountry $query = "SELECT sum(a.value) as val, TRUNCATE(supplierPostcode,-2) as postcode from (SELECT value, supplierName, supplierPostcode, supplierCountry
FROM `contractnotice` WHERE (YEAR(contractStart) >= 2009) AND childCN = 0 FROM `contractnotice` WHERE (YEAR(contractStart) >= 2009) AND childCN = 0
GROUP BY supplierName ORDER BY value LIMIT 18446744073709551610 OFFSET $topX) as a GROUP BY supplierName ORDER BY value LIMIT 18446744073709551610 OFFSET $topX) as a
WHERE (supplierCountry LIKE 'Australia' OR supplierCountry LIKE 'AUSTRALIA') AND supplierPostcode < 10000 WHERE (supplierCountry LIKE 'Australia' OR supplierCountry LIKE 'AUSTRALIA') AND supplierPostcode < 10000
group by TRUNCATE(supplierPostcode,-2) group by TRUNCATE(supplierPostcode,-2)
order by val DESC"; order by val DESC";
$result = mysql_query($query); $result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
if ($row['postcode'][0] == 2 && $row['postcode'][1] == 6) $ACTvalue += $row[0]; if ($row['postcode'][0] == 2 && $row['postcode'][1] == 6) $ACTvalue += $row[0];
else if ($row['postcode'][0] == 2 || $row['postcode'][0] == 1) $NSWvalue += $row[0]; else if ($row['postcode'][0] == 2 || $row['postcode'][0] == 1) $NSWvalue += $row[0];
else if ($row['postcode'][0] == 3 || $row['postcode'][0] == 8) $Vicvalue += $row[0]; else if ($row['postcode'][0] == 3 || $row['postcode'][0] == 8) $Vicvalue += $row[0];
else if ($row['postcode'][0] == 4 || $row['postcode'][0] == 9) $QLDvalue += $row[0]; else if ($row['postcode'][0] == 4 || $row['postcode'][0] == 9) $QLDvalue += $row[0];
else if ($row['postcode'][0] == 5) $SAvalue += $row[0]; else if ($row['postcode'][0] == 5) $SAvalue += $row[0];
else if ($row['postcode'][0] == 6) $WAvalue += $row[0]; else if ($row['postcode'][0] == 6) $WAvalue += $row[0];
else if ($row['postcode'][0] == 7) $Tasvalue += $row[0]; else if ($row['postcode'][0] == 7) $Tasvalue += $row[0];
else if ($row['postcode'][0] == 0) $NTvalue += $row[0]; else if ($row['postcode'][0] == 0) $NTvalue += $row[0];
} }
mysql_free_result($result); mysql_free_result($result);
$suppliers[] = "Other suppliers in Australia - ACT"; $suppliers[] = "Other suppliers in Australia - ACT";
$values[] = doubleval($ACTvalue); $values[] = doubleval($ACTvalue);
$suppliers[] = "Other suppliers in Australia - NSW"; $suppliers[] = "Other suppliers in Australia - NSW";
$values[] = doubleval($NSWvalue); $values[] = doubleval($NSWvalue);
$suppliers[] = "Other suppliers in Australia - Victoria"; $suppliers[] = "Other suppliers in Australia - Victoria";
$values[] = doubleval($Vicvalue); $values[] = doubleval($Vicvalue);
$suppliers[] = "Other suppliers in Australia - Queensland"; $suppliers[] = "Other suppliers in Australia - Queensland";
$values[] = doubleval($QLDvalue); $values[] = doubleval($QLDvalue);
$suppliers[] = "Other suppliers in Australia - NT"; $suppliers[] = "Other suppliers in Australia - NT";
$values[] = doubleval($NTvalue); $values[] = doubleval($NTvalue);
$suppliers[] = "Other suppliers in Australia - West Australia"; $suppliers[] = "Other suppliers in Australia - West Australia";
$values[] = doubleval($WAvalue); $values[] = doubleval($WAvalue);
$suppliers[] = "Other suppliers in Australia - South Australia"; $suppliers[] = "Other suppliers in Australia - South Australia";
$values[] = doubleval($SAvalue); $values[] = doubleval($SAvalue);
$suppliers[] = "Other suppliers in Australia - Tasmania"; $suppliers[] = "Other suppliers in Australia - Tasmania";
$values[] = doubleval($Tasvalue); $values[] = doubleval($Tasvalue);
// Width and height of the graph // Width and height of the graph
$width = 800; $width = 800;
$height = 800; $height = 800;
// Create a graph instance // Create a graph instance
$graph = new PieGraph($width, $height); $graph = new PieGraph($width, $height);
$pieplot = new PiePlot($values); $pieplot = new PiePlot($values);
$pieplot->SetCenter(400, 300); $pieplot->SetCenter(400, 300);
$pieplot->SetGuideLines(true, false); $pieplot->SetGuideLines(true, false);
$pieplot->SetLegends($suppliers); $pieplot->SetLegends($suppliers);
$pieplot->SetTheme('earth'); $pieplot->SetTheme('earth');
// Add the plot to the graph // Add the plot to the graph
$graph->Add($pieplot); $graph->Add($pieplot);
$graph->legend->SetPos(0.1, 0.97, 'left', 'bottom'); $graph->legend->SetPos(0.1, 0.97, 'left', 'bottom');
$graph->legend->SetColumns(2); $graph->legend->SetColumns(2);
// Display the graph // Display the graph
$graph->Stroke(); $graph->Stroke();
?> ?>
if(typeof(bsn)=="undefined")_b=bsn={};if(typeof(_b.Autosuggest)=="undefined")_b.Autosuggest={};else alert("Autosuggest is already set!");_b.AutoSuggest=function(b,c){if(!document.getElementById)return 0;this.fld=_b.DOM.gE(b);if(!this.fld)return 0;this.sInp="";this.nInpC=0;this.aSug=[];this.iHigh=0;this.oP=c?c:{};var k,def={minchars:1,meth:"get",varname:"input",className:"autosuggest",timeout:2500,delay:500,offsety:-5,shownoresults:true,noresults:"No results!",maxheight:250,cache:true,maxentries:25};for(k in def){if(typeof(this.oP[k])!=typeof(def[k]))this.oP[k]=def[k]}var p=this;this.fld.onkeypress=function(a){return p.onKeyPress(a)};this.fld.onkeyup=function(a){return p.onKeyUp(a)};this.fld.setAttribute("autocomplete","off")};_b.AutoSuggest.prototype.onKeyPress=function(a){var b=(window.event)?window.event.keyCode:a.keyCode;var c=13;var d=9;var e=27;var f=1;switch(b){case c:this.setHighlightedValue();f=0;break;case e:this.clearSuggestions();break}return f};_b.AutoSuggest.prototype.onKeyUp=function(a){var b=(window.event)?window.event.keyCode:a.keyCode;var c=38;var d=40;var e=1;switch(b){case c:this.changeHighlight(b);e=0;break;case d:this.changeHighlight(b);e=0;break;default:this.getSuggestions(this.fld.value)}return e};_b.AutoSuggest.prototype.getSuggestions=function(a){if(a==this.sInp)return 0;_b.DOM.remE(this.idAs);this.sInp=a;if(a.length<this.oP.minchars){this.aSug=[];this.nInpC=a.length;return 0}var b=this.nInpC;this.nInpC=a.length?a.length:0;var l=this.aSug.length;if(this.nInpC>b&&l&&l<this.oP.maxentries&&this.oP.cache){var c=[];for(var i=0;i<l;i++){if(this.aSug[i].value.substr(0,a.length).toLowerCase()==a.toLowerCase())c.push(this.aSug[i])}this.aSug=c;this.createList(this.aSug);return false}else{var d=this;var e=this.sInp;clearTimeout(this.ajID);this.ajID=setTimeout(function(){d.doAjaxRequest(e)},this.oP.delay)}return false};_b.AutoSuggest.prototype.doAjaxRequest=function(b){if(b!=this.fld.value)return false;var c=this;if(typeof(this.oP.script)=="function")var d=this.oP.script(encodeURIComponent(this.sInp));else var d=this.oP.script+this.oP.varname+"="+encodeURIComponent(this.sInp);if(!d)return false;var e=this.oP.meth;var b=this.sInp;var f=function(a){c.setSuggestions(a,b)};var g=function(a){alert("AJAX error: "+a)};var h=new _b.Ajax();h.makeRequest(d,e,f,g)};_b.AutoSuggest.prototype.setSuggestions=function(a,b){if(b!=this.fld.value)return false;this.aSug=[];if(this.oP.json){var c=eval('('+a.responseText+')');for(var i=0;i<c.results.length;i++){this.aSug.push({'id':c.results[i].id,'value':c.results[i].value,'info':c.results[i].info})}}else{var d=a.responseXML;var e=d.getElementsByTagName('results')[0].childNodes;for(var i=0;i<e.length;i++){if(e[i].hasChildNodes())this.aSug.push({'id':e[i].getAttribute('id'),'value':e[i].childNodes[0].nodeValue,'info':e[i].getAttribute('info')})}}this.idAs="as_"+this.fld.id;this.createList(this.aSug)};_b.AutoSuggest.prototype.createList=function(b){var c=this;_b.DOM.remE(this.idAs);this.killTimeout();if(b.length==0&&!this.oP.shownoresults)return false;var d=_b.DOM.cE("div",{id:this.idAs,className:this.oP.className});var e=_b.DOM.cE("div",{className:"as_corner"});var f=_b.DOM.cE("div",{className:"as_bar"});var g=_b.DOM.cE("div",{className:"as_header"});g.appendChild(e);g.appendChild(f);d.appendChild(g);var h=_b.DOM.cE("ul",{id:"as_ul"});for(var i=0;i<b.length;i++){var j=b[i].value;var k=j.toLowerCase().indexOf(this.sInp.toLowerCase());var l=j.substring(0,k)+"<em>"+j.substring(k,k+this.sInp.length)+"</em>"+j.substring(k+this.sInp.length);var m=_b.DOM.cE("span",{},l,true);if(b[i].info!=""){var n=_b.DOM.cE("br",{});m.appendChild(n);var o=_b.DOM.cE("small",{},b[i].info);m.appendChild(o)}var a=_b.DOM.cE("a",{href:"#"});var p=_b.DOM.cE("span",{className:"tl"}," ");var q=_b.DOM.cE("span",{className:"tr"}," ");a.appendChild(p);a.appendChild(q);a.appendChild(m);a.name=i+1;a.onclick=function(){c.setHighlightedValue();return false};a.onmouseover=function(){c.setHighlight(this.name)};var r=_b.DOM.cE("li",{},a);h.appendChild(r)}if(b.length==0&&this.oP.shownoresults){var r=_b.DOM.cE("li",{className:"as_warning"},this.oP.noresults);h.appendChild(r)}d.appendChild(h);var s=_b.DOM.cE("div",{className:"as_corner"});var t=_b.DOM.cE("div",{className:"as_bar"});var u=_b.DOM.cE("div",{className:"as_footer"});u.appendChild(s);u.appendChild(t);d.appendChild(u);var v=_b.DOM.getPos(this.fld);d.style.left=v.x+"px";d.style.top=(v.y+this.fld.offsetHeight+this.oP.offsety)+"px";d.style.width=this.fld.offsetWidth+"px";d.onmouseover=function(){c.killTimeout()};d.onmouseout=function(){c.resetTimeout()};document.getElementsByTagName("body")[0].appendChild(d);this.iHigh=0;var c=this;this.toID=setTimeout(function(){c.clearSuggestions()},this.oP.timeout)};_b.AutoSuggest.prototype.changeHighlight=function(a){var b=_b.DOM.gE("as_ul");if(!b)return false;var n;if(a==40)n=this.iHigh+1;else if(a==38)n=this.iHigh-1;if(n>b.childNodes.length)n=b.childNodes.length;if(n<1)n=1;this.setHighlight(n)};_b.AutoSuggest.prototype.setHighlight=function(n){var a=_b.DOM.gE("as_ul");if(!a)return false;if(this.iHigh>0)this.clearHighlight();this.iHigh=Number(n);a.childNodes[this.iHigh-1].className="as_highlight";this.killTimeout()};_b.AutoSuggest.prototype.clearHighlight=function(){var a=_b.DOM.gE("as_ul");if(!a)return false;if(this.iHigh>0){a.childNodes[this.iHigh-1].className="";this.iHigh=0}};_b.AutoSuggest.prototype.setHighlightedValue=function(){if(this.iHigh){this.sInp=this.fld.value=this.aSug[this.iHigh-1].value;this.fld.focus();if(this.fld.selectionStart)this.fld.setSelectionRange(this.sInp.length,this.sInp.length);this.clearSuggestions();if(typeof(this.oP.callback)=="function")this.oP.callback(this.aSug[this.iHigh-1])}};_b.AutoSuggest.prototype.killTimeout=function(){clearTimeout(this.toID)};_b.AutoSuggest.prototype.resetTimeout=function(){clearTimeout(this.toID);var a=this;this.toID=setTimeout(function(){a.clearSuggestions()},1000)};_b.AutoSuggest.prototype.clearSuggestions=function(){this.killTimeout();var a=_b.DOM.gE(this.idAs);var b=this;if(a){var c=new _b.Fader(a,1,0,250,function(){_b.DOM.remE(b.idAs)})}};if(typeof(_b.Ajax)=="undefined")_b.Ajax={};_b.Ajax=function(){this.req={};this.isIE=false};_b.Ajax.prototype.makeRequest=function(a,b,c,d){if(b!="POST")b="GET";this.onComplete=c;this.onError=d;var e=this;if(window.XMLHttpRequest){this.req=new XMLHttpRequest();this.req.onreadystatechange=function(){e.processReqChange()};this.req.open("GET",a,true);this.req.send(null)}else if(window.ActiveXObject){this.req=new ActiveXObject("Microsoft.XMLHTTP");if(this.req){this.req.onreadystatechange=function(){e.processReqChange()};this.req.open(b,a,true);this.req.send()}}};_b.Ajax.prototype.processReqChange=function(){if(this.req.readyState==4){if(this.req.status==200){this.onComplete(this.req)}else{this.onError(this.req.status)}}};if(typeof(_b.DOM)=="undefined")_b.DOM={};_b.DOM.cE=function(b,c,d,e){var f=document.createElement(b);if(!f)return 0;for(var a in c)f[a]=c[a];var t=typeof(d);if(t=="string"&&!e)f.appendChild(document.createTextNode(d));else if(t=="string"&&e)f.innerHTML=d;else if(t=="object")f.appendChild(d);return f};_b.DOM.gE=function(e){var t=typeof(e);if(t=="undefined")return 0;else if(t=="string"){var a=document.getElementById(e);if(!a)return 0;else if(typeof(a.appendChild)!="undefined")return a;else return 0}else if(typeof(e.appendChild)!="undefined")return e;else return 0};_b.DOM.remE=function(a){var e=this.gE(a);if(!e)return 0;else if(e.parentNode.removeChild(e))return true;else return 0};_b.DOM.getPos=function(e){var e=this.gE(e);var a=e;var b=0;if(a.offsetParent){while(a.offsetParent){b+=a.offsetLeft;a=a.offsetParent}}else if(a.x)b+=a.x;var a=e;var c=0;if(a.offsetParent){while(a.offsetParent){c+=a.offsetTop;a=a.offsetParent}}else if(a.y)c+=a.y;return{x:b,y:c}};if(typeof(_b.Fader)=="undefined")_b.Fader={};_b.Fader=function(a,b,c,d,e){if(!a)return 0;this.e=a;this.from=b;this.to=c;this.cb=e;this.nDur=d;this.nInt=50;this.nTime=0;var p=this;this.nID=setInterval(function(){p._fade()},this.nInt)};_b.Fader.prototype._fade=function(){this.nTime+=this.nInt;var a=Math.round(this._tween(this.nTime,this.from,this.to,this.nDur)*100);var b=a/100;if(this.e.filters){try{this.e.filters.item("DXImageTransform.Microsoft.Alpha").opacity=a}catch(e){this.e.style.filter='progid:DXImageTransform.Microsoft.Alpha(opacity='+a+')'}}else{this.e.style.opacity=b}if(this.nTime==this.nDur){clearInterval(this.nID);if(this.cb!=undefined)this.cb()}};_b.Fader.prototype._tween=function(t,b,c,d){return b+((c-b)*(t/d))}; if(typeof(bsn)=="undefined")_b=bsn={};if(typeof(_b.Autosuggest)=="undefined")_b.Autosuggest={};else alert("Autosuggest is already set!");_b.AutoSuggest=function(b,c){if(!document.getElementById)return 0;this.fld=_b.DOM.gE(b);if(!this.fld)return 0;this.sInp="";this.nInpC=0;this.aSug=[];this.iHigh=0;this.oP=c?c:{};var k,def={minchars:1,meth:"get",varname:"input",className:"autosuggest",timeout:2500,delay:500,offsety:-5,shownoresults:true,noresults:"No results!",maxheight:250,cache:true,maxentries:25};for(k in def){if(typeof(this.oP[k])!=typeof(def[k]))this.oP[k]=def[k]}var p=this;this.fld.onkeypress=function(a){return p.onKeyPress(a)};this.fld.onkeyup=function(a){return p.onKeyUp(a)};this.fld.setAttribute("autocomplete","off")};_b.AutoSuggest.prototype.onKeyPress=function(a){var b=(window.event)?window.event.keyCode:a.keyCode;var c=13;var d=9;var e=27;var f=1;switch(b){case c:this.setHighlightedValue();f=0;break;case e:this.clearSuggestions();break}return f};_b.AutoSuggest.prototype.onKeyUp=function(a){var b=(window.event)?window.event.keyCode:a.keyCode;var c=38;var d=40;var e=1;switch(b){case c:this.changeHighlight(b);e=0;break;case d:this.changeHighlight(b);e=0;break;default:this.getSuggestions(this.fld.value)}return e};_b.AutoSuggest.prototype.getSuggestions=function(a){if(a==this.sInp)return 0;_b.DOM.remE(this.idAs);this.sInp=a;if(a.length<this.oP.minchars){this.aSug=[];this.nInpC=a.length;return 0}var b=this.nInpC;this.nInpC=a.length?a.length:0;var l=this.aSug.length;if(this.nInpC>b&&l&&l<this.oP.maxentries&&this.oP.cache){var c=[];for(var i=0;i<l;i++){if(this.aSug[i].value.substr(0,a.length).toLowerCase()==a.toLowerCase())c.push(this.aSug[i])}this.aSug=c;this.createList(this.aSug);return false}else{var d=this;var e=this.sInp;clearTimeout(this.ajID);this.ajID=setTimeout(function(){d.doAjaxRequest(e)},this.oP.delay)}return false};_b.AutoSuggest.prototype.doAjaxRequest=function(b){if(b!=this.fld.value)return false;var c=this;if(typeof(this.oP.script)=="function")var d=this.oP.script(encodeURIComponent(this.sInp));else var d=this.oP.script+this.oP.varname+"="+encodeURIComponent(this.sInp);if(!d)return false;var e=this.oP.meth;var b=this.sInp;var f=function(a){c.setSuggestions(a,b)};var g=function(a){alert("AJAX error: "+a)};var h=new _b.Ajax();h.makeRequest(d,e,f,g)};_b.AutoSuggest.prototype.setSuggestions=function(a,b){if(b!=this.fld.value)return false;this.aSug=[];if(this.oP.json){var c=eval('('+a.responseText+')');for(var i=0;i<c.results.length;i++){this.aSug.push({'id':c.results[i].id,'value':c.results[i].value,'info':c.results[i].info})}}else{var d=a.responseXML;var e=d.getElementsByTagName('results')[0].childNodes;for(var i=0;i<e.length;i++){if(e[i].hasChildNodes())this.aSug.push({'id':e[i].getAttribute('id'),'value':e[i].childNodes[0].nodeValue,'info':e[i].getAttribute('info')})}}this.idAs="as_"+this.fld.id;this.createList(this.aSug)};_b.AutoSuggest.prototype.createList=function(b){var c=this;_b.DOM.remE(this.idAs);this.killTimeout();if(b.length==0&&!this.oP.shownoresults)return false;var d=_b.DOM.cE("div",{id:this.idAs,className:this.oP.className});var e=_b.DOM.cE("div",{className:"as_corner"});var f=_b.DOM.cE("div",{className:"as_bar"});var g=_b.DOM.cE("div",{className:"as_header"});g.appendChild(e);g.appendChild(f);d.appendChild(g);var h=_b.DOM.cE("ul",{id:"as_ul"});for(var i=0;i<b.length;i++){var j=b[i].value;var k=j.toLowerCase().indexOf(this.sInp.toLowerCase());var l=j.substring(0,k)+"<em>"+j.substring(k,k+this.sInp.length)+"</em>"+j.substring(k+this.sInp.length);var m=_b.DOM.cE("span",{},l,true);if(b[i].info!=""){var n=_b.DOM.cE("br",{});m.appendChild(n);var o=_b.DOM.cE("small",{},b[i].info);m.appendChild(o)}var a=_b.DOM.cE("a",{href:"#"});var p=_b.DOM.cE("span",{className:"tl"}," ");var q=_b.DOM.cE("span",{className:"tr"}," ");a.appendChild(p);a.appendChild(q);a.appendChild(m);a.name=i+1;a.onclick=function(){c.setHighlightedValue();return false};a.onmouseover=function(){c.setHighlight(this.name)};var r=_b.DOM.cE("li",{},a);h.appendChild(r)}if(b.length==0&&this.oP.shownoresults){var r=_b.DOM.cE("li",{className:"as_warning"},this.oP.noresults);h.appendChild(r)}d.appendChild(h);var s=_b.DOM.cE("div",{className:"as_corner"});var t=_b.DOM.cE("div",{className:"as_bar"});var u=_b.DOM.cE("div",{className:"as_footer"});u.appendChild(s);u.appendChild(t);d.appendChild(u);var v=_b.DOM.getPos(this.fld);d.style.left=v.x+"px";d.style.top=(v.y+this.fld.offsetHeight+this.oP.offsety)+"px";d.style.width=this.fld.offsetWidth+"px";d.onmouseover=function(){c.killTimeout()};d.onmouseout=function(){c.resetTimeout()};document.getElementsByTagName("body")[0].appendChild(d);this.iHigh=0;var c=this;this.toID=setTimeout(function(){c.clearSuggestions()},this.oP.timeout)};_b.AutoSuggest.prototype.changeHighlight=function(a){var b=_b.DOM.gE("as_ul");if(!b)return false;var n;if(a==40)n=this.iHigh+1;else if(a==38)n=this.iHigh-1;if(n>b.childNodes.length)n=b.childNodes.length;if(n<1)n=1;this.setHighlight(n)};_b.AutoSuggest.prototype.setHighlight=function(n){var a=_b.DOM.gE("as_ul");if(!a)return false;if(this.iHigh>0)this.clearHighlight();this.iHigh=Number(n);a.childNodes[this.iHigh-1].className="as_highlight";this.killTimeout()};_b.AutoSuggest.prototype.clearHighlight=function(){var a=_b.DOM.gE("as_ul");if(!a)return false;if(this.iHigh>0){a.childNodes[this.iHigh-1].className="";this.iHigh=0}};_b.AutoSuggest.prototype.setHighlightedValue=function(){if(this.iHigh){this.sInp=this.fld.value=this.aSug[this.iHigh-1].value;this.fld.focus();if(this.fld.selectionStart)this.fld.setSelectionRange(this.sInp.length,this.sInp.length);this.clearSuggestions();if(typeof(this.oP.callback)=="function")this.oP.callback(this.aSug[this.iHigh-1])}};_b.AutoSuggest.prototype.killTimeout=function(){clearTimeout(this.toID)};_b.AutoSuggest.prototype.resetTimeout=function(){clearTimeout(this.toID);var a=this;this.toID=setTimeout(function(){a.clearSuggestions()},1000)};_b.AutoSuggest.prototype.clearSuggestions=function(){this.killTimeout();var a=_b.DOM.gE(this.idAs);var b=this;if(a){var c=new _b.Fader(a,1,0,250,function(){_b.DOM.remE(b.idAs)})}};if(typeof(_b.Ajax)=="undefined")_b.Ajax={};_b.Ajax=function(){this.req={};this.isIE=false};_b.Ajax.prototype.makeRequest=function(a,b,c,d){if(b!="POST")b="GET";this.onComplete=c;this.onError=d;var e=this;if(window.XMLHttpRequest){this.req=new XMLHttpRequest();this.req.onreadystatechange=function(){e.processReqChange()};this.req.open("GET",a,true);this.req.send(null)}else if(window.ActiveXObject){this.req=new ActiveXObject("Microsoft.XMLHTTP");if(this.req){this.req.onreadystatechange=function(){e.processReqChange()};this.req.open(b,a,true);this.req.send()}}};_b.Ajax.prototype.processReqChange=function(){if(this.req.readyState==4){if(this.req.status==200){this.onComplete(this.req)}else{this.onError(this.req.status)}}};if(typeof(_b.DOM)=="undefined")_b.DOM={};_b.DOM.cE=function(b,c,d,e){var f=document.createElement(b);if(!f)return 0;for(var a in c)f[a]=c[a];var t=typeof(d);if(t=="string"&&!e)f.appendChild(document.createTextNode(d));else if(t=="string"&&e)f.innerHTML=d;else if(t=="object")f.appendChild(d);return f};_b.DOM.gE=function(e){var t=typeof(e);if(t=="undefined")return 0;else if(t=="string"){var a=document.getElementById(e);if(!a)return 0;else if(typeof(a.appendChild)!="undefined")return a;else return 0}else if(typeof(e.appendChild)!="undefined")return e;else return 0};_b.DOM.remE=function(a){var e=this.gE(a);if(!e)return 0;else if(e.parentNode.removeChild(e))return true;else return 0};_b.DOM.getPos=function(e){var e=this.gE(e);var a=e;var b=0;if(a.offsetParent){while(a.offsetParent){b+=a.offsetLeft;a=a.offsetParent}}else if(a.x)b+=a.x;var a=e;var c=0;if(a.offsetParent){while(a.offsetParent){c+=a.offsetTop;a=a.offsetParent}}else if(a.y)c+=a.y;return{x:b,y:c}};if(typeof(_b.Fader)=="undefined")_b.Fader={};_b.Fader=function(a,b,c,d,e){if(!a)return 0;this.e=a;this.from=b;this.to=c;this.cb=e;this.nDur=d;this.nInt=50;this.nTime=0;var p=this;this.nID=setInterval(function(){p._fade()},this.nInt)};_b.Fader.prototype._fade=function(){this.nTime+=this.nInt;var a=Math.round(this._tween(this.nTime,this.from,this.to,this.nDur)*100);var b=a/100;if(this.e.filters){try{this.e.filters.item("DXImageTransform.Microsoft.Alpha").opacity=a}catch(e){this.e.style.filter='progid:DXImageTransform.Microsoft.Alpha(opacity='+a+')'}}else{this.e.style.opacity=b}if(this.nTime==this.nDur){clearInterval(this.nID);if(this.cb!=undefined)this.cb()}};_b.Fader.prototype._tween=function(t,b,c,d){return b+((c-b)*(t/d))};
<?php <?php
require_once ('jpgraph/jpgraph.php'); require_once ('jpgraph/jpgraph.php');
require_once ('jpgraph/jpgraph_line.php'); require_once ('jpgraph/jpgraph_line.php');
require_once ('jpgraph/jpgraph_log.php'); require_once ('jpgraph/jpgraph_log.php');
require_once ('jpgraph/jpgraph_mgraph.php'); require_once ('jpgraph/jpgraph_mgraph.php');
require_once ('jpgraph/jpgraph_pie.php'); require_once ('jpgraph/jpgraph_pie.php');
require_once ('jpgraph/jpgraph_bar.php'); require_once ('jpgraph/jpgraph_bar.php');
require_once ('jpgraph/jpgraph_date.php'); require_once ('jpgraph/jpgraph_date.php');
error_reporting(E_ALL ^ E_NOTICE); error_reporting(E_ALL ^ E_NOTICE);
$link = mysql_connect('localhost', 'root', ''); $link = mysql_connect('localhost', 'root', '');
if (!$link) { if (!$link) {
die('Could not connect: ' . mysql_error()); die('Could not connect: ' . mysql_error());
} }
@mysql_select_db("contractDashboard") or die("Unable to select database"); @mysql_select_db("contractDashboard") or die("Unable to select database");
function ucsmart($str) { function ucsmart($str) {
return preg_replace("/(?<=(?<!:|’s)\W) return preg_replace("/(?<=(?<!:|’s)\W)
(A|An|And|At|For|In|Of|On|Or|The|To|With) (A|An|And|At|For|In|Of|On|Or|The|To|With)
(?=\W)/e", 'strtolower("$1")', ucwords(strtolower($str))); (?=\W)/e", 'strtolower("$1")', ucwords(strtolower($str)));
} }
function percent($num_amount, $num_total) { function percent($num_amount, $num_total) {
$count1 = $num_amount / $num_total; $count1 = $num_amount / $num_total;
$count2 = $count1 * 100; $count2 = $count1 * 100;
$count = number_format($count2, 2); $count = number_format($count2, 2);
return $count; return $count;
} }
function array_sum_all($a) { function array_sum_all($a) {
if(!is_array($a)) return $a; if(!is_array($a)) return $a;
foreach($a as $key=>$value) foreach($a as $key=>$value)
$totale += array_sum_all($value); $totale += array_sum_all($value);
return $totale; return $totale;
} }
$agency = mysql_real_escape_string(stripslashes($_REQUEST['agency'])); $agency = mysql_real_escape_string(stripslashes($_REQUEST['agency']));
if ($agency != "") $agencyQ = "agencyName = '" . $agency . "' AND"; if ($agency != "") $agencyQ = "agencyName = '" . $agency . "' AND";
$supplier = mysql_real_escape_string(stripslashes($_REQUEST['supplier'])); $supplier = mysql_real_escape_string(stripslashes($_REQUEST['supplier']));
if ($supplier != "") { if ($supplier != "") {
$supplierParts = explode("-", $supplier); $supplierParts = explode("-", $supplier);
if ($supplierParts[0] > 0) $supplierQ = "supplierABN = '" . $supplierParts[0] . "' AND"; if ($supplierParts[0] > 0) $supplierQ = "supplierABN = '" . $supplierParts[0] . "' AND";
else $supplierQ = "supplierName LIKE '%" . $supplierParts[1] . "%' AND"; else $supplierQ = "supplierName LIKE '%" . $supplierParts[1] . "%' AND";
} }
$year = mysql_real_escape_string(stripslashes($_REQUEST['year'])); $year = mysql_real_escape_string(stripslashes($_REQUEST['year']));
if ($year != "") $yearQ = "agencyName = '" . $agency . "' AND"; if ($year != "") $yearQ = "agencyName = '" . $agency . "' AND";
$start =0.0; $start =0.0;
function include_header($title) { function include_header($title) {
global $start; global $start;
?> ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd"> "http://www.w3.org/TR/html4/strict.dtd">
<html> <html>
<head> <head>
<title>Contract Dashboard - <?=$title?></title> <title>Contract Dashboard - <?=$title?></title>
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.0r4/build/reset-fonts-grids/reset-fonts-grids.css"> <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.0r4/build/reset-fonts-grids/reset-fonts-grids.css">
<link type="text/css" rel="stylesheet" href="style.css"> <link type="text/css" rel="stylesheet" href="style.css">
<script type="text/javascript" src="lib/bsn.AutoSuggest_2.1.3_comp.js" charset="utf-8"></script> <script type="text/javascript" src="lib/bsn.AutoSuggest_2.1.3_comp.js" charset="utf-8"></script>
<link rel="stylesheet" href="autosuggest_inquisitor.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="autosuggest_inquisitor.css" type="text/css" media="screen" charset="utf-8" />
<script type="text/javascript" src="lib/jquery.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() $(document).ready(function()
{ {
//hide the all of the element with class msg_body //hide the all of the element with class msg_body
$(".msg_body").hide(); $(".msg_body").hide();
//toggle the componenet with class msg_body //toggle the componenet with class msg_body
$(".msg_head").click(function() $(".msg_head").click(function()
{ {
$(this).next(".msg_body").slideToggle(600); $(this).next(".msg_body").slideToggle(600);
}); });
}); });
</script> </script>
</head> </head>
<body><div id="doc3" class="yui-t4"> <body><div id="doc3" class="yui-t4">
<div id="hd"> <div id="hd">
<h1> contract dashboard</h1> <h1> contract dashboard</h1>
</div> </div>
<div id="sitenav"> <div id="sitenav">
<a href="displayAgency.php">agencies</a> <a href="displayAgency.php">agencies</a>
<a href="displaySupplier.php">suppliers</a> <a href="displaySupplier.php">suppliers</a>
<a href="displayCategory.php">product/service categories</a> <a href="displayCategory.php">product/service categories</a>
<a href="displayCalendar.php">time periods</a> <a href="displayCalendar.php">time periods</a>
| metrics | | metrics |
<a href="displayProcurementMethod.php">procurement method</a> <a href="displayProcurementMethod.php">procurement method</a>
<a href="displayConfidentialities.php">contractual confidentiality</a> <a href="displayConfidentialities.php">contractual confidentiality</a>
<a href="displayConsultancies.php">consultancies</a> <a href="displayConsultancies.php">consultancies</a>
  <a href="displayAmendments.php">consultancies</a>
<a href="displayMap.php">postcodes</a> <a href="displayMap.php">postcodes</a>
<div id="search"><form method="post" action="search.php" class="asholder"> <div id="search"><form method="post" action="search.php" class="asholder">
<label for="searchKeyword">search</label> <label for="searchKeyword">search</label>
<input type="text" id="searchKeyword" name="searchKeyword" value="" style="width:150px" /> <input type="text" id="searchKeyword" name="searchKeyword" value="" style="width:150px" />
<input type="hidden" id="searchID" name="searchID" value=""/><input type="submit" value="submit" /> <input type="hidden" id="searchID" name="searchID" value=""/><input type="submit" value="submit" />
</form></div> </form></div>
<script type="text/javascript"> <script type="text/javascript">
var options_xml = { var options_xml = {
script: function (input) { return "search_autosuggest.php?input="+input; }, script: function (input) { return "search_autosuggest.php?input="+input; },
varname:"input", varname:"input",
callback: function (obj) { document.getElementById('searchID').value = obj.id; } callback: function (obj) { document.getElementById('searchID').value = obj.id; }
}; };
var as_xml = new bsn.AutoSuggest('searchKeyword', options_xml); var as_xml = new bsn.AutoSuggest('searchKeyword', options_xml);
</script> </script>
</div> </div>
<div id="bd" role="main"> <div id="bd" role="main">
<div id="yui-main"> <div id="yui-main">
<div class="yui-b"><div class="yui-g"> <div class="yui-b"><div class="yui-g">
<? <?php
$start = (float) array_sum(explode(' ',microtime())); $start = (float) array_sum(explode(' ',microtime()));
} }
function include_footer() { function include_footer() {
global $start; global $start;
$end = (float) array_sum(explode(' ',microtime())); $end = (float) array_sum(explode(' ',microtime()));
?> ?>
</div> </div>
</div> </div>
</div> </div>
<div class="yui-b"> <div class="yui-b">
Filter by:<ul> Filter by:<ul>
<li>year <li>year
<ul><li>2008</li> <ul><li>2008</li>
</ul> </ul>
</li> </li>
</ul> <br> </div> </div> </ul> <br> </div> </div>
<? <?php
echo '<div id="ft"><p>'."Processing time: ". sprintf("%.4f", ($end-$start))." seconds".'</p></div>'; echo '<div id="ft"><p>'."Processing time: ". sprintf("%.4f", ($end-$start))." seconds".'</p></div>';
echo '</div> </body> </html>'; echo '</div> </body> </html>';
} ?> }
  ?>
   
<?php <?php
require_once '../jpgraph.php'; require_once '../jpgraph.php';
require_once '../jpgraph_canvas.php'; require_once '../jpgraph_canvas.php';
require_once '../jpgraph_canvtools.php'; require_once '../jpgraph_canvtools.php';
/* /*
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
   
/** /**
* Description of test_findpolygon * Description of test_findpolygon
* *
* @author ljp * @author ljp
*/ */
class Findpolygon { class Findpolygon {
private $nbrContours=-1; private $nbrContours=-1;
public $contourCoord=array(); public $contourCoord=array();
private $scale = array(0,6,0,8); private $scale = array(0,6,0,8);
   
function flattenEdges($p) { function flattenEdges($p) {
$fp=array(); $fp=array();
for ($i = 0 ; $i < count($p) ; $i++) { for ($i = 0 ; $i < count($p) ; $i++) {
$fp[] = $p[$i][0]; $fp[] = $p[$i][0];
$fp[] = $p[$i][1]; $fp[] = $p[$i][1];
} }
return $fp; return $fp;
} }
   
function SetupTestData() { function SetupTestData() {
// for($i=0; $i<count($this->contourCoord[0]); ++$i) { // for($i=0; $i<count($this->contourCoord[0]); ++$i) {
// echo '('.$this->contourCoord[0][$i][0][0].','.$this->contourCoord[0][$i][0][1].') -> '. // echo '('.$this->contourCoord[0][$i][0][0].','.$this->contourCoord[0][$i][0][1].') -> '.
// '('.$this->contourCoord[0][$i][1][0].','.$this->contourCoord[0][$i][1][1].")\n"; // '('.$this->contourCoord[0][$i][1][0].','.$this->contourCoord[0][$i][1][1].")\n";
// } // }
// //
   
$c=0; $c=0;
$p[$c] = array(0.6,1, 1,0.5, 2,0.5, 3,0.5, 3.5,1, 3.5,2, 3,2.5, 2,2.5, 1,2.5, 0.5,2, 0.6,1); $p[$c] = array(0.6,1, 1,0.5, 2,0.5, 3,0.5, 3.5,1, 3.5,2, 3,2.5, 2,2.5, 1,2.5, 0.5,2, 0.6,1);
$c++; $c++;
$p[$c] = array(6,0.5, 5.5,1, 5.5,2, 6,2.5); $p[$c] = array(6,0.5, 5.5,1, 5.5,2, 6,2.5);
   
$this->nbrContours = $c+1; $this->nbrContours = $c+1;
   
for ($c = 0 ; $c < count($p) ; $c++) { for ($c = 0 ; $c < count($p) ; $c++) {
$n=count($p[$c]); $n=count($p[$c]);
   
$this->contourCoord[$c][0] = array(array($p[$c][0],$p[$c][1]),array($p[$c][2],$p[$c][3])); $this->contourCoord[$c][0] = array(array($p[$c][0],$p[$c][1]),array($p[$c][2],$p[$c][3]));
$k=1; $k=1;
for ($i = 0; $i < ($n-4)/2; $i++, $k++) { for ($i = 0; $i < ($n-4)/2; $i++, $k++) {
$this->contourCoord[$c][$k] = array($this->contourCoord[$c][$k-1][1], array($p[$c][2*$k+2],$p[$c][2*$k+1+2])); $this->contourCoord[$c][$k] = array($this->contourCoord[$c][$k-1][1], array($p[$c][2*$k+2],$p[$c][2*$k+1+2]));
} }
   
// Swap edges order at random // Swap edges order at random
$n = count($this->contourCoord[$c]); $n = count($this->contourCoord[$c]);
for($i=0; $i < floor($n/2); ++$i) { for($i=0; $i < floor($n/2); ++$i) {
$swap1 = rand(0,$n-1); $swap1 = rand(0,$n-1);
$t = $this->contourCoord[$c][$swap1]; $t = $this->contourCoord[$c][$swap1];
while( $swap1 == ($swap2 = rand(0,$n-1)) ) while( $swap1 == ($swap2 = rand(0,$n-1)) )
; ;
$this->contourCoord[$c][$swap1] = $this->contourCoord[$c][$swap2]; $this->contourCoord[$c][$swap1] = $this->contourCoord[$c][$swap2];
$this->contourCoord[$c][$swap2] = $t; $this->contourCoord[$c][$swap2] = $t;
} }
   
// Swap vector direction on 1/3 of the edges // Swap vector direction on 1/3 of the edges
for ($i = 0 ; $i < floor(count($this->contourCoord[$c])/3) ; $i++) { for ($i = 0 ; $i < floor(count($this->contourCoord[$c])/3) ; $i++) {
$e = rand(0, count($this->contourCoord[$c])-1); $e = rand(0, count($this->contourCoord[$c])-1);
$edge = $this->contourCoord[$c][$e]; $edge = $this->contourCoord[$c][$e];
$v1 = $edge[0]; $v2 = $edge[1]; $v1 = $edge[0]; $v2 = $edge[1];
$this->contourCoord[$c][$e][0] = $v2; $this->contourCoord[$c][$e][0] = $v2;
$this->contourCoord[$c][$e][1] = $v1; $this->contourCoord[$c][$e][1] = $v1;
} }
} }
   
$pp = array(); $pp = array();
for($j=0; $j < count($p); ++$j ) { for($j=0; $j < count($p); ++$j ) {
for( $i=0; $i < count($p[$j])/2; ++$i ) { for( $i=0; $i < count($p[$j])/2; ++$i ) {
$pp[$j][$i] = array($p[$j][2*$i],$p[$j][2*$i+1]); $pp[$j][$i] = array($p[$j][2*$i],$p[$j][2*$i+1]);
} }
} }
return $pp; return $pp;
} }
   
function p_edges($v) { function p_edges($v) {
for ($i = 0 ; $i < count($v) ; $i++) { for ($i = 0 ; $i < count($v) ; $i++) {
echo "(".$v[$i][0][0].",".$v[$i][0][1].") -> (".$v[$i][1][0].",".$v[$i][1][1].")\n"; echo "(".$v[$i][0][0].",".$v[$i][0][1].") -> (".$v[$i][1][0].",".$v[$i][1][1].")\n";
} }
echo "\n"; echo "\n";
} }
   
function CompareCyclic($a,$b,$forward=true) { function CompareCyclic($a,$b,$forward=true) {
   
// We assume disjoint vertices and if last==first this just means // We assume disjoint vertices and if last==first this just means
// that the polygon is closed. For this comparison it must be unique // that the polygon is closed. For this comparison it must be unique
// elements // elements
if( $a[count($a)-1] == $a[0] ) { if( $a[count($a)-1] == $a[0] ) {
array_pop($a); array_pop($a);
} }
if( $b[count($b)-1] == $b[0] ) { if( $b[count($b)-1] == $b[0] ) {
array_pop($b); array_pop($b);
} }
   
$n1 = count($a); $n2 = count($b); $n1 = count($a); $n2 = count($b);
if( $n1 != $n2 ) if( $n1 != $n2 )
return false; return false;
   
$i=0; $i=0;
while( ($i < $n2) && ($a[0] != $b[$i]) ) while( ($i < $n2) && ($a[0] != $b[$i]) )
++$i; ++$i;
   
if( $i >= $n2 ) if( $i >= $n2 )
return false; return false;
   
$j=0; $j=0;
if( $forward ) { if( $forward ) {
while( ($j < $n1) && ($a[$j] == $b[$i]) ) { while( ($j < $n1) && ($a[$j] == $b[$i]) ) {
$i = ($i + 1) % $n2; $i = ($i + 1) % $n2;
++$j; ++$j;
} }
} }
else { else {
while( ($j < $n1) && ($a[$j] == $b[$i]) ) { while( ($j < $n1) && ($a[$j] == $b[$i]) ) {
--$i; --$i;
if( $i < 0 ) { if( $i < 0 ) {
$i = $n2-1; $i = $n2-1;
} }
++$j; ++$j;
} }
} }
return $j >= $n1; return $j >= $n1;
} }
   
function dbg($s) { function dbg($s) {
// echo $s."\n"; // echo $s."\n";
} }
   
function IsVerticeOnBorder($x1,$y1) { function IsVerticeOnBorder($x1,$y1) {
// Check if the vertice lies on any of the four border // Check if the vertice lies on any of the four border
if( $x1==$this->scale[0] || $x1==$this->scale[1] ) { if( $x1==$this->scale[0] || $x1==$this->scale[1] ) {
return true; return true;
} }
if( $y1==$this->scale[2] || $y1==$this->scale[3] ) { if( $y1==$this->scale[2] || $y1==$this->scale[3] ) {
return true; return true;
} }
return false; return false;
} }
   
function FindPolygons($debug=false) { function FindPolygons($debug=false) {
   
$pol = 0; $pol = 0;
for ($c = 0; $c < $this->nbrContours; $c++) { for ($c = 0; $c < $this->nbrContours; $c++) {
   
$this->dbg("\n** Searching polygon chain $c ... "); $this->dbg("\n** Searching polygon chain $c ... ");
$this->dbg("------------------------------------------\n"); $this->dbg("------------------------------------------\n");
   
$edges = $this->contourCoord[$c]; $edges = $this->contourCoord[$c];
while( count($edges) > 0 ) { while( count($edges) > 0 ) {
   
$edge = array_shift($edges); $edge = array_shift($edges);
list($x1,$y1) = $edge[0]; list($x1,$y1) = $edge[0];
list($x2,$y2) = $edge[1]; list($x2,$y2) = $edge[1];
$polygons[$pol]=array( $polygons[$pol]=array(
array($x1,$y1),array($x2,$y2) array($x1,$y1),array($x2,$y2)
); );
   
$this->dbg("Searching on second vertice."); $this->dbg("Searching on second vertice.");
   
$found=false; $found=false;
if( ! $this->IsVerticeOnBorder($x2,$y2) ) { if( ! $this->IsVerticeOnBorder($x2,$y2) ) {
do { do {
   
$this->dbg(" --Searching on edge: ($x1,$y1)->($x2,$y2)"); $this->dbg(" --Searching on edge: ($x1,$y1)->($x2,$y2)");
   
$found=false; $found=false;
$nn = count($edges); $nn = count($edges);
for( $i=0; $i < $nn && !$found; ++$i ) { for( $i=0; $i < $nn && !$found; ++$i ) {
$edge = $edges[$i]; $edge = $edges[$i];
if( $found = ($x2==$edge[0][0] && $y2==$edge[0][1]) ) { if( $found = ($x2==$edge[0][0] && $y2==$edge[0][1]) ) {
$polygons[$pol][] = array($edge[1][0],$edge[1][1]); $polygons[$pol][] = array($edge[1][0],$edge[1][1]);
$x1 = $x2; $y1 = $y2; $x1 = $x2; $y1 = $y2;
$x2 = $edge[1][0]; $y2 = $edge[1][1]; $x2 = $edge[1][0]; $y2 = $edge[1][1];
} }
elseif( $found = ($x2==$edge[1][0] && $y2==$edge[1][1]) ) { elseif( $found = ($x2==$edge[1][0] && $y2==$edge[1][1]) ) {
$polygons[$pol][] = array($edge[0][0],$edge[0][1]); $polygons[$pol][] = array($edge[0][0],$edge[0][1]);
$x1 = $x2; $y1 = $y2; $x1 = $x2; $y1 = $y2;
$x2 = $edge[0][0]; $y2 = $edge[0][1]; $x2 = $edge[0][0]; $y2 = $edge[0][1];
} }
if( $found ) { if( $found ) {
$this->dbg(" --Found next edge: [i=$i], (%,%) -> ($x2,$y2)"); $this->dbg(" --Found next edge: [i=$i], (%,%) -> ($x2,$y2)");
unset($edges[$i]); unset($edges[$i]);
$edges = array_values($edges); $edges = array_values($edges);
} }
} }
   
} while( $found ); } while( $found );
} }
   
if( !$found && count($edges)>0 ) { if( !$found && count($edges)>0 ) {
$this->dbg("Searching on first vertice."); $this->dbg("Searching on first vertice.");
list($x1,$y1) = $polygons[$pol][0]; list($x1,$y1) = $polygons[$pol][0];
list($x2,$y2) = $polygons[$pol][1]; list($x2,$y2) = $polygons[$pol][1];
   
if( ! $this->IsVerticeOnBorder($x1,$y1) ) { if( ! $this->IsVerticeOnBorder($x1,$y1) ) {
do { do {
   
$this->dbg(" --Searching on edge: ($x1,$y1)->($x2,$y2)"); $this->dbg(" --Searching on edge: ($x1,$y1)->($x2,$y2)");
   
$found=false; $found=false;
$nn = count($edges); $nn = count($edges);
for( $i=0; $i < $nn && !$found; ++$i ) { for( $i=0; $i < $nn && !$found; ++$i ) {
$edge = $edges[$i]; $edge = $edges[$i];
if( $found = ($x1==$edge[0][0] && $y1==$edge[0][1]) ) { if( $found = ($x1==$edge[0][0] && $y1==$edge[0][1]) ) {
array_unshift($polygons[$pol],array($edge[1][0],$edge[1][1])); array_unshift($polygons[$pol],array($edge[1][0],$edge[1][1]));
$x2 = $x1; $y2 = $y1; $x2 = $x1; $y2 = $y1;
$x1 = $edge[1][0]; $y1 = $edge[1][1]; $x1 = $edge[1][0]; $y1 = $edge[1][1];
} }
elseif( $found = ($x1==$edge[1][0] && $y1==$edge[1][1]) ) { elseif( $found = ($x1==$edge[1][0] && $y1==$edge[1][1]) ) {
array_unshift($polygons[$pol],array($edge[0][0],$edge[0][1])); array_unshift($polygons[$pol],array($edge[0][0],$edge[0][1]));
$x2 = $x1; $y2 = $y1; $x2 = $x1; $y2 = $y1;
$x1 = $edge[0][0]; $y1 = $edge[0][1]; $x1 = $edge[0][0]; $y1 = $edge[0][1];
} }
if( $found ) { if( $found ) {
$this->dbg(" --Found next edge: [i=$i], ($x1,$y1) -> (%,%)"); $this->dbg(" --Found next edge: [i=$i], ($x1,$y1) -> (%,%)");
unset($edges[$i]); unset($edges[$i]);
$edges = array_values($edges); $edges = array_values($edges);
} }
} }
   
} while( $found ); } while( $found );
} }
   
} }
   
$pol++; $pol++;
} }
} }
   
return $polygons; return $polygons;
} }
   
} }
define('HORIZ_EDGE',0); define('HORIZ_EDGE',0);
define('VERT_EDGE',1); define('VERT_EDGE',1);
   
class FillGridRect { class FillGridRect {
private $edges,$dataPoints,$colors,$isoBars; private $edges,$dataPoints,$colors,$isoBars;
private $invert=false; private $invert=false;
   
function __construct(&$edges,&$dataPoints,$isoBars,$colors) { function __construct(&$edges,&$dataPoints,$isoBars,$colors) {
$this->edges = $edges; $this->edges = $edges;
$this->dataPoints = $dataPoints; $this->dataPoints = $dataPoints;
$this->colors = $colors; $this->colors = $colors;
$this->isoBars = $isoBars; $this->isoBars = $isoBars;
} }
   
function GetIsobarColor($val) { function GetIsobarColor($val) {
for ($i = 0 ; $i < count($this->isoBars) ; $i++) { for ($i = 0 ; $i < count($this->isoBars) ; $i++) {
if( $val <= $this->isoBars[$i] ) { if( $val <= $this->isoBars[$i] ) {
return $this->colors[$i]; return $this->colors[$i];
} }
} }
return $this->colors[$i]; // The color for all values above the highest isobar return $this->colors[$i]; // The color for all values above the highest isobar
} }
   
function GetIsobarVal($a,$b) { function GetIsobarVal($a,$b) {
// Get the isobar that is between the values a and b // Get the isobar that is between the values a and b
// If there are more isobars then return the one with lowest index // If there are more isobars then return the one with lowest index
if( $b < $a ) { if( $b < $a ) {
$t=$a; $a=$b; $b=$t; $t=$a; $a=$b; $b=$t;
} }
$i = 0 ; $i = 0 ;
$n = count($this->isoBars); $n = count($this->isoBars);
while( $i < $n && $this->isoBars[$i] < $a ) { while( $i < $n && $this->isoBars[$i] < $a ) {
++$i; ++$i;
} }
if( $i >= $n ) if( $i >= $n )
die("Internal error. Cannot find isobar values for ($a,$b)"); die("Internal error. Cannot find isobar values for ($a,$b)");
return $this->isoBars[$i]; return $this->isoBars[$i];
} }
   
function getCrossingCoord($aRow,$aCol,$aEdgeDir,$aIsobarVal) { function getCrossingCoord($aRow,$aCol,$aEdgeDir,$aIsobarVal) {
// In order to avoid numerical problem when two vertices are very close // In order to avoid numerical problem when two vertices are very close
// we have to check and avoid dividing by close to zero denumerator. // we have to check and avoid dividing by close to zero denumerator.
if( $aEdgeDir == HORIZ_EDGE ) { if( $aEdgeDir == HORIZ_EDGE ) {
$d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow][$aCol+1]); $d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow][$aCol+1]);
if( $d > 0.001 ) { if( $d > 0.001 ) {
$xcoord = $aCol + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d; $xcoord = $aCol + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d;
} }
else { else {
$xcoord = $aCol; $xcoord = $aCol;
} }
$ycoord = $aRow; $ycoord = $aRow;
} }
else { else {
$d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow+1][$aCol]); $d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow+1][$aCol]);
if( $d > 0.001 ) { if( $d > 0.001 ) {
$ycoord = $aRow + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d; $ycoord = $aRow + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d;
} }
else { else {
$ycoord = $aRow; $ycoord = $aRow;
} }
$xcoord = $aCol; $xcoord = $aCol;
} }
if( $this->invert ) { if( $this->invert ) {
$ycoord = $this->nbrRows-1 - $ycoord; $ycoord = $this->nbrRows-1 - $ycoord;
} }
return array($xcoord,$ycoord); return array($xcoord,$ycoord);
} }
   
function Fill(ContCanvas $canvas) { function Fill(ContCanvas $canvas) {
   
$nx_vertices = count($this->dataPoints[0]); $nx_vertices = count($this->dataPoints[0]);
$ny_vertices = count($this->dataPoints); $ny_vertices = count($this->dataPoints);
   
// Loop through all squares in the grid // Loop through all squares in the grid
for($col=0; $col < $nx_vertices-1; ++$col) { for($col=0; $col < $nx_vertices-1; ++$col) {
for($row=0; $row < $ny_vertices-1; ++$row) { for($row=0; $row < $ny_vertices-1; ++$row) {
   
$n = 0;$quad_edges=array(); $n = 0;$quad_edges=array();
if ( $this->edges[VERT_EDGE][$row][$col] ) $quad_edges[$n++] = array($row, $col, VERT_EDGE); if ( $this->edges[VERT_EDGE][$row][$col] ) $quad_edges[$n++] = array($row, $col, VERT_EDGE);
if ( $this->edges[VERT_EDGE][$row][$col+1] ) $quad_edges[$n++] = array($row, $col+1,VERT_EDGE); if ( $this->edges[VERT_EDGE][$row][$col+1] ) $quad_edges[$n++] = array($row, $col+1,VERT_EDGE);
if ( $this->edges[HORIZ_EDGE][$row][$col] ) $quad_edges[$n++] = array($row, $col, HORIZ_EDGE); if ( $this->edges[HORIZ_EDGE][$row][$col] ) $quad_edges[$n++] = array($row, $col, HORIZ_EDGE);
if ( $this->edges[HORIZ_EDGE][$row+1][$col] ) $quad_edges[$n++] = array($row+1,$col, HORIZ_EDGE); if ( $this->edges[HORIZ_EDGE][$row+1][$col] ) $quad_edges[$n++] = array($row+1,$col, HORIZ_EDGE);
   
if( $n == 0 ) { if( $n == 0 ) {
// Easy, fill the entire quadrant with one color since we have no crossings // Easy, fill the entire quadrant with one color since we have no crossings
// Select the top left datapoint as representing this quadrant // Select the top left datapoint as representing this quadrant
// color for this quadrant // color for this quadrant
$color = $this->GetIsobarColor($this->dataPoints[$row][$col]); $color = $this->GetIsobarColor($this->dataPoints[$row][$col]);
$polygon = array($col,$row,$col,$row+1,$col+1,$row+1,$col+1,$row,$col,$row); $polygon = array($col,$row,$col,$row+1,$col+1,$row+1,$col+1,$row,$col,$row);
$canvas->FilledPolygon($polygon,$color); $canvas->FilledPolygon($polygon,$color);
   
} elseif( $n==2 ) { } elseif( $n==2 ) {
   
// There is one isobar edge crossing this quadrant. In order to fill we need to // There is one isobar edge crossing this quadrant. In order to fill we need to
// find out the orientation of the two areas this edge is separating in order to // find out the orientation of the two areas this edge is separating in order to
// construct the two polygons that define the two areas to be filled // construct the two polygons that define the two areas to be filled
// There are six possible variants // There are six possible variants
// 0) North-South // 0) North-South
// 1) West-East // 1) West-East
// 2) West-North // 2) West-North
// 3) East-North // 3) East-North
// 4) West-South // 4) West-South
// 5) East-South // 5) East-South
$type=-1; $type=-1;
if( $this->edges[HORIZ_EDGE][$row][$col] ) { if( $this->edges[HORIZ_EDGE][$row][$col] ) {
if( $this->edges[HORIZ_EDGE][$row+1][$col] ) $type=0; // North-South if( $this->edges[HORIZ_EDGE][$row+1][$col] ) $type=0; // North-South
elseif( $this->edges[VERT_EDGE][$row][$col] ) $type=2; elseif( $this->edges[VERT_EDGE][$row][$col] ) $type=2;
elseif( $this->edges[VERT_EDGE][$row][$col+1] ) $type=3; elseif( $this->edges[VERT_EDGE][$row][$col+1] ) $type=3;
} }
elseif( $this->edges[HORIZ_EDGE][$row+1][$col] ) { elseif( $this->edges[HORIZ_EDGE][$row+1][$col] ) {
if( $this->edges[VERT_EDGE][$row][$col] ) $type=4; if( $this->edges[VERT_EDGE][$row][$col] ) $type=4;
elseif( $this->edges[VERT_EDGE][$row][$col+1] ) $type=5; elseif( $this->edges[VERT_EDGE][$row][$col+1] ) $type=5;
} }
else { else {
$type=1; $type=1;
} }
if( $type==-1 ) { if( $type==-1 ) {
die('Internal error: n=2 but no edges in the quadrant was find to determine type.'); die('Internal error: n=2 but no edges in the quadrant was find to determine type.');
} }
   
switch( $type ) { switch( $type ) {
case 0: //North-South case 0: //North-South
   
// North vertice // North vertice
$v1 = $this->dataPoints[$row][$col]; $v1 = $this->dataPoints[$row][$col];
$v2 = $this->dataPoints[$row][$col+1]; $v2 = $this->dataPoints[$row][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x1,$y1) = $this->getCrossingCoord($row, $col,HORIZ_EDGE, $isobarValue); list($x1,$y1) = $this->getCrossingCoord($row, $col,HORIZ_EDGE, $isobarValue);
   
// South vertice // South vertice
$v1 = $this->dataPoints[$row+1][$col]; $v1 = $this->dataPoints[$row+1][$col];
$v2 = $this->dataPoints[$row+1][$col+1]; $v2 = $this->dataPoints[$row+1][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x2,$y2) = $this->getCrossingCoord($row+1, $col,HORIZ_EDGE, $isobarValue); list($x2,$y2) = $this->getCrossingCoord($row+1, $col,HORIZ_EDGE, $isobarValue);
   
$polygon = array($col,$row,$x1,$y1,$x2,$y2,$col,$row+1,$col,$row); $polygon = array($col,$row,$x1,$y1,$x2,$y2,$col,$row+1,$col,$row);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1));
   
$polygon = array($col+1,$row,$x1,$y1,$x2,$y2,$col+1,$row+1,$col+1,$row); $polygon = array($col+1,$row,$x1,$y1,$x2,$y2,$col+1,$row+1,$col+1,$row);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2));
   
break; break;
   
case 1: // West-East case 1: // West-East
   
// West vertice // West vertice
$v1 = $this->dataPoints[$row][$col]; $v1 = $this->dataPoints[$row][$col];
$v2 = $this->dataPoints[$row+1][$col]; $v2 = $this->dataPoints[$row+1][$col];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x1,$y1) = $this->getCrossingCoord($row, $col,VERT_EDGE, $isobarValue); list($x1,$y1) = $this->getCrossingCoord($row, $col,VERT_EDGE, $isobarValue);
   
// East vertice // East vertice
$v1 = $this->dataPoints[$row][$col+1]; $v1 = $this->dataPoints[$row][$col+1];
$v2 = $this->dataPoints[$row+1][$col+1]; $v2 = $this->dataPoints[$row+1][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x2,$y2) = $this->getCrossingCoord($row, $col+1,VERT_EDGE, $isobarValue); list($x2,$y2) = $this->getCrossingCoord($row, $col+1,VERT_EDGE, $isobarValue);
   
$polygon = array($col,$row,$x1,$y1,$x2,$y2,$col+1,$row,$col,$row); $polygon = array($col,$row,$x1,$y1,$x2,$y2,$col+1,$row,$col,$row);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1));
   
$polygon = array($col,$row+1,$x1,$y1,$x2,$y2,$col+1,$row+1,$col,$row+1); $polygon = array($col,$row+1,$x1,$y1,$x2,$y2,$col+1,$row+1,$col,$row+1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2));
break; break;
   
case 2: // West-North case 2: // West-North
   
// West vertice // West vertice
$v1 = $this->dataPoints[$row][$col]; $v1 = $this->dataPoints[$row][$col];
$v2 = $this->dataPoints[$row+1][$col]; $v2 = $this->dataPoints[$row+1][$col];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x1,$y1) = $this->getCrossingCoord($row, $col,VERT_EDGE, $isobarValue); list($x1,$y1) = $this->getCrossingCoord($row, $col,VERT_EDGE, $isobarValue);
   
// North vertice // North vertice
$v1 = $this->dataPoints[$row][$col]; $v1 = $this->dataPoints[$row][$col];
$v2 = $this->dataPoints[$row][$col+1]; $v2 = $this->dataPoints[$row][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x2,$y2) = $this->getCrossingCoord($row, $col,HORIZ_EDGE, $isobarValue); list($x2,$y2) = $this->getCrossingCoord($row, $col,HORIZ_EDGE, $isobarValue);
   
$polygon = array($col,$row,$x1,$y1,$x2,$y2,$col,$row); $polygon = array($col,$row,$x1,$y1,$x2,$y2,$col,$row);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1));
   
$polygon = array($x1,$y1,$x2,$y2,$col+1,$row,$col+1,$row+1,$col,$row+1,$x1,$y1); $polygon = array($x1,$y1,$x2,$y2,$col+1,$row,$col+1,$row+1,$col,$row+1,$x1,$y1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2));
   
break; break;
   
case 3: // East-North case 3: // East-North
   
// if( $row==3 && $col==1 && $n==2 ) { // if( $row==3 && $col==1 && $n==2 ) {
// echo " ** East-North<br>"; // echo " ** East-North<br>";
// } // }
   
   
// East vertice // East vertice
$v1 = $this->dataPoints[$row][$col+1]; $v1 = $this->dataPoints[$row][$col+1];
$v2 = $this->dataPoints[$row+1][$col+1]; $v2 = $this->dataPoints[$row+1][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x1,$y1) = $this->getCrossingCoord($row, $col+1,VERT_EDGE, $isobarValue); list($x1,$y1) = $this->getCrossingCoord($row, $col+1,VERT_EDGE, $isobarValue);
// //
// if( $row==3 && $col==1 && $n==2 ) { // if( $row==3 && $col==1 && $n==2 ) {
// echo " ** E_val($v1,$v2), isobar=$isobarValue<br>"; // echo " ** E_val($v1,$v2), isobar=$isobarValue<br>";
// echo " ** E($x1,$y1)<br>"; // echo " ** E($x1,$y1)<br>";
// } // }
   
   
// North vertice // North vertice
$v1 = $this->dataPoints[$row][$col]; $v1 = $this->dataPoints[$row][$col];
$v2 = $this->dataPoints[$row][$col+1]; $v2 = $this->dataPoints[$row][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x2,$y2) = $this->getCrossingCoord($row, $col,HORIZ_EDGE, $isobarValue); list($x2,$y2) = $this->getCrossingCoord($row, $col,HORIZ_EDGE, $isobarValue);
   
// if( $row==3 && $col==1 && $n==2 ) { // if( $row==3 && $col==1 && $n==2 ) {
// echo " ** N_val($v1,$v2), isobar=$isobarValue<br>"; // echo " ** N_val($v1,$v2), isobar=$isobarValue<br>";
// echo " ** N($x2,$y2)<br>"; // echo " ** N($x2,$y2)<br>";
// } // }
// if( $row==3 && $col==1 && $n==2 ) // if( $row==3 && $col==1 && $n==2 )
// $canvas->Line($x1,$y1,$x2,$y2,'blue'); // $canvas->Line($x1,$y1,$x2,$y2,'blue');
   
$polygon = array($x1,$y1,$x2,$y2,$col+1,$row,$x1,$y1); $polygon = array($x1,$y1,$x2,$y2,$col+1,$row,$x1,$y1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2));
   
$polygon = array($col,$row,$x2,$y2,$x1,$y1,$col+1,$row+1,$col,$row+1,$col,$row); $polygon = array($col,$row,$x2,$y2,$x1,$y1,$col+1,$row+1,$col,$row+1,$col,$row);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1));
   
break; break;
   
case 4: // West-South case 4: // West-South
   
// West vertice // West vertice
$v1 = $this->dataPoints[$row][$col]; $v1 = $this->dataPoints[$row][$col];
$v2 = $this->dataPoints[$row+1][$col]; $v2 = $this->dataPoints[$row+1][$col];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x1,$y1) = $this->getCrossingCoord($row, $col,VERT_EDGE, $isobarValue); list($x1,$y1) = $this->getCrossingCoord($row, $col,VERT_EDGE, $isobarValue);
   
// South vertice // South vertice
$v1 = $this->dataPoints[$row+1][$col]; $v1 = $this->dataPoints[$row+1][$col];
$v2 = $this->dataPoints[$row+1][$col+1]; $v2 = $this->dataPoints[$row+1][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x2,$y2) = $this->getCrossingCoord($row+1, $col,HORIZ_EDGE, $isobarValue); list($x2,$y2) = $this->getCrossingCoord($row+1, $col,HORIZ_EDGE, $isobarValue);
   
$polygon = array($col,$row+1,$x1,$y1,$x2,$y2,$col,$row+1); $polygon = array($col,$row+1,$x1,$y1,$x2,$y2,$col,$row+1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1));
   
$polygon = array($x1,$y1,$x2,$y2,$col+1,$row+1,$col+1,$row,$col,$row,$x1,$y1); $polygon = array($x1,$y1,$x2,$y2,$col+1,$row+1,$col+1,$row,$col,$row,$x1,$y1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2));
   
break; break;
   
case 5: // East-South case 5: // East-South
   
// //
// if( $row==1 && $col==1 && $n==2 ) { // if( $row==1 && $col==1 && $n==2 ) {
// echo " ** Sout-East<br>"; // echo " ** Sout-East<br>";
// } // }
   
// East vertice // East vertice
$v1 = $this->dataPoints[$row][$col+1]; $v1 = $this->dataPoints[$row][$col+1];
$v2 = $this->dataPoints[$row+1][$col+1]; $v2 = $this->dataPoints[$row+1][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x1,$y1) = $this->getCrossingCoord($row, $col+1,VERT_EDGE, $isobarValue); list($x1,$y1) = $this->getCrossingCoord($row, $col+1,VERT_EDGE, $isobarValue);
   
// if( $row==1 && $col==1 && $n==2 ) { // if( $row==1 && $col==1 && $n==2 ) {
// echo " ** E_val($v1,$v2), isobar=$isobarValue<br>"; // echo " ** E_val($v1,$v2), isobar=$isobarValue<br>";
// echo " ** E($x1,$y1)<br>"; // echo " ** E($x1,$y1)<br>";
// } // }
   
// South vertice // South vertice
$v1 = $this->dataPoints[$row+1][$col]; $v1 = $this->dataPoints[$row+1][$col];
$v2 = $this->dataPoints[$row+1][$col+1]; $v2 = $this->dataPoints[$row+1][$col+1];
$isobarValue = $this->GetIsobarVal($v1, $v2); $isobarValue = $this->GetIsobarVal($v1, $v2);
list($x2,$y2) = $this->getCrossingCoord($row+1, $col,HORIZ_EDGE, $isobarValue); list($x2,$y2) = $this->getCrossingCoord($row+1, $col,HORIZ_EDGE, $isobarValue);
   
// if( $row==1 && $col==1 && $n==2 ) { // if( $row==1 && $col==1 && $n==2 ) {
// echo " ** S_val($v1,$v2), isobar=$isobarValue<br>"; // echo " ** S_val($v1,$v2), isobar=$isobarValue<br>";
// echo " ** S($x2,$y2)<br>"; // echo " ** S($x2,$y2)<br>";
// } // }
   
$polygon = array($col+1,$row+1,$x1,$y1,$x2,$y2,$col+1,$row+1); $polygon = array($col+1,$row+1,$x1,$y1,$x2,$y2,$col+1,$row+1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v2));
   
$polygon = array($x1,$y1,$x2,$y2,$col,$row+1,$col,$row,$col+1,$row,$x1,$y1); $polygon = array($x1,$y1,$x2,$y2,$col,$row+1,$col,$row,$col+1,$row,$x1,$y1);
$canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1)); $canvas->FilledPolygon($polygon,$this->GetIsobarColor($v1));
   
break; break;
   
} }
   
} }
   
} }
} }
   
} }
} }
   
   
class ContCanvas { class ContCanvas {
public $g; public $g;
public $shape,$scale; public $shape,$scale;
function __construct($xmax=6,$ymax=6,$width=400,$height=400) { function __construct($xmax=6,$ymax=6,$width=400,$height=400) {
   
$this->g = new CanvasGraph($width,$height); $this->g = new CanvasGraph($width,$height);
$this->scale = new CanvasScale($this->g, 0, $xmax, 0, $ymax); $this->scale = new CanvasScale($this->g, 0, $xmax, 0, $ymax);
$this->shape = new Shape($this->g, $this->scale); $this->shape = new Shape($this->g, $this->scale);
   
//$this->g->SetFrame(true); //$this->g->SetFrame(true);
$this->g->SetMargin(5,5,5,5); $this->g->SetMargin(5,5,5,5);
$this->g->SetMarginColor('white@1'); $this->g->SetMarginColor('white@1');
$this->g->InitFrame(); $this->g->InitFrame();
   
   
$this->shape->SetColor('gray'); $this->shape->SetColor('gray');
for( $col=1; $col<$xmax; ++$col ) { for( $col=1; $col<$xmax; ++$col ) {
$this->shape->Line($col, 0, $col, $ymax); $this->shape->Line($col, 0, $col, $ymax);
} }
for( $row=1; $row<$ymax; ++$row ) { for( $row=1; $row<$ymax; ++$row ) {
$this->shape->Line(0, $row, $xmax, $row); $this->shape->Line(0, $row, $xmax, $row);
} }
} }
   
function SetDatapoints($datapoints) { function SetDatapoints($datapoints) {
$ny=count($datapoints); $ny=count($datapoints);
$nx=count($datapoints[0]); $nx=count($datapoints[0]);
$t = new Text(); $t = new Text();
$t->SetFont(FF_ARIAL,FS_NORMAL,8); $t->SetFont(FF_ARIAL,FS_NORMAL,8);
for( $x=0; $x < $nx; ++$x ) { for( $x=0; $x < $nx; ++$x ) {
for( $y=0; $y < $ny; ++$y ) { for( $y=0; $y < $ny; ++$y ) {
list($x1,$y1) = $this->scale->Translate($x,$y); list($x1,$y1) = $this->scale->Translate($x,$y);
   
if( $datapoints[$y][$x] > 0 ) if( $datapoints[$y][$x] > 0 )
$t->SetColor('blue'); $t->SetColor('blue');
else else
$t->SetColor('black'); $t->SetColor('black');
$t->SetFont(FF_ARIAL,FS_BOLD,8); $t->SetFont(FF_ARIAL,FS_BOLD,8);
$t->Set($datapoints[$y][$x]); $t->Set($datapoints[$y][$x]);
$t->Stroke($this->g->img,$x1,$y1); $t->Stroke($this->g->img,$x1,$y1);
   
$t->SetColor('gray'); $t->SetColor('gray');
$t->SetFont(FF_ARIAL,FS_NORMAL,8); $t->SetFont(FF_ARIAL,FS_NORMAL,8);
$t->Set("($y,$x)"); $t->Set("($y,$x)");
$t->Stroke($this->g->img,$x1+10,$y1); $t->Stroke($this->g->img,$x1+10,$y1);
   
} }
} }
} }
   
function DrawLinePolygons($p,$color='red') { function DrawLinePolygons($p,$color='red') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
for ($i = 0 ; $i < count($p) ; $i++) { for ($i = 0 ; $i < count($p) ; $i++) {
$x1 = $p[$i][0][0]; $y1 = $p[$i][0][1]; $x1 = $p[$i][0][0]; $y1 = $p[$i][0][1];
for ($j = 1 ; $j < count($p[$i]) ; $j++) { for ($j = 1 ; $j < count($p[$i]) ; $j++) {
$x2=$p[$i][$j][0]; $y2 = $p[$i][$j][1]; $x2=$p[$i][$j][0]; $y2 = $p[$i][$j][1];
$this->shape->Line($x1, $y1, $x2, $y2); $this->shape->Line($x1, $y1, $x2, $y2);
$x1=$x2; $y1=$y2; $x1=$x2; $y1=$y2;
} }
} }
} }
   
function Line($x1,$y1,$x2,$y2,$color='red') { function Line($x1,$y1,$x2,$y2,$color='red') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->Line($x1, $y1, $x2, $y2); $this->shape->Line($x1, $y1, $x2, $y2);
} }
function Polygon($p,$color='blue') { function Polygon($p,$color='blue') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->Polygon($p); $this->shape->Polygon($p);
} }
   
function FilledPolygon($p,$color='lightblue') { function FilledPolygon($p,$color='lightblue') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->FilledPolygon($p); $this->shape->FilledPolygon($p);
} }
   
function Point($x,$y,$color) { function Point($x,$y,$color) {
list($x1,$y1) = $this->scale->Translate($x, $y); list($x1,$y1) = $this->scale->Translate($x, $y);
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->g->img->Point($x1,$y1); $this->g->img->Point($x1,$y1);
} }
   
function Stroke() { function Stroke() {
$this->g->Stroke(); $this->g->Stroke();
} }
   
} }
   
   
class PixelFill { class PixelFill {
   
private $edges,$dataPoints,$colors,$isoBars; private $edges,$dataPoints,$colors,$isoBars;
   
function __construct(&$edges,&$dataPoints,$isoBars,$colors) { function __construct(&$edges,&$dataPoints,$isoBars,$colors) {
$this->edges = $edges; $this->edges = $edges;
$this->dataPoints = $dataPoints; $this->dataPoints = $dataPoints;
$this->colors = $colors; $this->colors = $colors;
$this->isoBars = $isoBars; $this->isoBars = $isoBars;
} }
   
function GetIsobarColor($val) { function GetIsobarColor($val) {
for ($i = 0 ; $i < count($this->isoBars) ; $i++) { for ($i = 0 ; $i < count($this->isoBars) ; $i++) {
if( $val <= $this->isoBars[$i] ) { if( $val <= $this->isoBars[$i] ) {
return $this->colors[$i]; return $this->colors[$i];
} }
} }
return $this->colors[$i]; // The color for all values above the highest isobar return $this->colors[$i]; // The color for all values above the highest isobar
} }
   
function Fill(ContCanvas $canvas) { function Fill(ContCanvas $canvas) {
   
$nx_vertices = count($this->dataPoints[0]); $nx_vertices = count($this->dataPoints[0]);
$ny_vertices = count($this->dataPoints); $ny_vertices = count($this->dataPoints);
   
// Loop through all squares in the grid // Loop through all squares in the grid
for($col=0; $col < $nx_vertices-1; ++$col) { for($col=0; $col < $nx_vertices-1; ++$col) {
for($row=0; $row < $ny_vertices-1; ++$row) { for($row=0; $row < $ny_vertices-1; ++$row) {
   
$v=array( $v=array(
$this->dataPoints[$row][$col], $this->dataPoints[$row][$col],
$this->dataPoints[$row][$col+1], $this->dataPoints[$row][$col+1],
$this->dataPoints[$row+1][$col+1], $this->dataPoints[$row+1][$col+1],
$this->dataPoints[$row+1][$col], $this->dataPoints[$row+1][$col],
); );
list($x1,$y1) = $canvas->scale->Translate($col, $row); list($x1,$y1) = $canvas->scale->Translate($col, $row);
list($x2,$y2) = $canvas->scale->Translate($col+1, $row+1); list($x2,$y2) = $canvas->scale->Translate($col+1, $row+1);
   
for( $x=$x1; $x < $x2; ++$x ) { for( $x=$x1; $x < $x2; ++$x ) {
for( $y=$y1; $y < $y2; ++$y ) { for( $y=$y1; $y < $y2; ++$y ) {
   
$v1 = $v[0] + ($v[1]-$v[0])*($x-$x1)/($x2-$x1); $v1 = $v[0] + ($v[1]-$v[0])*($x-$x1)/($x2-$x1);
$v2 = $v[3] + ($v[2]-$v[3])*($x-$x1)/($x2-$x1); $v2 = $v[3] + ($v[2]-$v[3])*($x-$x1)/($x2-$x1);
$val = $v1 + ($v2-$v1)*($y-$y1)/($y2-$y1); $val = $v1 + ($v2-$v1)*($y-$y1)/($y2-$y1);
   
if( $row==2 && $col==2 ) { if( $row==2 && $col==2 ) {
//echo " ($val ($x,$y)) (".$v[0].",".$v[1].",".$v[2].",".$v[3].")<br>"; //echo " ($val ($x,$y)) (".$v[0].",".$v[1].",".$v[2].",".$v[3].")<br>";
} }
$color = $this->GetIsobarColor($val); $color = $this->GetIsobarColor($val);
$canvas->g->img->SetColor($color); $canvas->g->img->SetColor($color);
$canvas->g->img->Point($x, $y); $canvas->g->img->Point($x, $y);
} }
} }
} }
} }
   
} }
   
} }
   
$edges=array(array(),array(),array()); $edges=array(array(),array(),array());
$datapoints=array(); $datapoints=array();
for($col=0; $col<6; $col++) { for($col=0; $col<6; $col++) {
for($row=0; $row<6; $row++) { for($row=0; $row<6; $row++) {
$datapoints[$row][$col]=0; $datapoints[$row][$col]=0;
$edges[VERT_EDGE][$row][$col] = false; $edges[VERT_EDGE][$row][$col] = false;
$edges[HORIZ_EDGE][$row][$col] = false; $edges[HORIZ_EDGE][$row][$col] = false;
} }
} }
   
$datapoints[1][2] = 2; $datapoints[1][2] = 2;
$datapoints[2][1] = 1; $datapoints[2][1] = 1;
$datapoints[2][2] = 7; $datapoints[2][2] = 7;
$datapoints[2][3] = 2; $datapoints[2][3] = 2;
$datapoints[3][1] = 2; $datapoints[3][1] = 2;
$datapoints[3][2] = 17; $datapoints[3][2] = 17;
$datapoints[3][3] = 4; $datapoints[3][3] = 4;
$datapoints[4][2] = 3; $datapoints[4][2] = 3;
   
$datapoints[1][4] = 12; $datapoints[1][4] = 12;
   
$edges[VERT_EDGE][1][2] = true; $edges[VERT_EDGE][1][2] = true;
$edges[VERT_EDGE][3][2] = true; $edges[VERT_EDGE][3][2] = true;
   
$edges[HORIZ_EDGE][2][1] = true; $edges[HORIZ_EDGE][2][1] = true;
$edges[HORIZ_EDGE][2][2] = true; $edges[HORIZ_EDGE][2][2] = true;
$edges[HORIZ_EDGE][3][1] = true; $edges[HORIZ_EDGE][3][1] = true;
$edges[HORIZ_EDGE][3][2] = true; $edges[HORIZ_EDGE][3][2] = true;
   
   
   
$isobars = array(5,10,15); $isobars = array(5,10,15);
$colors = array('lightgray','lightblue','lightred','red'); $colors = array('lightgray','lightblue','lightred','red');
   
$engine = new PixelFill($edges, $datapoints, $isobars, $colors); $engine = new PixelFill($edges, $datapoints, $isobars, $colors);
$canvas = new ContCanvas(); $canvas = new ContCanvas();
$engine->Fill($canvas); $engine->Fill($canvas);
$canvas->SetDatapoints($datapoints); $canvas->SetDatapoints($datapoints);
$canvas->Stroke(); $canvas->Stroke();
die(); die();
   
   
//$tst = new Findpolygon(); //$tst = new Findpolygon();
//$p1 = $tst->SetupTestData(); //$p1 = $tst->SetupTestData();
// //
//$canvas = new ContCanvas(); //$canvas = new ContCanvas();
//for ($i = 0 ; $i < count($tst->contourCoord); $i++) { //for ($i = 0 ; $i < count($tst->contourCoord); $i++) {
// $canvas->DrawLinePolygons($tst->contourCoord[$i]); // $canvas->DrawLinePolygons($tst->contourCoord[$i]);
//} //}
// //
//$p2 = $tst->FindPolygons(); //$p2 = $tst->FindPolygons();
//for ($i = 0 ; $i < count($p2) ; $i++) { //for ($i = 0 ; $i < count($p2) ; $i++) {
// $canvas->FilledPolygon($tst->flattenEdges($p2[$i])); // $canvas->FilledPolygon($tst->flattenEdges($p2[$i]));
//} //}
// //
//for ($i = 0 ; $i < count($p2) ; $i++) { //for ($i = 0 ; $i < count($p2) ; $i++) {
// $canvas->Polygon($tst->flattenEdges($p2[$i])); // $canvas->Polygon($tst->flattenEdges($p2[$i]));
//} //}
// //
//$canvas->Stroke(); //$canvas->Stroke();
//die(); //die();
   
   
//for( $trial = 0; $trial < 1; ++$trial ) { //for( $trial = 0; $trial < 1; ++$trial ) {
// echo "\nTest $trial:\n"; // echo "\nTest $trial:\n";
// echo "========================================\n"; // echo "========================================\n";
// $tst = new Findpolygon(); // $tst = new Findpolygon();
// $p1 = $tst->SetupTestData(); // $p1 = $tst->SetupTestData();
// //
// // for ($i = 0 ; $i < count($p1) ; $i++) { // // for ($i = 0 ; $i < count($p1) ; $i++) {
// // echo "Test polygon $i:\n"; // // echo "Test polygon $i:\n";
// // echo "---------------------\n"; // // echo "---------------------\n";
// // $tst->p_edges($tst->contourCoord[$i]); // // $tst->p_edges($tst->contourCoord[$i]);
// // echo "\n"; // // echo "\n";
// // } // // }
// // // //
// $p2 = $tst->FindPolygons(); // $p2 = $tst->FindPolygons();
// $npol = count($p2); // $npol = count($p2);
// //echo "\n** Found $npol separate polygon chains.\n\n"; // //echo "\n** Found $npol separate polygon chains.\n\n";
// //
// for( $i=0; $i<$npol; ++$i ) { // for( $i=0; $i<$npol; ++$i ) {
// //
// $res_forward = $tst->CompareCyclic($p1[$i], $p2[$i],true); // $res_forward = $tst->CompareCyclic($p1[$i], $p2[$i],true);
// $res_backward = $tst->CompareCyclic($p1[$i], $p2[$i],false); // $res_backward = $tst->CompareCyclic($p1[$i], $p2[$i],false);
// if( $res_backward || $res_forward ) { // if( $res_backward || $res_forward ) {
// // if( $res_forward ) // // if( $res_forward )
// // echo "Forward matches!\n"; // // echo "Forward matches!\n";
// // else // // else
// // echo "Backward matches!\n"; // // echo "Backward matches!\n";
// } // }
// else { // else {
// echo "********** NO MATCH!!.\n\n"; // echo "********** NO MATCH!!.\n\n";
// echo "\nBefore find:\n"; // echo "\nBefore find:\n";
// for ($j = 0 ; $j < count($p1[$i]) ; $j++) { // for ($j = 0 ; $j < count($p1[$i]) ; $j++) {
// echo "(".$p1[$i][$j][0].','.$p1[$i][$j][1]."), "; // echo "(".$p1[$i][$j][0].','.$p1[$i][$j][1]."), ";
// } // }
// echo "\n"; // echo "\n";
// //
// echo "\nAfter find:\n"; // echo "\nAfter find:\n";
// for ($j = 0 ; $j < count($p2[$i]) ; $j++) { // for ($j = 0 ; $j < count($p2[$i]) ; $j++) {
// echo "(".$p2[$i][$j][0].','.$p2[$i][$j][1]."), "; // echo "(".$p2[$i][$j][0].','.$p2[$i][$j][1]."), ";
// } // }
// echo "\n"; // echo "\n";
// } // }
// //
// } // }
//} //}
// //
//echo "\n\nAll tests ready.\n\n"; //echo "\n\nAll tests ready.\n\n";
// //
   
   
?> ?>
   
<?php <?php
require_once '../jpgraph.php'; require_once '../jpgraph.php';
require_once '../jpgraph_canvas.php'; require_once '../jpgraph_canvas.php';
require_once '../jpgraph_canvtools.php'; require_once '../jpgraph_canvtools.php';
   
   
class ContCanvas { class ContCanvas {
public $g; public $g;
public $shape,$scale; public $shape,$scale;
function __construct($xmax=5,$ymax=5,$width=350,$height=350) { function __construct($xmax=5,$ymax=5,$width=350,$height=350) {
   
$this->g = new CanvasGraph($width,$height); $this->g = new CanvasGraph($width,$height);
$this->scale = new CanvasScale($this->g, 0, $xmax, 0, $ymax); $this->scale = new CanvasScale($this->g, 0, $xmax, 0, $ymax);
$this->shape = new Shape($this->g, $this->scale); $this->shape = new Shape($this->g, $this->scale);
   
//$this->g->SetFrame(true); //$this->g->SetFrame(true);
$this->g->SetMargin(2,2,2,2); $this->g->SetMargin(2,2,2,2);
$this->g->SetMarginColor('white@1'); $this->g->SetMarginColor('white@1');
$this->g->InitFrame(); $this->g->InitFrame();
} }
   
function StrokeGrid() { function StrokeGrid() {
list($xmin,$xmax,$ymin,$ymax) = $this->scale->Get(); list($xmin,$xmax,$ymin,$ymax) = $this->scale->Get();
$this->shape->SetColor('gray'); $this->shape->SetColor('gray');
for( $col=1; $col<$xmax; ++$col ) { for( $col=1; $col<$xmax; ++$col ) {
$this->shape->Line($col, 0, $col, $ymax); $this->shape->Line($col, 0, $col, $ymax);
} }
for( $row=1; $row<$ymax; ++$row ) { for( $row=1; $row<$ymax; ++$row ) {
$this->shape->Line(0, $row, $xmax, $row); $this->shape->Line(0, $row, $xmax, $row);
} }
} }
   
function SetDatapoints($datapoints) { function SetDatapoints($datapoints) {
$ny=count($datapoints); $ny=count($datapoints);
$nx=count($datapoints[0]); $nx=count($datapoints[0]);
$t = new Text(); $t = new Text();
$t->SetFont(FF_ARIAL,FS_NORMAL,8); $t->SetFont(FF_ARIAL,FS_NORMAL,8);
for( $x=0; $x < $nx; ++$x ) { for( $x=0; $x < $nx; ++$x ) {
for( $y=0; $y < $ny; ++$y ) { for( $y=0; $y < $ny; ++$y ) {
list($x1,$y1) = $this->scale->Translate($x,$y); list($x1,$y1) = $this->scale->Translate($x,$y);
   
if( $datapoints[$y][$x] > 0 ) if( $datapoints[$y][$x] > 0 )
$t->SetColor('blue'); $t->SetColor('blue');
else else
$t->SetColor('black'); $t->SetColor('black');
$t->SetFont(FF_ARIAL,FS_BOLD,8); $t->SetFont(FF_ARIAL,FS_BOLD,8);
$t->Set($datapoints[$y][$x]); $t->Set($datapoints[$y][$x]);
$t->Stroke($this->g->img,$x1,$y1); $t->Stroke($this->g->img,$x1,$y1);
   
$t->SetColor('gray'); $t->SetColor('gray');
$t->SetFont(FF_ARIAL,FS_NORMAL,8); $t->SetFont(FF_ARIAL,FS_NORMAL,8);
$t->Set("($y,$x)"); $t->Set("($y,$x)");
$t->Stroke($this->g->img,$x1+10,$y1); $t->Stroke($this->g->img,$x1+10,$y1);
   
} }
} }
} }
   
function DrawLinePolygons($p,$color='red') { function DrawLinePolygons($p,$color='red') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
for ($i = 0 ; $i < count($p) ; $i++) { for ($i = 0 ; $i < count($p) ; $i++) {
$x1 = $p[$i][0][0]; $y1 = $p[$i][0][1]; $x1 = $p[$i][0][0]; $y1 = $p[$i][0][1];
for ($j = 1 ; $j < count($p[$i]) ; $j++) { for ($j = 1 ; $j < count($p[$i]) ; $j++) {
$x2=$p[$i][$j][0]; $y2 = $p[$i][$j][1]; $x2=$p[$i][$j][0]; $y2 = $p[$i][$j][1];
$this->shape->Line($x1, $y1, $x2, $y2); $this->shape->Line($x1, $y1, $x2, $y2);
$x1=$x2; $y1=$y2; $x1=$x2; $y1=$y2;
} }
} }
} }
   
function Line($x1,$y1,$x2,$y2,$color='red') { function Line($x1,$y1,$x2,$y2,$color='red') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->Line($x1, $y1, $x2, $y2); $this->shape->Line($x1, $y1, $x2, $y2);
} }
function Polygon($p,$color='blue') { function Polygon($p,$color='blue') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->Polygon($p); $this->shape->Polygon($p);
} }
   
function FilledPolygon($p,$color='lightblue') { function FilledPolygon($p,$color='lightblue') {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->FilledPolygon($p); $this->shape->FilledPolygon($p);
} }
   
function Point($x,$y,$color) { function Point($x,$y,$color) {
list($x1,$y1) = $this->scale->Translate($x, $y); list($x1,$y1) = $this->scale->Translate($x, $y);
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->g->img->Point($x1,$y1); $this->g->img->Point($x1,$y1);
} }
   
function Stroke() { function Stroke() {
$this->g->Stroke(); $this->g->Stroke();
} }
   
} }
   
// Calculate the area for a simple polygon. This will not work for // Calculate the area for a simple polygon. This will not work for
// non-simple polygons, i.e. self crossing. // non-simple polygons, i.e. self crossing.
function polygonArea($aX, $aY) { function polygonArea($aX, $aY) {
$n = count($aX); $n = count($aX);
$area = 0 ; $area = 0 ;
$j = 0 ; $j = 0 ;
for ($i=0; $i < $n; $i++) { for ($i=0; $i < $n; $i++) {
$j++; $j++;
if ( $j == $n) { if ( $j == $n) {
$j=0; $j=0;
} }
$area += ($aX[i]+$aX[j])*($aY[i]-$aY[j]); $area += ($aX[i]+$aX[j])*($aY[i]-$aY[j]);
} }
return area*.5; return area*.5;
} }
   
class SingleTestTriangle { class SingleTestTriangle {
const contval=5; const contval=5;
static $maxdepth=2; static $maxdepth=2;
static $cnt=0; static $cnt=0;
static $t; static $t;
public $g; public $g;
public $shape,$scale; public $shape,$scale;
public $cont = array(2,4,5); public $cont = array(2,4,5);
public $contcolors = array('yellow','purple','seagreen','green','lightblue','blue','teal','orange','red','darkred','brown'); public $contcolors = array('yellow','purple','seagreen','green','lightblue','blue','teal','orange','red','darkred','brown');
public $dofill=false; public $dofill=false;
public $showtriangulation=false,$triangulation_color="lightgray"; public $showtriangulation=false,$triangulation_color="lightgray";
public $showannotation=false; public $showannotation=false;
public $contlinecolor='black',$showcontlines=true; public $contlinecolor='black',$showcontlines=true;
private $labels = array(), $showlabels=false; private $labels = array(), $showlabels=false;
private $labelColor='black',$labelFF=FF_ARIAL,$labelFS=FS_BOLD,$labelFSize=9; private $labelColor='black',$labelFF=FF_ARIAL,$labelFS=FS_BOLD,$labelFSize=9;
   
function __construct($width,$height,$nx,$ny) { function __construct($width,$height,$nx,$ny) {
$xmax=$nx+0.1;$ymax=$ny+0.1; $xmax=$nx+0.1;$ymax=$ny+0.1;
$this->g = new CanvasGraph($width,$height); $this->g = new CanvasGraph($width,$height);
$this->scale = new CanvasScale($this->g, -0.1, $xmax, -0.1, $ymax); $this->scale = new CanvasScale($this->g, -0.1, $xmax, -0.1, $ymax);
$this->shape = new Shape($this->g, $this->scale); $this->shape = new Shape($this->g, $this->scale);
   
//$this->g->SetFrame(true); //$this->g->SetFrame(true);
$this->g->SetMargin(2,2,2,2); $this->g->SetMargin(2,2,2,2);
$this->g->SetMarginColor('white@1'); $this->g->SetMarginColor('white@1');
//$this->g->InitFrame(); //$this->g->InitFrame();
   
self::$t = new Text(); self::$t = new Text();
self::$t->SetColor('black'); self::$t->SetColor('black');
self::$t->SetFont(FF_ARIAL,FS_BOLD,9); self::$t->SetFont(FF_ARIAL,FS_BOLD,9);
self::$t->SetAlign('center','center'); self::$t->SetAlign('center','center');
} }
   
function getPlotSize() { function getPlotSize() {
return array($this->g->img->width,$this->g->img->height); return array($this->g->img->width,$this->g->img->height);
} }
   
function SetContours($c) { function SetContours($c) {
$this->cont = $c; $this->cont = $c;
} }
   
function ShowLabels($aFlg=true) { function ShowLabels($aFlg=true) {
$this->showlabels = $aFlg; $this->showlabels = $aFlg;
} }
   
function ShowLines($aFlg=true) { function ShowLines($aFlg=true) {
$this->showcontlines=$aFlg; $this->showcontlines=$aFlg;
} }
   
function SetFilled($f=true) { function SetFilled($f=true) {
$this->dofill = $f; $this->dofill = $f;
} }
   
function ShowTriangulation($f=true) { function ShowTriangulation($f=true) {
$this->showtriangulation = $f; $this->showtriangulation = $f;
} }
   
function Stroke() { function Stroke() {
$this->g->Stroke(); $this->g->Stroke();
} }
   
function FillPolygon($color,&$p) { function FillPolygon($color,&$p) {
self::$cnt++; self::$cnt++;
if( $this->dofill ) { if( $this->dofill ) {
$this->shape->SetColor($color); $this->shape->SetColor($color);
$this->shape->FilledPolygon($p); $this->shape->FilledPolygon($p);
} }
if( $this->showtriangulation ) { if( $this->showtriangulation ) {
$this->shape->SetColor($this->triangulation_color); $this->shape->SetColor($this->triangulation_color);
$this->shape->Polygon($p); $this->shape->Polygon($p);
} }
} }
function GetNextHigherContourIdx($val) { function GetNextHigherContourIdx($val) {
for( $i=0; $i < count($this->cont); ++$i ) { for( $i=0; $i < count($this->cont); ++$i ) {
if( $val < $this->cont[$i] ) return $i; if( $val < $this->cont[$i] ) return $i;
} }
return count($this->cont); return count($this->cont);
} }
   
function GetContVal($v1) { function GetContVal($v1) {
for( $i=0; $i < count($this->cont); ++$i ) { for( $i=0; $i < count($this->cont); ++$i ) {
if( $this->cont[$i] > $v1 ) { if( $this->cont[$i] > $v1 ) {
return $this->cont[$i]; return $this->cont[$i];
} }
} }
die('No contour value is larger or equal than : '.$v1); die('No contour value is larger or equal than : '.$v1);
} }
function GetColor($v) { function GetColor($v) {
return $this->contcolors[$this->GetNextHigherContourIdx($v)]; return $this->contcolors[$this->GetNextHigherContourIdx($v)];
} }
   
function storeAnnotation($x1,$y1,$v1,$angle) { function storeAnnotation($x1,$y1,$v1,$angle) {
$this->labels[$this->GetNextHigherContourIdx($v1)][] = array($x1,$y1,$v1,$angle); $this->labels[$this->GetNextHigherContourIdx($v1)][] = array($x1,$y1,$v1,$angle);
} }
   
function labelProx($x1,$y1,$v1) { function labelProx($x1,$y1,$v1) {
   
list($w,$h) = $this->getPlotSize(); list($w,$h) = $this->getPlotSize();
   
   
if( $x1 < 20 || $x1 > $w-20 ) if( $x1 < 20 || $x1 > $w-20 )
return true; return true;
   
if( $y1 < 20 || $y1 > $h-20 ) if( $y1 < 20 || $y1 > $h-20 )
return true; return true;
if( !isset ($this->labels[$this->GetNextHigherContourIdx($v1)]) ) { if( !isset ($this->labels[$this->GetNextHigherContourIdx($v1)]) ) {
return false; return false;
} }
$p = $this->labels[$this->GetNextHigherContourIdx($v1)]; $p = $this->labels[$this->GetNextHigherContourIdx($v1)];
$n = count($p); $n = count($p);
$d = 999999; $d = 999999;
for ($i = 0 ; $i < $n ; $i++) { for ($i = 0 ; $i < $n ; $i++) {
$xp = $p[$i][0]; $xp = $p[$i][0];
$yp = $p[$i][1]; $yp = $p[$i][1];
$d = min($d, ($x1-$xp)*($x1-$xp) + ($y1-$yp)*($y1-$yp)); $d = min($d, ($x1-$xp)*($x1-$xp) + ($y1-$yp)*($y1-$yp));
} }
$limit = $w*$h/9; $limit = $w*$h/9;
$limit = max(min($limit,20000),3500); $limit = max(min($limit,20000),3500);
if( $d < $limit ) return true; if( $d < $limit ) return true;
else return false; else return false;
} }
   
function putLabel($x1,$y1,$x2,$y2,$v1) { function putLabel($x1,$y1,$x2,$y2,$v1) {
   
$angle = 0; $angle = 0;
if( $x2 - $x1 != 0 ) { if( $x2 - $x1 != 0 ) {
$grad = ($y2-$y1)/($x2-$x1); $grad = ($y2-$y1)/($x2-$x1);
$angle = -(atan($grad) * 180/M_PI); $angle = -(atan($grad) * 180/M_PI);
self::$t->SetAngle($angle); self::$t->SetAngle($angle);
} }
   
$x = $this->scale->TranslateX($x1); $x = $this->scale->TranslateX($x1);
$y = $this->scale->TranslateY($y1); $y = $this->scale->TranslateY($y1);
if( !$this->labelProx($x, $y, $v1) ) { if( !$this->labelProx($x, $y, $v1) ) {
$this->storeAnnotation($x, $y, $v1, $angle); $this->storeAnnotation($x, $y, $v1, $angle);
} }
} }
   
function strokeLabels() { function strokeLabels() {
$t = new Text(); $t = new Text();
$t->SetColor($this->labelColor); $t->SetColor($this->labelColor);
$t->SetFont($this->labelFF,$this->labelFS,$this->labelFSize); $t->SetFont($this->labelFF,$this->labelFS,$this->labelFSize);
$t->SetAlign('center','center'); $t->SetAlign('center','center');
   
foreach ($this->labels as $cont_idx => $pos) { foreach ($this->labels as $cont_idx => $pos) {
if( $cont_idx >= 10 ) return; if( $cont_idx >= 10 ) return;
foreach ($pos as $idx => $coord) { foreach ($pos as $idx => $coord) {
$t->Set( sprintf("%.1f",$coord[2]) ); $t->Set( sprintf("%.1f",$coord[2]) );
$t->SetAngle($coord[3]); $t->SetAngle($coord[3]);
$t->Stroke($this->g->img,$coord[0],$coord[1]); $t->Stroke($this->g->img,$coord[0],$coord[1]);
} }
} }
} }
   
function annotate($x1,$y1,$x2,$y2,$x1p,$y1p,$v1,$v2,$v1p) { function annotate($x1,$y1,$x2,$y2,$x1p,$y1p,$v1,$v2,$v1p) {
if( !$this->showannotation ) return; if( !$this->showannotation ) return;
/* /*
$this->g->img->SetColor('green'); $this->g->img->SetColor('green');
$this->g->img->FilledCircle($this->scale->TranslateX($x1),$this->scale->TranslateY($y1), 4); $this->g->img->FilledCircle($this->scale->TranslateX($x1),$this->scale->TranslateY($y1), 4);
$this->g->img->FilledCircle($this->scale->TranslateX($x2),$this->scale->TranslateY($y2), 4); $this->g->img->FilledCircle($this->scale->TranslateX($x2),$this->scale->TranslateY($y2), 4);
   
$this->g->img->SetColor('red'); $this->g->img->SetColor('red');
$this->g->img->FilledCircle($this->scale->TranslateX($x1p),$this->scale->TranslateY($y1p), 4); $this->g->img->FilledCircle($this->scale->TranslateX($x1p),$this->scale->TranslateY($y1p), 4);
*/ */
//self::$t->Set(sprintf("%.1f",$v1,$this->VC($v1))); //self::$t->Set(sprintf("%.1f",$v1,$this->VC($v1)));
//self::$t->Stroke($this->g->img,$this->scale->TranslateX($x1),$this->scale->TranslateY($y1)); //self::$t->Stroke($this->g->img,$this->scale->TranslateX($x1),$this->scale->TranslateY($y1));
//self::$t->Set(sprintf("%.1f",$v2,$this->VC($v2))); //self::$t->Set(sprintf("%.1f",$v2,$this->VC($v2)));
//self::$t->Stroke($this->g->img,$this->scale->TranslateX($x2),$this->scale->TranslateY($y2)); //self::$t->Stroke($this->g->img,$this->scale->TranslateX($x2),$this->scale->TranslateY($y2));
   
$x = $this->scale->TranslateX($x1p); $x = $this->scale->TranslateX($x1p);
$y = $this->scale->TranslateY($y1p); $y = $this->scale->TranslateY($y1p);
if( !$this->labelProx($x, $y, $v1p) ) { if( !$this->labelProx($x, $y, $v1p) ) {
$this->storeAnnotation($x, $y, $v1p); $this->storeAnnotation($x, $y, $v1p);
self::$t->Set(sprintf("%.1f",$v1p,$this->VC($v1p))); self::$t->Set(sprintf("%.1f",$v1p,$this->VC($v1p)));
self::$t->Stroke($this->g->img,$x,$y); self::$t->Stroke($this->g->img,$x,$y);
} }
} }
   
function Pertubate(&$v1,&$v2,&$v3,&$v4) { function Pertubate(&$v1,&$v2,&$v3,&$v4) {
$pert = 0.9999; $pert = 0.9999;
$n = count($this->cont); $n = count($this->cont);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $v1==$this->cont[$i] ) { if( $v1==$this->cont[$i] ) {
$v1 *= $pert; $v1 *= $pert;
break; break;
} }
} }
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $v2==$this->cont[$i] ) { if( $v2==$this->cont[$i] ) {
$v2 *= $pert; $v2 *= $pert;
break; break;
} }
} }
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $v3==$this->cont[$i] ) { if( $v3==$this->cont[$i] ) {
$v3 *= $pert; $v3 *= $pert;
break; break;
} }
} }
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $v4==$this->cont[$i] ) { if( $v4==$this->cont[$i] ) {
$v4 *= $pert; $v4 *= $pert;
break; break;
} }
} }
} }
   
function interp2($x1,$y1,$x2,$y2,$v1,$v2) { function interp2($x1,$y1,$x2,$y2,$v1,$v2) {
$cv = $this->GetContVal(min($v1,$v2)); $cv = $this->GetContVal(min($v1,$v2));
$alpha = ($v1-$cv)/($v1-$v2); $alpha = ($v1-$cv)/($v1-$v2);
$x1p = $x1*(1-$alpha) + $x2*$alpha; $x1p = $x1*(1-$alpha) + $x2*$alpha;
$y1p = $y1*(1-$alpha) + $y2*$alpha; $y1p = $y1*(1-$alpha) + $y2*$alpha;
$v1p = $v1 + $alpha*($v2-$v1); $v1p = $v1 + $alpha*($v2-$v1);
return array($x1p,$y1p,$v1p); return array($x1p,$y1p,$v1p);
} }
   
function RectFill($v1,$v2,$v3,$v4,$x1,$y1,$x2,$y2,$x3,$y3,$x4,$y4,$depth) { function RectFill($v1,$v2,$v3,$v4,$x1,$y1,$x2,$y2,$x3,$y3,$x4,$y4,$depth) {
if( $depth >= self::$maxdepth ) { if( $depth >= self::$maxdepth ) {
// Abort and just appoximate the color of this area // Abort and just appoximate the color of this area
// with the average of the three values // with the average of the three values
$color = $this->GetColor(($v1+$v2+$v3+$v4)/4); $color = $this->GetColor(($v1+$v2+$v3+$v4)/4);
$p = array($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $x1, $y1); $p = array($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $x1, $y1);
$this->FillPolygon($color,$p) ; $this->FillPolygon($color,$p) ;
} }
else { else {
   
$this->Pertubate($v1,$v2,$v3,$v4); $this->Pertubate($v1,$v2,$v3,$v4);
   
$fcnt = 0 ; $fcnt = 0 ;
$vv1 = $this->GetNextHigherContourIdx($v1); $vv1 = $this->GetNextHigherContourIdx($v1);
$vv2 = $this->GetNextHigherContourIdx($v2); $vv2 = $this->GetNextHigherContourIdx($v2);
$vv3 = $this->GetNextHigherContourIdx($v3); $vv3 = $this->GetNextHigherContourIdx($v3);
$vv4 = $this->GetNextHigherContourIdx($v4); $vv4 = $this->GetNextHigherContourIdx($v4);
$eps = 0.0001; $eps = 0.0001;
   
if( $vv1 == $vv2 && $vv2 == $vv3 && $vv3 == $vv4 ) { if( $vv1 == $vv2 && $vv2 == $vv3 && $vv3 == $vv4 ) {
$color = $this->GetColor($v1); $color = $this->GetColor($v1);
$p = array($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $x1, $y1); $p = array($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $x1, $y1);
$this->FillPolygon($color,$p) ; $this->FillPolygon($color,$p) ;
} }
else { else {
   
$dv1 = abs($vv1-$vv2); $dv1 = abs($vv1-$vv2);
$dv2 = abs($vv2-$vv3); $dv2 = abs($vv2-$vv3);
$dv3 = abs($vv3-$vv4); $dv3 = abs($vv3-$vv4);
$dv4 = abs($vv1-$vv4); $dv4 = abs($vv1-$vv4);
if( $dv1 == 1 ) { if( $dv1 == 1 ) {
list($x1p,$y1p,$v1p) = $this->interp2($x1,$y1,$x2,$y2,$v1,$v2); list($x1p,$y1p,$v1p) = $this->interp2($x1,$y1,$x2,$y2,$v1,$v2);
$fcnt++; $fcnt++;
} }
if( $dv2 == 1 ) { if( $dv2 == 1 ) {
list($x2p,$y2p,$v2p) = $this->interp2($x2,$y2,$x3,$y3,$v2,$v3); list($x2p,$y2p,$v2p) = $this->interp2($x2,$y2,$x3,$y3,$v2,$v3);
$fcnt++; $fcnt++;
} }
if( $dv3 == 1 ) { if( $dv3 == 1 ) {
list($x3p,$y3p,$v3p) = $this->interp2($x3,$y3,$x4,$y4,$v3,$v4); list($x3p,$y3p,$v3p) = $this->interp2($x3,$y3,$x4,$y4,$v3,$v4);
$fcnt++; $fcnt++;
} }
   
if( $dv4 == 1 ) { if( $dv4 == 1 ) {
list($x4p,$y4p,$v4p) = $this->interp2($x4,$y4,$x1,$y1,$v4,$v1); list($x4p,$y4p,$v4p) = $this->interp2($x4,$y4,$x1,$y1,$v4,$v1);
$fcnt++; $fcnt++;
} }
   
$totdv = $dv1 + $dv2 + $dv3 + $dv4 ; $totdv = $dv1 + $dv2 + $dv3 + $dv4 ;
if( ($fcnt == 2 && $totdv==2) || ($fcnt == 4 && $totdv==4) ) { if( ($fcnt == 2 && $totdv==2) || ($fcnt == 4 && $totdv==4) ) {
   
if( $fcnt == 2 && $totdv==2 ) { if( $fcnt == 2 && $totdv==2 ) {
   
if( $dv1 == 1 && $dv2 == 1) { if( $dv1 == 1 && $dv2 == 1) {
$color1 = $this->GetColor($v2); $color1 = $this->GetColor($v2);
$p1 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p); $p1 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p);
$color2 = $this->GetColor($v4); $color2 = $this->GetColor($v4);
$p2 = array($x1,$y1,$x1p,$y1p,$x2p,$y2p,$x3,$y3,$x4,$y4,$x1,$y1); $p2 = array($x1,$y1,$x1p,$y1p,$x2p,$y2p,$x3,$y3,$x4,$y4,$x1,$y1);
   
$color = $this->GetColor($v1p); $color = $this->GetColor($v1p);
$p = array($x1p,$y1p,$x2p,$y2p); $p = array($x1p,$y1p,$x2p,$y2p);
$v = $v1p; $v = $v1p;
} }
elseif( $dv1 == 1 && $dv3 == 1 ) { elseif( $dv1 == 1 && $dv3 == 1 ) {
$color1 = $this->GetColor($v2); $color1 = $this->GetColor($v2);
$p1 = array($x1p,$y1p,$x2,$y2,$x3,$y3,$x3p,$y3p,$x1p,$y1p); $p1 = array($x1p,$y1p,$x2,$y2,$x3,$y3,$x3p,$y3p,$x1p,$y1p);
$color2 = $this->GetColor($v4); $color2 = $this->GetColor($v4);
$p2 = array($x1,$y1,$x1p,$y1p,$x3p,$y3p,$x4,$y4,$x1,$y1); $p2 = array($x1,$y1,$x1p,$y1p,$x3p,$y3p,$x4,$y4,$x1,$y1);
   
$color = $this->GetColor($v1p); $color = $this->GetColor($v1p);
$p = array($x1p,$y1p,$x3p,$y3p); $p = array($x1p,$y1p,$x3p,$y3p);
$v = $v1p; $v = $v1p;
} }
elseif( $dv1 == 1 && $dv4 == 1 ) { elseif( $dv1 == 1 && $dv4 == 1 ) {
$color1 = $this->GetColor($v1); $color1 = $this->GetColor($v1);
$p1 = array($x1,$y1,$x1p,$y1p,$x4p,$y4p,$x1,$y1); $p1 = array($x1,$y1,$x1p,$y1p,$x4p,$y4p,$x1,$y1);
$color2 = $this->GetColor($v3); $color2 = $this->GetColor($v3);
$p2 = array($x1p,$y1p,$x2,$y2,$x3,$y3,$x4,$y4,$x4p,$y4p,$x1p,$y1p); $p2 = array($x1p,$y1p,$x2,$y2,$x3,$y3,$x4,$y4,$x4p,$y4p,$x1p,$y1p);
   
$color = $this->GetColor($v1p); $color = $this->GetColor($v1p);
$p = array($x1p,$y1p,$x4p,$y4p); $p = array($x1p,$y1p,$x4p,$y4p);
$v = $v1p; $v = $v1p;
} }
elseif( $dv2 == 1 && $dv4 == 1 ) { elseif( $dv2 == 1 && $dv4 == 1 ) {
$color1 = $this->GetColor($v1); $color1 = $this->GetColor($v1);
$p1 = array($x1,$y1,$x2,$y2,$x2p,$y2p,$x4p,$y4p,$x1,$y1); $p1 = array($x1,$y1,$x2,$y2,$x2p,$y2p,$x4p,$y4p,$x1,$y1);
$color2 = $this->GetColor($v3); $color2 = $this->GetColor($v3);
$p2 = array($x4p,$y4p,$x2p,$y2p,$x3,$y3,$x4,$y4,$x4p,$y4p); $p2 = array($x4p,$y4p,$x2p,$y2p,$x3,$y3,$x4,$y4,$x4p,$y4p);
   
$color = $this->GetColor($v2p); $color = $this->GetColor($v2p);
$p = array($x2p,$y2p,$x4p,$y4p); $p = array($x2p,$y2p,$x4p,$y4p);
$v = $v2p; $v = $v2p;
} }
elseif( $dv2 == 1 && $dv3 == 1 ) { elseif( $dv2 == 1 && $dv3 == 1 ) {
$color1 = $this->GetColor($v1); $color1 = $this->GetColor($v1);
$p1 = array($x1,$y1,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x4,$y4,$x1,$y1); $p1 = array($x1,$y1,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x4,$y4,$x1,$y1);
$color2 = $this->GetColor($v3); $color2 = $this->GetColor($v3);
$p2 = array($x2p,$y2p,$x3,$y3,$x3p,$y3p,$x2p,$y2p); $p2 = array($x2p,$y2p,$x3,$y3,$x3p,$y3p,$x2p,$y2p);
   
$color = $this->GetColor($v2p); $color = $this->GetColor($v2p);
$p = array($x2p,$y2p,$x3p,$y3p); $p = array($x2p,$y2p,$x3p,$y3p);
$v = $v2p; $v = $v2p;
} }
elseif( $dv3 == 1 && $dv4 == 1 ) { elseif( $dv3 == 1 && $dv4 == 1 ) {
$color1 = $this->GetColor($v1); $color1 = $this->GetColor($v1);
$p1 = array($x1,$y1,$x2,$y2,$x3,$y3,$x3p,$y3p,$x4p,$y4p,$x1,$y1); $p1 = array($x1,$y1,$x2,$y2,$x3,$y3,$x3p,$y3p,$x4p,$y4p,$x1,$y1);
$color2 = $this->GetColor($v4); $color2 = $this->GetColor($v4);
$p2 = array($x4p,$y4p,$x3p,$y3p,$x4,$y4,$x4p,$y4p); $p2 = array($x4p,$y4p,$x3p,$y3p,$x4,$y4,$x4p,$y4p);
   
$color = $this->GetColor($v4p); $color = $this->GetColor($v4p);
$p = array($x4p,$y4p,$x3p,$y3p); $p = array($x4p,$y4p,$x3p,$y3p);
$v = $v4p; $v = $v4p;
} }
   
$this->FillPolygon($color1,$p1); $this->FillPolygon($color1,$p1);
$this->FillPolygon($color2,$p2); $this->FillPolygon($color2,$p2);
   
if( $this->showcontlines ) { if( $this->showcontlines ) {
if( $this->dofill ) { if( $this->dofill ) {
$this->shape->SetColor($this->contlinecolor); $this->shape->SetColor($this->contlinecolor);
} }
else { else {
$this->shape->SetColor($color); $this->shape->SetColor($color);
} }
$this->shape->Line($p[0],$p[1],$p[2],$p[3]); $this->shape->Line($p[0],$p[1],$p[2],$p[3]);
} }
if( $this->showlabels ) { if( $this->showlabels ) {
$this->putLabel( ($p[0]+$p[2])/2, ($p[1]+$p[3])/2, $p[2],$p[3] , $v); $this->putLabel( ($p[0]+$p[2])/2, ($p[1]+$p[3])/2, $p[2],$p[3] , $v);
} }
} }
elseif( $fcnt == 4 && $totdv==4 ) { elseif( $fcnt == 4 && $totdv==4 ) {
$vc = ($v1+$v2+$v3+$v4)/4; $vc = ($v1+$v2+$v3+$v4)/4;
   
if( $v1p == $v2p && $v2p == $v3p && $v3p == $v4p ) { if( $v1p == $v2p && $v2p == $v3p && $v3p == $v4p ) {
// Four edge crossings (saddle point) of the same contour // Four edge crossings (saddle point) of the same contour
// so we first need to // so we first need to
// find out how the saddle is crossing "/" or "\" // find out how the saddle is crossing "/" or "\"
   
if( $this->GetNextHigherContourIdx($vc) == $this->GetNextHigherContourIdx($v1) ) { if( $this->GetNextHigherContourIdx($vc) == $this->GetNextHigherContourIdx($v1) ) {
// "\" // "\"
$color1 = $this->GetColor($v1); $color1 = $this->GetColor($v1);
$p1 = array($x1,$y1,$x1p,$y1p,$x4p,$y4p,$x1,$y1); $p1 = array($x1,$y1,$x1p,$y1p,$x4p,$y4p,$x1,$y1);
   
$color2 = $this->GetColor($v2); $color2 = $this->GetColor($v2);
$p2 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x4,$y4,$x4p,$y4p,$x1p,$y1p); $p2 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x4,$y4,$x4p,$y4p,$x1p,$y1p);
   
$color3 = $color1; $color3 = $color1;
$p3 = array($x2p,$y2p,$x3,$y3,$x3p,$y3p,$x2p,$y2p); $p3 = array($x2p,$y2p,$x3,$y3,$x3p,$y3p,$x2p,$y2p);
   
$colorl1 = $this->GetColor($v1p); $colorl1 = $this->GetColor($v1p);
$pl1 = array($x1p,$y1p,$x4p,$y4p); $pl1 = array($x1p,$y1p,$x4p,$y4p);
$colorl2 = $this->GetColor($v2p); $colorl2 = $this->GetColor($v2p);
$pl2 = array($x2p,$y2p,$x3p,$y3p); $pl2 = array($x2p,$y2p,$x3p,$y3p);
$vl1 = $v1p; $vl2 = $v2p; $vl1 = $v1p; $vl2 = $v2p;
   
} }
else { else {
// "/" // "/"
$color1 = $this->GetColor($v2); $color1 = $this->GetColor($v2);
$p1 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p); $p1 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p);
   
$color2 = $this->GetColor($v3); $color2 = $this->GetColor($v3);
$p2 = array($x1p,$y1p,$x2p,$y2p,$x3,$y3,$x3p,$y3p,$x4p,$y4p,$x1,$y1,$x1p,$y1p); $p2 = array($x1p,$y1p,$x2p,$y2p,$x3,$y3,$x3p,$y3p,$x4p,$y4p,$x1,$y1,$x1p,$y1p);
   
$color3 = $color1; $color3 = $color1;
$p3 = array($x4p,$y4p,$x3p,$y3p,$x4,$y4,$x4p,$y4p); $p3 = array($x4p,$y4p,$x3p,$y3p,$x4,$y4,$x4p,$y4p);
   
$colorl1 = $this->GetColor($v1p); $colorl1 = $this->GetColor($v1p);
$pl1 = array($x1p,$y1p,$x2p,$y2p); $pl1 = array($x1p,$y1p,$x2p,$y2p);
$colorl2 = $this->GetColor($v4p); $colorl2 = $this->GetColor($v4p);
$pl2 = array($x4p,$y4p,$x3p,$y3p); $pl2 = array($x4p,$y4p,$x3p,$y3p);
$vl1 = $v1p; $vl2 = $v4p; $vl1 = $v1p; $vl2 = $v4p;
} }
} }
else { else {
// There are two different contours crossing so we need to find // There are two different contours crossing so we need to find
// out which belongs to which // out which belongs to which
if( $v1p == $v2p ) { if( $v1p == $v2p ) {
// "/" // "/"
$color1 = $this->GetColor($v2); $color1 = $this->GetColor($v2);
$p1 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p); $p1 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p);
   
$color2 = $this->GetColor($v3); $color2 = $this->GetColor($v3);
$p2 = array($x1p,$y1p,$x2p,$y2p,$x3,$y3,$x3p,$y3p,$x4p,$y4p,$x1,$y1,$x1p,$y1p); $p2 = array($x1p,$y1p,$x2p,$y2p,$x3,$y3,$x3p,$y3p,$x4p,$y4p,$x1,$y1,$x1p,$y1p);
   
$color3 = $this->GetColor($v4); $color3 = $this->GetColor($v4);
$p3 = array($x4p,$y4p,$x3p,$y3p,$x4,$y4,$x4p,$y4p); $p3 = array($x4p,$y4p,$x3p,$y3p,$x4,$y4,$x4p,$y4p);
   
$colorl1 = $this->GetColor($v1p); $colorl1 = $this->GetColor($v1p);
$pl1 = array($x1p,$y1p,$x2p,$y2p); $pl1 = array($x1p,$y1p,$x2p,$y2p);
$colorl2 = $this->GetColor($v4p); $colorl2 = $this->GetColor($v4p);
$pl2 = array($x4p,$y4p,$x3p,$y3p); $pl2 = array($x4p,$y4p,$x3p,$y3p);
$vl1 = $v1p; $vl2 = $v4p; $vl1 = $v1p; $vl2 = $v4p;
} }
else { //( $v1p == $v4p ) else { //( $v1p == $v4p )
// "\" // "\"
$color1 = $this->GetColor($v1); $color1 = $this->GetColor($v1);
$p1 = array($x1,$y1,$x1p,$y1p,$x4p,$y4p,$x1,$y1); $p1 = array($x1,$y1,$x1p,$y1p,$x4p,$y4p,$x1,$y1);
   
$color2 = $this->GetColor($v2); $color2 = $this->GetColor($v2);
$p2 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x4,$y4,$x4p,$y4p,$x1p,$y1p); $p2 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x4,$y4,$x4p,$y4p,$x1p,$y1p);
   
$color3 = $this->GetColor($v3); $color3 = $this->GetColor($v3);
$p3 = array($x2p,$y2p,$x3,$y3,$x3p,$y3p,$x2p,$y2p); $p3 = array($x2p,$y2p,$x3,$y3,$x3p,$y3p,$x2p,$y2p);
   
$colorl1 = $this->GetColor($v1p); $colorl1 = $this->GetColor($v1p);
$pl1 = array($x1p,$y1p,$x4p,$y4p); $pl1 = array($x1p,$y1p,$x4p,$y4p);
$colorl2 = $this->GetColor($v2p); $colorl2 = $this->GetColor($v2p);
$pl2 = array($x2p,$y2p,$x3p,$y3p); $pl2 = array($x2p,$y2p,$x3p,$y3p);
$vl1 = $v1p; $vl2 = $v2p; $vl1 = $v1p; $vl2 = $v2p;
} }
} }
$this->FillPolygon($color1,$p1); $this->FillPolygon($color1,$p1);
$this->FillPolygon($color2,$p2); $this->FillPolygon($color2,$p2);
$this->FillPolygon($color3,$p3); $this->FillPolygon($color3,$p3);
   
if( $this->showcontlines ) { if( $this->showcontlines ) {
if( $this->dofill ) { if( $this->dofill ) {
$this->shape->SetColor($this->contlinecolor); $this->shape->SetColor($this->contlinecolor);
$this->shape->Line($pl1[0],$pl1[1],$pl1[2],$pl1[3]); $this->shape->Line($pl1[0],$pl1[1],$pl1[2],$pl1[3]);
$this->shape->Line($pl2[0],$pl2[1],$pl2[2],$pl2[3]); $this->shape->Line($pl2[0],$pl2[1],$pl2[2],$pl2[3]);
} }
else { else {
$this->shape->SetColor($colorl1); $this->shape->SetColor($colorl1);
$this->shape->Line($pl1[0],$pl1[1],$pl1[2],$pl1[3]); $this->shape->Line($pl1[0],$pl1[1],$pl1[2],$pl1[3]);
$this->shape->SetColor($colorl2); $this->shape->SetColor($colorl2);
$this->shape->Line($pl2[0],$pl2[1],$pl2[2],$pl2[3]); $this->shape->Line($pl2[0],$pl2[1],$pl2[2],$pl2[3]);
} }
} }
if( $this->showlabels ) { if( $this->showlabels ) {
$this->putLabel( ($pl1[0]+$pl1[2])/2, ($pl1[1]+$pl1[3])/2, $pl1[2], $pl1[3], $vl1); $this->putLabel( ($pl1[0]+$pl1[2])/2, ($pl1[1]+$pl1[3])/2, $pl1[2], $pl1[3], $vl1);
$this->putLabel( ($pl2[0]+$pl2[2])/2, ($pl2[1]+$pl2[3])/2, $pl2[2], $pl2[3],$vl2); $this->putLabel( ($pl2[0]+$pl2[2])/2, ($pl2[1]+$pl2[3])/2, $pl2[2], $pl2[3],$vl2);
} }
} }
} }
else { else {
$vc = ($v1+$v2+$v3+$v4)/4; $vc = ($v1+$v2+$v3+$v4)/4;
$xc = ($x1+$x4)/2; $xc = ($x1+$x4)/2;
$yc = ($y1+$y2)/2; $yc = ($y1+$y2)/2;
   
// Top left // Top left
$this->RectFill(($v1+$v2)/2, $v2, ($v2+$v3)/2, $vc, $this->RectFill(($v1+$v2)/2, $v2, ($v2+$v3)/2, $vc,
$x1,$yc, $x2,$y2, $xc,$y2, $xc,$yc, $depth+1); $x1,$yc, $x2,$y2, $xc,$y2, $xc,$yc, $depth+1);
// Top right // Top right
$this->RectFill($vc, ($v2+$v3)/2, $v3, ($v3+$v4)/2, $this->RectFill($vc, ($v2+$v3)/2, $v3, ($v3+$v4)/2,
$xc,$yc, $xc,$y2, $x3,$y3, $x3,$yc, $depth+1); $xc,$yc, $xc,$y2, $x3,$y3, $x3,$yc, $depth+1);
   
// Bottom left // Bottom left
$this->RectFill($v1, ($v1+$v2)/2, $vc, ($v1+$v4)/2, $this->RectFill($v1, ($v1+$v2)/2, $vc, ($v1+$v4)/2,
$x1,$y1, $x1,$yc, $xc,$yc, $xc,$y4, $depth+1); $x1,$y1, $x1,$yc, $xc,$yc, $xc,$y4, $depth+1);
   
// Bottom right // Bottom right
$this->RectFill(($v1+$v4)/2, $vc, ($v3+$v4)/2, $v4, $this->RectFill(($v1+$v4)/2, $vc, ($v3+$v4)/2, $v4,
$xc,$y1, $xc,$yc, $x3,$yc, $x4,$y4, $depth+1); $xc,$y1, $xc,$yc, $x3,$yc, $x4,$y4, $depth+1);
   
} }
} }
} }
} }
   
function TriFill($v1,$v2,$v3,$x1,$y1,$x2,$y2,$x3,$y3,$depth) { function TriFill($v1,$v2,$v3,$x1,$y1,$x2,$y2,$x3,$y3,$depth) {
if( $depth >= self::$maxdepth ) { if( $depth >= self::$maxdepth ) {
// Abort and just appoximate the color of this area // Abort and just appoximate the color of this area
// with the average of the three values // with the average of the three values
$color = $this->GetColor(($v1+$v2+$v3)/3); $color = $this->GetColor(($v1+$v2+$v3)/3);
$p = array($x1, $y1, $x2, $y2, $x3, $y3, $x1, $y1); $p = array($x1, $y1, $x2, $y2, $x3, $y3, $x1, $y1);
$this->FillPolygon($color,$p) ; $this->FillPolygon($color,$p) ;
} }
else { else {
// In order to avoid some real unpleasentness in case a vertice is exactly // In order to avoid some real unpleasentness in case a vertice is exactly
// the same value as a contour we pertuberate them so that we do not end up // the same value as a contour we pertuberate them so that we do not end up
// in udefined situation. This will only affect the calculations and not the // in udefined situation. This will only affect the calculations and not the
// visual appearance // visual appearance
   
$dummy=0; $dummy=0;
$this->Pertubate($v1,$v2,$v3,$dummy); $this->Pertubate($v1,$v2,$v3,$dummy);
   
$fcnt = 0 ; $fcnt = 0 ;
$vv1 = $this->GetNextHigherContourIdx($v1); $vv1 = $this->GetNextHigherContourIdx($v1);
$vv2 = $this->GetNextHigherContourIdx($v2); $vv2 = $this->GetNextHigherContourIdx($v2);
$vv3 = $this->GetNextHigherContourIdx($v3); $vv3 = $this->GetNextHigherContourIdx($v3);
$eps = 0.0001; $eps = 0.0001;
   
if( $vv1 == $vv2 && $vv2 == $vv3 ) { if( $vv1 == $vv2 && $vv2 == $vv3 ) {
$color = $this->GetColor($v1); $color = $this->GetColor($v1);
$p = array($x1, $y1, $x2, $y2, $x3, $y3, $x1, $y1); $p = array($x1, $y1, $x2, $y2, $x3, $y3, $x1, $y1);
$this->FillPolygon($color,$p) ; $this->FillPolygon($color,$p) ;
} }
else { else {
$dv1 = abs($vv1-$vv2); $dv1 = abs($vv1-$vv2);
$dv2 = abs($vv2-$vv3); $dv2 = abs($vv2-$vv3);
$dv3 = abs($vv1-$vv3); $dv3 = abs($vv1-$vv3);
   
if( $dv1 == 1 ) { if( $dv1 == 1 ) {
list($x1p,$y1p,$v1p) = $this->interp2($x1,$y1,$x2,$y2,$v1,$v2); list($x1p,$y1p,$v1p) = $this->interp2($x1,$y1,$x2,$y2,$v1,$v2);
$fcnt++; $fcnt++;
} }
else { else {
$x1p = ($x1+$x2)/2; $x1p = ($x1+$x2)/2;
$y1p = ($y1+$y2)/2; $y1p = ($y1+$y2)/2;
$v1p = ($v1+$v2)/2; $v1p = ($v1+$v2)/2;
} }
   
if( $dv2 == 1 ) { if( $dv2 == 1 ) {
list($x2p,$y2p,$v2p) = $this->interp2($x2,$y2,$x3,$y3,$v2,$v3); list($x2p,$y2p,$v2p) = $this->interp2($x2,$y2,$x3,$y3,$v2,$v3);
$fcnt++; $fcnt++;
} }
else { else {
$x2p = ($x2+$x3)/2; $x2p = ($x2+$x3)/2;
$y2p = ($y2+$y3)/2; $y2p = ($y2+$y3)/2;
$v2p = ($v2+$v3)/2; $v2p = ($v2+$v3)/2;
} }
   
if( $dv3 == 1 ) { if( $dv3 == 1 ) {
list($x3p,$y3p,$v3p) = $this->interp2($x3,$y3,$x1,$y1,$v3,$v1); list($x3p,$y3p,$v3p) = $this->interp2($x3,$y3,$x1,$y1,$v3,$v1);
$fcnt++; $fcnt++;
} }
else { else {
$x3p = ($x3+$x1)/2; $x3p = ($x3+$x1)/2;
$y3p = ($y3+$y1)/2; $y3p = ($y3+$y1)/2;
$v3p = ($v3+$v1)/2; $v3p = ($v3+$v1)/2;
} }
   
if( $fcnt == 2 && if( $fcnt == 2 &&
((abs($v1p-$v2p) < $eps && $dv1 ==1 && $dv2==1 ) || ((abs($v1p-$v2p) < $eps && $dv1 ==1 && $dv2==1 ) ||
(abs($v1p-$v3p) < $eps && $dv1 ==1 && $dv3==1 ) || (abs($v1p-$v3p) < $eps && $dv1 ==1 && $dv3==1 ) ||
(abs($v2p-$v3p) < $eps && $dv2 ==1 && $dv3==1 )) ) { (abs($v2p-$v3p) < $eps && $dv2 ==1 && $dv3==1 )) ) {
   
// This means that the contour line crosses exactly two sides // This means that the contour line crosses exactly two sides
// and that the values of each vertice is such that only this // and that the values of each vertice is such that only this
// contour line will cross this section. // contour line will cross this section.
// We can now be smart. The cotour line will simply divide the // We can now be smart. The cotour line will simply divide the
// area in two polygons that we can fill and then return. There is no // area in two polygons that we can fill and then return. There is no
// need to recurse. // need to recurse.
// First find out which two sides the contour is crossing // First find out which two sides the contour is crossing
if( abs($v1p-$v2p) < $eps ) { if( abs($v1p-$v2p) < $eps ) {
$p4 = array($x1,$y1,$x1p,$y1p,$x2p,$y2p,$x3,$y3,$x1,$y1); $p4 = array($x1,$y1,$x1p,$y1p,$x2p,$y2p,$x3,$y3,$x1,$y1);
$color4 = $this->GetColor($v1); $color4 = $this->GetColor($v1);
$p3 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p); $p3 = array($x1p,$y1p,$x2,$y2,$x2p,$y2p,$x1p,$y1p);
$color3 = $this->GetColor($v2); $color3 = $this->GetColor($v2);
   
$p = array($x1p,$y1p,$x2p,$y2p); $p = array($x1p,$y1p,$x2p,$y2p);
$color = $this->GetColor($v1p); $color = $this->GetColor($v1p);
$v = $v1p; $v = $v1p;
} }
elseif( abs($v1p-$v3p) < $eps ) { elseif( abs($v1p-$v3p) < $eps ) {
$p4 = array($x1p,$y1p,$x2,$y2,$x3,$y3,$x3p,$y3p,$x1p,$y1p); $p4 = array($x1p,$y1p,$x2,$y2,$x3,$y3,$x3p,$y3p,$x1p,$y1p);
$color4 = $this->GetColor($v2); $color4 = $this->GetColor($v2);
$p3 = array($x1,$y1,$x1p,$y1p,$x3p,$y3p,$x1,$y1); $p3 = array($x1,$y1,$x1p,$y1p,$x3p,$y3p,$x1,$y1);
$color3 = $this->GetColor($v1); $color3 = $this->GetColor($v1);
   
$p = array($x1p,$y1p,$x3p,$y3p); $p = array($x1p,$y1p,$x3p,$y3p);
$color = $this->GetColor($v1p); $color = $this->GetColor($v1p);
$v = $v1p; $v = $v1p;
} }
else { else {
$p4 = array($x1,$y1,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x1,$y1); $p4 = array($x1,$y1,$x2,$y2,$x2p,$y2p,$x3p,$y3p,$x1,$y1);
$color4 = $this->GetColor($v2); $color4 = $this->GetColor($v2);
   
$p3 = array($x3p,$y3p,$x2p,$y2p,$x3,$y3,$x3p,$y3p); $p3 = array($x3p,$y3p,$x2p,$y2p,$x3,$y3,$x3p,$y3p);
$color3 = $this->GetColor($v3); $color3 = $this->GetColor($v3);
   
$p = array($x3p,$y3p,$x2p,$y2p); $p = array($x3p,$y3p,$x2p,$y2p);
$color = $this->GetColor($v3p); $color = $this->GetColor($v3p);
$v = $v3p; $v = $v3p;
} }
$this->FillPolygon($color4,$p4); $this->FillPolygon($color4,$p4);
$this->FillPolygon($color3,$p3); $this->FillPolygon($color3,$p3);
   
if( $this->showcontlines ) { if( $this->showcontlines ) {
if( $this->dofill ) { if( $this->dofill ) {
$this->shape->SetColor($this->contlinecolor); $this->shape->SetColor($this->contlinecolor);
} }
else { else {
$this->shape->SetColor($color); $this->shape->SetColor($color);
} }
$this->shape->Line($p[0],$p[1],$p[2],$p[3]); $this->shape->Line($p[0],$p[1],$p[2],$p[3]);
} }
if( $this->showlabels ) { if( $this->showlabels ) {
$this->putLabel( ($p[0]+$p[2])/2, ($p[1]+$p[3])/2, $p[2], $p[3], $v); $this->putLabel( ($p[0]+$p[2])/2, ($p[1]+$p[3])/2, $p[2], $p[3], $v);
} }
} }
else { else {
$this->TriFill($v1, $v1p, $v3p, $x1, $y1, $x1p, $y1p, $x3p, $y3p, $depth+1); $this->TriFill($v1, $v1p, $v3p, $x1, $y1, $x1p, $y1p, $x3p, $y3p, $depth+1);
$this->TriFill($v1p, $v2, $v2p, $x1p, $y1p, $x2, $y2, $x2p, $y2p, $depth+1); $this->TriFill($v1p, $v2, $v2p, $x1p, $y1p, $x2, $y2, $x2p, $y2p, $depth+1);
$this->TriFill($v3p, $v1p, $v2p, $x3p, $y3p, $x1p, $y1p, $x2p, $y2p, $depth+1); $this->TriFill($v3p, $v1p, $v2p, $x3p, $y3p, $x1p, $y1p, $x2p, $y2p, $depth+1);
$this->TriFill($v3p, $v2p, $v3, $x3p, $y3p, $x2p, $y2p, $x3, $y3, $depth+1); $this->TriFill($v3p, $v2p, $v3, $x3p, $y3p, $x2p, $y2p, $x3, $y3, $depth+1);
} }
} }
} }
} }
   
function Fill($v1,$v2,$v3,$maxdepth) { function Fill($v1,$v2,$v3,$maxdepth) {
$x1=0; $y1=1; $x1=0; $y1=1;
$x2=1; $y2=0; $x2=1; $y2=0;
$x3=1; $y3=1; $x3=1; $y3=1;
self::$maxdepth = $maxdepth; self::$maxdepth = $maxdepth;
$this->TriFill($v1, $v2, $v3, $x1, $y1, $x2, $y2, $x3, $y3, 0); $this->TriFill($v1, $v2, $v3, $x1, $y1, $x2, $y2, $x3, $y3, 0);
} }
   
function Fillmesh($meshdata,$maxdepth,$method='tri') { function Fillmesh($meshdata,$maxdepth,$method='tri') {
$nx = count($meshdata[0]); $nx = count($meshdata[0]);
$ny = count($meshdata); $ny = count($meshdata);
self::$maxdepth = $maxdepth; self::$maxdepth = $maxdepth;
for( $x=0; $x < $nx-1; ++$x ) { for( $x=0; $x < $nx-1; ++$x ) {
for( $y=0; $y < $ny-1; ++$y ) { for( $y=0; $y < $ny-1; ++$y ) {
$v1 = $meshdata[$y][$x]; $v1 = $meshdata[$y][$x];
$v2 = $meshdata[$y][$x+1]; $v2 = $meshdata[$y][$x+1];
$v3 = $meshdata[$y+1][$x+1]; $v3 = $meshdata[$y+1][$x+1];
$v4 = $meshdata[$y+1][$x]; $v4 = $meshdata[$y+1][$x];
   
if( $method == 'tri' ) { if( $method == 'tri' ) {
// Fill upper and lower triangle // Fill upper and lower triangle
$this->TriFill($v4, $v1, $v2, $x, $y+1, $x, $y, $x+1, $y, 0); $this->TriFill($v4, $v1, $v2, $x, $y+1, $x, $y, $x+1, $y, 0);
$this->TriFill($v4, $v2, $v3, $x, $y+1, $x+1, $y, $x+1, $y+1, 0); $this->TriFill($v4, $v2, $v3, $x, $y+1, $x+1, $y, $x+1, $y+1, 0);
} }
else { else {
$this->RectFill($v4, $v1, $v2, $v3, $x, $y+1, $x, $y, $x+1, $y, $x+1, $y+1, 0); $this->RectFill($v4, $v1, $v2, $v3, $x, $y+1, $x, $y, $x+1, $y, $x+1, $y+1, 0);
} }
} }
} }
if( $this->showlabels ) { if( $this->showlabels ) {
$this->strokeLabels(); $this->strokeLabels();
} }
} }
} }
   
$meshdata = array( $meshdata = array(
array (12,12,10,10), array (12,12,10,10),
array (10,10,8,14), array (10,10,8,14),
array (7,7,13,17), array (7,7,13,17),
array (4,5,8,12), array (4,5,8,12),
array (10,8,7,8)); array (10,8,7,8));
   
$tt = new SingleTestTriangle(400,400,count($meshdata[0])-1,count($meshdata)-1); $tt = new SingleTestTriangle(400,400,count($meshdata[0])-1,count($meshdata)-1);
$tt->SetContours(array(4.7, 6.0, 7.2, 8.6, 9.9, 11.2, 12.5, 13.8, 15.1, 16.4)); $tt->SetContours(array(4.7, 6.0, 7.2, 8.6, 9.9, 11.2, 12.5, 13.8, 15.1, 16.4));
$tt->SetFilled(true); $tt->SetFilled(true);
   
//$tt->ShowTriangulation(true); //$tt->ShowTriangulation(true);
$tt->ShowLines(true); $tt->ShowLines(true);
   
//$tt->ShowLabels(true); //$tt->ShowLabels(true);
$tt->Fillmesh($meshdata, 8, 'rect'); $tt->Fillmesh($meshdata, 8, 'rect');
   
//$tt->Fill(4.0,3.0,7.0, 4); //$tt->Fill(4.0,3.0,7.0, 4);
//$tt->Fill(7,4,1,5); //$tt->Fill(7,4,1,5);
//$tt->Fill(1,7,4,5); //$tt->Fill(1,7,4,5);
   
$tt->Stroke(); $tt->Stroke();
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: GD_IMAGE.INC.PHP // File: GD_IMAGE.INC.PHP
// Description: PHP Graph Plotting library. Low level image drawing routines // Description: PHP Graph Plotting library. Low level image drawing routines
// Created: 2001-01-08, refactored 2008-03-29 // Created: 2001-01-08, refactored 2008-03-29
// Ver: $Id: gd_image.inc.php 1904 2009-10-06 18:00:06Z ljp $ // Ver: $Id: gd_image.inc.php 1904 2009-10-06 18:00:06Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
require_once 'jpgraph_rgb.inc.php'; require_once 'jpgraph_rgb.inc.php';
require_once 'jpgraph_ttf.inc.php'; require_once 'jpgraph_ttf.inc.php';
   
// Line styles // Line styles
define('LINESTYLE_SOLID',1); define('LINESTYLE_SOLID',1);
define('LINESTYLE_DOTTED',2); define('LINESTYLE_DOTTED',2);
define('LINESTYLE_DASHED',3); define('LINESTYLE_DASHED',3);
define('LINESTYLE_LONGDASH',4); define('LINESTYLE_LONGDASH',4);
   
// The DEFAULT_GFORMAT sets the default graphic encoding format, i.e. // The DEFAULT_GFORMAT sets the default graphic encoding format, i.e.
// PNG, JPG or GIF depending on what is installed on the target system // PNG, JPG or GIF depending on what is installed on the target system
// in that order. // in that order.
if( !DEFINED("DEFAULT_GFORMAT") ) { if( !DEFINED("DEFAULT_GFORMAT") ) {
define("DEFAULT_GFORMAT","auto"); define("DEFAULT_GFORMAT","auto");
} }
   
//======================================================================== //========================================================================
// CLASS Image // CLASS Image
// Description: The very coor image drawing class that encapsulates all // Description: The very coor image drawing class that encapsulates all
// calls to the GD library // calls to the GD library
// Note: The class used by the library is the decendant // Note: The class used by the library is the decendant
// class RotImage which extends the Image class with transparent // class RotImage which extends the Image class with transparent
// rotation. // rotation.
//========================================================================= //=========================================================================
class Image { class Image {
public $left_margin=30,$right_margin=30,$top_margin=20,$bottom_margin=30; public $left_margin=30,$right_margin=30,$top_margin=20,$bottom_margin=30;
public $img=null; public $img=null;
public $plotwidth=0,$plotheight=0; public $plotwidth=0,$plotheight=0;
public $width=0, $height=0; public $width=0, $height=0;
public $rgb=null; public $rgb=null;
public $current_color,$current_color_name; public $current_color,$current_color_name;
public $line_weight=1, $line_style=LINESTYLE_SOLID; public $line_weight=1, $line_style=LINESTYLE_SOLID;
public $img_format; public $img_format;
public $ttf=null; public $ttf=null;
protected $expired=true; protected $expired=true;
protected $lastx=0, $lasty=0; protected $lastx=0, $lasty=0;
protected $obs_list=array(); protected $obs_list=array();
protected $font_size=12,$font_family=FF_FONT1, $font_style=FS_NORMAL; protected $font_size=12,$font_family=FF_FONT1, $font_style=FS_NORMAL;
protected $font_file=''; protected $font_file='';
protected $text_halign="left",$text_valign="bottom"; protected $text_halign="left",$text_valign="bottom";
protected $use_anti_aliasing=false; protected $use_anti_aliasing=false;
protected $quality=null; protected $quality=null;
protected $colorstack=array(),$colorstackidx=0; protected $colorstack=array(),$colorstackidx=0;
protected $canvascolor = 'white' ; protected $canvascolor = 'white' ;
protected $langconv = null ; protected $langconv = null ;
protected $iInterlace=false; protected $iInterlace=false;
protected $bbox_cache = array(); // STore the last found tetx bounding box protected $bbox_cache = array(); // STore the last found tetx bounding box
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aWidth=0,$aHeight=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) { function __construct($aWidth=0,$aHeight=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) {
$this->CreateImgCanvas($aWidth,$aHeight); $this->CreateImgCanvas($aWidth,$aHeight);
   
if( $aSetAutoMargin ) { if( $aSetAutoMargin ) {
$this->SetAutoMargin(); $this->SetAutoMargin();
} }
   
if( !$this->SetImgFormat($aFormat) ) { if( !$this->SetImgFormat($aFormat) ) {
JpGraphError::RaiseL(25081,$aFormat);//("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]"); JpGraphError::RaiseL(25081,$aFormat);//("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]");
} }
$this->ttf = new TTF(); $this->ttf = new TTF();
$this->langconv = new LanguageConv(); $this->langconv = new LanguageConv();
} }
   
// Enable interlacing in images // Enable interlacing in images
function SetInterlace($aFlg=true) { function SetInterlace($aFlg=true) {
$this->iInterlace=$aFlg; $this->iInterlace=$aFlg;
} }
   
// Should we use anti-aliasing. Note: This really slows down graphics! // Should we use anti-aliasing. Note: This really slows down graphics!
function SetAntiAliasing($aFlg=true) { function SetAntiAliasing($aFlg=true) {
$this->use_anti_aliasing = $aFlg; $this->use_anti_aliasing = $aFlg;
if( function_exists('imageantialias') ) { if( function_exists('imageantialias') ) {
imageantialias($this->img,$aFlg); imageantialias($this->img,$aFlg);
} }
else { 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.') 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() { function GetAntiAliasing() {
return $this->use_anti_aliasing ; return $this->use_anti_aliasing ;
} }
   
function CreateRawCanvas($aWidth=0,$aHeight=0) { function CreateRawCanvas($aWidth=0,$aHeight=0) {
if( $aWidth <= 1 || $aHeight <= 1 ) { 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)"); 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); $this->img = @imagecreatetruecolor($aWidth, $aHeight);
if( $this->img < 1 ) { if( $this->img < 1 ) {
JpGraphError::RaiseL(25126); JpGraphError::RaiseL(25126);
//die("Can't create truecolor image. Check that you really have GD2 library installed."); //die("Can't create truecolor image. Check that you really have GD2 library installed.");
} }
$this->SetAlphaBlending(); $this->SetAlphaBlending();
   
if( $this->iInterlace ) { if( $this->iInterlace ) {
imageinterlace($this->img,1); imageinterlace($this->img,1);
} }
if( $this->rgb != null ) { if( $this->rgb != null ) {
$this->rgb->img = $this->img ; $this->rgb->img = $this->img ;
} }
else { else {
$this->rgb = new RGB($this->img); $this->rgb = new RGB($this->img);
} }
} }
   
function CloneCanvasH() { function CloneCanvasH() {
$oldimage = $this->img; $oldimage = $this->img;
$this->CreateRawCanvas($this->width,$this->height); $this->CreateRawCanvas($this->width,$this->height);
imagecopy($this->img,$oldimage,0,0,0,0,$this->width,$this->height); imagecopy($this->img,$oldimage,0,0,0,0,$this->width,$this->height);
return $oldimage; return $oldimage;
} }
   
function CreateImgCanvas($aWidth=0,$aHeight=0) { function CreateImgCanvas($aWidth=0,$aHeight=0) {
   
$old = array($this->img,$this->width,$this->height); $old = array($this->img,$this->width,$this->height);
   
$aWidth = round($aWidth); $aWidth = round($aWidth);
$aHeight = round($aHeight); $aHeight = round($aHeight);
   
$this->width=$aWidth; $this->width=$aWidth;
$this->height=$aHeight; $this->height=$aHeight;
   
   
if( $aWidth==0 || $aHeight==0 ) { if( $aWidth==0 || $aHeight==0 ) {
// We will set the final size later. // We will set the final size later.
// Note: The size must be specified before any other // Note: The size must be specified before any other
// img routines that stroke anything are called. // img routines that stroke anything are called.
$this->img = null; $this->img = null;
$this->rgb = null; $this->rgb = null;
return $old; return $old;
} }
   
$this->CreateRawCanvas($aWidth,$aHeight); $this->CreateRawCanvas($aWidth,$aHeight);
// Set canvas color (will also be the background color for a // Set canvas color (will also be the background color for a
// a pallett image // a pallett image
$this->SetColor($this->canvascolor); $this->SetColor($this->canvascolor);
$this->FilledRectangle(0,0,$aWidth-1,$aHeight-1); $this->FilledRectangle(0,0,$aWidth-1,$aHeight-1);
   
return $old ; return $old ;
} }
   
function CopyCanvasH($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY,$aWidth,$aHeight,$aw=-1,$ah=-1) { function CopyCanvasH($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY,$aWidth,$aHeight,$aw=-1,$ah=-1) {
if( $aw === -1 ) { if( $aw === -1 ) {
$aw = $aWidth; $aw = $aWidth;
$ah = $aHeight; $ah = $aHeight;
$f = 'imagecopyresized'; $f = 'imagecopyresized';
} }
else { else {
$f = 'imagecopyresampled'; $f = 'imagecopyresampled';
} }
$f($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY, $aWidth,$aHeight,$aw,$ah); $f($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY, $aWidth,$aHeight,$aw,$ah);
} }
   
function Copy($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1) { 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); $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) { function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) {
if( $aMix == 100 ) { if( $aMix == 100 ) {
$this->CopyCanvasH($this->img,$fromImg, $this->CopyCanvasH($this->img,$fromImg,
$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight); $toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight);
} }
else { else {
if( ($fromWidth != -1 && ($fromWidth != $toWidth)) || ($fromHeight != -1 && ($fromHeight != $fromHeight)) ) { if( ($fromWidth != -1 && ($fromWidth != $toWidth)) || ($fromHeight != -1 && ($fromHeight != $fromHeight)) ) {
// Create a new canvas that will hold the re-scaled original from image // Create a new canvas that will hold the re-scaled original from image
if( $toWidth <= 1 || $toHeight <= 1 ) { if( $toWidth <= 1 || $toHeight <= 1 ) {
JpGraphError::RaiseL(25083);//('Illegal image size when copying image. Size for copied to image is 1 pixel or less.'); JpGraphError::RaiseL(25083);//('Illegal image size when copying image. Size for copied to image is 1 pixel or less.');
} }
   
$tmpimg = @imagecreatetruecolor($toWidth, $toHeight); $tmpimg = @imagecreatetruecolor($toWidth, $toHeight);
   
if( $tmpimg < 1 ) { if( $tmpimg < 1 ) {
JpGraphError::RaiseL(25084);//('Failed to create temporary GD canvas. Out of memory ?'); JpGraphError::RaiseL(25084);//('Failed to create temporary GD canvas. Out of memory ?');
} }
$this->CopyCanvasH($tmpimg,$fromImg,0,0,0,0, $this->CopyCanvasH($tmpimg,$fromImg,0,0,0,0,
$toWidth,$toHeight,$fromWidth,$fromHeight); $toWidth,$toHeight,$fromWidth,$fromHeight);
$fromImg = $tmpimg; $fromImg = $tmpimg;
} }
imagecopymerge($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$aMix); imagecopymerge($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$aMix);
} }
} }
   
static function GetWidth($aImg=null) { static function GetWidth($aImg=null) {
if( $aImg === null ) { if( $aImg === null ) {
$aImg = $this->img; $aImg = $this->img;
} }
return imagesx($aImg); return imagesx($aImg);
} }
   
static function GetHeight($aImg=null) { static function GetHeight($aImg=null) {
if( $aImg === null ) { if( $aImg === null ) {
$aImg = $this->img; $aImg = $this->img;
} }
return imagesy($aImg); return imagesy($aImg);
} }
   
static function CreateFromString($aStr) { static function CreateFromString($aStr) {
$img = imagecreatefromstring($aStr); $img = imagecreatefromstring($aStr);
if( $img === false ) { if( $img === false ) {
JpGraphError::RaiseL(25085); 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.'); //('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; return $img;
} }
   
function SetCanvasH($aHdl) { function SetCanvasH($aHdl) {
$this->img = $aHdl; $this->img = $aHdl;
$this->rgb->img = $aHdl; $this->rgb->img = $aHdl;
} }
   
function SetCanvasColor($aColor) { function SetCanvasColor($aColor) {
$this->canvascolor = $aColor ; $this->canvascolor = $aColor ;
} }
   
function SetAlphaBlending($aFlg=true) { function SetAlphaBlending($aFlg=true) {
ImageAlphaBlending($this->img,$aFlg); ImageAlphaBlending($this->img,$aFlg);
} }
   
function SetAutoMargin() { function SetAutoMargin() {
$min_bm=5; $min_bm=5;
$lm = min(40,$this->width/7); $lm = min(40,$this->width/7);
$rm = min(20,$this->width/10); $rm = min(20,$this->width/10);
$tm = max(5,$this->height/7); $tm = max(5,$this->height/7);
$bm = max($min_bm,$this->height/6); $bm = max($min_bm,$this->height/6);
$this->SetMargin($lm,$rm,$tm,$bm); $this->SetMargin($lm,$rm,$tm,$bm);
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
function SetFont($family,$style=FS_NORMAL,$size=10) { function SetFont($family,$style=FS_NORMAL,$size=10) {
$this->font_family=$family; $this->font_family=$family;
$this->font_style=$style; $this->font_style=$style;
$this->font_size=$size; $this->font_size=$size;
$this->font_file=''; $this->font_file='';
if( ($this->font_family==FF_FONT1 || $this->font_family==FF_FONT2) && $this->font_style==FS_BOLD ){ if( ($this->font_family==FF_FONT1 || $this->font_family==FF_FONT2) && $this->font_style==FS_BOLD ){
++$this->font_family; ++$this->font_family;
} }
if( $this->font_family > FF_FONT2+1 ) { // A TTF font so get the font file if( $this->font_family > FF_FONT2+1 ) { // A TTF font so get the font file
   
// Check that this PHP has support for TTF fonts // Check that this PHP has support for TTF fonts
if( !function_exists('imagettfbbox') ) { 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.'); JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.');
} }
$this->font_file = $this->ttf->File($this->font_family,$this->font_style); $this->font_file = $this->ttf->File($this->font_family,$this->font_style);
} }
} }
   
// Get the specific height for a text string // Get the specific height for a text string
function GetTextHeight($txt="",$angle=0) { function GetTextHeight($txt="",$angle=0) {
$tmp = preg_split('/\n/',$txt); $tmp = preg_split('/\n/',$txt);
$n = count($tmp); $n = count($tmp);
$m=0; $m=0;
for($i=0; $i< $n; ++$i) { for($i=0; $i< $n; ++$i) {
$m = max($m,strlen($tmp[$i])); $m = max($m,strlen($tmp[$i]));
} }
   
if( $this->font_family <= FF_FONT2+1 ) { if( $this->font_family <= FF_FONT2+1 ) {
if( $angle==0 ) { if( $angle==0 ) {
$h = imagefontheight($this->font_family); $h = imagefontheight($this->font_family);
if( $h === false ) { if( $h === false ) {
JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
} }
   
return $n*$h; return $n*$h;
} }
else { else {
$w = @imagefontwidth($this->font_family); $w = @imagefontwidth($this->font_family);
if( $w === false ) { if( $w === false ) {
JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
} }
   
return $m*$w; return $m*$w;
} }
} }
else { else {
$bbox = $this->GetTTFBBox($txt,$angle); $bbox = $this->GetTTFBBox($txt,$angle);
return $bbox[1]-$bbox[5]+1; return $bbox[1]-$bbox[5]+1;
} }
} }
   
// Estimate font height // Estimate font height
function GetFontHeight($angle=0) { function GetFontHeight($angle=0) {
$txt = "XOMg"; $txt = "XOMg";
return $this->GetTextHeight($txt,$angle); return $this->GetTextHeight($txt,$angle);
} }
   
// Approximate font width with width of letter "O" // Approximate font width with width of letter "O"
function GetFontWidth($angle=0) { function GetFontWidth($angle=0) {
$txt = 'O'; $txt = 'O';
return $this->GetTextWidth($txt,$angle); return $this->GetTextWidth($txt,$angle);
} }
   
// Get actual width of text in absolute pixels. Note that the width is the // 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 // texts projected with onto the x-axis. Call with angle=0 to get the true
// etxt width. // etxt width.
function GetTextWidth($txt,$angle=0) { function GetTextWidth($txt,$angle=0) {
   
$tmp = preg_split('/\n/',$txt); $tmp = preg_split('/\n/',$txt);
$n = count($tmp); $n = count($tmp);
if( $this->font_family <= FF_FONT2+1 ) { if( $this->font_family <= FF_FONT2+1 ) {
   
$m=0; $m=0;
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$l=strlen($tmp[$i]); $l=strlen($tmp[$i]);
if( $l > $m ) { if( $l > $m ) {
$m = $l; $m = $l;
} }
} }
   
if( $angle==0 ) { if( $angle==0 ) {
$w = @imagefontwidth($this->font_family); $w = @imagefontwidth($this->font_family);
if( $w === false ) { if( $w === false ) {
JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.'); JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
} }
return $m*$w; return $m*$w;
} }
else { else {
// 90 degrees internal so height becomes width // 90 degrees internal so height becomes width
$h = @imagefontheight($this->font_family); $h = @imagefontheight($this->font_family);
if( $h === false ) { if( $h === false ) {
JpGraphError::RaiseL(25089);//('You have a misconfigured GD font support. The call to imagefontheight() fails.'); JpGraphError::RaiseL(25089);//('You have a misconfigured GD font support. The call to imagefontheight() fails.');
} }
return $n*$h; return $n*$h;
} }
} }
else { else {
// For TTF fonts we must walk through a lines and find the // For TTF fonts we must walk through a lines and find the
// widest one which we use as the width of the multi-line // widest one which we use as the width of the multi-line
// paragraph // paragraph
$m=0; $m=0;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$bbox = $this->GetTTFBBox($tmp[$i],$angle); $bbox = $this->GetTTFBBox($tmp[$i],$angle);
$mm = $bbox[2] - $bbox[0]; $mm = $bbox[2] - $bbox[0];
if( $mm > $m ) if( $mm > $m )
$m = $mm; $m = $mm;
} }
return $m; return $m;
} }
} }
   
   
// Draw text with a box around it // Draw text with a box around it
function StrokeBoxedText($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black", function StrokeBoxedText($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black",
$shadowcolor=false,$paragraph_align="left", $shadowcolor=false,$paragraph_align="left",
$xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) { $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) {
   
$oldx = $this->lastx; $oldx = $this->lastx;
$oldy = $this->lasty; $oldy = $this->lasty;
   
if( !is_numeric($dir) ) { if( !is_numeric($dir) ) {
if( $dir=="h" ) $dir=0; if( $dir=="h" ) $dir=0;
elseif( $dir=="v" ) $dir=90; elseif( $dir=="v" ) $dir=90;
else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]"); 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) { if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) {
$width=$this->GetTextWidth($txt,$dir) ; $width=$this->GetTextWidth($txt,$dir) ;
$height=$this->GetTextHeight($txt,$dir) ; $height=$this->GetTextHeight($txt,$dir) ;
} }
else { else {
$width=$this->GetBBoxWidth($txt,$dir) ; $width=$this->GetBBoxWidth($txt,$dir) ;
$height=$this->GetBBoxHeight($txt,$dir) ; $height=$this->GetBBoxHeight($txt,$dir) ;
} }
   
$height += 2*$ymarg; $height += 2*$ymarg;
$width += 2*$xmarg; $width += 2*$xmarg;
   
if( $this->text_halign=="right" ) $x -= $width; if( $this->text_halign=="right" ) $x -= $width;
elseif( $this->text_halign=="center" ) $x -= $width/2; elseif( $this->text_halign=="center" ) $x -= $width/2;
   
if( $this->text_valign=="bottom" ) $y -= $height; if( $this->text_valign=="bottom" ) $y -= $height;
elseif( $this->text_valign=="center" ) $y -= $height/2; elseif( $this->text_valign=="center" ) $y -= $height/2;
   
$olda = $this->SetAngle(0); $olda = $this->SetAngle(0);
   
if( $shadowcolor ) { if( $shadowcolor ) {
$this->PushColor($shadowcolor); $this->PushColor($shadowcolor);
$this->FilledRoundedRectangle($x-$xmarg+$dropwidth,$y-$ymarg+$dropwidth, $this->FilledRoundedRectangle($x-$xmarg+$dropwidth,$y-$ymarg+$dropwidth,
$x+$width+$dropwidth,$y+$height-$ymarg+$dropwidth, $x+$width+$dropwidth,$y+$height-$ymarg+$dropwidth,
$cornerradius); $cornerradius);
$this->PopColor(); $this->PopColor();
$this->PushColor($fcolor); $this->PushColor($fcolor);
$this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg, $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,
$x+$width,$y+$height-$ymarg, $x+$width,$y+$height-$ymarg,
$cornerradius); $cornerradius);
$this->PopColor(); $this->PopColor();
$this->PushColor($bcolor); $this->PushColor($bcolor);
$this->RoundedRectangle($x-$xmarg,$y-$ymarg, $this->RoundedRectangle($x-$xmarg,$y-$ymarg,
$x+$width,$y+$height-$ymarg,$cornerradius); $x+$width,$y+$height-$ymarg,$cornerradius);
$this->PopColor(); $this->PopColor();
} }
else { else {
if( $fcolor ) { if( $fcolor ) {
$oc=$this->current_color; $oc=$this->current_color;
$this->SetColor($fcolor); $this->SetColor($fcolor);
$this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius); $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius);
$this->current_color=$oc; $this->current_color=$oc;
} }
if( $bcolor ) { if( $bcolor ) {
$oc=$this->current_color; $oc=$this->current_color;
$this->SetColor($bcolor); $this->SetColor($bcolor);
$this->RoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius); $this->RoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius);
$this->current_color=$oc; $this->current_color=$oc;
} }
} }
   
$h=$this->text_halign; $h=$this->text_halign;
$v=$this->text_valign; $v=$this->text_valign;
$this->SetTextAlign("left","top"); $this->SetTextAlign("left","top");
   
$debug=false; $debug=false;
$this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug); $this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug);
   
$bb = array($x-$xmarg,$y+$height-$ymarg,$x+$width,$y+$height-$ymarg, $bb = array($x-$xmarg,$y+$height-$ymarg,$x+$width,$y+$height-$ymarg,
$x+$width,$y-$ymarg,$x-$xmarg,$y-$ymarg); $x+$width,$y-$ymarg,$x-$xmarg,$y-$ymarg);
$this->SetTextAlign($h,$v); $this->SetTextAlign($h,$v);
   
$this->SetAngle($olda); $this->SetAngle($olda);
$this->lastx = $oldx; $this->lastx = $oldx;
$this->lasty = $oldy; $this->lasty = $oldy;
   
return $bb; return $bb;
} }
   
// Draw text with a box around it. This time the box will be rotated // 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 // with the text. The previous method will just make a larger enough non-rotated
// box to hold the text inside. // box to hold the text inside.
function StrokeBoxedText2($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black", function StrokeBoxedText2($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black",
$shadowcolor=false,$paragraph_align="left", $shadowcolor=false,$paragraph_align="left",
$xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) { $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) {
   
// This version of boxed text will stroke a rotated box round the text // This version of boxed text will stroke a rotated box round the text
// thta will follow the angle of the text. // thta will follow the angle of the text.
// This has two implications: // This has two implications:
// 1) This methos will only support TTF fonts // 1) This methos will only support TTF fonts
// 2) The only two alignment that makes sense are centered or baselined // 2) The only two alignment that makes sense are centered or baselined
   
if( $this->font_family <= FF_FONT2+1 ) { if( $this->font_family <= FF_FONT2+1 ) {
JpGraphError::RaiseL(25131);//StrokeBoxedText2() Only support TTF fonts and not built in bitmap fonts JpGraphError::RaiseL(25131);//StrokeBoxedText2() Only support TTF fonts and not built in bitmap fonts
} }
   
$oldx = $this->lastx; $oldx = $this->lastx;
$oldy = $this->lasty; $oldy = $this->lasty;
$dir = $this->NormAngle($dir); $dir = $this->NormAngle($dir);
   
if( !is_numeric($dir) ) { if( !is_numeric($dir) ) {
if( $dir=="h" ) $dir=0; if( $dir=="h" ) $dir=0;
elseif( $dir=="v" ) $dir=90; elseif( $dir=="v" ) $dir=90;
else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]"); else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
} }
   
$width=$this->GetTextWidth($txt,0) + 2*$xmarg; $width=$this->GetTextWidth($txt,0) + 2*$xmarg;
$height=$this->GetTextHeight($txt,0) + 2*$ymarg ; $height=$this->GetTextHeight($txt,0) + 2*$ymarg ;
$rect_width=$this->GetBBoxWidth($txt,$dir) ; $rect_width=$this->GetBBoxWidth($txt,$dir) ;
$rect_height=$this->GetBBoxHeight($txt,$dir) ; $rect_height=$this->GetBBoxHeight($txt,$dir) ;
   
$baseline_offset = $this->bbox_cache[1]-1; $baseline_offset = $this->bbox_cache[1]-1;
   
if( $this->text_halign=="center" ) { if( $this->text_halign=="center" ) {
if( $dir >= 0 && $dir <= 90 ) { if( $dir >= 0 && $dir <= 90 ) {
   
$x -= $rect_width/2; $x -= $rect_width/2;
$x += sin($dir*M_PI/180)*$height; $x += sin($dir*M_PI/180)*$height;
$y += $rect_height/2; $y += $rect_height/2;
   
} elseif( $dir >= 270 && $dir <= 360 ) { } elseif( $dir >= 270 && $dir <= 360 ) {
   
$x -= $rect_width/2; $x -= $rect_width/2;
$y -= $rect_height/2; $y -= $rect_height/2;
$y += cos($dir*M_PI/180)*$height; $y += cos($dir*M_PI/180)*$height;
   
} elseif( $dir >= 90 && $dir <= 180 ) { } elseif( $dir >= 90 && $dir <= 180 ) {
   
$x += $rect_width/2; $x += $rect_width/2;
$y += $rect_height/2; $y += $rect_height/2;
$y += cos($dir*M_PI/180)*$height; $y += cos($dir*M_PI/180)*$height;
   
} }
else { else {
// $dir > 180 && $dir < 270 // $dir > 180 && $dir < 270
$x += $rect_width/2; $x += $rect_width/2;
$x += sin($dir*M_PI/180)*$height; $x += sin($dir*M_PI/180)*$height;
$y -= $rect_height/2; $y -= $rect_height/2;
} }
} }
   
// Rotate the box around this point // Rotate the box around this point
$this->SetCenter($x,$y); $this->SetCenter($x,$y);
$olda = $this->SetAngle(-$dir); $olda = $this->SetAngle(-$dir);
   
// We need to use adjusted coordinats for the box to be able // 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 // 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 // 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 // point where the text will rotate and we cannot change this since
// that is where the GD/GreeType will rotate the text // that is where the GD/GreeType will rotate the text
   
   
// For smaller <14pt font we need to do some additional // For smaller <14pt font we need to do some additional
// adjustments to make it look good // adjustments to make it look good
if( $this->font_size < 14 ) { if( $this->font_size < 14 ) {
$x -= 2; $x -= 2;
$y += 2; $y += 2;
} }
else { else {
// $y += $baseline_offset; // $y += $baseline_offset;
} }
   
if( $shadowcolor ) { if( $shadowcolor ) {
$this->PushColor($shadowcolor); $this->PushColor($shadowcolor);
$this->FilledRectangle($x-$xmarg+$dropwidth,$y+$ymarg+$dropwidth-$height, $this->FilledRectangle($x-$xmarg+$dropwidth,$y+$ymarg+$dropwidth-$height,
$x+$width+$dropwidth,$y+$ymarg+$dropwidth); $x+$width+$dropwidth,$y+$ymarg+$dropwidth);
//$cornerradius); //$cornerradius);
$this->PopColor(); $this->PopColor();
$this->PushColor($fcolor); $this->PushColor($fcolor);
$this->FilledRectangle($x-$xmarg, $y+$ymarg-$height, $this->FilledRectangle($x-$xmarg, $y+$ymarg-$height,
$x+$width, $y+$ymarg); $x+$width, $y+$ymarg);
//$cornerradius); //$cornerradius);
$this->PopColor(); $this->PopColor();
$this->PushColor($bcolor); $this->PushColor($bcolor);
$this->Rectangle($x-$xmarg,$y+$ymarg-$height, $this->Rectangle($x-$xmarg,$y+$ymarg-$height,
$x+$width,$y+$ymarg); $x+$width,$y+$ymarg);
//$cornerradius); //$cornerradius);
$this->PopColor(); $this->PopColor();
} }
else { else {
if( $fcolor ) { if( $fcolor ) {
$oc=$this->current_color; $oc=$this->current_color;
$this->SetColor($fcolor); $this->SetColor($fcolor);
$this->FilledRectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius); $this->FilledRectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius);
$this->current_color=$oc; $this->current_color=$oc;
} }
if( $bcolor ) { if( $bcolor ) {
$oc=$this->current_color; $oc=$this->current_color;
$this->SetColor($bcolor); $this->SetColor($bcolor);
$this->Rectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius); $this->Rectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius);
$this->current_color=$oc; $this->current_color=$oc;
} }
} }
   
if( $this->font_size < 14 ) { if( $this->font_size < 14 ) {
$x += 2; $x += 2;
$y -= 2; $y -= 2;
} }
else { else {
   
// Restore the original y before we stroke the text // Restore the original y before we stroke the text
// $y -= $baseline_offset; // $y -= $baseline_offset;
   
} }
   
$this->SetCenter(0,0); $this->SetCenter(0,0);
$this->SetAngle($olda); $this->SetAngle($olda);
   
$h=$this->text_halign; $h=$this->text_halign;
$v=$this->text_valign; $v=$this->text_valign;
if( $this->text_halign == 'center') { if( $this->text_halign == 'center') {
$this->SetTextAlign('center','basepoint'); $this->SetTextAlign('center','basepoint');
} }
else { else {
$this->SetTextAlign('basepoint','basepoint'); $this->SetTextAlign('basepoint','basepoint');
} }
   
$debug=false; $debug=false;
$this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug); $this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug);
   
$bb = array($x-$xmarg, $y+$height-$ymarg, $bb = array($x-$xmarg, $y+$height-$ymarg,
$x+$width, $y+$height-$ymarg, $x+$width, $y+$height-$ymarg,
$x+$width, $y-$ymarg, $x+$width, $y-$ymarg,
$x-$xmarg, $y-$ymarg); $x-$xmarg, $y-$ymarg);
   
$this->SetTextAlign($h,$v); $this->SetTextAlign($h,$v);
$this->SetAngle($olda); $this->SetAngle($olda);
   
$this->lastx = $oldx; $this->lastx = $oldx;
$this->lasty = $oldy; $this->lasty = $oldy;
   
return $bb; return $bb;
} }
   
// Set text alignment // Set text alignment
function SetTextAlign($halign,$valign="bottom") { function SetTextAlign($halign,$valign="bottom") {
$this->text_halign=$halign; $this->text_halign=$halign;
$this->text_valign=$valign; $this->text_valign=$valign;
} }
   
function _StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$aDebug=false) { function _StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$aDebug=false) {
   
if( is_numeric($dir) && $dir!=90 && $dir!=0) 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."); JpGraphError::RaiseL(25091);//(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.");
   
$h=$this->GetTextHeight($txt); $h=$this->GetTextHeight($txt);
$fh=$this->GetFontHeight(); $fh=$this->GetFontHeight();
$w=$this->GetTextWidth($txt); $w=$this->GetTextWidth($txt);
   
if( $this->text_halign=="right") { if( $this->text_halign=="right") {
$x -= $dir==0 ? $w : $h; $x -= $dir==0 ? $w : $h;
} }
elseif( $this->text_halign=="center" ) { elseif( $this->text_halign=="center" ) {
// For center we subtract 1 pixel since this makes the middle // For center we subtract 1 pixel since this makes the middle
// be prefectly in the middle // be prefectly in the middle
$x -= $dir==0 ? $w/2-1 : $h/2; $x -= $dir==0 ? $w/2-1 : $h/2;
} }
if( $this->text_valign=="top" ) { if( $this->text_valign=="top" ) {
$y += $dir==0 ? $h : $w; $y += $dir==0 ? $h : $w;
} }
elseif( $this->text_valign=="center" ) { elseif( $this->text_valign=="center" ) {
$y += $dir==0 ? $h/2 : $w/2; $y += $dir==0 ? $h/2 : $w/2;
} }
   
if( $dir==90 ) { if( $dir==90 ) {
imagestringup($this->img,$this->font_family,$x,$y,$txt,$this->current_color); 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)); $aBoundingBox = array(round($x),round($y),round($x),round($y-$w),round($x+$h),round($y-$w),round($x+$h),round($y));
if( $aDebug ) { if( $aDebug ) {
// Draw bounding box // Draw bounding box
$this->PushColor('green'); $this->PushColor('green');
$this->Polygon($aBoundingBox,true); $this->Polygon($aBoundingBox,true);
$this->PopColor(); $this->PopColor();
} }
} }
else { else {
if( preg_match('/\n/',$txt) ) { if( preg_match('/\n/',$txt) ) {
$tmp = preg_split('/\n/',$txt); $tmp = preg_split('/\n/',$txt);
for($i=0; $i < count($tmp); ++$i) { for($i=0; $i < count($tmp); ++$i) {
$w1 = $this->GetTextWidth($tmp[$i]); $w1 = $this->GetTextWidth($tmp[$i]);
if( $paragraph_align=="left" ) { if( $paragraph_align=="left" ) {
imagestring($this->img,$this->font_family,$x,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); imagestring($this->img,$this->font_family,$x,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
} }
elseif( $paragraph_align=="right" ) { elseif( $paragraph_align=="right" ) {
imagestring($this->img,$this->font_family,$x+($w-$w1),$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); imagestring($this->img,$this->font_family,$x+($w-$w1),$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
} }
else { else {
imagestring($this->img,$this->font_family,$x+$w/2-$w1/2,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color); imagestring($this->img,$this->font_family,$x+$w/2-$w1/2,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
} }
} }
} }
else { else {
//Put the text //Put the text
imagestring($this->img,$this->font_family,$x,$y-$h+1,$txt,$this->current_color); imagestring($this->img,$this->font_family,$x,$y-$h+1,$txt,$this->current_color);
} }
if( $aDebug ) { if( $aDebug ) {
// Draw the bounding rectangle and the bounding box // 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)); $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 // Draw bounding box
$this->PushColor('green'); $this->PushColor('green');
$this->Polygon($p1,true); $this->Polygon($p1,true);
$this->PopColor(); $this->PopColor();
   
} }
$aBoundingBox=array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y)); $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) { function AddTxtCR($aTxt) {
// If the user has just specified a '\n' // If the user has just specified a '\n'
// instead of '\n\t' we have to add '\r' since // instead of '\n\t' we have to add '\r' since
// the width will be too muchy otherwise since when // the width will be too muchy otherwise since when
// we print we stroke the individually lines by hand. // we print we stroke the individually lines by hand.
$e = explode("\n",$aTxt); $e = explode("\n",$aTxt);
$n = count($e); $n = count($e);
for($i=0; $i<$n; ++$i) { for($i=0; $i<$n; ++$i) {
$e[$i]=str_replace("\r","",$e[$i]); $e[$i]=str_replace("\r","",$e[$i]);
} }
return implode("\n\r",$e); return implode("\n\r",$e);
} }
   
function NormAngle($a) { function NormAngle($a) {
// Normalize angle in degrees // Normalize angle in degrees
// Normalize angle to be between 0-360 // Normalize angle to be between 0-360
while( $a > 360 ) while( $a > 360 )
$a -= 360; $a -= 360;
while( $a < -360 ) while( $a < -360 )
$a += 360; $a += 360;
if( $a < 0 ) if( $a < 0 )
$a = 360 + $a; $a = 360 + $a;
return $a; return $a;
} }
   
function imagettfbbox_fixed($size, $angle, $fontfile, $text) { function imagettfbbox_fixed($size, $angle, $fontfile, $text) {
   
   
if( ! USE_LIBRARY_IMAGETTFBBOX ) { if( ! USE_LIBRARY_IMAGETTFBBOX ) {
   
$bbox = @imagettfbbox($size, $angle, $fontfile, $text); $bbox = @imagettfbbox($size, $angle, $fontfile, $text);
if( $bbox === false ) { if( $bbox === false ) {
JpGraphError::RaiseL(25092,$this->font_file); 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."); //("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; $this->bbox_cache = $bbox;
return $bbox; return $bbox;
} }
   
// The built in imagettfbbox is buggy for angles != 0 so // The built in imagettfbbox is buggy for angles != 0 so
// we calculate this manually by getting the bounding box at // we calculate this manually by getting the bounding box at
// angle = 0 and then rotate the bounding box manually // angle = 0 and then rotate the bounding box manually
$bbox = @imagettfbbox($size, 0, $fontfile, $text); $bbox = @imagettfbbox($size, 0, $fontfile, $text);
if( $bbox === false ) { if( $bbox === false ) {
JpGraphError::RaiseL(25092,$this->font_file); 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."); //("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); $angle = $this->NormAngle($angle);
   
$a = $angle*M_PI/180; $a = $angle*M_PI/180;
$ca = cos($a); $ca = cos($a);
$sa = sin($a); $sa = sin($a);
$ret = array(); $ret = array();
   
// We always add 1 pixel to the left since the left edge of the bounding // 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 // box is sometimes coinciding with the first pixel of the text
//$bbox[0] -= 1; //$bbox[0] -= 1;
//$bbox[6] -= 1; //$bbox[6] -= 1;
// For roatated text we need to add extra width for rotated // 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 since the kerning and stroking of the TTF is not the same as for
// text at a 0 degree angle // text at a 0 degree angle
   
if( $angle > 0.001 && abs($angle-360) > 0.001 ) { if( $angle > 0.001 && abs($angle-360) > 0.001 ) {
$h = abs($bbox[7]-$bbox[1]); $h = abs($bbox[7]-$bbox[1]);
$w = abs($bbox[2]-$bbox[0]); $w = abs($bbox[2]-$bbox[0]);
   
$bbox[0] -= 2; $bbox[0] -= 2;
$bbox[6] -= 2; $bbox[6] -= 2;
// The width is underestimated so compensate for that // The width is underestimated so compensate for that
$bbox[2] += round($w*0.06); $bbox[2] += round($w*0.06);
$bbox[4] += round($w*0.06); $bbox[4] += round($w*0.06);
   
// and we also need to compensate with increased height // and we also need to compensate with increased height
$bbox[5] -= round($h*0.1); $bbox[5] -= round($h*0.1);
$bbox[7] -= round($h*0.1); $bbox[7] -= round($h*0.1);
   
if( $angle > 90 ) { if( $angle > 90 ) {
// For angles > 90 we also need to extend the height further down // For angles > 90 we also need to extend the height further down
// by the baseline since that is also one more problem // by the baseline since that is also one more problem
$bbox[1] += round($h*0.15); $bbox[1] += round($h*0.15);
$bbox[3] += round($h*0.15); $bbox[3] += round($h*0.15);
   
// and also make it slighty less height // and also make it slighty less height
$bbox[7] += round($h*0.05); $bbox[7] += round($h*0.05);
$bbox[5] += 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) // And we need to move the box slightly top the rright (from a tetx perspective)
$bbox[0] += round($w*0.02); $bbox[0] += round($w*0.02);
$bbox[6] += round($w*0.02); $bbox[6] += round($w*0.02);
   
if( $angle > 180 ) { if( $angle > 180 ) {
// And we need to move the box slightly to the left (from a text perspective) // And we need to move the box slightly to the left (from a text perspective)
$bbox[0] -= round($w*0.02); $bbox[0] -= round($w*0.02);
$bbox[6] -= round($w*0.02); $bbox[6] -= round($w*0.02);
$bbox[2] -= round($w*0.02); $bbox[2] -= round($w*0.02);
$bbox[4] -= round($w*0.02); $bbox[4] -= round($w*0.02);
   
} }
   
} }
for($i = 0; $i < 7; $i += 2) { for($i = 0; $i < 7; $i += 2) {
$ret[$i] = round($bbox[$i] * $ca + $bbox[$i+1] * $sa); $ret[$i] = round($bbox[$i] * $ca + $bbox[$i+1] * $sa);
$ret[$i+1] = round($bbox[$i+1] * $ca - $bbox[$i] * $sa); $ret[$i+1] = round($bbox[$i+1] * $ca - $bbox[$i] * $sa);
} }
$this->bbox_cache = $ret; $this->bbox_cache = $ret;
return $ret; return $ret;
} }
else { else {
$this->bbox_cache = $bbox; $this->bbox_cache = $bbox;
return $bbox; return $bbox;
} }
} }
   
// Deprecated // Deprecated
function GetTTFBBox($aTxt,$aAngle=0) { function GetTTFBBox($aTxt,$aAngle=0) {
$bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt); $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt);
return $bbox; return $bbox;
} }
   
function GetBBoxTTF($aTxt,$aAngle=0) { function GetBBoxTTF($aTxt,$aAngle=0) {
// Normalize the bounding box to become a minimum // Normalize the bounding box to become a minimum
// enscribing rectangle // enscribing rectangle
   
$aTxt = $this->AddTxtCR($aTxt); $aTxt = $this->AddTxtCR($aTxt);
   
if( !is_readable($this->font_file) ) { if( !is_readable($this->font_file) ) {
JpGraphError::RaiseL(25093,$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.'); //('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); $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt);
   
if( $aAngle==0 ) return $bbox; if( $aAngle==0 ) return $bbox;
   
if( $aAngle >= 0 ) { if( $aAngle >= 0 ) {
if( $aAngle <= 90 ) { //<=0 if( $aAngle <= 90 ) { //<=0
$bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1], $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1],
$bbox[2],$bbox[5],$bbox[6],$bbox[5]); $bbox[2],$bbox[5],$bbox[6],$bbox[5]);
} }
elseif( $aAngle <= 180 ) { //<= 2 elseif( $aAngle <= 180 ) { //<= 2
$bbox = array($bbox[4],$bbox[7],$bbox[0],$bbox[7], $bbox = array($bbox[4],$bbox[7],$bbox[0],$bbox[7],
$bbox[0],$bbox[3],$bbox[4],$bbox[3]); $bbox[0],$bbox[3],$bbox[4],$bbox[3]);
} }
elseif( $aAngle <= 270 ) { //<= 3 elseif( $aAngle <= 270 ) { //<= 3
$bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5], $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5],
$bbox[6],$bbox[1],$bbox[2],$bbox[1]); $bbox[6],$bbox[1],$bbox[2],$bbox[1]);
} }
else { else {
$bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
$bbox[4],$bbox[7],$bbox[0],$bbox[7]); $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
} }
} }
elseif( $aAngle < 0 ) { elseif( $aAngle < 0 ) {
if( $aAngle <= -270 ) { // <= -3 if( $aAngle <= -270 ) { // <= -3
$bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1], $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1],
$bbox[2],$bbox[5],$bbox[6],$bbox[5]); $bbox[2],$bbox[5],$bbox[6],$bbox[5]);
} }
elseif( $aAngle <= -180 ) { // <= -2 elseif( $aAngle <= -180 ) { // <= -2
$bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
$bbox[4],$bbox[7],$bbox[0],$bbox[7]); $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
} }
elseif( $aAngle <= -90 ) { // <= -1 elseif( $aAngle <= -90 ) { // <= -1
$bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5], $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5],
$bbox[6],$bbox[1],$bbox[2],$bbox[1]); $bbox[6],$bbox[1],$bbox[2],$bbox[1]);
} }
else { else {
$bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3], $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
$bbox[4],$bbox[7],$bbox[0],$bbox[7]); $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
} }
} }
return $bbox; return $bbox;
} }
   
function GetBBoxHeight($aTxt,$aAngle=0) { function GetBBoxHeight($aTxt,$aAngle=0) {
$box = $this->GetBBoxTTF($aTxt,$aAngle); $box = $this->GetBBoxTTF($aTxt,$aAngle);
return abs($box[7]-$box[1]); return abs($box[7]-$box[1]);
} }
   
function GetBBoxWidth($aTxt,$aAngle=0) { function GetBBoxWidth($aTxt,$aAngle=0) {
$box = $this->GetBBoxTTF($aTxt,$aAngle); $box = $this->GetBBoxTTF($aTxt,$aAngle);
return $box[2]-$box[0]+1; return $box[2]-$box[0]+1;
} }
   
   
function _StrokeTTF($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$debug=false) { function _StrokeTTF($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$debug=false) {
   
// Setup default inter line margin for paragraphs to be // Setup default inter line margin for paragraphs to be
// 3% of the font height. // 3% of the font height.
$ConstLineSpacing = 0.03 ; $ConstLineSpacing = 0.03 ;
   
// Remember the anchor point before adjustment // Remember the anchor point before adjustment
if( $debug ) { if( $debug ) {
$ox=$x; $ox=$x;
$oy=$y; $oy=$y;
} }
   
if( !preg_match('/\n/',$txt) || ($dir>0 && preg_match('/\n/',$txt)) ) { if( !preg_match('/\n/',$txt) || ($dir>0 && preg_match('/\n/',$txt)) ) {
// Format a single line // Format a single line
   
$txt = $this->AddTxtCR($txt); $txt = $this->AddTxtCR($txt);
$bbox=$this->GetBBoxTTF($txt,$dir); $bbox=$this->GetBBoxTTF($txt,$dir);
$width = $this->GetBBoxWidth($txt,$dir); $width = $this->GetBBoxWidth($txt,$dir);
$height = $this->GetBBoxHeight($txt,$dir); $height = $this->GetBBoxHeight($txt,$dir);
   
// The special alignment "basepoint" is mostly used internally // The special alignment "basepoint" is mostly used internally
// in the library. This will put the anchor position at the left // in the library. This will put the anchor position at the left
// basepoint of the tetx. This is the default anchor point for // basepoint of the tetx. This is the default anchor point for
// TTF text. // TTF text.
   
if( $this->text_valign != 'basepoint' ) { if( $this->text_valign != 'basepoint' ) {
// Align x,y ot lower left corner of bbox // Align x,y ot lower left corner of bbox
   
if( $this->text_halign=='right' ) { if( $this->text_halign=='right' ) {
$x -= $width; $x -= $width;
$x -= $bbox[0]; $x -= $bbox[0];
} }
elseif( $this->text_halign=='center' ) { elseif( $this->text_halign=='center' ) {
$x -= $width/2; $x -= $width/2;
$x -= $bbox[0]; $x -= $bbox[0];
} }
elseif( $this->text_halign=='baseline' ) { elseif( $this->text_halign=='baseline' ) {
// This is only support for text at 90 degree !! // This is only support for text at 90 degree !!
// Do nothing the text is drawn at baseline by default // Do nothing the text is drawn at baseline by default
} }
   
if( $this->text_valign=='top' ) { if( $this->text_valign=='top' ) {
$y -= $bbox[1]; // Adjust to bottom of text $y -= $bbox[1]; // Adjust to bottom of text
$y += $height; $y += $height;
} }
elseif( $this->text_valign=='center' ) { elseif( $this->text_valign=='center' ) {
$y -= $bbox[1]; // Adjust to bottom of text $y -= $bbox[1]; // Adjust to bottom of text
$y += $height/2; $y += $height/2;
} }
elseif( $this->text_valign=='baseline' ) { elseif( $this->text_valign=='baseline' ) {
// This is only support for text at 0 degree !! // This is only support for text at 0 degree !!
// Do nothing the text is drawn at baseline by default // Do nothing the text is drawn at baseline by default
} }
} }
ImageTTFText ($this->img, $this->font_size, $dir, $x, $y, ImageTTFText ($this->img, $this->font_size, $dir, $x, $y,
$this->current_color,$this->font_file,$txt); $this->current_color,$this->font_file,$txt);
   
// Calculate and return the co-ordinates for the bounding box // Calculate and return the co-ordinates for the bounding box
$box = $this->imagettfbbox_fixed($this->font_size,$dir,$this->font_file,$txt); $box = $this->imagettfbbox_fixed($this->font_size,$dir,$this->font_file,$txt);
$p1 = array(); $p1 = array();
   
for($i=0; $i < 4; ++$i) { for($i=0; $i < 4; ++$i) {
$p1[] = round($box[$i*2]+$x); $p1[] = round($box[$i*2]+$x);
$p1[] = round($box[$i*2+1]+$y); $p1[] = round($box[$i*2+1]+$y);
} }
$aBoundingBox = $p1; $aBoundingBox = $p1;
   
// Debugging code to highlight the bonding box and bounding rectangle // Debugging code to highlight the bonding box and bounding rectangle
// For text at 0 degrees the bounding box and bounding rectangle are the // For text at 0 degrees the bounding box and bounding rectangle are the
// same // same
if( $debug ) { if( $debug ) {
// Draw the bounding rectangle and the bounding box // Draw the bounding rectangle and the bounding box
   
$p = array(); $p = array();
$p1 = array(); $p1 = array();
   
for($i=0; $i < 4; ++$i) { for($i=0; $i < 4; ++$i) {
$p[] = $bbox[$i*2]+$x ; $p[] = $bbox[$i*2]+$x ;
$p[] = $bbox[$i*2+1]+$y; $p[] = $bbox[$i*2+1]+$y;
$p1[] = $box[$i*2]+$x ; $p1[] = $box[$i*2]+$x ;
$p1[] = $box[$i*2+1]+$y ; $p1[] = $box[$i*2+1]+$y ;
} }
   
// Draw bounding box // Draw bounding box
$this->PushColor('green'); $this->PushColor('green');
$this->Polygon($p1,true); $this->Polygon($p1,true);
$this->PopColor(); $this->PopColor();
   
// Draw bounding rectangle // Draw bounding rectangle
$this->PushColor('darkgreen'); $this->PushColor('darkgreen');
$this->Polygon($p,true); $this->Polygon($p,true);
$this->PopColor(); $this->PopColor();
   
// Draw a cross at the anchor point // Draw a cross at the anchor point
$this->PushColor('red'); $this->PushColor('red');
$this->Line($ox-15,$oy,$ox+15,$oy); $this->Line($ox-15,$oy,$ox+15,$oy);
$this->Line($ox,$oy-15,$ox,$oy+15); $this->Line($ox,$oy-15,$ox,$oy+15);
$this->PopColor(); $this->PopColor();
} }
} }
else { else {
// Format a text paragraph // Format a text paragraph
$fh=$this->GetFontHeight(); $fh=$this->GetFontHeight();
   
// Line margin is 25% of font height // Line margin is 25% of font height
$linemargin=round($fh*$ConstLineSpacing); $linemargin=round($fh*$ConstLineSpacing);
$fh += $linemargin; $fh += $linemargin;
$w=$this->GetTextWidth($txt); $w=$this->GetTextWidth($txt);
   
$y -= $linemargin/2; $y -= $linemargin/2;
$tmp = preg_split('/\n/',$txt); $tmp = preg_split('/\n/',$txt);
$nl = count($tmp); $nl = count($tmp);
$h = $nl * $fh; $h = $nl * $fh;
   
if( $this->text_halign=='right') { if( $this->text_halign=='right') {
$x -= $dir==0 ? $w : $h; $x -= $dir==0 ? $w : $h;
} }
elseif( $this->text_halign=='center' ) { elseif( $this->text_halign=='center' ) {
$x -= $dir==0 ? $w/2 : $h/2; $x -= $dir==0 ? $w/2 : $h/2;
} }
   
if( $this->text_valign=='top' ) { if( $this->text_valign=='top' ) {
$y += $dir==0 ? $h : $w; $y += $dir==0 ? $h : $w;
} }
elseif( $this->text_valign=='center' ) { elseif( $this->text_valign=='center' ) {
$y += $dir==0 ? $h/2 : $w/2; $y += $dir==0 ? $h/2 : $w/2;
} }
   
// Here comes a tricky bit. // Here comes a tricky bit.
// Since we have to give the position for the string at the // Since we have to give the position for the string at the
// baseline this means thaht text will move slightly up // baseline this means thaht text will move slightly up
// and down depending on any of it's character descend below // and down depending on any of it's character descend below
// the baseline, for example a 'g'. To adjust the Y-position // the baseline, for example a 'g'. To adjust the Y-position
// we therefore adjust the text with the baseline Y-offset // we therefore adjust the text with the baseline Y-offset
// as used for the current font and size. This will keep the // as used for the current font and size. This will keep the
// baseline at a fixed positoned disregarding the actual // baseline at a fixed positoned disregarding the actual
// characters in the string. // characters in the string.
$standardbox = $this->GetTTFBBox('Gg',$dir); $standardbox = $this->GetTTFBBox('Gg',$dir);
$yadj = $standardbox[1]; $yadj = $standardbox[1];
$xadj = $standardbox[0]; $xadj = $standardbox[0];
$aBoundingBox = array(); $aBoundingBox = array();
for($i=0; $i < $nl; ++$i) { for($i=0; $i < $nl; ++$i) {
$wl = $this->GetTextWidth($tmp[$i]); $wl = $this->GetTextWidth($tmp[$i]);
$bbox = $this->GetTTFBBox($tmp[$i],$dir); $bbox = $this->GetTTFBBox($tmp[$i],$dir);
if( $paragraph_align=='left' ) { if( $paragraph_align=='left' ) {
$xl = $x; $xl = $x;
} }
elseif( $paragraph_align=='right' ) { elseif( $paragraph_align=='right' ) {
$xl = $x + ($w-$wl); $xl = $x + ($w-$wl);
} }
else { else {
// Center // Center
$xl = $x + $w/2 - $wl/2 ; $xl = $x + $w/2 - $wl/2 ;
} }
   
// In theory we should adjust with full pre-lead to get the lines // 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 // lined up but this doesn't look good so therfore we only adjust with
// half th pre-lead // half th pre-lead
$xl -= $bbox[0]/2; $xl -= $bbox[0]/2;
$yl = $y - $yadj; $yl = $y - $yadj;
//$xl = $xl- $xadj; //$xl = $xl- $xadj;
ImageTTFText($this->img, $this->font_size, $dir, $xl, $yl-($h-$fh)+$fh*$i, ImageTTFText($this->img, $this->font_size, $dir, $xl, $yl-($h-$fh)+$fh*$i,
$this->current_color,$this->font_file,$tmp[$i]); $this->current_color,$this->font_file,$tmp[$i]);
   
// echo "xl=$xl,".$tmp[$i]." <br>"; // echo "xl=$xl,".$tmp[$i]." <br>";
if( $debug ) { if( $debug ) {
// Draw the bounding rectangle around each line // Draw the bounding rectangle around each line
$box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$tmp[$i]); $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$tmp[$i]);
$p = array(); $p = array();
for($j=0; $j < 4; ++$j) { for($j=0; $j < 4; ++$j) {
$p[] = $bbox[$j*2]+$xl; $p[] = $bbox[$j*2]+$xl;
$p[] = $bbox[$j*2+1]+$yl-($h-$fh)+$fh*$i; $p[] = $bbox[$j*2+1]+$yl-($h-$fh)+$fh*$i;
} }
   
// Draw bounding rectangle // Draw bounding rectangle
$this->PushColor('darkgreen'); $this->PushColor('darkgreen');
$this->Polygon($p,true); $this->Polygon($p,true);
$this->PopColor(); $this->PopColor();
} }
} }
   
// Get the bounding box // Get the bounding box
$bbox = $this->GetBBoxTTF($txt,$dir); $bbox = $this->GetBBoxTTF($txt,$dir);
for($j=0; $j < 4; ++$j) { for($j=0; $j < 4; ++$j) {
$bbox[$j*2]+= round($x); $bbox[$j*2]+= round($x);
$bbox[$j*2+1]+= round($y - ($h-$fh) - $yadj); $bbox[$j*2+1]+= round($y - ($h-$fh) - $yadj);
} }
$aBoundingBox = $bbox; $aBoundingBox = $bbox;
   
if( $debug ) { if( $debug ) {
// Draw a cross at the anchor point // Draw a cross at the anchor point
$this->PushColor('red'); $this->PushColor('red');
$this->Line($ox-25,$oy,$ox+25,$oy); $this->Line($ox-25,$oy,$ox+25,$oy);
$this->Line($ox,$oy-25,$ox,$oy+25); $this->Line($ox,$oy-25,$ox,$oy+25);
$this->PopColor(); $this->PopColor();
} }
   
} }
} }
   
function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) { function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) {
   
$x = round($x); $x = round($x);
$y = round($y); $y = round($y);
   
// Do special language encoding // Do special language encoding
$txt = $this->langconv->Convert($txt,$this->font_family); $txt = $this->langconv->Convert($txt,$this->font_family);
   
if( !is_numeric($dir) ) { if( !is_numeric($dir) ) {
JpGraphError::RaiseL(25094);//(" Direction for text most be given as an angle between 0 and 90."); 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) { if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) {
$this->_StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug); $this->_StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug);
} }
elseif( $this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT) { elseif( $this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT) {
$this->_StrokeTTF($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug); $this->_StrokeTTF($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug);
} }
else { else {
JpGraphError::RaiseL(25095);//(" Unknown font font family specification. "); JpGraphError::RaiseL(25095);//(" Unknown font font family specification. ");
} }
return $boundingbox; return $boundingbox;
} }
   
function SetMargin($lm,$rm,$tm,$bm) { function SetMargin($lm,$rm,$tm,$bm) {
$this->left_margin=$lm; $this->left_margin=$lm;
$this->right_margin=$rm; $this->right_margin=$rm;
$this->top_margin=$tm; $this->top_margin=$tm;
$this->bottom_margin=$bm; $this->bottom_margin=$bm;
$this->plotwidth=$this->width - $this->left_margin-$this->right_margin ; $this->plotwidth=$this->width - $this->left_margin-$this->right_margin ;
$this->plotheight=$this->height - $this->top_margin-$this->bottom_margin ; $this->plotheight=$this->height - $this->top_margin-$this->bottom_margin ;
if( $this->width > 0 && $this->height > 0 ) { if( $this->width > 0 && $this->height > 0 ) {
if( $this->plotwidth < 0 || $this->plotheight < 0 ) { if( $this->plotwidth < 0 || $this->plotheight < 0 ) {
JpGraphError::RaiseL(25130, $this->plotwidth, $this->plotheight); 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."); //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) { function SetTransparent($color) {
imagecolortransparent ($this->img,$this->rgb->allocate($color)); imagecolortransparent ($this->img,$this->rgb->allocate($color));
} }
   
function SetColor($color,$aAlpha=0) { function SetColor($color,$aAlpha=0) {
$this->current_color_name = $color; $this->current_color_name = $color;
$this->current_color=$this->rgb->allocate($color,$aAlpha); $this->current_color=$this->rgb->allocate($color,$aAlpha);
if( $this->current_color == -1 ) { if( $this->current_color == -1 ) {
$tc=imagecolorstotal($this->img); $tc=imagecolorstotal($this->img);
JpGraphError::RaiseL(25096); JpGraphError::RaiseL(25096);
//("Can't allocate any more colors. Image has already allocated maximum of <b>$tc colors</b>. This might happen if you have anti-aliasing turned on together with a background image or perhaps gradient fill since this requires many, many colors. Try to turn off anti-aliasing. If there is still a problem try downgrading the quality of the background image to use a smaller pallete to leave some entries for your graphs. You should try to limit the number of colors in your background image to 64. If there is still problem set the constant DEFINE(\"USE_APPROX_COLORS\",true); in jpgraph.php This will use approximative colors when the palette is full. Unfortunately there is not much JpGraph can do about this since the palette size is a limitation of current graphic format and what the underlying GD library suppports."); //("Can't allocate any more colors. Image has already allocated maximum of <b>$tc colors</b>. This might happen if you have anti-aliasing turned on together with a background image or perhaps gradient fill since this requires many, many colors. Try to turn off anti-aliasing. If there is still a problem try downgrading the quality of the background image to use a smaller pallete to leave some entries for your graphs. You should try to limit the number of colors in your background image to 64. If there is still problem set the constant DEFINE(\"USE_APPROX_COLORS\",true); in jpgraph.php This will use approximative colors when the palette is full. Unfortunately there is not much JpGraph can do about this since the palette size is a limitation of current graphic format and what the underlying GD library suppports.");
} }
return $this->current_color; return $this->current_color;
} }
   
function PushColor($color) { function PushColor($color) {
if( $color != "" ) { if( $color != "" ) {
$this->colorstack[$this->colorstackidx]=$this->current_color_name; $this->colorstack[$this->colorstackidx]=$this->current_color_name;
$this->colorstack[$this->colorstackidx+1]=$this->current_color; $this->colorstack[$this->colorstackidx+1]=$this->current_color;
$this->colorstackidx+=2; $this->colorstackidx+=2;
$this->SetColor($color); $this->SetColor($color);
} }
else { else {
JpGraphError::RaiseL(25097);//("Color specified as empty string in PushColor()."); JpGraphError::RaiseL(25097);//("Color specified as empty string in PushColor().");
} }
} }
   
function PopColor() { function PopColor() {
if( $this->colorstackidx < 1 ) { if( $this->colorstackidx < 1 ) {
JpGraphError::RaiseL(25098);//(" Negative Color stack index. Unmatched call to PopColor()"); JpGraphError::RaiseL(25098);//(" Negative Color stack index. Unmatched call to PopColor()");
} }
$this->current_color=$this->colorstack[--$this->colorstackidx]; $this->current_color=$this->colorstack[--$this->colorstackidx];
$this->current_color_name=$this->colorstack[--$this->colorstackidx]; $this->current_color_name=$this->colorstack[--$this->colorstackidx];
} }
   
   
function SetLineWeight($weight) { function SetLineWeight($weight) {
$old = $this->line_weight; $old = $this->line_weight;
imagesetthickness($this->img,$weight); imagesetthickness($this->img,$weight);
$this->line_weight = $weight; $this->line_weight = $weight;
return $old; return $old;
} }
   
function SetStartPoint($x,$y) { function SetStartPoint($x,$y) {
$this->lastx=round($x); $this->lastx=round($x);
$this->lasty=round($y); $this->lasty=round($y);
} }
   
function Arc($cx,$cy,$w,$h,$s,$e) { function Arc($cx,$cy,$w,$h,$s,$e) {
// GD Arc doesn't like negative angles // GD Arc doesn't like negative angles
while( $s < 0) $s += 360; while( $s < 0) $s += 360;
while( $e < 0) $e += 360; while( $e < 0) $e += 360;
imagearc($this->img,round($cx),round($cy),round($w),round($h),$s,$e,$this->current_color); 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='') { function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') {
$s = round($s); $s = round($s);
$e = round($e); $e = round($e);
while( $s < 0 ) $s += 360; while( $s < 0 ) $s += 360;
while( $e < 0 ) $e += 360; while( $e < 0 ) $e += 360;
if( $style=='' ) if( $style=='' )
$style=IMG_ARC_PIE; $style=IMG_ARC_PIE;
if( abs($s-$e) > 0 ) { if( abs($s-$e) > 0 ) {
imagefilledarc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style); imagefilledarc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style);
} }
} }
   
function FilledCakeSlice($cx,$cy,$w,$h,$s,$e) { function FilledCakeSlice($cx,$cy,$w,$h,$s,$e) {
$this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name); $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name);
} }
   
function CakeSlice($xc,$yc,$w,$h,$s,$e,$fillcolor="",$arccolor="") { function CakeSlice($xc,$yc,$w,$h,$s,$e,$fillcolor="",$arccolor="") {
$s = round($s); $e = round($e); $s = round($s); $e = round($e);
$w = round($w); $h = round($h); $w = round($w); $h = round($h);
$xc = round($xc); $yc = round($yc); $xc = round($xc); $yc = round($yc);
if( $s ==$e ) { if( $s ==$e ) {
// A full circle. We draw this a plain circle // A full circle. We draw this a plain circle
$this->PushColor($fillcolor); $this->PushColor($fillcolor);
imagefilledellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color); imagefilledellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color);
$this->PopColor(); $this->PopColor();
$this->PushColor($arccolor); $this->PushColor($arccolor);
imageellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color); 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->Line($xc,$yc,cos($s*M_PI/180)*$w+$xc,$yc+sin($s*M_PI/180)*$h);
$this->PopColor(); $this->PopColor();
} }
else { else {
$this->PushColor($fillcolor); $this->PushColor($fillcolor);
$this->FilledArc($xc,$yc,2*$w,2*$h,$s,$e); $this->FilledArc($xc,$yc,2*$w,2*$h,$s,$e);
$this->PopColor(); $this->PopColor();
if( $arccolor != "" ) { if( $arccolor != "" ) {
$this->PushColor($arccolor); $this->PushColor($arccolor);
// We add 2 pixels to make the Arc() better aligned with // We add 2 pixels to make the Arc() better aligned with
// the filled arc. // the filled arc.
imagefilledarc($this->img,$xc,$yc,2*$w,2*$h,$s,$e,$this->current_color,IMG_ARC_NOFILL | IMG_ARC_EDGED ) ; imagefilledarc($this->img,$xc,$yc,2*$w,2*$h,$s,$e,$this->current_color,IMG_ARC_NOFILL | IMG_ARC_EDGED ) ;
$this->PopColor(); $this->PopColor();
} }
} }
} }
   
function Ellipse($xc,$yc,$w,$h) { function Ellipse($xc,$yc,$w,$h) {
$this->Arc($xc,$yc,$w,$h,0,360); $this->Arc($xc,$yc,$w,$h,0,360);
} }
   
function Circle($xc,$yc,$r) { function Circle($xc,$yc,$r) {
imageellipse($this->img,round($xc),round($yc),$r*2,$r*2,$this->current_color); imageellipse($this->img,round($xc),round($yc),$r*2,$r*2,$this->current_color);
} }
   
function FilledCircle($xc,$yc,$r) { function FilledCircle($xc,$yc,$r) {
imagefilledellipse($this->img,round($xc),round($yc),2*$r,2*$r,$this->current_color); imagefilledellipse($this->img,round($xc),round($yc),2*$r,2*$r,$this->current_color);
} }
   
// Linear Color InterPolation // Linear Color InterPolation
function lip($f,$t,$p) { function lip($f,$t,$p) {
$p = round($p,1); $p = round($p,1);
$r = $f[0] + ($t[0]-$f[0])*$p; $r = $f[0] + ($t[0]-$f[0])*$p;
$g = $f[1] + ($t[1]-$f[1])*$p; $g = $f[1] + ($t[1]-$f[1])*$p;
$b = $f[2] + ($t[2]-$f[2])*$p; $b = $f[2] + ($t[2]-$f[2])*$p;
return array($r,$g,$b); return array($r,$g,$b);
} }
   
// Set line style dashed, dotted etc // Set line style dashed, dotted etc
function SetLineStyle($s) { function SetLineStyle($s) {
if( is_numeric($s) ) { if( is_numeric($s) ) {
if( $s<1 || $s>4 ) { if( $s<1 || $s>4 ) {
JpGraphError::RaiseL(25101,$s);//(" Illegal numeric argument to SetLineStyle(): ($s)"); JpGraphError::RaiseL(25101,$s);//(" Illegal numeric argument to SetLineStyle(): ($s)");
} }
} }
elseif( is_string($s) ) { elseif( is_string($s) ) {
if( $s == "solid" ) $s=1; if( $s == "solid" ) $s=1;
elseif( $s == "dotted" ) $s=2; elseif( $s == "dotted" ) $s=2;
elseif( $s == "dashed" ) $s=3; elseif( $s == "dashed" ) $s=3;
elseif( $s == "longdashed" ) $s=4; elseif( $s == "longdashed" ) $s=4;
else { else {
JpGraphError::RaiseL(25102,$s);//(" Illegal string argument to SetLineStyle(): $s"); JpGraphError::RaiseL(25102,$s);//(" Illegal string argument to SetLineStyle(): $s");
} }
} }
else { else {
JpGraphError::RaiseL(25103,$s);//(" Illegal argument to SetLineStyle $s"); JpGraphError::RaiseL(25103,$s);//(" Illegal argument to SetLineStyle $s");
} }
$old = $this->line_style; $old = $this->line_style;
$this->line_style=$s; $this->line_style=$s;
return $old; return $old;
} }
   
// Same as Line but take the line_style into account // Same as Line but take the line_style into account
function StyleLine($x1,$y1,$x2,$y2,$aStyle='') { function StyleLine($x1,$y1,$x2,$y2,$aStyle='') {
if( $this->line_weight <= 0 ) return; if( $this->line_weight <= 0 ) return;
   
if( $aStyle === '' ) { if( $aStyle === '' ) {
$aStyle = $this->line_style; $aStyle = $this->line_style;
} }
   
// Add error check since dashed line will only work if anti-alias is disabled // Add error check since dashed line will only work if anti-alias is disabled
// this is a limitation in GD // this is a limitation in GD
   
if( $aStyle == 1 ) { if( $aStyle == 1 ) {
// Solid style. We can handle anti-aliasing for this // Solid style. We can handle anti-aliasing for this
$this->Line($x1,$y1,$x2,$y2); $this->Line($x1,$y1,$x2,$y2);
} }
else { else {
// Since the GD routines doesn't handle AA for styled line // 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 // we have no option than to turn it off to get any lines at
// all if the weight > 1 // all if the weight > 1
$oldaa = $this->GetAntiAliasing(); $oldaa = $this->GetAntiAliasing();
if( $oldaa && $this->line_weight > 1 ) { if( $oldaa && $this->line_weight > 1 ) {
$this->SetAntiAliasing(false); $this->SetAntiAliasing(false);
} }
   
switch( $aStyle ) { switch( $aStyle ) {
case 2: // Dotted case 2: // Dotted
$this->DashedLine($x1,$y1,$x2,$y2,2,6); $this->DashedLine($x1,$y1,$x2,$y2,2,6);
break; break;
case 3: // Dashed case 3: // Dashed
$this->DashedLine($x1,$y1,$x2,$y2,5,9); $this->DashedLine($x1,$y1,$x2,$y2,5,9);
break; break;
case 4: // Longdashes case 4: // Longdashes
$this->DashedLine($x1,$y1,$x2,$y2,9,13); $this->DashedLine($x1,$y1,$x2,$y2,9,13);
break; break;
default: default:
JpGraphError::RaiseL(25104,$this->line_style);//(" Unknown line style: $this->line_style "); JpGraphError::RaiseL(25104,$this->line_style);//(" Unknown line style: $this->line_style ");
break; break;
} }
if( $oldaa ) { if( $oldaa ) {
$this->SetAntiAliasing(true); $this->SetAntiAliasing(true);
} }
} }
} }
   
function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) { function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
   
if( $this->line_weight <= 0 ) return; if( $this->line_weight <= 0 ) return;
   
// Add error check to make sure anti-alias is not enabled. // Add error check to make sure anti-alias is not enabled.
// Dashed line does not work with anti-alias enabled. This // Dashed line does not work with anti-alias enabled. This
// is a limitation in GD. // is a limitation in GD.
if( $this->use_anti_aliasing ) { 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. JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
} }
   
   
$x1 = round($x1); $x1 = round($x1);
$x2 = round($x2); $x2 = round($x2);
$y1 = round($y1); $y1 = round($y1);
$y2 = round($y2); $y2 = round($y2);
   
$style = array_fill(0,$dash_length,$this->current_color); $style = array_fill(0,$dash_length,$this->current_color);
$style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT); $style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT);
imagesetstyle($this->img, $style); imagesetstyle($this->img, $style);
imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
$this->lastx = $x2; $this->lastx = $x2;
$this->lasty = $y2; $this->lasty = $y2;
} }
   
function Line($x1,$y1,$x2,$y2) { function Line($x1,$y1,$x2,$y2) {
   
if( $this->line_weight <= 0 ) return; if( $this->line_weight <= 0 ) return;
   
$x1 = round($x1); $x1 = round($x1);
$x2 = round($x2); $x2 = round($x2);
$y1 = round($y1); $y1 = round($y1);
$y2 = round($y2); $y2 = round($y2);
   
imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color); imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color);
$this->lastx=$x2; $this->lastx=$x2;
$this->lasty=$y2; $this->lasty=$y2;
} }
   
function Polygon($p,$closed=FALSE,$fast=FALSE) { function Polygon($p,$closed=FALSE,$fast=FALSE) {
   
if( $this->line_weight <= 0 ) return; if( $this->line_weight <= 0 ) return;
   
$n=count($p); $n=count($p);
$oldx = $p[0]; $oldx = $p[0];
$oldy = $p[1]; $oldy = $p[1];
if( $fast ) { if( $fast ) {
for( $i=2; $i < $n; $i+=2 ) { for( $i=2; $i < $n; $i+=2 ) {
imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->current_color); imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->current_color);
$oldx = $p[$i]; $oldx = $p[$i];
$oldy = $p[$i+1]; $oldy = $p[$i+1];
} }
if( $closed ) { if( $closed ) {
imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->current_color); imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->current_color);
} }
} }
else { else {
for( $i=2; $i < $n; $i+=2 ) { for( $i=2; $i < $n; $i+=2 ) {
$this->StyleLine($oldx,$oldy,$p[$i],$p[$i+1]); $this->StyleLine($oldx,$oldy,$p[$i],$p[$i+1]);
$oldx = $p[$i]; $oldx = $p[$i];
$oldy = $p[$i+1]; $oldy = $p[$i+1];
} }
if( $closed ) { if( $closed ) {
$this->StyleLine($oldx,$oldy,$p[0],$p[1]); $this->StyleLine($oldx,$oldy,$p[0],$p[1]);
} }
} }
} }
   
function FilledPolygon($pts) { function FilledPolygon($pts) {
$n=count($pts); $n=count($pts);
if( $n == 0 ) { if( $n == 0 ) {
JpGraphError::RaiseL(25105);//('NULL data specified for a filled polygon. Check that your data is not NULL.'); JpGraphError::RaiseL(25105);//('NULL data specified for a filled polygon. Check that your data is not NULL.');
} }
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$pts[$i] = round($pts[$i]); $pts[$i] = round($pts[$i]);
} }
$old = $this->line_weight; $old = $this->line_weight;
imagesetthickness($this->img,1); imagesetthickness($this->img,1);
imagefilledpolygon($this->img,$pts,count($pts)/2,$this->current_color); imagefilledpolygon($this->img,$pts,count($pts)/2,$this->current_color);
$this->line_weight = $old; $this->line_weight = $old;
imagesetthickness($this->img,$old); imagesetthickness($this->img,$old);
} }
   
function Rectangle($xl,$yu,$xr,$yl) { function Rectangle($xl,$yu,$xr,$yl) {
$this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu)); $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu));
} }
   
function FilledRectangle($xl,$yu,$xr,$yl) { function FilledRectangle($xl,$yu,$xr,$yl) {
$this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl)); $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl));
} }
   
function FilledRectangle2($xl,$yu,$xr,$yl,$color1,$color2,$style=1) { function FilledRectangle2($xl,$yu,$xr,$yl,$color1,$color2,$style=1) {
// Fill a rectangle with lines of two colors // Fill a rectangle with lines of two colors
if( $style===1 ) { if( $style===1 ) {
// Horizontal stripe // Horizontal stripe
if( $yl < $yu ) { if( $yl < $yu ) {
$t = $yl; $yl=$yu; $yu=$t; $t = $yl; $yl=$yu; $yu=$t;
} }
for( $y=$yu; $y <= $yl; ++$y) { for( $y=$yu; $y <= $yl; ++$y) {
$this->SetColor($color1); $this->SetColor($color1);
$this->Line($xl,$y,$xr,$y); $this->Line($xl,$y,$xr,$y);
++$y; ++$y;
$this->SetColor($color2); $this->SetColor($color2);
$this->Line($xl,$y,$xr,$y); $this->Line($xl,$y,$xr,$y);
} }
} }
else { else {
if( $xl < $xl ) { if( $xl < $xl ) {
$t = $xl; $xl=$xr; $xr=$t; $t = $xl; $xl=$xr; $xr=$t;
} }
for( $x=$xl; $x <= $xr; ++$x) { for( $x=$xl; $x <= $xr; ++$x) {
$this->SetColor($color1); $this->SetColor($color1);
$this->Line($x,$yu,$x,$yl); $this->Line($x,$yu,$x,$yl);
++$x; ++$x;
$this->SetColor($color2); $this->SetColor($color2);
$this->Line($x,$yu,$x,$yl); $this->Line($x,$yu,$x,$yl);
} }
} }
} }
   
function ShadowRectangle($xl,$yu,$xr,$yl,$fcolor=false,$shadow_width=4,$shadow_color='darkgray',$useAlpha=true) { 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 // This is complicated by the fact that we must also handle the case where
// the reactangle has no fill color // the reactangle has no fill color
$xl = floor($xl); $xl = floor($xl);
$yu = floor($yu); $yu = floor($yu);
$xr = floor($xr); $xr = floor($xr);
$yl = floor($yl); $yl = floor($yl);
$this->PushColor($shadow_color); $this->PushColor($shadow_color);
$shadowAlpha=0; $shadowAlpha=0;
$this->SetLineWeight(1); $this->SetLineWeight(1);
$this->SetLineStyle('solid'); $this->SetLineStyle('solid');
$basecolor = $this->rgb->Color($shadow_color); $basecolor = $this->rgb->Color($shadow_color);
$shadow_color = array($basecolor[0],$basecolor[1],$basecolor[2],); $shadow_color = array($basecolor[0],$basecolor[1],$basecolor[2],);
for( $i=0; $i < $shadow_width; ++$i ) { for( $i=0; $i < $shadow_width; ++$i ) {
$this->SetColor($shadow_color,$shadowAlpha); $this->SetColor($shadow_color,$shadowAlpha);
$this->Line($xr-$shadow_width+$i, $yu+$shadow_width, $this->Line($xr-$shadow_width+$i, $yu+$shadow_width,
$xr-$shadow_width+$i, $yl-$shadow_width-1+$i); $xr-$shadow_width+$i, $yl-$shadow_width-1+$i);
$this->Line($xl+$shadow_width, $yl-$shadow_width+$i, $this->Line($xl+$shadow_width, $yl-$shadow_width+$i,
$xr-$shadow_width+$i, $yl-$shadow_width+$i); $xr-$shadow_width+$i, $yl-$shadow_width+$i);
if( $useAlpha ) $shadowAlpha += 1.0/$shadow_width; if( $useAlpha ) $shadowAlpha += 1.0/$shadow_width;
} }
   
$this->PopColor(); $this->PopColor();
if( $fcolor==false ) { if( $fcolor==false ) {
$this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
} }
else { else {
$this->PushColor($fcolor); $this->PushColor($fcolor);
$this->FilledRectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); $this->FilledRectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
$this->PopColor(); $this->PopColor();
$this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1); $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
} }
} }
   
function FilledRoundedRectangle($xt,$yt,$xr,$yl,$r=5) { function FilledRoundedRectangle($xt,$yt,$xr,$yl,$r=5) {
if( $r==0 ) { if( $r==0 ) {
$this->FilledRectangle($xt,$yt,$xr,$yl); $this->FilledRectangle($xt,$yt,$xr,$yl);
return; return;
} }
   
// To avoid overlapping fillings (which will look strange // To avoid overlapping fillings (which will look strange
// when alphablending is enabled) we have no choice but // when alphablending is enabled) we have no choice but
// to fill the five distinct areas one by one. // to fill the five distinct areas one by one.
   
// Center square // Center square
$this->FilledRectangle($xt+$r,$yt+$r,$xr-$r,$yl-$r); $this->FilledRectangle($xt+$r,$yt+$r,$xr-$r,$yl-$r);
// Top band // Top band
$this->FilledRectangle($xt+$r,$yt,$xr-$r,$yt+$r); $this->FilledRectangle($xt+$r,$yt,$xr-$r,$yt+$r);
// Bottom band // Bottom band
$this->FilledRectangle($xt+$r,$yl-$r,$xr-$r,$yl); $this->FilledRectangle($xt+$r,$yl-$r,$xr-$r,$yl);
// Left band // Left band
$this->FilledRectangle($xt,$yt+$r,$xt+$r,$yl-$r); $this->FilledRectangle($xt,$yt+$r,$xt+$r,$yl-$r);
// Right band // Right band
$this->FilledRectangle($xr-$r,$yt+$r,$xr,$yl-$r); $this->FilledRectangle($xr-$r,$yt+$r,$xr,$yl-$r);
   
// Topleft & Topright arc // Topleft & Topright arc
$this->FilledArc($xt+$r,$yt+$r,$r*2,$r*2,180,270); $this->FilledArc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
$this->FilledArc($xr-$r,$yt+$r,$r*2,$r*2,270,360); $this->FilledArc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
   
// Bottomleft & Bottom right arc // Bottomleft & Bottom right arc
$this->FilledArc($xt+$r,$yl-$r,$r*2,$r*2,90,180); $this->FilledArc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
$this->FilledArc($xr-$r,$yl-$r,$r*2,$r*2,0,90); $this->FilledArc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
   
} }
   
function RoundedRectangle($xt,$yt,$xr,$yl,$r=5) { function RoundedRectangle($xt,$yt,$xr,$yl,$r=5) {
   
if( $r==0 ) { if( $r==0 ) {
$this->Rectangle($xt,$yt,$xr,$yl); $this->Rectangle($xt,$yt,$xr,$yl);
return; return;
} }
   
// Top & Bottom line // Top & Bottom line
$this->Line($xt+$r,$yt,$xr-$r,$yt); $this->Line($xt+$r,$yt,$xr-$r,$yt);
$this->Line($xt+$r,$yl,$xr-$r,$yl); $this->Line($xt+$r,$yl,$xr-$r,$yl);
   
// Left & Right line // Left & Right line
$this->Line($xt,$yt+$r,$xt,$yl-$r); $this->Line($xt,$yt+$r,$xt,$yl-$r);
$this->Line($xr,$yt+$r,$xr,$yl-$r); $this->Line($xr,$yt+$r,$xr,$yl-$r);
   
// Topleft & Topright arc // Topleft & Topright arc
$this->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); $this->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
$this->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); $this->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
   
// Bottomleft & Bottomright arc // Bottomleft & Bottomright arc
$this->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); $this->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
$this->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); $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') { function FilledBevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='darkgray@0.4') {
$this->FilledRectangle($x1,$y1,$x2,$y2); $this->FilledRectangle($x1,$y1,$x2,$y2);
$this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2); $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') { function Bevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='black@0.5') {
$this->PushColor($color1); $this->PushColor($color1);
for( $i=0; $i < $depth; ++$i ) { for( $i=0; $i < $depth; ++$i ) {
$this->Line($x1+$i,$y1+$i,$x1+$i,$y2-$i); $this->Line($x1+$i,$y1+$i,$x1+$i,$y2-$i);
$this->Line($x1+$i,$y1+$i,$x2-$i,$y1+$i); $this->Line($x1+$i,$y1+$i,$x2-$i,$y1+$i);
} }
$this->PopColor(); $this->PopColor();
   
$this->PushColor($color2); $this->PushColor($color2);
for( $i=0; $i < $depth; ++$i ) { for( $i=0; $i < $depth; ++$i ) {
$this->Line($x1+$i,$y2-$i,$x2-$i,$y2-$i); $this->Line($x1+$i,$y2-$i,$x2-$i,$y2-$i);
$this->Line($x2-$i,$y1+$i,$x2-$i,$y2-$i-1); $this->Line($x2-$i,$y1+$i,$x2-$i,$y2-$i-1);
} }
$this->PopColor(); $this->PopColor();
} }
   
function StyleLineTo($x,$y) { function StyleLineTo($x,$y) {
$this->StyleLine($this->lastx,$this->lasty,$x,$y); $this->StyleLine($this->lastx,$this->lasty,$x,$y);
$this->lastx=$x; $this->lastx=$x;
$this->lasty=$y; $this->lasty=$y;
} }
   
function LineTo($x,$y) { function LineTo($x,$y) {
$this->Line($this->lastx,$this->lasty,$x,$y); $this->Line($this->lastx,$this->lasty,$x,$y);
$this->lastx=$x; $this->lastx=$x;
$this->lasty=$y; $this->lasty=$y;
} }
   
function Point($x,$y) { function Point($x,$y) {
imagesetpixel($this->img,round($x),round($y),$this->current_color); imagesetpixel($this->img,round($x),round($y),$this->current_color);
} }
   
function Fill($x,$y) { function Fill($x,$y) {
imagefill($this->img,round($x),round($y),$this->current_color); imagefill($this->img,round($x),round($y),$this->current_color);
} }
   
function FillToBorder($x,$y,$aBordColor) { function FillToBorder($x,$y,$aBordColor) {
$bc = $this->rgb->allocate($aBordColor); $bc = $this->rgb->allocate($aBordColor);
if( $bc == -1 ) { if( $bc == -1 ) {
JpGraphError::RaiseL(25106);//('Image::FillToBorder : Can not allocate more colors'); JpGraphError::RaiseL(25106);//('Image::FillToBorder : Can not allocate more colors');
} }
imagefilltoborder($this->img,round($x),round($y),$bc,$this->current_color); imagefilltoborder($this->img,round($x),round($y),$bc,$this->current_color);
} }
   
function SetExpired($aFlg=true) { function SetExpired($aFlg=true) {
$this->expired = $aFlg; $this->expired = $aFlg;
} }
   
// Generate image header // Generate image header
function Headers() { function Headers() {
   
// In case we are running from the command line with the client version of // In case we are running from the command line with the client version of
// PHP we can't send any headers. // PHP we can't send any headers.
$sapi = php_sapi_name(); $sapi = php_sapi_name();
if( $sapi == 'cli' ) return; if( $sapi == 'cli' ) return;
   
// These parameters are set by headers_sent() but they might cause // These parameters are set by headers_sent() but they might cause
// an undefined variable error unless they are initilized // an undefined variable error unless they are initilized
$file=''; $file='';
$lineno=''; $lineno='';
if( headers_sent($file,$lineno) ) { if( headers_sent($file,$lineno) ) {
$file=basename($file); $file=basename($file);
$t = new ErrMsgText(); $t = new ErrMsgText();
$msg = $t->Get(10,$file,$lineno); $msg = $t->Get(10,$file,$lineno);
die($msg); die($msg);
} }
   
if ($this->expired) { if ($this->expired) {
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-cache, must-revalidate"); header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache"); header("Pragma: no-cache");
} }
header("Content-type: image/$this->img_format"); header("Content-type: image/$this->img_format");
} }
   
// Adjust image quality for formats that allow this // Adjust image quality for formats that allow this
function SetQuality($q) { function SetQuality($q) {
$this->quality = $q; $this->quality = $q;
} }
   
// Stream image to browser or to file // Stream image to browser or to file
function Stream($aFile="") { function Stream($aFile="") {
$func="image".$this->img_format; $func="image".$this->img_format;
if( $this->img_format=="jpeg" && $this->quality != null ) { if( $this->img_format=="jpeg" && $this->quality != null ) {
$res = @$func($this->img,$aFile,$this->quality); $res = @$func($this->img,$aFile,$this->quality);
} }
else { else {
if( $aFile != "" ) { if( $aFile != "" ) {
$res = @$func($this->img,$aFile); $res = @$func($this->img,$aFile);
if( !$res ) { if( !$res ) {
JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission."); JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
} }
} }
else { else {
$res = @$func($this->img); $res = @$func($this->img);
if( !$res ) { 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."); 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 resources used by image (this is normally not used since all resources are/should be // Clear resources used by image (this is normally not used since all resources are/should be
// returned when the script terminates // returned when the script terminates
function Destroy() { function Destroy() {
imagedestroy($this->img); imagedestroy($this->img);
} }
   
// Specify image format. Note depending on your installation // Specify image format. Note depending on your installation
// of PHP not all formats may be supported. // of PHP not all formats may be supported.
function SetImgFormat($aFormat,$aQuality=75) { function SetImgFormat($aFormat,$aQuality=75) {
$this->quality = $aQuality; $this->quality = $aQuality;
$aFormat = strtolower($aFormat); $aFormat = strtolower($aFormat);
$tst = true; $tst = true;
$supported = imagetypes(); $supported = imagetypes();
if( $aFormat=="auto" ) { if( $aFormat=="auto" ) {
if( $supported & IMG_PNG ) $this->img_format="png"; if( $supported & IMG_PNG ) $this->img_format="png";
elseif( $supported & IMG_JPG ) $this->img_format="jpeg"; elseif( $supported & IMG_JPG ) $this->img_format="jpeg";
elseif( $supported & IMG_GIF ) $this->img_format="gif"; elseif( $supported & IMG_GIF ) $this->img_format="gif";
elseif( $supported & IMG_WBMP ) $this->img_format="wbmp"; elseif( $supported & IMG_WBMP ) $this->img_format="wbmp";
elseif( $supported & IMG_XPM ) $this->img_format="xpm"; elseif( $supported & IMG_XPM ) $this->img_format="xpm";
else { 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."); 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; return true;
} }
else { else {
if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) { if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) {
if( $aFormat=="jpeg" && !($supported & IMG_JPG) ) $tst=false; if( $aFormat=="jpeg" && !($supported & IMG_JPG) ) $tst=false;
elseif( $aFormat=="png" && !($supported & IMG_PNG) ) $tst=false; elseif( $aFormat=="png" && !($supported & IMG_PNG) ) $tst=false;
elseif( $aFormat=="gif" && !($supported & IMG_GIF) ) $tst=false; elseif( $aFormat=="gif" && !($supported & IMG_GIF) ) $tst=false;
elseif( $aFormat=="wbmp" && !($supported & IMG_WBMP) ) $tst=false; elseif( $aFormat=="wbmp" && !($supported & IMG_WBMP) ) $tst=false;
elseif( $aFormat=="xpm" && !($supported & IMG_XPM) ) $tst=false; elseif( $aFormat=="xpm" && !($supported & IMG_XPM) ) $tst=false;
else { else {
$this->img_format=$aFormat; $this->img_format=$aFormat;
return true; return true;
} }
} }
else { else {
$tst=false; $tst=false;
} }
if( !$tst ) { if( !$tst ) {
JpGraphError::RaiseL(25110,$aFormat);//(" Your PHP installation does not support the chosen graphic format: $aFormat"); JpGraphError::RaiseL(25110,$aFormat);//(" Your PHP installation does not support the chosen graphic format: $aFormat");
} }
} }
} }
} // CLASS } // CLASS
   
//=================================================== //===================================================
// CLASS RotImage // CLASS RotImage
// Description: Exactly as Image but draws the image at // Description: Exactly as Image but draws the image at
// a specified angle around a specified rotation point. // a specified angle around a specified rotation point.
//=================================================== //===================================================
class RotImage extends Image { class RotImage extends Image {
public $a=0; public $a=0;
public $dx=0,$dy=0,$transx=0,$transy=0; public $dx=0,$dy=0,$transx=0,$transy=0;
private $m=array(); private $m=array();
   
function __construct($aWidth,$aHeight,$a=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) { function __construct($aWidth,$aHeight,$a=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) {
parent::__construct($aWidth,$aHeight,$aFormat,$aSetAutoMargin); parent::__construct($aWidth,$aHeight,$aFormat,$aSetAutoMargin);
$this->dx=$this->left_margin+$this->plotwidth/2; $this->dx=$this->left_margin+$this->plotwidth/2;
$this->dy=$this->top_margin+$this->plotheight/2; $this->dy=$this->top_margin+$this->plotheight/2;
$this->SetAngle($a); $this->SetAngle($a);
} }
   
function SetCenter($dx,$dy) { function SetCenter($dx,$dy) {
$old_dx = $this->dx; $old_dx = $this->dx;
$old_dy = $this->dy; $old_dy = $this->dy;
$this->dx=$dx; $this->dx=$dx;
$this->dy=$dy; $this->dy=$dy;
$this->SetAngle($this->a); $this->SetAngle($this->a);
return array($old_dx,$old_dy); return array($old_dx,$old_dy);
} }
   
function SetTranslation($dx,$dy) { function SetTranslation($dx,$dy) {
$old = array($this->transx,$this->transy); $old = array($this->transx,$this->transy);
$this->transx = $dx; $this->transx = $dx;
$this->transy = $dy; $this->transy = $dy;
return $old; return $old;
} }
   
function UpdateRotMatrice() { function UpdateRotMatrice() {
$a = $this->a; $a = $this->a;
$a *= M_PI/180; $a *= M_PI/180;
$sa=sin($a); $ca=cos($a); $sa=sin($a); $ca=cos($a);
// Create the rotation matrix // Create the rotation matrix
$this->m[0][0] = $ca; $this->m[0][0] = $ca;
$this->m[0][1] = -$sa; $this->m[0][1] = -$sa;
$this->m[0][2] = $this->dx*(1-$ca) + $sa*$this->dy ; $this->m[0][2] = $this->dx*(1-$ca) + $sa*$this->dy ;
$this->m[1][0] = $sa; $this->m[1][0] = $sa;
$this->m[1][1] = $ca; $this->m[1][1] = $ca;
$this->m[1][2] = $this->dy*(1-$ca) - $sa*$this->dx ; $this->m[1][2] = $this->dy*(1-$ca) - $sa*$this->dx ;
} }
   
function SetAngle($a) { function SetAngle($a) {
$tmp = $this->a; $tmp = $this->a;
$this->a = $a; $this->a = $a;
$this->UpdateRotMatrice(); $this->UpdateRotMatrice();
return $tmp; return $tmp;
} }
   
function Circle($xc,$yc,$r) { function Circle($xc,$yc,$r) {
list($xc,$yc) = $this->Rotate($xc,$yc); list($xc,$yc) = $this->Rotate($xc,$yc);
parent::Circle($xc,$yc,$r); parent::Circle($xc,$yc,$r);
} }
   
function FilledCircle($xc,$yc,$r) { function FilledCircle($xc,$yc,$r) {
list($xc,$yc) = $this->Rotate($xc,$yc); list($xc,$yc) = $this->Rotate($xc,$yc);
parent::FilledCircle($xc,$yc,$r); parent::FilledCircle($xc,$yc,$r);
} }
   
   
function Arc($xc,$yc,$w,$h,$s,$e) { function Arc($xc,$yc,$w,$h,$s,$e) {
list($xc,$yc) = $this->Rotate($xc,$yc); list($xc,$yc) = $this->Rotate($xc,$yc);
$s += $this->a; $s += $this->a;
$e += $this->a; $e += $this->a;
parent::Arc($xc,$yc,$w,$h,$s,$e); parent::Arc($xc,$yc,$w,$h,$s,$e);
} }
   
function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') { function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') {
list($xc,$yc) = $this->Rotate($xc,$yc); list($xc,$yc) = $this->Rotate($xc,$yc);
$s += $this->a; $s += $this->a;
$e += $this->a; $e += $this->a;
parent::FilledArc($xc,$yc,$w,$h,$s,$e); parent::FilledArc($xc,$yc,$w,$h,$s,$e);
} }
   
function SetMargin($lm,$rm,$tm,$bm) { function SetMargin($lm,$rm,$tm,$bm) {
parent::SetMargin($lm,$rm,$tm,$bm); parent::SetMargin($lm,$rm,$tm,$bm);
$this->dx=$this->left_margin+$this->plotwidth/2; $this->dx=$this->left_margin+$this->plotwidth/2;
$this->dy=$this->top_margin+$this->plotheight/2; $this->dy=$this->top_margin+$this->plotheight/2;
$this->UpdateRotMatrice(); $this->UpdateRotMatrice();
} }
   
function Rotate($x,$y) { function Rotate($x,$y) {
// Optimization. Ignore rotation if Angle==0 || Angle==360 // Optimization. Ignore rotation if Angle==0 || Angle==360
if( $this->a == 0 || $this->a == 360 ) { if( $this->a == 0 || $this->a == 360 ) {
return array($x + $this->transx, $y + $this->transy ); return array($x + $this->transx, $y + $this->transy );
} }
else { else {
$x1=round($this->m[0][0]*$x + $this->m[0][1]*$y,1) + $this->m[0][2] + $this->transx; $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; $y1=round($this->m[1][0]*$x + $this->m[1][1]*$y,1) + $this->m[1][2] + $this->transy;
return array($x1,$y1); return array($x1,$y1);
} }
} }
   
function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) { function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) {
list($toX,$toY) = $this->Rotate($toX,$toY); list($toX,$toY) = $this->Rotate($toX,$toY);
parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix); parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix);
   
} }
   
function ArrRotate($pnts) { function ArrRotate($pnts) {
$n = count($pnts)-1; $n = count($pnts)-1;
for($i=0; $i < $n; $i+=2) { for($i=0; $i < $n; $i+=2) {
list ($x,$y) = $this->Rotate($pnts[$i],$pnts[$i+1]); list ($x,$y) = $this->Rotate($pnts[$i],$pnts[$i+1]);
$pnts[$i] = $x; $pnts[$i+1] = $y; $pnts[$i] = $x; $pnts[$i+1] = $y;
} }
return $pnts; return $pnts;
} }
   
function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) { function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
list($x1,$y1) = $this->Rotate($x1,$y1); list($x1,$y1) = $this->Rotate($x1,$y1);
list($x2,$y2) = $this->Rotate($x2,$y2); list($x2,$y2) = $this->Rotate($x2,$y2);
parent::DashedLine($x1,$y1,$x2,$y2,$dash_length,$dash_space); parent::DashedLine($x1,$y1,$x2,$y2,$dash_length,$dash_space);
} }
   
function Line($x1,$y1,$x2,$y2) { function Line($x1,$y1,$x2,$y2) {
list($x1,$y1) = $this->Rotate($x1,$y1); list($x1,$y1) = $this->Rotate($x1,$y1);
list($x2,$y2) = $this->Rotate($x2,$y2); list($x2,$y2) = $this->Rotate($x2,$y2);
parent::Line($x1,$y1,$x2,$y2); parent::Line($x1,$y1,$x2,$y2);
} }
   
function Rectangle($x1,$y1,$x2,$y2) { function Rectangle($x1,$y1,$x2,$y2) {
// Rectangle uses Line() so it will be rotated through that call // Rectangle uses Line() so it will be rotated through that call
parent::Rectangle($x1,$y1,$x2,$y2); parent::Rectangle($x1,$y1,$x2,$y2);
} }
   
function FilledRectangle($x1,$y1,$x2,$y2) { function FilledRectangle($x1,$y1,$x2,$y2) {
if( $y1==$y2 || $x1==$x2 ) if( $y1==$y2 || $x1==$x2 )
$this->Line($x1,$y1,$x2,$y2); $this->Line($x1,$y1,$x2,$y2);
else else
$this->FilledPolygon(array($x1,$y1,$x2,$y1,$x2,$y2,$x1,$y2)); $this->FilledPolygon(array($x1,$y1,$x2,$y1,$x2,$y2,$x1,$y2));
} }
   
function Polygon($pnts,$closed=FALSE,$fast=FALSE) { function Polygon($pnts,$closed=FALSE,$fast=FALSE) {
// Polygon uses Line() so it will be rotated through that call unless // Polygon uses Line() so it will be rotated through that call unless
// fast drawing routines are used in which case a rotate is needed // fast drawing routines are used in which case a rotate is needed
if( $fast ) { if( $fast ) {
parent::Polygon($this->ArrRotate($pnts)); parent::Polygon($this->ArrRotate($pnts));
} }
else { else {
parent::Polygon($pnts,$closed,$fast); parent::Polygon($pnts,$closed,$fast);
} }
} }
   
function FilledPolygon($pnts) { function FilledPolygon($pnts) {
parent::FilledPolygon($this->ArrRotate($pnts)); parent::FilledPolygon($this->ArrRotate($pnts));
} }
   
function Point($x,$y) { function Point($x,$y) {
list($xp,$yp) = $this->Rotate($x,$y); list($xp,$yp) = $this->Rotate($x,$y);
parent::Point($xp,$yp); parent::Point($xp,$yp);
} }
   
function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) { function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) {
list($xp,$yp) = $this->Rotate($x,$y); list($xp,$yp) = $this->Rotate($x,$y);
return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug); return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug);
} }
} }
   
//======================================================================= //=======================================================================
// CLASS ImgStreamCache // CLASS ImgStreamCache
// Description: Handle caching of graphs to files. All image output goes // Description: Handle caching of graphs to files. All image output goes
// through this class // through this class
//======================================================================= //=======================================================================
class ImgStreamCache { class ImgStreamCache {
private $cache_dir, $timeout=0; // Infinite timeout private $cache_dir, $timeout=0; // Infinite timeout
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aCacheDir=CACHE_DIR) { function __construct($aCacheDir=CACHE_DIR) {
$this->cache_dir = $aCacheDir; $this->cache_dir = $aCacheDir;
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
// Specify a timeout (in minutes) for the file. If the file is older then the // 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. // 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 // 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 // timeout is set to -1 this is the same as infinite small timeout
function SetTimeout($aTimeout) { function SetTimeout($aTimeout) {
$this->timeout=$aTimeout; $this->timeout=$aTimeout;
} }
   
// Output image to browser and also write it to the cache // Output image to browser and also write it to the cache
function PutAndStream($aImage,$aCacheFileName,$aInline,$aStrokeFileName) { function PutAndStream($aImage,$aCacheFileName,$aInline,$aStrokeFileName) {
   
// Check if we should always stroke the image to a file // Check if we should always stroke the image to a file
if( _FORCE_IMGTOFILE ) { if( _FORCE_IMGTOFILE ) {
$aStrokeFileName = _FORCE_IMGDIR.GenImgName(); $aStrokeFileName = _FORCE_IMGDIR.GenImgName();
} }
   
if( $aStrokeFileName != '' ) { if( $aStrokeFileName != '' ) {
   
if( $aStrokeFileName == 'auto' ) { if( $aStrokeFileName == 'auto' ) {
$aStrokeFileName = GenImgName(); $aStrokeFileName = GenImgName();
} }
   
if( file_exists($aStrokeFileName) ) { if( file_exists($aStrokeFileName) ) {
   
// Wait for lock (to make sure no readers are trying to access the image) // Wait for lock (to make sure no readers are trying to access the image)
$fd = fopen($aStrokeFileName,'w'); $fd = fopen($aStrokeFileName,'w');
$lock = flock($fd, LOCK_EX); $lock = flock($fd, LOCK_EX);
   
// Since the image write routines only accepts a filename which must not // Since the image write routines only accepts a filename which must not
// exist we need to delete the old file first // exist we need to delete the old file first
if( !@unlink($aStrokeFileName) ) { if( !@unlink($aStrokeFileName) ) {
$lock = flock($fd, LOCK_UN); $lock = flock($fd, LOCK_UN);
JpGraphError::RaiseL(25111,$aStrokeFileName); JpGraphError::RaiseL(25111,$aStrokeFileName);
//(" Can't delete cached image $aStrokeFileName. Permission problem?"); //(" Can't delete cached image $aStrokeFileName. Permission problem?");
} }
$aImage->Stream($aStrokeFileName); $aImage->Stream($aStrokeFileName);
$lock = flock($fd, LOCK_UN); $lock = flock($fd, LOCK_UN);
fclose($fd); fclose($fd);
   
} }
else { else {
$aImage->Stream($aStrokeFileName); $aImage->Stream($aStrokeFileName);
} }
   
return; return;
} }
   
if( $aCacheFileName != '' && USE_CACHE) { if( $aCacheFileName != '' && USE_CACHE) {
   
$aCacheFileName = $this->cache_dir . $aCacheFileName; $aCacheFileName = $this->cache_dir . $aCacheFileName;
if( file_exists($aCacheFileName) ) { if( file_exists($aCacheFileName) ) {
if( !$aInline ) { if( !$aInline ) {
// If we are generating image off-line (just writing to the cache) // If we are generating image off-line (just writing to the cache)
// and the file exists and is still valid (no timeout) // and the file exists and is still valid (no timeout)
// then do nothing, just return. // then do nothing, just return.
$diff=time()-filemtime($aCacheFileName); $diff=time()-filemtime($aCacheFileName);
if( $diff < 0 ) { if( $diff < 0 ) {
JpGraphError::RaiseL(25112,$aCacheFileName); JpGraphError::RaiseL(25112,$aCacheFileName);
//(" Cached imagefile ($aCacheFileName) has file date in the future!!"); //(" Cached imagefile ($aCacheFileName) has file date in the future!!");
} }
if( $this->timeout>0 && ($diff <= $this->timeout*60) ) return; if( $this->timeout>0 && ($diff <= $this->timeout*60) ) return;
} }
   
// Wait for lock (to make sure no readers are trying to access the image) // Wait for lock (to make sure no readers are trying to access the image)
$fd = fopen($aCacheFileName,'w'); $fd = fopen($aCacheFileName,'w');
$lock = flock($fd, LOCK_EX); $lock = flock($fd, LOCK_EX);
   
if( !@unlink($aCacheFileName) ) { if( !@unlink($aCacheFileName) ) {
$lock = flock($fd, LOCK_UN); $lock = flock($fd, LOCK_UN);
JpGraphError::RaiseL(25113,$aStrokeFileName); JpGraphError::RaiseL(25113,$aStrokeFileName);
//(" Can't delete cached image $aStrokeFileName. Permission problem?"); //(" Can't delete cached image $aStrokeFileName. Permission problem?");
} }
$aImage->Stream($aCacheFileName); $aImage->Stream($aCacheFileName);
$lock = flock($fd, LOCK_UN); $lock = flock($fd, LOCK_UN);
fclose($fd); fclose($fd);
   
} }
else { else {
$this->MakeDirs(dirname($aCacheFileName)); $this->MakeDirs(dirname($aCacheFileName));
if( !is_writeable(dirname($aCacheFileName)) ) { if( !is_writeable(dirname($aCacheFileName)) ) {
JpGraphError::RaiseL(25114,$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.'); //('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); $aImage->Stream($aCacheFileName);
} }
   
$res=true; $res=true;
// Set group to specified // Set group to specified
if( CACHE_FILE_GROUP != '' ) { if( CACHE_FILE_GROUP != '' ) {
$res = @chgrp($aCacheFileName,CACHE_FILE_GROUP); $res = @chgrp($aCacheFileName,CACHE_FILE_GROUP);
} }
if( CACHE_FILE_MOD != '' ) { if( CACHE_FILE_MOD != '' ) {
$res = @chmod($aCacheFileName,CACHE_FILE_MOD); $res = @chmod($aCacheFileName,CACHE_FILE_MOD);
} }
if( !$res ) { if( !$res ) {
JpGraphError::RaiseL(25115,$aStrokeFileName); JpGraphError::RaiseL(25115,$aStrokeFileName);
//(" Can't set permission for cached image $aStrokeFileName. Permission problem?"); //(" Can't set permission for cached image $aStrokeFileName. Permission problem?");
} }
   
$aImage->Destroy(); $aImage->Destroy();
if( $aInline ) { if( $aInline ) {
if ($fh = @fopen($aCacheFileName, "rb") ) { if ($fh = @fopen($aCacheFileName, "rb") ) {
$aImage->Headers(); $aImage->Headers();
fpassthru($fh); fpassthru($fh);
return; return;
} }
else { else {
JpGraphError::RaiseL(25116,$aFile);//(" Cant open file from cache [$aFile]"); JpGraphError::RaiseL(25116,$aFile);//(" Cant open file from cache [$aFile]");
} }
} }
} }
elseif( $aInline ) { elseif( $aInline ) {
$aImage->Headers(); $aImage->Headers();
$aImage->Stream(); $aImage->Stream();
return; return;
} }
} }
   
function IsValid($aCacheFileName) { function IsValid($aCacheFileName) {
$aCacheFileName = $this->cache_dir.$aCacheFileName; $aCacheFileName = $this->cache_dir.$aCacheFileName;
if ( USE_CACHE && file_exists($aCacheFileName) ) { if ( USE_CACHE && file_exists($aCacheFileName) ) {
$diff=time()-filemtime($aCacheFileName); $diff=time()-filemtime($aCacheFileName);
if( $this->timeout>0 && ($diff > $this->timeout*60) ) { if( $this->timeout>0 && ($diff > $this->timeout*60) ) {
return false; return false;
} }
else { else {
return true; return true;
} }
} }
else { else {
return false; return false;
} }
} }
   
function StreamImgFile($aImage,$aCacheFileName) { function StreamImgFile($aImage,$aCacheFileName) {
$aCacheFileName = $this->cache_dir.$aCacheFileName; $aCacheFileName = $this->cache_dir.$aCacheFileName;
if ( $fh = @fopen($aCacheFileName, 'rb') ) { if ( $fh = @fopen($aCacheFileName, 'rb') ) {
$lock = flock($fh, LOCK_SH); $lock = flock($fh, LOCK_SH);
$aImage->Headers(); $aImage->Headers();
fpassthru($fh); fpassthru($fh);
$lock = flock($fh, LOCK_UN); $lock = flock($fh, LOCK_UN);
fclose($fh); fclose($fh);
return true; return true;
} }
else { else {
JpGraphError::RaiseL(25117,$aCacheFileName);//(" Can't open cached image \"$aCacheFileName\" for reading."); JpGraphError::RaiseL(25117,$aCacheFileName);//(" Can't open cached image \"$aCacheFileName\" for reading.");
} }
} }
   
// Check if a given image is in cache and in that case // Check if a given image is in cache and in that case
// pass it directly on to web browser. Return false if the // pass it directly on to web browser. Return false if the
// image file doesn't exist or exists but is to old // image file doesn't exist or exists but is to old
function GetAndStream($aImage,$aCacheFileName) { function GetAndStream($aImage,$aCacheFileName) {
if( $this->Isvalid($aCacheFileName) ) { if( $this->Isvalid($aCacheFileName) ) {
$this->StreamImgFile($aImage,$aCacheFileName); $this->StreamImgFile($aImage,$aCacheFileName);
} }
else { else {
return false; return false;
} }
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
// Create all necessary directories in a path // Create all necessary directories in a path
function MakeDirs($aFile) { function MakeDirs($aFile) {
$dirs = array(); $dirs = array();
// In order to better work when open_basedir is enabled // In order to better work when open_basedir is enabled
// we do not create directories in the root path // we do not create directories in the root path
while ( $aFile != '/' && !(file_exists($aFile)) ) { while ( $aFile != '/' && !(file_exists($aFile)) ) {
$dirs[] = $aFile.'/'; $dirs[] = $aFile.'/';
$aFile = dirname($aFile); $aFile = dirname($aFile);
} }
for ($i = sizeof($dirs)-1; $i>=0; $i--) { for ($i = sizeof($dirs)-1; $i>=0; $i--) {
if(! @mkdir($dirs[$i],0777) ) { if(! @mkdir($dirs[$i],0777) ) {
JpGraphError::RaiseL(25118,$aFile);//(" Can't create directory $aFile. Make sure PHP has write permission to this directory."); 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. // We also specify mode here after we have changed group.
// This is necessary if Apache user doesn't belong the // This is necessary if Apache user doesn't belong the
// default group and hence can't specify group permission // default group and hence can't specify group permission
// in the previous mkdir() call // in the previous mkdir() call
if( CACHE_FILE_GROUP != "" ) { if( CACHE_FILE_GROUP != "" ) {
$res=true; $res=true;
$res =@chgrp($dirs[$i],CACHE_FILE_GROUP); $res =@chgrp($dirs[$i],CACHE_FILE_GROUP);
$res = @chmod($dirs[$i],0777); $res = @chmod($dirs[$i],0777);
if( !$res ) { if( !$res ) {
JpGraphError::RaiseL(25119,$aFile);//(" Can't set permissions for $aFile. Permission problems?"); JpGraphError::RaiseL(25119,$aFile);//(" Can't set permissions for $aFile. Permission problems?");
} }
} }
} }
return true; return true;
} }
} // CLASS Cache } // CLASS Cache
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: IMGDATA_ROUNDBALLS.INC // File: IMGDATA_ROUNDBALLS.INC
// Description: Base64 encoded images for small round markers // Description: Base64 encoded images for small round markers
// Created: 2003-03-20 // Created: 2003-03-20
// Ver: $Id: imgdata_balls.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: imgdata_balls.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class ImgData_Balls extends ImgData { class ImgData_Balls extends ImgData {
protected $name = 'Round Balls'; protected $name = 'Round Balls';
protected $an = array(MARK_IMG_LBALL => 'imgdata_large', protected $an = array(MARK_IMG_LBALL => 'imgdata_large',
MARK_IMG_MBALL => 'imgdata_small', MARK_IMG_MBALL => 'imgdata_small',
MARK_IMG_SBALL => 'imgdata_xsmall', MARK_IMG_SBALL => 'imgdata_xsmall',
MARK_IMG_BALL => 'imgdata_xsmall'); MARK_IMG_BALL => 'imgdata_xsmall');
protected $colors,$index,$maxidx; protected $colors,$index,$maxidx;
private $colors_1 = array('blue','lightblue','brown','darkgreen', private $colors_1 = array('blue','lightblue','brown','darkgreen',
'green','purple','red','gray','yellow','silver','gray'); 'green','purple','red','gray','yellow','silver','gray');
private $index_1 = array('blue'=>9,'lightblue'=>1,'brown'=>6,'darkgreen'=>7, private $index_1 = array('blue'=>9,'lightblue'=>1,'brown'=>6,'darkgreen'=>7,
'green'=>8,'purple'=>4,'red'=>0,'gray'=>5,'silver'=>3,'yellow'=>2); 'green'=>8,'purple'=>4,'red'=>0,'gray'=>5,'silver'=>3,'yellow'=>2);
private $maxidx_1 = 9 ; private $maxidx_1 = 9 ;
   
private $colors_2 = array('blue','bluegreen','brown','cyan', private $colors_2 = array('blue','bluegreen','brown','cyan',
'darkgray','greengray','gray','green', 'darkgray','greengray','gray','green',
'greenblue','lightblue','lightred', 'greenblue','lightblue','lightred',
'purple','red','white','yellow'); 'purple','red','white','yellow');
   
private $index_2 = array('blue'=>9,'bluegreen'=>13,'brown'=>8,'cyan'=>12, private $index_2 = array('blue'=>9,'bluegreen'=>13,'brown'=>8,'cyan'=>12,
'darkgray'=>5,'greengray'=>6,'gray'=>2,'green'=>10, 'darkgray'=>5,'greengray'=>6,'gray'=>2,'green'=>10,
'greenblue'=>3,'lightblue'=>1,'lightred'=>14, 'greenblue'=>3,'lightblue'=>1,'lightred'=>14,
'purple'=>7,'red'=>0,'white'=>11,'yellow'=>4); 'purple'=>7,'red'=>0,'white'=>11,'yellow'=>4);
private $maxidx_2 = 14 ; private $maxidx_2 = 14 ;
   
   
private $colors_3 = array('bluegreen','cyan','darkgray','greengray', private $colors_3 = array('bluegreen','cyan','darkgray','greengray',
'gray','graypurple','green','greenblue','lightblue', 'gray','graypurple','green','greenblue','lightblue',
'lightred','navy','orange','purple','red','yellow'); 'lightred','navy','orange','purple','red','yellow');
   
private $index_3 = array('bluegreen'=>1,'cyan'=>11,'darkgray'=>14,'greengray'=>10, private $index_3 = array('bluegreen'=>1,'cyan'=>11,'darkgray'=>14,'greengray'=>10,
'gray'=>3,'graypurple'=>4,'green'=>9,'greenblue'=>7, 'gray'=>3,'graypurple'=>4,'green'=>9,'greenblue'=>7,
'lightblue'=>13,'lightred'=>0,'navy'=>2,'orange'=>12, 'lightblue'=>13,'lightred'=>0,'navy'=>2,'orange'=>12,
'purple'=>8,'red'=>5,'yellow'=>6); 'purple'=>8,'red'=>5,'yellow'=>6);
private $maxidx_3 = 14 ; private $maxidx_3 = 14 ;
   
protected $imgdata_large, $imgdata_small, $imgdata_xsmall ; protected $imgdata_large, $imgdata_small, $imgdata_xsmall ;
   
   
function GetImg($aMark,$aIdx) { function GetImg($aMark,$aIdx) {
switch( $aMark ) { switch( $aMark ) {
case MARK_IMG_SBALL: case MARK_IMG_SBALL:
case MARK_IMG_BALL: case MARK_IMG_BALL:
$this->colors = $this->colors_3; $this->colors = $this->colors_3;
$this->index = $this->index_3 ; $this->index = $this->index_3 ;
$this->maxidx = $this->maxidx_3 ; $this->maxidx = $this->maxidx_3 ;
break; break;
case MARK_IMG_MBALL: case MARK_IMG_MBALL:
$this->colors = $this->colors_2; $this->colors = $this->colors_2;
$this->index = $this->index_2 ; $this->index = $this->index_2 ;
$this->maxidx = $this->maxidx_2 ; $this->maxidx = $this->maxidx_2 ;
break; break;
default: default:
$this->colors = $this->colors_1; $this->colors = $this->colors_1;
$this->index = $this->index_1 ; $this->index = $this->index_1 ;
$this->maxidx = $this->maxidx_1 ; $this->maxidx = $this->maxidx_1 ;
break; break;
} }
return parent::GetImg($aMark,$aIdx); return parent::GetImg($aMark,$aIdx);
} }
   
function __construct() { function __construct() {
   
//========================================================== //==========================================================
// File: bl_red.png // File: bl_red.png
//========================================================== //==========================================================
$this->imgdata_large[0][0]= 1072 ; $this->imgdata_large[0][0]= 1072 ;
$this->imgdata_large[0][1]= $this->imgdata_large[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAByF'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAByF'.
'BMVEX/////////xsb/vb3/lIz/hIT/e3v/c3P/c2v/a2v/Y2P/'. 'BMVEX/////////xsb/vb3/lIz/hIT/e3v/c3P/c2v/a2v/Y2P/'.
'UlL/Skr/SkL/Qjn/MTH/MSn/KSn/ISH/IRj/GBj/GBD/EBD/EA'. 'UlL/Skr/SkL/Qjn/MTH/MSn/KSn/ISH/IRj/GBj/GBD/EBD/EA'.
'j/CAj/CAD/AAD3QkL3MTH3KSn3KSH3GBj3EBD3CAj3AAD1zMzv'. 'j/CAj/CAD/AAD3QkL3MTH3KSn3KSH3GBj3EBD3CAj3AAD1zMzv'.
'QkLvISHvIRjvGBjvEBDvEAjvAADnUlLnSkrnMTnnKSnnIRjnGB'. 'QkLvISHvIRjvGBjvEBDvEAjvAADnUlLnSkrnMTnnKSnnIRjnGB'.
'DnEBDnCAjnAADec3PeSkreISHeGBjeGBDeEAjWhITWa2vWUlLW'. 'DnEBDnCAjnAADec3PeSkreISHeGBjeGBDeEAjWhITWa2vWUlLW'.
'SkrWISnWGBjWEBDWEAjWCAjWAADOnp7Oa2vOGCHOGBjOGBDOEB'. 'SkrWISnWGBjWEBDWEAjWCAjWAADOnp7Oa2vOGCHOGBjOGBDOEB'.
'DOCAjOAADJrq7Gt7fGGBjGEBDGCAjGAADEpKS/v7+9QkK9GBC9'. 'DOCAjOAADJrq7Gt7fGGBjGEBDGCAjGAADEpKS/v7+9QkK9GBC9'.
'EBC9CAi9AAC1e3u1a2u1Skq1KSm1EBC1CAi1AACtEBCtCBCtCA'. 'EBC9CAi9AAC1e3u1a2u1Skq1KSm1EBC1CAi1AACtEBCtCBCtCA'.
'itAACngYGlCAilAACghIScOTmcCAicAACYgYGUGAiUCAiUAAiU'. 'itAACngYGlCAilAACghIScOTmcCAicAACYgYGUGAiUCAiUAAiU'.
'AACMKSmMEACMAACEa2uEGAiEAAB7GBh7CAB7AABzOTlzGBBzCA'. 'AACMKSmMEACMAACEa2uEGAiEAAB7GBh7CAB7AABzOTlzGBBzCA'.
'BzAABrSkprOTlrGBhrAABjOTljAABaQkJaOTlaCABaAABSKSlS'. 'BzAABrSkprOTlrGBhrAABjOTljAABaQkJaOTlaCABaAABSKSlS'.
'GBhSAABKKSlKGBhKAABCGBhCCABCAAA5CAA5AAAxCAAxAAApCA'. 'GBhSAABKKSlKGBhKAABCGBhCCABCAAA5CAA5AAAxCAAxAAApCA'.
'ApAAAhAAAYAACc9eRyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. 'ApAAAhAAAYAACc9eRyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFD'. 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFD'.
'UHLytKAAAB4UlEQVR4nGNgIAK4mGjrmNq6BmFIWMmISUpKSmk5'. 'UHLytKAAAB4UlEQVR4nGNgIAK4mGjrmNq6BmFIWMmISUpKSmk5'.
'B8ZEokj4qoiLiQCBgqald3xaBpKMj6y4sLCQkJCIvIaFV0RaUR'. 'B8ZEokj4qoiLiQCBgqald3xaBpKMj6y4sLCQkJCIvIaFV0RaUR'.
'lCSk5cWEiAn19ASN7QwisuraihHiajKyEixM/NwckjoKrvEACU'. 'lCSk5cWEiAn19ASN7QwisuraihHiajKyEixM/NwckjoKrvEACU'.
'qumpg7pAUlREiJdNmZmLT9/cMzwps7Smc3I2WEpGUkxYkJuFiY'. 'qumpg7pAUlREiJdNmZmLT9/cMzwps7Smc3I2WEpGUkxYkJuFiY'.
'lTxszePzY1v7Shc2oX2D+K4iLCgjzsrOw8embuYUmZeTVtPVOn'. 'lTxszePzY1v7Shc2oX2D+K4iLCgjzsrOw8embuYUmZeTVtPVOn'.
'gqSslYAOF+Ln4ZHWtXMPTcjMrWno7J82rRgoZWOsqaCgrqaqqm'. 'gqSslYAOF+Ln4ZHWtXMPTcjMrWno7J82rRgoZWOsqaCgrqaqqm'.
'fn5peQmlsK1DR52vRaoFSIs5GRoYG5ub27n19CYm5pdVPnxKnT'. 'fn5peQmlsK1DR52vRaoFSIs5GRoYG5ub27n19CYm5pdVPnxKnT'.
'pjWDpLydnZwcHTz8QxMSEnJLgDL9U6dNnQ6Sio4PDAgICA+PTU'. 'pjWDpLydnZwcHTz8QxMSEnJLgDL9U6dNnQ6Sio4PDAgICA+PTU'.
'zNzSkph8hADIxKS46Pj0tKTc3MLSksqWrtmQySAjuDIT8rKy0r'. 'zNzSkph8hADIxKS46Pj0tKTc3MLSksqWrtmQySAjuDIT8rKy0r'.
'Kz+vtLSmur6jb9JUIJgGdjxDQUVRUVFpaUVNQ1NrZ9+kKVOmTZ'. 'Kz+vtLSmur6jb9JUIJgGdjxDQUVRUVFpaUVNQ1NrZ9+kKVOmTZ'.
'k6vR0sldJUAwQNTU2dnX0TgOJTQLrSIYFY2dPW1NbW2TNxwtQp'. 'k6vR0sldJUAwQNTU2dnX0TgOJTQLrSIYFY2dPW1NbW2TNxwtQp'.
'U6ZMmjJt2rRGWNB3TO7vnzh5MsgSoB6gy7sREdY7bRrQEDAGOb'. 'U6ZMmjJt2rRGWNB3TO7vnzh5MsgSoB6gy7sREdY7bRrQEDAGOb'.
'wXOQW0TJsOEpwClmxBTTbZ7UDVIPkp7dkYaYqhuLa5trYYUxwL'. 'wXOQW0TJsOEpwClmxBTTbZ7UDVIPkp7dkYaYqhuLa5trYYUxwL'.
'AADzm6uekAAcXAAAAABJRU5ErkJggg==' ; 'AADzm6uekAAcXAAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bl_bluegreen.png // File: bl_bluegreen.png
//========================================================== //==========================================================
$this->imgdata_large[1][0]= 1368 ; $this->imgdata_large[1][0]= 1368 ;
$this->imgdata_large[1][1]= $this->imgdata_large[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMMFi8hE9b2uAAABOVJREFUeNq9lk2sJFUVx3+3qv'. 'B3RJTUUH0wMMFi8hE9b2uAAABOVJREFUeNq9lk2sJFUVx3+3qv'.
'tW95t57zFvhiFxmCFRUJRoNCQiJARMhiFx/Igxii5goTG6ZDAu'. 'tW95t57zFvhiFxmCFRUJRoNCQiJARMhiFx/Igxii5goTG6ZDAu'.
'/EhcSCIrTAgLEiKsJ8ywABNZEMJXEDYCukAmjgjzBkK/j35V1d'. '/EhcSCIrTAgLEiKsJ8ywABNZEMJXEDYCukAmjgjzBkK/j35V1d'.
'333FtV97io97pfzwxfG86qcu/N+Z3zP+fcW/Apmfk4hx57+R/6'. '333FtV97io97pfzwxfG86qcu/N+Z3zP+fcW/Apmfk4hx57+R/6'.
'Rqmc9ykhsWjlsUngAA1fXIQ7b73pI/186IGHnn9dH/8frC8v4I'. 'Rqmc9ykhsWjlsUngAA1fXIQ7b73pI/186IGHnn9dH/8frC8v4I'.
'PiG53uaerR4GmKkv31mB8cyfjd946ZTwR66qVX9OTWIi8UKUv9'. 'PiG53uaerR4GmKkv31mB8cyfjd946ZTwR66qVX9OTWIi8UKUv9'.
'BOrZXpYZvFeiBvzI0fgSUSFKwbVG+Pl1V3HH0VvNR4KeeukV/f'. 'BOrZXpYZvFeiBvzI0fgSUSFKwbVG+Pl1V3HH0VvNR4KeeukV/f'.
'PmMmdHhst76aXD64AbeVQ9bjNHaiGOC2o3wLrAb2/4LL/84ffn'. 'PmMmdHhst76aXD64AbeVQ9bjNHaiGOC2o3wLrAb2/4LL/84ffn'.
'fCdzkOdayKpLppBemrBsU5Y1Zdmm9LJdGU6E/t4M24Q26jRDRL'. 'fCdzkOdayKpLppBemrBsU5Y1Zdmm9LJdGU6E/t4M24Q26jRDRL'.
'j3mdc49cSTekFsMzs5XuTsyLDUNSDQ25NwKOly9YIl22MYhJr/'. 'j3mdc49cSTekFsMzs5XuTsyLDUNSDQ25NwKOly9YIl22MYhJr/'.
'uoDtBBoT0CxBRGYOAhibIaOCe//2MpfM6KHnX9cXipSlbkKWmS'. 'uoDtBBoT0CxBRGYOAhibIaOCe//2MpfM6KHnX9cXipSlbkKWmS'.
'nk9iv38J0jixw7vJfrTMYBOvhSoQHJBS09ANELloAGDxW8tfoW'. 'nk9iv38J0jixw7vJfrTMYBOvhSoQHJBS09ANELloAGDxW8tfoW'.
'J+5/UC8CPS0LU7r3SpYarr7M8rmFjMPLXT6/33L4si7Z2GCrQC'. 'J+5/UC8CPS0LU7r3SpYarr7M8rmFjMPLXT6/33L4si7Z2GCrQC'.
'+0ctlOaNs9DReV8vSLr85ndPLpZ/WNvHW+01kAVFBOGvJx0wYg'. '+0ctlOaNs9DReV8vSLr85ndPLpZ/WNvHW+01kAVFBOGvJx0wYg'.
'Sp47RIQ4Emwa8FGJXlDxSCFo5YlVgAo2hwPue/hRndboTV3EW2'. 'Sp47RIQ4Emwa8FGJXlDxSCFo5YlVgAo2hwPue/hRndboTV3EW2'.
'Wp3k6wBp8q56QiWzecW6vwQfnPRkAWhFgILnq08jQ+R2nlUzzN'. 'Wp3k6wBp8q56QiWzecW6vwQfnPRkAWhFgILnq08jQ+R2nlUzzN'.
'uES9Q7Vd+9fba7NmWJW61db2247qACmcjxXr45psYphsFGSLBu'. 'uES9Q7Vd+9fba7NmWJW61db2247qACmcjxXr45psYphsFGSLBu'.
'kIajxqtjNwHkvAjQt0sg3crhPA2+fPz0CuyNFOghsGsr19mnFg'. 'kIajxqtjNwHkvAjQt0sg3crhPA2+fPz0CuyNFOghsGsr19mnFg'.
'DGwrRm8UoAtNmQPQtRXDgdC4HImCFEKcCE0oieUWUYq2LtbiGp'. 'DGwrRm8UoAtNmQPQtRXDgdC4HImCFEKcCE0oieUWUYq2LtbiGp'.
'mBQmppfIkjw45DK0QNNkvQ0jMBtPL0UnDRM1rN+cxKwzvOo2NP'. 'mBQmppfIkjw45DK0QNNkvQ0jMBtPL0UnDRM1rN+cxKwzvOo2NP'.
'tykR9a1kfpZNDLMG6QDYJqCTBvUe1+uxs+YKyPoGrTwY2HhvC4'. 'tykR9a1kfpZNDLMG6QDYJqCTBvUe1+uxs+YKyPoGrTwY2HhvC4'.
'CDWQd5d4xNApNQEEMgjgLdUCLBQ5cprL/trwNwKG2IUmDqDFd5'. 'CDWQd5d4xNApNQEEMgjgLdUCLBQ5cprL/trwNwKG2IUmDqDFd5'.
'sr5BWrlxuSdLDFEFlqAzXGc4zFjupqh6uqYihpxJcEgp026l2w'. 'sr5BWrlxuSdLDFEFlqAzXGc4zFjupqh6uqYihpxJcEgp026l2w'.
'7wFUv7Z6AvrfRo/n0OYzPwIKE3HUKAJg2otMBiElnsF7wngis9'. '7wFUv7Z6AvrfRo/n0OYzPwIKE3HUKAJg2otMBiElnsF7wngis9'.
'3ZDjNnLi7huCWUZfueZKTu/M0V3HvmkOFDVxVKDG04ScejSgW5'. '3ZDjNnLi7huCWUZfueZKTu/M0V3HvmkOFDVxVKDG04ScejSgW5'.
'V0q5JYFEghuDLHlTmToqDeGOCKIVtrW9hsdmXufEcNLPSXuPHa'. 'V0q5JYFEghuDLHlTmToqDeGOCKIVtrW9hsdmXufEcNLPSXuPHa'.
'a+bvuh9df5AH/v5PDFmbWQC3Mx+TVvfGVTRB2CodNgT2JBX003'. 'a+bvuh9df5AH/v5PDFmbWQC3Mx+TVvfGVTRB2CodNgT2JBX003'.
'aANZAYS/BxCv32TV/l2C03G7jgmfjGiT/qmeEmibEYm7XzAO2k'. 'aANZAYS/BxCv32TV/l2C03G7jgmfjGiT/qmeEmibEYm7XzAO2k'.
'A+pbgHhBgydqu54YO5eRiLCy7yDvPP6Xqf+5Z+Lu277OYuOpiw'. 'A+pbgHhBgydqu54YO5eRiLCy7yDvPP6Xqf+5Z+Lu277OYuOpiw'.
'H15oBmlNOMcmK5RbP+PrEscGU+DSAxdg4CICIkxnLP8aNz63Og'. 'H15oBmlNOMcmK5RbP+PrEscGU+DSAxdg4CICIkxnLP8aNz63Og'.
'H3/rdvOb795GVhuaYo0oBc3GGrEsUPVTwO6a7LYd+X51x3Hu/t'. 'H3/rdvOb795GVhuaYo0oBc3GGrEsUPVTwO6a7LYd+X51x3Hu/t'.
'lP5tS65FN+6okn9U+n/sqb596dTvhOF+02myXTmkQNrOw7yD3H'. 'lP5tS65FN+6okn9U+n/sqb596dTvhOF+02myXTmkQNrOw7yD3H'.
'j14E+UDQjp24/0E9/eKrbA4HH3aMK1b2ccvXvswjv//1J/s5ud'. 'j14E+UDQjp24/0E9/eKrbA4HH3aMK1b2ccvXvswjv//1J/s5ud'.
'Due/hRPfP+OmfOrk7vrn7a48ihA3zh8CH+8Iuffiw/n4r9H1ZZ'. 'Due/hRPfP+OmfOrk7vrn7a48ihA3zh8CH+8Iuffiw/n4r9H1ZZ'.
'0zz7G56hAAAAAElFTkSuQmCC' ; '0zz7G56hAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bl_yellow.png // File: bl_yellow.png
//========================================================== //==========================================================
$this->imgdata_large[2][0]= 1101 ; $this->imgdata_large[2][0]= 1101 ;
$this->imgdata_large[2][1]= $this->imgdata_large[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'.
'BMVEX//////////+///+f//9b//8b//73//7X//63//6X//5T/'. 'BMVEX//////////+///+f//9b//8b//73//7X//63//6X//5T/'.
'/4z//4T//3P//2v//1r//0r//0L//zH//yn//yH//xj//xD//w'. '/4z//4T//3P//2v//1r//0r//0L//zH//yn//yH//xj//xD//w'.
'j//wD/90L/9zn/9zH/9xj/9xD/9wj/9wD39yn37zn37zH37yH3'. 'j//wD/90L/9zn/9zH/9xj/9xD/9wj/9wD39yn37zn37zH37yH3'.
'7xD37wj37wDv70Lv50rv50Lv5znv5yHv5xjv5wjv5wDn51Ln5x'. '7xD37wj37wDv70Lv50rv50Lv5znv5yHv5xjv5wjv5wDn51Ln5x'.
'Dn3jHn3iHn3hjn3hDn3gje3oze3nPe3lLe1oze1nPe1lLe1ine'. 'Dn3jHn3iHn3hjn3hDn3gje3oze3nPe3lLe1oze1nPe1lLe1ine'.
'1iHe1hje1hDe1gje1gDW1qXW1mvWzqXWzkLWzhjWzhDWzgjWzg'. '1iHe1hje1hDe1gje1gDW1qXW1mvWzqXWzkLWzhjWzhDWzgjWzg'.
'DOzrXOzq3OzpzOzgDOxkrOxinOxhjOxhDOxgjOxgDGxqXGxnvG'. 'DOzrXOzq3OzpzOzgDOxkrOxinOxhjOxhDOxgjOxgDGxqXGxnvG'.
'xmvGvRjGvRDGvQjGvQDFxbnAvr6/v7+9vaW9vZS9vQi9vQC9tR'. 'xmvGvRjGvRDGvQjGvQDFxbnAvr6/v7+9vaW9vZS9vQi9vQC9tR'.
'C9tQi9tQC7u7W1tZS1tXu1tTG1tQi1rRC1rQi1rQCtrYytrSGt'. 'C9tQi9tQC7u7W1tZS1tXu1tTG1tQi1rRC1rQi1rQCtrYytrSGt'.
'rQitrQCtpYStpSGtpQitpQClpYSlpXulpQClnBClnAilnACcnG'. 'rQitrQCtpYStpSGtpQitpQClpYSlpXulpQClnBClnAilnACcnG'.
'ucnAicnACclAiclACUlFqUlCmUlAiUlACUjFKUjAiUjACMjFKM'. 'ucnAicnACclAiclACUlFqUlCmUlAiUlACUjFKUjAiUjACMjFKM'.
'jEqMjACMhACEhACEewB7ezF7exB7ewB7cwBzcylzcwBzaxBzaw'. 'jEqMjACMhACEhACEewB7ezF7exB7ewB7cwBzcylzcwBzaxBzaw'.
'BraxhrawhrawBrYxBrYwBjYwBjWgBaWgBaUgCXBwRMAAAAAXRS'. 'BraxhrawhrawBrYxBrYwBjYwBjWgBaWgBaUgCXBwRMAAAAAXRS'.
'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
'LdfvwAAAAHdElNRQfTAwkRFBKiJZ4hAAAB7ElEQVR4nI3S+1vS'. 'LdfvwAAAAHdElNRQfTAwkRFBKiJZ4hAAAB7ElEQVR4nI3S+1vS'.
'UBgHcB67WJmIMWAVdDHEDLBC6Go0slj3Ft0m9RRBWQEmFZFDEM'. 'UBgHcB67WJmIMWAVdDHEDLBC6Go0slj3Ft0m9RRBWQEmFZFDEM'.
'Qgt0EMFBY7p/+198hj1kM/9N1+++x73rOd6XT/kStnTx4fPzd9'. 'Qgt0EMFBY7p/+198hj1kM/9N1+++x73rOd6XT/kStnTx4fPzd9'.
'uwfOjFhomj7smAhwj/6Cm2O0xUwy6g7cCL99uCW3jtBmE7lsdr'. 'uwfOjFhomj7smAhwj/6Cm2O0xUwy6g7cCL99uCW3jtBmE7lsdr'.
'fvejgpzP7uEDFRRoqy2k8xQPnypo2BUMP6waF9Vpf3ciiSzErL'. 'fvejgpzP7uEDFRRoqy2k8xQPnypo2BUMP6waF9Vpf3ciiSzErL'.
'XTkPc0zDe3bsHDAcc00yoVgqL3UWN2iENpspff+2vn6D0+NnZ9'. 'XTkPc0zDe3bsHDAcc00yoVgqL3UWN2iENpspff+2vn6D0+NnZ9'.
'6lC5K6RuSqBTZn1O/a3rd7v/MSez+WyIpVFX8GuuCA9SjD4N6B'. '6lC5K6RuSqBTZn1O/a3rd7v/MSez+WyIpVFX8GuuCA9SjD4N6B'.
'oRNTfo5PCAVR0fBXoIuOQzab1XjwwNHx00GOj8/nKtV1DdeArk'. 'oRNTfo5PCAVR0fBXoIuOQzab1XjwwNHx00GOj8/nKtV1DdeArk'.
'24R+0ul9PjmbrHPYl+EipyU0OoQSjg8/m83kl/MMhx0fjCkqio'. '24R+0ul9PjmbrHPYl+EipyU0OoQSjg8/m83kl/MMhx0fjCkqio'.
'SMOE7t4JMAzDsizH81AqSdW2hroLPg4/CEF4PhKNx98vlevrbY'. 'SMOE7t4JMAzDsizH81AqSdW2hroLPg4/CEF4PhKNx98vlevrbY'.
'QQXgV6kXwVfjkTiSXmhYVcSa7DIE1DOENe7GM6lUym0l+EXKks'. 'QQXgV6kXwVfjkTiSXmhYVcSa7DIE1DOENe7GM6lUym0l+EXKks'.
'K20VAeH2M0JvVgrZfL5Qqkiy0lRVaMBd7H7EZUmsiJJcrTdVja'. 'K20VAeH2M0JvVgrZfL5Qqkiy0lRVaMBd7H7EZUmsiJJcrTdVja'.
'wGpdbTLj3/3qwrUOjAfGgg4LnNA5tdQx14Hm00QFBm65hfNzAm'. 'wGpdbTLj3/3qwrUOjAfGgg4LnNA5tdQx14Hm00QFBm65hfNzAm'.
'+yIFhFtzuj+z2MI/MQn6Uez5pz4Ua41G7VumB/6RX4zMr1TKBr'. '+yIFhFtzuj+z2MI/MQn6Uez5pz4Ua41G7VumB/6RX4zMr1TKBr'.
'SXAAAAAElFTkSuQmCC' ; 'SXAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bl_silver.png // File: bl_silver.png
//========================================================== //==========================================================
$this->imgdata_large[3][0]= 1481 ; $this->imgdata_large[3][0]= 1481 ;
$this->imgdata_large[3][1]= $this->imgdata_large[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAADAF'. 'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAADAF'.
'BMVEUAAADOzs7Gxsa9vb21tbXOxsbOzsbGzsb3///O1ta1vb2c'. 'BMVEUAAADOzs7Gxsa9vb21tbXOxsbOzsbGzsb3///O1ta1vb2c'.
'paVSWlpKWlpSY2ve5+97hIze7/9aY2vO5/9zhJRaa3tSY3PGzt'. 'paVSWlpKWlpSY2ve5+97hIze7/9aY2vO5/9zhJRaa3tSY3PGzt'.
'aMlJxrc3tja3NKUlpCSlK1vcZze4RSWmPW5/+Upb3G3v9zhJxS'. 'aMlJxrc3tja3NKUlpCSlK1vcZze4RSWmPW5/+Upb3G3v9zhJxS'.
'Y3t7jKVaa4TO3veltc6ElK1re5Rjc4ycpbV7hJRaY3M5QlLn7/'. 'Y3t7jKVaa4TO3veltc6ElK1re5Rjc4ycpbV7hJRaY3M5QlLn7/'.
'/Gzt6lrb2EjJzO3v9ja3vG1ve9zu+1xueltdacrc6UpcaMnL1C'. '/Gzt6lrb2EjJzO3v9ja3vG1ve9zu+1xueltdacrc6UpcaMnL1C'.
'SlqElLV7jK1zhKVre5zW3u/O1ue1vc6ttcaMlKVze4xrc4RSWm'. 'SlqElLV7jK1zhKVre5zW3u/O1ue1vc6ttcaMlKVze4xrc4RSWm'.
'tKUmPG1v+9zve1xu+tveeltd6crdbe5/+9xt6cpb17hJxaY3s5'. 'tKUmPG1v+9zve1xu+tveeltd6crdbe5/+9xt6cpb17hJxaY3s5'.
'QlrW3vfO1u/Gzue1vdattc6lrcaUnLWMlK2EjKVze5Rrc4xja4'. 'QlrW3vfO1u/Gzue1vdattc6lrcaUnLWMlK2EjKVze5Rrc4xja4'.
'RSWnNKUmtCSmO9xuecpcZ7hKVaY4TW3v/O1vfGzu+1vd6ttdal'. 'RSWnNKUmtCSmO9xuecpcZ7hKVaY4TW3v/O1vfGzu+1vd6ttdal'.
'rc69xu+UnL2MlLWEjK1ze5xrc5R7hK1ja4zO1v+1veettd6lrd'. 'rc69xu+UnL2MlLWEjK1ze5xrc5R7hK1ja4zO1v+1veettd6lrd'.
'aMlL3Gzv/39//W1t7Gxs61tb29vcatrbWlpa2cnKWUlJyEhIx7'. 'aMlL3Gzv/39//W1t7Gxs61tb29vcatrbWlpa2cnKWUlJyEhIx7'.
'e4TW1ufGxta1tcZSUlqcnK3W1u+UlKW9vda1tc57e4ytrcalpb'. 'e4TW1ufGxta1tcZSUlqcnK3W1u+UlKW9vda1tc57e4ytrcalpb'.
'1ra3vOzu9jY3OUlK29vd6MjKWEhJxaWmtSUmNzc4xKSlpjY3tK'. '1ra3vOzu9jY3OUlK29vd6MjKWEhJxaWmtSUmNzc4xKSlpjY3tK'.
'SmNCQlqUjJzOxs7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'SmNCQlqUjJzOxs7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
'AAAAAAAAAAAAAAAAAAAAAAAAD///9fnkWVAAAAAnRSTlP/AOW3'. 'AAAAAAAAAAAAAAAAAAAAAAAAD///9fnkWVAAAAAnRSTlP/AOW3'.
'MEoAAAABYktHRP+lB/LFAAAACXBIWXMAAABFAAAARQBP+QatAA'. 'MEoAAAABYktHRP+lB/LFAAAACXBIWXMAAABFAAAARQBP+QatAA'.
'AB/klEQVR42mNgxAsYqCdd3+lcb4hLmj8wMMvEu8DCMqYbU9op'. 'AB/klEQVR42mNgxAsYqCdd3+lcb4hLmj8wMMvEu8DCMqYbU9op'.
'UEFB2MTb26eyysomFl06XEEhUCHLpAKo2z/fujikEUVaXUFBMB'. 'UEFB2MTb26eyysomFl06XEEhUCHLpAKo2z/fujikEUVaXUFBMB'.
'BouLePuV+VVWGRciIXknSEsImCQd3//xwmPr65llaFcSFJHkjS'. 'BouLePuV+VVWGRciIXknSEsImCQd3//xwmPr65llaFcSFJHkjS'.
'3iYmWUDZ//8NfCr989NjNUMSUyTg0jneSiaCINn/gmlVQM12qg'. '3iYmWUDZ//8NfCr989NjNUMSUyTg0jneSiaCINn/gmlVQM12qg'.
'lJnp5waTMTE5NAkCyHWZW/lXWNfUlikmdYK0zax7siS4EDKJtd'. 'lJnp5waTMTE5NAkCyHWZW/lXWNfUlikmdYK0zax7siS4EDKJtd'.
'mQeU1XRwLBdLkRGASucWmGVnZ4dnhZvn5lmm29iVOWpnJqcuko'. 'mQeU1XRwLBdLkRGASucWmGVnZ4dnhZvn5lmm29iVOWpnJqcuko'.
'JKR1Wm5eTkRKYF5eblp9sU2ZeUJiV7zbfVg0pH56UFBQXNjIqK'. 'JKR1Wm5eTkRKYF5eblp9sU2ZeUJiV7zbfVg0pH56UFBQXNjIqK'.
'jgkujItX1koKTVmYajsdKu2qETVhwgSXiUDZ2Bn9xqUeoZ5e0t'. 'jgkujItX1koKTVmYajsdKu2qETVhwgSXiUDZ2Bn9xqUeoZ5e0t'.
'LzYYZ3B092ndjtOnmKTmycW1s7SHa+l5dtB8zlccE6RlN0dGbM'. 'LzYYZ3B092ndjtOnmKTmycW1s7SHa+l5dtB8zlccE6RlN0dGbM'.
'mDVbd5KupNBcL6+F82XgHouLj5vRP2PWLGNdd4+ppnxe8tJec6'. 'mDVbd5KupNBcL6+F82XgHouLj5vRP2PWLGNdd4+ppnxe8tJec6'.
'XnNsKkm0uVQ5RDRHQTPTym68nPlZbvkfYCexsa5rpJ2qXa5Umm'. 'XnNsKkm0uVQ5RDRHQTPTym68nPlZbvkfYCexsa5rpJ2qXa5Umm'.
'ocmec3m8vHjmSs+fgxyhC5JDQ8WSPT2lvbzm8vDIe0nbtiBLN8'. 'ocmec3m8vHjmSs+fgxyhC5JDQ8WSPT2lvbzm8vDIe0nbtiBLN8'.
'8BigNdu1B6Lsje+fPbUFMLi5TMfGmvHi/puUAv23q2YCTFNqH5'. '8BigNdu1B6Lsje+fPbUFMLi5TMfGmvHi/puUAv23q2YCTFNqH5'.
'MvPnSwPh3HasCbm3XUpv+nS5VtrkEkwAANSTpGHdye9PAAAASn'. 'MvPnSwPh3HasCbm3XUpv+nS5VtrkEkwAANSTpGHdye9PAAAASn'.
'RFWHRzaWduYXR1cmUANGJkODkyYmE4MWZhNTk4MTIyNDJjNjUx'. 'RFWHRzaWduYXR1cmUANGJkODkyYmE4MWZhNTk4MTIyNDJjNjUx'.
'NzZhY2UxMDAzOGFhZjdhZWIyNzliNTM2ZGFmZDlkM2RiNDU3Zm'. 'NzZhY2UxMDAzOGFhZjdhZWIyNzliNTM2ZGFmZDlkM2RiNDU3Zm'.
'NlNT9CliMAAAAASUVORK5CYII=' ; 'NlNT9CliMAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bl_purple.png // File: bl_purple.png
//========================================================== //==========================================================
$this->imgdata_large[4][0]= 1149 ; $this->imgdata_large[4][0]= 1149 ;
$this->imgdata_large[4][1]= $this->imgdata_large[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACAV'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACAV'.
'BMVEX/////////7///5///1v//xv//rf//pf//lP//jP//hP//'. 'BMVEX/////////7///5///1v//xv//rf//pf//lP//jP//hP//'.
'c///a///Wv//Wvf/Uv//Sv//Qv//Qvf/Off/Mf//Kf//If//If'. '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'. 'f/GP//GPf/EP//EPf/CP//CPf/CO//AP//APf3Oe/3Kff3Ke/3'.
'Ie/3GO/3EO/3AO/vSu/vSufvOefvMefvIefvGOfvEOfvCOfvAO'. 'Ie/3GO/3EO/3AO/vSu/vSufvOefvMefvIefvGOfvEOfvCOfvAO'.
'fnUufnSufnMd7nId7nGN7nGNbnEN7nCN7nAN7ejN7ejNbec97e'. 'fnUufnSufnMd7nId7nGN7nGNbnEN7nCN7nAN7ejN7ejNbec97e'.
'c9beUtbeQtbeIdbeGNbeENbeCNbeANbWpdbWa9bWQs7WGM7WEM'. 'c9beUtbeQtbeIdbeGNbeENbeCNbeANbWpdbWa9bWQs7WGM7WEM'.
'7WCM7WAM7Otc7Orc7OnM7OSsbOIb3OGMbOEMbOCMbOAM7OAMbG'. '7WCM7WAM7Otc7Orc7OnM7OSsbOIb3OGMbOEMbOCMbOAM7OAMbG'.
'pcbGnMbGe8bGa8bGKbXGEL3GCL3GAL3FucXBu73AvsC/v7+9pb'. 'pcbGnMbGe8bGa8bGKbXGEL3GCL3GAL3FucXBu73AvsC/v7+9pb'.
'29Ka29GLW9ELW9CLW9AL29ALW5rrm1lLW1e7W1MbW1GKW1EK21'. '29Ka29GLW9ELW9CLW9AL29ALW5rrm1lLW1e7W1MbW1GKW1EK21'.
'CLW1CK21AK2tjK2thKWtMaWtIaWtGJytCK2tCKWtAK2tAKWlhK'. 'CLW1CK21AK2tjK2thKWtMaWtIaWtGJytCK2tCKWtAK2tAKWlhK'.
'Wle6WlEJylCJylAKWlAJyca5ycGJScEJScCJScAJycAJSUWpSU'. 'Wle6WlEJylCJylAKWlAJyca5ycGJScEJScCJScAJycAJSUWpSU'.
'UoyUKZSUEIyUCIyUAJSUAIyMUoyMSoyMIYSMEISMCISMAIyMAI'. 'UoyUKZSUEIyUCIyUAJSUAIyMUoyMSoyMIYSMEISMCISMAIyMAI'.
'SECHuEAISEAHt7MXt7EHt7CHt7AHt7AHNzKXNzEGtzAHNzAGtr'. 'SECHuEAISEAHt7MXt7EHt7CHt7AHt7AHNzKXNzEGtzAHNzAGtr'.
'GGtrEGNrCGtrAGtrAGNjCFpjAGNjAFpaAFpaAFIpZn4bAAAAAX'. 'GGtrEGNrCGtrAGtrAGNjCFpjAGNjAFpaAFpaAFIpZn4bAAAAAX'.
'RSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsS'. 'RSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsS'.
'AdLdfvwAAAAHdElNRQfTAwkRFB0ymoOwAAAB9UlEQVR4nGNgIA'. 'AdLdfvwAAAAHdElNRQfTAwkRFB0ymoOwAAAB9UlEQVR4nGNgIA'.
'K42hhqGtm5+WFIWClKycvLK6gbuARGoEj4aMjLSElISUir6Tt7'. 'K42hhqGtm5+WFIWClKycvLK6gbuARGoEj4aMjLSElISUir6Tt7'.
'x+aEIWR8leQlwEBSTc/CK7awLguuR0lGQkJMVFRUTFJVzwko1d'. 'x+aEIWR8leQlwEBSTc/CK7awLguuR0lGQkJMVFRUTFJVzwko1d'.
'oFk9OQl5IQE+Dh5hVR0TV3CkkvbJgyASJjDZIR5GBl5eRX0TH1'. 'oFk9OQl5IQE+Dh5hVR0TV3CkkvbJgyASJjDZIR5GBl5eRX0TH1'.
'DEqrbJ2ypBEspSgvJSXKw8bMxMavbOLoGZNf1TZlybw4oIyfLN'. 'DEqrbJ2ypBEspSgvJSXKw8bMxMavbOLoGZNf1TZlybw4oIyfLN'.
'BxotxsLEzsQiaOHkFpBQ2905esrAZK2SpIAaUEuDm5+LTNPAKj'. 'BxotxsLEzsQiaOHkFpBQ2905esrAZK2SpIAaUEuDm5+LTNPAKj'.
'C+pbps1evrIDKGWnLictKSkuLKyoZQyUya9o7Z2+YMXKGUApew'. 'C+pbps1evrIDKGWnLictKSkuLKyoZQyUya9o7Z2+YMXKGUApew'.
'M9PTVdXR0TEwf3wOjUirruafOXL18xFyjl72Kpb25qaurg4REU'. 'M9PTVdXR0TEwf3wOjUirruafOXL18xFyjl72Kpb25qaurg4REU'.
'EFVe2zJ5zpLlK1aCpbydnZ2dnDwDA6NTopLLeiZNXbB8BcTAyP'. 'EFVe2zJ5zpLlK1aCpbydnZ2dnDwDA6NTopLLeiZNXbB8BcTAyP'.
'TQ0JDg4KCY1NS83JKmiVOBepYvX9UPlAovzEiPSU/LLyior2vq'. 'TQ0JDg4KCY1NS83JKmiVOBepYvX9UPlAovzEiPSU/LLyior2vq'.
'mjZr3vLlIF01IC+XVhUWFlZW1Lc290ycOGfxohVATSsXx4Oksn'. 'mjZr3vLlIF01IC+XVhUWFlZW1Lc290ycOGfxohVATSsXx4Oksn'.
'vaWlsb2tq6J0+bM2/RohVA81asbIcEYueU3t7JU6ZNnwNyGkhm'. 'vaWlsb2tq6J0+bM2/RohVA81asbIcEYueU3t7JU6ZNnwNyGkhm'.
'+cp5CRCppJnzZ8+ZM3/JUogECBbBIixr8Yqly8FCy8F6ltUgoj'. '+cp5CRCppJnzZ8+ZM3/JUogECBbBIixr8Yqly8FCy8F6ltUgoj'.
'lz7sqVK2ByK+cVMSCDxoUrwWDVysXt8WhJKqG4Y8bcuTP6qrGk'. 'lz7sqVK2ByK+cVMSCDxoUrwWDVysXt8WhJKqG4Y8bcuTP6qrGk'.
'QwwAABiMu7T4HMi4AAAAAElFTkSuQmCC' ; 'QwwAABiMu7T4HMi4AAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bl_gray.png // File: bl_gray.png
//========================================================== //==========================================================
$this->imgdata_large[5][0]= 905 ; $this->imgdata_large[5][0]= 905 ;
$this->imgdata_large[5][1]= $this->imgdata_large[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAABO1'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAABO1'.
'BMVEX////////3///39/fv7+/e5+fW3t7Wzs7WxsbG1tbGzsbG'. 'BMVEX////////3///39/fv7+/e5+fW3t7Wzs7WxsbG1tbGzsbG'.
'xsbDxMS/v7++wMC+v7+9zsa9xsa9vb29tbW9ra29pa24uLi1xs'. 'xsbDxMS/v7++wMC+v7+9zsa9xsa9vb29tbW9ra29pa24uLi1xs'.
'a1vb21tbWxtrattbWmpqalra2cra2cpaWcnJycjIyUpaWUnJyU'. 'a1vb21tbWxtrattbWmpqalra2cra2cpaWcnJycjIyUpaWUnJyU'.
'lJSUjIyMnJyMnJSMlJSMlIyMjJSMjIyElJSElIyEjIyEhIR7jI'. 'lJSUjIyMnJyMnJSMlJSMlIyMjJSMjIyElJSElIyEjIyEhIR7jI'.
'x7hIR7hHt7e3t7e3N7e2tzhIRze3tze3Nzc3Nre3trc3Nrc2tr'. 'x7hIR7hHt7e3t7e3N7e2tzhIRze3tze3Nzc3Nre3trc3Nrc2tr'.
'a2tjc3Njc2tja3Nja2tjY2NjWlpaa2taY2taY2NaY1paWlpaUl'. 'a2tjc3Njc2tja3Nja2tjY2NjWlpaa2taY2taY2NaY1paWlpaUl'.
'JSY2NSY1pSWlpSWlJSUlJSUkpKWlpKWlJKUlpKUlJKUkpKSkpK'. 'JSY2NSY1pSWlpSWlJSUlJSUkpKWlpKWlJKUlpKUlJKUkpKSkpK'.
'SkJCUlJCUkJCSkpCSkJCQkI5Sko5QkI5Qjk5OUI5OTkxQkIxOT'. 'SkJCUlJCUkJCSkpCSkJCQkI5Sko5QkI5Qjk5OUI5OTkxQkIxOT'.
'kxMTkxMTEpMTEhMTEhKSkYISEpy7AFAAAAAXRSTlMAQObYZgAA'. 'kxMTkxMTEpMTEhMTEhKSkYISEpy7AFAAAAAXRSTlMAQObYZgAA'.
'AAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdE'. 'AAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdE'.
'lNRQfTAwkRFQfW40uLAAABx0lEQVR4nI3SbXfSMBQA4NV3nce5'. 'lNRQfTAwkRFQfW40uLAAABx0lEQVR4nI3SbXfSMBQA4NV3nce5'.
'TecAHUywRMHSgFuBCFsQUqwBS1OsWQh0GTj//y8wZUzdwQ/efM'. 'TecAHUywRMHSgFuBCFsQUqwBS1OsWQh0GTj//y8wZUzdwQ/efM'.
'tzcm/uuXdj4z9ic/PR9k4qk1qDnf0X2/uZzKt8GaRvSubg4LVp'. 'tzcm/uuXdj4z9ic/PR9k4qk1qDnf0X2/uZzKt8GaRvSubg4LVp'.
'mkWzCGAT/i3Zsm2XNQHLsm2n2937LaaNnGoJFAEo27B50qN0ay'. 'mkWzCGAT/i3Zsm2XNQHLsm2n2937LaaNnGoJFAEo27B50qN0ay'.
'Wg26lXsw8fP8nmzcJb2CbsnF5JmmCE8ncN404KvLfsYwd7/MdV'. 'Wg26lXsw8fP8nmzcJb2CbsnF5JmmCE8ncN404KvLfsYwd7/MdV'.
'Pdgl/VbKMIzbuwVgVZw2JlSKJTVJ3609vWUY957lgAUd1KNcqr'. 'Pdgl/VbKMIzbuwVgVZw2JlSKJTVJ3609vWUY957lgAUd1KNcqr'.
'yWnOcOPn8q7d5/8PywAqsOOiVDrn42NFk+HQ7dVuXNYeFdBTpN'. 'yWnOcOPn8q7d5/8PywAqsOOiVDrn42NFk+HQ7dVuXNYeFdBTpN'.
'nY5JdZl8xI5Y+HXYaTVqEDp1hAnRohZM03EUjMdhn5wghOoNnD'. 'nY5JdZl8xI5Y+HXYaTVqEDp1hAnRohZM03EUjMdhn5wghOoNnD'.
'wSK7KiiDPqEtz+iD4ctdyAifNYzUnScBSxwPd6GLfRURW7Ay5i'. 'wSK7KiiDPqEtz+iD4ctdyAifNYzUnScBSxwPd6GLfRURW7Ay5i'.
'pS5bmrY8348C5vvUI+TLiIVSJrVA0heK/GDkJxYMRoyfCSmk4s'. 'pS5bmrY8348C5vvUI+TLiIVSJrVA0heK/GDkJxYMRoyfCSmk4s'.
'uWc3yic/oBo4yF374LGQs5Xw0GyQljI8bYmEsxVUoKxa6HMpAT'. 'uWc3yic/oBo4yF374LGQs5Xw0GyQljI8bYmEsxVUoKxa6HMpAT'.
'vgyhU2mR8uU1pXmsa8ezqb6U4mwWF/5MeY8uLtQ0nmmQ8UWYvb'. 'vgyhU2mR8uU1pXmsa8ezqb6U4mwWF/5MeY8uLtQ0nmmQ8UWYvb'.
'EcJaYWar7QhztrO5Wr4Q4hDbAG/4hfTAF2iCiWrCEAAAAASUVO'. 'EcJaYWar7QhztrO5Wr4Q4hDbAG/4hfTAF2iCiWrCEAAAAASUVO'.
'RK5CYII=' ; 'RK5CYII=' ;
   
//========================================================== //==========================================================
// File: bl_brown.png // File: bl_brown.png
//========================================================== //==========================================================
$this->imgdata_large[6][0]= 1053 ; $this->imgdata_large[6][0]= 1053 ;
$this->imgdata_large[6][1]= $this->imgdata_large[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAABoV'. 'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAABoV'.
'BMVEX////Gzs7GvbXGrZTGpXu9nHO1nHO1nIy9taXGxs7GtaXO'. 'BMVEX////Gzs7GvbXGrZTGpXu9nHO1nHO1nIy9taXGxs7GtaXO'.
'nHPGlFrGjEq9hEq1hEqte0Klczmcazmce1KtnIzGxsbGvb3OlF'. 'nHPGlFrGjEq9hEq1hEqte0Klczmcazmce1KtnIzGxsbGvb3OlF'.
'LOlFq9hFKte0qcc0KUYzGEWimMc1K9ta3OnGvOnGPWnGO9jFq9'. 'LOlFq9hFKte0qcc0KUYzGEWimMc1K9ta3OnGvOnGPWnGO9jFq9'.
'jFKlc0KUazmMYzl7UilzUjGtpZzGxr3GnGPWpWvepXO1hFJ7Wj'. 'jFKlc0KUazmMYzl7UilzUjGtpZzGxr3GnGPWpWvepXO1hFJ7Wj'.
'FrSiFjUjG1ra3GnHPvxpT/5733zpythFKUa0KEYzlzUilaOSF7'. 'FrSiFjUjG1ra3GnHPvxpT/5733zpythFKUa0KEYzlzUilaOSF7'.
'Wjm9jErvvYz/99b///f/78bnrYS1hFqle0p7UjFrSiljQiFCMR'. 'Wjm9jErvvYz/99b///f/78bnrYS1hFqle0p7UjFrSiljQiFCMR'.
'iMhHO9lGvGjFLWnGv/3q3////erXuthEqlc0paQiFKMRhSQin/'. 'iMhHO9lGvGjFLWnGv/3q3////erXuthEqlc0paQiFKMRhSQin/'.
'1qX/997//++cc0pjSilaQilKORhCKRiclIy9pYzGlGPntYT33q'. '1qX/997//++cc0pjSilaQilKORhCKRiclIy9pYzGlGPntYT33q'.
'3vvZSEWjlSOSE5KRB7c2O1lHutczmthFqte1JrWkqtjGtCKRBa'. '3vvZSEWjlSOSE5KRB7c2O1lHutczmthFqte1JrWkqtjGtCKRBa'.
'SjmljGuca0KMYzGMaznOztaclISUYzmEWjFKOSF7a1qEYzFaSi'. 'SjmljGuca0KMYzGMaznOztaclISUYzmEWjFKOSF7a1qEYzFaSi'.
'GUjISEa0pKOSm9vb2llIxaQhg5IQiEc2tzY0paORilnJy1raVS'. 'GUjISEa0pKOSm9vb2llIxaQhg5IQiEc2tzY0paORilnJy1raVS'.
'OSljUkJjWkKTpvQWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. 'OSljUkJjWkKTpvQWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkREiei'. 'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkREiei'.
'zP2EAAAB9UlEQVR4nGWS/VfSUBjHL5QluhhBxtwyWcCus5Blpm'. 'zP2EAAAB9UlEQVR4nGWS/VfSUBjHL5QluhhBxtwyWcCus5Blpm'.
'wDC4ONaWXCyBi7RMZmpQ2Bypm9W/byV3cHHo/W88s95/s5z/d5'. 'wDC4ONaWXCyBi7RMZmpQ2Bypm9W/byV3cHHo/W88s95/s5z/d5'.
'uwCcCh/4L3zAf+bs0NC588On9QAYGSUuBINk6GI4cmnsBLk8Go'. 'uwCcCh/4L3zAf+bs0NC588On9QAYGSUuBINk6GI4cmnsBLk8Go'.
'1SFEGMkzRzZeLq5JE8FvDHouw1lqXiCZJOcnCKnx4AcP0GBqmZ'. '1SFEGMkzRzZeLq5JE8FvDHouw1lqXiCZJOcnCKnx4AcP0GBqmZ'.
'mRgRT9MMB4Wbs7cGSXNRik3dnp9fiMUzNCNKgpzN9bsaWaQo9s'. 'mRgRT9MMB4Wbs7cGSXNRik3dnp9fiMUzNCNKgpzN9bsaWaQo9s'.
'7dfH7pXiFTZCBU1JK27LmtBO8TDx7mV1eXHqXXyiIUFLWiVzHx'. '7dfH7pXiFTZCBU1JK27LmtBO8TDx7mV1eXHqXXyiIUFLWiVzHx'.
'BxcJIvV4/cn6wkqmWOOwmVE3UQOAp6HxRKL5bGPj+VwhUhalFq'. 'BxcJIvV4/cn6wkqmWOOwmVE3UQOAp6HxRKL5bGPj+VwhUhalFq'.
'8alm5vAt+LlySZTsebzcKrraIIW4JqZC3N3ga+1+EQTZKZta1M'. '8alm5vAt+LlySZTsebzcKrraIIW4JqZC3N3ga+1+EQTZKZta1M'.
'pCZCSeDViqVrThsEdsLJZLJYLpZrHVGScrKBvTQNtQHY6XIM02'. 'pCZCSeDViqVrThsEdsLJZLJYLpZrHVGScrKBvTQNtQHY6XIM02'.
'E6Ik7odRW1Dzy3N28n3kGuB3tQagm7UMBFXI/sATAs7L5vdbEs'. 'E6Ik7odRW1Dzy3N28n3kGuB3tQagm7UMBFXI/sATAs7L5vdbEs'.
'8Lycm923NB0j5wMe6KOsKIIyxcuqauxbrmlqyEWfPmPy5assY1'. '8Lycm923NB0j5wMe6KOsKIIyxcuqauxbrmlqyEWfPmPy5assY1'.
'U1SvWKZWom9nK/HfQ3+v2HYZSMStayTNN0PYKqg11P1nWsWq7u'. 'U1SvWKZWom9nK/HfQ3+v2HYZSMStayTNN0PYKqg11P1nWsWq7u'.
'4gJeY8g9PLrddNXRdW8Iryv86I3ja/9s26gvukhDdvUQnIjlKr'. '4gJeY8g9PLrddNXRdW8Iryv86I3ja/9s26gvukhDdvUQnIjlKr'.
'IdZCNH+3Xw779qbG63f//ZOzb6C4+ofdbzERrSAAAAAElFTkSu'. 'IdZCNH+3Xw779qbG63f//ZOzb6C4+ofdbzERrSAAAAAElFTkSu'.
'QmCC' ; 'QmCC' ;
   
//========================================================== //==========================================================
// File: bl_darkgreen.png // File: bl_darkgreen.png
//========================================================== //==========================================================
$this->imgdata_large[7][0]= 1113 ; $this->imgdata_large[7][0]= 1113 ;
$this->imgdata_large[7][1]= $this->imgdata_large[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'.
'BMVEX////////3///v///n/+/e99bW/+/W99bO786/v7++vr69'. 'BMVEX////////3///v///n/+/e99bW/+/W99bO786/v7++vr69'.
'/96999a7wb24vbu1/9a1zqW1u7itxrWosq6l772l1qWlxrWlxq'. '/96999a7wb24vbu1/9a1zqW1u7itxrWosq6l772l1qWlxrWlxq'.
'2lva2cxpSU562U3q2UxqWUvaWUpZyM77WM57WMvYyMtZyMrZyM'. '2lva2cxpSU562U3q2UxqWUvaWUpZyM77WM57WMvYyMtZyMrZyM'.
'pZSMnJSEvZyEtYyErZSElIx7zpR7xpx7xpR7vZR7jIRz1pRzxp'. 'pZSMnJSEvZyEtYyErZSElIx7zpR7xpx7xpR7vZR7jIRz1pRzxp'.
'RzjIRrzpRrzoxrxoxrtYRrrYxrrXtrpYRrhHNjzoxjxoxjxoRj'. 'RzjIRrzpRrzoxrxoxrtYRrrYxrrXtrpYRrhHNjzoxjxoxjxoRj'.
'vYRjtYRjrXtjpXtjlGNje2tazoxazoRaxoxaxoRavYRatYRatX'. 'vYRjtYRjrXtjpXtjlGNje2tazoxazoRaxoxaxoRavYRatYRatX'.
'tarXtapXNanHNajFpae2tSzoRSxoRSvXtStXtSrXtSrXNSpXNS'. 'tarXtapXNanHNajFpae2tSzoRSxoRSvXtStXtSrXtSrXNSpXNS'.
'nHNSnGtSlGtSlGNSjGtSjGNKvXtKtXNKrXNKpWtKnGtKlGNKjG'. 'nHNSnGtSlGtSlGNSjGtSjGNKvXtKtXNKrXNKpWtKnGtKlGNKjG'.
'NKhGNKhFJKc1pKa1JCrWtCpWtCnGtClGNCjGNCjFpChFpCe1JC'. 'NKhGNKhFJKc1pKa1JCrWtCpWtCnGtClGNCjGNCjFpChFpCe1JC'.
'a1JCY1I5pWs5nGM5lGM5jFo5hFo5e1o5c0o5WkoxjFoxhFoxhF'. 'a1JCY1I5pWs5nGM5lGM5jFo5hFo5e1o5c0o5WkoxjFoxhFoxhF'.
'Ixe1Ixc1Ixc0oxa0ophFIpe0opc0opa0opa0IpY0IpWkIpWjkp'. 'Ixe1Ixc1Ixc0oxa0ophFIpe0opc0opa0opa0IpY0IpWkIpWjkp'.
'UkIpUjkhc0oha0IhY0IhWjkhWjEhUjkhUjEhSjEhSikhQjEhQi'. 'UkIpUjkhc0oha0IhY0IhWjkhWjEhUjkhUjEhSjEhSikhQjEhQi'.
'kYWjkYSjEYSikYQjEYQikQSikQQikQQiEQOSExf8saAAAAAXRS'. 'kYWjkYSjEYSikYQjEYQikQSikQQikQQiEQOSExf8saAAAAAXRS'.
'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
'LdfvwAAAAHdElNRQfTAwkRFCaDkWqUAAAB+ElEQVR4nI3S+1vS'. 'LdfvwAAAAHdElNRQfTAwkRFCaDkWqUAAAB+ElEQVR4nI3S+1vS'.
'UBgHcGZlPV0ks/vFrmQWFimJjiwiYUJWjFBWFhClyZCy5hLrwA'. 'UBgHcGZlPV0ks/vFrmQWFimJjiwiYUJWjFBWFhClyZCy5hLrwA'.
'x2EIwJC1w7zf2vnU0re+iHvs9++7x7zznvORbLf+TA6ct9fYMX'. 'x2EIwJC1w7zf2vnU0re+iHvs9++7x7zznvORbLf+TA6ct9fYMX'.
'jrfAUYefpp+/iM1ykxf/lmuhUZ/PTwXC8dml5Wcd23o5H5Mk6b'. 'jrfAUYefpp+/iM1ykxf/lmuhUZ/PTwXC8dml5Wcd23o5H5Mk6b'.
'5NUU8icXbhS67rNzn9JDnguOEYGQtEEtwC+Crs3RJ76P5A/znr'. '5NUU8icXbhS67rNzn9JDnguOEYGQtEEtwC+Crs3RJ76P5A/znr'.
'vsNX7wQnEiwHCtK7TTkW8rvdZ9uJtvZTLkxpHhSrP66bNEj7/P'. 'vsNX7wQnEiwHCtK7TTkW8rvdZ9uJtvZTLkxpHhSrP66bNEj7/P'.
'3WNoLYeeSWQQCIpe9lQw7RNEU5rDsIYtcJ14Nocg7kRUlBNkxn'. '3WNoLYeeSWQQCIpe9lQw7RNEU5rDsIYtcJ14Nocg7kRUlBNkxn'.
'YmGKcp7cv3vPwR7XOJPmc0VYU3Sv0e9NOBAYG7Hbz/cMjTMveZ'. 'YmGKcp7cv3vPwR7XOJPmc0VYU3Sv0e9NOBAYG7Hbz/cMjTMveZ'.
'CHkqxuTBv0PhYJB4N3XR6PJ5rMAPMnpGUxDX1IxSeMTEaZp1OZ'. 'CHkqxuTBv0PhYJB4N3XR6PJ5rMAPMnpGUxDX1IxSeMTEaZp1OZ'.
'nGAIQiYtsalUIhFlmGTy3sO3AizJCKn6DKYryxzHsWyaneMzr6'. 'nGAIQiYtsalUIhFlmGTy3sO3AizJCKn6DKYryxzHsWyaneMzr6'.
'cWxRVZVlFTe4SpE3zm+U/4+whyiwJcWVMQNr3XONirVWAklxcE'. 'cWxRVZVlFTe4SpE3zm+U/4+whyiwJcWVMQNr3XONirVWAklxcE'.
'EdbqchPhjhVzGpeqhUKhWBQhLElr9fo3pDaQPrw5xOl1CGG1JE'. 'EdbqchPhjhVzGpeqhUKhWBQhLElr9fo3pDaQPrw5xOl1CGG1JE'.
'k1uYEBIVkrb02+o6RItfq6rBhbw/tuINT96766KhuqYpY3UFPF'. 'k1uYEBIVkrb02+o6RItfq6rBhbw/tuINT96766KhuqYpY3UFPF'.
'BbY/19yZ1XF1U0UNBa9T7rZsz80K0jWk6bpWGW55UzbvTHZ+3t'. 'BbY/19yZ1XF1U0UNBa9T7rZsz80K0jWk6bpWGW55UzbvTHZ+3t'.
'vbAv/IT+K1uCmhIrKJAAAAAElFTkSuQmCC' ; 'vbAv/IT+K1uCmhIrKJAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bl_green.png // File: bl_green.png
//========================================================== //==========================================================
$this->imgdata_large[8][0]= 1484 ; $this->imgdata_large[8][0]= 1484 ;
$this->imgdata_large[8][1]= $this->imgdata_large[8][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMMFjM4kcoDJQAABVlJREFUeNq9ll2MJFUVx3/11V'. 'B3RJTUUH0wMMFjM4kcoDJQAABVlJREFUeNq9ll2MJFUVx3/11V'.
'Vd/TE9vU0v4zLDwJIF16jBqLAPhsRXEiDqg0QTJiQSjcSNvCzw'. 'Vd/TE9vU0v4zLDwJIF16jBqLAPhsRXEiDqg0QTJiQSjcSNvCzw'.
'sBEDDxizhvAAxBgf1oR9QF9NiE9ESFZkQyZB5WtddmdnZ3qqqr'. 'sBEDDxizhvAAxBgf1oR9QF9NiE9ESFZkQyZB5WtddmdnZ3qqqr'.
'uqbt367Cofqu3ZZpWVaDzJfbkf53//55z/PVdZXV3l/2H6f7Lp'. 'uqbt367Cofqu3ZZpWVaDzJfbkf53//55z/PVdZXV3l/2H6f7Lp'.
'5VdOV/4Nb+GmHpUeA7AdBNxc3kafNb73jRPK9Xwon8ToxVefqU'. '5VdOV/4Nb+GmHpUeA7AdBNxc3kafNb73jRPK9Xwon8ToxVefqU'.
'b91wibH5EkCQBCizFihTSviHUHR0hWws9xe3wvJ7/7nPKpgX5y'. 'b91wibH5EkCQBCizFihTSviHUHR0hWws9xe3wvJ7/7nPKpgX5y'.
'9oFqt3eOgWniRBoAbUBGGqZUibSYaeoT2B5bnkdaSA6793Cv/S'. '9oFqt3eOgWniRBoAbUBGGqZUibSYaeoT2B5bnkdaSA6793Cv/S'.
'QPPbihXBfo5VdOV+8dfgnvwAU62YH5fCZ12sDujFkwyegCqTrB'. 'QPPbihXBfo5VdOV+8dfgnvwAU62YH5fCZ12sDujFkwyegCqTrB'.
'iUOKTOJKj8jr88jS8zy6cXwBTP048nuHX0I0nDlIp7RpTG7kM0'. 'iUOKTOJKj8jr88jS8zy6cXwBTP048nuHX0I0nDlIp7RpTG7kM0'.
'sdyAYsTVukUuWGhlWHMq0ITL92lnUp9R1Obz/GmTNnqn9bDD8/'. 'sdyAYsTVukUuWGhlWHMq0ITL92lnUp9R1Obz/GmTNnqn9bDD8/'.
'+0D1oX0O0zQZZDYCsK2j3Gl9jQqDfHiei8GfiKVLlsZkJaBAN1'. '+0D1oX0O0zQZZDYCsK2j3Gl9jQqDfHiei8GfiKVLlsZkJaBAN1'.
'0i6PgwUbB0GxG5/PrtE/xLRr959Znqw9452oVNI+jiJhnr1pe4'. '0i6PgwUbB0GxG5/PrtE/xLRr959Znqw9452oVNI+jiJhnr1pe4'.
'k29zB1/nFr5Kj7tpt1YYhJ0FJ7nUYbcJQBgahN2MzeCP/OipR6'. 'k29zB1/nFr5Kj7tpt1YYhJ0FJ7nUYbcJQBgahN2MzeCP/OipR6'.
'prgN6Qr6ELFQFUWoRpNVjlKwxZB8DCpE+PtfEKqV1cUzxpVudu'. 'prgN6Qr6ELFQFUWoRpNVjlKwxZB8DCpE+PtfEKqV1cUzxpVudu'.
'GTBHA5Y1g99e+dUio9O/P1Vpq+/WE5GGjDSMoAtAQjrf3C52IP'. 'GTBHA5Y1g99e+dUio9O/P1Vpq+/WE5GGjDSMoAtAQjrf3C52IP'.
'QxpY4WK2hpReka9Gfrhqgz0bACRoCWjDh56kQ1z9FeuUUQxVhK'. 'QxpY4WK2hpReka9Gfrhqgz0bACRoCWjDh56kQ1z9FeuUUQxVhK'.
'B92sD1VahM+bAJgcoJhGjP/6Ln8rAgDiRCVRKiIzxMkkodBJ85'. 'B92sD1VahM+bAJgcoJhGjP/6Ln8rAgDiRCVRKiIzxMkkodBJ85'.
'im1IlEHbE4k1xyNveL4YP8HarmGJIOpqyjeQmfNHmTvnqZTWBt'. 'im1IlEHbE4k1xyNveL4YP8HarmGJIOpqyjeQmfNHmTvnqZTWBt'.
'vIJXpPwlukJSuSTKGK3pEwtJmiX00ZlInTyNscImO6XBITvH1c'. 'vIJXpPwlukJSuSTKGK3pEwtJmiX00ZlInTyNscImO6XBITvH1c'.
'8vVt2OucdKvIyeKRTNCivsEMgcpg6taYs30nfq0Gqg6hOSSFJ4'. '8vVt2OucdKvIyeKRTNCivsEMgcpg6taYs30nfq0Gqg6hOSSFJ4'.
'BSnJPht0IqEjWmOGocEI6F0J94F0qaL6BntTF0MtUfweKQKAPU'. 'BSnJPht0IqEjWmOGocEI6F0J94F0qaL6BntTF0MtUfweKQKAPU'.
'Wwp4OcVnQAmVb0p9DLOzjEhEKnGRmoRc7EzRGlwA6NujAKG4yP'. 'Wwp4OcVnQAmVb0p9DLOzjEhEKnGRmoRc7EzRGlwA6NujAKG4yP'.
'6Sjwc4aVznZ7DK0xXdkDoJf0kGmFBniFBOBGcZSCCSKd0IwN0k'. '6Sjwc4aVznZ7DK0xXdkDoJf0kGmFBniFBOBGcZSCCSKd0IwN0k'.
'IS+QZWCGVZex4BnUxya3+Zt9iugQbcRFpIAtuHvAZulPUdLhUJ'. 'IS+QZWCGVZex4BnUxya3+Zt9iugQbcRFpIAtuHvAZulPUdLhUJ'.
'RqegI3WcqaSXddlT3idsWMSRRGkEtNwmyTifAwyBo7LP+11J0e'. 'RqegI3WcqaSXddlT3idsWMSRRGkEtNwmyTifAwyBo7LP+11J0e'.
'7tM7pZOYblHkBLcqZ5LcYtw6Wbd4CM3SpE9foYZsIHoqDKCrbz'. '7tM7pZOYblHkBLcqZ5LcYtw6Wbd4CM3SpE9foYZsIHoqDKCrbz'.
'mLSQtPwmuhXgtBLs0GBdbXOhFGB7WBKO2F8GXt9/VO97Ya3atF'. 'mLSQtPwmuhXgtBLs0GBdbXOhFGB7WBKO2F8GXt9/VO97Ya3atF'.
'7nUHnwGjGGQqcPxFEdFqURkEidiZszAERoYIsGju1hq21kWee3'. '7nUHnwGjGGQqcPxFEdFqURkEidiZszAERoYIsGju1hq21kWee3'.
'bw15+8WpsvAy3K1+i3JkkhZyPpxxjjPOsfOYiZ+TFhLPzQnHOU'. 'bw15+8WpsvAy3K1+i3JkkhZyPpxxjjPOsfOYiZ+TFhLPzQnHOU'.
'tpzGB2dgA4tscIkKIx19Cxg/fPL7vQJu47eXt1VvsDK8pwPueZ'. 'tpzGB2dgA4tscIkKIx19Cxg/fPL7vQJu47eXt1VvsDK8pwPueZ'.
'PuZoQMOqhRoJHSs0kKLBWjvjYinmeQGw1TaX1RFdfZ3LMzYLjA'. 'PuZoQMOqhRoJHSs0kKLBWjvjYinmeQGw1TaX1RFdfZ3LMzYLjA'.
'C++dkn6AaH2Nobk6cxEzdnuG0TdC8zvdJkN0hqkFkO/jwL0fxa'. 'C++dkn6AaH2Nobk6cxEzdnuG0TdC8zvdJkN0hqkFkO/jwL0fxa'.
'so8sBcuFzQ+/+MRC+BeAHnpwQzn++ee5KT9Eshuy46dcKAXm32'. 'so8sBcuFzQ+/+MRC+BeAHnpwQzn++ee5KT9Eshuy46dcKAXm32'.
'0uzPQhS4GttkH2GQID2Wc0Y4LtAbDxhZ/x5A+e/uTG9+jGceXH'. '0uzPQhS4GttkH2GQID2Wc0Y4LtAbDxhZ/x5A+e/uTG9+jGceXH'.
'9/ySnnIXnUzOxXe1038mW3ZynNmam4yYWkO+f9cv+Oljz16/lV'. '9/ySnnIXnUzOxXe1038mW3ZynNmam4yYWkO+f9cv+Oljz16/lV'.
'9tDz/9nerc1hm8ZEScSRK7VvtYl1i1dklsOKyvc+zg/bzw1O8+'. '9tDz/9nerc1hm8ZEScSRK7VvtYl1i1dklsOKyvc+zg/bzw1O8+'.
'/efkajt56kR1ydlEJBc5H46xzbrJ3dY9wrB7hGcff+6/+279L+'. '/efkajt56kR1ydlEJBc5H46xzbrJ3dY9wrB7hGcff+6/+279L+'.
'0fHxyiE8XMLl4AAAAASUVORK5CYII=' ; '0fHxyiE8XMLl4AAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bl_blue.png // File: bl_blue.png
//========================================================== //==========================================================
$this->imgdata_large[9][0]= 1169 ; $this->imgdata_large[9][0]= 1169 ;
$this->imgdata_large[9][1]= $this->imgdata_large[9][1]=
'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACEF'. 'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACEF'.
'BMVEX/////////7//35//v1v/exv/Wvf/Wrf/Wpf/Orf+/v7+9'. 'BMVEX/////////7//35//v1v/exv/Wvf/Wrf/Wpf/Orf+/v7+9'.
'tc69jP+9hP+5ucW1tc6tlP+rq7Wlpdalpcalpb2cnM6cnMacc/'. 'tc69jP+9hP+5ucW1tc6tlP+rq7Wlpdalpcalpb2cnM6cnMacc/'.
'+cWv+UlLWUjN6UjK2Uc/+Ma/+MUv+EhKWEa/+EQvd7e8Z7e7V7'. '+cWv+UlLWUjN6UjK2Uc/+Ma/+MUv+EhKWEa/+EQvd7e8Z7e7V7'.
'e6V7c957Wv9za9Zza8ZzSv9ra5xrSv9rOf9rMe9jUudjQv9jOe'. 'e6V7c957Wv9za9Zza8ZzSv9ra5xrSv9rOf9rMe9jUudjQv9jOe'.
'9aWpRaUt5aUpRaSu9aSudSUoxSSs5SSoxSMf9KQtZKOfdKMedK'. '9aWpRaUt5aUpRaSu9aSudSUoxSSs5SSoxSMf9KQtZKOfdKMedK'.
'Kf9KKe9CKf9CKb1CKa1CIfdCIedCId45MXs5Kfc5If85Iec5Id'. 'Kf9KKe9CKf9CKb1CKa1CIfdCIedCId45MXs5Kfc5If85Iec5Id'.
'Y5GP8xMbUxMXsxKc4xKZQxIf8xGP8xGO8xGN4xGNYxGL0xGK0p'. 'Y5GP8xMbUxMXsxKc4xKZQxIf8xGP8xGO8xGN4xGNYxGL0xGK0p'.
'KXMpIYwpGP8pGO8pGOcpGNYpGM4pEP8pEPcpEOcpEN4pENYpEM'. 'KXMpIYwpGP8pGO8pGOcpGNYpGM4pEP8pEPcpEOcpEN4pENYpEM'.
'YpEL0hGKUhEP8hEPchEO8hEOchEN4hENYhEM4hEMYhELUhCP8h'. 'YpEL0hGKUhEP8hEPchEO8hEOchEN4hENYhEM4hEMYhELUhCP8h'.
'CO8hCN4YGJwYGGsYEL0YEK0YEHMYCN4YCM4YCMYYCL0YCKUYAP'. 'CO8hCN4YGJwYGGsYEL0YEK0YEHMYCN4YCM4YCMYYCL0YCKUYAP'.
'8QEJQQEIwQEHsQEGsQCM4QCLUQCK0QCKUQCJwQCJQQCIwQCHMQ'. '8QEJQQEIwQEHsQEGsQCM4QCLUQCK0QCKUQCJwQCJQQCIwQCHMQ'.
'CGsQAP8QAPcQAO8QAOcQAN4QANYQAM4QAMYQAL0QALUQAKUQAJ'. 'CGsQAP8QAPcQAO8QAOcQAN4QANYQAM4QAMYQAL0QALUQAKUQAJ'.
'QQAIQICGsICGMIAO8IANYIAL0IALUIAK0IAKUIAJwIAJQIAIwI'. 'QQAIQICGsICGMIAO8IANYIAL0IALUIAK0IAKUIAJwIAJQIAIwI'.
'AIQIAHsIAHMIAGsIAGMAAN4AAMYAAK0AAJQAAIwAAIQAAHMAAG'. 'AIQIAHsIAHMIAGsIAGMAAN4AAMYAAK0AAJQAAIwAAIQAAHMAAG'.
'sAAGMAAFrR1dDlAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'sAAGMAAFrR1dDlAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFRPMOZ'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFRPMOZ'.
'/2AAAB+klEQVR4nGNgIAIIqeqZmBqpi2JISNml5lVXV3d198Yo'. '/2AAAB+klEQVR4nGNgIAIIqeqZmBqpi2JISNml5lVXV3d198Yo'.
'oUjwm1SnxsbGRsSm5ZfNXO4tjCTjVh0ABhFx6QV9E1Y0S8JkuN'. 'oUjwm1SnxsbGRsSm5ZfNXO4tjCTjVh0ABhFx6QV9E1Y0S8JkuN'.
'3yAgLc7W3t/QPi4jPKJ8ye1yoIlTKpjvVy15eVUbN0i4zKLJ8w'. '3yAgLc7W3t/QPi4jPKJ8ye1yoIlTKpjvVy15eVUbN0i4zKLJ8w'.
'ae6qcKgLqmMj3PUFWFl5NJ0CExLLJzbNW7BWCyxlXR0ba6/Axs'. 'ae6qcKgLqmMj3PUFWFl5NJ0CExLLJzbNW7BWCyxlXR0ba6/Axs'.
'zELmfnkRBT0QiSKgXJCOflxUbYy3KyMHEoOrtEZ1c2TZ6/cMl6'. 'zELmfnkRBT0QiSKgXJCOflxUbYy3KyMHEoOrtEZ1c2TZ6/cMl6'.
'eaCUamdsbIC7tjgPr4SBS3BMMVDTwkXr1hsDpYy6UmMj/O0tdX'. 'eaCUamdsbIC7tjgPr4SBS3BMMVDTwkXr1hsDpYy6UmMj/O0tdX'.
'QNbDxjknJLWqYsXLx0vStQynxGflpkZGCgs7Onp29SbtNkoMy6'. 'QNbDxjknJLWqYsXLx0vStQynxGflpkZGCgs7Onp29SbtNkoMy6'.
'pevCgFJWy3oyMuKjgoKCPWNCvEuqWhcsWrJ06XqQlPnMvrKyrM'. 'pevCgFJWy3oyMuKjgoKCPWNCvEuqWhcsWrJ06XqQlPnMvrKyrM'.
'TomJjkZAfHlNa2qdOWrlu63gcopbG8v7+hvLwip7g4JdSxsLZu'. 'TomJjkZAfHlNa2qdOWrlu63gcopbG8v7+hvLwip7g4JdSxsLZu'.
'8dKlS9ettwBKic2eNXHChIkTG5tKqgpr2uo6loLAehWQx0LnzJ'. '8dKlS9ettwBKic2eNXHChIkTG5tKqgpr2uo6loLAehWQx0LnzJ'.
'49p6mpeXLLlNq6RUvqly6dvnR9Bx9ISnnlvLmT582bMr9t4aL2'. '49p6mpeXLLlNq6RUvqly6dvnR9Bx9ISnnlvLmT582bMr9t4aL2'.
'+vrp60GaDCGB6Ld6wfwFCxYCJZYsXQ+SmL6+FBryInVrFi1atH'. '+vrp60GaDCGB6Ld6wfwFCxYCJZYsXQ+SmL6+FBryInVrFi1atH'.
'jJkqVQsH6pNCzCJNvXrQW6CmQJREYFEc2CYevXrwMLAyXXl0oz'. 'jJkqVQsH6pNCzCJNvXrQW6CmQJREYFEc2CYevXrwMLAyXXl0oz'.
'IAOt0vVQUGSIkabkDV3DwlzNVDAksAAAfUbNQRCwr88AAAAASU'. 'IAOt0vVQUGSIkabkDV3DwlzNVDAksAAAfUbNQRCwr88AAAAASU'.
'VORK5CYII=' ; 'VORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bs_red.png // File: bs_red.png
//========================================================== //==========================================================
$this->imgdata_small[0][0]= 437 ; $this->imgdata_small[0][0]= 437 ;
$this->imgdata_small[0][1]= $this->imgdata_small[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'.
'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'. 'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'.
'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'. 'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'.
'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'. 'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'.
'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'. 'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'.
'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. 'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGDNEMgOYAAAAm0'. 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGDNEMgOYAAAAm0'.
'lEQVR4nI3Q3RKCIBAFYGZMy9RKzX7MVUAUlQTe/+kS0K49d3wD'. 'lEQVR4nI3Q3RKCIBAFYGZMy9RKzX7MVUAUlQTe/+kS0K49d3wD'.
'7JlFaG+CvIR3FvzPXgpLatxevVVS+Jzv0BDGk/UJwOkQ1ph2g/'. '7JlFaG+CvIR3FvzPXgpLatxevVVS+Jzv0BDGk/UJwOkQ1ph2g/'.
'Ct5ACX4wNT1o/zzUoJUFUGBiGfVnDTYGJgmrWy8iKEtp0Bpd2d'. 'Ct5ACX4wNT1o/zzUoJUFUGBiGfVnDTYGJgmrWy8iKEtp0Bpd2d'.
'jLGu56MB7f4JOOfDJAwoNwslk/jOUi+Jts6RVNrC1hkhPy50Ef'. 'jLGu56MB7f4JOOfDJAwoNwslk/jOUi+Jts6RVNrC1hkhPy50Ef'.
'u79/ADQMQSGQ8bBywAAAAASUVORK5CYII=' ; 'u79/ADQMQSGQ8bBywAAAAASUVORK5CYII=' ;
   
   
//========================================================== //==========================================================
// File: bs_lightblue.png // File: bs_lightblue.png
//========================================================== //==========================================================
$this->imgdata_small[1][0]= 657 ; $this->imgdata_small[1][0]= 657 ;
$this->imgdata_small[1][1]= $this->imgdata_small[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABVl'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABVl'.
'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'. 'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'.
'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'. 'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'.
'+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'. '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'.
'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'. 'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'.
'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'. 'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'.
'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'. 'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'.
'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'. 'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'.
'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'. 'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'.
'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'. 'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'.
'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. 'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGTok'. 'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGTok'.
'9Yp9AAAAtElEQVR4nGNgIBaw8wkpKghzwvksPAKiUsraprYiLF'. '9Yp9AAAAtElEQVR4nGNgIBaw8wkpKghzwvksPAKiUsraprYiLF'.
'ARXkE2JiZ1PXMHXzGIAIekOFBE08TGLTCOCyzCLyvDxsZqZOnk'. 'ARXkE2JiZ1PXMHXzGIAIekOFBE08TGLTCOCyzCLyvDxsZqZOnk'.
'E56kAhaRV9NQUjW2tPcMjs9wBYsY6Oobmlk7egRGpxZmgkW0zC'. 'E56kAhaRV9NQUjW2tPcMjs9wBYsY6Oobmlk7egRGpxZmgkW0zC'.
'2s7Jy9giKT8gohaiQcnVzc/UNjkrMLCyHmcHr7BYREJKTlFxbm'. '2s7Jy9giKT8gohaiQcnVzc/UNjkrMLCyHmcHr7BYREJKTlFxbm'.
'QOxiEIuKTUzJKgQCaZibpdOzQfwCOZibGRi4dcJyw3S4iQ4HAL'. 'QOxiEIuKTUzJKgQCaZibpdOzQfwCOZibGRi4dcJyw3S4iQ4HAL'.
'qvIlIAMH7YAAAAAElFTkSuQmCC' ; 'qvIlIAMH7YAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bs_gray.png // File: bs_gray.png
//========================================================== //==========================================================
$this->imgdata_small[2][0]= 550 ; $this->imgdata_small[2][0]= 550 ;
$this->imgdata_small[2][1]= $this->imgdata_small[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAABI1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAABI1'.
'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'. 'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'.
'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'. 'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'.
'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'. 'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'.
'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'. 'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'.
'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'. 'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'.
'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'. 'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'.
'3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'. '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'.
'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'. 'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'.
'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIA'. 'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIA'.
'AAsSAdLdfvwAAAAHdElNRQfTAwkUGiIctEHoAAAAfElEQVR4nI'. 'AAsSAdLdfvwAAAAHdElNRQfTAwkUGiIctEHoAAAAfElEQVR4nI'.
'2N2xKDIAwF+bZ2kAa8cNFosBD//yvKWGh9dN+yk9kjxH28R7ze'. '2N2xKDIAwF+bZ2kAa8cNFosBD//yvKWGh9dN+yk9kjxH28R7ze'.
'wzBOYSX6CaNB927Z9qZ66KTSNmBM7UU9Hx2c5qjmJaWCaV5j4t'. 'wzBOYSX6CaNB927Z9qZ66KTSNmBM7UU9Hx2c5qjmJaWCaV5j4t'.
'o1ANr40sn5a+x4biElrqHgrXMeac/c1nEpFHG0LSFoo/jO/BeF'. 'o1ANr40sn5a+x4biElrqHgrXMeac/c1nEpFHG0LSFoo/jO/BeF'.
'lJnFbT58ayUf0BpA8wAAAABJRU5ErkJggg==' ; 'lJnFbT58ayUf0BpA8wAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bs_greenblue.png // File: bs_greenblue.png
//========================================================== //==========================================================
$this->imgdata_small[3][0]= 503 ; $this->imgdata_small[3][0]= 503 ;
$this->imgdata_small[3][1]= $this->imgdata_small[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAxl'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAxl'.
'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'. 'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'.
'9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'. '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'.
'17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'. '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'.
'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'. 'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'.
'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'. 'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'.
'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'. 'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'.
'dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfT'. 'dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfT'.
'AwkUGTIqLgJPAAAAqklEQVR4nI2QVxOCMBCEM6Mi2OiCvSslJB'. 'AwkUGTIqLgJPAAAAqklEQVR4nI2QVxOCMBCEM6Mi2OiCvSslJB'.
'CUoqjn//9TYgCfubf9Zu9uZxFqO+rscO7b6l/LljMZX29J2pNr'. 'CUoqjn//9TYgCfubf9Zu9uZxFqO+rscO7b6l/LljMZX29J2pNr'.
'YjmX4ZaIEs2NeiWO19NNacl8rHAyD4LR6jjw6PMRdTjZE0JOiU'. 'YjmX4ZaIEs2NeiWO19NNacl8rHAyD4LR6jjw6PMRdTjZE0JOiU'.
'dDv2ALTlzRvSdCCfAHGCc7yRPSrAQRQOWxKc3C/IUjBlDdUcM8'. 'dDv2ALTlzRvSdCCfAHGCc7yRPSrAQRQOWxKc3C/IUjBlDdUcM8'.
'97vFGwBY9QsZGBc/A4DWZNbeXIPWZEZI0c2lqSute/gCO9MXGY'. '97vFGwBY9QsZGBc/A4DWZNbeXIPWZEZI0c2lqSute/gCO9MXGY'.
'4/IOkAAAAASUVORK5CYII=' ; '4/IOkAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bs_yellow.png // File: bs_yellow.png
//========================================================== //==========================================================
$this->imgdata_small[4][0]= 507 ; $this->imgdata_small[4][0]= 507 ;
$this->imgdata_small[4][1]= $this->imgdata_small[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAzF'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAzF'.
'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'. 'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'.
'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'. 'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'.
'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'. 'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'.
'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'. 'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'.
'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'. 'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'.
'50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'. '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'.
'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAH'. 'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAH'.
'dElNRQfTAwkUGSDZl3MHAAAAqElEQVR4nI3QWRNDMBAA4My09E'. 'dElNRQfTAwkUGSDZl3MHAAAAqElEQVR4nI3QWRNDMBAA4My09E'.
'IF1SME0VT1okXvM/3//6kEfbZv+81eswA0DfHxRpOV+M+zkDGG'. 'IF1SME0VT1okXvM/3//6kEfbZv+81eswA0DfHxRpOV+M+zkDGG'.
'rL63zCoJ2ef2RLZDIqNqYexyvFrY9ePkxGWdpvfzC7tEGtIRly'. 'rL63zCoJ2ef2RLZDIqNqYexyvFrY9ePkxGWdpvfzC7tEGtIRly'.
'nqzboFKMlizAXbNnZyiFUKAy4bZ+B6W0lRaQDLmg4h/k7eFwDL'. 'nqzboFKMlizAXbNnZyiFUKAy4bZ+B6W0lRaQDLmg4h/k7eFwDL'.
'OWIky8qhXUBQ7gKGmsxpC+ah1TdriwByqG8GQNDNr6kLjf/wAx'. 'OWIky8qhXUBQ7gKGmsxpC+ah1TdriwByqG8GQNDNr6kLjf/wAx'.
'KgEq+FpPbfAAAAAElFTkSuQmCC' ; 'KgEq+FpPbfAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bs_darkgray.png // File: bs_darkgray.png
//========================================================== //==========================================================
$this->imgdata_small[5][0]= 611 ; $this->imgdata_small[5][0]= 611 ;
$this->imgdata_small[5][1]= $this->imgdata_small[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAABJl'. 'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAABJl'.
'BMVEX////////o8v/f6O7W4OnR3PXL1OTL0evEyLvCzePAwMC/'. 'BMVEX////////o8v/f6O7W4OnR3PXL1OTL0evEyLvCzePAwMC/'.
'v7a8wsq7t7C1xum1vtS1q6GzopmyxeKsrsOqvNWoq7anvN+nsb'. 'v7a8wsq7t7C1xum1vtS1q6GzopmyxeKsrsOqvNWoq7anvN+nsb'.
'qhrcGgqbGfpq6cp7+bqMuVmJKRm7yPlKKMnL6FkKWFipOEkLSE'. 'qhrcGgqbGfpq6cp7+bqMuVmJKRm7yPlKKMnL6FkKWFipOEkLSE'.
'j6qEhoqAiaB+jqd8haF7hZR4iJt4g5l3hZl2gIt2cod1hJVzeY'. 'j6qEhoqAiaB+jqd8haF7hZR4iJt4g5l3hZl2gIt2cod1hJVzeY'.
'VzboJvhp9sfJJsb41peY1pd5xpdoVod4xndI5lcHxka4BjcYVg'. 'VzboJvhp9sfJJsb41peY1pd5xpdoVod4xndI5lcHxka4BjcYVg'.
'Z3BfboFbb4lbZnZbYntaZ4laZYVZV3JYYWpXX3JWWm5VX4RVW2'. 'Z3BfboFbb4lbZnZbYntaZ4laZYVZV3JYYWpXX3JWWm5VX4RVW2'.
'NUYX9SXHxPWn5OVFxNWWtNVXVMVWFKV3xHUGZGU3dGTldFSlxE'. 'NUYX9SXHxPWn5OVFxNWWtNVXVMVWFKV3xHUGZGU3dGTldFSlxE'.
'Sk9ESXBCRlNBS3k/SGs/RU4+R1k9R2U6RFU2PUg0PEQxNU0ECL'. 'Sk9ESXBCRlNBS3k/SGs/RU4+R1k9R2U6RFU2PUg0PEQxNU0ECL'.
'QWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA'. 'QWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA'.
'CxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGQmbJetrAAAAtklEQV'. 'CxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGQmbJetrAAAAtklEQV'.
'R4nGNgwAK4JZTNNOWlYDxhMT4ZDTOzQE1uMF9CiJWVU0LbxDlS'. 'R4nGNgwAK4JZTNNOWlYDxhMT4ZDTOzQE1uMF9CiJWVU0LbxDlS'.
'G8QVF+FnZ2KRNHAIiPUHaZGSlmZj5lH19A1KjLUA8lXU5MWllF'. 'G8QVF+FnZ2KRNHAIiPUHaZGSlmZj5lH19A1KjLUA8lXU5MWllF'.
'yjo30TYr2BfG19G11b37CEeN84H38gX1HbwTUkOjo+zjfG3hLI'. 'yjo30TYr2BfG19G11b37CEeN84H38gX1HbwTUkOjo+zjfG3hLI'.
'l1exCvCNCwnxjfMz0gTyRdXNHXx9fUNCQu2MwU6SN3ZwD42LCH'. 'l1exCvCNCwnxjfMz0gTyRdXNHXx9fUNCQu2MwU6SN3ZwD42LCH'.
'W30IK4T8vUJSAkNMhDiwPqYiktXWN9JZj7UQAAjWEfhlG+kScA'. 'W30IK4T8vUJSAkNMhDiwPqYiktXWN9JZj7UQAAjWEfhlG+kScA'.
'AAAASUVORK5CYII=' ; 'AAAASUVORK5CYII=' ;
   
   
//========================================================== //==========================================================
// File: bs_darkgreen.png // File: bs_darkgreen.png
//========================================================== //==========================================================
$this->imgdata_small[6][0]= 666 ; $this->imgdata_small[6][0]= 666 ;
$this->imgdata_small[6][1]= $this->imgdata_small[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABX1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABX1'.
'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'. 'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'.
'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'. 'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'.
'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'. 'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'.
'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'. 'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'.
'6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'. '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'.
'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'. 'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'.
'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'. 'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'.
'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'. 'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'.
'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'. 'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'.
'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'. 'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
'RQfTAwkUGRjxlcuZAAAAtElEQVR4nGNgIBZw8osqqIpzw/msfI'. 'RQfTAwkUGRjxlcuZAAAAtElEQVR4nGNgIBZw8osqqIpzw/msfI'.
'IiUmr6lo6SbFARASEOJiYtQ2uXADmIAJeEGFBE18LBMySBBywi'. 'IiUmr6lo6SbFARASEOJiYtQ2uXADmIAJeEGFBE18LBMySBBywi'.
'LC/LwcFiZuvmH5WiAxZR0tRW1DC3dfYJS8zyAouYGBibWtm7+o'. 'LC/LwcFiZuvmH5WiAxZR0tRW1DC3dfYJS8zyAouYGBibWtm7+o'.
'TEpZfkgEX0rG3snNx9Q2NSCksgaqRd3Ty8gyLiU/NKSiDmcPsF'. 'TEpZfkgEX0rG3snNx9Q2NSCksgaqRd3Ty8gyLiU/NKSiDmcPsF'.
'BodHJ2UUlZTkQ+xikIlNSE7LLgECZagL2VQyc0H8YnV2uD94jS'. 'BodHJ2UUlZTkQ+xikIlNSE7LLgECZagL2VQyc0H8YnV2uD94jS'.
'ILIo14iQ4HALarJBNwbJVNAAAAAElFTkSuQmCC' ; 'ILIo14iQ4HALarJBNwbJVNAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bs_purple.png // File: bs_purple.png
//========================================================== //==========================================================
$this->imgdata_small[7][0]= 447 ; $this->imgdata_small[7][0]= 447 ;
$this->imgdata_small[7][1]= $this->imgdata_small[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAnF'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAnF'.
'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'. 'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'.
'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'. 'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'.
'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'. 'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'.
'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'. 'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'.
'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. 'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGS'. 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGS'.
'o5QpoZAAAAnElEQVR4nI3Q2xJDMBAG4MyQokWrZz3oSkJISJH3'. 'o5QpoZAAAAnElEQVR4nI3Q2xJDMBAG4MyQokWrZz3oSkJISJH3'.
'f7dK0Gv/Xb7J7vyzCK0NjtPsHuH/2wlhTE7LnTNLCO/TFQjjIp'. 'f7dK0Gv/Xb7J7vyzCK0NjtPsHuH/2wlhTE7LnTNLCO/TFQjjIp'.
'hHAA6bY06LSqppMAY47x+04HXTba2kAFlmQKr+YuVDCGUG2k6/'. 'hHAA6bY06LSqppMAY47x+04HXTba2kAFlmQKr+YuVDCGUG2k6/'.
'rNwYK8rKwKCnPxHnVS0aA3rag4UQslUGhrlk0Kpv1+sx3tLZ6w'. 'rNwYK8rKwKCnPxHnVS0aA3rag4UQslUGhrlk0Kpv1+sx3tLZ6w'.
'dtYemMkOsnz8R3V9/hB87DEu2Wos5+AAAAAElFTkSuQmCC' ; 'dtYemMkOsnz8R3V9/hB87DEu2Wos5+AAAAAElFTkSuQmCC' ;
   
   
//========================================================== //==========================================================
// File: bs_brown.png // File: bs_brown.png
//========================================================== //==========================================================
$this->imgdata_small[8][0]= 677 ; $this->imgdata_small[8][0]= 677 ;
$this->imgdata_small[8][1]= $this->imgdata_small[8][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABaF'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABaF'.
'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'. 'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'.
'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'. 'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'.
'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'. 'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'.
'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'. 'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'.
'/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'. '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'.
'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'. 'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'.
'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'. 'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'.
'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'. 'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'.
'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'. 'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'.
'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'. 'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'.
'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLd'. 'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLd'.
'fvwAAAAHdElNRQfTAwkUGho0tvl2AAAAtklEQVR4nGNgIBaoSg'. 'fvwAAAAHdElNRQfTAwkUGho0tvl2AAAAtklEQVR4nGNgIBaoSg'.
'mLKGpowfkGMty8AqJKpi4mRlAROR5ONg4JFUv3YHOIgDo/HwsT'. 'mLKGpowfkGMty8AqJKpi4mRlAROR5ONg4JFUv3YHOIgDo/HwsT'.
'q6yps29EsjZYREFIkJ2ZS9/OMzA20wEsIi8uKSZtaOPmH5WSFw'. 'q6yps29EsjZYREFIkJ2ZS9/OMzA20wEsIi8uKSZtaOPmH5WSFw'.
'YW0VRW07Vw8vCLSMguLwCL6FlaObp6B0TGZxSXQ9TouHv6+IXG'. 'YW0VRW07Vw8vCLSMguLwCL6FlaObp6B0TGZxSXQ9TouHv6+IXG'.
'JGYWlpdDzNEKCgmPjkvLKS0vL4LYxWAen5SelV8OBNZQFxrZ5h'. 'JGYWlpdDzNEKCgmPjkvLKS0vL4LYxWAen5SelV8OBNZQFxrZ5h'.
'aC+GX2MDczMBh7pZakehkTHQ4AA0Am/jsB5gkAAAAASUVORK5C'. 'aC+GX2MDczMBh7pZakehkTHQ4AA0Am/jsB5gkAAAAASUVORK5C'.
'YII=' ; 'YII=' ;
   
//========================================================== //==========================================================
// File: bs_blue.png // File: bs_blue.png
//========================================================== //==========================================================
$this->imgdata_small[9][0]= 436 ; $this->imgdata_small[9][0]= 436 ;
$this->imgdata_small[9][1]= $this->imgdata_small[9][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'.
'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'. 'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'.
'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'. 'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'.
'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'. 'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'.
'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'. 'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'.
'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. 'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGhNNakHSAAAAmk'. 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGhNNakHSAAAAmk'.
'lEQVR4nI3P2xKCIBAGYGfM6SBWo1nauIqogaDA+z9dK9Lhrv47'. 'lEQVR4nI3P2xKCIBAGYGfM6SBWo1nauIqogaDA+z9dK9Lhrv47'.
'vtl/2A2CfxNlJRRp9IETYGraJeEb7ocLNKznia8A7Db7umWDUG'. 'vtl/2A2CfxNlJRRp9IETYGraJeEb7ocLNKznia8A7Db7umWDUG'.
'sxAzhurxRHxok4KQGqCuEhlL45oU1D2w5BztY4KRhj/bCAsetM'. 'sxAzhurxRHxok4KQGqCuEhlL45oU1D2w5BztY4KRhj/bCAsetM'.
'2uObjwvY8/oX50JItYDxSyZSTrO2mNhvGMbaWAevnbFIcpuTr7'. '2uObjwvY8/oX50JItYDxSyZSTrO2mNhvGMbaWAevnbFIcpuTr7'.
't+5AkyfBIKSJHdSQAAAABJRU5ErkJggg==' ; 't+5AkyfBIKSJHdSQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bs_green.png // File: bs_green.png
//========================================================== //==========================================================
$this->imgdata_small[10][0]= 452 ; $this->imgdata_small[10][0]= 452 ;
$this->imgdata_small[10][1]= $this->imgdata_small[10][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAn1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAn1'.
'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'. 'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'.
'/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'. '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'.
'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'. 'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'.
'5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'. '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'.
'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'. 'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'.
'AIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAw'. 'AIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAw'.
'kUGgW5vvSDAAAAnklEQVR4nI3QSxKCMAwA0M4gqCgoiiJ+kEAL'. 'kUGgW5vvSDAAAAnklEQVR4nI3QSxKCMAwA0M4gqCgoiiJ+kEAL'.
'LQUq0PufzX7ENdnlJZNkgtDS2CYZvK6bf+7EoKLA9cH5SQzv6A'. 'LQUq0PufzX7ENdnlJZNkgtDS2CYZvK6bf+7EoKLA9cH5SQzv6A'.
'YloTywsAbYr44FrlgrXCMJwHl3xxVtuuFkJAPIcw2tGB9GcFli'. 'YloTywsAbYr44FrlgrXCMJwHl3xxVtuuFkJAPIcw2tGB9GcFli'.
'oqEf5GTkSUhVMw2TtD0XSlnDOw3SznE5520vNEi7CwW9+Ayjyq'. 'oqEf5GTkSUhVMw2TtD0XSlnDOw3SznE5520vNEi7CwW9+Ayjyq'.
'U/3+yPuq5gvhkhL0xlGnqL//AFf14UIh4mkEkAAAAASUVORK5C'. 'U/3+yPuq5gvhkhL0xlGnqL//AFf14UIh4mkEkAAAAASUVORK5C'.
'YII=' ; 'YII=' ;
   
   
//========================================================== //==========================================================
// File: bs_white.png // File: bs_white.png
//========================================================== //==========================================================
$this->imgdata_small[11][0]= 480 ; $this->imgdata_small[11][0]= 480 ;
$this->imgdata_small[11][1]= $this->imgdata_small[11][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMLFTsY/ewvBQAAAW1JREFUeJytkz2u4jAUhT/jic'. 'B3RJTUUH0wMLFTsY/ewvBQAAAW1JREFUeJytkz2u4jAUhT/jic'.
'gfBUKiZhE0bIKeVbCWrIKenp6eDiGlCEEEBArIxvzGU4xeZjLk'. 'gfBUKiZhE0bIKeVbCWrIKenp6eDiGlCEEEBArIxvzGU4xeZjLk'.
'jWb05lRXuvbx+exr4bouX1Xjyw7Atz81F4uFBYjjGIDhcCjq1o'. 'jWb05lRXuvbx+exr4bouX1Xjyw7Atz81F4uFBYjjGIDhcCjq1o'.
'k6nN1uZwFerxfP55Msy1itVmRZBsB4PK6YveHkeW5d18XzPIIg'. 'k6nN1uZwFerxfP55Msy1itVmRZBsB4PK6YveHkeW5d18XzPIIg'.
'wPd9Wq0WnU6HMAxJkoQoiuynOIfDwUopkVIihKAoCgAcx6Hdbm'. 'wPd9Wq0WnU6HMAxJkoQoiuynOIfDwUopkVIihKAoCgAcx6Hdbm'.
'OMIU1T5vN55eBKEikljUYDIX6kFUKU9e8aDAZlmjcca+1b7TgO'. 'OMIU1T5vN55eBKEikljUYDIX6kFUKU9e8aDAZlmjcca+1b7TgO'.
'1+uVy+VS9nzfr8e53++VzdZaiqIgz3OMMWitOZ/PaK0JgqDeRC'. '1+uVy+VS9nzfr8e53++VzdZaiqIgz3OMMWitOZ/PaK0JgqDeRC'.
'mF53lIKYGfr3O73TDGoJQiTVO01nS73XqT4/FIs9kkCAIej0eZ'. 'mF53lIKYGfr3O73TDGoJQiTVO01nS73XqT4/FIs9kkCAIej0eZ'.
'brPZEMcxSZKgtQZgMpmIWpN+vy+m06n1PK9yTx8Gy+WS/X5Pr9'. 'brPZEMcxSZKgtQZgMpmIWpN+vy+m06n1PK9yTx8Gy+WS/X5Pr9'.
'er9GuHLYoiG4YhSilOpxPr9Zrtdlti/JriU5MPjUYjq7UuEWaz'. 'er9GuHLYoiG4YhSilOpxPr9Zrtdlti/JriU5MPjUYjq7UuEWaz'.
'2d+P/b/qv/zi75oetJcv7QQXAAAAAElFTkSuQmCC' ; '2d+P/b/qv/zi75oetJcv7QQXAAAAAElFTkSuQmCC' ;
   
   
//========================================================== //==========================================================
// File: bs_cyan.png // File: bs_cyan.png
//========================================================== //==========================================================
$this->imgdata_small[12][0]= 633 ; $this->imgdata_small[12][0]= 633 ;
$this->imgdata_small[12][1]= $this->imgdata_small[12][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABPl'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABPl'.
'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'. 'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'.
'//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'. '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'.
'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'. 'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'.
'/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'. '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'.
'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'. 'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'.
'3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'. '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'.
'4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'. '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'.
'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'. 'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'.
'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'. 'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'.
'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
'AHdElNRQfTAwkUGQDi+VPPAAAAtElEQVR4nGNgIBawikipyIiy'. 'AHdElNRQfTAwkUGQDi+VPPAAAAtElEQVR4nGNgIBawikipyIiy'.
'wfksfJpGRkamNtr8LFARPiMFHmFDcztXfwGoFi0jLiZuZRtnry'. 'wfksfJpGRkamNtr8LFARPiMFHmFDcztXfwGoFi0jLiZuZRtnry'.
'BddrCIiJEGL6eklYO7X3iCOFhE2thESdHawdUnJDZFDiyiamZh'. 'BddrCIiJEGL6eklYO7X3iCOFhE2thESdHawdUnJDZFDiyiamZh'.
'aevk5h0UlZSpBhaRtbN3dPHwDY5MSM+EqBFzc/f0DgiLTkjLzI'. 'aevk5h0UlZSpBhaRtbN3dPHwDY5MSM+EqBFzc/f0DgiLTkjLzI'.
'SYw6bjHxgaEZeckZmpD7GLQSAqJj4xNRMIBGFuFtRLA/ENhGBu'. 'SYw6bjHxgaEZeckZmpD7GLQSAqJj4xNRMIBGFuFtRLA/ENhGBu'.
'ZmDgkJBXl5fgIDocAAKcINaFePT4AAAAAElFTkSuQmCC' ; 'ZmDgkJBXl5fgIDocAAKcINaFePT4AAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bs_bluegreen.png // File: bs_bluegreen.png
//========================================================== //==========================================================
$this->imgdata_small[13][0]= 493 ; $this->imgdata_small[13][0]= 493 ;
$this->imgdata_small[13][1]= $this->imgdata_small[13][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAvV'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAvV'.
'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'. 'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'.
'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'. 'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'.
'8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'. '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'.
'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'. 'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'.
'0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'. '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'.
'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'. 'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'.
'AJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGxNUcXCT'. 'AJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGxNUcXCT'.
'AAAAqUlEQVR4nI2Q1xKCMBREM2NHLCCogAGCjd6SqLT8/2cZKT'. 'AAAAqUlEQVR4nI2Q1xKCMBREM2NHLCCogAGCjd6SqLT8/2cZKT'.
'6zb3tm987OBWCsXoejp8rC35fi4+l6gXFZlD0Rz6fZ1tdDmKR9'. '6zb3tm987OBWCsXoejp8rC35fi4+l6gXFZlD0Rz6fZ1tdDmKR9'.
'RdOmkzmP7DDpilfX3SzvRgQ/Vr1uiZplfsCBiVf03RJd140wgj'. 'RdOmkzmP7DDpilfX3SzvRgQ/Vr1uiZplfsCBiVf03RJd140wgj'.
'kmNqMtuYXcxyYmNWJdRoYwzpM9qRvGujuCmSR7q7ARY00/MiWk'. 'kmNqMtuYXcxyYmNWJdRoYwzpM9qRvGujuCmSR7q7ARY00/MiWk'.
'sCnjkobNEm1+HknDZgAqR0GKU43+wxdu2hYzbsHU6AAAAABJRU'. 'sCnjkobNEm1+HknDZgAqR0GKU43+wxdu2hYzbsHU6AAAAABJRU'.
'5ErkJggg==' ; '5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bs_lightred.png // File: bs_lightred.png
//========================================================== //==========================================================
$this->imgdata_small[14][0]= 532 ; $this->imgdata_small[14][0]= 532 ;
$this->imgdata_small[14][1]= $this->imgdata_small[14][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAA3l'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAA3l'.
'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'. 'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'.
'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'. 'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'.
'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'. 'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'.
'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'. 'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'.
'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'. 'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'.
'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'. 'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'.
'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. 'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGjoP2Nm+AAAAr0'. 'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGjoP2Nm+AAAAr0'.
'lEQVR4nGNgIBaYiOk62imYwPnMkiIyso76yhJSzFARMxkRNk49'. 'lEQVR4nGNgIBaYiOk62imYwPnMkiIyso76yhJSzFARMxkRNk49'.
'a3t5OW6oFk1LVkYOfWUHKxUXiEYzLS12DnN3VXkjIRtFsIiSk5'. 'a3t5OW6oFk1LVkYOfWUHKxUXiEYzLS12DnN3VXkjIRtFsIiSk5'.
'6evqGqhYGKugAfWMRa1FpD2UHeQEXQRlgALCJur+rgbCUNFOAS'. '6evqGqhYGKugAfWMRa1FpD2UHeQEXQRlgALCJur+rgbCUNFOAS'.
'hqjRkZe3MpBTcwEKCEPMMTGSs3Xz8OQHCnBBHckt6OJpIyAMBD'. 'hqjRkZe3MpBTcwEKCEPMMTGSs3Xz8OQHCnBBHckt6OJpIyAMBD'.
'wwN/MYc4H4LK4wNzMwmGrzcvFqmxIdDgDiHRT6VVQkrAAAAABJ'. 'wwN/MYc4H4LK4wNzMwmGrzcvFqmxIdDgDiHRT6VVQkrAAAAABJ'.
'RU5ErkJggg==' ; 'RU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bxs_lightred.png // File: bxs_lightred.png
//========================================================== //==========================================================
$this->imgdata_xsmall[0][0]= 432 ; $this->imgdata_xsmall[0][0]= 432 ;
$this->imgdata_xsmall[0][1]= $this->imgdata_xsmall[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAA3l'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAA3l'.
'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'. 'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'.
'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'. 'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'.
'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'. 'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'.
'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'. 'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'.
'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'. 'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'.
'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'. 'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'.
'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. 'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKBOgGhWjAAAAS0'. 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKBOgGhWjAAAAS0'.
'lEQVR4nGNgQAEmunYmEJaMCKe1vBxYzJKVQ9lKBSSupKdnaKGi'. 'lEQVR4nGNgQAEmunYmEJaMCKe1vBxYzJKVQ9lKBSSupKdnaKGi'.
'zgdkiqs6WKnYcIGYJnK2HvzCwmCNgi42wsLCECNMeXlNUY0HAL'. 'zgdkiqs6WKnYcIGYJnK2HvzCwmCNgi42wsLCECNMeXlNUY0HAL'.
'DaB7Du8MiEAAAAAElFTkSuQmCC' ; 'DaB7Du8MiEAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bxs_bluegreen.png // File: bxs_bluegreen.png
//========================================================== //==========================================================
$this->imgdata_xsmall[1][0]= 397 ; $this->imgdata_xsmall[1][0]= 397 ;
$this->imgdata_xsmall[1][1]= $this->imgdata_xsmall[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAvV'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAvV'.
'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'. 'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'.
'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'. 'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'.
'8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'. '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'.
'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'. 'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'.
'0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'. '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'.
'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'. 'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'.
'AJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKDVyF5Be'. 'AJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKDVyF5Be'.
'AAAASUlEQVR4nGNgQAFmYqJcEJaEOJ+UrD5YTJKFTZrfGCQuaq'. 'AAAASUlEQVR4nGNgQAFmYqJcEJaEOJ+UrD5YTJKFTZrfGCQuaq'.
'glLWvMaQ5kqujo6hnbKIKYXPr68gp2dmCNJiZAlh3ECGsREWtU'. 'glLWvMaQ5kqujo6hnbKIKYXPr68gp2dmCNJiZAlh3ECGsREWtU'.
'4wF1kwdpAHfnSwAAAABJRU5ErkJggg==' ; '4wF1kwdpAHfnSwAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bxs_navy.png // File: bxs_navy.png
//========================================================== //==========================================================
$this->imgdata_xsmall[2][0]= 353 ; $this->imgdata_xsmall[2][0]= 353 ;
$this->imgdata_xsmall[2][1]= $this->imgdata_xsmall[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'.
'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'. 'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'.
'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'. 'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'.
'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'. 'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'.
'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'. 'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'.
'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. 'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJxXO4axZAAAAR0'. 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJxXO4axZAAAAR0'.
'lEQVR4nGNgQAGskhKsEJaslIi8ijpYTJaDU1FVAyQuKSujoKKh'. 'lEQVR4nGNgQAGskhKsEJaslIi8ijpYTJaDU1FVAyQuKSujoKKh'.
'LQ5kSigpqWro6oOYrOoaWroGBmCNWiCWAdQwUVFWVOMBOp4GCJ'. 'LQ5kSigpqWro6oOYrOoaWroGBmCNWiCWAdQwUVFWVOMBOp4GCJ'.
's5S60AAAAASUVORK5CYII=' ; 's5S60AAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bxs_gray.png // File: bxs_gray.png
//========================================================== //==========================================================
$this->imgdata_xsmall[3][0]= 492 ; $this->imgdata_xsmall[3][0]= 492 ;
$this->imgdata_xsmall[3][1]= $this->imgdata_xsmall[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABI1'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABI1'.
'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'. 'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'.
'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'. 'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'.
'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'. 'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'.
'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'. 'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'.
'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'. 'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'.
'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'. 'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'.
'3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'. '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'.
'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'. 'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'.
'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEA'. 'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEA'.
'AAsRAX9kX5EAAAAHdElNRQfTAwkUKC74clmyAAAAQklEQVR4nG'. 'AAsRAX9kX5EAAAAHdElNRQfTAwkUKC74clmyAAAAQklEQVR4nG'.
'NgQAVBYVCGt5dXYEQ0mOnp5h4QFgVmeri6+4dHxYMVeHoFRUTH'. 'NgQAVBYVCGt5dXYEQ0mOnp5h4QFgVmeri6+4dHxYMVeHoFRUTH'.
'gTUFBIZBWAwMkZEx8bFQM2Lj0UwHANc/DV6yq/BiAAAAAElFTk'. 'gTUFBIZBWAwMkZEx8bFQM2Lj0UwHANc/DV6yq/BiAAAAAElFTk'.
'SuQmCC' ; 'SuQmCC' ;
   
//========================================================== //==========================================================
// File: bxs_graypurple.png // File: bxs_graypurple.png
//========================================================== //==========================================================
$this->imgdata_xsmall[4][0]= 542 ; $this->imgdata_xsmall[4][0]= 542 ;
$this->imgdata_xsmall[4][1]= $this->imgdata_xsmall[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABSl'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABSl'.
'BMVEX////////11P/MqdvKrNfAwMC+u7+9u7+4rr24lsi3rby3'. 'BMVEX////////11P/MqdvKrNfAwMC+u7+9u7+4rr24lsi3rby3'.
'lMe1rLq1o720q7i0oL20ksSzoryyqbaykMGxlb2wkL+vnbiujb'. 'lMe1rLq1o720q7i0oL20ksSzoryyqbaykMGxlb2wkL+vnbiujb'.
'2sjLuri7qpl7GoirWoibenmK2mla6mjLKmhrSllauki7CjhrCj'. '2sjLuri7qpl7GoirWoibenmK2mla6mjLKmhrSllauki7CjhrCj'.
'hLGihLChg6+ggq2fkqadkKOcfqqai6Gag6WYe6WXeqSWeaOTd6'. 'hLGihLChg6+ggq2fkqadkKOcfqqai6Gag6WYe6WXeqSWeaOTd6'.
'CTd5+Rdp6RdZ6RdZ2Qg5eOc5qMcpiLcZeJb5WIbpOHbZKGbJGE'. 'CTd5+Rdp6RdZ6RdZ2Qg5eOc5qMcpiLcZeJb5WIbpOHbZKGbJGE'.
'a4+CaY2AZ4t/Z4p/Zop/Zol+Zol7ZIZ6Y4V5YoR1ZH11X391Xn'. 'a4+CaY2AZ4t/Z4p/Zop/Zol+Zol7ZIZ6Y4V5YoR1ZH11X391Xn'.
'9zXX1yXXtxXHtvWnluWXhsV3VqVnNpVXJoVHFnU3BmUm9jUGth'. '9zXX1yXXtxXHtvWnluWXhsV3VqVnNpVXJoVHFnU3BmUm9jUGth'.
'VGdgTmheTGZcS2RcSmRaSWJYR19XRl5SQllRQlhQQVdPQFZOP1'. 'VGdgTmheTGZcS2RcSmRaSWJYR19XRl5SQllRQlhQQVdPQFZOP1'.
'VLPlFJO09IPE5IOk5FOEtEN0lDOEpDOElDNklCNkc/M0XhbrfD'. 'VLPlFJO09IPE5IOk5FOEtEN0lDOEpDOElDNklCNkc/M0XhbrfD'.
'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
'EAAAsRAX9kX5EAAAAHdElNRQfTAwkUKCgREfyHAAAATUlEQVR4'. 'EAAAsRAX9kX5EAAAAHdElNRQfTAwkUKCgREfyHAAAATUlEQVR4'.
'nGNgQAEcIko8EBY3M5Ougy+IxSXMwmTsFsAHZMqrSRvZB0W7A5'. 'nGNgQAEcIko8EBY3M5Ougy+IxSXMwmTsFsAHZMqrSRvZB0W7A5'.
'k6FlYugXEZICaPr394Um4uSAFDRFRCbm4uxAihsDAhVOMBHT0L'. 'k6FlYugXEZICaPr394Um4uSAFDRFRCbm4uxAihsDAhVOMBHT0L'.
'hkeRpo8AAAAASUVORK5CYII=' ; 'hkeRpo8AAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bxs_red.png // File: bxs_red.png
//========================================================== //==========================================================
$this->imgdata_xsmall[5][0]= 357 ; $this->imgdata_xsmall[5][0]= 357 ;
$this->imgdata_xsmall[5][1]= $this->imgdata_xsmall[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'.
'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'. 'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'.
'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'. 'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'.
'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'. 'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'.
'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'. 'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'.
'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'. 'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIyjy5SVMAAAAS0'. 'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIyjy5SVMAAAAS0'.
'lEQVR4nGNgQAFsUpJsEJastIi8ijpYTJaDU0FVgxXIlJKVUVDR'. 'lEQVR4nGNgQAFsUpJsEJastIi8ijpYTJaDU0FVgxXIlJKVUVDR'.
'0BYHMiUUlVQ1dPVBTDZ1dS1dAwOQAgYtbSDLAGIEq6goK6rxAD'. '0BYHMiUUlVQ1dPVBTDZ1dS1dAwOQAgYtbSDLAGIEq6goK6rxAD'.
'yXBg73lwGUAAAAAElFTkSuQmCC' ; 'yXBg73lwGUAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: bxs_yellow.png // File: bxs_yellow.png
//========================================================== //==========================================================
$this->imgdata_xsmall[6][0]= 414 ; $this->imgdata_xsmall[6][0]= 414 ;
$this->imgdata_xsmall[6][1]= $this->imgdata_xsmall[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAzF'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAzF'.
'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'. 'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'.
'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'. 'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'.
'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'. 'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'.
'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'. 'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'.
'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'. 'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'.
'50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'. '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'.
'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAH'. 'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAH'.
'dElNRQfTAwkUIzoBXFQEAAAAS0lEQVR4nGNgQAFsDhJsEJaTo5'. 'dElNRQfTAwkUIzoBXFQEAAAAS0lEQVR4nGNgQAFsDhJsEJaTo5'.
'2skj5YzMnSSk7ZwBzIlOSUklPiMxYHMnW4FXT5VNVBTDZeXiNV'. '2skj5YzMnSSk7ZwBzIlOSUklPiMxYHMnW4FXT5VNVBTDZeXiNV'.
'QUGQAgYBYyBLEGIEq5gYK6rxAH4kBmHBaMQQAAAAAElFTkSuQm'. 'QUGQAgYBYyBLEGIEq5gYK6rxAH4kBmHBaMQQAAAAAElFTkSuQm'.
'CC' ; 'CC' ;
   
//========================================================== //==========================================================
// File: bxs_greenblue.png // File: bxs_greenblue.png
//========================================================== //==========================================================
$this->imgdata_xsmall[7][0]= 410 ; $this->imgdata_xsmall[7][0]= 410 ;
$this->imgdata_xsmall[7][1]= $this->imgdata_xsmall[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAxl'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAxl'.
'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'. 'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'.
'9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'. '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'.
'17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'. '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'.
'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'. 'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'.
'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'. 'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'.
'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'. 'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'.
'dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfT'. 'dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfT'.
'AwkUJy5/6kV9AAAATUlEQVR4nGNgQAGCyuyCEJaGugKHviVYzF'. 'AwkUJy5/6kV9AAAATUlEQVR4nGNgQAGCyuyCEJaGugKHviVYzF'.
'hO3sxCWwDIVNLTM9PXtpEGMhW12Cy0DR1ATEFLSxZ7BweQAgYd'. 'hO3sxCWwDIVNLTM9PXtpEGMhW12Cy0DR1ATEFLSxZ7BweQAgYd'.
'HUMHBweIEQKiogKoxgMAo/4H5AfSehsAAAAASUVORK5CYII=' ; 'HUMHBweIEQKiogKoxgMAo/4H5AfSehsAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bxs_purple.png // File: bxs_purple.png
//========================================================== //==========================================================
$this->imgdata_xsmall[8][0]= 364 ; $this->imgdata_xsmall[8][0]= 364 ;
$this->imgdata_xsmall[8][1]= $this->imgdata_xsmall[8][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAnF'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAnF'.
'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'. 'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'.
'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'. 'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'.
'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'. 'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'.
'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'. 'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'.
'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. 'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
'HUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIj'. 'HUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIj'.
'mBTjT/AAAASUlEQVR4nGNgQAGskhKsEJaCrJiSuhZYTEFASFlD'. 'mBTjT/AAAASUlEQVR4nGNgQAGskhKsEJaCrJiSuhZYTEFASFlD'.
'GyQuqSCnrK6tJwpkiquoamgbGIGYrFpaugbGxmCNunpAljHECB'. 'GyQuqSCnrK6tJwpkiquoamgbGIGYrFpaugbGxmCNunpAljHECB'.
'ZBQRZU4wFSMAZsXeM71AAAAABJRU5ErkJggg==' ; 'ZBQRZU4wFSMAZsXeM71AAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bxs_green.png // File: bxs_green.png
//========================================================== //==========================================================
$this->imgdata_xsmall[9][0]= 370 ; $this->imgdata_xsmall[9][0]= 370 ;
$this->imgdata_xsmall[9][1]= $this->imgdata_xsmall[9][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAn1'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAn1'.
'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'. 'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'.
'/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'. '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'.
'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'. 'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'.
'5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'. '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'.
'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'. 'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'.
'AIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAw'. 'AIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAw'.
'kUKBrZxq0HAAAATElEQVR4nGNgQAGccrIcEJaivISyhjaIxa7I'. 'kUKBrZxq0HAAAATElEQVR4nGNgQAGccrIcEJaivISyhjaIxa7I'.
'I6CiqcMKZMopKqho6OhLA5kyqmqaOobGICartraeoYkJSAGDnj'. 'I6CiqcMKZMopKqho6OhLA5kyqmqaOobGICartraeoYkJSAGDnj'.
'6QZQIxgk1Skg3VeABlVgbItqEBUwAAAABJRU5ErkJggg==' ; '6QZQIxgk1Skg3VeABlVgbItqEBUwAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bxs_darkgreen.png // File: bxs_darkgreen.png
//========================================================== //==========================================================
$this->imgdata_xsmall[10][0]= 563 ; $this->imgdata_xsmall[10][0]= 563 ;
$this->imgdata_xsmall[10][1]= $this->imgdata_xsmall[10][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABX1'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABX1'.
'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'. 'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'.
'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'. 'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'.
'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'. 'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'.
'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'. 'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'.
'6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'. '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'.
'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'. 'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'.
'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'. 'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'.
'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'. 'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'.
'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'. 'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'.
'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'. 'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'.
'RQfTAwkUKCFozUQjAAAATUlEQVR4nGNgQAGcoqrcEJYQB5OhSw'. 'RQfTAwkUKCFozUQjAAAATUlEQVR4nGNgQAGcoqrcEJYQB5OhSw'.
'CIxSXGwWThGcIDZCppK5o7hyV6AZl6NnbuoSmFICZ3YHB0RkkJ'. 'CIxSXGwWThGcIDZCppK5o7hyV6AZl6NnbuoSmFICZ3YHB0RkkJ'.
'SAFDbEJaSUkJxAjeyEheVOMBQj4MOEkWew4AAAAASUVORK5CYI'. 'SAFDbEJaSUkJxAjeyEheVOMBQj4MOEkWew4AAAAASUVORK5CYI'.
'I=' ; 'I=' ;
   
//========================================================== //==========================================================
// File: bxs_cyan.png // File: bxs_cyan.png
//========================================================== //==========================================================
$this->imgdata_xsmall[11][0]= 530 ; $this->imgdata_xsmall[11][0]= 530 ;
$this->imgdata_xsmall[11][1]= $this->imgdata_xsmall[11][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABPl'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABPl'.
'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'. 'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'.
'//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'. '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'.
'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'. 'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'.
'/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'. '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'.
'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'. 'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'.
'3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'. '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'.
'4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'. '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'.
'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'. 'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'.
'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'. 'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'.
'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAA'. 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAA'.
'AHdElNRQfTAwkUKQFKuFWqAAAATUlEQVR4nGNgQAGsUjJsEJaR'. 'AHdElNRQfTAwkUKQFKuFWqAAAATUlEQVR4nGNgQAGsUjJsEJaR'.
'grC5qz9YzIiL28YriB3IlDZRsnYNiZUDMmXtHT2CE9JBTDb/wI'. 'grC5qz9YzIiL28YriB3IlDZRsnYNiZUDMmXtHT2CE9JBTDb/wI'.
'jkzEyQAoaomMTMzEyIERzy8hyoxgMAN2MLVPW0f4gAAAAASUVO'. 'jkzEyQAoaomMTMzEyIERzy8hyoxgMAN2MLVPW0f4gAAAAASUVO'.
'RK5CYII=' ; 'RK5CYII=' ;
   
//========================================================== //==========================================================
// File: bxs_orange.png // File: bxs_orange.png
//========================================================== //==========================================================
$this->imgdata_xsmall[12][0]= 572 ; $this->imgdata_xsmall[12][0]= 572 ;
$this->imgdata_xsmall[12][1]= $this->imgdata_xsmall[12][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABaF'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABaF'.
'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'. 'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'.
'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'. 'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'.
'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'. 'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'.
'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'. 'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'.
'/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'. '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'.
'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'. 'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'.
'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'. 'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'.
'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'. 'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'.
'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'. 'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'.
'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'. 'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'.
'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9k'. 'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9k'.
'X5EAAAAHdElNRQfTAwkUJBSSy88MAAAATUlEQVR4nGNgQAGqwo'. 'X5EAAAAHdElNRQfTAwkUJBSSy88MAAAATUlEQVR4nGNgQAGqwo'.
'paEBYPJ4eKezCIpc7HwmrqG6ENZMpLihm6RaWEAZl6Vo7ekRnF'. 'paEBYPJ4eKezCIpc7HwmrqG6ENZMpLihm6RaWEAZl6Vo7ekRnF'.
'IKZWSHhcTnk5SAFDfFJWeXk5xAjj1FRjVOMBeFwNcWYSLjsAAA'. 'IKZWSHhcTnk5SAFDfFJWeXk5xAjj1FRjVOMBeFwNcWYSLjsAAA'.
'AASUVORK5CYII=' ; 'AASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bxs_lightblue.png // File: bxs_lightblue.png
//========================================================== //==========================================================
$this->imgdata_xsmall[13][0]= 554 ; $this->imgdata_xsmall[13][0]= 554 ;
$this->imgdata_xsmall[13][1]= $this->imgdata_xsmall[13][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABVl'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABVl'.
'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'. 'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'.
'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'. 'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'.
'+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'. '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'.
'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'. 'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'.
'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'. 'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'.
'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'. 'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'.
'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'. 'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'.
'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'. 'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'.
'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'. 'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'.
'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'. 'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
'gAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJziL'. 'gAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJziL'.
'PvAsAAAATUlEQVR4nGNgQAHsQgqcEJYgG5Oegy+IxSHOxmTiFs'. 'PvAsAAAATUlEQVR4nGNgQAHsQgqcEJYgG5Oegy+IxSHOxmTiFs'.
'gFZMprKBnbB8e7AplaFlbOQUl5ICanX0BEWmEhSAFDVGxKYWEh'. 'gFZMprKBnbB8e7AplaFlbOQUl5ICanX0BEWmEhSAFDVGxKYWEh'.
'xAjusDBuVOMBJO8LrFHRAykAAAAASUVORK5CYII=' ; 'xAjusDBuVOMBJO8LrFHRAykAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bxs_darkgray.png // File: bxs_darkgray.png
//========================================================== //==========================================================
$this->imgdata_xsmall[14][0]= 574 ; $this->imgdata_xsmall[14][0]= 574 ;
$this->imgdata_xsmall[14][1]= $this->imgdata_xsmall[14][1]=
'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABm'.
'JLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAB'. 'JLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAB'.
'iElEQVR42k3QPU8TYRwA8P//ebkXrgdIColXRAOEkJqbaExMut'. 'iElEQVR42k3QPU8TYRwA8P//ebkXrgdIColXRAOEkJqbaExMut'.
'DBhE1GNjYHPg+DG6ODiU6QOLjVxITBcFKBYCstlAC2Bz17fe76'. 'DBhE1GNjYHPg+DG6ODiU6QOLjVxITBcFKBYCstlAC2Bz17fe76'.
'vLD6+wg/1FpTRFR5lpaub/u1eGBGaAT4HneD4OlXx7avtDYUjT'. 'vLD6+wg/1FpTRFR5lpaub/u1eGBGaAT4HneD4OlXx7avtDYUjT'.
'HQabd2Ti8e3vVSKzxrtHS32wIpFVldno22Nqvvg2Bhl0gp/aNm'. 'HQabd2Ti8e3vVSKzxrtHS32wIpFVldno22Nqvvg2Bhl0gp/aNm'.
'vJ3qqXAtLIva+ks1H0wqlSXi4+d6+OFTfRsAfHJx2d1od24rZP'. 'vJ3qqXAtLIva+ks1H0wqlSXi4+d6+OFTfRsAfHJx2d1od24rZP'.
'xP2HzopINr1mkesX7ccojqif0v9crxWXODZTno3+dNGA7uWLsd'. 'xP2HzopINr1mkesX7ccojqif0v9crxWXODZTno3+dNGA7uWLsd'.
'mUYU4fHJCViMG9umLBmM4L6fagZGg9QKfjZ+Qfy3C3G/B3mugF'. 'mUYU4fHJCViMG9umLBmM4L6fagZGg9QKfjZ+Qfy3C3G/B3mugF'.
'IHHNcDf64E3KJALApk2p8CSolUUqLjFkyxOGMsTtFyJ+Wz57NQ'. 'IHHNcDf64E3KJALApk2p8CSolUUqLjFkyxOGMsTtFyJ+Wz57NQ'.
'8DghS4sLB0svioeZZo7nPhFoUKZDIVFbglkTTnl5/rC8snjAkJ'. '8DghS4sLB0svioeZZo7nPhFoUKZDIVFbglkTTnl5/rC8snjAkJ'.
'Bk/XV5LxHC/v7tR8jzTFPbg8LENK9WX0Vv31T2AEmCSmlKCCoh'. 'Bk/XV5LxHC/v7tR8jzTFPbg8LENK9WX0Vv31T2AEmCSmlKCCoh'.
'ROnP1U1tPFYjJBRcbtzSf+GPsFTAQBq1n4AAAABKdEVYdHNpZ2'. 'ROnP1U1tPFYjJBRcbtzSf+GPsFTAQBq1n4AAAABKdEVYdHNpZ2'.
'5hdHVyZQBiYzYyMDIyNjgwYThjODMyMmUxNjk0NWUzZjljOGFh'. '5hdHVyZQBiYzYyMDIyNjgwYThjODMyMmUxNjk0NWUzZjljOGFh'.
'N2VmZWFhMjA4OTE2ZjkwOTdhZWE1MzYyMjk0MWRkM2I5EqaPDA'. 'N2VmZWFhMjA4OTE2ZjkwOTdhZWE1MzYyMjk0MWRkM2I5EqaPDA'.
'AAAABJRU5ErkJggg==' ; 'AAAABJRU5ErkJggg==' ;
} }
} }
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: IMGDATA_BEVELS.INC // File: IMGDATA_BEVELS.INC
// Description: Base64 encoded images for round bevels // Description: Base64 encoded images for round bevels
// Created: 2003-03-20 // Created: 2003-03-20
// Ver: $Id: imgdata_bevels.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: imgdata_bevels.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class ImgData_Bevels extends ImgData { class ImgData_Bevels extends ImgData {
protected $name = 'Round Bevels'; protected $name = 'Round Bevels';
protected $an = array(MARK_IMG_BEVEL => 'imgdata'); protected $an = array(MARK_IMG_BEVEL => 'imgdata');
   
protected $colors = array('green','purple','orange','red','yellow'); protected $colors = array('green','purple','orange','red','yellow');
protected $index = array('green'=>1,'purple'=>4,'orange'=>2,'red'=>0,'yellow'=>3); protected $index = array('green'=>1,'purple'=>4,'orange'=>2,'red'=>0,'yellow'=>3);
protected $maxidx = 4 ; protected $maxidx = 4 ;
   
protected $imgdata ; protected $imgdata ;
   
function __construct() { function __construct() {
//========================================================== //==========================================================
// File: bullets_balls_red_013.png // File: bullets_balls_red_013.png
//========================================================== //==========================================================
$this->imgdata[0][0]= 337 ; $this->imgdata[0][0]= 337 ;
$this->imgdata[0][1]= $this->imgdata[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
'BMVEX////////27t/f3+LFwcmNxMuxm62DmqKth1VpZmIWg6fv'. 'BMVEX////////27t/f3+LFwcmNxMuxm62DmqKth1VpZmIWg6fv'.
'HCa7K0BwMEytCjFnIyUlEBg9vhQvAAAAAXRSTlMAQObYZgAAAA'. 'HCa7K0BwMEytCjFnIyUlEBg9vhQvAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
'RQfTAxcBNhk+pYJVAAAAl0lEQVR4nE2Q2xLDIAgFHUWBKJf//9'. 'RQfTAxcBNhk+pYJVAAAAl0lEQVR4nE2Q2xLDIAgFHUWBKJf//9'.
'oekmbafVDZARRbK/pYTKP9WNcNv64zzUdd9BjmrgnsVXRNSzO3'. 'oekmbafVDZARRbK/pYTKP9WNcNv64zzUdd9BjmrgnsVXRNSzO3'.
'CJ5ahdhy0XKQkxld1kxb45j7dp0x2lBNOyVgQpMaoadX7Hs7zr'. 'CJ5ahdhy0XKQkxld1kxb45j7dp0x2lBNOyVgQpMaoadX7Hs7zr'.
'P1yKj47DKBnKaBKiSAkNss7O6PkMx6kIgYXISQJpcZCqdY6KR+'. 'P1yKj47DKBnKaBKiSAkNss7O6PkMx6kIgYXISQJpcZCqdY6KR+'.
'J1PkS5Xob/h7MNz8x6D3fz5DKQjpkZOBYAAAAABJRU5ErkJggg'. 'J1PkS5Xob/h7MNz8x6D3fz5DKQjpkZOBYAAAAABJRU5ErkJggg'.
'==' ; '==' ;
   
//========================================================== //==========================================================
// File: bullets_balls_green_013.png // File: bullets_balls_green_013.png
//========================================================== //==========================================================
$this->imgdata[1][0]= 344 ; $this->imgdata[1][0]= 344 ;
$this->imgdata[1][1]= $this->imgdata[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
'BMVEX////////27t/e3+K3vriUub/Dm18j4xc3ob10k0ItqQlU'. 'BMVEX////////27t/e3+K3vriUub/Dm18j4xc3ob10k0ItqQlU'.
'e5JBmwpxY1ENaKBgUh0iHgwsSre9AAAAAXRSTlMAQObYZgAAAA'. 'e5JBmwpxY1ENaKBgUh0iHgwsSre9AAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
'RQfTAxcBNTfJXtxZAAAAnklEQVR4nE2QWY4EMQhDUVhSIRC4/2'. 'RQfTAxcBNTfJXtxZAAAAnklEQVR4nE2QWY4EMQhDUVhSIRC4/2'.
'kbaqLp9p+f2AxAayAzDfiK9znPORuvH0x8Ss9z6I9sHp6tcxE9'. 'kbaqLp9p+f2AxAayAzDfiK9znPORuvH0x8Ss9z6I9sHp6tcxE9'.
'nLmWmebmt5F5p2AR0+C9AWpLBjXRaZsCAT3SqklVp0YkAWaGtd'. 'nLmWmebmt5F5p2AR0+C9AWpLBjXRaZsCAT3SqklVp0YkAWaGtd'.
'c5Z41/STYpPzW7BjyiRrwkVmQto/Cw9tNEMvsgcekyCyFPboIu'. 'c5Z41/STYpPzW7BjyiRrwkVmQto/Cw9tNEMvsgcekyCyFPboIu'.
'IsuXiKffYB4NK4r/h6d4g9HPPwCR7i8+GscIiiaonUAAAAAASU'. 'IsuXiKffYB4NK4r/h6d4g9HPPwCR7i8+GscIiiaonUAAAAAASU'.
'VORK5CYII=' ; 'VORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bullets_balls_oy_035.png // File: bullets_balls_oy_035.png
//========================================================== //==========================================================
$this->imgdata[2][0]= 341 ; $this->imgdata[2][0]= 341 ;
$this->imgdata[2][1]= $this->imgdata[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
'BMVEX////////27t/f3+K5tbqNwcjnkjXjbxR2i5anfEoNkbis'. 'BMVEX////////27t/f3+K5tbqNwcjnkjXjbxR2i5anfEoNkbis'.
'PBxpU0sZbZejKgdqIRIlERIwYtkYAAAAAXRSTlMAQObYZgAAAA'. 'PBxpU0sZbZejKgdqIRIlERIwYtkYAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
'RQfTAxcBNgK0wEu5AAAAm0lEQVR4nE3QVxIEIQgEUErAgTHA/U'. 'RQfTAxcBNgK0wEu5AAAAm0lEQVR4nE3QVxIEIQgEUErAgTHA/U'.
'+7zbipf9RXgoGo0liMmX6RdSPLPtZM9F4LuuSIaZtZWffiU6Iz'. '+7zbipf9RXgoGo0liMmX6RdSPLPtZM9F4LuuSIaZtZWffiU6Iz'.
'Y8SOMF0NogBj30ioGRGLZgiPvce1TbIRz6oBQEbOFGK0rIoxrn'. 'Y8SOMF0NogBj30ioGRGLZgiPvce1TbIRz6oBQEbOFGK0rIoxrn'.
'5hDomMA1cfGRCaRVhjS3gkzheM+4HtnlkXcvdZhWG4qZawewe6'. '5hDomMA1cfGRCaRVhjS3gkzheM+4HtnlkXcvdZhWG4qZawewe6'.
'9Jnz/TKLB/ML6HUepn//QczazuwFO/0Ivpolhi4AAAAASUVORK'. '9Jnz/TKLB/ML6HUepn//QczazuwFO/0Ivpolhi4AAAAASUVORK'.
'5CYII=' ; '5CYII=' ;
   
//========================================================== //==========================================================
// File: bullets_balls_oy_036.png // File: bullets_balls_oy_036.png
//========================================================== //==========================================================
$this->imgdata[3][0]= 340 ; $this->imgdata[3][0]= 340 ;
$this->imgdata[3][1]= $this->imgdata[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
'BMVEX////////27t/e3+LO3hfYzz65ubiNwci6uQ12ipadgVGa'. 'BMVEX////////27t/e3+LO3hfYzz65ubiNwci6uQ12ipadgVGa'.
'fwsNkbhnVkcaZ5dwSA8lFg7CEepmAAAAAXRSTlMAQObYZgAAAA'. 'fwsNkbhnVkcaZ5dwSA8lFg7CEepmAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'.
'RQfTAxcCBySi1nevAAAAjElEQVR4nFXPWw7EIAgFUNMoCMhj/6'. 'RQfTAxcCBySi1nevAAAAjElEQVR4nFXPWw7EIAgFUNMoCMhj/6'.
'staKczc/2RkwjS2glQ+w3YytgXCXCZpRo8gJdGxZadJws13CUP'. 'staKczc/2RkwjS2glQ+w3YytgXCXCZpRo8gJdGxZadJws13CUP'.
'4SZI4MYiUxypeiGGw1XShVBTNN9kLXP2GRrZPFvKgd7z/sqGGV'. '4SZI4MYiUxypeiGGw1XShVBTNN9kLXP2GRrZPFvKgd7z/sqGGV'.
'7C7r7r3l09alYN3iA8Yn+ImdVrNoEeSRqJPAaHfhZzLYwXstdZ'. '7C7r7r3l09alYN3iA8Yn+ImdVrNoEeSRqJPAaHfhZzLYwXstdZ'.
'rP3n2bvdAI4INwtihiwAAAAASUVORK5CYII=' ; 'rP3n2bvdAI4INwtihiwAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: bullets_balls_pp_019.png // File: bullets_balls_pp_019.png
//========================================================== //==========================================================
$this->imgdata[4][0]= 334 ; $this->imgdata[4][0]= 334 ;
$this->imgdata[4][1]= $this->imgdata[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'. 'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
'BMVEX////+/v7i4eO/w8eHxcvKroNVormtfkjrMN2BeXQrepPc'. 'BMVEX////+/v7i4eO/w8eHxcvKroNVormtfkjrMN2BeXQrepPc'.
'Esy4IL+OFaR7F25LHF8mFRh5XXtUAAAAAXRSTlMAQObYZgAAAA'. 'Esy4IL+OFaR7F25LHF8mFRh5XXtUAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
'RQfTAxcBNgkjEpIxAAAAlElEQVR4nE2QAQ7FIAhDDTAVndL7n3'. 'RQfTAxcBNgkjEpIxAAAAlElEQVR4nE2QAQ7FIAhDDTAVndL7n3'.
'ZV/7JfEwMvFIWUlkTMVNInbVv5ZeJqG7Smh2QTBwJBpsdizAZP'. 'ZV/7JfEwMvFIWUlkTMVNInbVv5ZeJqG7Smh2QTBwJBpsdizAZP'.
'5NyW0awhK8kYodnZxS6ECvPRp2sI+y7PBv1mN02KH7h77QCJ8D'. '5NyW0awhK8kYodnZxS6ECvPRp2sI+y7PBv1mN02KH7h77QCJ8D'.
'4VvY5NUgEmCwj6ZMzHtJRgRSXwC1gfcqJJH0GBnSnK1kUQ72DY'. '4VvY5NUgEmCwj6ZMzHtJRgRSXwC1gfcqJJH0GBnSnK1kUQ72DY'.
'CPBv+MCS/e0jib77eQAJxwiEWm7hFwAAAABJRU5ErkJggg==' ; 'CPBv+MCS/e0jib77eQAJxwiEWm7hFwAAAABJRU5ErkJggg==' ;
   
} }
} }
   
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: IMGDATA_DIAMONDS.INC // File: IMGDATA_DIAMONDS.INC
// Description: Base64 encoded images for diamonds // Description: Base64 encoded images for diamonds
// Created: 2003-03-20 // Created: 2003-03-20
// Ver: $Id: imgdata_diamonds.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: imgdata_diamonds.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class ImgData_Diamonds extends ImgData { class ImgData_Diamonds extends ImgData {
protected $name = 'Diamonds'; protected $name = 'Diamonds';
protected $an = array(MARK_IMG_DIAMOND =>'imgdata'); protected $an = array(MARK_IMG_DIAMOND =>'imgdata');
protected $colors = array('lightblue','darkblue','gray', protected $colors = array('lightblue','darkblue','gray',
'blue','pink','purple','red','yellow'); 'blue','pink','purple','red','yellow');
protected $index = array('lightblue' =>7,'darkblue'=>2,'gray'=>6, protected $index = array('lightblue' =>7,'darkblue'=>2,'gray'=>6,
'blue'=>4,'pink'=>1,'purple'=>5,'red'=>0,'yellow'=>3); 'blue'=>4,'pink'=>1,'purple'=>5,'red'=>0,'yellow'=>3);
   
protected $maxidx = 7 ; protected $maxidx = 7 ;
protected $imgdata ; protected $imgdata ;
   
function __construct() { function __construct() {
//========================================================== //==========================================================
// File: diam_red.png // File: diam_red.png
//========================================================== //==========================================================
$this->imgdata[0][0]= 668 ; $this->imgdata[0][0]= 668 ;
$this->imgdata[0][1]= $this->imgdata[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'.
'BMVEX///////+cAAD/AADOAABjAABrAADWGBjOCAj/CAj/GBj/'. 'BMVEX///////+cAAD/AADOAABjAABrAADWGBjOCAj/CAj/GBj/'.
'EBCcCAiMOTl7KSl7ISFzGBilGBjOEBBrCAjv5+eMQkK1QkKtMT'. 'EBCcCAiMOTl7KSl7ISFzGBilGBjOEBBrCAjv5+eMQkK1QkKtMT'.
'GtKSnWKSn/KSlzEBCcEBDexsb/tbXOe3ucWlqcUlKUSkr/e3vn'. 'GtKSnWKSn/KSlzEBCcEBDexsb/tbXOe3ucWlqcUlKUSkr/e3vn'.
'a2u9UlL/a2uEMTHeUlLeSkqtOTn/UlL/SkrWOTn/QkL/OTmlIS'. 'a2u9UlL/a2uEMTHeUlLeSkqtOTn/UlL/SkrWOTn/QkL/OTmlIS'.
'H/MTH/ISH39/f/9/f35+fezs7/5+fvzs7WtbXOra3nvb3/zs7G'. 'H/MTH/ISH39/f/9/f35+fezs7/5+fvzs7WtbXOra3nvb3/zs7G'.
'nJzvtbXGlJTepaW9jIy1hITWlJS1e3uta2ulY2P/lJTnhITne3'. 'nJzvtbXGlJTepaW9jIy1hITWlJS1e3uta2ulY2P/lJTnhITne3'.
'vGY2O9Wlr/c3PeY2O1Skr/Y2P/WlreQkLWISGlEBCglEUaAAAA'. 'vGY2O9Wlr/c3PeY2O1Skr/Y2P/WlreQkLWISGlEBCglEUaAAAA'.
'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'. 'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'.
'sSAdLdfvwAAAAHdElNRQfTAwsWEw5WI4qnAAABGUlEQVR4nHXQ'. 'sSAdLdfvwAAAAHdElNRQfTAwsWEw5WI4qnAAABGUlEQVR4nHXQ'.
'1XLDMBAFUKUCM1NiO8zcpIxpp8z0//9SWY7b2LHv6EU6s1qtAN'. '1XLDMBAFUKUCM1NiO8zcpIxpp8z0//9SWY7b2LHv6EU6s1qtAN'.
'iMBAojLPkigpJvogKC4pxDuQipjanlICXof1RQDkYEF21mKIfg'. 'iMBAojLPkigpJvogKC4pxDuQipjanlICXof1RQDkYEF21mKIfg'.
'/GGKtjAmOKt9oSyuCU7OhyiDCQnjowGfRnooCJIkiWJvv8NxnG'. '/GGKtjAmOKt9oSyuCU7OhyiDCQnjowGfRnooCJIkiWJvv8NxnG'.
'nyNAwFcekvZpPP3mu7Vrp8fOq8DYbTyjdnAvBj7Jbd7nP95urs'. 'nyNAwFcekvZpPP3mu7Vrp8fOq8DYbTyjdnAvBj7Jbd7nP95urs'.
'+MC2D6unF+Cu0VJULQBAlsOQuueN3Hrp2nGUvqppemBZ0aU7Se'. '+MC2D6unF+Cu0VJULQBAlsOQuueN3Hrp2nGUvqppemBZ0aU7Se'.
'SXvYZFMKaLJn7MH3btJmZEMEmGSOreqy0SI/4ffo3uiUOYEACy'. 'SXvYZFMKaLJn7MH3btJmZEMEmGSOreqy0SI/4ffo3uiUOYEACy'.
'OFopmNWlP5uZd9uPWmUoxvK9ilO9NtBo6mS7KkZD0fOJYqgGBU'. 'OFopmNWlP5uZd9uPWmUoxvK9ilO9NtBo6mS7KkZD0fOJYqgGBU'.
'S/T7OKCAA9tfsFOicXcbxt29cAAAAASUVORK5CYII=' ; 'S/T7OKCAA9tfsFOicXcbxt29cAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: diam_pink.png // File: diam_pink.png
//========================================================== //==========================================================
$this->imgdata[1][0]= 262 ; $this->imgdata[1][0]= 262 ;
$this->imgdata[1][1]= $this->imgdata[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
'BMVEX///+AgID/M5n/Zpn/zMz/mZn1xELhAAAAAXRSTlMAQObY'. 'BMVEX///+AgID/M5n/Zpn/zMz/mZn1xELhAAAAAXRSTlMAQObY'.
'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
'AHdElNRQfTAwsWEi3tX8qUAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. 'AHdElNRQfTAwsWEi3tX8qUAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
'6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
'==' ; '==' ;
   
//========================================================== //==========================================================
// File: diam_blue.png // File: diam_blue.png
//========================================================== //==========================================================
$this->imgdata[2][0]= 662 ; $this->imgdata[2][0]= 662 ;
$this->imgdata[2][1]= $this->imgdata[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA+V'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA+V'.
'BMVEX///+AgIAAAJwAAP8AAM4AAGMAAGsQEP8YGHMQEHMYGP8Q'. 'BMVEX///+AgIAAAJwAAP8AAM4AAGMAAGsQEP8YGHMQEHMYGP8Q'.
'EKUICJwICM5KSpQxMYQpKXsYGNYQEM4ICGsICP97e85aWpw5OY'. 'EKUICJwICM5KSpQxMYQpKXsYGNYQEM4ICGsICP97e85aWpw5OY'.
'xSUv85ObVCQt4xMa0pKa0hIaUpKf+9vd6EhLVra+dzc/9SUr1r'. 'xSUv85ObVCQt4xMa0pKa0hIaUpKf+9vd6EhLVra+dzc/9SUr1r'.
'a/9aWt5SUt5CQrVaWv9KSv8hIXs5Of8xMf8pKdYhIdYYGKUhIf'. 'a/9aWt5SUt5CQrVaWv9KSv8hIXs5Of8xMf8pKdYhIdYYGKUhIf'.
'/Ozs739//v7/fn5+/v7//n5/fW1ufOzufOzu/W1v+trc69veel'. '/Ozs739//v7/fn5+/v7//n5/fW1ufOzufOzu/W1v+trc69veel'.
'pc6trd6UlMa9vf+MjL21tfe1tf+UlNZzc61ra6Wlpf+EhOeMjP'. 'pc6trd6UlMa9vf+MjL21tfe1tf+UlNZzc61ra6Wlpf+EhOeMjP'.
'9ra8ZSUpyEhP9CQoxKSrVCQv85Od4xMdYQENZnJhlWAAAAAXRS'. '9ra8ZSUpyEhP9CQoxKSrVCQv85Od4xMdYQENZnJhlWAAAAAXRS'.
'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'. 'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
'LdfvwAAAAHdElNRQfTAwsWEx3Snct5AAABFklEQVR4nHXR5XbD'. 'LdfvwAAAAHdElNRQfTAwsWEx3Snct5AAABFklEQVR4nHXR5XbD'.
'IBgGYM6AuHsaqbvOfeuknev9X8xISbplSd5/8JyXwwcA/I0AKm'. 'IBgGYM6AuHsaqbvOfeuknev9X8xISbplSd5/8JyXwwcA/I0AKm'.
'PFchVBdvKNKggKQx2VIoRwMZihMiQE49YUlWBCcPL0hYq4ITh+'. 'PFchVBdvKNKggKQx2VIoRwMZihMiQE49YUlWBCcPL0hYq4ITh+'.
'qKECUoLDZWqoQNA766F/mJHlHXblPJJNiyURhM5eU9cNw5BlmS'. 'qKECUoLDZWqoQNA766F/mJHlHXblPJJNiyURhM5eU9cNw5BlmS'.
'IrLOLxhzfotF7vwO2j3ez2ap/TmW4AIM7DoN9+tu+vLk6Pdg9O'. 'IrLOLxhzfotF7vwO2j3ez2ap/TmW4AIM7DoN9+tu+vLk6Pdg9O'.
'6ufXjfXLm6pxPACSJIpRFAa+/26DhuK6qjbiON40k0N3skjOvm'. '6ufXjfXLm6pxPACSJIpRFAa+/26DhuK6qjbiON40k0N3skjOvm'.
'NijBmchF5mi+1jhQqDmWyIzPp1hUlrv8On5l+6mMm1tigFNyrt'. 'NijBmchF5mi+1jhQqDmWyIzPp1hUlrv8On5l+6mMm1tigFNyrt'.
'5R97g+FKKyGKkTNKesXPJTZXOFIrUoKiypcTQVHjK4g8H2dWEQ'. '5R97g+FKKyGKkTNKesXPJTZXOFIrUoKiypcTQVHjK4g8H2dWEQ'.
'B8bvUDLSQXSr41rmEAAAAASUVORK5CYII=' ; 'B8bvUDLSQXSr41rmEAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: diam_yellow.png // File: diam_yellow.png
//========================================================== //==========================================================
$this->imgdata[3][0]= 262 ; $this->imgdata[3][0]= 262 ;
$this->imgdata[3][1]= $this->imgdata[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
'BMVEX///+AgIBmMwCZZgD/zADMmQD/QLMZAAAAAXRSTlMAQObY'. 'BMVEX///+AgIBmMwCZZgD/zADMmQD/QLMZAAAAAXRSTlMAQObY'.
'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
'AHdElNRQfTAwsWEwcv/zIDAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. 'AHdElNRQfTAwsWEwcv/zIDAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
'6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
'==' ; '==' ;
   
//========================================================== //==========================================================
// File: diam_lightblue.png // File: diam_lightblue.png
//========================================================== //==========================================================
$this->imgdata[4][0]= 671 ; $this->imgdata[4][0]= 671 ;
$this->imgdata[4][1]= $this->imgdata[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/1'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/1'.
'BMVEX///+AgIAAnP8A//8Azv8AY/8Aa/8I//8Y1v8Izv8Y//8Q'. 'BMVEX///+AgIAAnP8A//8Azv8AY/8Aa/8I//8Y1v8Izv8Y//8Q'.
'//8InP8Qzv8Ypf85jP8he/8Yc/8Ia/8pe/8p//8p1v9Ctf8xrf'. '//8InP8Qzv8Ypf85jP8he/8Yc/8Ia/8pe/8p//8p1v9Ctf8xrf'.
'8prf8QnP8Qc/9CjP+1//97//9r//9S//9K//9C//85//8x//8h'. '8prf8QnP8Qc/9CjP+1//97//9r//9S//9K//9C//85//8x//8h'.
'//9r5/9K3v9S3v851v97zv9Svf85rf8hpf/G3v9SnP9anP9KlP'. '//9r5/9K3v9S3v851v97zv9Svf85rf8hpf/G3v9SnP9anP9KlP'.
'8xhP/n7//v7+f3///n///O//+U//9z//9j//9a//975/9C3v8h'. '8xhP/n7//v7+f3///n///O//+U//9z//9j//9a//975/9C3v8h'.
'1v+E5/+17/9j3v/O7//n9/+95/+l3v9jxv+U1v8Qpf9avf9Ktf'. '1v+E5/+17/9j3v/O7//n9/+95/+l3v9jxv+U1v8Qpf9avf9Ktf'.
'+Uxv+11v97tf9rrf+cxv+Mvf9jpf+tzv+Etf/O3v/39/8Akkxr'. '+Uxv+11v97tf9rrf+cxv+Mvf9jpf+tzv+Etf/O3v/39/8Akkxr'.
'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
'IAAAsSAdLdfvwAAAAHdElNRQfTAwsWEiHk6Ya/AAABGUlEQVR4'. 'IAAAsSAdLdfvwAAAAHdElNRQfTAwsWEiHk6Ya/AAABGUlEQVR4'.
'nHXQ13KDMBAF0J2o0E01GHDvJa7p3em95/+/JQJMYjDc0Yt0Zr'. 'nHXQ13KDMBAF0J2o0E01GHDvJa7p3em95/+/JQJMYjDc0Yt0Zr'.
'VaAaxHgtxwbSGPkGQpOIeQ2ORxJiJmNWYZyAhZR0WcgQGhViU0'. 'VaAaxHgtxwbSGPkGQpOIeQ2ORxJiJmNWYZyAhZR0WcgQGhViU0'.
'nEGoedDHGxgRapRPcRpXhOr7XZzCmLjaXk9IIjvkOEmSRLG62+'. 'nEGoedDHGxgRapRPcRpXhOr7XZzCmLjaXk9IIjvkOEmSRLG62+'.
'F5XlEElhA5sW21GvXj6mGlDBfnJ51lr9svnvEKwH1hu2QPbwd3'. 'F5XlEElhA5sW21GvXj6mGlDBfnJ51lr9svnvEKwH1hu2QPbwd3'.
'N9eXVzuL7/Hn29frdKaamgcgy67L3HFG9gDefV+dm5qme4YRXL'. 'N9eXVzuL7/Hn29frdKaamgcgy67L3HFG9gDefV+dm5qme4YRXL'.
'oVR374mRqUELZYosf84XAxISFRQuMh4rrH8YxGSP6HX6H97NNQ'. 'oVR374mRqUELZYosf84XAxISFRQuMh4rrH8YxGSP6HX6H97NNQ'.
'KEAaR08qCeuSnx2a8zIPWqUowtKHSRK91rAw0elmVYQFVc8mhq'. 'KEAaR08qCeuSnx2a8zIPWqUowtKHSRK91rAw0elmVYQFVc8mhq'.
'7p5RD7Ps3IIwA9sfsFxFUX6eZ4Zh4AAAAASUVORK5CYII=' ; '7p5RD7Ps3IIwA9sfsFxFUX6eZ4Zh4AAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: diam_purple.png // File: diam_purple.png
//========================================================== //==========================================================
$this->imgdata[5][0]= 657 ; $this->imgdata[5][0]= 657 ;
$this->imgdata[5][1]= $this->imgdata[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'.
'BMVEX///////8xAP/OAP+cAP9jAP9rAP+cCP85CP/OEP9SKf/O'. 'BMVEX///////8xAP/OAP+cAP9jAP9rAP+cCP85CP/OEP9SKf/O'.
'CP9CEP9zGP9rCP+lGP/WOf/WIf9KIf9jOf+MQv+EMf97If9zEP'. 'CP9CEP9zGP9rCP+lGP/WOf/WIf9KIf9jOf+MQv+EMf97If9zEP'.
'+1Sv+lIf/ne//eUv/na//n5//Oxv/Wzv+chP9zUv97Wv9rQv9a'. '+1Sv+lIf/ne//eUv/na//n5//Oxv/Wzv+chP9zUv97Wv9rQv9a'.
'Mf9KGP/v5/+te/97Kf+9Y/+tOf+tKf+lEP/vtf/WMf/WKf/v7+'. 'Mf9KGP/v5/+te/97Kf+9Y/+tOf+tKf+lEP/vtf/WMf/WKf/v7+'.
'f39/+tnP+9rf9rSv9jQv9CGP+ljP+EY//Gtf+tlP+Ma/9zSv/e'. 'f39/+tnP+9rf9rSv9jQv9CGP+ljP+EY//Gtf+tlP+Ma/9zSv/e'.
'zv+UUv+9lP+cWv+lY/+cUv+MOf+EKf+UQv/Opf/OhP/Ga/+1Qv'. 'zv+UUv+9lP+cWv+lY/+cUv+MOf+EKf+UQv/Opf/OhP/Ga/+1Qv'.
'/Oe/+9Uv/ntf/eWv/eSv/WGP/3zv/vlP/WEP//9/+pL4oHAAAA'. '/Oe/+9Uv/ntf/eWv/eSv/WGP/3zv/vlP/WEP//9/+pL4oHAAAA'.
'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'. 'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'.
'sSAdLdfvwAAAAHdElNRQfTAwsWEjX+M1LCAAABDklEQVR4nHXQ'. 'sSAdLdfvwAAAAHdElNRQfTAwsWEjX+M1LCAAABDklEQVR4nHXQ'.
'1bLDIBAGYFqIEW+ksbr7cXd3ff93OUCamdOE/Mxw882yywLwPz'. '1bLDIBAGYFqIEW+ksbr7cXd3ff93OUCamdOE/Mxw882yywLwPz'.
'+gNKotlRFUVnNUQlCxTMRFCKEdE+MgpJaEiIOU4DKaoSIygtb3'. '+gNKotlRFUVnNUQlCxTMRFCKEdE+MgpJaEiIOU4DKaoSIygtb3'.
'FBUQrm3xjPK4JvXjK0A5hFniYSBtIilQVYUm+X0KTVNiYah+2q'. 'FBUQrm3xjPK4JvXjK0A5hFniYSBtIilQVYUm+X0KTVNiYah+2q'.
'ulFb8nUbSovD2+TCavwXQWmnMA6ro+di+uR5cPzfPhVqPV3N1p'. 'ulFb8nUbSovD2+TCavwXQWmnMA6ro+di+uR5cPzfPhVqPV3N1p'.
'n3b3+rimAWAYhP3xnXd7P6oc9vadPsa1wYEs00dFQRAFehlX21'. 'n3b3+rimAWAYhP3xnXd7P6oc9vadPsa1wYEs00dFQRAFehlX21'.
'25Sg9NOgwF5jeNTjVL9om0TjDc1lmeCKZ17nFPzhPtSRt6J06R'. '25Sg9NOgwF5jeNTjVL9om0TjDc1lmeCKZ17nFPzhPtSRt6J06R'.
'WKUoeG3MoXRa/wjLHGLodwZcotPqjsYngnWslRBZH91hWTbpD2'. 'WKUoeG3MoXRa/wjLHGLodwZcotPqjsYngnWslRBZH91hWTbpD2'.
'EdF1ECWW1SAAAAAElFTkSuQmCC' ; 'EdF1ECWW1SAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: diam_gray.png // File: diam_gray.png
//========================================================== //==========================================================
$this->imgdata[6][0]= 262 ; $this->imgdata[6][0]= 262 ;
$this->imgdata[6][1]= $this->imgdata[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
'BMVEX//////wAzMzNmZmbMzMyZmZlq4Qo5AAAAAXRSTlMAQObY'. 'BMVEX//////wAzMzNmZmbMzMyZmZlq4Qo5AAAAAXRSTlMAQObY'.
'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
'AHdElNRQfTAwsWExZFTxLxAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. 'AHdElNRQfTAwsWExZFTxLxAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
'6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
'==' ; '==' ;
   
//========================================================== //==========================================================
// File: diam_blgr.png // File: diam_blgr.png
//========================================================== //==========================================================
$this->imgdata[7][0]= 262 ; $this->imgdata[7][0]= 262 ;
$this->imgdata[7][1]= $this->imgdata[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'. 'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
'BMVEX///+AgIBmzP9m///M//+Z//8hMmBVAAAAAXRSTlMAQObY'. 'BMVEX///+AgIBmzP9m///M//+Z//8hMmBVAAAAAXRSTlMAQObY'.
'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'. 'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
'AHdElNRQfTAwsWEwCxm6egAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'. 'AHdElNRQfTAwsWEwCxm6egAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'. 'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
'6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'. '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'. 'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
'==' ; '==' ;
} }
} }
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: IMGDATA_PUSHPINS.INC // File: IMGDATA_PUSHPINS.INC
// Description: Base64 encoded images for pushpins // Description: Base64 encoded images for pushpins
// Created: 2003-03-20 // Created: 2003-03-20
// Ver: $Id: imgdata_pushpins.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: imgdata_pushpins.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class ImgData_PushPins extends ImgData { class ImgData_PushPins extends ImgData {
protected $name = 'Push pins'; protected $name = 'Push pins';
protected $an = array(MARK_IMG_PUSHPIN => 'imgdata_small', protected $an = array(MARK_IMG_PUSHPIN => 'imgdata_small',
MARK_IMG_SPUSHPIN => 'imgdata_small', MARK_IMG_SPUSHPIN => 'imgdata_small',
MARK_IMG_LPUSHPIN => 'imgdata_large'); MARK_IMG_LPUSHPIN => 'imgdata_large');
   
protected $colors = array('blue','green','orange','pink','red'); protected $colors = array('blue','green','orange','pink','red');
protected $index = array('red' => 0, 'orange' => 1, 'pink' => 2, 'blue' => 3, 'green' => 4 ) ; protected $index = array('red' => 0, 'orange' => 1, 'pink' => 2, 'blue' => 3, 'green' => 4 ) ;
protected $maxidx = 4 ; protected $maxidx = 4 ;
protected $imgdata_large, $imgdata_small ; protected $imgdata_large, $imgdata_small ;
   
function __construct() { function __construct() {
   
// The anchor should be where the needle "hits" the paper // The anchor should be where the needle "hits" the paper
// (bottom left corner) // (bottom left corner)
$this->anchor_x = 0; $this->anchor_x = 0;
$this->anchor_y = 1; $this->anchor_y = 1;
   
//========================================================== //==========================================================
// File: ppl_red.png // File: ppl_red.png
//========================================================== //==========================================================
$this->imgdata_large[0][0]= 2490 ; $this->imgdata_large[0][0]= 2490 ;
$this->imgdata_large[0][1]= $this->imgdata_large[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMKBh4Ryh89CgAACUdJREFUeJy9mNtTFFcexz+/7p'. 'B3RJTUUH0wMKBh4Ryh89CgAACUdJREFUeJy9mNtTFFcexz+/7p'.
'4Lw1wZJKDGCAwmDAqUySamcCq1ed6k9mn3UfMP7F+1T3nYqn2J'. '4Lw1wZJKDGCAwmDAqUySamcCq1ed6k9mn3UfMP7F+1T3nYqn2J'.
'lZdoDEjpbq0KG8EBFBFBEJye6Zmenkv32Ydu5GYiUMmeqq6uqT'. 'lZdoDEjpbq0KG8EBFBFBEJye6Zmenkv32Ydu5GYiUMmeqq6uqT'.
'6Xz3zP73aOcIKmAQkIFyD3N/jrBPwlKjLQEglVlJKyUjR3u7cc'. '6Xz3zP73aOcIKmAQkIFyD3N/jrBPwlKjLQEglVlJKyUjR3u7cc'.
'WLoP3/4dvv03LNrQ8I6x1rFbDML9kOmHvh7IRHU9JKmUSG8vpF'. 'WLoP3/4dvv03LNrQ8I6x1rFbDML9kOmHvh7IRHU9JKmUSG8vpF'.
'IoXX/TV0AiEM5A5jT0noFMFMJHXUt/d5f9TUAbhtQ3cPFruDog'. 'IoXX/TV0AiEM5A5jT0noFMFMJHXUt/d5f9TUAbhtQ3cPFruDog'.
'8klHMnmO0dGYe/myOJGINEwTz3F2higFXgy8PpAkOC+h8hoaCt'. '8klHMnmO0dGYe/myOJGINEwTz3F2higFXgy8PpAkOC+h8hoaCt'.
'4ppHFcQAWSgOQlyI/p+lUjmRxWAwNJd3xca/f34yoFi4tgmjtD'. '4ppHFcQAWSgOQlyI/p+lUjmRxWAwNJd3xca/f34yoFi4tgmjtD'.
'NIFkJ4xcgBCgVqEBFJ9DqcZea/gNAAVEg7AOGYnHe9XoaJd3+X'. 'NIFkJ4xcgBCgVqEBFJ9DqcZea/gNAAVEg7AOGYnHe9XoaJd3+X'.
'LISSSwnz6lsbKCZ9sHh4UVdBkwdA6cPwNnIfJPmC3Ctgft3wwQ'. 'LISSSwnz6lsbKCZ9sHh4UVdBkwdA6cPwNnIfJPmC3Ctgft3wwQ'.
'QPkvTZJJnbExzfvsM2nMzVG7e5fG48d4lnXwTwEYCjJxuHQBog'. 'QPkvTZJJnbExzfvsM2nMzVG7e5fG48d4lnXwTwEYCjJxuHQBog'.
'BHUfKkgAIIhiGk06hTp/Dm5qS1uYlXLvtWd4gPgIiCrAEcVckT'. 'BHUfKkgAIIhiGk06hTp/Dm5qS1uYlXLvtWd4gPgIiCrAEcVckT'.
'Ab5p7TaYJrK1hQaEenrwSiVfQdc91P0kSp7Ii89D5ksY/kAkLy'. 'Ab5p7TaYJrK1hQaEenrwSiVfQdc91P0kSp7Ii89D5ksY/kAkLy'.
'IZXFdXkQjS1YUSEbdcRu168V6+HTUNIKJDRwdE+sBIQmP9Ld59'. 'IZXFdXkQjS1YUSEbdcRu168V6+HTUNIKJDRwdE+sBIQmP9Ld59'.
'bEBA3of4F/D+uXb7rGaaCSmXI3pPj64PDaHCYfEqFVSjgWo2D2'. 'bEBA3of4F/D+uXb7rGaaCSmXI3pPj64PDaHCYfEqFVSjgWo2D2'.
'73XlJNQTgCyQykIuBWoNKEeh1aLXBPBCggGdBOgxZVSjoajVhH'. '73XlJNQTgCyQykIuBWoNKEeh1aLXBPBCggGdBOgxZVSjoajVhH'.
'o5HWlIpq4bCQSgm9vXhK4ZZKh5SUYygp4J1EQVUD9xlU18BJQD'. 'o5HWlIpq4bCQSgm9vXhK4ZZKh5SUYygp4J1EQVUD9xlU18BJQD'.
'bUbJ5T5XJStyxN9fSI099P3baxV1dRloW2h2ivx/yakg2ot6F1'. 'bUbJ5T5XJStyxN9fSI099P3baxV1dRloW2h2ivx/yakg2ot6F1'.
'EkCa4G1D+zVEq5ArKTWM42Q6HUczQV7U66w9e0ZpdRXlOIQ5vF'. 'EkCa4G1D+zVEq5ArKTWM42Q6HUczQV7U66w9e0ZpdRXlOIQ5vF'.
'VHUXILKify4jiEzkOqC3peQMoBQymFlMt4Dx6wUSxSsm2UZXEK'. 'VHUXILKify4jiEzkOqC3peQMoBQymFlMt4Dx6wUSxSsm2UZXEK'.
'P30QvOUt8/2Sd78CdWwFDTA+gsw3cOlPcPUD+CQB52oQ21RKXM'. 'P30QvOUt8/2Sd78CdWwFDTA+gsw3cOlPcPUD+CQB52oQ21RKXM'.
'eRhGXhOg7VoKrx8KuS4ygZhVg3ZI8FGIfwR9BVgAtfwxdXdP3L'. 'eRhGXhOg7VoKrx8KuS4ygZhVg3ZI8FGIfwR9BVgAtfwxdXdP3L'.
'86nUR91dXelNXTeWWy10paQHX602YAP1ADASAL7LJvFtMpOCc0'. '86nUR91dXelNXTeWWy10paQHX602YAP1ADASAL7LJvFtMpOCc0'.
'cG3FHuGlz6Gr4YEpnoTCbzsdHRbOzy5RCRiLRMk5rjyOtAimwA'. 'cG3FHuGlz6Gr4YEpnoTCbzsdHRbOzy5RCRiLRMk5rjyOtAimwA'.
'U4U3SurBN/0wnAASBCVDIKpB4kiAB5Ub0/UvO9LpPAMDGfn005'. 'U4U3SurBN/0wnAASBCVDIKpB4kiAB5Ub0/UvO9LpPAMDGfn005'.
'AxPCzxep3Q6iqPLUseBoufCZRsAE6g5g5kKIDfKUj3wnpAG8QB'. 'AxPCzxep3Q6iqPLUseBoufCZRsAE6g5g5kKIDfKUj3wnpAG8QB'.
'/Z1OIqANQuI65AtwNScyYXR2XlAXL2YZHzcklRKWl5GVFXFtGx'. '/Z1OIqANQuI65AtwNScyYXR2XlAXL2YZHzcklRKWl5GVFXFtGx'.
'MoAiV/EQaAGH6BUQNWgQpwFngv+Ca8KUAQEBcwgTJHyMV7679R'. 'MoAiV/EQaAGH6BUQNWgQpwFngv+Ca8KUAQEBcwgTJHyMV7679R'.
'XS8YqdSI6u/PMD5ukMtJY3GR2uQkr5aXeWVZOEALmA8WsIAxfL'. 'XS8YqdSI6u/PMD5ukMtJY3GR2uQkr5aXeWVZOEALmA8WsIAxfL'.
'd0goVLAdCOd+/YpgqeVtBv4yiA++q/RKKXixe7GB8PSyoljcVF'. 'd0goVLAdCOd+/YpgqeVtBv4yiA++q/RKKXixe7GB8PSyoljcVF'.
'yg8fyubyMpulEk2lyAIfAAvAC+B+oOQFoAt/+0rAejB/EzjNri'. 'yg8fyubyMpulEk2lyAIfAAvAC+B+oOQFoAt/+0rAejB/EzjNri'.
'vvqNnCd64jxcE39V8spnP+vMbAgDSePKE2NcXm06dslMuUlcID'. 'vvqNnCd64jxcE39V8spnP+vMbAgDSePKE2NcXm06dslMuUlcID'.
'TuFvqwXMBU8N39bGgRR+ki0Dz4L5DSAe9NGD7zq+6kcN1L6H2b'. 'TuFvqwXMBU8N39bGgRR+ki0Dz4L5DSAe9NGD7zq+6kcN1L6H2b'.
'ao5WWaQHllRTafPmWrVMJUimoAQrBYJFjQwre7B6A8YAi8LCgD'. 'ao5WWaQHllRTafPmWrVMJUimoAQrBYJFjQwre7B6A8YAi8LCgD'.
'5DVo6/hbb/iHK1KggvFeD3hHziQKEMuiNTNDbXGRTdtmw7Iwla'. '5DVo6/hbb/iHK1KggvFeD3hHziQKEMuiNTNDbXGRTdtmw7Iwla'.
'KGH0oqwbscLOoG46rAY6AOzRhY74PT6QuUKEN4PegXxd/yEDTT'. 'KGH0oqwbscLOoG46rAY6AOzRhY74PT6QuUKEN4PegXxd/yEDTT'.
'YMWOk+oEaLkuFdNk0zTZwjfkavDUArXWgGXgFb4dEShXhfYqlI'. 'YMWOk+oEaLkuFdNk0zTZwjfkavDUArXWgGXgFb4dEShXhfYqlI'.
'ow3w9rg3B6ED60IOOA5oEYQBrcpG+mj9bg0VG8GMJhVDZLyzAo'. 'ow3w9rg3B6ED60IOOA5oEYQBrcpG+mj9bg0VG8GMJhVDZLyzAo'.
'VSq8rFYxXXefcjVgG9+uisDrXUCApoKSBcUHMBmHhfcgNwhtD3'. 'VSq8rFYxXXefcjVgG9+uisDrXUCApoKSBcUHMBmHhfcgNwhtD3'.
'q9IG6Lr15b4OUTmPwBJt8JqGuapp05o0mhoHnptLQfPsR+8IBK'. 'q9IG6Lr15b4OUTmPwBJt8JqGuapp05o0mhoHnptLQfPsR+8IBK'.
'uYyNH3yr+B77LHheA3tK1Ta+IrMeTL2C6Xl48TOsNWDDgAz7s5'. 'uYyNH3yr+B77LHheA3tK1Ta+IrMeTL2C6Xl48TOsNWDDgAz7s5'.
'/r+krP/eddCsbj8fDQ4GBm9MqVvvRXX2VULBayRGRzaYn1SoWa'. '/r+krP/eddCsbj8fDQ4GBm9MqVvvRXX2VULBayRGRzaYn1SoWa'.
'UjgB4PIB5QK4ZgBXBKaAHxQsrED1H7CRgCUPwgHZDqACmhWwXv'. 'UjgB4PIB5QK4ZgBXBKaAHxQsrED1H7CRgCUPwgHZDqACmhWwXv'.
'2aDRqGYeRyufS169cvThQKV88PDuYbW1vJ5VRK+5euqxWlPMdX'. '2aDRqGYeRyufS169cvThQKV88PDuYbW1vJ5VRK+5euqxWlPMdX'.
'SRqgreHbZGN3ijfKBXBTAeh2Fdwi2MofshP/dvKwCmKhp4m83Y'. 'SRqgreHbZGN3ijfKBXBTAeh2Fdwi2MofshP/dvKwCmKhp4m83Y'.
'vj8Xg4l8tlCoXC0MTExMTFkZE/1m37wvLGRvKRacoD1209E7Fc'. 'vj8Xg4l8tlCoXC0MTExMTFkZE/1m37wvLGRvKRacoD1209E7Fc'.
'pZwYREOQqEJ4z3HskHLsz4AoXykPIBSN0t3dTTQafROoHdumXC'. 'pZwYREOQqEJ4z3HskHLsz4AoXykPIBSN0t3dTTQafROoHdumXC'.
'4fjoMiog0ODiauX7+eLxQKV3O53ETdti88nJnJ3rl505ifmWm3'. '4fjoMiog0ODiauX7+eLxQKV3O53ETdti88nJnJ3rl505ifmWm3'.
'arWSodR8GNbycDoNHy5C5jFold1k8d+DyvELNwg93d18/vnn9P'. 'arWSodR8GNbycDoNHy5C5jFold1k8d+DyvELNwg93d18/vnn9P'.
'X1oes6nufx/Plz7t+/fxhQKSWJRCI5NjaWHxkZKdj1+sjSwkJm'. 'X1oes6nufx/Plz7t+/fxhQKSWJRCI5NjaWHxkZKdj1+sjSwkJm'.
'+uZN/dZ337VqCwullGUVdZjsgIUC5LqhrUPvCugWuApeApPAzY'. '+uZN/dZ337VqCwullGUVdZjsgIUC5LqhrUPvCugWuApeApPAzY'.
'PKHWyaphGNRunt7WVwcBARwfM8Ojo6sCzrMKBhGLphGFEF2Wq1'. 'PKHWyaphGNRunt7WVwcBARwfM8Ojo6sCzrMKBhGLphGFEF2Wq1'.
'2jc7M5OZ/vHH0MPbt93awkJJmeZsC6ZaMK3DCwvWdNioQUb5B6'. '2jc7M5OZ/vHH0MPbt93awkJJmeZsC6ZaMK3DCwvWdNioQUb5B6'.
'AdBR+9SzkAz/NwHIeXL18iIui6TjgcJplMMjY2th8wHo+Hh4aG'. 'AdBR+9SzkAz/NwHIeXL18iIui6TjgcJplMMjY2th8wHo+Hh4aG'.
'MsPDw6fddru7+Phxx51bt/RbN260qwsLpZhlFZsw9QJ+2Pbrga'. 'MsPDw6fddru7+Phxx51bt/RbN260qwsLpZhlFZsw9QJ+2Pbrga'.
'oJG2FY2oKwuTtVEz9uV34NbqdtbW0xPT1NNBoF4MyZM1y5coWu'. 'oJG2FY2oKwuTtVEz9uV34NbqdtbW0xPT1NNBoF4MyZM1y5coWu'.
'rq5dQBHRcrlc4tq1a/l8Pj9RMs38ndu3Ez//9JNXLRZNyuXZJk'. 'rq5dQBHRcrlc4tq1a/l8Pj9RMs38ndu3Ez//9JNXLRZNyuXZJk'.
'xVYKoExQpsK/+IaAuYb7no8zjC/R+A4zisrq7u+53NZjl16tQ+'. 'xVYKoExQpsK/+IaAuYb7no8zjC/R+A4zisrq7u+53NZjl16tQ+'.
'QIlEIslsNpuPRCJXZ2dnh2/duNFRW1oy07a96MKd575yxRqU1B'. 'QIlEIslsNpuPRCJXZ2dnh2/duNFRW1oy07a96MKd575yxRqU1B'.
'5vPMpF5HHa1tYW9+7do7Ozc/eQpZTSQ6FQt1Lq8pMnT/5w7969'. '5vPMpF5HHa1tYW9+7do7Ozc/eQpZTSQ6FQt1Lq8pMnT/5w7969'.
'nuLcXE1rNufO9fRMhlKpOyvt9qPtVmvb25fFfvvWbrepVCqHwo'. 'nuLcXE1rNufO9fRMhlKpOyvt9qPtVmvb25fFfvvWbrepVCqHwo'.
'xaX19vff/996ZhGC8qlkW9Wt1Onz073fXxxz+6MB+9e9dUjuO+'. 'xaX19vff/996ZhGC8qlkW9Wt1Onz073fXxxz+6MB+9e9dUjuO+'.
'7ebq9wLdB9hoNCrr6+s/4wf3FCJW3fPmTZhXsNWCprjuW66Dfr'. '7ebq9wLdB9hoNCrr6+s/4wf3FCJW3fPmTZhXsNWCprjuW66Dfr'.
'928KAfBhJAEgiJSLuzs7OSTqctoFkqlZRt26j/I+L/AGjPTN4d'. '928KAfBhJAEgiJSLuzs7OSTqctoFkqlZRt26j/I+L/AGjPTN4d'.
'Nqn4AAAAAElFTkSuQmCC' ; 'Nqn4AAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: ppl_orange.png // File: ppl_orange.png
//========================================================== //==========================================================
$this->imgdata_large[1][0]= 2753 ; $this->imgdata_large[1][0]= 2753 ;
$this->imgdata_large[1][1]= $this->imgdata_large[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMLFQ0VCkHCzQAACk5JREFUeJytmGtzG0d2hp8zNw'. 'B3RJTUUH0wMLFQ0VCkHCzQAACk5JREFUeJytmGtzG0d2hp8zNw'.
'AEcRdJ6EJK9FL0CqZUm9jWbkwq3vhDstl8dmLvz8rP2H8Q75ZT'. 'AEcRdJ6EJK9FL0CqZUm9jWbkwq3vhDstl8dmLvz8rP2H8Q75ZT'.
'pkRfpLgqsS6WIFEKGYkiSBCDO+banQ8DUpRWEkklXQUUqlCDfv'. 'pkRfpLgqsS6WIFEKGYkiSBCDO+banQ8DUpRWEkklXQUUqlCDfv'.
'rp857pgfAOQ4AMOJdg4R/hX96Hf06bvDc5iT07i8yeg8ksiIAI'. 'rp857pgfAOQ4AMOJdg4R/hX96Hf06bvDc5iT07i8yeg8ksiIAI'.
'4TBi/ds9/vivD/njapNHvRBfHXMu410AM+BUoVSF05NQsi1sO4'. '4TBi/ds9/vivD/njapNHvRBfHXMu410AM+BUoVSF05NQsi1sO4'.
'8402AXwLQTuP31OAZO2aG0MEn14iSlnI1z3LnMk8IZYJyBwjIs'. '8402AXwLQTuP31OAZO2aG0MEn14iSlnI1z3LnMk8IZYJyBwjIs'.
'/TWsVIWPJkvMFS4zMfMhUp5BsoCpAAEBLYKaMFGn00jBxnvu02'. '/TWsVIWPJkvMFS4zMfMhUp5BsoCpAAEBLYKaMFGn00jBxnvu02'.
'35+JHmSJEnBpQEcPo38MmCxd/nS9Ry71Ga/g1W9a8gn0GsHkgA'. '35+JHmSJEnBpQEcPo38MmCxd/nS9Ry71Ga/g1W9a8gn0GsHkgA'.
'6DGjxkqb5CoO+YxF3A3p+jGjQUzoK+L/V0ADzFMwtSR8eLbAr8'. '6DGjxkqb5CoO+YxF3A3p+jGjQUzoK+L/V0ADzFMwtSR8eLbAr8'.
'uXOTf9NzhTc0geSLUQcYHgYEH786RMg0zWJHV2Aitv4x/HpHVS'. 'uXOTf9NzhTc0geSLUQcYHgYEH786RMg0zWJHV2Aitv4x/HpHVS'.
'QA2YBqTTGIUq5qkPMWaWkVwPnPtAA/BevmZcjxaaUtHh8pJJGu'. 'QA2YBqTTGIUq5qkPMWaWkVwPnPtAA/BevmZcjxaaUtHh8pJJGu'.
'DpCB9FvT7A7YT7S3p5vFMNzmWo/O0MSx/Ms3TqI8r59zFTfUQe'. 'DpCB9FvT7A7YT7S3p5vFMNzmWo/O0MSx/Ms3TqI8r59zFTfUQe'.
'I7SBODE3tnfoIxYnNHligwik0zAzDdVpyKbA8sff5YAeMEwgkV'. 'I7SBODE3tnfoIxYnNHligwik0zAzDdVpyKbA8sff5YAeMEwgkV'.
'cufQeTJzZoCsaFLKXPTnNpoUTNsSgJmNoGsuNQjIDwYD2HlnZy'. 'cufQeTJzZoCsaFLKXPTnNpoUTNsSgJmNoGsuNQjIDwYD2HlnZy'.
'k++yxTKXZfKTU8zOpjhneeQYkorSmGERtIlICBKRbLX+y98YN3'. 'k++yxTKXZfKTU8zOpjhneeQYkorSmGERtIlICBKRbLX+y98YN3'.
'ADcNIm+bJD4U3pPnmbEaRgYVRTGBkDSSsmxKfY7ZLuDJA4hdjl'. 'ADcNIm+bJD4U3pPnmbEaRgYVRTGBkDSSsmxKfY7ZLuDJA4hdjl'.
'JEgyBB2SJOvQ9RzTpNKoEwNq0CNFvOXR3/HxMgYVPObaz8kPmh'. 'JEgyBB2SJOvQ9RzTpNKoEwNq0CNFvOXR3/HxMgYVPObaz8kPmh'.
'hkEWMatAfRONGGvLizyOE9P8KkpwhPDAgQKJQbELUD0oOIhbbH'. 'hkEWMatAfRONGGvLizyOE9P8KkpwhPDAgQKJQbELUD0oOIhbbH'.
'JeVTmowxjAgZutB5AoOngA+2DdYrcTyOyYZP9+QpBvI29vwEhb'. 'JeVTmowxjAgZutB5AoOngA+2DdYrcTyOyYZP9+QpBvI29vwEhb'.
'It042BVQgDy9KTMfkwQG1A9ACCLlgBBGUwxxoc52WDh2ATyEPp'. 'It042BVQgDy9KTMfkwQG1A9ACCLlgBBGUwxxoc52WDh2ATyEPp'.
'1hoaPvrEBh0Dq5an9OUsl/9hylk5b5c+mowLc4E2Jtw4Eoljyf'. '1hoaPvrEBh0Dq5an9OUsl/9hylk5b5c+mowLc4E2Jtw4Eoljyf'.
'ogA/AGEAagNRjGyUxOmEycyVA5EWDBxrmUp3ytLIv/NJP69Goh'. 'ogA/AGEAagNRjGyUxOmEycyVA5EWDBxrmUp3ytLIv/NJP69Goh'.
'+9mFydIvS5PZYkvH1oY/RFtKymlwBFQAgQd+kAA6qSQ8pvn2mp'. '+9mFydIvS5PZYkvH1oY/RFtKymlwBFQAgQd+kAA6qSQ8pvn2mp'.
'SkJkuVFHPHBnQMrEt5Sl+e4/Lvp51PF1PF5Xy6WMvOWZXMom8z'. 'SkJkuVFHPHBnQMrEt5Sl+e4/Lvp51PF1PF5Xy6WMvOWZXMom8z'.
'OZTQ8+j5sbQiMEwopsCIwRtBGIJSCdzbTGo9NimkDcgdC7Bg49'. 'OZTQ8+j5sbQiMEwopsCIwRtBGIJSCdzbTGo9NimkDcgdC7Bg49'.
'TG5n4/nfr0Si77WdYp1YzyZEkWPdteaEnB7pPqBTxuIf/VgciE'. 'TG5n4/nfr0Si77WdYp1YzyZEkWPdteaEnB7pPqBTxuIf/VgciE'.
'SgasCPwh+GNIkaNNag1RiPge5pEhMQVjfoLcF+eoXSvbKxedwn'. 'SgasCPwh+GNIkaNNag1RiPge5pEhMQVjfoLcF+eoXSvbKxedwn'.
'LKzC3KWbOi5/sW5a44/SHFUSgVA7SCzRG0AvA9mPOgFIETgu4n'. 'LKzC3KWbOi5/sW5a44/SHFUSgVA7SCzRG0AvA9mPOgFIETgu4n'.
'Ww0wNQWFAqRSL6D2ZQYBdDrQ7R7jXiwgRcvIL02makuTmWtpM/'. 'Ww0wNQWFAqRSL6D2ZQYBdDrQ7R7jXiwgRcvIL02makuTmWtpM/'.
'+BlLMl5vuWzLVEuwH6oYnR1KS8kJINGXMM2YdfRlALoQoQQKeb'. '+BlLMl5vuWzLVEuwH6oYnR1KS8kJINGXMM2YdfRlALoQoQQKeb'.
'bDVwoMdxQMaLCwLo96HZTF5HbrEhmOftianfZisfzueKv7ZmrX'. 'bDVwoMdxQMaLCwLo96HZTF5HbrEhmOftianfZisfzueKv7ZmrX'.
'MsjhxKXZGBjzyeEHmSE3oWiggtyVGmE8DTIXTC5NxgAxOAGUM8'. 'MsjhxKXZGBjzyeEHmSE3oWiggtyVGmE8DTIXTC5NxgAxOAGUM8'.
'fun9mnSSLQ/CxNzOTgJ3LIMgoGwkKBiiMyaVviHVkdCO4FEKNv'. 'fun9mnSSLQ/CxNzOTgJ3LIMgoGwkKBiiMyaVviHVkdCO4FEKNv'.
'LQzWBYHfITPa4UBVM0LR/WB7ARJsdDDTjA6deYFIFUOimJ3d0E'. 'LQzWBYHfITPa4UBVM0LR/WB7ARJsdDDTjA6deYFIFUOimJ3d0E'.
'sNdLavYYgBpthqKcjiiJRO8K6CK0CsJTjfQAGaJtD9vQFAxNNQ'. 'sNdLavYYgBpthqKcjiiJRO8K6CK0CsJTjfQAGaJtD9vQFAxNNQ'.
'1FB0yBAfA8gdMAIagLoCVAen0M00zMOTYShNDtoHs9CAIUoI4E'. '1FB0yBAfA8gdMAIagLoCVAen0M00zMOTYShNDtoHs9CAIUoI4E'.
'1IBihCdNhsMhsj6NuV7BCC2IBpBqQaaFOENCCeiEsO1BO4RQgy'. '1IBihCdNhsMhsj6NuV7BCC2IBpBqQaaFOENCCeiEsO1BO4RQgy'.
'I5Hm4k4oIU9MrgZSAdBeTabZz+ODxKQRRBFBJo6IUc51anYRQo'. 'I5Hm4k4oIU9MrgZSAdBeTabZz+ODxKQRRBFBJo6IUc51anYRQo'.
'dto+24FNxYCiaWKkQsj00KkO4gxRRkAngJ868M0u3OkkM+hxQA'. 'dto+24FNxYCiaWKkQsj00KkO4gxRRkAngJ868M0u3OkkM+hxQA'.
'cQ7YD7GO5XYSsPZybh/TCkFIYY+kWniTW4Q7jXgHvHMhiRpmuW'. 'cQ7YD7GO5XYSsPZybh/TCkFIYY+kWniTW4Q7jXgHvHMhiRpmuW'.
'ca08GZkkZ/nY6TZMNhCnf2CuPoDVJvxpB+q9BHA8Ag1uH+oP4c'. 'ca08GZkkZ/nY6TZMNhCnf2CuPoDVJvxpB+q9BHA8Ag1uH+oP4c'.
'YEPCzDwmzSLquShHW/E0YRbG/BjZtw40hAy7aNzJlzRn75E6N0'. 'YEPCzDwmzSLquShHW/E0YRbG/BjZtw40hAy7aNzJlzRn75E6N0'.
'qiwTzafI7kOU3gWrhzZC2iHcbsPqLlxvJnCt4KC1RYAL3I5hzY'. 'qiwTzafI7kOU3gWrhzZC2iHcbsPqLlxvJnCt4KC1RYAL3I5hzY'.
'Xv/huePYCtITQMKEnyB4KQvMURuJvw889HGSwUCs7CwkLpo6tX'. 'Xv/huePYCtITQMKEnyB4KQvMURuJvw889HGSwUCs7CwkLpo6tX'.
'Ty/+7nel6VLGDn/8N9m+eZuo1UP8iNhLau6b3RfmOsHBGTUYw9'. 'Ty/+7nel6VLGDn/8N9m+eZuo1UP8iNhLau6b3RfmOsHBGTUYw9'.
'WBNeDrGB4+h/4qNLKwTnLbHj9CJw/6GoIh9Jpvq0HHcayFhYXi'. 'WBNeDrGB4+h/4qNLKwTnLbHj9CJw/6GoIh9Jpvq0HHcayFhYXi'.
'l3/4w9LK8vLKexfma3G/mb/3n1njTivS7tNQaaU1grQDjJ868D'. 'l3/4w9LK8vLKexfma3G/mb/3n1njTivS7tNQaaU1grQDjJ868D'.
'Axx6vmxnBrY9C9IcSbSXbavNjb/S3eN6/0m1JcKBScixcvllZW'. 'Axx6vmxnBrY9C9IcSbSXbavNjb/S3eN6/0m1JcKBScixcvllZW'.
'Vi6uLC8v12q1v/M8b/HxVjP//YYr32yE4dYWvShO0ogi14xwxq'. 'Vi6uLC8v12q1v/M8b/HxVjP//YYr32yE4dYWvShO0ogi14xwxq'.
'F4rbnxZ3cMjtpvEEeMvwA0TdOYn5/PffHFF7Vr166tvPeLXyx7'. 'F4rbnxZ3cMjtpvEEeMvwA0TdOYn5/PffHFF7Vr166tvPeLXyx7'.
'nrd4+/btyg/frFo//Xgncnd67qCn78earQqcmYD3fSi1wPCTSV'. 'nrd4+/btyg/frFo//Xgncnd67qCn78earQqcmYD3fSi1wPCTSV'.
'3gzqvm9uFOMl5nUAqFQn5paal26dKla57vf7D+6FHph9VV88af'. '3gzqvm9uFOMl5nUAqFQn5paal26dKla57vf7D+6FHph9VV88af'.
'vgq79bo70e3VT2l9A3hYg4UiRALVHTCHSZvYBm4A//6quf8zoG'. 'vgq79bo70e3VT2l9A3hYg4UiRALVHTCHSZvYBm4A//6quf8zoG'.
'3bpuM4acMwKr1+//SDe/dK31+/bv90/Xrcq9fduNW6rbVeC+E7'. '3bpuM4acMwKr1+//SDe/dK31+/bv90/Xrcq9fduNW6rbVeC+E7'.
'gWdD2DKg4UEpBmPcm10RuScida31ntb62HAigoigDw6Gh0axWH'. 'gWdD2DKg4UEpBmPcm10RuScida31ntb62HAigoigDw6Gh0axWH'.
'QWFhZKi4uLZ+I4PrVer2e+u37dXPvqq6hbr7tOp1NXWq89h6/b'. 'QWFhZKi4uLZ+I4PrVer2e+u37dXPvqq6hbr7tOp1NXWq89h6/b'.
'8FBB34WGBesdcPrj38lkMkGlUuml0+mu53nR3t4eo9HoSLhMJk'. '8FBB34WGBesdcPrj38lkMkGlUuml0+mu53nR3t4eo9HoSLhMJk'.
'OlUiGdTuN5Hq7rvgA0TdO4cOFC7vPPP6/VarXldqdTu7m2lrv7'. 'OlUiGdTuN5Hq7rvgA0TdO4cOFC7vPPP6/VarXldqdTu7m2lrv7'.
'7beq++BBO263b/tKrfWSXlbvwJ6CuAtDgTYiaBFMw6BSqfDxxx'. '7beq++BBO263b/tKrfWSXlbvwJ6CuAtDgTYiaBFMw6BSqfDxxx'.
'+rarWqGo0GN2/eZGtrC6XenAkRoVKpcPXqVWZmZmg0Gty6desF'. '+rarWqGo0GN2/eZGtrC6XenAkRoVKpcPXqVWZmZmg0Gty6desF'.
'oIhIOp3Ol8vlmmVZK3fv3Lm09uc/Zwbr653ccPgoNIzvnmn99Z'. 'oIhIOp3Ol8vlmmVZK3fv3Lm09uc/Zwbr653ccPgoNIzvnmn99Z'.
'7W9QG46lAaM5mM2l95GIYUi0VOnz7N7OwsWmsymQzyuse5Q8Mw'. '7W9QG46lAaM5mM2l95GIYUi0VOnz7N7OwsWmsymQzyuse5Q8Mw'.
'DNLpNDMzM5w/f/7A6AGgUkoajYa9urpayOXzUz/fvZutr68Pim'. 'DNLpNDMzM5w/f/7A6AGgUkoajYa9urpayOXzUz/fvZutr68Pim'.
'F4/2y1+n2o9Q/ru7uPesPhXnyo4A+vfHp6mmazybNnz9jZ2UFr'. 'F4/2y1+n2o9Q/ru7uPesPhXnyo4A+vfHp6mmazybNnz9jZ2UFr'.
'TbPZJAhe+8/aS0Mphed5NBoNABqNBqPR6MWBVWstvu/nnj9/Pv'. 'TbPZJAhe+8/aS0Mphed5NBoNABqNBqPR6MWBVWstvu/nnj9/Pv'.
'vo0aPq5uZmPBgM/qcwPf39xV/9ajU1M3Nvq9PZaw8GoT50PjdN'. 'vo0aPq5uZmPBgM/qcwPf39xV/9ajU1M3Nvq9PZaw8GoT50PjdN'.
'k6mpKa5cucL58+eJ45j19XWePHnCzs4OnudhmiaWZRGGIVH05r'. 'k6mpKa5cucL58+eJ45j19XWePHnCzs4OnudhmiaWZRGGIVH05r'.
'yEYYjrumxubrKxsfFyDQJ6NBp1Pc+7C4jWumBaVm+kVL2l1H2l'. 'yEYYjrumxubrKxsfFyDQJ6NBp1Pc+7C4jWumBaVm+kVL2l1H2l'.
'1G6otS+H6V6z8u3tbVzXpdFooJRicXGRqakptre3uXXr1ltrcT'. '1G6otS+H6V6z8u3tbVzXpdFooJRicXGRqakptre3uXXr1ltrcT'.
'Qa8ezZszemWAE9rfUdYBOwtVLRbrPZ+48ff+wDvuu6Sr3MB4Dr'. 'Qa8ezZszemWAE9rfUdYBOwtVLRbrPZ+48ff+wDvuu6Sr3MB4Dr'.
'uty6desgfa1WC3iRyrNnz4pSSmezWUzTfGtYtNYcdvC/9sMlgP'. 'uty6desgfa1WC3iRyrNnz4pSSmezWUzTfGtYtNYcdvC/9sMlgP'.
'n5N4cAAAAASUVORK5CYII=' ; 'n5N4cAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// File: ppl_pink.png // File: ppl_pink.png
//========================================================== //==========================================================
$this->imgdata_large[2][0]= 2779 ; $this->imgdata_large[2][0]= 2779 ;
$this->imgdata_large[2][1]= $this->imgdata_large[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMLFQolY9lkpgAACmhJREFUeJy9mOtzFNl5h5+3b9'. 'B3RJTUUH0wMLFQolY9lkpgAACmhJREFUeJy9mOtzFNl5h5+3b9'.
'Mz0kzPBWmEVtIiWYhIiC0HCDhB8lb8ISk7nzdZ5+/zJ/8BTmpT'. 'Mz0kzPBWmEVtIiWYhIiC0HCDhB8lb8ISk7nzdZ5+/zJ/8BTmpT'.
'660CZLwG1pVFgBkgGIHECEaa+/T9nHzQCCQuRpCNz6mp6g893U'. '660CZLwG1pVFgBkgGIHECEaa+/T9nHzQCCQuRpCNz6mp6g893U'.
'8/c37ve3qEjxiC4OA4n/Lp/EUu/tsMM/+aEWduVBx7WhdkShcY'. '8/c37ve3qEjxiC4OA4n/Lp/EUu/tsMM/+aEWduVBx7WhdkShcY'.
'xUH2zo0Dwod/5N6vf8V//PoGdx8M8EOFPtK9jI8BdHCcMuVSmf'. 'xUH2zo0Dwod/5N6vf8V//PoGdx8M8EOFPtK9jI8BdHCcMuVSmf'.
'LxHLmSZdm2U8xIbmKETDGDZZnIy4dBbCynyGhphurEDBOlHFnn'. 'LxHLmSZdm2U8xIbmKETDGDZZnIy4dBbCynyGhphurEDBOlHFnn'.
'qPcyPxTOwDCOccw7w5nlBRZWylI+ny/mZ6rL1dzUZ5/IWGZU3D'. 'qPcyPxTOwDCOccw7w5nlBRZWylI+ny/mZ6rL1dzUZ5/IWGZU3D'.
'ZIOMQDDaJcHDVGWUbJBi9odVr0QoVSPzigIEaZ8vgSS/8wZU3/'. 'ZIOMQDDaJcHDVGWUbJBi9odVr0QoVSPzigIEaZ8vgSS/8wZU3/'.
'k1fylipz5dLM2WlrZqHKaGCKbEbontq3KAKWQyZfZKTgYqc9Bp'. 'k1fylipz5dLM2WlrZqHKaGCKbEbontq3KAKWQyZfZKTgYqc9Bp'.
'2I2PcJ4ogk/UEBQcwipbFZmT13vDBx8fhnE1Ofnp9yJopFyT3X'. '2I2PcJ4ogk/UEBQcwipbFZmT13vDBx8fhnE1Ofnp9yJopFyT3X'.
'yANfks0QHSQMDaL37pOxMLIu2UyVkjVKLjyKSeuD8dAYCFkso1'. 'yANfks0QHSQMDaL37pOxMLIu2UyVkjVKLjyKSeuD8dAYCFkso1'.
'gYMaeWJ40T56cl8yAi/O4FSa2P6kYczIDsgVpAqcDImZPMuAB1'. 'gYMaeWJ40T56cl8yAi/O4FSa2P6kYczIDsgVpAqcDImZPMuAB1'.
'dkLQtcc8a/bwox8IUHAxZVxGZMouSLVYwKuMkD5IxN+JSdsRJB'. 'dkLQtcc8a/bwox8IUHAxZVxGZMouSLVYwKuMkD5IxN+JSdsRJB'.
'pexuTVgYYM6EoGmxkmg3/hEhNUMr/hd7dqbOzExMn/GRDAxWZc'. 'pexuTVgYYM6EoGmxkmg3/hEhNUMr/hd7dqbOzExMn/GRDAxWZc'.
'j3I8HiXfMjF2FQowKw7pjoN6E/Llw/GBJj8qxVOMlX4ipxc/lY'. 'j3I8HiXfMjF2FQowKw7pjoN6E/Llw/GBJj8qxVOMlX4ipxc/lY'.
'kl2zBLkmrTcEzMkoNoRLVidLi/9g+Z3I+1xRHX5EcAihxnbPRv'. 'kl2zBLkmrTcEzMkoNoRLVidLi/9g+Z3I+1xRHX5EcAihxnbPRv'.
'OTU9kZSmpKPy9FTGrLimPZ1H+UiyGaF67w6n7E1DwMngFDxGvc'. 'OTU9kZSmpKPy9FTGrLimPZ1H+UiyGaF67w6n7E1DwMngFDxGvc'.
'w70v0xZUby5IxjlIyMssUJrJwVWkXBdbXvSvwEibcSdKCAFI16'. 'w70v0xZUby5IxjlIyMssUJrJwVWkXBdbXvSvwEibcSdKCAFI16'.
'4/sc0SRo9cGAGq1DwvQFzV6DVuBiV4zYnlEts6A2TSPcSiXoxo'. '4/sc0SRo9cGAGq1DwvQFzV6DVuBiV4zYnlEts6A2TSPcSiXoxo'.
'QqJCEEFMbQ2b69o5qMiOOPqIMQkagu/aSL7waE8101WFShLjk9'. 'QqJCEEFMbQ2b69o5qMiOOPqIMQkagu/aSL7waE8101WFShLjk9'.
'yxgEvjRUiyYd+gwAjY2J9VpXfZ/JEXLhDp3OR6U4T97+hEnPwx'. 'yxgEvjRUiyYd+gwAjY2J9VpXfZ/JEXLhDp3OR6U4T97+hEnPwx'.
'tv4HsRjy2tTQSFzQgDUnwSLBQRI+x1ZgcH87Vcv4SF19Kt0ezS'. 'tv4HsRjy2tTQSFzQgDUnwSLBQRI+x1ZgcH87Vcv4SF19Kt0ezS'.
'1h9s0Ma25pgr/YJfnLnEysok0+ezjM6EBLldGqKIJYuDRhOQEJ'. '1h9s0Ma25pgr/YJfnLnEysok0+ezjM6EBLldGqKIJYuDRhOQEJ'.
'Oih8X9Q0xmcXNjlCofBJgn78wxVz7L2YWf8tPPz1hnfjbjzfxN'. 'Oih8X9Q0xmcXNjlCofBJgn78wxVz7L2YWf8tPPz1hnfjbjzfxN'.
'qVwutq2etZXUQSXikcXGIgUiUkJSDIQMJgYGJsaB3c7b1qQ4GZ'. 'qVwutq2etZXUQSXikcXGIgUiUkJSDIQMJgYGJsaB3c7b1qQ4GZ'.
'xSkdGZIwMeNLfK6uezMnvJK3pLxeVixfvMsyVjSNSO6IV9adPG'. 'xSkdGZIwMeNLfK6uezMnvJK3pLxeVixfvMsyVjSNSO6IV9adPG'.
'AArkEEz8oUkFmBjYGO80qfd6pCWIayD59wIKcsjcKqufn7JO/S'. 'AArkEEz8oUkFmBjYGO80qfd6pCWIayD59wIKcsjcKqufn7JO/S'.
'xfyi+5c24pey5rZ09mJRNkiDdT/tzbkBr3SYkpMYpgEaIJSYhI'. 'xfyi+5c24pey5rZ09mJRNkiDdT/tzbkBr3SYkpMYpgEaIJSYhI'.
'kSOY1GhilAQk5ntDIojxCZ/kf87Pl85xbuWEnLiUy+cW3NNuJX'. 'kSOY1GhilAQk5ntDIojxCZ/kf87Pl85xbuWEnLiUy+cW3NNuJX'.
'MmY5meKf6mT7wZS+THdOjxlG06tIlIOMZxchSxcFFEGAwAGGME'. 'MmY5meKf6mT7wZS+THdOjxlG06tIlIOMZxchSxcFFEGAwAGGME'.
'jwyZYSnWL3cXWiIUbUI6hO/vxXuFOV84ycmlBWthNeflTjuzTi'. 'jwyZYSnWL3cXWiIUbUI6hO/vxXuFOV84ycmlBWthNeflTjuzTi'.
'lzJmM5s46Ej0J63/ZoPmoy6PYxtYVNhmfs0mbAND1mmKVMBY1L'. 'lzJmM5s46Ej0J63/ZoPmoy6PYxtYVNhmfs0mbAND1mmKVMBY1L'.
'mxA1LN7WgXQbCApNhKJHRIM+DQbv7yQGhjnJ5NgFuXBuxpu5mD'. 'mxA1LN7WgXQbCApNhKJHRIM+DQbv7yQGhjnJ5NgFuXBuxpu5mD'.
'udm3LPuY7pmZLUE6L1SIJaIPFuDAqyw9lnwDYv6NFHkWJh4ZDB'. 'udm3LPuY7pmZLUE6L1SIJaIPFuDAqyw9lnwDYv6NFHkWJh4ZDB'.
'wCBFD3uMxsTAwcBAiElpE/KcPg36dIiOvpsRxDCyhmlP2YY9ZU'. 'wCBFD3uMxsTAwcBAiElpE/KcPg36dIiOvpsRxDCyhmlP2YY9ZU'.
'v8NMb/1id+FGO0DTztkSXLOONUqeITsMkW2zwnJEIDFhYGx+A1'. 'v8NMb/1id+FGO0DTztkSXLOONUqeITsMkW2zwnJEIDFhYGx+A1'.
'kwK4mASkvKDPc3p0iYhRRwYUhZLUTyV6Eu0t4s1Y4kcx6W6KaM'. 'kwK4mASkvKDPc3p0iYhRRwYUhZLUTyV6Eu0t4s1Y4kcx6W6KaM'.
'EZThcXH59RRhGEgIAddnBwNEBKqqpUtWBIF22YDIhJsbEkJqFN'. 'EZThcXH59RRhGEgIAddnBwNEBKqqpUtWBIF22YDIhJsbEkJqFN'.
'qLtERHs7GnUkwISEQAf0uj30bY39PzbiC6qrDu2cExJ69Nhhhz'. 'qLtERHs7GnUkwISEQAf0uj30bY39PzbiC6qrDu2cExJ69Nhhhz'.
'59UlIUipCQOnVi4sjG7ubJBy6um0C+he/0iDHQKIQERYyKFLqr'. '59UlIUipCQOnVi4sjG7ubJBy6um0C+he/0iDHQKIQERYyKFLqr'.
'SI/W6kJCnvOcrWSLSquC1/Jw9Ks3R0FQKHr0uMc9bnCDGjX69A'. 'SI/W6kJCnvOcrWSLSquC1/Jw9Ks3R0FQKHr0uMc9bnCDGjX69A'.
'H0XlcJkibN5jOe/alCZStHbjJL9lSMLkXExvCXRiDV6GZEeGeX'. 'H0XlcJkibN5jOe/alCZStHbjJL9lSMLkXExvCXRiDV6GZEeGeX'.
'3TvvBVQoEjfBL/v0rT75Th7VU5C8gktI6NLlMY+5yU3WWGODDf'. '3TvvBVQoEjfBL/v0rT75Th7VU5C8gktI6NLlMY+5yU3WWGODDf'.
'r098tHpNFNH7/2lKdXXdz7efLzVaqJIBOCmK8AJUlI6g0aV+9y'. 'r098tHpNFNH7/2lKdXXdz7efLzVaqJIBOCmK8AJUlI6g0aV+9y'.
'9+p7AR3bMQpTBWPy7yeN6fy0jNwewfpvC9Xe+3kFoUuXe9zj5n'. '9+p7AR3bMQpTBWPy7yeN6fy0jNwewfpvC9Xe+3kFoUuXe9zj5n'.
'BusEGHjh6GIAGawC2FWuvSvbbF1maFylZAsC1ISZADBiVNSJrP'. 'BusEGHjh6GIAGawC2FWuvSvbbF1maFylZAsC1ISZADBiVNSJrP'.
'eX73MY//skHP85z5+fnSxQsXj//4n39cmnPn7LbZlsajBmEnBL'. 'eX73MY//skHP85z5+fnSxQsXj//4n39cmnPn7LbZlsajBmEnBL'.
'1nuEGDG9x4aa5Ldz+h0RCuBqwBv1Wo+7vs9r7n++0MmYeAM+zB'. '1nuEGDG9x4aa5Ldz+h0RCuBqwBv1Wo+7vs9r7n++0MmYeAM+zB'.
'+61EK1QUEnbbtN+9Bh3Hsebn54u//PdfLq9eWl2ZnZ1dSnaSwu'. '+61EK1QUEnbbtN+9Bh3Hsebn54u//PdfLq9eWl2ZnZ1dSnaSwu'.
'Pin40b9g3doKE0WoNIl65xj3v75njd3BBubQi6ExKmDWkMRKSl'. 'Pin40b9g3doKE0WoNIl65xj3v75njd3BBubQi6ExKmDWkMRKSl'.
'tSbVKQcMao1Go5Ugb0+x53nOyZMnSysrKydXLq1cWlxa/McgCB'. 'tSbVKQcMao1Go5Ugb0+x53nOyZMnSysrKydXLq1cWlxa/McgCB'.
'Yev3hU+GPrD3I5/q94k3pXYQY58q6B5Bs0HB//neaGx00gyWaz'. 'Yev3hU+GPrD3I5/q94k3pXYQY58q6B5Bs0HB//neaGx00gyWaz'.
'VCoV7bquCoKAnZ0dfN/f03egLGj0m3XQNE1jdnY2/+WXXy6trq'. 'VCoV7bquCoKAnZ0dfN/f03egLGj0m3XQNE1jdnY2/+WXXy6trq'.
'6uzP3oR5eCIFi4detW5feXL1vr679Let37zVB3/mQytjXJwmSB'. '6uzP3oR5eCIFi4detW5feXL1vr679Let37zVB3/mQytjXJwmSB'.
'wikHp9ShY0RESqObwPrr5oBERKhUKly4cIFqtUq9XufmzZtsbW'. 'wikHp9ShY0RESqObwPrr5oBERKhUKly4cIFqtUq9XufmzZtsbW'.
'2hXvuDwTTNtxZq8TyvsLy8vLS4uLgahOHphw8elL69fNlc++qr'. '2hXvuDwTTNtxZq8TyvsLy8vLS4uLgahOHphw8elL69fNlc++qr'.
'uFOrNXPddm1cczVL5f5P+Lv5MuOJgTGxwYbZpZsCdeAq8M1Bcw'. 'uFOrNXPddm1cczVL5f5P+Lv5MuOJgTGxwYbZpZsCdeAq8M1Bcw'.
'CGYeC6LtVqlRMnTjAyMkKn0yGXyx0N0LZt03Ec1zCMSrfXO37v'. 'CGYeC6LtVqlRMnTjAyMkKn0yGXyx0N0LZt03Ec1zCMSrfXO37v'.
'zp3S769csb+/ciXt1mrNdHf3ltZ6Lca8ZpJsduhtCdb2gEFJoQ'. 'zp3S769csb+/ciXt1mrNdHf3ltZ6Lca8ZpJsduhtCdb2gEFJoQ'.
'xADYHuHDS3f32lFEEQUK/XGRkZoVAocP78eZaXl9FaI/Jq25Uk'. 'xADYHuHDS3f32lFEEQUK/XGRkZoVAocP78eZaXl9FaI/Jq25Uk'.
'yWHAYrHozM/PlxYWFibTND32sFbLXrtyxVz76qukXas1M61WTW'. 'yWHAYrHozM/PlxYWFibTND32sFbLXrtyxVz76qukXas1M61WTW'.
'm99gx+20TdN9jqtfjP7QzOwwYNp037Zd0DukDnIByA1pqdnR2+'. 'm99gx+20TdN9jqtfjP7QzOwwYNp037Zd0DukDnIByA1pqdnR2+'.
'++472u02Z8+eZWJiAsMwDsEBRNGBzYJpmsaJEyfyX3zxxdLS0t'. '++472u02Z8+eZWJiAsMwDsEBRNGBzYJpmsaJEyfyX3zxxdLS0t'.
'KlVqu1dP3q1cLta9ekU6u1dat1J9b6Sk9kraV1rYXegW7apDYw'. 'KlVqu1dP3q1cLta9ekU6u1dat1J9b6Sk9kraV1rYXegW7apDYw'.
'kFY6fPc4MNTw88bwfZ/NzU2UUnieRxAEiAiGcXiXfcigiIjruo'. 'kFY6fPc4MNTw88bwfZ/NzU2UUnieRxAEiAiGcXiXfcigiIjruo'.
'VyubxkWdbK7fX1xWvffFMInjzBM82uMT5+p++6V1UUrSe7u03t'. 'VyubxkWdbK7fX1xWvffFMInjzBM82uMT5+p++6V1UUrSe7u03t'.
'+8lezlKt3gHyl0aSJDQaDa5fv876+vo+w6FzDq1BpZRsb2/bly'. '+8lezlKt3gHyl0aSJDQaDa5fv876+vo+w6FzDq1BpZRsb2/bly'.
'9f9vL5/Njdu3fzG0+eMJHNxsfn532vXN5NPG/7abPZal6/Hvfe'. '9f9vL5/Njdu3fzG0+eMJHNxsfn532vXN5NPG/7abPZal6/Hvfe'.
'kroPHfsm98f7AHW9Xo+//vrrlmVZm71+37QNw3JnZ9PK4uJGpV'. 'kroPHfsm98f7AHW9Xo+//vrrlmVZm71+37QNw3JnZ9PK4uJGpV'.
'pt4Dh+vLGhsrmcfv1iHzu01m89HjIdCon2fb8TBMHtvYeRUn50'. 'pt4Dh+vLGhsrmcfv1iHzu01m89HjIdCon2fb8TBMHtvYeRUn50'.
'1Oj4vqp3Ok1f5LYSadfr9dQfDN642P/XeF2DA+SBAuA4jkOhUK'. '1Oj4vqp3Ok1f5LYSadfr9dQfDN642P/XeF2DA+SBAuA4jkOhUK'.
'BQKESO43S11p3BYBDt7u4y+CtB/i/q7jp1GMiw2AAAAABJRU5E'. 'BQKESO43S11p3BYBDt7u4y+CtB/i/q7jp1GMiw2AAAAABJRU5E'.
'rkJggg==' ; 'rkJggg==' ;
   
//========================================================== //==========================================================
// File: ppl_blue.png // File: ppl_blue.png
//========================================================== //==========================================================
$this->imgdata_large[3][0]= 2284 ; $this->imgdata_large[3][0]= 2284 ;
$this->imgdata_large[3][1]= $this->imgdata_large[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMLFRAiTZAL3gAACHlJREFUeJy9mGtv29YZgJ9zKF'. 'B3RJTUUH0wMLFRAiTZAL3gAACHlJREFUeJy9mGtv29YZgJ9zKF'.
'F3y/Q9jh05tuQkarKgbYasde0UBdZgwNou/Vqga/sD9mP2B4a1'. 'F3y/Q9jh05tuQkarKgbYasde0UBdZgwNou/Vqga/sD9mP2B4a1'.
'BbZ9atFPxb5sqOtmXbI19bqsluPYiR3HN90vFEWRZx/IJI5zqa'. 'BbZ9atFPxb5sqOtmXbI19bqsluPYiR3HN90vFEWRZx/IJI5zqa'.
'x0OwBBSgR5Hj7v+55zSEFXTUgIJyA9C6/9RsjMjAyFIxxJCDc7'. 'x0OwBBSgR5Hj7v+55zSEFXTUgIJyA9C6/9RsjMjAyFIxxJCDc7'.
'iBqKgyZACGg3G2x9+xXf/fG33P3mC9qNKsp1O+1JdkEnQTdgIO'. 'iBqKgyZACGg3G2x9+xXf/fG33P3mC9qNKsp1O+1JdkEnQTdgIO'.
'ttCSMUi8gj072MnugllAyB9G8rBGi6RsToJTF6iuRoFi1kHKZf'. 'ttCSMUi8gj072MnugllAyB9G8rBGi6RsToJTF6iuRoFi1kHKZf'.
'7fB8Iggj0/Dy23D2dakNTR3JDsXPvzstxmZGRMER1EwHhQAEgE'. '7fB8Iggj0/Dy23D2dakNTR3JDsXPvzstxmZGRMER1EwHhQAEgE'.
'CLhIkPD6InY9S3djGLJVBtQP1Qb4HDAyoJYQOOZkPx49nhTH9i'. 'CLhIkPD6InY9S3djGLJVBtQP1Qb4HDAyoJYQOOZkPx49nhTH9i'.
'7MUBGT7egxkJgd70wZS/CUkoZtA/fRoE1DZ2ACiv52ibReCp4e'. '7MUBGT7egxkJgd70wZS/CUkoZtA/fRoE1DZ2ACiv52ibReCp4e'.
'7CIEHomxDiuVdGTqUnf/ZeOjR8fpiVXZul5ZrY3bWwbdcLr/dA'. '7CIEHomxDiuVdGTqUnf/ZeOjR8fpiVXZul5ZrY3bWwbdcLr/dA'.
'AAIpAwQjUWIjQ+g9HZvswiCgBVF9/SI6OSLGzo0i+oLi6+Utbq'. 'AAIpAwQjUWIjQ+g9HZvswiCgBVF9/SI6OSLGzo0i+oLi6+Utbq'.
'+bKEftgwOE/0Ohocf66M+cBjo22U2RQLIHMhmYnvaOpR9S8bSU'. '+bKEftgwOE/0Ohocf66M+cBjo22U2RQLIHMhmYnvaOpR9S8bSU'.
'UqCURGpRkuMZMm9cIvPGJZLj0yBjT2LprkiSkykx9cuXIhOnUs'. 'UqCURGpRkuMZMm9cIvPGJZLj0yBjT2LprkiSkykx9cuXIhOnUs'.
'm+QNC2XdG02ggBTcvFabsPWwTPpBAChSCgh4kYBpoeplWp47Qs'. 'm+QNC2XdG02ggBTcvFabsPWwTPpBAChSCgh4kYBpoeplWp47Qs'.
'7EYDt21xINzd5GCAxLExRl89Z+nHjpbKMmjbmkgfDzI0JEW53K'. '7EYDt21xINzd5GCAxLExRl89Z+nHjpbKMmjbmkgfDzI0JEW53K'.
'Jaa6NcAOEX8v52uJzsBlAS6u0hcnTIccPRqhWPCUcLD+s1EaUp'. 'Jaa6NcAOEX8v52uJzsBlAS6u0hcnTIccPRqhWPCUcLD+s1EaUp'.
'HCEhEMCyHNpt9SjgIU12A6iw6xb123vYhaaKjB9tlgMD5X+uBp'. 'HCEhEMCyHNpt9SjgIU12A6iw6xb123vYhaaKjB9tlgMD5X+uBp'.
'zdkpg6azA8EaNQtKlVba+Xez4eCntnJrsDdFsW5nYFpxlFN846'. 'zdkpg6azA8EaNQtKlVba+Xez4eCntnJrsDdFsW5nYFpxlFN846'.
'DXe8utkM4mhi+EgQmjYbS2WqexZKk6BpjwJ2YlK5VjeA3pNDiH'. 'DXe8utkM4mhi+EgQmjYbS2WqexZKk6BpjwJ2YlK5VjeA3pNDiH'.
'YjRWPzPE7tmBo8EWwGhkXx+z3uXL7D3rU97LIF8RBEAl6lK/Uo'. 'YjRWPzPE7tmBo8EWwGhkXx+z3uXL7D3rU97LIF8RBEAl6lK/Uo'.
'6JNM1rZ2aTcr3eUgIQOGTgbdwXMGyRejenLYTvQGbAdRuetSud'. '6JNM1rZ2aTcr3eUgIQOGTgbdwXMGyRejenLYTvQGbAdRuetSud'.
'OivVuFZgtCEgICghICnZoMhmlVTPR49LCAEkQUhk/B7KXe0MWf'. 'OivVuFZgtCEgICghICnZoMhmlVTPR49LCAEkQUhk/B7KXe0MWf'.
'nxj8xVR/cDheK14WZmtVMJSBnlGoN6FmQq0FLfdwJgORKPHRo/'. 'nxj8xVR/cDheK14WZmtVMJSBnlGoN6FmQq0FLfdwJgORKPHRo/'.
'Snzx4G0F/FjJ4KiOdmjPCrrx8bffnMybMv9MQGNG3rzlVqtR1B'. 'Snzx4G0F/FjJ4KiOdmjPCrrx8bffnMybMv9MQGNG3rzlVqtR1B'.
'sh/CYXCD4Aag1oCW7ZnUOjSp6WFi/QNEB8Y7BfTNjZyCmUvJ0I'. 'sh/CYXCD4Aag1oCW7ZnUOjSp6WFi/QNEB8Y7BfTNjZyCmUvJ0I'.
'XXT47MTp98Ybon9VZCk8cVazfqlNargsY34G7ByAlIjkHd9CCr'. 'XXT47MTp98Ybon9VZCk8cVazfqlNargsY34G7ByAlIjkHd9CCr'.
'LbBdiHViUgiECuDKYCdz8b2cywREdiYZOj8zNnLuzOTzx6ODp+'. 'LbBdiHViUgiECuDKYCdz8b2cywREdiYZOj8zNnLuzOTzx6ODp+'.
'OaGaqwVzBFqz0Idhz2loE7YEwBLaAJLQcKbW8qjAcBF5Jh0AMP'. 'OaGaqwVzBFqz0Idhz2loE7YEwBLaAJLQcKbW8qjAcBF5Jh0AMP'.
'IOHe6kxgtb3UMO2OxkF//ffK28nQqxfvm3szrtnDVa799Qb/+v'. 'IOHe6kxgtb3UMO2OxkF//ffK28nQqxfvm3szrtnDVa799Qb/+v'.
'NtsbNSpm3tAv8B+w7Ub0FhAyoBcMPec9oK6raXk48ziQBXQcmC'. 'NtsbNSpm3tAv8B+w7Ub0FhAyoBcMPec9oK6raXk48ziQBXQcmC'.
'pT3YqHa0mpEBkTR6wz/Jjo2cy04+fzwxdDquNfQKO7sFUbpu0c'. 'pT3YqHa0mpEBkTR6wz/Jjo2cy04+fzwxdDquNfQKO7sFUbpu0c'.
'wp3JoAYsA42Bbkl4GCryUNDEM7Avm6Z/CgSYBWG8pNuFuDu1Wo'. 'wp3JoAYsA42Bbkl4GCryUNDEM7Avm6Z/CgSYBWG8pNuFuDu1Wo'.
'tjoxKIJGeHIiM/jmK9NnX5ycuJQMtUcqXPvLDTa+qIie4hAJ1U'. 'tjoxKIJGeHIiM/jmK9NnX5ycuJQMtUcqXPvLDTa+qIie4hAJ1U'.
'vdrmO2HaDfB931twJgAn1A4lGT96obPHPLBbhVgUoTHHWo9aAA'. 'vdrmO2HaDfB931twJgAn1A4lGT96obPHPLBbhVgUoTHHWo9aAA'.
'JVAKpyKEmQNzWRENAsL18ycKjAFN/9gCNvzLB/390MMmE7pnDi'. 'JVAKpyKEmQNzWRENAsL18ycKjAFN/9gCNvzLB/390MMmE7pnDi'.
'Bvwt0K5Jv3O+0oB22nJ1Vvjb/UMhOpcKknqN1OiMB2DNHU2G5s'. 'Bvwt0K5Jv3O+0oB22nJ1Vvjb/UMhOpcKknqN1OiMB2DNHU2G5s'.
'sVndpGJVcZXjX1IAlvw9PmhRQcOFPhsSDkiBrQR1G7brgs0a7D'. 'sVndpGJVcZXjX1IAlvw9PmhRQcOFPhsSDkiBrQR1G7brgs0a7D'.
'ag3FK4rguqBXarI4Nt1SJv5gls7TEWtJDRBO2GwnIs8maevFnA'. 'ag3FK4rguqBXarI4Nt1SJv5gls7TEWtJDRBO2GwnIs8maevFnA'.
'Gx6awLZvzeTBu4kFbLigijC47pscpx0xyDfkvtUEnlarCDtrUC'. 'Gx6awLZvzeTBu4kFbLigijC47pscpx0xyDfkvtUEnlarCDtrUC'.
't2HGIhvPHVdVwqjTIrxRU2a5uUrYoP0QZ2gMvACl7+3V/LuKDq'. 't2HGIhvPHVdVwqjTIrxRU2a5uUrYoP0QZ2gMvACl7+3V/LuKDq'.
'sJuDy597516+CEezIHXv7vcgXQu2l+Bvn8He9Y4AE4kgk5P9DE'. 'sJuDy597516+CEezIHXv7vcgXQu2l+Bvn8He9Y4AE4kgk5P9DE'.
'R6aFdq5Et5Nit3yTf3m9sBcsAN3+D98c0Fit5JawE25r1zg1Fo'. 'R6aFdq5Et5Nit3yTf3m9sBcsAN3+D98c0Fit5JawE25r1zg1Fo'.
'5B8GFD7g+nVYnu8EUEop9XTa0N/9dUbqcphP/rDJzbUClVbpgR'. '5B8GFD7g+nVYnu8EUEop9XTa0N/9dUbqcphP/rDJzbUClVbpgR'.
'y2fXM3fND95qj75J8AC6BWPINfVSBieK+x+6cS5UCzCLu3oFV9'. 'y2fXM3fND95qj75J8AC6BWPINfVSBieK+x+6cS5UCzCLu3oFV9'.
'GqCMx2NGOp2Znpv7aXZudsool3T5J/179sxVlHJ4kGPrP2COBX'. 'GqCMx2NGOp2Znpv7aXZudsool3T5J/179sxVlHJ4kGPrP2COBX'.
'/7DmiApWCjxIMXpYNznYuXM+6TAKWUMppOZzLvv//ery5cuDCT'. '/7DmiApWCjxIMXpYNznYuXM+6TAKWUMppOZzLvv//ery5cuDCT'.
'SqVS336bCwr1JfAPB9r+2KAFwJS+OcETzZHz/7v3etl6ipz77X'. 'SqVS336bCwr1JfAPB9r+2KAFwJS+OcETzZHz/7v3etl6ipz77X'.
'GAMh6PG+l0OjM3NzczOzs3k0pNnFlbW43+e/GKtMqrblSsF03V'. 'GAMh6PG+l0OjM3NzczOzs3k0pNnFlbW43+e/GKtMqrblSsF03V'.
'WHcJA0PjIAzvg9JTze2H67g9DjAwOTmZ+uCDD96anZ2dnZiYmF'. 'WHcJA0PjIAzvg9JTze2H67g9DjAwOTmZ+uCDD96anZ2dnZiYmF'.
'5dW41++Lvfa1fnr7qllVK9103mXNTnJgPA+YugsvB3HTaEl+Qs'. '5dW41++Lvfa1fnr7qllVK9103mXNTnJgPA+YugsvB3HTaEl+Qs'.
'AZ/yeHPPDCiTyaRx5syZbGoilV1dW00szC9oV+avusuLy0Xd0X'. 'AZ/yeHPPDCiTyaRx5syZbGoilV1dW00szC9oV+avusuLy0Xd0X'.
'MgFkDM+zkYBZEHV8f7wwKu84zmngQoNU0LaZoWUa4K31y5qX/8'. 'MgFkDM+zkYBZEHV8f7wwKu84zmngQoNU0LaZoWUa4K31y5qX/8'.
'4cfyyvwVN5/L10NOKNeg8UmDxoKF5Vfj1xXAgD0JrgAcvBDfel'. '4cfyyvwVN5/L10NOKNeg8UmDxoKF5Vfj1xXAgD0JrgAcvBDfel'.
'a4g4AykUgY6XR6emJiIru2ttZXq9S0K19eUcuLy8WQE8o5OAsN'. 'a4g4AykUgY6XR6emJiIru2ttZXq9S0K19eUcuLy8WQE8o5OAsN'.
'Ggsmpl+NpoL1g9X4UBU+C9xDgEKIwNTUVOqdd955M9mbnJ3/cj'. 'Ggsmpl+NpoL1g9X4UBU+C9xDgEKIwNTUVOqdd955M9mbnJ3/cj'.
'6Vu5aTheXCQXNdVeMzAwJSCGEA2XKpnF1cXIzlFnOVhJPIKdR+'. '6Vu5aTheXCQXNdVeMzAwJSCGEA2XKpnF1cXIzlFnOVhJPIKdR+'.
'c88ctq4AlVKsrKzw0UcfKcC5uXqzXnNqSzb2pwLxOHP/l7Z/BN'. 'c88ctq4AlVKsrKzw0UcfKcC5uXqzXnNqSzb2pwLxOHP/l7Z/BN'.
'eB01LKt4HTrusKvGr8jB+hGn8MQAkYQMrfw4Nq/MFPtf+rdvDb'. 'eB01LKt4HTrusKvGr8jB+hGn8MQAkYQMrfw4Nq/MFPtf+rdvDb'.
'k8QL+/5Z4Uepxm7bfwHuTAVUWpWaqAAAAABJRU5ErkJggg==' ; 'k8QL+/5Z4Uepxm7bfwHuTAVUWpWaqAAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: ppl_green.png // File: ppl_green.png
//========================================================== //==========================================================
$this->imgdata_large[4][0]= 2854 ; $this->imgdata_large[4][0]= 2854 ;
$this->imgdata_large[4][1]= $this->imgdata_large[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMLFQ4hANhluwAACrNJREFUeJytmF1zE1eagJ+3u9'. 'B3RJTUUH0wMLFQ4hANhluwAACrNJREFUeJytmF1zE1eagJ+3u9'.
'XdkvUty2AbmLEtEzDBgZ0UpDBOalNTUzU3czl7tct/2n+wt3M/'. 'XdkvUty2AbmLEtEzDBgZ0UpDBOalNTUzU3czl7tct/2n+wt3M/'.
'NVM12SSTQQSyW2TA+QAJQogtYYFtyfrqL3WfvWj5g8AEjzfvhS'. 'NVM12SSTQQSyW2TA+QAJQogtYYFtyfrqL3WfvWj5g8AEjzfvhS'.
'SXjk8//Zz3Pf3qCMcJAWxMKlT4kH+jwu/FknnJSUItKFHzCrKA'. 'SXjk8//Zz3Pf3qCMcJAWxMKlT4kH+jwu/FknnJSUItKFHzCrKA'.
'BggBQx5ziz/wn/yBz3hED4/oaJfSjgVoYjJJgTLTZCjohp7IGT'. 'BggBQx5ziz/wn/yBz3hED4/oaJfSjgVoYjJJgTLTZCjohp7IGT'.
'k5aZ4kb+bRTR30Q7djj8f/kpPMUSCFedRL6W8e8qMQNE6S4xpv'. 'k5aZ4kb+bRTR30Q7djj8f/kpPMUSCFedRL6W8e8qMQNE6S4xpv'.
'c5HrTPFubiJ3ZnlyOXV59rJYU5Z00h1c3d0brxAiUkScRijisk'. 'c5HrTPFubiJ3ZnlyOXV59rJYU5Z00h1c3d0brxAiUkScRijisk'.
'6XLTyiN3s8HuAJpniXa/q8/pt8Or+0kF8oXJm5YiydWcIpOrJu'. '6XLTyiN3s8HuAJpniXa/q8/pt8Or+0kF8oXJm5YiydWcIpOrJu'.
'rjOQwd54AQwsMpTJYhPSoYuLQ58An/DnBQSdImXO8avsTPbqpc'. 'rjOQwd54AQwsMpTJYhPSoYuLQ58An/DnBQSdImXO8avsTPbqpc'.
'lLp67OXDVzMznZLGxSs2qyIRu4at8gKHQEC50kE1icxqCAdxST'. 'lLp67OXDVzMznZLGxSs2qyIRu4at8gKHQEC50kE1icxqCAdxST'.
'xjEA44tqaJlERl8uLWvvnX5PHuQfcCdxh5qq0aX76vj4WgWyXO'. 'xjEA44tqaJlERl8uLWvvnX5PHuQfcCdxh5qq0aX76vj4WgWyXO'.
'QiNgBP8IAaddr08X8+wHFmJSQhBbPAZGoSZSt5wQs6qoNC7UEd'. 'QiNgBP8IAaddr08X8+wHFmJSQhBbPAZGoSZSt5wQs6qoNC7UEd'.
'4AEoLIQSCaCCy78Dv8Tiv1hjjW1CRj8XIAgEKqDtt9keboMJZa'. '4AEoLIQSCaCCy78Dv8Tiv1hjjW1CRj8XIAgEKqDtt9keboMJZa'.
'vMjuzQVd3Xr9prTJo+GF/jKZea95R25Lxs8jg5qFGiwDnOS0mW'. 'vMjuzQVd3Xr9prTJo+GF/jKZea95R25Lxs8jg5qFGiwDnOS0mW'.
'NE0rjNRIt3WbklUCA9mV3Zdz8OBT/JfCQLB0SKYVVjGFYSfx/E'. 'NE0rjNRIt3WbklUCA9mV3Zdz8OBT/JfCQLB0SKYVVjGFYSfx/E'.
'26ow4e6uDujlPFQpE0FU6P8qNTHdXJdEdda0qf0itWBVM3pa/3'. '26ow4e6uDujlPFQpE0FU6P8qNTHdXJdEdda0qf0itWBVM3pa/3'.
'ccUlIECJet0cAJoeYk5EZCeS5IwEoerSxccJBwRqFFf38QCTaO'. 'ccUlIECJet0cAJoeYk5EZCeS5IwEoerSxccJBwRqFFf38QCTaO'.
'TRVFKJm3NTbtLNSyh2IkhIXsvLCesEGNCWdmwyruSD/z9kUlRc'. 'TRVFKJm3NTbtLNSyh2IkhIXsvLCesEGNCWdmwyruSD/z9kUlRc'.
'3bqNlSxhJNJ43p5JITrOEis8Qtr0cXEpU/JT/pmO18n2vb42pU'. '3bqNlSxhJNJ43p5JITrOEis8Qtr0cXEpU/JT/pmO18n2vb42pU'.
'3JnDnHMBqyPlpnoAaxhr2llv1ZUBqEGlqYwDQMsskMOcMgVL3Y'. '3JnDnHMBqyPlpnoAaxhr2llv1ZUBqEGlqYwDQMsskMOcMgVL3Y'.
'ZOQTHAcQQiIGjHCwCaiovjrv4hbcpKuJJjIcDHm685RGr4GLCx'. 'ZOQTHAcQQiIGjHCwCaiovjrv4hbcpKuJJjIcDHm685RGr4GLCx'.
'YHkAcrLoAoDSLBiAQrMkjqybHJCbxgh+7xAC1MpsgzwRwD3qHL'. 'YHkAcrLoAoDSLBiAQrMkjqybHJCbxgh+7xAC1MpsgzwRwD3qHL'.
'WyTIBdlAa6u2rHfXaew06PV78ZZjAwleNnkolECoH5i090wOcY'. 'WyTIBdlAa6u2rHfXaew06PV78ZZjAwleNnkolECoH5i090wOcY'.
'+TgwYzFHiPi1zkOkXexeAMASnVU+LiyiA1wFUuaqggACLizeWw'. '+TgwYzFHiPi1zkOkXexeAMASnVU+LiyiA1wFUuaqggACLizeWw'.
'ycMzyssmVYKkbpGyC5T+OUALk2mKLHKWf+ED/az+YW42d66YL+'. 'ycMzyssmVYKkbpGyC5T+OUALk2mKLHKWf+ED/az+YW42d66YL+'.
'aNrmEEzQCFEnKw368EgEvcN1m80eTIQIt0TFOjMJHkzNEBBYPp'. 'aNrmEEzQCFEnKw368EgEvcN1m80eTIQIt0TFOjMJHkzNEBBYPp'.
'sblf8QHzrORO5JaWZ5ZLl6cuJyyxpNPv4PZdoT+GyIxBfI5uUg'. 'sblf8QHzrORO5JaWZ5ZLl6cuJyyxpNPv4PZdoT+GyIxBfI5uUg'.
'eJMCwP2/bIHO1JEudcgUUWOceKNq99mCvnzs5PzRcuTV4y5mRO'. 'eJMCwP2/bIHO1JEudcgUUWOceKNq99mCvnzs5PzRcuTV4y5mRO'.
'SMIjo47z5S7a94oQCNKgJsZwO7D/IDNg3/LLhRNXt4JohBb4aG'. 'SMIjo47z5S7a94oQCNKgJsZwO7D/IDNg3/LLhRNXt4JohBb4aG'.
'82GLdXcf93mQ+Y43r2RHZp+cRy6cqJK4l8MS+tdItaqiYtc0Mm'. '82GLdXcf93mQ+Y43r2RHZp+cRy6cqJK4l8MS+tdItaqiYtc0Mm'.
'QpfJARh98HYh9IiXVcaAo58wGb+LBAjbSPgCOcoSa0wzxXtc08'. 'QpfJARh98HYh9IiXVcaAo58wGb+LBAjbSPgCOcoSa0wzxXtc08'.
'/pv8mfyL+9MLVQvDJ1JVHJV6SZbFI1qtTsB+KlehRtRTGE8Afo'. '/pv8mfyL+9MLVQvDJ1JVHJV6SZbFI1qtTsB+KlehRtRTGE8Afo'.
'P4DRcAxiEudhAHjjzz+ubgX4oHowakHQOlqzICQwyVPITGVOXi'. 'P4DRcAxiEudhAHjjzz+ubgX4oHowakHQOlqzICQwyVPITGVOXi'.
'xfLF6aumzmczl5lHzMff2+fCdPaGttEkXoLQAO9B7C6EugPYby'. 'xfLF6aumzmczl5lHzMff2+fCdPaGttEkXoLQAO9B7C6EugPYby'.
'gVPjGXc5eIbNAJPjGwiAbaAJUQv8wVG7GROkJFpyOqn/ovgLba'. 'gVPjGXc5eIbNAJPjGwiAbaAJUQv8wVG7GROkJFpyOqn/ovgLba'.
'44L0+sDaraXb6jzq7aBQWjBOyUoHcaopOgmaA3IRyNDZnA1HjO'. '44L0+sDaraXb6jzq7aBQWjBOyUoHcaopOgmaA3IRyNDZnA1HjO'.
'HSBkr7eEFDAEngHrQCf+/s2A8cSiSkqcKUeeTjwFy2Jd78t3+L'. 'HSBkr7eEFDAEngHrQCf+/s2A8cSiSkqcKUeeTjwFy2Jd78t3+L'.
'TR4itIiBLwLQhzkJyB5Cx4HXDaENVQCBAQcRqFIHTRaBIvuYXg'. 'TR4itIiBLwLQhzkJyB5Cx4HXDaENVQCBAQcRqFIHTRaBIvuYXg'.
'AdsouuNxEL0ZUBHnSQp66R73zYfUtQ6OytKT8RckQAJQoLtgO5'. 'AdsouuNxEL0ZUBHnSQp66R73zYfUtQ6OytKT8RckQAJQoLtgO5'.
'BJgj0D/WfgdyHaAHx8THoUcbGx8ciwhUl3bDEiToURPooeI7pH'. 'BJgj0D/WfgdyHaAHx8THoUcbGx8ciwhUl3bDEiToURPooeI7pH'.
'MziK9Yd9nU5a6GgKjOH41vsgI4hAcyC5AZkapF+AoYNrjjsuhx'. 'MziK9Yd9nU5a6GgKjOH41vsgI4hAcyC5AZkapF+AoYNrjjsuhx'.
'FbtPmeB5ykyQQzTPAWAQWC8S9oAI0QRRuPb9jkmyMZNAOTklvC'. 'FbtPmeB5ykyQQzTPAWAQWC8S9oAI0QRRuPb9jkmyMZNAOTklvC'.
'GGYZaFkGmkVAh8h4DtKFMIBunG+pB5B5AIkGBDsQ+qBiL20caj'. 'GGYZaFkGmkVAh8h4DtKFMIBunG+pB5B5AIkGBDsQ+qBiL20caj'.
'zhJknq5KlgMkLjJHJos4kYEbFJi5vc5eYbATVN02bNWe19+32t'. 'zhJknq5KlgMkLjJHJos4kYEbFJi5vc5eYbATVN02bNWe19+32t'.
'aJWlFm3wbf8Rz5NbDFJdlOFBF/g7cBf0JkrbBb+F6j1DOduEkU'. 'aJWlFm3wbf8Rz5NbDFJdlOFBF/g7cBf0JkrbBb+F6j1DOduEkU'.
'8bWCOiSofPWadBnSZDWmgUkEMGhZCINut8S/0NBtPptFlZrBSu'. '8bWCOiSofPWadBnSZDWmgUkEMGhZCINut8S/0NBtPptFlZrBSu'.
'vnt1+ndnflfIp9OJ/279Ubbbd+lP7KBKPoEBsgnqLph/BRzwdS'. 'vnt1+ndnflfIp9OJ/279Ubbbd+lP7KBKPoEBsgnqLph/BRzwdS'.
'LnBUFvHcfdpRsGPAGqwMco6jynz+e0SPKYCHMfLX5VKHwcenR+'. 'LnBUFvHcfdpRsGPAGqwMco6jynz+e0SPKYCHMfLX5VKHwcenR+'.
'Igd1XTcqlUr+xn/cePv91fevzy8sLO2OtrOpWkqL7gXKSAVRdh'. 'Igd1XTcqlUr+xn/cePv91fevzy8sLO2OtrOpWkqL7gXKSAVRdh'.
'ZFEmEXoYkwBNqovoc/3GHH3aUR+jwC1oD/AWrANi4hGwyBzqEG'. 'ZFEmEXoYkwBNqovoc/3GHH3aUR+jwC1oD/AWrANi4hGwyBzqEG'.
'Vvb77Dgi0eT1VZzJZMxKpVJYXV1dXF1dXVm6sPSvruue3Xzcyj'. 'Vvb77Dgi0eT1VZzJZMxKpVJYXV1dXF1dXVm6sPSvruue3Xzcyj'.
'6/syvDzwj0lNazK6Fj5LFCRZouZpBABj6jXouu3+Np6HNvDHaf'. '6/syvDzwj0lNazK6Fj5LFCRZouZpBABj6jXouu3+Np6HNvDHaf'.
'g91t74msbMuOJicnSSaTKKUQEUQEpRSO69But1/dB0VEm5uby9'. 'g91t74msbMuOJicnSSaTKKUQEUQEpRSO69But1/dB0VEm5uby9'.
'y4cWNpdXX1+sLCworrume//PuXpeqnVeOban0U1PW2kcx+O9L7'. 'y4cWNpdXX1+sLCworrume//PuXpeqnVeOban0U1PW2kcx+O9L7'.
'Te9sUB4lWFR9SqNtNGcHx+/RDD2+Am4D94CnQA8OjjlEhMnyJC'. 'Te9sUB4lWFR9SqNtNGcHx+/RDD2+Am4D94CnQA8OjjlEhMnyJC'.
'srK8zOzu7BiYioMAzZ2Njg9u3brwIqpSSXy2WXl5eXLly4sOo4'. 'srK8zOzu7BiYioMAzZ2Njg9u3brwIqpSSXy2WXl5eXLly4sOo4'.
'zoV6vV6oflrVP/7Tx8Hmw1Zb6ydqmpWp7ha8h4O3gjOhzVANmF'. 'zoV6vV6oflrVP/7Tx8Hmw1Zb6ydqmpWp7ha8h4O3gjOhzVANmF'.
'XPMNQWvdDnCXCXuHR+APqH4fbCtm2mp6eZn59H13WJuYXRaKSU'. 'XPMNQWvdDnCXCXuHR+APqH4fbCtm2mp6eZn59H13WJuYXRaKSU'.
'UiSTyVcBdV3XDcOwRaTU7/en19bWCn/79G+JL/76RbhZ22y7u+'. 'UiSTyVcBdV3XDcOwRaTU7/en19bWCn/79G+JL/76RbhZ22y7u+'.
'6ahl71nPDz/nO17m7wAxlabFOihy4+DvAcqAMbPzZ3OFzX5dmz'. '6ahl71nPDz/nO17m7wAxlabFOihy4+DvAcqAMbPzZ3OFzX5dmz'.
'Z2iahoiosUUVhiGNRgPHcV4GzGQy5uLiYuH8+fMzo9FoslarJW'. 'Z2iahoiosUUVhiGNRgPHcV4GzGQy5uLiYuH8+fMzo9FoslarJW'.
'9+elP75E+fBJu1zY7qqpqBUW3T/niohnVvy+1zm5aVtp+WE2XT'. '9+elP75E+fBJu1zY7qqpqBUW3T/niohnVvy+1zm5aVtp+WE2XT'.
'nrHFzbjh1tYLz3XdPjD4R3BKKba2tqhWq4dzUO3noBPn4H5PKy'. 'nrHFzbjh1tYLz3XdPjD4R3BKKba2tqhWq4dzUO3noBPn4H5PKy'.
'LaO++8U7hx48byhQsXVne7u6tf3/v64t3P7mbq9+odt+OuaWi3'. 'LaO++8U7hx48byhQsXVne7u6tf3/v64t3P7mbq9+odt+OuaWi3'.
'PLxbW2ytubjbQCgiMnt6VlaurWgz0zM0m02q1WrUaDSUUuqI56'. 'PLxbW2ytubjbQCgiMnt6VlaurWgz0zM0m02q1WrUaDSUUuqI56'.
'ivDxE5MCgiYllWtlwuL5mmufLV/a/O/uXPf9Ff1F+80Lv6Yx29'. 'ivDxE5MCgiYllWtlwuL5mmufLV/a/O/uXPf9Ff1F+80Lv6Yx29'.
'2qHzyZBh3cdvc7gaTZuZkzPh/Py8ACqVSv1/uPZDKXUAGEWRtF'. '2qHzyZBh3cdvc7gaTZuZkzPh/Py8ACqVSv1/uPZDKXUAGEWRtF'.
'qtxEcffZTL5XLF+2v39fqjeivshA/TpP83JLwzYFBzcA4370Cc'. 'qtxEcffZTL5XLF+2v39fqjeivshA/TpP83JLwzYFBzcA4370Cc'.
'S81nTRBUs9lkOByi1GuOPI4Rh3+26JZlnSkWi781DOPXvV4v3+'. 'S81nTRBUs9lkOByi1GuOPI4Rh3+26JZlnSkWi781DOPXvV4v3+'.
'/2G0R8kSBxB/jew+tERK+c49m2TblcxrZtXNfl+fPneJ6HZVmU'. '/2G0R8kSBxB/jew+tERK+c49m2TblcxrZtXNfl+fPneJ6HZVmU'.
'y2VJJpNyaJ9TSinlOA5bW1u4rntkQA0oAG8D54gb9W3ianxM3A'. 'y2VJJpNyaJ9TSinlOA5bW1u4rntkQA0oAG8D54gb9W3ianxM3A'.
'e/cn73U3Hq1Cm5du2aPjs7a+ztcSIShmE4ajQa6tatWzQajZ+0'. 'e/cn73U3Hq1Cm5du2aPjs7a+ztcSIShmE4ajQa6tatWzQajZ+0'.
'fbiKI+It4SvijVUj7kL2qvGfgkskEqTTaZmcnDROnTplJhIJTU'. 'fbiKI+It4SvijVUj7kL2qvGfgkskEqTTaZmcnDROnTplJhIJTU'.
'QiwPd9P/Q8T6XTaQzDIAiCfzjP/wFVfszuFqdHXgAAAABJRU5E'. 'QiwPd9P/Q8T6XTaQzDIAiCfzjP/wFVfszuFqdHXgAAAABJRU5E'.
'rkJggg==' ; 'rkJggg==' ;
   
   
//========================================================== //==========================================================
// File: pp_red.png // File: pp_red.png
//========================================================== //==========================================================
$this->imgdata_small[0][0]= 384 ; $this->imgdata_small[0][0]= 384 ;
$this->imgdata_small[0][1]= $this->imgdata_small[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
'B3RJTUUH0wMJFhouFobZrQAAAQ1JREFUeJyV1dFtwyAQBuD/og'. 'B3RJTUUH0wMJFhouFobZrQAAAQ1JREFUeJyV1dFtwyAQBuD/og'.
'xQdYxa8gRY6hJ0jK6QdohMkTEuE5wUj5ERen05IoLvID7Jkn2G'. 'xQdYxa8gRY6hJ0jK6QdohMkTEuE5wUj5ERen05IoLvID7Jkn2G'.
'j8MgTMyMXqRlUQBYq9ydmaL2h1cwqD7l30t+L1iwlbYFRegY7I'. 'j8MgTMyMXqRlUQBYq9ydmaL2h1cwqD7l30t+L1iwlbYFRegY7I'.
'SHjkEifGg4ww3aBa/l4+9AhxWWr/dLhEunXUGHq6yGniw3QkOw'. 'SHjkEifGg4ww3aBa/l4+9AhxWWr/dLhEunXUGHq6yGniw3QkOw'.
'3jJ7UBd82n/VVAlAtvsfp98lAj2sAJOhU4AeQ7DC1ubVBODWDJ'. '3jJ7UBd82n/VVAlAtvsfp98lAj2sAJOhU4AeQ7DC1ubVBODWDJ'.
'TtCsEWa6u5M1NeFs1NzgdtuhHGtj+9Q2IDppQUAL6Cyrlz0gDN'. 'TtCsEWa6u5M1NeFs1NzgdtuhHGtj+9Q2IDppQUAL6Cyrlz0gDN'.
'ohSMiJCt861672EiAhEhESG3woJ9V9OKTkwRKbdqz4cHmFLSFg'. 'ohSMiJCt861672EiAhEhESG3woJ9V9OKTkwRKbdqz4cHmFLSFg'.
's69+LvAZKdeZ/n89uLnd2g0S+gjd5g8zzjH5Y/eLLi+NPEAAAA'. 's69+LvAZKdeZ/n89uLnd2g0S+gjd5g8zzjH5Y/eLLi+NPEAAAA'.
'AElFTkSuQmCC' ; 'AElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// File: pp_orange.png // File: pp_orange.png
//========================================================== //==========================================================
$this->imgdata_small[1][0]= 403 ; $this->imgdata_small[1][0]= 403 ;
$this->imgdata_small[1][1]= $this->imgdata_small[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
'B3RJTUUH0wMJFhwAnApz5AAAASBJREFUeJyN1dFthDAMBuDf7S'. 'B3RJTUUH0wMJFhwAnApz5AAAASBJREFUeJyN1dFthDAMBuDf7S'.
'3BCm2VCRKpS4QxbhikW6IewzcBqm6Fm6JyH7iEEByCn5AJH38g'. '3BCm2VCRKpS4QxbhikW6IewzcBqm6Fm6JyH7iEEByCn5AJH38g'.
'BBIRHNUzBAWAGNfe/SrUGv92CtNt309BrfFdMGPjvt9CD8Fyml'. 'BBIRHNUzBAWAGNfe/SrUGv92CtNt309BrfFdMGPjvt9CD8Fyml'.
'ZZaDchRgA/59FDMD18pvNoNyHxMnUmgLmPHoJ+CqqfMaNAH22C'. 'ZZaDchRgA/59FDMD18pvNoNyHxMnUmgLmPHoJ+CqqfMaNAH22C'.
'fgqKRwR+GRpxGjXBEiuXDBWQhTK3plxijyWWvtKVS5KNG1xM8I'. 'fgqKRwR+GRpxGjXBEiuXDBWQhTK3plxijyWWvtKVS5KNG1xM8I'.
'OBr7geV1WupDqpmTAPKjCqLhxk/z0PImQmjKrAuI6vMXlhFroD'. 'OBr7geV1WupDqpmTAPKjCqLhxk/z0PImQmjKrAuI6vMXlhFroD'.
'vfdqITXWqg2YMSJEAFcReoag6UXU2DzPG8w5t09YYsAyLWvHrL'. 'vfdqITXWqg2YMSJEAFcReoag6UXU2DzPG8w5t09YYsAyLWvHrL'.
'HUy6D3XmvMAAhAay8kAJpBosX4vt0G4+4Jam6s6Rz1fgFG0ncA'. 'HUy6D3XmvMAAhAay8kAJpBosX4vt0G4+4Jam6s6Rz1fgFG0ncA'.
'f3XfOQcA+Acv5IUSdQw9hgAAAABJRU5ErkJggg==' ; 'f3XfOQcA+Acv5IUSdQw9hgAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: pp_pink.png // File: pp_pink.png
//========================================================== //==========================================================
$this->imgdata_small[2][0]= 419 ; $this->imgdata_small[2][0]= 419 ;
$this->imgdata_small[2][1]= $this->imgdata_small[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
'B3RJTUUH0wMJFhsQzvz1RwAAATBJREFUeJyd1MFthDAQheF/oi'. 'B3RJTUUH0wMJFhsQzvz1RwAAATBJREFUeJyd1MFthDAQheF/oi'.
'gF+JYWQKICkCJRA1vGtrDbxFbhGvY0HVjCLeS2BeTiHFgTB2wg'. 'gF+JYWQKICkCJRA1vGtrDbxFbhGvY0HVjCLeS2BeTiHFgTB2wg'.
'eRISstCnmcG2qCpbuXf3ADBQzWsPfZfS9y9HsEu4/Fo33Wf4Fx'. 'eRISstCnmcG2qCpbuXf3ADBQzWsPfZfS9y9HsEu4/Fo33Wf4Fx'.
'gxL3a1XkI3wbTNXHLoboVeLFUYDqObYBy+Fw/Uh9DdCmtOwIjF'. 'gxL3a1XkI3wbTNXHLoboVeLFUYDqObYBy+Fw/Uh9DdCmtOwIjF'.
'YvG76CZoOhNGRmpO8zz30CJoOhMAqlDxFzQLppgXj2XaNlP7FF'. 'YvG76CZoOhNGRmpO8zz30CJoOhMAqlDxFzQLppgXj2XaNlP7FF'.
'GLL7ccMYCBgZERgCvXLBrfi2DEclmiKZwFY4tp6sW26bVfnede'. 'GLL7ccMYCBgZERgCvXLBrfi2DEclmiKZwFY4tp6sW26bVfnede'.
'e5Hc5dC2bUgrXGKqWrwcXnNYDjmCrcCIiQgDcFYV05kQ8SXmnB'. 'e5Hc5dC2bUgrXGKqWrwcXnNYDjmCrcCIiQgDcFYV05kQ8SXmnB'.
'NgPiVN06wrTDGAhz5EWY/FOccTk+cTnHM/YNu2YYllgFxCWuUM'. 'NgPiVN06wrTDGAhz5EWY/FOccTk+cTnHM/YNu2YYllgFxCWuUM'.
'ikzGx+2Gc+4N+CoJW8n+5a2UKm2aBoBvGA6L7wfl8aoAAAAASU'. 'ikzGx+2Gc+4N+CoJW8n+5a2UKm2aBoBvGA6L7wfl8aoAAAAASU'.
'VORK5CYII=' ; 'VORK5CYII=' ;
   
   
//========================================================== //==========================================================
// File: pp_blue.png // File: pp_blue.png
//========================================================== //==========================================================
$this->imgdata_small[3][0]= 883 ; $this->imgdata_small[3][0]= 883 ;
$this->imgdata_small[3][1]= $this->imgdata_small[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAACi1'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAACi1'.
'BMVEX///8AAAAAADMAAGYAAJkAAMwAAP8zAAAzADMzAGYzAJkz'. 'BMVEX///8AAAAAADMAAGYAAJkAAMwAAP8zAAAzADMzAGYzAJkz'.
'AMwzAP9mAABmADNmAGZmAJlmAMxmAP+ZAACZADOZAGaZAJmZAM'. 'AMwzAP9mAABmADNmAGZmAJlmAMxmAP+ZAACZADOZAGaZAJmZAM'.
'yZAP/MAADMADPMAGbMAJnMAMzMAP//AAD/ADP/AGb/AJn/AMz/'. 'yZAP/MAADMADPMAGbMAJnMAMzMAP//AAD/ADP/AGb/AJn/AMz/'.
'AP8AMwAAMzMAM2YAM5kAM8wAM/8zMwAzMzMzM2YzM5kzM8wzM/'. 'AP8AMwAAMzMAM2YAM5kAM8wAM/8zMwAzMzMzM2YzM5kzM8wzM/'.
'9mMwBmMzNmM2ZmM5lmM8xmM/+ZMwCZMzOZM2aZM5mZM8yZM//M'. '9mMwBmMzNmM2ZmM5lmM8xmM/+ZMwCZMzOZM2aZM5mZM8yZM//M'.
'MwDMMzPMM2bMM5nMM8zMM///MwD/MzP/M2b/M5n/M8z/M/8AZg'. 'MwDMMzPMM2bMM5nMM8zMM///MwD/MzP/M2b/M5n/M8z/M/8AZg'.
'AAZjMAZmYAZpkAZswAZv8zZgAzZjMzZmYzZpkzZswzZv9mZgBm'. 'AAZjMAZmYAZpkAZswAZv8zZgAzZjMzZmYzZpkzZswzZv9mZgBm'.
'ZjNmZmZmZplmZsxmZv+ZZgCZZjOZZmaZZpmZZsyZZv/MZgDMZj'. 'ZjNmZmZmZplmZsxmZv+ZZgCZZjOZZmaZZpmZZsyZZv/MZgDMZj'.
'PMZmbMZpnMZszMZv//ZgD/ZjP/Zmb/Zpn/Zsz/Zv8AmQAAmTMA'. 'PMZmbMZpnMZszMZv//ZgD/ZjP/Zmb/Zpn/Zsz/Zv8AmQAAmTMA'.
'mWYAmZkAmcwAmf8zmQAzmTMzmWYzmZkzmcwzmf9mmQBmmTNmmW'. 'mWYAmZkAmcwAmf8zmQAzmTMzmWYzmZkzmcwzmf9mmQBmmTNmmW'.
'ZmmZlmmcxmmf+ZmQCZmTOZmWaZmZmZmcyZmf/MmQDMmTPMmWbM'. 'ZmmZlmmcxmmf+ZmQCZmTOZmWaZmZmZmcyZmf/MmQDMmTPMmWbM'.
'mZnMmczMmf//mQD/mTP/mWb/mZn/mcz/mf8AzAAAzDMAzGYAzJ'. 'mZnMmczMmf//mQD/mTP/mWb/mZn/mcz/mf8AzAAAzDMAzGYAzJ'.
'kAzMwAzP8zzAAzzDMzzGYzzJkzzMwzzP9mzABmzDNmzGZmzJlm'. 'kAzMwAzP8zzAAzzDMzzGYzzJkzzMwzzP9mzABmzDNmzGZmzJlm'.
'zMxmzP+ZzACZzDOZzGaZzJmZzMyZzP/MzADMzDPMzGbMzJnMzM'. 'zMxmzP+ZzACZzDOZzGaZzJmZzMyZzP/MzADMzDPMzGbMzJnMzM'.
'zMzP//zAD/zDP/zGb/zJn/zMz/zP8A/wAA/zMA/2YA/5kA/8wA'. 'zMzP//zAD/zDP/zGb/zJn/zMz/zP8A/wAA/zMA/2YA/5kA/8wA'.
'//8z/wAz/zMz/2Yz/5kz/8wz//9m/wBm/zNm/2Zm/5lm/8xm//'. '//8z/wAz/zMz/2Yz/5kz/8wz//9m/wBm/zNm/2Zm/5lm/8xm//'.
'+Z/wCZ/zOZ/2aZ/5mZ/8yZ///M/wDM/zPM/2bM/5nM/8zM////'. '+Z/wCZ/zOZ/2aZ/5mZ/8yZ///M/wDM/zPM/2bM/5nM/8zM////'.
'/wD//zP//2b//5n//8z///9jJVUgAAAAAXRSTlMAQObYZgAAAA'. '/wD//zP//2b//5n//8z///9jJVUgAAAAAXRSTlMAQObYZgAAAA'.
'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'. 'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
'RQfTAwkWGTNerea3AAAAYUlEQVR4nHXNwQ3AIAxDUUfyoROxRZ'. 'RQfTAwkWGTNerea3AAAAYUlEQVR4nHXNwQ3AIAxDUUfyoROxRZ'.
'icARin0EBTIP3Hp1gBRqSqYo0seqjZpnngojlWBir5+b8o06lM'. 'icARin0EBTIP3Hp1gBRqSqYo0seqjZpnngojlWBir5+b8o06lM'.
'ha5uFKEpDZulV8l52axhVzqaCdxQp32qVSSwC1wN3fYiw7b76w'. 'ha5uFKEpDZulV8l52axhVzqaCdxQp32qVSSwC1wN3fYiw7b76w'.
'bN4SMue4/KbwAAAABJRU5ErkJggg==' ; 'bN4SMue4/KbwAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: pp_green.png // File: pp_green.png
//========================================================== //==========================================================
$this->imgdata_small[4][0]= 447 ; $this->imgdata_small[4][0]= 447 ;
$this->imgdata_small[4][1]= $this->imgdata_small[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
'B3RJTUUH0wMJFhkLdq9eKQAAAUxJREFUeJyN1LFVwzAQxvH/8f'. 'B3RJTUUH0wMJFhkLdq9eKQAAAUxJREFUeJyN1LFVwzAQxvH/8f'.
'IeDS0FLKABlN6eIwPYAzCHB0gWYI2jj+i1ABUTQN4TRSQ7iiWZ'. 'IeDS0FLKABlN6eIwPYAzCHB0gWYI2jj+i1ABUTQN4TRSQ7iiWZ'.
'qxLn9Mt9ydmiqrSq930AYFiu6YdKrf/hP1gYQn6960PxwBaYMG'. 'qxLn9Mt9ydmiqrSq930AYFiu6YdKrf/hP1gYQn6960PxwBaYMG'.
'E9UA3dBFtVQjdBOQmBakLennK0CapRwbZRZ3N0O/IeEsqp3HKL'. 'E9UA3dBFtVQjdBOQmBakLennK0CapRwbZRZ3N0O/IeEsqp3HKL'.
'Smtt5pUZgTPg4gdDud+6xoS97wM2rsxxmRSoTgoVcMZsXJkBho'. 'Smtt5pUZgTPg4gdDud+6xoS97wM2rsxxmRSoTgoVcMZsXJkBho'.
'SmKqCuOuEtls6nmGMFPTUmxBKx/MeyNfQGLoOOiC2ddsxb1Kzv'. 'SmKqCuOuEtls6nmGMFPTUmxBKx/MeyNfQGLoOOiC2ddsxb1Kzv'.
'ZzUqu5IXbGDvBJf+hDisi77qFSuhq7Xpuu66TyJLRGbsXVUPxV'. 'ZzUqu5IXbGDvBJf+hDisi77qFSuhq7Xpuu66TyJLRGbsXVUPxV'.
'SxsgkzDMt0mKT3/RcjL8C5hHnvJToXY0xYRZ4xnVKsV/S+a8YA'. 'SxsgkzDMt0mKT3/RcjL8C5hHnvJToXY0xYRZ4xnVKsV/S+a8YA'.
'AvCb3s9g13UhYj+TTo93B3fApRV1FVlEAD6H42DjN9/WvzDYuJ'. 'AvCb3s9g13UhYj+TTo93B3fApRV1FVlEAD6H42DjN9/WvzDYuJ'.
'dL5b1/ji+/IX8EGWP4AwRii8PdFHTqAAAAAElFTkSuQmCC' ; 'dL5b1/ji+/IX8EGWP4AwRii8PdFHTqAAAAAElFTkSuQmCC' ;
} }
} }
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: IMGDATA_SQUARES.INC // File: IMGDATA_SQUARES.INC
// Description: Base64 encoded images for squares // Description: Base64 encoded images for squares
// Created: 2003-03-20 // Created: 2003-03-20
// Ver: $Id: imgdata_squares.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: imgdata_squares.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class ImgData_Squares extends ImgData { class ImgData_Squares extends ImgData {
protected $name = 'Squares'; protected $name = 'Squares';
protected $an = array(MARK_IMG_SQUARE =>'imgdata'); protected $an = array(MARK_IMG_SQUARE =>'imgdata');
   
protected $colors = array('bluegreen','blue','green', protected $colors = array('bluegreen','blue','green',
'lightblue','orange','purple','red','yellow'); 'lightblue','orange','purple','red','yellow');
protected $index = array('bluegreen' =>2,'blue'=>5,'green'=>6, protected $index = array('bluegreen' =>2,'blue'=>5,'green'=>6,
'lightblue'=>0,'orange'=>7,'purple'=>4,'red'=>3,'yellow'=>1); 'lightblue'=>0,'orange'=>7,'purple'=>4,'red'=>3,'yellow'=>1);
protected $maxidx = 7 ; protected $maxidx = 7 ;
protected $imgdata ; protected $imgdata ;
   
function ImgData_Squares () { function ImgData_Squares () {
//========================================================== //==========================================================
//sq_lblue.png //sq_lblue.png
//========================================================== //==========================================================
$this->imgdata[0][0]= 362 ; $this->imgdata[0][0]= 362 ;
$this->imgdata[0][1]= $this->imgdata[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAABm'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAABm'.
'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'. 'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
'B3RJTUUH0wMLFgojiPx/ygAAAPdJREFUeNpj/P377+kzHx89/c'. 'B3RJTUUH0wMLFgojiPx/ygAAAPdJREFUeNpj/P377+kzHx89/c'.
'VAHNBQ5VBX52HavPWWjg6nnDQbkXoUFTnnL7zD9PPXrz17HxCj'. 'VAHNBQ5VBX52HavPWWjg6nnDQbkXoUFTnnL7zD9PPXrz17HxCj'.
'E6Jn6fL7H7/+ZWJgYCBGJ7IeBgYGJogofp1oehDa8OjE1IOiDa'. 'E6Jn6fL7H7/+ZWJgYCBGJ7IeBgYGJogofp1oehDa8OjE1IOiDa'.
'tOrHoYGBhY0NwD0enirMDAwMDFxYRVD7ptyDrNTAU0NXix6sGu'. 'tOrHoYGBhY0NwD0enirMDAwMDFxYRVD7ptyDrNTAU0NXix6sGu'.
'jYGBgZOT9e/f/0xMjFyczFgVsGAKCfBza2kKzpl3hIuT1c9Xb/'. 'jYGBgZOT9e/f/0xMjFyczFgVsGAKCfBza2kKzpl3hIuT1c9Xb/'.
'PW58/foKchJqx6tmy98vbjj8cvPm/afMnXW1JShA2fNmQ9EBFc'. 'PW58/foKchJqx6tmy98vbjj8cvPm/afMnXW1JShA2fNmQ9EBFc'.
'Opnw6MGjkwm/Hlw6mQjqwaqTiRg9mDoZv//4M2/+UYJ64EBWgj'. 'Opnw6MGjkwm/Hlw6mQjqwaqTiRg9mDoZv//4M2/+UYJ64EBWgj'.
'cm2hwA8l24oNDl+DMAAAAASUVORK5CYII=' ; 'cm2hwA8l24oNDl+DMAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
//sq_yellow.png //sq_yellow.png
//========================================================== //==========================================================
$this->imgdata[1][0]= 338 ; $this->imgdata[1][0]= 338 ;
$this->imgdata[1][1]= $this->imgdata[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAWl'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAWl'.
'BMVEX////+/+H+/9/9/9v8/8P8/8H8/7v8/7n6/4P5/335/3n5'. 'BMVEX////+/+H+/9/9/9v8/8P8/8H8/7v8/7n6/4P5/335/3n5'.
'/3X4/1f4/1P3/031/w30/wn0/wPt+ADp9ADm8ADk7gDc5gDa5A'. '/3X4/1f4/1P3/031/w30/wn0/wPt+ADp9ADm8ADk7gDc5gDa5A'.
'DL1ADFzgCwuACqsgClrABzeAC9M0MzAAAAAWJLR0QAiAUdSAAA'. 'DL1ADFzgCwuACqsgClrABzeAC9M0MzAAAAAWJLR0QAiAUdSAAA'.
'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEDlOgDj'. 'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEDlOgDj'.
'EAAAB+SURBVHjaVcpbCsQgDEDRGERGKopjDa2a/W9zfLWj9/Nw'. 'EAAAB+SURBVHjaVcpbCsQgDEDRGERGKopjDa2a/W9zfLWj9/Nw'.
'Ac21ZRBOtZlRN9ApzSYFaDUj79KIorRDbJNO9bN/GUSh2ZRJFJ'. 'Ac21ZRBOtZlRN9ApzSYFaDUj79KIorRDbJNO9bN/GUSh2ZRJFJ'.
'S18iorURBiyksO8buT0zkfYaUqzI91ckfhWhoGXTLzsDjI68Sz'. 'S18iorURBiyksO8buT0zkfYaUqzI91ckfhWhoGXTLzsDjI68Sz'.
'pGMjrzPzauA/iXk1AtykmvgBC8UcWUdc9HkAAAAASUVORK5CYI'. 'pGMjrzPzauA/iXk1AtykmvgBC8UcWUdc9HkAAAAASUVORK5CYI'.
'I=' ; 'I=' ;
   
//========================================================== //==========================================================
//sq_blgr.png //sq_blgr.png
//========================================================== //==========================================================
$this->imgdata[2][0]= 347 ; $this->imgdata[2][0]= 347 ;
$this->imgdata[2][1]= $this->imgdata[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAZl'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAZl'.
'BMVEX////0+vv0+vrz+fry+frv+Png7e/d7e/a6+zY6+250tSz'. 'BMVEX////0+vv0+vrz+fry+frv+Png7e/d7e/a6+zY6+250tSz'.
'0tSyztCtztGM0NWIz9SDzdNfsLVcrrRZrbJOp61MpqtIr7dHn6'. '0tSyztCtztGM0NWIz9SDzdNfsLVcrrRZrbJOp61MpqtIr7dHn6'.
'RErrZArLQ6q7M2g4kygYcsp68npa4ctr8QZ20JnqepKsl4AAAA'. 'RErrZArLQ6q7M2g4kygYcsp68npa4ctr8QZ20JnqepKsl4AAAA'.
'AWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU'. 'AWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU'.
'1FB9MDCxYEByp8tpUAAAB7SURBVHjaVcjRFoIgDADQWZpWJpjY'. '1FB9MDCxYEByp8tpUAAAB7SURBVHjaVcjRFoIgDADQWZpWJpjY'.
'MsnG//9kzIFn3McLzfArDA3MndFjrhvgfDHFBEB9pt0CVzwrY3'. 'MsnG//9kzIFn3McLzfArDA3MndFjrhvgfDHFBEB9pt0CVzwrY3'.
'n2yicjhY4vTSp0nbXtN+hCV53SHDWe61dZY+/9463r2XuifHAM'. 'n2yicjhY4vTSp0nbXtN+hCV53SHDWe61dZY+/9463r2XuifHAM'.
'0SoH+6xEcovUlCfefeFSIwfTTQ3fB+pi4lV/bTIgvmaA7a0AAA'. '0SoH+6xEcovUlCfefeFSIwfTTQ3fB+pi4lV/bTIgvmaA7a0AAA'.
'AASUVORK5CYII=' ; 'AASUVORK5CYII=' ;
   
//========================================================== //==========================================================
//sq_red.png //sq_red.png
//========================================================== //==========================================================
$this->imgdata[3][0]= 324 ; $this->imgdata[3][0]= 324 ;
$this->imgdata[3][1]= $this->imgdata[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'.
'BMVEX////++Pn99/j99ff99fb98/X98/T98PL55uj43+P24+bw'. 'BMVEX////++Pn99/j99ff99fb98/X98/T98PL55uj43+P24+bw'.
'kKPvjaHviJ3teJHpxMnoL2Pjs73WW3rWNljVWXnUVnbUK1DTJk'. 'kKPvjaHviJ3teJHpxMnoL2Pjs73WW3rWNljVWXnUVnbUK1DTJk'.
'3SUHPOBz/KQmmxPVmuOFasNFOeIkWVka/fAAAAAWJLR0QAiAUd'. '3SUHPOBz/KQmmxPVmuOFasNFOeIkWVka/fAAAAAWJLR0QAiAUd'.
'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEHd'. 'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEHd'.
'ceT+8AAABtSURBVHjaVchbAkMwEAXQq6i3VrQiQfa/zDYTw8z5'. 'ceT+8AAABtSURBVHjaVchbAkMwEAXQq6i3VrQiQfa/zDYTw8z5'.
'PCjGt9JVWFt1XWPh1fWNdfDy+tq6WPfRUPENNKnSnXNWPB4uv2'. 'PCjGt9JVWFt1XWPh1fWNdfDy+tq6WPfRUPENNKnSnXNWPB4uv2'.
'b54nSZ8jHrMtOxvWZZZtpD4KP6xLkO9/AhzhaCOMhJh68cOjzV'. 'b54nSZ8jHrMtOxvWZZZtpD4KP6xLkO9/AhzhaCOMhJh68cOjzV'.
'/K/4Ac2cG+nBcaRuAAAAAElFTkSuQmCC' ; '/K/4Ac2cG+nBcaRuAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
//sq_pink.png //sq_pink.png
//========================================================== //==========================================================
$this->imgdata[4][0]= 445 ; $this->imgdata[4][0]= 445 ;
$this->imgdata[4][1]= $this->imgdata[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAApV'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAApV'.
'BMVEX////6+Pz69/v49Pr38/r17/jr4+/l3Onj2efh1ua/L+i+'. 'BMVEX////6+Pz69/v49Pr38/r17/jr4+/l3Onj2efh1ua/L+i+'.
'q8m+Lue9Lua8qsS8LuW8LeS7pca5LOG4LN+2Y9O2YNW1ZdO1Kt'. 'q8m+Lue9Lua8qsS8LuW8LeS7pca5LOG4LN+2Y9O2YNW1ZdO1Kt'.
'y0atC0aNGzb82zbc6zKtuzKdqycsuwa8qtJtOISZ2GRpuFN6GE'. 'y0atC0aNGzb82zbc6zKtuzKdqycsuwa8qtJtOISZ2GRpuFN6GE'.
'NqCDQpmCMZ+BPpd/LJ1/K519S5B9Jpx9Jpt9JZt6RY11BJZ1BJ'. 'NqCDQpmCMZ+BPpd/LJ1/K519S5B9Jpx9Jpt9JZt6RY11BJZ1BJ'.
'V0BJV0BJRzBJNvNoRtIoJUEmdZ/XbrAAAAAWJLR0QAiAUdSAAA'. 'V0BJV0BJRzBJNvNoRtIoJUEmdZ/XbrAAAAAWJLR0QAiAUdSAAA'.
'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYDF3iKMD'. 'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYDF3iKMD'.
'YAAACeSURBVHjaVczbEoIgGARgCiMtrexoWpaa2FHUgvd/tH4Y'. 'YAAACeSURBVHjaVczbEoIgGARgCiMtrexoWpaa2FHUgvd/tH4Y'.
'BnEvv9ldhNPradPnnGBUTtPDzMRPSIF46SaBoR25dYjz3I20Lb'. 'BnEvv9ldhNPradPnnGBUTtPDzMRPSIF46SaBoR25dYjz3I20Lb'.
'ek6BgQz73Il7KKpSgCO0pTHU0886J1sCe0ZYbALjGhjFnEM2es'. 'ek6BgQz73Il7KKpSgCO0pTHU0886J1sCe0ZYbALjGhjFnEM2es'.
'VhZVI4d+B1QtfnV47ywCEaKeP/p7JdLejSYt0j6NIiOq1wJZIs'. 'VhZVI4d+B1QtfnV47ywCEaKeP/p7JdLejSYt0j6NIiOq1wJZIs'.
'QTDA0ELHwhPBCwyR/Cni9cOmzJtwAAAABJRU5ErkJggg==' ; 'QTDA0ELHwhPBCwyR/Cni9cOmzJtwAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
//sq_blue.png //sq_blue.png
//========================================================== //==========================================================
$this->imgdata[5][0]= 283 ; $this->imgdata[5][0]= 283 ;
$this->imgdata[5][1]= $this->imgdata[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAQl'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAQl'.
'BMVEX////4+fz39/z19vvy8vru7/ni4+7g4fHW1ue8vteXmt6B'. 'BMVEX////4+fz39/z19vvy8vru7/ni4+7g4fHW1ue8vteXmt6B'.
'hdhiZ7FQVaZETcxCSJo1Oq4zNoMjKakhJHcKFaMEC2jRVYdWAA'. 'hdhiZ7FQVaZETcxCSJo1Oq4zNoMjKakhJHcKFaMEC2jRVYdWAA'.
'AAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0'. 'AAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0'.
'SU1FB9MDCxYDN0PkEP4AAABfSURBVHjaVchHAoAgDATAVcCCIF'. 'SU1FB9MDCxYDN0PkEP4AAABfSURBVHjaVchHAoAgDATAVcCCIF'.
'j4/1elJEjmOFDHKVgDv4iz640gLs+LMF6ZUv/VqcXXplU7Gqpy'. 'j4/1elJEjmOFDHKVgDv4iz640gLs+LMF6ZUv/VqcXXplU7Gqpy'.
'PFzBT5qml9NzlOX259riWHlS4kOffviHD8PQYZx2EFMPRkw+9Q'. 'PFzBT5qml9NzlOX259riWHlS4kOffviHD8PQYZx2EFMPRkw+9Q'.
'FSnRPeWEDzKAAAAABJRU5ErkJggg==' ; 'FSnRPeWEDzKAAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
//sq_green.png //sq_green.png
//========================================================== //==========================================================
$this->imgdata[6][0]= 325 ; $this->imgdata[6][0]= 325 ;
$this->imgdata[6][1]= $this->imgdata[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'.
'BMVEX////2+vX1+vX1+fT0+fPz+PPx9/Dv9u7u9e3h7uHe697a'. 'BMVEX////2+vX1+vX1+fT0+fPz+PPx9/Dv9u7u9e3h7uHe697a'.
'6dnO2s3I1sa10LOvza2ay5aEwYBWlE9TqE5Tkk1RkEpMrUJMg0'. '6dnO2s3I1sa10LOvza2ay5aEwYBWlE9TqE5Tkk1RkEpMrUJMg0'.
'hKiUNGpEFBojw8oTcsbScaYBMWlwmMT0NtAAAAAWJLR0QAiAUd'. 'hKiUNGpEFBojw8oTcsbScaYBMWlwmMT0NtAAAAAWJLR0QAiAUd'.
'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEFd'. 'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEFd'.
'nFx90AAABuSURBVHjaVc9HAoAgDADB2HuJWLDx/2cKBITscW4L'. 'nFx90AAABuSURBVHjaVc9HAoAgDADB2HuJWLDx/2cKBITscW4L'.
'5byzMIWtZobNDZIZtrcCGZsRQ8GwvRSRNxIiMuysODKG3alikl'. '5byzMIWtZobNDZIZtrcCGZsRQ8GwvRSRNxIiMuysODKG3alikl'.
'ueOPlpKTLBaRmOZxQxaXlfb5ZWI9om4WntrXiDSJzp7SBkwMQa'. 'ueOPlpKTLBaRmOZxQxaXlfb5ZWI9om4WntrXiDSJzp7SBkwMQa'.
'FEy0VR/NAB2kNuj7rgAAAABJRU5ErkJggg==' ; 'FEy0VR/NAB2kNuj7rgAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
//sq_orange.png //sq_orange.png
//========================================================== //==========================================================
$this->imgdata[7][0]= 321 ; $this->imgdata[7][0]= 321 ;
$this->imgdata[7][1]= $this->imgdata[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAUV'. 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAUV'.
'BMVEX/////8+n/8uf/8OP/59H/5Mv/zqH/zJ3/ypv/yJf/vYH/'. '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'. 'u33/uXn/n0n/nUX/m0H/lzn/ljf/lDP/kS3/kCv/iR//hxv/fg'.
'n/fAX/eQDYZgDW6ia5AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAL'. 'n/fAX/eQDYZgDW6ia5AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAL'.
'EgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEJIgbx+cAAAB2SURBVH'. 'EgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEJIgbx+cAAAB2SURBVH'.
'jaVczRCoQwDETRbLAWLZSGUA35/w/dVI0283i4DODew3YESmWW'. 'jaVczRCoQwDETRbLAWLZSGUA35/w/dVI0283i4DODew3YESmWW'.
'kg5gWkoQAe6TleUQI/66Sy7i56+kLk7cht2N0+hcnJgQu0SqiC'. 'kg5gWkoQAe6TleUQI/66Sy7i56+kLk7cht2N0+hcnJgQu0SqiC'.
'1SzSIbzWSi6gavqJ63wSduRi2f+kwyD5rEukwCdZ1kGAMGMfv9'. '1SzSIbzWSi6gavqJ63wSduRi2f+kwyD5rEukwCdZ1kGAMGMfv9'.
'AbWuGMOr5COSAAAAAElFTkSuQmCC' ; 'AbWuGMOr5COSAAAAAElFTkSuQmCC' ;
} }
} }
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: IMGDATA_STARS.INC // File: IMGDATA_STARS.INC
// Description: Base64 encoded images for stars // Description: Base64 encoded images for stars
// Created: 2003-03-20 // Created: 2003-03-20
// Ver: $Id: imgdata_stars.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: imgdata_stars.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
class ImgData_Stars extends ImgData { class ImgData_Stars extends ImgData {
protected $name = 'Stars'; protected $name = 'Stars';
protected $an = array(MARK_IMG_STAR => 'imgdata'); protected $an = array(MARK_IMG_STAR => 'imgdata');
   
protected $colors = array('bluegreen','lightblue','purple','blue','green','pink','red','yellow'); protected $colors = array('bluegreen','lightblue','purple','blue','green','pink','red','yellow');
protected $index = array('bluegreen'=>3,'lightblue'=>4,'purple'=>1, protected $index = array('bluegreen'=>3,'lightblue'=>4,'purple'=>1,
'blue'=>5,'green'=>0,'pink'=>7,'red'=>2,'yellow'=>6); 'blue'=>5,'green'=>0,'pink'=>7,'red'=>2,'yellow'=>6);
protected $maxidx = 7 ; protected $maxidx = 7 ;
protected $imgdata ; protected $imgdata ;
   
function __construct() { function __construct() {
//========================================================== //==========================================================
// File: bstar_green_001.png // File: bstar_green_001.png
//========================================================== //==========================================================
$this->imgdata[0][0]= 329 ; $this->imgdata[0][0]= 329 ;
$this->imgdata[0][1]= $this->imgdata[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAAUV'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAAUV'.
'BMVEX///////+/v7+83rqcyY2Q/4R7/15y/1tp/05p/0lg/zdX'. 'BMVEX///////+/v7+83rqcyY2Q/4R7/15y/1tp/05p/0lg/zdX'.
'/zdX/zVV/zdO/zFJ9TFJvDFD4yg+8Bw+3iU68hwurhYotxYosx'. '/zdX/zVV/zdO/zFJ9TFJvDFD4yg+8Bw+3iU68hwurhYotxYosx'.
'YokBoTfwANgQFUp7DWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'. 'YokBoTfwANgQFUp7DWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJj'. 'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJj'.
'CRyxgTAAAAcUlEQVR4nH3MSw6AIAwEUBL/IKBWwXL/g0pLojUS'. 'CRyxgTAAAAcUlEQVR4nH3MSw6AIAwEUBL/IKBWwXL/g0pLojUS'.
'ZzGLl8ko9Zumhr5iy66/GH0dp49llNPB5sTotDY5PVuLG6tnM9'. 'ZzGLl8ko9Zumhr5iy66/GH0dp49llNPB5sTotDY5PVuLG6tnM9'.
'CVKSIe1joSgPsAKSuANNaENFQvTAGzmheSkUpMBWeJZwqBT8wo'. 'CVKSIe1joSgPsAKSuANNaENFQvTAGzmheSkUpMBWeJZwqBT8wo'.
'hmysD4bnnPsC/x8ItUdGPfAAAAAASUVORK5CYII=' ; 'hmysD4bnnPsC/x8ItUdGPfAAAAAASUVORK5CYII=' ;
//========================================================== //==========================================================
// File: bstar_blred.png // File: bstar_blred.png
//========================================================== //==========================================================
$this->imgdata[1][0]= 325 ; $this->imgdata[1][0]= 325 ;
$this->imgdata[1][1]= $this->imgdata[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v79uRJ6jWPOSUtKrb+ejWO+gWPaGTruJTr6rZvF2'. 'BMVEX///+/v79uRJ6jWPOSUtKrb+ejWO+gWPaGTruJTr6rZvF2'.
'RqC2ocqdVuCeV+egV/GsnLuIXL66rMSpcOyATbipY/OdWOp+VK'. 'RqC2ocqdVuCeV+egV/GsnLuIXL66rMSpcOyATbipY/OdWOp+VK'.
'aTU9WhV+yJKBoLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'aTU9WhV+yJKBoLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJwynv1'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJwynv1'.
'XVAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'XVAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bstar_red_001.png // File: bstar_red_001.png
//========================================================== //==========================================================
$this->imgdata[2][0]= 325 ; $this->imgdata[2][0]= 325 ;
$this->imgdata[2][1]= $this->imgdata[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v7+eRFHzWG3SUmHnb37vWGr2WHG7Tlm+TljxZneg'. 'BMVEX///+/v7+eRFHzWG3SUmHnb37vWGr2WHG7Tlm+TljxZneg'.
'Rk3KoaXgVmXnV2nxV227nJ++XGzErK3scIS4TVzzY3fqWG2mVF'. 'Rk3KoaXgVmXnV2nxV227nJ++XGzErK3scIS4TVzzY3fqWG2mVF'.
'zVU2PsV2rJFw9VAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'zVU2PsV2rJFw9VAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJzCI0C'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJzCI0C'.
'lSAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'lSAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bstar_blgr_001.png // File: bstar_blgr_001.png
//========================================================== //==========================================================
$this->imgdata[3][0]= 325 ; $this->imgdata[3][0]= 325 ;
$this->imgdata[3][1]= $this->imgdata[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v79Ehp5Yx/NSq9Jvw+dYwu9YzfZOmbtOmb5myPFG'. 'BMVEX///+/v79Ehp5Yx/NSq9Jvw+dYwu9YzfZOmbtOmb5myPFG'.
'gqChvcpWteBXvedXxvGcsbtcpb6su8RwzOxNmrhjyvNYwupUjK'. 'gqChvcpWteBXvedXxvGcsbtcpb6su8RwzOxNmrhjyvNYwupUjK'.
'ZTr9VXwOyJhmWNAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'ZTr9VXwOyJhmWNAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJTC65k'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJTC65k'.
'vQAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'vQAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bstar_blgr_002.png // File: bstar_blgr_002.png
//========================================================== //==========================================================
$this->imgdata[4][0]= 325 ; $this->imgdata[4][0]= 325 ;
$this->imgdata[4][1]= $this->imgdata[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v79EnpxY8/FS0dJv5+dY7+9Y9vBOubtOur5m8fFG'. 'BMVEX///+/v79EnpxY8/FS0dJv5+dY7+9Y9vBOubtOur5m8fFG'.
'nKChycpW3uBX5+ZX8e2curtcvrqswsRw7OdNuLZj8/BY6udUpK'. 'nKChycpW3uBX5+ZX8e2curtcvrqswsRw7OdNuLZj8/BY6udUpK'.
'ZT1dRX7OtNkrW5AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'ZT1dRX7OtNkrW5AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJgXHeN'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJgXHeN'.
'wwAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'wwAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bstar_blue_001.png // File: bstar_blue_001.png
//========================================================== //==========================================================
$this->imgdata[5][0]= 325 ; $this->imgdata[5][0]= 325 ;
$this->imgdata[5][1]= $this->imgdata[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v79EY55Yi/NSetJvledYiO9YkPZOb7tObr5mkvFG'. 'BMVEX///+/v79EY55Yi/NSetJvledYiO9YkPZOb7tObr5mkvFG'.
'X6ChrcpWgOBXhedXi/Gcpbtcf76sssRwnOxNcbhjk/NYiepUbK'. 'X6ChrcpWgOBXhedXi/Gcpbtcf76sssRwnOxNcbhjk/NYiepUbK'.
'ZTfdVXh+ynNEzzAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'ZTfdVXh+ynNEzzAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJhStyP'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJhStyP'.
'zCAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'zCAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bstar_oy_007.png // File: bstar_oy_007.png
//========================================================== //==========================================================
$this->imgdata[6][0]= 325 ; $this->imgdata[6][0]= 325 ;
$this->imgdata[6][1]= $this->imgdata[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v7+ejUTz11jSvVLn02/v1lj21li7q06+r07x2mag'. 'BMVEX///+/v7+ejUTz11jSvVLn02/v1lj21li7q06+r07x2mag'.
'lUbKxKHgy1bnz1fx1Ve7t5y+qlzEwqzs03C4pE3z2WPqz1imml'. 'lUbKxKHgy1bnz1fx1Ve7t5y+qlzEwqzs03C4pE3z2WPqz1imml'.
'TVv1Ps01dGRjeyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'TVv1Ps01dGRjeyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJjsGGc'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJjsGGc'.
'GbAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'GbAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// File: bstar_lred.png // File: bstar_lred.png
//========================================================== //==========================================================
$this->imgdata[7][0]= 325 ; $this->imgdata[7][0]= 325 ;
$this->imgdata[7][1]= $this->imgdata[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'. 'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
'BMVEX///+/v7+eRJPzWN3SUr7nb9TvWNj2WOS7Tqi+TqnxZtyg'. 'BMVEX///+/v7+eRJPzWN3SUr7nb9TvWNj2WOS7Tqi+TqnxZtyg'.
'Ro/KocPgVsjnV9LxV927nLa+XLTErL7scN24TarzY9/qWNemVJ'. 'Ro/KocPgVsjnV9LxV927nLa+XLTErL7scN24TarzY9/qWNemVJ'.
'jVU8LsV9VCwcc9AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'. 'jVU8LsV9VCwcc9AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJxi9ZY'. 'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJxi9ZY'.
'GoAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'. 'GoAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'. 'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'. 'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ; 'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
} }
} }
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: JPG-CONFIG.INC // File: JPG-CONFIG.INC
// Description: Configuration file for JpGraph library // Description: Configuration file for JpGraph library
// Created: 2004-03-27 // Created: 2004-03-27
// Ver: $Id: jpg-config.inc.php 1871 2009-09-29 05:56:39Z ljp $ // Ver: $Id: jpg-config.inc.php 1871 2009-09-29 05:56:39Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Directories for cache and font directory. // Directories for cache and font directory.
// //
// CACHE_DIR: // CACHE_DIR:
// The full absolute name of the directory to be used to store the // The full absolute name of the directory to be used to store the
// cached image files. This directory will not be used if the USE_CACHE // cached image files. This directory will not be used if the USE_CACHE
// define (further down) is false. If you enable the cache please note that // define (further down) is false. If you enable the cache please note that
// this directory MUST be readable and writable for the process running PHP. // this directory MUST be readable and writable for the process running PHP.
// Must end with '/' // Must end with '/'
// //
// TTF_DIR: // TTF_DIR:
// Directory where TTF fonts can be found. Must end with '/' // Directory where TTF fonts can be found. Must end with '/'
// //
// The default values used if these defines are left commented out are: // The default values used if these defines are left commented out are:
// //
// UNIX: // UNIX:
// CACHE_DIR /tmp/jpgraph_cache/ // CACHE_DIR /tmp/jpgraph_cache/
// TTF_DIR /usr/share/fonts/truetype/ // TTF_DIR /usr/share/fonts/truetype/
// MBTTF_DIR /usr/share/fonts/truetype/ // MBTTF_DIR /usr/share/fonts/truetype/
// //
// WINDOWS: // WINDOWS:
// CACHE_DIR $SERVER_TEMP/jpgraph_cache/ // CACHE_DIR $SERVER_TEMP/jpgraph_cache/
// TTF_DIR $SERVER_SYSTEMROOT/fonts/ // TTF_DIR $SERVER_SYSTEMROOT/fonts/
// MBTTF_DIR $SERVER_SYSTEMROOT/fonts/ // MBTTF_DIR $SERVER_SYSTEMROOT/fonts/
// //
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// define('CACHE_DIR','/tmp/jpgraph_cache/'); // define('CACHE_DIR','/tmp/jpgraph_cache/');
// define('TTF_DIR','/usr/share/fonts/truetype/'); // define('TTF_DIR','/usr/share/fonts/truetype/');
// define('MBTTF_DIR','/usr/share/fonts/truetype/'); // define('MBTTF_DIR','/usr/share/fonts/truetype/');
   
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Cache directory specification for use with CSIM graphs that are // Cache directory specification for use with CSIM graphs that are
// using the cache. // using the cache.
// The directory must be the filesysystem name as seen by PHP // The directory must be the filesysystem name as seen by PHP
// and the 'http' version must be the same directory but as // and the 'http' version must be the same directory but as
// seen by the HTTP server relative to the 'htdocs' ddirectory. // seen by the HTTP server relative to the 'htdocs' ddirectory.
// If a relative path is specified it is taken to be relative from where // If a relative path is specified it is taken to be relative from where
// the image script is executed. // the image script is executed.
// Note: The default setting is to create a subdirectory in the // Note: The default setting is to create a subdirectory in the
// directory from where the image script is executed and store all files // directory from where the image script is executed and store all files
// there. As ususal this directory must be writeable by the PHP process. // there. As ususal this directory must be writeable by the PHP process.
define('CSIMCACHE_DIR','csimcache/'); define('CSIMCACHE_DIR','csimcache/');
define('CSIMCACHE_HTTP_DIR','csimcache/'); define('CSIMCACHE_HTTP_DIR','csimcache/');
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Various JpGraph Settings. Adjust accordingly to your // Various JpGraph Settings. Adjust accordingly to your
// preferences. Note that cache functionality is turned off by // preferences. Note that cache functionality is turned off by
// default (Enable by setting USE_CACHE to true) // default (Enable by setting USE_CACHE to true)
//------------------------------------------------------------------------ //------------------------------------------------------------------------
   
// Deafult locale for error messages. // Deafult locale for error messages.
// This defaults to English = 'en' // This defaults to English = 'en'
define('DEFAULT_ERR_LOCALE','en'); define('DEFAULT_ERR_LOCALE','en');
   
// Deafult graphic format set to 'auto' which will automatically // Deafult graphic format set to 'auto' which will automatically
// choose the best available format in the order png,gif,jpeg // choose the best available format in the order png,gif,jpeg
// (The supported format depends on what your PHP installation supports) // (The supported format depends on what your PHP installation supports)
define('DEFAULT_GFORMAT','auto'); define('DEFAULT_GFORMAT','auto');
   
// Should the cache be used at all? By setting this to false no // Should the cache be used at all? By setting this to false no
// files will be generated in the cache directory. // files will be generated in the cache directory.
// The difference from READ_CACHE being that setting READ_CACHE to // The difference from READ_CACHE being that setting READ_CACHE to
// false will still create the image in the cache directory // false will still create the image in the cache directory
// just not use it. By setting USE_CACHE=false no files will even // just not use it. By setting USE_CACHE=false no files will even
// be generated in the cache directory. // be generated in the cache directory.
define('USE_CACHE',false); define('USE_CACHE',false);
   
// Should we try to find an image in the cache before generating it? // Should we try to find an image in the cache before generating it?
// Set this define to false to bypass the reading of the cache and always // Set this define to false to bypass the reading of the cache and always
// regenerate the image. Note that even if reading the cache is // regenerate the image. Note that even if reading the cache is
// disabled the cached will still be updated with the newly generated // disabled the cached will still be updated with the newly generated
// image. Set also 'USE_CACHE' below. // image. Set also 'USE_CACHE' below.
define('READ_CACHE',true); define('READ_CACHE',true);
   
// Determine if the error handler should be image based or purely // Determine if the error handler should be image based or purely
// text based. Image based makes it easier since the script will // text based. Image based makes it easier since the script will
// always return an image even in case of errors. // always return an image even in case of errors.
define('USE_IMAGE_ERROR_HANDLER',true); define('USE_IMAGE_ERROR_HANDLER',true);
   
// Should the library examine the global php_errmsg string and convert // Should the library examine the global php_errmsg string and convert
// any error in it to a graphical representation. This is handy for the // any error in it to a graphical representation. This is handy for the
// occasions when, for example, header files cannot be found and this results // occasions when, for example, header files cannot be found and this results
// in the graph not being created and just a 'red-cross' image would be seen. // in the graph not being created and just a 'red-cross' image would be seen.
// This should be turned off for a production site. // This should be turned off for a production site.
define('CATCH_PHPERRMSG',true); define('CATCH_PHPERRMSG',true);
   
// Determine if the library should also setup the default PHP // Determine if the library should also setup the default PHP
// error handler to generate a graphic error mesage. This is useful // error handler to generate a graphic error mesage. This is useful
// during development to be able to see the error message as an image // during development to be able to see the error message as an image
// instead as a 'red-cross' in a page where an image is expected. // instead as a 'red-cross' in a page where an image is expected.
define('INSTALL_PHP_ERR_HANDLER',false); define('INSTALL_PHP_ERR_HANDLER',false);
   
// Should usage of deprecated functions and parameters give a fatal error? // Should usage of deprecated functions and parameters give a fatal error?
// (Useful to check if code is future proof.) // (Useful to check if code is future proof.)
define('ERR_DEPRECATED',true); define('ERR_DEPRECATED',true);
   
// The builtin GD function imagettfbbox() fuction which calculates the bounding box for // The builtin GD function imagettfbbox() fuction which calculates the bounding box for
// text using TTF fonts is buggy. By setting this define to true the library // text using TTF fonts is buggy. By setting this define to true the library
// uses its own compensation for this bug. However this will give a // uses its own compensation for this bug. However this will give a
// slightly different visual apparance than not using this compensation. // slightly different visual apparance than not using this compensation.
// Enabling this compensation will in general give text a bit more space to more // Enabling this compensation will in general give text a bit more space to more
// truly reflect the actual bounding box which is a bit larger than what the // truly reflect the actual bounding box which is a bit larger than what the
// GD function thinks. // GD function thinks.
define('USE_LIBRARY_IMAGETTFBBOX',true); define('USE_LIBRARY_IMAGETTFBBOX',true);
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// The following constants should rarely have to be changed ! // The following constants should rarely have to be changed !
//------------------------------------------------------------------------ //------------------------------------------------------------------------
   
// What group should the cached file belong to // What group should the cached file belong to
// (Set to '' will give the default group for the 'PHP-user') // (Set to '' will give the default group for the 'PHP-user')
// Please note that the Apache user must be a member of the // Please note that the Apache user must be a member of the
// specified group since otherwise it is impossible for Apache // specified group since otherwise it is impossible for Apache
// to set the specified group. // to set the specified group.
define('CACHE_FILE_GROUP','www'); define('CACHE_FILE_GROUP','www');
   
// What permissions should the cached file have // What permissions should the cached file have
// (Set to '' will give the default persmissions for the 'PHP-user') // (Set to '' will give the default persmissions for the 'PHP-user')
define('CACHE_FILE_MOD',0664); define('CACHE_FILE_MOD',0664);
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH.PHP // File: JPGRAPH.PHP
// Description: PHP Graph Plotting library. Base module. // Description: PHP Graph Plotting library. Base module.
// Created: 2001-01-08 // Created: 2001-01-08
// Ver: $Id: jpgraph.php 1912 2009-10-10 10:26:03Z ljp $ // Ver: $Id: jpgraph.php 1912 2009-10-10 10:26:03Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
require_once('jpg-config.inc.php'); require_once('jpg-config.inc.php');
require_once('jpgraph_gradient.php'); require_once('jpgraph_gradient.php');
require_once('jpgraph_errhandler.inc.php'); require_once('jpgraph_errhandler.inc.php');
require_once('jpgraph_ttf.inc.php'); require_once('jpgraph_ttf.inc.php');
require_once('jpgraph_rgb.inc.php'); require_once('jpgraph_rgb.inc.php');
require_once('jpgraph_text.inc.php'); require_once('jpgraph_text.inc.php');
require_once('jpgraph_legend.inc.php'); require_once('jpgraph_legend.inc.php');
require_once('gd_image.inc.php'); require_once('gd_image.inc.php');
   
// Version info // Version info
define('JPG_VERSION','3.0.6'); define('JPG_VERSION','3.0.6');
   
// Minimum required PHP version // Minimum required PHP version
define('MIN_PHPVERSION','5.1.0'); define('MIN_PHPVERSION','5.1.0');
   
// Special file name to indicate that we only want to calc // Special file name to indicate that we only want to calc
// the image map in the call to Graph::Stroke() used // the image map in the call to Graph::Stroke() used
// internally from the GetHTMLCSIM() method. // internally from the GetHTMLCSIM() method.
define('_CSIM_SPECIALFILE','_csim_special_'); define('_CSIM_SPECIALFILE','_csim_special_');
   
// HTTP GET argument that is used with image map // HTTP GET argument that is used with image map
// to indicate to the script to just generate the image // to indicate to the script to just generate the image
// and not the full CSIM HTML page. // and not the full CSIM HTML page.
define('_CSIM_DISPLAY','_jpg_csimd'); define('_CSIM_DISPLAY','_jpg_csimd');
   
// Special filename for Graph::Stroke(). If this filename is given // Special filename for Graph::Stroke(). If this filename is given
// then the image will NOT be streamed to browser of file. Instead the // then the image will NOT be streamed to browser of file. Instead the
// Stroke call will return the handler for the created GD image. // Stroke call will return the handler for the created GD image.
define('_IMG_HANDLER','__handle'); define('_IMG_HANDLER','__handle');
   
// Special filename for Graph::Stroke(). If this filename is given // Special filename for Graph::Stroke(). If this filename is given
// the image will be stroked to a file with a name based on the script name. // the image will be stroked to a file with a name based on the script name.
define('_IMG_AUTO','auto'); define('_IMG_AUTO','auto');
   
// Tick density // Tick density
define("TICKD_DENSE",1); define("TICKD_DENSE",1);
define("TICKD_NORMAL",2); define("TICKD_NORMAL",2);
define("TICKD_SPARSE",3); define("TICKD_SPARSE",3);
define("TICKD_VERYSPARSE",4); define("TICKD_VERYSPARSE",4);
   
// Side for ticks and labels. // Side for ticks and labels.
define("SIDE_LEFT",-1); define("SIDE_LEFT",-1);
define("SIDE_RIGHT",1); define("SIDE_RIGHT",1);
define("SIDE_DOWN",-1); define("SIDE_DOWN",-1);
define("SIDE_BOTTOM",-1); define("SIDE_BOTTOM",-1);
define("SIDE_UP",1); define("SIDE_UP",1);
define("SIDE_TOP",1); define("SIDE_TOP",1);
   
// Legend type stacked vertical or horizontal // Legend type stacked vertical or horizontal
define("LEGEND_VERT",0); define("LEGEND_VERT",0);
define("LEGEND_HOR",1); define("LEGEND_HOR",1);
   
// Mark types for plot marks // Mark types for plot marks
define("MARK_SQUARE",1); define("MARK_SQUARE",1);
define("MARK_UTRIANGLE",2); define("MARK_UTRIANGLE",2);
define("MARK_DTRIANGLE",3); define("MARK_DTRIANGLE",3);
define("MARK_DIAMOND",4); define("MARK_DIAMOND",4);
define("MARK_CIRCLE",5); define("MARK_CIRCLE",5);
define("MARK_FILLEDCIRCLE",6); define("MARK_FILLEDCIRCLE",6);
define("MARK_CROSS",7); define("MARK_CROSS",7);
define("MARK_STAR",8); define("MARK_STAR",8);
define("MARK_X",9); define("MARK_X",9);
define("MARK_LEFTTRIANGLE",10); define("MARK_LEFTTRIANGLE",10);
define("MARK_RIGHTTRIANGLE",11); define("MARK_RIGHTTRIANGLE",11);
define("MARK_FLASH",12); define("MARK_FLASH",12);
define("MARK_IMG",13); define("MARK_IMG",13);
define("MARK_FLAG1",14); define("MARK_FLAG1",14);
define("MARK_FLAG2",15); define("MARK_FLAG2",15);
define("MARK_FLAG3",16); define("MARK_FLAG3",16);
define("MARK_FLAG4",17); define("MARK_FLAG4",17);
   
// Builtin images // Builtin images
define("MARK_IMG_PUSHPIN",50); define("MARK_IMG_PUSHPIN",50);
define("MARK_IMG_SPUSHPIN",50); define("MARK_IMG_SPUSHPIN",50);
define("MARK_IMG_LPUSHPIN",51); define("MARK_IMG_LPUSHPIN",51);
define("MARK_IMG_DIAMOND",52); define("MARK_IMG_DIAMOND",52);
define("MARK_IMG_SQUARE",53); define("MARK_IMG_SQUARE",53);
define("MARK_IMG_STAR",54); define("MARK_IMG_STAR",54);
define("MARK_IMG_BALL",55); define("MARK_IMG_BALL",55);
define("MARK_IMG_SBALL",55); define("MARK_IMG_SBALL",55);
define("MARK_IMG_MBALL",56); define("MARK_IMG_MBALL",56);
define("MARK_IMG_LBALL",57); define("MARK_IMG_LBALL",57);
define("MARK_IMG_BEVEL",58); define("MARK_IMG_BEVEL",58);
   
// Inline defines // Inline defines
define("INLINE_YES",1); define("INLINE_YES",1);
define("INLINE_NO",0); define("INLINE_NO",0);
   
// Format for background images // Format for background images
define("BGIMG_FILLPLOT",1); define("BGIMG_FILLPLOT",1);
define("BGIMG_FILLFRAME",2); define("BGIMG_FILLFRAME",2);
define("BGIMG_COPY",3); define("BGIMG_COPY",3);
define("BGIMG_CENTER",4); define("BGIMG_CENTER",4);
define("BGIMG_FREE",5); define("BGIMG_FREE",5);
   
// Depth of objects // Depth of objects
define("DEPTH_BACK",0); define("DEPTH_BACK",0);
define("DEPTH_FRONT",1); define("DEPTH_FRONT",1);
   
// Direction // Direction
define("VERTICAL",1); define("VERTICAL",1);
define("HORIZONTAL",0); define("HORIZONTAL",0);
   
// Axis styles for scientific style axis // Axis styles for scientific style axis
define('AXSTYLE_SIMPLE',1); define('AXSTYLE_SIMPLE',1);
define('AXSTYLE_BOXIN',2); define('AXSTYLE_BOXIN',2);
define('AXSTYLE_BOXOUT',3); define('AXSTYLE_BOXOUT',3);
define('AXSTYLE_YBOXIN',4); define('AXSTYLE_YBOXIN',4);
define('AXSTYLE_YBOXOUT',5); define('AXSTYLE_YBOXOUT',5);
   
// Style for title backgrounds // Style for title backgrounds
define('TITLEBKG_STYLE1',1); define('TITLEBKG_STYLE1',1);
define('TITLEBKG_STYLE2',2); define('TITLEBKG_STYLE2',2);
define('TITLEBKG_STYLE3',3); define('TITLEBKG_STYLE3',3);
define('TITLEBKG_FRAME_NONE',0); define('TITLEBKG_FRAME_NONE',0);
define('TITLEBKG_FRAME_FULL',1); define('TITLEBKG_FRAME_FULL',1);
define('TITLEBKG_FRAME_BOTTOM',2); define('TITLEBKG_FRAME_BOTTOM',2);
define('TITLEBKG_FRAME_BEVEL',3); define('TITLEBKG_FRAME_BEVEL',3);
define('TITLEBKG_FILLSTYLE_HSTRIPED',1); define('TITLEBKG_FILLSTYLE_HSTRIPED',1);
define('TITLEBKG_FILLSTYLE_VSTRIPED',2); define('TITLEBKG_FILLSTYLE_VSTRIPED',2);
define('TITLEBKG_FILLSTYLE_SOLID',3); define('TITLEBKG_FILLSTYLE_SOLID',3);
   
// Styles for axis labels background // Styles for axis labels background
define('LABELBKG_NONE',0); define('LABELBKG_NONE',0);
define('LABELBKG_XAXIS',1); define('LABELBKG_XAXIS',1);
define('LABELBKG_YAXIS',2); define('LABELBKG_YAXIS',2);
define('LABELBKG_XAXISFULL',3); define('LABELBKG_XAXISFULL',3);
define('LABELBKG_YAXISFULL',4); define('LABELBKG_YAXISFULL',4);
define('LABELBKG_XYFULL',5); define('LABELBKG_XYFULL',5);
define('LABELBKG_XY',6); define('LABELBKG_XY',6);
   
   
// Style for background gradient fills // Style for background gradient fills
define('BGRAD_FRAME',1); define('BGRAD_FRAME',1);
define('BGRAD_MARGIN',2); define('BGRAD_MARGIN',2);
define('BGRAD_PLOT',3); define('BGRAD_PLOT',3);
   
// Width of tab titles // Width of tab titles
define('TABTITLE_WIDTHFIT',0); define('TABTITLE_WIDTHFIT',0);
define('TABTITLE_WIDTHFULL',-1); define('TABTITLE_WIDTHFULL',-1);
   
// Defines for 3D skew directions // Defines for 3D skew directions
define('SKEW3D_UP',0); define('SKEW3D_UP',0);
define('SKEW3D_DOWN',1); define('SKEW3D_DOWN',1);
define('SKEW3D_LEFT',2); define('SKEW3D_LEFT',2);
define('SKEW3D_RIGHT',3); define('SKEW3D_RIGHT',3);
   
// For internal use only // For internal use only
define("_JPG_DEBUG",false); define("_JPG_DEBUG",false);
define("_FORCE_IMGTOFILE",false); define("_FORCE_IMGTOFILE",false);
define("_FORCE_IMGDIR",'/tmp/jpgimg/'); define("_FORCE_IMGDIR",'/tmp/jpgimg/');
   
// //
// Automatic settings of path for cache and font directory // Automatic settings of path for cache and font directory
// if they have not been previously specified // if they have not been previously specified
// //
if(USE_CACHE) { if(USE_CACHE) {
if (!defined('CACHE_DIR')) { if (!defined('CACHE_DIR')) {
if ( strstr( PHP_OS, 'WIN') ) { if ( strstr( PHP_OS, 'WIN') ) {
if( empty($_SERVER['TEMP']) ) { if( empty($_SERVER['TEMP']) ) {
$t = new ErrMsgText(); $t = new ErrMsgText();
$msg = $t->Get(11,$file,$lineno); $msg = $t->Get(11,$file,$lineno);
die($msg); die($msg);
} }
else { else {
define('CACHE_DIR', $_SERVER['TEMP'] . '/'); define('CACHE_DIR', $_SERVER['TEMP'] . '/');
} }
} else { } else {
define('CACHE_DIR','/tmp/jpgraph_cache/'); define('CACHE_DIR','/tmp/jpgraph_cache/');
} }
} }
} }
elseif( !defined('CACHE_DIR') ) { elseif( !defined('CACHE_DIR') ) {
define('CACHE_DIR', ''); define('CACHE_DIR', '');
} }
   
// //
// Setup path for western/latin TTF fonts // Setup path for western/latin TTF fonts
// //
if (!defined('TTF_DIR')) { if (!defined('TTF_DIR')) {
if (strstr( PHP_OS, 'WIN') ) { if (strstr( PHP_OS, 'WIN') ) {
$sroot = getenv('SystemRoot'); $sroot = getenv('SystemRoot');
if( empty($sroot) ) { if( empty($sroot) ) {
$t = new ErrMsgText(); $t = new ErrMsgText();
$msg = $t->Get(12,$file,$lineno); $msg = $t->Get(12,$file,$lineno);
die($msg); die($msg);
} }
else { else {
define('TTF_DIR', $sroot.'/fonts/'); define('TTF_DIR', $sroot.'/fonts/');
} }
} else { } else {
define('TTF_DIR','/usr/share/fonts/truetype/'); define('TTF_DIR','/usr/share/fonts/truetype/');
} }
} }
   
// //
// Setup path for MultiByte TTF fonts (japanese, chinese etc.) // Setup path for MultiByte TTF fonts (japanese, chinese etc.)
// //
if (!defined('MBTTF_DIR')) { if (!defined('MBTTF_DIR')) {
if (strstr( PHP_OS, 'WIN') ) { if (strstr( PHP_OS, 'WIN') ) {
$sroot = getenv('SystemRoot'); $sroot = getenv('SystemRoot');
if( empty($sroot) ) { if( empty($sroot) ) {
$t = new ErrMsgText(); $t = new ErrMsgText();
$msg = $t->Get(12,$file,$lineno); $msg = $t->Get(12,$file,$lineno);
die($msg); die($msg);
} }
else { else {
define('MBTTF_DIR', $sroot.'/fonts/'); define('MBTTF_DIR', $sroot.'/fonts/');
} }
} else { } else {
define('MBTTF_DIR','/usr/share/fonts/truetype/'); define('MBTTF_DIR','/usr/share/fonts/truetype/');
} }
} }
   
// //
// Check minimum PHP version // Check minimum PHP version
// //
function CheckPHPVersion($aMinVersion) { function CheckPHPVersion($aMinVersion) {
list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION); list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION);
list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion); list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion);
   
if ($majorC != $majorR) return false; if ($majorC != $majorR) return false;
if ($majorC < $majorR) return false; if ($majorC < $majorR) return false;
// same major - check minor // same major - check minor
if ($minorC > $minorR) return true; if ($minorC > $minorR) return true;
if ($minorC < $minorR) return false; if ($minorC < $minorR) return false;
// and same minor // and same minor
if ($editC >= $editR) return true; if ($editC >= $editR) return true;
return true; return true;
} }
   
// //
// Make sure PHP version is high enough // Make sure PHP version is high enough
// //
if( !CheckPHPVersion(MIN_PHPVERSION) ) { if( !CheckPHPVersion(MIN_PHPVERSION) ) {
JpGraphError::RaiseL(13,PHP_VERSION,MIN_PHPVERSION); JpGraphError::RaiseL(13,PHP_VERSION,MIN_PHPVERSION);
die(); die();
} }
   
// //
// Make GD sanity check // Make GD sanity check
// //
if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) { if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) {
JpGraphError::RaiseL(25001); 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)"); //("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 // Setup PHP error handler
// //
function _phpErrorHandler($errno,$errmsg,$filename, $linenum, $vars) { function _phpErrorHandler($errno,$errmsg,$filename, $linenum, $vars) {
// Respect current error level // Respect current error level
if( $errno & error_reporting() ) { if( $errno & error_reporting() ) {
JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg); JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
} }
} }
   
if( INSTALL_PHP_ERR_HANDLER ) { if( INSTALL_PHP_ERR_HANDLER ) {
set_error_handler("_phpErrorHandler"); set_error_handler("_phpErrorHandler");
} }
   
// //
// Check if there were any warnings, perhaps some wrong includes by the user. In this // 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 // 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 // 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']) ) { if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']); JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']);
} }
   
// Useful mathematical function // Useful mathematical function
function sign($a) {return $a >= 0 ? 1 : -1;} function sign($a) {return $a >= 0 ? 1 : -1;}
   
// //
// Utility function to generate an image name based on the filename we // Utility function to generate an image name based on the filename we
// are running from and assuming we use auto detection of graphic format // are running from and assuming we use auto detection of graphic format
// (top level), i.e it is safe to call this function // (top level), i.e it is safe to call this function
// from a script that uses JpGraph // from a script that uses JpGraph
// //
function GenImgName() { function GenImgName() {
// Determine what format we should use when we save the images // Determine what format we should use when we save the images
$supported = imagetypes(); $supported = imagetypes();
if( $supported & IMG_PNG ) $img_format="png"; if( $supported & IMG_PNG ) $img_format="png";
elseif( $supported & IMG_GIF ) $img_format="gif"; elseif( $supported & IMG_GIF ) $img_format="gif";
elseif( $supported & IMG_JPG ) $img_format="jpeg"; elseif( $supported & IMG_JPG ) $img_format="jpeg";
elseif( $supported & IMG_WBMP ) $img_format="wbmp"; elseif( $supported & IMG_WBMP ) $img_format="wbmp";
elseif( $supported & IMG_XPM ) $img_format="xpm"; elseif( $supported & IMG_XPM ) $img_format="xpm";
   
   
if( !isset($_SERVER['PHP_SELF']) ) { if( !isset($_SERVER['PHP_SELF']) ) {
JpGraphError::RaiseL(25005); 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."); //(" 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']); $fname = basename($_SERVER['PHP_SELF']);
if( !empty($_SERVER['QUERY_STRING']) ) { if( !empty($_SERVER['QUERY_STRING']) ) {
$q = @$_SERVER['QUERY_STRING']; $q = @$_SERVER['QUERY_STRING'];
$fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format; $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
} }
else { else {
$fname = substr($fname,0,strlen($fname)-4).'.'.$img_format; $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
} }
return $fname; return $fname;
} }
   
//=================================================== //===================================================
// CLASS JpgTimer // CLASS JpgTimer
// Description: General timing utility class to handle // Description: General timing utility class to handle
// time measurement of generating graphs. Multiple // time measurement of generating graphs. Multiple
// timers can be started. // timers can be started.
//=================================================== //===================================================
class JpgTimer { class JpgTimer {
private $start, $idx; private $start, $idx;
   
function __construct() { function __construct() {
$this->idx=0; $this->idx=0;
} }
   
// Push a new timer start on stack // Push a new timer start on stack
function Push() { function Push() {
list($ms,$s)=explode(" ",microtime()); list($ms,$s)=explode(" ",microtime());
$this->start[$this->idx++]=floor($ms*1000) + 1000*$s; $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;
} }
   
// Pop the latest timer start and return the diff with the // Pop the latest timer start and return the diff with the
// current time // current time
function Pop() { function Pop() {
assert($this->idx>0); assert($this->idx>0);
list($ms,$s)=explode(" ",microtime()); list($ms,$s)=explode(" ",microtime());
$etime=floor($ms*1000) + (1000*$s); $etime=floor($ms*1000) + (1000*$s);
$this->idx--; $this->idx--;
return $etime-$this->start[$this->idx]; return $etime-$this->start[$this->idx];
} }
} // Class } // Class
   
//=================================================== //===================================================
// CLASS DateLocale // CLASS DateLocale
// Description: Hold localized text used in dates // Description: Hold localized text used in dates
//=================================================== //===================================================
class DateLocale { class DateLocale {
   
public $iLocale = 'C'; // environmental locale be used by default public $iLocale = 'C'; // environmental locale be used by default
private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null; private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null;
   
function __construct() { function __construct() {
settype($this->iDayAbb, 'array'); settype($this->iDayAbb, 'array');
settype($this->iShortDay, 'array'); settype($this->iShortDay, 'array');
settype($this->iShortMonth, 'array'); settype($this->iShortMonth, 'array');
settype($this->iMonthName, 'array'); settype($this->iMonthName, 'array');
$this->Set('C'); $this->Set('C');
} }
   
function Set($aLocale) { function Set($aLocale) {
if ( in_array($aLocale, array_keys($this->iDayAbb)) ){ if ( in_array($aLocale, array_keys($this->iDayAbb)) ){
$this->iLocale = $aLocale; $this->iLocale = $aLocale;
return TRUE; // already cached nothing else to do! return TRUE; // already cached nothing else to do!
} }
   
$pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME
   
if (is_array($aLocale)) { if (is_array($aLocale)) {
foreach ($aLocale as $loc) { foreach ($aLocale as $loc) {
$res = @setlocale(LC_TIME, $loc); $res = @setlocale(LC_TIME, $loc);
if ( $res ) { if ( $res ) {
$aLocale = $loc; $aLocale = $loc;
break; break;
} }
} }
} }
else { else {
$res = @setlocale(LC_TIME, $aLocale); $res = @setlocale(LC_TIME, $aLocale);
} }
   
if ( ! $res ) { if ( ! $res ) {
JpGraphError::RaiseL(25007,$aLocale); 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."); //("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; return FALSE;
} }
   
$this->iLocale = $aLocale; $this->iLocale = $aLocale;
for( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ) { for( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ) {
$day = strftime('%a', strtotime("$ofs day")); $day = strftime('%a', strtotime("$ofs day"));
$day[0] = strtoupper($day[0]); $day[0] = strtoupper($day[0]);
$this->iDayAbb[$aLocale][]= $day[0]; $this->iDayAbb[$aLocale][]= $day[0];
$this->iShortDay[$aLocale][]= $day; $this->iShortDay[$aLocale][]= $day;
} }
   
for($i=1; $i<=12; ++$i) { for($i=1; $i<=12; ++$i) {
list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01"))); list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01")));
$this->iShortMonth[$aLocale][] = ucfirst($short); $this->iShortMonth[$aLocale][] = ucfirst($short);
$this->iMonthName [$aLocale][] = ucfirst($full); $this->iMonthName [$aLocale][] = ucfirst($full);
} }
   
setlocale(LC_TIME, $pLocale); setlocale(LC_TIME, $pLocale);
   
return TRUE; return TRUE;
} }
   
   
function GetDayAbb() { function GetDayAbb() {
return $this->iDayAbb[$this->iLocale]; return $this->iDayAbb[$this->iLocale];
} }
   
function GetShortDay() { function GetShortDay() {
return $this->iShortDay[$this->iLocale]; return $this->iShortDay[$this->iLocale];
} }
   
function GetShortMonth() { function GetShortMonth() {
return $this->iShortMonth[$this->iLocale]; return $this->iShortMonth[$this->iLocale];
} }
   
function GetShortMonthName($aNbr) { function GetShortMonthName($aNbr) {
return $this->iShortMonth[$this->iLocale][$aNbr]; return $this->iShortMonth[$this->iLocale][$aNbr];
} }
   
function GetLongMonthName($aNbr) { function GetLongMonthName($aNbr) {
return $this->iMonthName[$this->iLocale][$aNbr]; return $this->iMonthName[$this->iLocale][$aNbr];
} }
   
function GetMonth() { function GetMonth() {
return $this->iMonthName[$this->iLocale]; return $this->iMonthName[$this->iLocale];
} }
} }
   
// Global object handlers // Global object handlers
$gDateLocale = new DateLocale(); $gDateLocale = new DateLocale();
$gJpgDateLocale = new DateLocale(); $gJpgDateLocale = new DateLocale();
   
//======================================================= //=======================================================
// CLASS Footer // CLASS Footer
// Description: Encapsulates the footer line in the Graph // Description: Encapsulates the footer line in the Graph
//======================================================= //=======================================================
class Footer { class Footer {
public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ; public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ;
public $left,$center,$right; public $left,$center,$right;
private $iTimer=null, $itimerpoststring=''; private $iTimer=null, $itimerpoststring='';
   
function __construct() { function __construct() {
$this->left = new Text(); $this->left = new Text();
$this->left->ParagraphAlign('left'); $this->left->ParagraphAlign('left');
$this->center = new Text(); $this->center = new Text();
$this->center->ParagraphAlign('center'); $this->center->ParagraphAlign('center');
$this->right = new Text(); $this->right = new Text();
$this->right->ParagraphAlign('right'); $this->right->ParagraphAlign('right');
} }
   
function SetTimer($aTimer,$aTimerPostString='') { function SetTimer($aTimer,$aTimerPostString='') {
$this->iTimer = $aTimer; $this->iTimer = $aTimer;
$this->itimerpoststring = $aTimerPostString; $this->itimerpoststring = $aTimerPostString;
} }
   
function SetMargin($aLeft=3,$aRight=3,$aBottom=3) { function SetMargin($aLeft=3,$aRight=3,$aBottom=3) {
$this->iLeftMargin = $aLeft; $this->iLeftMargin = $aLeft;
$this->iRightMargin = $aRight; $this->iRightMargin = $aRight;
$this->iBottomMargin = $aBottom; $this->iBottomMargin = $aBottom;
} }
   
function Stroke($aImg) { function Stroke($aImg) {
$y = $aImg->height - $this->iBottomMargin; $y = $aImg->height - $this->iBottomMargin;
$x = $this->iLeftMargin; $x = $this->iLeftMargin;
$this->left->Align('left','bottom'); $this->left->Align('left','bottom');
$this->left->Stroke($aImg,$x,$y); $this->left->Stroke($aImg,$x,$y);
   
$x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2; $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2;
$this->center->Align('center','bottom'); $this->center->Align('center','bottom');
$this->center->Stroke($aImg,$x,$y); $this->center->Stroke($aImg,$x,$y);
   
$x = $aImg->width - $this->iRightMargin; $x = $aImg->width - $this->iRightMargin;
$this->right->Align('right','bottom'); $this->right->Align('right','bottom');
if( $this->iTimer != null ) { if( $this->iTimer != null ) {
$this->right->Set( $this->right->t . sprintf('%.3f',$this->iTimer->Pop()/1000.0) . $this->itimerpoststring ); $this->right->Set( $this->right->t . sprintf('%.3f',$this->iTimer->Pop()/1000.0) . $this->itimerpoststring );
} }
$this->right->Stroke($aImg,$x,$y); $this->right->Stroke($aImg,$x,$y);
} }
} }
   
   
//=================================================== //===================================================
// CLASS Graph // CLASS Graph
// Description: Main class to handle graphs // Description: Main class to handle graphs
//=================================================== //===================================================
class Graph { class Graph {
public $cache=null; // Cache object (singleton) public $cache=null; // Cache object (singleton)
public $img=null; // Img object (singleton) public $img=null; // Img object (singleton)
public $plots=array(); // Array of all plot object in the graph (for Y 1 axis) 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 $y2plots=array(); // Array of all plot object in the graph (for Y 2 axis)
public $ynplots=array(); public $ynplots=array();
public $xscale=null; // X Scale object (could be instance of LinearScale or LogScale public $xscale=null; // X Scale object (could be instance of LinearScale or LogScale
public $yscale=null,$y2scale=null, $ynscale=array(); public $yscale=null,$y2scale=null, $ynscale=array();
public $iIcons = array(); // Array of Icons to add to 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 $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 $xgrid=null; // X Grid object (linear or logarithmic)
public $ygrid=null,$y2grid=null; //dito for Y public $ygrid=null,$y2grid=null; //dito for Y
public $doframe=true,$frame_color='black', $frame_weight=1; // Frame around graph public $doframe=true,$frame_color='black', $frame_weight=1; // Frame around graph
public $boxed=false, $box_color='black', $box_weight=1; // Box around plot area 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 $doshadow=false,$shadow_width=4,$shadow_color='gray@0.5'; // Shadow for graph
public $xaxis=null; // X-axis (instane of Axis class) public $xaxis=null; // X-axis (instane of Axis class)
public $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class) public $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class)
public $margin_color=array(230,230,230); // Margin color of graph public $margin_color=array(230,230,230); // Margin color of graph
public $plotarea_color=array(255,255,255); // Plot area color public $plotarea_color=array(255,255,255); // Plot area color
public $title,$subtitle,$subsubtitle; // Title and subtitle(s) text object public $title,$subtitle,$subsubtitle; // Title and subtitle(s) text object
public $axtype="linlin"; // Type of axis 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 $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 $texts=null, $y2texts=null; // Text object to ge shown in the graph
public $lines=null, $y2lines=null; public $lines=null, $y2lines=null;
public $bands=null, $y2bands=null; public $bands=null, $y2bands=null;
public $text_scale_off=0, $text_scale_abscenteroff=-1; // Text scale in fractions and for centering bars 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='',$background_image_type=-1,$background_image_format="png";
public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0; public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0;
public $background_image_xpos=0,$background_image_ypos=0; public $background_image_xpos=0,$background_image_ypos=0;
public $image_bright=0, $image_contr=0, $image_sat=0; public $image_bright=0, $image_contr=0, $image_sat=0;
public $inline; public $inline;
public $showcsim=0,$csimcolor="red";//debug stuff, draw the csim boundaris on the image if <>0 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 $grid_depth=DEPTH_BACK; // Draw grid under all plots as default
public $iAxisStyle = AXSTYLE_SIMPLE; public $iAxisStyle = AXSTYLE_SIMPLE;
public $iCSIMdisplay=false,$iHasStroked = false; public $iCSIMdisplay=false,$iHasStroked = false;
public $footer; public $footer;
public $csimcachename = '', $csimcachetimeout = 0, $iCSIMImgAlt=''; public $csimcachename = '', $csimcachetimeout = 0, $iCSIMImgAlt='';
public $iDoClipping = false; public $iDoClipping = false;
public $y2orderback=true; public $y2orderback=true;
public $tabtitle; public $tabtitle;
public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN; public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN;
public $bkg_gradfrom='navy', $bkg_gradto='silver'; public $bkg_gradfrom='navy', $bkg_gradto='silver';
public $plot_gradtype=-1,$plot_gradstyle=BGRAD_MARGIN; public $plot_gradtype=-1,$plot_gradstyle=BGRAD_MARGIN;
public $plot_gradfrom='silver', $plot_gradto='navy'; public $plot_gradfrom='silver', $plot_gradto='navy';
   
public $titlebackground = false; public $titlebackground = false;
public $titlebackground_color = 'lightblue', public $titlebackground_color = 'lightblue',
$titlebackground_style = 1, $titlebackground_style = 1,
$titlebackground_framecolor = 'blue', $titlebackground_framecolor = 'blue',
$titlebackground_framestyle = 2, $titlebackground_framestyle = 2,
$titlebackground_frameweight = 1, $titlebackground_frameweight = 1,
$titlebackground_bevelheight = 3 ; $titlebackground_bevelheight = 3 ;
public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID; public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID;
public $titlebkg_scolor1='black',$titlebkg_scolor2='white'; public $titlebkg_scolor1='black',$titlebkg_scolor2='white';
public $framebevel = false, $framebeveldepth = 2 ; public $framebevel = false, $framebeveldepth = 2 ;
public $framebevelborder = false, $framebevelbordercolor='black'; public $framebevelborder = false, $framebevelbordercolor='black';
public $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4'; public $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4';
public $background_image_mix=100; public $background_image_mix=100;
public $background_cflag = ''; public $background_cflag = '';
public $background_cflag_type = BGIMG_FILLPLOT; public $background_cflag_type = BGIMG_FILLPLOT;
public $background_cflag_mix = 100; public $background_cflag_mix = 100;
public $iImgTrans=false, public $iImgTrans=false,
$iImgTransHorizon = 100,$iImgTransSkewDist=150, $iImgTransHorizon = 100,$iImgTransSkewDist=150,
$iImgTransDirection = 1, $iImgTransMinSize = true, $iImgTransDirection = 1, $iImgTransMinSize = true,
$iImgTransFillColor='white',$iImgTransHighQ=false, $iImgTransFillColor='white',$iImgTransHighQ=false,
$iImgTransBorder=false,$iImgTransHorizonPos=0.5; $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
public $legend; public $legend;
protected $iYAxisDeltaPos=50; protected $iYAxisDeltaPos=50;
protected $iIconDepth=DEPTH_BACK; protected $iIconDepth=DEPTH_BACK;
protected $iAxisLblBgType = 0, protected $iAxisLblBgType = 0,
$iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black', $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
$iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black'; $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
protected $iTables=NULL; protected $iTables=NULL;
   
// aWIdth Width in pixels of image // aWIdth Width in pixels of image
// aHeight Height in pixels of image // aHeight Height in pixels of image
// aCachedName Name for image file in cache directory // aCachedName Name for image file in cache directory
// aTimeOut Timeout in minutes for image in cache // aTimeOut Timeout in minutes for image in cache
// aInline If true the image is streamed back in the call to Stroke() // aInline If true the image is streamed back in the call to Stroke()
// If false the image is just created in the cache // If false the image is just created in the cache
function __construct($aWidth=300,$aHeight=200,$aCachedName='',$aTimeout=0,$aInline=true) { function __construct($aWidth=300,$aHeight=200,$aCachedName='',$aTimeout=0,$aInline=true) {
   
if( !is_numeric($aWidth) || !is_numeric($aHeight) ) { if( !is_numeric($aWidth) || !is_numeric($aHeight) ) {
JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric'); 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 // Automatically generate the image file name based on the name of the script that
// generates the graph // generates the graph
if( $aCachedName == 'auto' ) { if( $aCachedName == 'auto' ) {
$aCachedName=GenImgName(); $aCachedName=GenImgName();
} }
   
// Should the image be streamed back to the browser or only to the cache? // Should the image be streamed back to the browser or only to the cache?
$this->inline=$aInline; $this->inline=$aInline;
   
$this->img = new RotImage($aWidth,$aHeight); $this->img = new RotImage($aWidth,$aHeight);
$this->cache = new ImgStreamCache(); $this->cache = new ImgStreamCache();
   
// Window doesn't like '?' in the file name so replace it with an '_' // Window doesn't like '?' in the file name so replace it with an '_'
$aCachedName = str_replace("?","_",$aCachedName); $aCachedName = str_replace("?","_",$aCachedName);
$this->SetupCache($aCachedName, $aTimeout); $this->SetupCache($aCachedName, $aTimeout);
   
$this->title = new Text(); $this->title = new Text();
$this->title->ParagraphAlign('center'); $this->title->ParagraphAlign('center');
$this->title->SetFont(FF_FONT2,FS_BOLD); $this->title->SetFont(FF_FONT2,FS_BOLD);
$this->title->SetMargin(5); $this->title->SetMargin(5);
$this->title->SetAlign('center'); $this->title->SetAlign('center');
   
$this->subtitle = new Text(); $this->subtitle = new Text();
$this->subtitle->ParagraphAlign('center'); $this->subtitle->ParagraphAlign('center');
$this->subtitle->SetMargin(3); $this->subtitle->SetMargin(3);
$this->subtitle->SetAlign('center'); $this->subtitle->SetAlign('center');
   
$this->subsubtitle = new Text(); $this->subsubtitle = new Text();
$this->subsubtitle->ParagraphAlign('center'); $this->subsubtitle->ParagraphAlign('center');
$this->subsubtitle->SetMargin(3); $this->subsubtitle->SetMargin(3);
$this->subsubtitle->SetAlign('center'); $this->subsubtitle->SetAlign('center');
   
$this->legend = new Legend(); $this->legend = new Legend();
$this->footer = new Footer(); $this->footer = new Footer();
   
// If the cached version exist just read it directly from the // If the cached version exist just read it directly from the
// cache, stream it back to browser and exit // cache, stream it back to browser and exit
if( $aCachedName!='' && READ_CACHE && $aInline ) { if( $aCachedName!='' && READ_CACHE && $aInline ) {
if( $this->cache->GetAndStream($this->img,$aCachedName) ) { if( $this->cache->GetAndStream($this->img,$aCachedName) ) {
exit(); exit();
} }
} }
   
$this->SetTickDensity(); // Normal density $this->SetTickDensity(); // Normal density
   
$this->tabtitle = new GraphTabTitle(); $this->tabtitle = new GraphTabTitle();
} }
   
function SetupCache($aFilename,$aTimeout=60) { function SetupCache($aFilename,$aTimeout=60) {
$this->cache_name = $aFilename; $this->cache_name = $aFilename;
$this->cache->SetTimeOut($aTimeout); $this->cache->SetTimeOut($aTimeout);
} }
   
// Enable final image perspective transformation // Enable final image perspective transformation
function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) { function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) {
$this->iImgTrans = true; $this->iImgTrans = true;
$this->iImgTransHorizon = $aHorizon; $this->iImgTransHorizon = $aHorizon;
$this->iImgTransSkewDist= $aSkewDist; $this->iImgTransSkewDist= $aSkewDist;
$this->iImgTransDirection = $aDir; $this->iImgTransDirection = $aDir;
$this->iImgTransMinSize = $aMinSize; $this->iImgTransMinSize = $aMinSize;
$this->iImgTransFillColor=$aFillColor; $this->iImgTransFillColor=$aFillColor;
$this->iImgTransHighQ=$aQuality; $this->iImgTransHighQ=$aQuality;
$this->iImgTransBorder=$aBorder; $this->iImgTransBorder=$aBorder;
$this->iImgTransHorizonPos=$aHorizonPos; $this->iImgTransHorizonPos=$aHorizonPos;
} }
   
function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt); $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
} }
   
function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt); $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
} }
   
function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt); $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
} }
   
function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt); $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
} }
   
// Set Image format and optional quality // Set Image format and optional quality
function SetImgFormat($aFormat,$aQuality=75) { function SetImgFormat($aFormat,$aQuality=75) {
$this->img->SetImgFormat($aFormat,$aQuality); $this->img->SetImgFormat($aFormat,$aQuality);
} }
   
// Should the grid be in front or back of the plot? // Should the grid be in front or back of the plot?
function SetGridDepth($aDepth) { function SetGridDepth($aDepth) {
$this->grid_depth=$aDepth; $this->grid_depth=$aDepth;
} }
   
function SetIconDepth($aDepth) { function SetIconDepth($aDepth) {
$this->iIconDepth=$aDepth; $this->iIconDepth=$aDepth;
} }
   
// Specify graph angle 0-360 degrees. // Specify graph angle 0-360 degrees.
function SetAngle($aAngle) { function SetAngle($aAngle) {
$this->img->SetAngle($aAngle); $this->img->SetAngle($aAngle);
} }
   
function SetAlphaBlending($aFlg=true) { function SetAlphaBlending($aFlg=true) {
$this->img->SetAlphaBlending($aFlg); $this->img->SetAlphaBlending($aFlg);
} }
   
// Shortcut to image margin // Shortcut to image margin
function SetMargin($lm,$rm,$tm,$bm) { function SetMargin($lm,$rm,$tm,$bm) {
$this->img->SetMargin($lm,$rm,$tm,$bm); $this->img->SetMargin($lm,$rm,$tm,$bm);
} }
   
function SetY2OrderBack($aBack=true) { function SetY2OrderBack($aBack=true) {
$this->y2orderback = $aBack; $this->y2orderback = $aBack;
} }
   
// Rotate the graph 90 degrees and set the margin // Rotate the graph 90 degrees and set the margin
// when we have done a 90 degree rotation // when we have done a 90 degree rotation
function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) { function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
$lm = $lm ==0 ? floor(0.2 * $this->img->width) : $lm ; $lm = $lm ==0 ? floor(0.2 * $this->img->width) : $lm ;
$rm = $rm ==0 ? floor(0.1 * $this->img->width) : $rm ; $rm = $rm ==0 ? floor(0.1 * $this->img->width) : $rm ;
$tm = $tm ==0 ? floor(0.2 * $this->img->height) : $tm ; $tm = $tm ==0 ? floor(0.2 * $this->img->height) : $tm ;
$bm = $bm ==0 ? floor(0.1 * $this->img->height) : $bm ; $bm = $bm ==0 ? floor(0.1 * $this->img->height) : $bm ;
   
$adj = ($this->img->height - $this->img->width)/2; $adj = ($this->img->height - $this->img->width)/2;
$this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj); $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->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
$this->SetAngle(90); $this->SetAngle(90);
if( empty($this->yaxis) || empty($this->xaxis) ) { if( empty($this->yaxis) || empty($this->xaxis) ) {
JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()'); JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()');
} }
$this->xaxis->SetLabelAlign('right','center'); $this->xaxis->SetLabelAlign('right','center');
$this->yaxis->SetLabelAlign('center','bottom'); $this->yaxis->SetLabelAlign('center','bottom');
} }
   
function SetClipping($aFlg=true) { function SetClipping($aFlg=true) {
$this->iDoClipping = $aFlg ; $this->iDoClipping = $aFlg ;
} }
   
// Add a plot object to the graph // Add a plot object to the graph
function Add($aPlot) { function Add($aPlot) {
if( $aPlot == null ) { if( $aPlot == null ) {
JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph."); JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
} }
if( is_array($aPlot) && count($aPlot) > 0 ) { if( is_array($aPlot) && count($aPlot) > 0 ) {
$cl = $aPlot[0]; $cl = $aPlot[0];
} }
else { else {
$cl = $aPlot; $cl = $aPlot;
} }
   
if( $cl instanceof Text ) $this->AddText($aPlot); if( $cl instanceof Text ) $this->AddText($aPlot);
elseif( class_exists('PlotLine') && ($cl instanceof PlotLine) ) $this->AddLine($aPlot); elseif( class_exists('PlotLine') && ($cl instanceof PlotLine) ) $this->AddLine($aPlot);
elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) $this->AddBand($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('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) ) $this->AddTable($aPlot); elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) ) $this->AddTable($aPlot);
else { else {
if( is_array($aPlot) ) { if( is_array($aPlot) ) {
$this->plots = array_merge($this->plots,$aPlot); $this->plots = array_merge($this->plots,$aPlot);
} }
else { else {
$this->plots[] = $aPlot; $this->plots[] = $aPlot;
} }
} }
} }
   
function AddTable($aTable) { function AddTable($aTable) {
if( is_array($aTable) ) { if( is_array($aTable) ) {
for($i=0; $i < count($aTable); ++$i ) { for($i=0; $i < count($aTable); ++$i ) {
$this->iTables[]=$aTable[$i]; $this->iTables[]=$aTable[$i];
} }
} }
else { else {
$this->iTables[] = $aTable ; $this->iTables[] = $aTable ;
} }
} }
   
function AddIcon($aIcon) { function AddIcon($aIcon) {
if( is_array($aIcon) ) { if( is_array($aIcon) ) {
for($i=0; $i < count($aIcon); ++$i ) { for($i=0; $i < count($aIcon); ++$i ) {
$this->iIcons[]=$aIcon[$i]; $this->iIcons[]=$aIcon[$i];
} }
} }
else { else {
$this->iIcons[] = $aIcon ; $this->iIcons[] = $aIcon ;
} }
} }
   
// Add plot to second Y-scale // Add plot to second Y-scale
function AddY2($aPlot) { function AddY2($aPlot) {
if( $aPlot == null ) { if( $aPlot == null ) {
JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph."); JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph.");
} }
   
if( is_array($aPlot) && count($aPlot) > 0 ) { if( is_array($aPlot) && count($aPlot) > 0 ) {
$cl = $aPlot[0]; $cl = $aPlot[0];
} }
else { else {
$cl = $aPlot; $cl = $aPlot;
} }
   
if( $cl instanceof Text ) { if( $cl instanceof Text ) {
$this->AddText($aPlot,true); $this->AddText($aPlot,true);
} }
elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) { elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) {
$this->AddLine($aPlot,true); $this->AddLine($aPlot,true);
} }
elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) { elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) {
$this->AddBand($aPlot,true); $this->AddBand($aPlot,true);
} }
else { else {
$this->y2plots[] = $aPlot; $this->y2plots[] = $aPlot;
} }
} }
   
// Add plot to the extra Y-axises // Add plot to the extra Y-axises
function AddY($aN,$aPlot) { function AddY($aN,$aPlot) {
   
if( $aPlot == null ) { if( $aPlot == null ) {
JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph."); JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph.");
} }
   
if( is_array($aPlot) && count($aPlot) > 0 ) { if( is_array($aPlot) && count($aPlot) > 0 ) {
$cl = $aPlot[0]; $cl = $aPlot[0];
} }
else { else {
$cl = $aPlot; $cl = $aPlot;
} }
   
if( ($cl instanceof Text) || if( ($cl instanceof Text) ||
(class_exists('PlotLine',false) && ($cl instanceof PlotLine)) || (class_exists('PlotLine',false) && ($cl instanceof PlotLine)) ||
(class_exists('PlotBand',false) && ($cl instanceof PlotBand)) ) { (class_exists('PlotBand',false) && ($cl instanceof PlotBand)) ) {
JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis'); JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis');
} }
else { else {
$this->ynplots[$aN][] = $aPlot; $this->ynplots[$aN][] = $aPlot;
} }
} }
   
// Add text object to the graph // Add text object to the graph
function AddText($aTxt,$aToY2=false) { function AddText($aTxt,$aToY2=false) {
if( $aTxt == null ) { if( $aTxt == null ) {
JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph."); JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph.");
} }
if( $aToY2 ) { if( $aToY2 ) {
if( is_array($aTxt) ) { if( is_array($aTxt) ) {
for($i=0; $i < count($aTxt); ++$i ) { for($i=0; $i < count($aTxt); ++$i ) {
$this->y2texts[]=$aTxt[$i]; $this->y2texts[]=$aTxt[$i];
} }
} }
else { else {
$this->y2texts[] = $aTxt; $this->y2texts[] = $aTxt;
} }
} }
else { else {
if( is_array($aTxt) ) { if( is_array($aTxt) ) {
for($i=0; $i < count($aTxt); ++$i ) { for($i=0; $i < count($aTxt); ++$i ) {
$this->texts[]=$aTxt[$i]; $this->texts[]=$aTxt[$i];
} }
} }
else { else {
$this->texts[] = $aTxt; $this->texts[] = $aTxt;
} }
} }
} }
   
// Add a line object (class PlotLine) to the graph // Add a line object (class PlotLine) to the graph
function AddLine($aLine,$aToY2=false) { function AddLine($aLine,$aToY2=false) {
if( $aLine == null ) { if( $aLine == null ) {
JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph."); JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph.");
} }
   
if( $aToY2 ) { if( $aToY2 ) {
if( is_array($aLine) ) { if( is_array($aLine) ) {
for($i=0; $i < count($aLine); ++$i ) { for($i=0; $i < count($aLine); ++$i ) {
//$this->y2lines[]=$aLine[$i]; //$this->y2lines[]=$aLine[$i];
$this->y2plots[]=$aLine[$i]; $this->y2plots[]=$aLine[$i];
} }
} }
else { else {
//$this->y2lines[] = $aLine; //$this->y2lines[] = $aLine;
$this->y2plots[]=$aLine; $this->y2plots[]=$aLine;
} }
} }
else { else {
if( is_array($aLine) ) { if( is_array($aLine) ) {
for($i=0; $i<count($aLine); ++$i ) { for($i=0; $i<count($aLine); ++$i ) {
//$this->lines[]=$aLine[$i]; //$this->lines[]=$aLine[$i];
$this->plots[]=$aLine[$i]; $this->plots[]=$aLine[$i];
} }
} }
else { else {
//$this->lines[] = $aLine; //$this->lines[] = $aLine;
$this->plots[] = $aLine; $this->plots[] = $aLine;
} }
} }
} }
   
// Add vertical or horizontal band // Add vertical or horizontal band
function AddBand($aBand,$aToY2=false) { function AddBand($aBand,$aToY2=false) {
if( $aBand == null ) { if( $aBand == null ) {
JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph."); JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph.");
} }
   
if( $aToY2 ) { if( $aToY2 ) {
if( is_array($aBand) ) { if( is_array($aBand) ) {
for($i=0; $i < count($aBand); ++$i ) { for($i=0; $i < count($aBand); ++$i ) {
$this->y2bands[] = $aBand[$i]; $this->y2bands[] = $aBand[$i];
} }
} }
else { else {
$this->y2bands[] = $aBand; $this->y2bands[] = $aBand;
} }
} }
else { else {
if( is_array($aBand) ) { if( is_array($aBand) ) {
for($i=0; $i < count($aBand); ++$i ) { for($i=0; $i < count($aBand); ++$i ) {
$this->bands[] = $aBand[$i]; $this->bands[] = $aBand[$i];
} }
} }
else { else {
$this->bands[] = $aBand; $this->bands[] = $aBand;
} }
} }
} }
   
function SetPlotGradient($aFrom='navy',$aTo='silver',$aGradType=2) { function SetPlotGradient($aFrom='navy',$aTo='silver',$aGradType=2) {
$this->plot_gradtype=$aGradType; $this->plot_gradtype=$aGradType;
$this->plot_gradfrom = $aFrom; $this->plot_gradfrom = $aFrom;
$this->plot_gradto = $aTo; $this->plot_gradto = $aTo;
} }
   
function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) { function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) {
$this->bkg_gradtype=$aGradType; $this->bkg_gradtype=$aGradType;
$this->bkg_gradstyle=$aStyle; $this->bkg_gradstyle=$aStyle;
$this->bkg_gradfrom = $aFrom; $this->bkg_gradfrom = $aFrom;
$this->bkg_gradto = $aTo; $this->bkg_gradto = $aTo;
} }
   
// Set a country flag in the background // Set a country flag in the background
function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) { function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
$this->background_cflag = $aName; $this->background_cflag = $aName;
$this->background_cflag_type = $aBgType; $this->background_cflag_type = $aBgType;
$this->background_cflag_mix = $aMix; $this->background_cflag_mix = $aMix;
} }
   
// Alias for the above method // Alias for the above method
function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) { function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
$this->background_cflag = $aName; $this->background_cflag = $aName;
$this->background_cflag_type = $aBgType; $this->background_cflag_type = $aBgType;
$this->background_cflag_mix = $aMix; $this->background_cflag_mix = $aMix;
} }
   
   
// Specify a background image // Specify a background image
function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat='auto') { function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat='auto') {
   
// Get extension to determine image type // Get extension to determine image type
if( $aImgFormat == 'auto' ) { if( $aImgFormat == 'auto' ) {
$e = explode('.',$aFileName); $e = explode('.',$aFileName);
if( !$e ) { 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'); 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'); $valid_formats = array('png', 'jpg', 'gif');
$aImgFormat = strtolower($e[count($e)-1]); $aImgFormat = strtolower($e[count($e)-1]);
if ($aImgFormat == 'jpeg') { if ($aImgFormat == 'jpeg') {
$aImgFormat = 'jpg'; $aImgFormat = 'jpg';
} }
elseif (!in_array($aImgFormat, $valid_formats) ) { elseif (!in_array($aImgFormat, $valid_formats) ) {
JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName); JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName);
} }
} }
   
$this->background_image = $aFileName; $this->background_image = $aFileName;
$this->background_image_type=$aBgType; $this->background_image_type=$aBgType;
$this->background_image_format=$aImgFormat; $this->background_image_format=$aImgFormat;
} }
   
function SetBackgroundImageMix($aMix) { function SetBackgroundImageMix($aMix) {
$this->background_image_mix = $aMix ; $this->background_image_mix = $aMix ;
} }
   
// Adjust background image position // Adjust background image position
function SetBackgroundImagePos($aXpos,$aYpos) { function SetBackgroundImagePos($aXpos,$aYpos) {
$this->background_image_xpos = $aXpos ; $this->background_image_xpos = $aXpos ;
$this->background_image_ypos = $aYpos ; $this->background_image_ypos = $aYpos ;
} }
   
// Specify axis style (boxed or single) // Specify axis style (boxed or single)
function SetAxisStyle($aStyle) { function SetAxisStyle($aStyle) {
$this->iAxisStyle = $aStyle ; $this->iAxisStyle = $aStyle ;
} }
   
// Set a frame around the plot area // Set a frame around the plot area
function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) { function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) {
$this->boxed = $aDrawPlotFrame; $this->boxed = $aDrawPlotFrame;
$this->box_weight = $aPlotFrameWeight; $this->box_weight = $aPlotFrameWeight;
$this->box_color = $aPlotFrameColor; $this->box_color = $aPlotFrameColor;
} }
   
// Specify color for the plotarea (not the margins) // Specify color for the plotarea (not the margins)
function SetColor($aColor) { function SetColor($aColor) {
$this->plotarea_color=$aColor; $this->plotarea_color=$aColor;
} }
   
// Specify color for the margins (all areas outside the plotarea) // Specify color for the margins (all areas outside the plotarea)
function SetMarginColor($aColor) { function SetMarginColor($aColor) {
$this->margin_color=$aColor; $this->margin_color=$aColor;
} }
   
// Set a frame around the entire image // Set a frame around the entire image
function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) { function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) {
$this->doframe = $aDrawImgFrame; $this->doframe = $aDrawImgFrame;
$this->frame_color = $aImgFrameColor; $this->frame_color = $aImgFrameColor;
$this->frame_weight = $aImgFrameWeight; $this->frame_weight = $aImgFrameWeight;
} }
   
function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) { function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) {
$this->framebevel = $aFlg ; $this->framebevel = $aFlg ;
$this->framebeveldepth = $aDepth ; $this->framebeveldepth = $aDepth ;
$this->framebevelborder = $aBorder ; $this->framebevelborder = $aBorder ;
$this->framebevelbordercolor = $aBorderColor ; $this->framebevelbordercolor = $aBorderColor ;
$this->framebevelcolor1 = $aColor1 ; $this->framebevelcolor1 = $aColor1 ;
$this->framebevelcolor2 = $aColor2 ; $this->framebevelcolor2 = $aColor2 ;
   
$this->doshadow = false ; $this->doshadow = false ;
} }
   
// Set the shadow around the whole image // Set the shadow around the whole image
function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor='darkgray') { function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor='darkgray') {
$this->doshadow = $aShowShadow; $this->doshadow = $aShowShadow;
$this->shadow_color = $aShadowColor; $this->shadow_color = $aShadowColor;
$this->shadow_width = $aShadowWidth; $this->shadow_width = $aShadowWidth;
$this->footer->iBottomMargin += $aShadowWidth; $this->footer->iBottomMargin += $aShadowWidth;
$this->footer->iRightMargin += $aShadowWidth; $this->footer->iRightMargin += $aShadowWidth;
} }
   
// Specify x,y scale. Note that if you manually specify the scale // 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() // you must also specify the tick distance with a call to Ticks::Set()
function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) { function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
$this->axtype = $aAxisType; $this->axtype = $aAxisType;
   
if( $aYMax < $aYMin || $aXMax < $aXMin ) { if( $aYMax < $aYMin || $aXMax < $aXMin ) {
JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.'); JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.');
} }
   
$yt=substr($aAxisType,-3,3); $yt=substr($aAxisType,-3,3);
if( $yt == 'lin' ) { if( $yt == 'lin' ) {
$this->yscale = new LinearScale($aYMin,$aYMax); $this->yscale = new LinearScale($aYMin,$aYMax);
} }
elseif( $yt == 'int' ) { elseif( $yt == 'int' ) {
$this->yscale = new LinearScale($aYMin,$aYMax); $this->yscale = new LinearScale($aYMin,$aYMax);
$this->yscale->SetIntScale(); $this->yscale->SetIntScale();
} }
elseif( $yt == 'log' ) { elseif( $yt == 'log' ) {
$this->yscale = new LogScale($aYMin,$aYMax); $this->yscale = new LogScale($aYMin,$aYMax);
} }
else { else {
JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)"); JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)");
} }
   
$xt=substr($aAxisType,0,3); $xt=substr($aAxisType,0,3);
if( $xt == 'lin' || $xt == 'tex' ) { if( $xt == 'lin' || $xt == 'tex' ) {
$this->xscale = new LinearScale($aXMin,$aXMax,'x'); $this->xscale = new LinearScale($aXMin,$aXMax,'x');
$this->xscale->textscale = ($xt == 'tex'); $this->xscale->textscale = ($xt == 'tex');
} }
elseif( $xt == 'int' ) { elseif( $xt == 'int' ) {
$this->xscale = new LinearScale($aXMin,$aXMax,'x'); $this->xscale = new LinearScale($aXMin,$aXMax,'x');
$this->xscale->SetIntScale(); $this->xscale->SetIntScale();
} }
elseif( $xt == 'dat' ) { elseif( $xt == 'dat' ) {
$this->xscale = new DateScale($aXMin,$aXMax,'x'); $this->xscale = new DateScale($aXMin,$aXMax,'x');
} }
elseif( $xt == 'log' ) { elseif( $xt == 'log' ) {
$this->xscale = new LogScale($aXMin,$aXMax,'x'); $this->xscale = new LogScale($aXMin,$aXMax,'x');
} }
else { else {
JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)"); JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)");
} }
   
$this->xaxis = new Axis($this->img,$this->xscale); $this->xaxis = new Axis($this->img,$this->xscale);
$this->yaxis = new Axis($this->img,$this->yscale); $this->yaxis = new Axis($this->img,$this->yscale);
$this->xgrid = new Grid($this->xaxis); $this->xgrid = new Grid($this->xaxis);
$this->ygrid = new Grid($this->yaxis); $this->ygrid = new Grid($this->yaxis);
$this->ygrid->Show(); $this->ygrid->Show();
} }
   
// Specify secondary Y scale // Specify secondary Y scale
function SetY2Scale($aAxisType='lin',$aY2Min=1,$aY2Max=1) { function SetY2Scale($aAxisType='lin',$aY2Min=1,$aY2Max=1) {
if( $aAxisType == 'lin' ) { if( $aAxisType == 'lin' ) {
$this->y2scale = new LinearScale($aY2Min,$aY2Max); $this->y2scale = new LinearScale($aY2Min,$aY2Max);
} }
elseif( $aAxisType == 'int' ) { elseif( $aAxisType == 'int' ) {
$this->y2scale = new LinearScale($aY2Min,$aY2Max); $this->y2scale = new LinearScale($aY2Min,$aY2Max);
$this->y2scale->SetIntScale(); $this->y2scale->SetIntScale();
} }
elseif( $aAxisType == 'log' ) { elseif( $aAxisType == 'log' ) {
$this->y2scale = new LogScale($aY2Min,$aY2Max); $this->y2scale = new LogScale($aY2Min,$aY2Max);
} }
else { else {
JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)"); 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 = new Axis($this->img,$this->y2scale);
$this->y2axis->scale->ticks->SetDirection(SIDE_LEFT); $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT);
$this->y2axis->SetLabelSide(SIDE_RIGHT); $this->y2axis->SetLabelSide(SIDE_RIGHT);
$this->y2axis->SetPos('max'); $this->y2axis->SetPos('max');
$this->y2axis->SetTitleSide(SIDE_RIGHT); $this->y2axis->SetTitleSide(SIDE_RIGHT);
   
// Deafult position is the max x-value // Deafult position is the max x-value
$this->y2grid = new Grid($this->y2axis); $this->y2grid = new Grid($this->y2axis);
} }
   
// Set the delta position (in pixels) between the multiple Y-axis // Set the delta position (in pixels) between the multiple Y-axis
function SetYDeltaDist($aDist) { function SetYDeltaDist($aDist) {
$this->iYAxisDeltaPos = $aDist; $this->iYAxisDeltaPos = $aDist;
} }
   
// Specify secondary Y scale // Specify secondary Y scale
function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) { function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) {
   
if( $aAxisType == 'lin' ) { if( $aAxisType == 'lin' ) {
$this->ynscale[$aN] = new LinearScale($aYMin,$aYMax); $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
} }
elseif( $aAxisType == 'int' ) { elseif( $aAxisType == 'int' ) {
$this->ynscale[$aN] = new LinearScale($aYMin,$aYMax); $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
$this->ynscale[$aN]->SetIntScale(); $this->ynscale[$aN]->SetIntScale();
} }
elseif( $aAxisType == 'log' ) { elseif( $aAxisType == 'log' ) {
$this->ynscale[$aN] = new LogScale($aYMin,$aYMax); $this->ynscale[$aN] = new LogScale($aYMin,$aYMax);
} }
else { else {
JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)"); 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] = new Axis($this->img,$this->ynscale[$aN]);
$this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT); $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT);
$this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT); $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT);
} }
   
// Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse' // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse'
// The dividing factor have been determined heuristically according to my aesthetic // The dividing factor have been determined heuristically according to my aesthetic
// sense (or lack off) y.m.m.v ! // sense (or lack off) y.m.m.v !
function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) { function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) {
$this->xtick_factor=30; $this->xtick_factor=30;
$this->ytick_factor=25; $this->ytick_factor=25;
switch( $aYDensity ) { switch( $aYDensity ) {
case TICKD_DENSE: case TICKD_DENSE:
$this->ytick_factor=12; $this->ytick_factor=12;
break; break;
case TICKD_NORMAL: case TICKD_NORMAL:
$this->ytick_factor=25; $this->ytick_factor=25;
break; break;
case TICKD_SPARSE: case TICKD_SPARSE:
$this->ytick_factor=40; $this->ytick_factor=40;
break; break;
case TICKD_VERYSPARSE: case TICKD_VERYSPARSE:
$this->ytick_factor=100; $this->ytick_factor=100;
break; break;
default: default:
JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy"); JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy");
} }
switch( $aXDensity ) { switch( $aXDensity ) {
case TICKD_DENSE: case TICKD_DENSE:
$this->xtick_factor=15; $this->xtick_factor=15;
break; break;
case TICKD_NORMAL: case TICKD_NORMAL:
$this->xtick_factor=30; $this->xtick_factor=30;
break; break;
case TICKD_SPARSE: case TICKD_SPARSE:
$this->xtick_factor=45; $this->xtick_factor=45;
break; break;
case TICKD_VERYSPARSE: case TICKD_VERYSPARSE:
$this->xtick_factor=60; $this->xtick_factor=60;
break; break;
default: default:
JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx"); JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx");
} }
} }
   
   
// Get a string of all image map areas // Get a string of all image map areas
function GetCSIMareas() { function GetCSIMareas() {
if( !$this->iHasStroked ) { if( !$this->iHasStroked ) {
$this->Stroke(_CSIM_SPECIALFILE); $this->Stroke(_CSIM_SPECIALFILE);
} }
   
$csim = $this->title->GetCSIMAreas(); $csim = $this->title->GetCSIMAreas();
$csim .= $this->subtitle->GetCSIMAreas(); $csim .= $this->subtitle->GetCSIMAreas();
$csim .= $this->subsubtitle->GetCSIMAreas(); $csim .= $this->subsubtitle->GetCSIMAreas();
$csim .= $this->legend->GetCSIMAreas(); $csim .= $this->legend->GetCSIMAreas();
   
if( $this->y2axis != NULL ) { if( $this->y2axis != NULL ) {
$csim .= $this->y2axis->title->GetCSIMAreas(); $csim .= $this->y2axis->title->GetCSIMAreas();
} }
   
if( $this->texts != null ) { if( $this->texts != null ) {
$n = count($this->texts); $n = count($this->texts);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$csim .= $this->texts[$i]->GetCSIMAreas(); $csim .= $this->texts[$i]->GetCSIMAreas();
} }
} }
   
if( $this->y2texts != null && $this->y2scale != null ) { if( $this->y2texts != null && $this->y2scale != null ) {
$n = count($this->y2texts); $n = count($this->y2texts);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$csim .= $this->y2texts[$i]->GetCSIMAreas(); $csim .= $this->y2texts[$i]->GetCSIMAreas();
} }
} }
   
if( $this->yaxis != null && $this->xaxis != null ) { if( $this->yaxis != null && $this->xaxis != null ) {
$csim .= $this->yaxis->title->GetCSIMAreas(); $csim .= $this->yaxis->title->GetCSIMAreas();
$csim .= $this->xaxis->title->GetCSIMAreas(); $csim .= $this->xaxis->title->GetCSIMAreas();
} }
   
$n = count($this->plots); $n = count($this->plots);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$csim .= $this->plots[$i]->GetCSIMareas(); $csim .= $this->plots[$i]->GetCSIMareas();
} }
   
$n = count($this->y2plots); $n = count($this->y2plots);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$csim .= $this->y2plots[$i]->GetCSIMareas(); $csim .= $this->y2plots[$i]->GetCSIMareas();
} }
   
$n = count($this->ynaxis); $n = count($this->ynaxis);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$m = count($this->ynplots[$i]); $m = count($this->ynplots[$i]);
for($j=0; $j < $m; ++$j ) { for($j=0; $j < $m; ++$j ) {
$csim .= $this->ynplots[$i][$j]->GetCSIMareas(); $csim .= $this->ynplots[$i][$j]->GetCSIMareas();
} }
} }
   
$n = count($this->iTables); $n = count($this->iTables);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$csim .= $this->iTables[$i]->GetCSIMareas(); $csim .= $this->iTables[$i]->GetCSIMareas();
} }
   
return $csim; return $csim;
} }
   
// Get a complete <MAP>..</MAP> tag for the final image map // Get a complete <MAP>..</MAP> tag for the final image map
function GetHTMLImageMap($aMapName) { function GetHTMLImageMap($aMapName) {
$im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n"; $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
$im .= $this->GetCSIMareas(); $im .= $this->GetCSIMareas();
$im .= "</map>"; $im .= "</map>";
return $im; return $im;
} }
   
function CheckCSIMCache($aCacheName,$aTimeOut=60) { function CheckCSIMCache($aCacheName,$aTimeOut=60) {
global $_SERVER; global $_SERVER;
   
if( $aCacheName=='auto' ) { if( $aCacheName=='auto' ) {
$aCacheName=basename($_SERVER['PHP_SELF']); $aCacheName=basename($_SERVER['PHP_SELF']);
} }
   
$urlarg = $this->GetURLArguments(); $urlarg = $this->GetURLArguments();
$this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg; $this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg;
$this->csimcachetimeout = $aTimeOut; $this->csimcachetimeout = $aTimeOut;
   
// First determine if we need to check for a cached version // First determine if we need to check for a cached version
// This differs from the standard cache in the sense that the // This differs from the standard cache in the sense that the
// image and CSIM map HTML file is written relative to the directory // image and CSIM map HTML file is written relative to the directory
// the script executes in and not the specified cache directory. // the script executes in and not the specified cache directory.
// The reason for this is that the cache directory is not necessarily // The reason for this is that the cache directory is not necessarily
// accessible from the HTTP server. // accessible from the HTTP server.
if( $this->csimcachename != '' ) { if( $this->csimcachename != '' ) {
$dir = dirname($this->csimcachename); $dir = dirname($this->csimcachename);
$base = basename($this->csimcachename); $base = basename($this->csimcachename);
$base = strtok($base,'.'); $base = strtok($base,'.');
$suffix = strtok('.'); $suffix = strtok('.');
$basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html'; $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
$baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format; $baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format;
   
$timedout=false; $timedout=false;
// Does it exist at all ? // Does it exist at all ?
   
if( file_exists($basecsim) && file_exists($baseimg) ) { if( file_exists($basecsim) && file_exists($baseimg) ) {
// Check that it hasn't timed out // Check that it hasn't timed out
$diff=time()-filemtime($basecsim); $diff=time()-filemtime($basecsim);
if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) { if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) {
$timedout=true; $timedout=true;
@unlink($basecsim); @unlink($basecsim);
@unlink($baseimg); @unlink($baseimg);
} }
else { else {
if ($fh = @fopen($basecsim, "r")) { if ($fh = @fopen($basecsim, "r")) {
fpassthru($fh); fpassthru($fh);
return true; return true;
} }
else { else {
JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading."); JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading.");
} }
} }
} }
} }
return false; return false;
} }
   
// Build the argument string to be used with the csim images // Build the argument string to be used with the csim images
static function GetURLArguments($aAddRecursiveBlocker=false) { static function GetURLArguments($aAddRecursiveBlocker=false) {
   
if( $aAddRecursiveBlocker ) { if( $aAddRecursiveBlocker ) {
// This is a JPGRAPH internal defined that prevents // This is a JPGRAPH internal defined that prevents
// us from recursively coming here again // us from recursively coming here again
$urlarg = _CSIM_DISPLAY.'=1'; $urlarg = _CSIM_DISPLAY.'=1';
} }
   
// Now reconstruct any user URL argument // Now reconstruct any user URL argument
reset($_GET); reset($_GET);
while( list($key,$value) = each($_GET) ) { while( list($key,$value) = each($_GET) ) {
if( is_array($value) ) { if( is_array($value) ) {
foreach ( $value as $k => $v ) { foreach ( $value as $k => $v ) {
$urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v); $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
} }
} }
else { else {
$urlarg .= '&amp;'.$key.'='.urlencode($value); $urlarg .= '&amp;'.$key.'='.urlencode($value);
} }
} }
   
// It's not ideal to convert POST argument to GET arguments // It's not ideal to convert POST argument to GET arguments
// but there is little else we can do. One idea for the // but there is little else we can do. One idea for the
// future might be recreate the POST header in case. // future might be recreate the POST header in case.
reset($_POST); reset($_POST);
while( list($key,$value) = each($_POST) ) { while( list($key,$value) = each($_POST) ) {
if( is_array($value) ) { if( is_array($value) ) {
foreach ( $value as $k => $v ) { foreach ( $value as $k => $v ) {
$urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v); $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
} }
} }
else { else {
$urlarg .= '&amp;'.$key.'='.urlencode($value); $urlarg .= '&amp;'.$key.'='.urlencode($value);
} }
} }
   
return $urlarg; return $urlarg;
} }
   
function SetCSIMImgAlt($aAlt) { function SetCSIMImgAlt($aAlt) {
$this->iCSIMImgAlt = $aAlt; $this->iCSIMImgAlt = $aAlt;
} }
   
function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) { function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) {
if( $aCSIMName=='' ) { if( $aCSIMName=='' ) {
// create a random map name // create a random map name
srand ((double) microtime() * 1000000); srand ((double) microtime() * 1000000);
$r = rand(0,100000); $r = rand(0,100000);
$aCSIMName='__mapname'.$r.'__'; $aCSIMName='__mapname'.$r.'__';
} }
   
if( $aScriptName=='auto' ) { if( $aScriptName=='auto' ) {
$aScriptName=basename($_SERVER['PHP_SELF']); $aScriptName=basename($_SERVER['PHP_SELF']);
} }
   
$urlarg = $this->GetURLArguments(true); $urlarg = $this->GetURLArguments(true);
   
if( empty($_GET[_CSIM_DISPLAY]) ) { if( empty($_GET[_CSIM_DISPLAY]) ) {
// First determine if we need to check for a cached version // First determine if we need to check for a cached version
// This differs from the standard cache in the sense that the // This differs from the standard cache in the sense that the
// image and CSIM map HTML file is written relative to the directory // image and CSIM map HTML file is written relative to the directory
// the script executes in and not the specified cache directory. // the script executes in and not the specified cache directory.
// The reason for this is that the cache directory is not necessarily // The reason for this is that the cache directory is not necessarily
// accessible from the HTTP server. // accessible from the HTTP server.
if( $this->csimcachename != '' ) { if( $this->csimcachename != '' ) {
$dir = dirname($this->csimcachename); $dir = dirname($this->csimcachename);
$base = basename($this->csimcachename); $base = basename($this->csimcachename);
$base = strtok($base,'.'); $base = strtok($base,'.');
$suffix = strtok('.'); $suffix = strtok('.');
$basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html'; $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
$baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format; $baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format;
   
// Check that apache can write to directory specified // Check that apache can write to directory specified
   
if( file_exists($dir) && !is_writeable($dir) ) { 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.'); JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.');
} }
   
// Make sure directory exists // Make sure directory exists
$this->cache->MakeDirs($dir); $this->cache->MakeDirs($dir);
   
// Write the image file // Write the image file
$this->Stroke(CSIMCACHE_DIR.$baseimg); $this->Stroke(CSIMCACHE_DIR.$baseimg);
   
// Construct wrapper HTML and write to file and send it back to browser // 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 // In the src URL we must replace the '?' with its encoding to prevent the arguments
// to be converted to real arguments. // to be converted to real arguments.
$tmp = str_replace('?','%3f',$baseimg); $tmp = str_replace('?','%3f',$baseimg);
$htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n". $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n".
'<img src="'.CSIMCACHE_HTTP_DIR.$tmp.'" ismap="ismap" usemap="#'.$aCSIMName.'" border="'.$aBorder.'" width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n"; '<img src="'.CSIMCACHE_HTTP_DIR.$tmp.'" ismap="ismap" usemap="#'.$aCSIMName.'" border="'.$aBorder.'" width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
   
if($fh = @fopen($basecsim,'w') ) { if($fh = @fopen($basecsim,'w') ) {
fwrite($fh,$htmlwrap); fwrite($fh,$htmlwrap);
fclose($fh); fclose($fh);
echo $htmlwrap; echo $htmlwrap;
} }
else { else {
JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions."); JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions.");
} }
} }
else { else {
   
if( $aScriptName=='' ) { 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().'); 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); echo $this->GetHTMLImageMap($aCSIMName) . $this->GetCSIMImgHTML($aCSIMName, $aScriptName, $aBorder);
} }
} }
else { else {
$this->Stroke(); $this->Stroke();
} }
} }
   
function StrokeCSIMImage() { function StrokeCSIMImage() {
if( @$_GET[_CSIM_DISPLAY] == 1 ) { if( @$_GET[_CSIM_DISPLAY] == 1 ) {
$this->Stroke(); $this->Stroke();
} }
} }
   
function GetCSIMImgHTML($aCSIMName, $aScriptName='auto', $aBorder=0 ) { function GetCSIMImgHTML($aCSIMName, $aScriptName='auto', $aBorder=0 ) {
if( $aScriptName=='auto' ) { if( $aScriptName=='auto' ) {
$aScriptName=basename($_SERVER['PHP_SELF']); $aScriptName=basename($_SERVER['PHP_SELF']);
} }
$urlarg = $this->GetURLArguments(true); $urlarg = $this->GetURLArguments(true);
return "<img src=\"".$aScriptName.'?'.$urlarg."\" ismap=\"ismap\" usemap=\"#".$aCSIMName.'" border="'.$aBorder.'" width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n"; return "<img src=\"".$aScriptName.'?'.$urlarg."\" ismap=\"ismap\" usemap=\"#".$aCSIMName.'" border="'.$aBorder.'" width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
} }
   
function GetTextsYMinMax($aY2=false) { function GetTextsYMinMax($aY2=false) {
if( $aY2 ) { if( $aY2 ) {
$txts = $this->y2texts; $txts = $this->y2texts;
} }
else { else {
$txts = $this->texts; $txts = $this->texts;
} }
$n = count($txts); $n = count($txts);
$min=null; $min=null;
$max=null; $max=null;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) { if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) {
if( $min === null ) { if( $min === null ) {
$min = $max = $txts[$i]->iScalePosY ; $min = $max = $txts[$i]->iScalePosY ;
} }
else { else {
$min = min($min,$txts[$i]->iScalePosY); $min = min($min,$txts[$i]->iScalePosY);
$max = max($max,$txts[$i]->iScalePosY); $max = max($max,$txts[$i]->iScalePosY);
} }
} }
} }
if( $min !== null ) { if( $min !== null ) {
return array($min,$max); return array($min,$max);
} }
else { else {
return null; return null;
} }
} }
   
function GetTextsXMinMax($aY2=false) { function GetTextsXMinMax($aY2=false) {
if( $aY2 ) { if( $aY2 ) {
$txts = $this->y2texts; $txts = $this->y2texts;
} }
else { else {
$txts = $this->texts; $txts = $this->texts;
} }
$n = count($txts); $n = count($txts);
$min=null; $min=null;
$max=null; $max=null;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) { if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) {
if( $min === null ) { if( $min === null ) {
$min = $max = $txts[$i]->iScalePosX ; $min = $max = $txts[$i]->iScalePosX ;
} }
else { else {
$min = min($min,$txts[$i]->iScalePosX); $min = min($min,$txts[$i]->iScalePosX);
$max = max($max,$txts[$i]->iScalePosX); $max = max($max,$txts[$i]->iScalePosX);
} }
} }
} }
if( $min !== null ) { if( $min !== null ) {
return array($min,$max); return array($min,$max);
} }
else { else {
return null; return null;
} }
} }
   
function GetXMinMax() { function GetXMinMax() {
   
list($min,$ymin) = $this->plots[0]->Min(); list($min,$ymin) = $this->plots[0]->Min();
list($max,$ymax) = $this->plots[0]->Max(); list($max,$ymax) = $this->plots[0]->Max();
   
$i=0; $i=0;
// Some plots, e.g. PlotLine should not affect the scale // Some plots, e.g. PlotLine should not affect the scale
// and will return (null,null). We should ignore those // and will return (null,null). We should ignore those
// values. // values.
while( ($min===null || $max === null) && ($i < count($this->plots)-1) ) { while( ($min===null || $max === null) && ($i < count($this->plots)-1) ) {
++$i; ++$i;
list($min,$ymin) = $this->plots[$i]->Min(); list($min,$ymin) = $this->plots[$i]->Min();
list($max,$ymax) = $this->plots[$i]->Max(); list($max,$ymax) = $this->plots[$i]->Max();
} }
   
foreach( $this->plots as $p ) { foreach( $this->plots as $p ) {
list($xmin,$ymin) = $p->Min(); list($xmin,$ymin) = $p->Min();
list($xmax,$ymax) = $p->Max(); list($xmax,$ymax) = $p->Max();
   
if( $xmin !== null && $xmax !== null ) { if( $xmin !== null && $xmax !== null ) {
$min = Min($xmin,$min); $min = Min($xmin,$min);
$max = Max($xmax,$max); $max = Max($xmax,$max);
} }
} }
   
if( $this->y2axis != null ) { if( $this->y2axis != null ) {
foreach( $this->y2plots as $p ) { foreach( $this->y2plots as $p ) {
list($xmin,$ymin) = $p->Min(); list($xmin,$ymin) = $p->Min();
list($xmax,$ymax) = $p->Max(); list($xmax,$ymax) = $p->Max();
$min = Min($xmin,$min); $min = Min($xmin,$min);
$max = Max($xmax,$max); $max = Max($xmax,$max);
} }
} }
   
$n = count($this->ynaxis); $n = count($this->ynaxis);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $this->ynaxis[$i] != null) { if( $this->ynaxis[$i] != null) {
foreach( $this->ynplots[$i] as $p ) { foreach( $this->ynplots[$i] as $p ) {
list($xmin,$ymin) = $p->Min(); list($xmin,$ymin) = $p->Min();
list($xmax,$ymax) = $p->Max(); list($xmax,$ymax) = $p->Max();
$min = Min($xmin,$min); $min = Min($xmin,$min);
$max = Max($xmax,$max); $max = Max($xmax,$max);
} }
} }
} }
return array($min,$max); return array($min,$max);
} }
   
function AdjustMarginsForTitles() { function AdjustMarginsForTitles() {
$totrequired = ($this->title->t != '' ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 : 0 ) + $totrequired = ($this->title->t != '' ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 : 0 ) +
($this->subtitle->t != '' ? $this->subtitle->GetTextHeight($this->img) + $this->subtitle->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 ) ; ($this->subsubtitle->t != '' ? $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 : 0 ) ;
   
$btotrequired = 0; $btotrequired = 0;
if($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels ) { if($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels ) {
// Minimum bottom margin // Minimum bottom margin
if( $this->xaxis->title->t != '' ) { if( $this->xaxis->title->t != '' ) {
if( $this->img->a == 90 ) { if( $this->img->a == 90 ) {
$btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 7 ; $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 7 ;
} }
else { else {
$btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 7 ; $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 7 ;
} }
} }
else { else {
$btotrequired = 0; $btotrequired = 0;
} }
   
if( $this->img->a == 90 ) { if( $this->img->a == 90 ) {
$this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style, $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style,
$this->yaxis->font_size); $this->yaxis->font_size);
$lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle); $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle);
} }
else { else {
$this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style, $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style,
$this->xaxis->font_size); $this->xaxis->font_size);
$lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle); $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle);
} }
   
$btotrequired += $lh + 6; $btotrequired += $lh + 6;
} }
   
if( $this->img->a == 90 ) { if( $this->img->a == 90 ) {
// DO Nothing. It gets too messy to do this properly for 90 deg... // DO Nothing. It gets too messy to do this properly for 90 deg...
} }
else{ else{
if( $this->img->top_margin < $totrequired ) { if( $this->img->top_margin < $totrequired ) {
$this->SetMargin($this->img->left_margin,$this->img->right_margin, $this->SetMargin($this->img->left_margin,$this->img->right_margin,
$totrequired,$this->img->bottom_margin); $totrequired,$this->img->bottom_margin);
} }
if( $this->img->bottom_margin < $btotrequired ) { if( $this->img->bottom_margin < $btotrequired ) {
$this->SetMargin($this->img->left_margin,$this->img->right_margin, $this->SetMargin($this->img->left_margin,$this->img->right_margin,
$this->img->top_margin,$btotrequired); $this->img->top_margin,$btotrequired);
} }
} }
} }
   
function StrokeStore($aStrokeFileName) { function StrokeStore($aStrokeFileName) {
// Get the handler to prevent the library from sending the // Get the handler to prevent the library from sending the
// image to the browser // image to the browser
$ih = $this->Stroke(_IMG_HANDLER); $ih = $this->Stroke(_IMG_HANDLER);
   
// Stroke it to a file // Stroke it to a file
$this->img->Stream($aStrokeFileName); $this->img->Stream($aStrokeFileName);
   
// Send it back to browser // Send it back to browser
$this->img->Headers(); $this->img->Headers();
$this->img->Stream(); $this->img->Stream();
} }
   
function doAutoscaleXAxis() { function doAutoscaleXAxis() {
//Check if we should autoscale x-axis //Check if we should autoscale x-axis
if( !$this->xscale->IsSpecified() ) { if( !$this->xscale->IsSpecified() ) {
if( substr($this->axtype,0,4) == "text" ) { if( substr($this->axtype,0,4) == "text" ) {
$max=0; $max=0;
$n = count($this->plots); $n = count($this->plots);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$p = $this->plots[$i]; $p = $this->plots[$i];
// We need some unfortunate sub class knowledge here in order // We need some unfortunate sub class knowledge here in order
// to increase number of data points in case it is a line plot // 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 // which has the barcenter set. If not it could mean that the
// last point of the data is outside the scale since the barcenter // 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 // 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. // to the right in oder to align with the center of the bars.
if( class_exists('BarPlot',false) ) { if( class_exists('BarPlot',false) ) {
$cl = strtolower(get_class($p)); $cl = strtolower(get_class($p));
if( (class_exists('BarPlot',false) && ($p instanceof BarPlot)) || empty($p->barcenter) ) { if( (class_exists('BarPlot',false) && ($p instanceof BarPlot)) || empty($p->barcenter) ) {
$max=max($max,$p->numpoints-1); $max=max($max,$p->numpoints-1);
} }
else { else {
$max=max($max,$p->numpoints); $max=max($max,$p->numpoints);
} }
} }
else { else {
if( empty($p->barcenter) ) { if( empty($p->barcenter) ) {
$max=max($max,$p->numpoints-1); $max=max($max,$p->numpoints-1);
} }
else { else {
$max=max($max,$p->numpoints); $max=max($max,$p->numpoints);
} }
} }
} }
$min=0; $min=0;
if( $this->y2axis != null ) { if( $this->y2axis != null ) {
foreach( $this->y2plots as $p ) { foreach( $this->y2plots as $p ) {
$max=max($max,$p->numpoints-1); $max=max($max,$p->numpoints-1);
} }
} }
$n = count($this->ynaxis); $n = count($this->ynaxis);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $this->ynaxis[$i] != null) { if( $this->ynaxis[$i] != null) {
foreach( $this->ynplots[$i] as $p ) { foreach( $this->ynplots[$i] as $p ) {
$max=max($max,$p->numpoints-1); $max=max($max,$p->numpoints-1);
} }
} }
} }
   
$this->xscale->Update($this->img,$min,$max); $this->xscale->Update($this->img,$min,$max);
$this->xscale->ticks->Set($this->xaxis->tick_step,1); $this->xscale->ticks->Set($this->xaxis->tick_step,1);
$this->xscale->ticks->SupressMinorTickMarks(); $this->xscale->ticks->SupressMinorTickMarks();
} }
else { else {
list($min,$max) = $this->GetXMinMax(); list($min,$max) = $this->GetXMinMax();
   
$lres = $this->GetLinesXMinMax($this->lines); $lres = $this->GetLinesXMinMax($this->lines);
if( $lres ) { if( $lres ) {
list($linmin,$linmax) = $lres ; list($linmin,$linmax) = $lres ;
$min = min($min,$linmin); $min = min($min,$linmin);
$max = max($max,$linmax); $max = max($max,$linmax);
} }
   
$lres = $this->GetLinesXMinMax($this->y2lines); $lres = $this->GetLinesXMinMax($this->y2lines);
if( $lres ) { if( $lres ) {
list($linmin,$linmax) = $lres ; list($linmin,$linmax) = $lres ;
$min = min($min,$linmin); $min = min($min,$linmin);
$max = max($max,$linmax); $max = max($max,$linmax);
} }
   
$tres = $this->GetTextsXMinMax(); $tres = $this->GetTextsXMinMax();
if( $tres ) { if( $tres ) {
list($tmin,$tmax) = $tres ; list($tmin,$tmax) = $tres ;
$min = min($min,$tmin); $min = min($min,$tmin);
$max = max($max,$tmax); $max = max($max,$tmax);
} }
   
$tres = $this->GetTextsXMinMax(true); $tres = $this->GetTextsXMinMax(true);
if( $tres ) { if( $tres ) {
list($tmin,$tmax) = $tres ; list($tmin,$tmax) = $tres ;
$min = min($min,$tmin); $min = min($min,$tmin);
$max = max($max,$tmax); $max = max($max,$tmax);
} }
   
$this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor)); $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 //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) ) { if( !is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos) ) {
$this->yaxis->SetPos($this->xscale->GetMinVal()); $this->yaxis->SetPos($this->xscale->GetMinVal());
} }
} }
elseif( $this->xscale->IsSpecified() && elseif( $this->xscale->IsSpecified() &&
( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) { ( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) {
// The tick calculation will use the user suplied min/max values to determine // 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 // the ticks. If auto_ticks is false the exact user specifed min and max
// values will be used for the scale. // values will be used for the scale.
// If auto_ticks is true then the scale might be slightly adjusted // 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. // so that the min and max values falls on an even major step.
$min = $this->xscale->scale[0]; $min = $this->xscale->scale[0];
$max = $this->xscale->scale[1]; $max = $this->xscale->scale[1];
$this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor),false); $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 // Now make sure we show enough precision to accurate display the
// labels. If this is not done then the user might end up with // 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 // a scale that might actually start with, say 13.5, butdue to rounding
// the scale label will ony show 14. // the scale label will ony show 14.
if( abs(floor($min)-$min) > 0 ) { if( abs(floor($min)-$min) > 0 ) {
   
// If the user has set a format then we bail out // If the user has set a format then we bail out
if( $this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '' ) { if( $this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '' ) {
$this->xscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; $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 // Position the optional Y2 and Yn axis to the rightmost position of the x-axis
if( $this->y2axis != null ) { if( $this->y2axis != null ) {
if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) { if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) {
$this->y2axis->SetPos($this->xscale->GetMaxVal()); $this->y2axis->SetPos($this->xscale->GetMaxVal());
} }
$this->y2axis->SetTitleSide(SIDE_RIGHT); $this->y2axis->SetTitleSide(SIDE_RIGHT);
} }
   
$n = count($this->ynaxis); $n = count($this->ynaxis);
$nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0; $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $this->ynaxis[$i] != null ) { if( $this->ynaxis[$i] != null ) {
if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) { if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) {
$this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal()); $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal());
$this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj); $this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj);
} }
$this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT); $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT);
} }
} }
} }
   
   
function doAutoScaleYnAxis() { function doAutoScaleYnAxis() {
   
if( $this->y2scale != null) { if( $this->y2scale != null) {
if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) { if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) {
list($min,$max) = $this->GetPlotsYMinMax($this->y2plots); list($min,$max) = $this->GetPlotsYMinMax($this->y2plots);
   
$lres = $this->GetLinesYMinMax($this->y2lines); $lres = $this->GetLinesYMinMax($this->y2lines);
if( is_array($lres) ) { if( is_array($lres) ) {
list($linmin,$linmax) = $lres ; list($linmin,$linmax) = $lres ;
$min = min($min,$linmin); $min = min($min,$linmin);
$max = max($max,$linmax); $max = max($max,$linmax);
} }
$tres = $this->GetTextsYMinMax(true); $tres = $this->GetTextsYMinMax(true);
if( is_array($tres) ) { if( is_array($tres) ) {
list($tmin,$tmax) = $tres ; list($tmin,$tmax) = $tres ;
$min = min($min,$tmin); $min = min($min,$tmin);
$max = max($max,$tmax); $max = max($max,$tmax);
} }
$this->y2scale->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor); $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()) ) { 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 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 // the ticks. If auto_ticks is false the exact user specifed min and max
// values will be used for the scale. // values will be used for the scale.
// If auto_ticks is true then the scale might be slightly adjusted // 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. // so that the min and max values falls on an even major step.
$min = $this->y2scale->scale[0]; $min = $this->y2scale->scale[0];
$max = $this->y2scale->scale[1]; $max = $this->y2scale->scale[1];
$this->y2scale->AutoScale($this->img,$min,$max, $this->y2scale->AutoScale($this->img,$min,$max,
$this->img->plotheight/$this->ytick_factor, $this->img->plotheight/$this->ytick_factor,
$this->y2scale->auto_ticks); $this->y2scale->auto_ticks);
   
// Now make sure we show enough precision to accurate display the // Now make sure we show enough precision to accurate display the
// labels. If this is not done then the user might end up with // 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 // a scale that might actually start with, say 13.5, butdue to rounding
// the scale label will ony show 14. // the scale label will ony show 14.
if( abs(floor($min)-$min) > 0 ) { if( abs(floor($min)-$min) > 0 ) {
// If the user has set a format then we bail out // If the user has set a format then we bail out
if( $this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '' ) { if( $this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '' ) {
$this->y2scale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; $this->y2scale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
} }
} }
   
} }
} }
   
   
// //
// Autoscale the extra Y-axises // Autoscale the extra Y-axises
// //
$n = count($this->ynaxis); $n = count($this->ynaxis);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $this->ynscale[$i] != null) { if( $this->ynscale[$i] != null) {
if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) { if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) {
list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]); list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]);
$this->ynscale[$i]->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor); $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()) ) { 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 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 // the ticks. If auto_ticks is false the exact user specifed min and max
// values will be used for the scale. // values will be used for the scale.
// If auto_ticks is true then the scale might be slightly adjusted // 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. // so that the min and max values falls on an even major step.
$min = $this->ynscale[$i]->scale[0]; $min = $this->ynscale[$i]->scale[0];
$max = $this->ynscale[$i]->scale[1]; $max = $this->ynscale[$i]->scale[1];
$this->ynscale[$i]->AutoScale($this->img,$min,$max, $this->ynscale[$i]->AutoScale($this->img,$min,$max,
$this->img->plotheight/$this->ytick_factor, $this->img->plotheight/$this->ytick_factor,
$this->ynscale[$i]->auto_ticks); $this->ynscale[$i]->auto_ticks);
   
// Now make sure we show enough precision to accurate display the // Now make sure we show enough precision to accurate display the
// labels. If this is not done then the user might end up with // 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 // a scale that might actually start with, say 13.5, butdue to rounding
// the scale label will ony show 14. // the scale label will ony show 14.
if( abs(floor($min)-$min) > 0 ) { if( abs(floor($min)-$min) > 0 ) {
// If the user has set a format then we bail out // If the user has set a format then we bail out
if( $this->ynscale[$i]->ticks->label_formatstr == '' && $this->ynscale[$i]->ticks->label_dateformatstr == '' ) { 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; $this->ynscale[$i]->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
} }
} }
} }
} }
} }
} }
   
function doAutoScaleYAxis() { function doAutoScaleYAxis() {
   
//Check if we should autoscale y-axis //Check if we should autoscale y-axis
if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) { if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) {
list($min,$max) = $this->GetPlotsYMinMax($this->plots); list($min,$max) = $this->GetPlotsYMinMax($this->plots);
$lres = $this->GetLinesYMinMax($this->lines); $lres = $this->GetLinesYMinMax($this->lines);
if( is_array($lres) ) { if( is_array($lres) ) {
list($linmin,$linmax) = $lres ; list($linmin,$linmax) = $lres ;
$min = min($min,$linmin); $min = min($min,$linmin);
$max = max($max,$linmax); $max = max($max,$linmax);
} }
$tres = $this->GetTextsYMinMax(); $tres = $this->GetTextsYMinMax();
if( is_array($tres) ) { if( is_array($tres) ) {
list($tmin,$tmax) = $tres ; list($tmin,$tmax) = $tres ;
$min = min($min,$tmin); $min = min($min,$tmin);
$max = max($max,$tmax); $max = max($max,$tmax);
} }
$this->yscale->AutoScale($this->img,$min,$max, $this->yscale->AutoScale($this->img,$min,$max,
$this->img->plotheight/$this->ytick_factor); $this->img->plotheight/$this->ytick_factor);
} }
elseif( $this->yscale->IsSpecified() && ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) { 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 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 // the ticks. If auto_ticks is false the exact user specifed min and max
// values will be used for the scale. // values will be used for the scale.
// If auto_ticks is true then the scale might be slightly adjusted // 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. // so that the min and max values falls on an even major step.
$min = $this->yscale->scale[0]; $min = $this->yscale->scale[0];
$max = $this->yscale->scale[1]; $max = $this->yscale->scale[1];
$this->yscale->AutoScale($this->img,$min,$max, $this->yscale->AutoScale($this->img,$min,$max,
$this->img->plotheight/$this->ytick_factor, $this->img->plotheight/$this->ytick_factor,
$this->yscale->auto_ticks); $this->yscale->auto_ticks);
   
// Now make sure we show enough precision to accurate display the // Now make sure we show enough precision to accurate display the
// labels. If this is not done then the user might end up with // 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 // a scale that might actually start with, say 13.5, butdue to rounding
// the scale label will ony show 14. // the scale label will ony show 14.
if( abs(floor($min)-$min) > 0 ) { if( abs(floor($min)-$min) > 0 ) {
   
// If the user has set a format then we bail out // If the user has set a format then we bail out
if( $this->yscale->ticks->label_formatstr == '' && $this->yscale->ticks->label_dateformatstr == '' ) { if( $this->yscale->ticks->label_formatstr == '' && $this->yscale->ticks->label_dateformatstr == '' ) {
$this->yscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1; $this->yscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
} }
} }
} }
   
} }
   
function InitScaleConstants() { function InitScaleConstants() {
// Setup scale constants // Setup scale constants
if( $this->yscale ) $this->yscale->InitConstants($this->img); if( $this->yscale ) $this->yscale->InitConstants($this->img);
if( $this->xscale ) $this->xscale->InitConstants($this->img); if( $this->xscale ) $this->xscale->InitConstants($this->img);
if( $this->y2scale ) $this->y2scale->InitConstants($this->img); if( $this->y2scale ) $this->y2scale->InitConstants($this->img);
   
$n=count($this->ynscale); $n=count($this->ynscale);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $this->ynscale[$i] ) { if( $this->ynscale[$i] ) {
$this->ynscale[$i]->InitConstants($this->img); $this->ynscale[$i]->InitConstants($this->img);
} }
} }
} }
   
function doPrestrokeAdjustments() { function doPrestrokeAdjustments() {
   
// Do any pre-stroke adjustment that is needed by the different plot types // 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) // (i.e bar plots want's to add an offset to the x-labels etc)
for($i=0; $i < count($this->plots) ; ++$i ) { for($i=0; $i < count($this->plots) ; ++$i ) {
$this->plots[$i]->PreStrokeAdjust($this); $this->plots[$i]->PreStrokeAdjust($this);
$this->plots[$i]->DoLegend($this); $this->plots[$i]->DoLegend($this);
} }
   
// Any plots on the second Y scale? // Any plots on the second Y scale?
if( $this->y2scale != null ) { if( $this->y2scale != null ) {
for($i=0; $i<count($this->y2plots) ; ++$i ) { for($i=0; $i<count($this->y2plots) ; ++$i ) {
$this->y2plots[$i]->PreStrokeAdjust($this); $this->y2plots[$i]->PreStrokeAdjust($this);
$this->y2plots[$i]->DoLegend($this); $this->y2plots[$i]->DoLegend($this);
} }
} }
   
// Any plots on the extra Y axises? // Any plots on the extra Y axises?
$n = count($this->ynaxis); $n = count($this->ynaxis);
for($i=0; $i<$n ; ++$i ) { for($i=0; $i<$n ; ++$i ) {
if( $this->ynplots == null || $this->ynplots[$i] == null) { if( $this->ynplots == null || $this->ynplots[$i] == null) {
JpGraphError::RaiseL(25032,$i);//("No plots for Y-axis nbr:$i"); JpGraphError::RaiseL(25032,$i);//("No plots for Y-axis nbr:$i");
} }
$m = count($this->ynplots[$i]); $m = count($this->ynplots[$i]);
for($j=0; $j < $m; ++$j ) { for($j=0; $j < $m; ++$j ) {
$this->ynplots[$i][$j]->PreStrokeAdjust($this); $this->ynplots[$i][$j]->PreStrokeAdjust($this);
$this->ynplots[$i][$j]->DoLegend($this); $this->ynplots[$i][$j]->DoLegend($this);
} }
} }
} }
   
function StrokeBands($aDepth,$aCSIM) { function StrokeBands($aDepth,$aCSIM) {
// Stroke bands // Stroke bands
if( $this->bands != null && !$aCSIM) { if( $this->bands != null && !$aCSIM) {
for($i=0; $i < count($this->bands); ++$i) { for($i=0; $i < count($this->bands); ++$i) {
// Stroke all bands that asks to be in the background // Stroke all bands that asks to be in the background
if( $this->bands[$i]->depth == $aDepth ) { if( $this->bands[$i]->depth == $aDepth ) {
$this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale); $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale);
} }
} }
} }
   
if( $this->y2bands != null && $this->y2scale != null && !$aCSIM ) { if( $this->y2bands != null && $this->y2scale != null && !$aCSIM ) {
for($i=0; $i < count($this->y2bands); ++$i) { for($i=0; $i < count($this->y2bands); ++$i) {
// Stroke all bands that asks to be in the foreground // Stroke all bands that asks to be in the foreground
if( $this->y2bands[$i]->depth == $aDepth ) { if( $this->y2bands[$i]->depth == $aDepth ) {
$this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale); $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
} }
} }
} }
} }
   
   
// Stroke the graph // Stroke the graph
// $aStrokeFileName If != "" the image will be written to this file and NOT // $aStrokeFileName If != "" the image will be written to this file and NOT
// streamed back to the browser // streamed back to the browser
function Stroke($aStrokeFileName='') { function Stroke($aStrokeFileName='') {
   
// Fist make a sanity check that user has specified a scale // Fist make a sanity check that user has specified a scale
if( empty($this->yscale) ) { if( empty($this->yscale) ) {
JpGraphError::RaiseL(25031);//('You must specify what scale to use with a call to Graph::SetScale().'); 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. // Start by adjusting the margin so that potential titles will fit.
$this->AdjustMarginsForTitles(); $this->AdjustMarginsForTitles();
   
// Give the plot a chance to do any scale adjuments the individual plots // 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 // wants to do. Right now this is only used by the contour plot to set scale
// limits // limits
for($i=0; $i < count($this->plots) ; ++$i ) { for($i=0; $i < count($this->plots) ; ++$i ) {
$this->plots[$i]->PreScaleSetup($this); $this->plots[$i]->PreScaleSetup($this);
} }
   
// Init scale constants that are used to calculate the transformation from // Init scale constants that are used to calculate the transformation from
// world to pixel coordinates // world to pixel coordinates
$this->InitScaleConstants(); $this->InitScaleConstants();
   
// If the filename is the predefined value = '_csim_special_' // If the filename is the predefined value = '_csim_special_'
// we assume that the call to stroke only needs to do enough // we assume that the call to stroke only needs to do enough
// to correctly generate the CSIM maps. // to correctly generate the CSIM maps.
// We use this variable to skip things we don't strictly need // We use this variable to skip things we don't strictly need
// to do to generate the image map to improve performance // 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 // a best we can. Therefor you will see a lot of tests !$_csim in the
// code below. // code below.
$_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
   
// If we are called the second time (perhaps the user has called GetHTMLImageMap() // 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 // 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 // CSIM coordinats. Since we do not want the legends to be populated a second time
// we clear the legends // we clear the legends
$this->legend->Clear(); $this->legend->Clear();
   
// We need to know if we have stroked the plot in the // We need to know if we have stroked the plot in the
// GetCSIMareas. Otherwise the CSIM hasn't been generated // GetCSIMareas. Otherwise the CSIM hasn't been generated
// and in the case of GetCSIM called before stroke to generate // and in the case of GetCSIM called before stroke to generate
// CSIM without storing an image to disk GetCSIM must call Stroke. // CSIM without storing an image to disk GetCSIM must call Stroke.
$this->iHasStroked = true; $this->iHasStroked = true;
   
// Setup pre-stroked adjustments and Legends // Setup pre-stroked adjustments and Legends
$this->doPrestrokeAdjustments(); $this->doPrestrokeAdjustments();
   
// Bail out if any of the Y-axis not been specified and // Bail out if any of the Y-axis not been specified and
// has no plots. (This means it is impossible to do autoscaling 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 // 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. // scaling you also have to supply the tick steps as well.
if( (!$this->yscale->IsSpecified() && count($this->plots)==0) || if( (!$this->yscale->IsSpecified() && count($this->plots)==0) ||
($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) { ($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) {
//$e = "n=".count($this->y2plots)."\n"; //$e = "n=".count($this->y2plots)."\n";
// $e = "Can't draw unspecified Y-scale.<br>\nYou have either:<br>\n"; // $e = "Can't draw unspecified Y-scale.<br>\nYou have either:<br>\n";
// $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots<br>\n"; // $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots<br>\n";
// $e .= "2. Specified a scale manually but have forgot to specify the tick steps"; // $e .= "2. Specified a scale manually but have forgot to specify the tick steps";
JpGraphError::RaiseL(25026); JpGraphError::RaiseL(25026);
} }
   
// Bail out if no plots and no specified X-scale // Bail out if no plots and no specified X-scale
if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) ) { if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) ) {
JpGraphError::RaiseL(25034);//("<strong>JpGraph: Can't draw unspecified X-scale.</strong><br>No plots.<br>"); JpGraphError::RaiseL(25034);//("<strong>JpGraph: Can't draw unspecified X-scale.</strong><br>No plots.<br>");
} }
   
// Autoscale the normal Y-axis // Autoscale the normal Y-axis
$this->doAutoScaleYAxis(); $this->doAutoScaleYAxis();
   
// Autoscale all additiopnal y-axis // Autoscale all additiopnal y-axis
$this->doAutoScaleYnAxis(); $this->doAutoScaleYnAxis();
   
// Autoscale the regular x-axis and position the y-axis properly // Autoscale the regular x-axis and position the y-axis properly
$this->doAutoScaleXAxis(); $this->doAutoScaleXAxis();
   
// If we have a negative values and x-axis position is at 0 // 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 // 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) // 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 test below might seem strange the reasone being that if
// the user hasn't specified a value for position this will not // 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 // be set until we do the stroke for the axis so as of now it
// is undefined. // is undefined.
// For X-text scale we ignore all this since the tick are usually // 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 // much further in and not close to the Y-axis. Hence the test
// for 'text' // for 'text'
if( ($this->yaxis->pos==$this->xscale->GetMinVal() || (is_string($this->yaxis->pos) && $this->yaxis->pos=='min')) && 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 && !is_numeric($this->xaxis->pos) && $this->yscale->GetMinVal() < 0 &&
substr($this->axtype,0,4) != 'text' && $this->xaxis->pos != 'min' ) { substr($this->axtype,0,4) != 'text' && $this->xaxis->pos != 'min' ) {
   
//$this->yscale->ticks->SupressZeroLabel(false); //$this->yscale->ticks->SupressZeroLabel(false);
$this->xscale->ticks->SupressFirst(); $this->xscale->ticks->SupressFirst();
if( $this->y2axis != null ) { if( $this->y2axis != null ) {
$this->xscale->ticks->SupressLast(); $this->xscale->ticks->SupressLast();
} }
} }
elseif( !is_numeric($this->yaxis->pos) && $this->yaxis->pos=='max' ) { elseif( !is_numeric($this->yaxis->pos) && $this->yaxis->pos=='max' ) {
$this->xscale->ticks->SupressLast(); $this->xscale->ticks->SupressLast();
} }
   
if( !$_csim ) { if( !$_csim ) {
$this->StrokePlotArea(); $this->StrokePlotArea();
if( $this->iIconDepth == DEPTH_BACK ) { if( $this->iIconDepth == DEPTH_BACK ) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
} }
$this->StrokeAxis(false); $this->StrokeAxis(false);
   
// Stroke colored bands // Stroke colored bands
$this->StrokeBands(DEPTH_BACK,$_csim); $this->StrokeBands(DEPTH_BACK,$_csim);
   
if( $this->grid_depth == DEPTH_BACK && !$_csim) { if( $this->grid_depth == DEPTH_BACK && !$_csim) {
$this->ygrid->Stroke(); $this->ygrid->Stroke();
$this->xgrid->Stroke(); $this->xgrid->Stroke();
} }
   
// Stroke Y2-axis // Stroke Y2-axis
if( $this->y2axis != null && !$_csim) { if( $this->y2axis != null && !$_csim) {
$this->y2axis->Stroke($this->xscale); $this->y2axis->Stroke($this->xscale);
$this->y2grid->Stroke(); $this->y2grid->Stroke();
} }
   
// Stroke yn-axis // Stroke yn-axis
$n = count($this->ynaxis); $n = count($this->ynaxis);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->ynaxis[$i]->Stroke($this->xscale); $this->ynaxis[$i]->Stroke($this->xscale);
} }
   
$oldoff=$this->xscale->off; $oldoff=$this->xscale->off;
if( substr($this->axtype,0,4) == 'text' ) { if( substr($this->axtype,0,4) == 'text' ) {
if( $this->text_scale_abscenteroff > -1 ) { if( $this->text_scale_abscenteroff > -1 ) {
// For a text scale the scale factor is the number of pixel per step. // 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 // 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 // per major scale step and use that in order to adjust the offset so that
// an object of width "abscenteroff" becomes centered. // an object of width "abscenteroff" becomes centered.
$this->xscale->off += round($this->xscale->scale_factor/2)-round($this->text_scale_abscenteroff/2); $this->xscale->off += round($this->xscale->scale_factor/2)-round($this->text_scale_abscenteroff/2);
} }
else { else {
$this->xscale->off += ceil($this->xscale->scale_factor*$this->text_scale_off*$this->xscale->ticks->minor_step); $this->xscale->off += ceil($this->xscale->scale_factor*$this->text_scale_off*$this->xscale->ticks->minor_step);
} }
} }
   
if( $this->iDoClipping ) { if( $this->iDoClipping ) {
$oldimage = $this->img->CloneCanvasH(); $oldimage = $this->img->CloneCanvasH();
} }
   
if( ! $this->y2orderback ) { if( ! $this->y2orderback ) {
// Stroke all plots for Y1 axis // Stroke all plots for Y1 axis
for($i=0; $i < count($this->plots); ++$i) { for($i=0; $i < count($this->plots); ++$i) {
$this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale); $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale);
$this->plots[$i]->StrokeMargin($this->img); $this->plots[$i]->StrokeMargin($this->img);
} }
} }
   
// Stroke all plots for Y2 axis // Stroke all plots for Y2 axis
if( $this->y2scale != null ) { if( $this->y2scale != null ) {
for($i=0; $i< count($this->y2plots); ++$i ) { for($i=0; $i< count($this->y2plots); ++$i ) {
$this->y2plots[$i]->Stroke($this->img,$this->xscale,$this->y2scale); $this->y2plots[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
} }
} }
   
if( $this->y2orderback ) { if( $this->y2orderback ) {
// Stroke all plots for Y1 axis // Stroke all plots for Y1 axis
for($i=0; $i < count($this->plots); ++$i) { for($i=0; $i < count($this->plots); ++$i) {
$this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale); $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale);
$this->plots[$i]->StrokeMargin($this->img); $this->plots[$i]->StrokeMargin($this->img);
} }
} }
   
$n = count($this->ynaxis); $n = count($this->ynaxis);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$m = count($this->ynplots[$i]); $m = count($this->ynplots[$i]);
for( $j=0; $j < $m; ++$j ) { for( $j=0; $j < $m; ++$j ) {
$this->ynplots[$i][$j]->Stroke($this->img,$this->xscale,$this->ynscale[$i]); $this->ynplots[$i][$j]->Stroke($this->img,$this->xscale,$this->ynscale[$i]);
$this->ynplots[$i][$j]->StrokeMargin($this->img); $this->ynplots[$i][$j]->StrokeMargin($this->img);
} }
} }
   
if( $this->iIconDepth == DEPTH_FRONT) { if( $this->iIconDepth == DEPTH_FRONT) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
   
if( $this->iDoClipping ) { if( $this->iDoClipping ) {
// Clipping only supports graphs at 0 and 90 degrees // Clipping only supports graphs at 0 and 90 degrees
if( $this->img->a == 0 ) { if( $this->img->a == 0 ) {
$this->img->CopyCanvasH($oldimage,$this->img->img, $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->left_margin,$this->img->top_margin, $this->img->left_margin,$this->img->top_margin,
$this->img->plotwidth+1,$this->img->plotheight); $this->img->plotwidth+1,$this->img->plotheight);
} }
elseif( $this->img->a == 90 ) { elseif( $this->img->a == 90 ) {
$adj = ($this->img->height - $this->img->width)/2; $adj = ($this->img->height - $this->img->width)/2;
$this->img->CopyCanvasH($oldimage,$this->img->img, $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->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); $this->img->plotheight+1,$this->img->plotwidth);
} }
else { 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.'); 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->Destroy();
$this->img->SetCanvasH($oldimage); $this->img->SetCanvasH($oldimage);
} }
   
$this->xscale->off=$oldoff; $this->xscale->off=$oldoff;
   
if( $this->grid_depth == DEPTH_FRONT && !$_csim ) { if( $this->grid_depth == DEPTH_FRONT && !$_csim ) {
$this->ygrid->Stroke(); $this->ygrid->Stroke();
$this->xgrid->Stroke(); $this->xgrid->Stroke();
} }
   
// Stroke colored bands // Stroke colored bands
$this->StrokeBands(DEPTH_FRONT,$_csim); $this->StrokeBands(DEPTH_FRONT,$_csim);
   
// Finally draw the axis again since some plots may have nagged // Finally draw the axis again since some plots may have nagged
// the axis in the edges. // the axis in the edges.
if( !$_csim ) { if( !$_csim ) {
$this->StrokeAxis(); $this->StrokeAxis();
} }
   
if( $this->y2scale != null && !$_csim ) { if( $this->y2scale != null && !$_csim ) {
$this->y2axis->Stroke($this->xscale,false); $this->y2axis->Stroke($this->xscale,false);
} }
   
if( !$_csim ) { if( !$_csim ) {
$this->StrokePlotBox(); $this->StrokePlotBox();
} }
   
// The titles and legends never gets rotated so make sure // The titles and legends never gets rotated so make sure
// that the angle is 0 before stroking them // that the angle is 0 before stroking them
$aa = $this->img->SetAngle(0); $aa = $this->img->SetAngle(0);
$this->StrokeTitles(); $this->StrokeTitles();
$this->footer->Stroke($this->img); $this->footer->Stroke($this->img);
$this->legend->Stroke($this->img); $this->legend->Stroke($this->img);
$this->img->SetAngle($aa); $this->img->SetAngle($aa);
$this->StrokeTexts(); $this->StrokeTexts();
$this->StrokeTables(); $this->StrokeTables();
   
if( !$_csim ) { if( !$_csim ) {
   
$this->img->SetAngle($aa); $this->img->SetAngle($aa);
   
// Draw an outline around the image map // Draw an outline around the image map
if(_JPG_DEBUG) { if(_JPG_DEBUG) {
$this->DisplayClientSideaImageMapAreas(); $this->DisplayClientSideaImageMapAreas();
} }
   
// Should we do any final image transformation // Should we do any final image transformation
if( $this->iImgTrans ) { if( $this->iImgTrans ) {
if( !class_exists('ImgTrans',false) ) { if( !class_exists('ImgTrans',false) ) {
require_once('jpgraph_imgtrans.php'); require_once('jpgraph_imgtrans.php');
//JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.'); //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); $tform = new ImgTrans($this->img->img);
$this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
$this->iImgTransDirection,$this->iImgTransHighQ, $this->iImgTransDirection,$this->iImgTransHighQ,
$this->iImgTransMinSize,$this->iImgTransFillColor, $this->iImgTransMinSize,$this->iImgTransFillColor,
$this->iImgTransBorder); $this->iImgTransBorder);
} }
   
// If the filename is given as the special "__handle" // If the filename is given as the special "__handle"
// then the image handler is returned and the image is NOT // then the image handler is returned and the image is NOT
// streamed back // streamed back
if( $aStrokeFileName == _IMG_HANDLER ) { if( $aStrokeFileName == _IMG_HANDLER ) {
return $this->img->img; return $this->img->img;
} }
else { else {
// Finally stream the generated picture // Finally stream the generated picture
$this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
} }
} }
} }
   
function SetAxisLabelBackground($aType,$aXFColor='lightgray',$aXColor='black',$aYFColor='lightgray',$aYColor='black') { function SetAxisLabelBackground($aType,$aXFColor='lightgray',$aXColor='black',$aYFColor='lightgray',$aYColor='black') {
$this->iAxisLblBgType = $aType; $this->iAxisLblBgType = $aType;
$this->iXAxisLblBgFillColor = $aXFColor; $this->iXAxisLblBgFillColor = $aXFColor;
$this->iXAxisLblBgColor = $aXColor; $this->iXAxisLblBgColor = $aXColor;
$this->iYAxisLblBgFillColor = $aYFColor; $this->iYAxisLblBgFillColor = $aYFColor;
$this->iYAxisLblBgColor = $aYColor; $this->iYAxisLblBgColor = $aYColor;
} }
   
function StrokeAxisLabelBackground() { function StrokeAxisLabelBackground() {
// Types // Types
// 0 = No background // 0 = No background
// 1 = Only X-labels, length of axis // 1 = Only X-labels, length of axis
// 2 = Only Y-labels, length of axis // 2 = Only Y-labels, length of axis
// 3 = As 1 but extends to width of graph // 3 = As 1 but extends to width of graph
// 4 = As 2 but extends to height of graph // 4 = As 2 but extends to height of graph
// 5 = Combination of 3 & 4 // 5 = Combination of 3 & 4
// 6 = Combination of 1 & 2 // 6 = Combination of 1 & 2
   
$t = $this->iAxisLblBgType ; $t = $this->iAxisLblBgType ;
if( $t < 1 ) return; if( $t < 1 ) return;
   
// Stroke optional X-axis label background color // Stroke optional X-axis label background color
if( $t == 1 || $t == 3 || $t == 5 || $t == 6 ) { if( $t == 1 || $t == 3 || $t == 5 || $t == 6 ) {
$this->img->PushColor($this->iXAxisLblBgFillColor); $this->img->PushColor($this->iXAxisLblBgFillColor);
if( $t == 1 || $t == 6 ) { if( $t == 1 || $t == 6 ) {
$xl = $this->img->left_margin; $xl = $this->img->left_margin;
$yu = $this->img->height - $this->img->bottom_margin + 1; $yu = $this->img->height - $this->img->bottom_margin + 1;
$xr = $this->img->width - $this->img->right_margin ; $xr = $this->img->width - $this->img->right_margin ;
$yl = $this->img->height-1-$this->frame_weight; $yl = $this->img->height-1-$this->frame_weight;
} }
else { // t==3 || t==5 else { // t==3 || t==5
$xl = $this->frame_weight; $xl = $this->frame_weight;
$yu = $this->img->height - $this->img->bottom_margin + 1; $yu = $this->img->height - $this->img->bottom_margin + 1;
$xr = $this->img->width - 1 - $this->frame_weight; $xr = $this->img->width - 1 - $this->frame_weight;
$yl = $this->img->height-1-$this->frame_weight; $yl = $this->img->height-1-$this->frame_weight;
} }
   
$this->img->FilledRectangle($xl,$yu,$xr,$yl); $this->img->FilledRectangle($xl,$yu,$xr,$yl);
$this->img->PopColor(); $this->img->PopColor();
   
// Check if we should add the vertical lines at left and right edge // Check if we should add the vertical lines at left and right edge
if( $this->iXAxisLblBgColor !== '' ) { if( $this->iXAxisLblBgColor !== '' ) {
// Hardcode to one pixel wide // Hardcode to one pixel wide
$this->img->SetLineWeight(1); $this->img->SetLineWeight(1);
$this->img->PushColor($this->iXAxisLblBgColor); $this->img->PushColor($this->iXAxisLblBgColor);
if( $t == 1 || $t == 6 ) { if( $t == 1 || $t == 6 ) {
$this->img->Line($xl,$yu,$xl,$yl); $this->img->Line($xl,$yu,$xl,$yl);
$this->img->Line($xr,$yu,$xr,$yl); $this->img->Line($xr,$yu,$xr,$yl);
} }
else { else {
$xl = $this->img->width - $this->img->right_margin ; $xl = $this->img->width - $this->img->right_margin ;
$this->img->Line($xl,$yu-1,$xr,$yu-1); $this->img->Line($xl,$yu-1,$xr,$yu-1);
} }
$this->img->PopColor(); $this->img->PopColor();
} }
} }
   
if( $t == 2 || $t == 4 || $t == 5 || $t == 6 ) { if( $t == 2 || $t == 4 || $t == 5 || $t == 6 ) {
$this->img->PushColor($this->iYAxisLblBgFillColor); $this->img->PushColor($this->iYAxisLblBgFillColor);
if( $t == 2 || $t == 6 ) { if( $t == 2 || $t == 6 ) {
$xl = $this->frame_weight; $xl = $this->frame_weight;
$yu = $this->frame_weight+$this->img->top_margin; $yu = $this->frame_weight+$this->img->top_margin;
$xr = $this->img->left_margin - 1; $xr = $this->img->left_margin - 1;
$yl = $this->img->height - $this->img->bottom_margin + 1; $yl = $this->img->height - $this->img->bottom_margin + 1;
} }
else { else {
$xl = $this->frame_weight; $xl = $this->frame_weight;
$yu = $this->frame_weight; $yu = $this->frame_weight;
$xr = $this->img->left_margin - 1; $xr = $this->img->left_margin - 1;
$yl = $this->img->height-1-$this->frame_weight; $yl = $this->img->height-1-$this->frame_weight;
} }
   
$this->img->FilledRectangle($xl,$yu,$xr,$yl); $this->img->FilledRectangle($xl,$yu,$xr,$yl);
$this->img->PopColor(); $this->img->PopColor();
   
// Check if we should add the vertical lines at left and right edge // Check if we should add the vertical lines at left and right edge
if( $this->iXAxisLblBgColor !== '' ) { if( $this->iXAxisLblBgColor !== '' ) {
$this->img->PushColor($this->iXAxisLblBgColor); $this->img->PushColor($this->iXAxisLblBgColor);
if( $t == 2 || $t == 6 ) { if( $t == 2 || $t == 6 ) {
$this->img->Line($xl,$yu-1,$xr,$yu-1); $this->img->Line($xl,$yu-1,$xr,$yu-1);
$this->img->Line($xl,$yl-1,$xr,$yl-1); $this->img->Line($xl,$yl-1,$xr,$yl-1);
} }
else { else {
$this->img->Line($xr+1,$yu,$xr+1,$this->img->top_margin); $this->img->Line($xr+1,$yu,$xr+1,$this->img->top_margin);
} }
$this->img->PopColor(); $this->img->PopColor();
} }
   
} }
} }
   
function StrokeAxis($aStrokeLabels=true) { function StrokeAxis($aStrokeLabels=true) {
   
if( $aStrokeLabels ) { if( $aStrokeLabels ) {
$this->StrokeAxisLabelBackground(); $this->StrokeAxisLabelBackground();
} }
   
// Stroke axis // Stroke axis
if( $this->iAxisStyle != AXSTYLE_SIMPLE ) { if( $this->iAxisStyle != AXSTYLE_SIMPLE ) {
switch( $this->iAxisStyle ) { switch( $this->iAxisStyle ) {
case AXSTYLE_BOXIN : case AXSTYLE_BOXIN :
$toppos = SIDE_DOWN; $toppos = SIDE_DOWN;
$bottompos = SIDE_UP; $bottompos = SIDE_UP;
$leftpos = SIDE_RIGHT; $leftpos = SIDE_RIGHT;
$rightpos = SIDE_LEFT; $rightpos = SIDE_LEFT;
break; break;
case AXSTYLE_BOXOUT : case AXSTYLE_BOXOUT :
$toppos = SIDE_UP; $toppos = SIDE_UP;
$bottompos = SIDE_DOWN; $bottompos = SIDE_DOWN;
$leftpos = SIDE_LEFT; $leftpos = SIDE_LEFT;
$rightpos = SIDE_RIGHT; $rightpos = SIDE_RIGHT;
break; break;
case AXSTYLE_YBOXIN: case AXSTYLE_YBOXIN:
$toppos = FALSE; $toppos = FALSE;
$bottompos = SIDE_UP; $bottompos = SIDE_UP;
$leftpos = SIDE_RIGHT; $leftpos = SIDE_RIGHT;
$rightpos = SIDE_LEFT; $rightpos = SIDE_LEFT;
break; break;
case AXSTYLE_YBOXOUT: case AXSTYLE_YBOXOUT:
$toppos = FALSE; $toppos = FALSE;
$bottompos = SIDE_DOWN; $bottompos = SIDE_DOWN;
$leftpos = SIDE_LEFT; $leftpos = SIDE_LEFT;
$rightpos = SIDE_RIGHT; $rightpos = SIDE_RIGHT;
break; break;
default: default:
JpGRaphError::RaiseL(25036,$this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle); JpGRaphError::RaiseL(25036,$this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle);
break; break;
} }
   
// By default we hide the first label so it doesn't cross the // 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. // 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 // However, if we use a box we always want the first value
// displayed so we make sure it will be displayed. // displayed so we make sure it will be displayed.
$this->xscale->ticks->SupressFirst(false); $this->xscale->ticks->SupressFirst(false);
   
// Now draw the bottom X-axis // Now draw the bottom X-axis
$this->xaxis->SetPos('min'); $this->xaxis->SetPos('min');
$this->xaxis->SetLabelSide(SIDE_DOWN); $this->xaxis->SetLabelSide(SIDE_DOWN);
$this->xaxis->scale->ticks->SetSide($bottompos); $this->xaxis->scale->ticks->SetSide($bottompos);
$this->xaxis->Stroke($this->yscale,$aStrokeLabels); $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
   
if( $toppos !== FALSE ) { if( $toppos !== FALSE ) {
// We also want a top X-axis // We also want a top X-axis
$this->xaxis = $this->xaxis; $this->xaxis = $this->xaxis;
$this->xaxis->SetPos('max'); $this->xaxis->SetPos('max');
$this->xaxis->SetLabelSide(SIDE_UP); $this->xaxis->SetLabelSide(SIDE_UP);
// No title for the top X-axis // No title for the top X-axis
if( $aStrokeLabels ) { if( $aStrokeLabels ) {
$this->xaxis->title->Set(''); $this->xaxis->title->Set('');
} }
$this->xaxis->scale->ticks->SetSide($toppos); $this->xaxis->scale->ticks->SetSide($toppos);
$this->xaxis->Stroke($this->yscale,$aStrokeLabels); $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
} }
   
// Stroke the left Y-axis // Stroke the left Y-axis
$this->yaxis->SetPos('min'); $this->yaxis->SetPos('min');
$this->yaxis->SetLabelSide(SIDE_LEFT); $this->yaxis->SetLabelSide(SIDE_LEFT);
$this->yaxis->scale->ticks->SetSide($leftpos); $this->yaxis->scale->ticks->SetSide($leftpos);
$this->yaxis->Stroke($this->xscale,$aStrokeLabels); $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
   
// Stroke the right Y-axis // Stroke the right Y-axis
$this->yaxis->SetPos('max'); $this->yaxis->SetPos('max');
// No title for the right side // No title for the right side
if( $aStrokeLabels ) { if( $aStrokeLabels ) {
$this->yaxis->title->Set(''); $this->yaxis->title->Set('');
} }
$this->yaxis->SetLabelSide(SIDE_RIGHT); $this->yaxis->SetLabelSide(SIDE_RIGHT);
$this->yaxis->scale->ticks->SetSide($rightpos); $this->yaxis->scale->ticks->SetSide($rightpos);
$this->yaxis->Stroke($this->xscale,$aStrokeLabels); $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
} }
else { else {
$this->xaxis->Stroke($this->yscale,$aStrokeLabels); $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
$this->yaxis->Stroke($this->xscale,$aStrokeLabels); $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
} }
} }
   
   
// Private helper function for backgound image // Private helper function for backgound image
static function LoadBkgImage($aImgFormat='',$aFile='',$aImgStr='') { static function LoadBkgImage($aImgFormat='',$aFile='',$aImgStr='') {
if( $aImgStr != '' ) { if( $aImgStr != '' ) {
return Image::CreateFromString($aImgStr); return Image::CreateFromString($aImgStr);
} }
   
// Remove case sensitivity and setup appropriate function to create image // Remove case sensitivity and setup appropriate function to create image
// Get file extension. This should be the LAST '.' separated part of the filename // Get file extension. This should be the LAST '.' separated part of the filename
$e = explode('.',$aFile); $e = explode('.',$aFile);
$ext = strtolower($e[count($e)-1]); $ext = strtolower($e[count($e)-1]);
if ($ext == "jpeg") { if ($ext == "jpeg") {
$ext = "jpg"; $ext = "jpg";
} }
   
if( trim($ext) == '' ) { if( trim($ext) == '' ) {
$ext = 'png'; // Assume PNG if no extension specified $ext = 'png'; // Assume PNG if no extension specified
} }
   
if( $aImgFormat == '' ) { if( $aImgFormat == '' ) {
$imgtag = $ext; $imgtag = $ext;
} }
else { else {
$imgtag = $aImgFormat; $imgtag = $aImgFormat;
} }
   
$supported = imagetypes(); $supported = imagetypes();
if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) || if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) ||
( $ext == 'gif' && !($supported & IMG_GIF) ) || ( $ext == 'gif' && !($supported & IMG_GIF) ) ||
( $ext == 'png' && !($supported & IMG_PNG) ) || ( $ext == 'png' && !($supported & IMG_PNG) ) ||
( $ext == 'bmp' && !($supported & IMG_WBMP) ) || ( $ext == 'bmp' && !($supported & IMG_WBMP) ) ||
( $ext == 'xpm' && !($supported & IMG_XPM) ) ) { ( $ext == 'xpm' && !($supported & IMG_XPM) ) ) {
   
JpGraphError::RaiseL(25037,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. '); JpGraphError::RaiseL(25037,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. ');
} }
   
   
if( $imgtag == "jpg" || $imgtag == "jpeg") { if( $imgtag == "jpg" || $imgtag == "jpeg") {
$f = "imagecreatefromjpeg"; $f = "imagecreatefromjpeg";
$imgtag = "jpg"; $imgtag = "jpg";
} }
else { else {
$f = "imagecreatefrom".$imgtag; $f = "imagecreatefrom".$imgtag;
} }
   
// Compare specified image type and file extension // Compare specified image type and file extension
if( $imgtag != $ext ) { if( $imgtag != $ext ) {
//$t = "Background image seems to be of different type (has different file extension) than specified imagetype. Specified: '".$aImgFormat."'File: '".$aFile."'"; //$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); JpGraphError::RaiseL(25038, $aImgFormat, $aFile);
} }
   
$img = @$f($aFile); $img = @$f($aFile);
if( !$img ) { if( !$img ) {
JpGraphError::RaiseL(25039,$aFile);//(" Can't read background image: '".$aFile."'"); JpGraphError::RaiseL(25039,$aFile);//(" Can't read background image: '".$aFile."'");
} }
return $img; return $img;
} }
   
function StrokePlotGrad() { function StrokePlotGrad() {
if( $this->plot_gradtype < 0 ) if( $this->plot_gradtype < 0 )
return; return;
$grad = new Gradient($this->img); $grad = new Gradient($this->img);
$xl = $this->img->left_margin; $xl = $this->img->left_margin;
$yt = $this->img->top_margin; $yt = $this->img->top_margin;
$xr = $xl + $this->img->plotwidth+1 ; $xr = $xl + $this->img->plotwidth+1 ;
$yb = $yt + $this->img->plotheight ; $yb = $yt + $this->img->plotheight ;
$grad->FilledRectangle($xl,$yt,$xr,$yb,$this->plot_gradfrom,$this->plot_gradto,$this->plot_gradtype); $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->plot_gradfrom,$this->plot_gradto,$this->plot_gradtype);
   
} }
   
function StrokeBackgroundGrad() { function StrokeBackgroundGrad() {
if( $this->bkg_gradtype < 0 ) if( $this->bkg_gradtype < 0 )
return; return;
   
$grad = new Gradient($this->img); $grad = new Gradient($this->img);
if( $this->bkg_gradstyle == BGRAD_PLOT ) { if( $this->bkg_gradstyle == BGRAD_PLOT ) {
$xl = $this->img->left_margin; $xl = $this->img->left_margin;
$yt = $this->img->top_margin; $yt = $this->img->top_margin;
$xr = $xl + $this->img->plotwidth+1 ; $xr = $xl + $this->img->plotwidth+1 ;
$yb = $yt + $this->img->plotheight ; $yb = $yt + $this->img->plotheight ;
$grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype); $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype);
} }
else { else {
$xl = 0; $xl = 0;
$yt = 0; $yt = 0;
$xr = $xl + $this->img->width - 1; $xr = $xl + $this->img->width - 1;
$yb = $yt + $this->img->height - 1 ; $yb = $yt + $this->img->height - 1 ;
if( $this->doshadow ) { if( $this->doshadow ) {
$xr -= $this->shadow_width; $xr -= $this->shadow_width;
$yb -= $this->shadow_width; $yb -= $this->shadow_width;
} }
if( $this->doframe ) { if( $this->doframe ) {
$yt += $this->frame_weight; $yt += $this->frame_weight;
$yb -= $this->frame_weight; $yb -= $this->frame_weight;
$xl += $this->frame_weight; $xl += $this->frame_weight;
$xr -= $this->frame_weight; $xr -= $this->frame_weight;
} }
$aa = $this->img->SetAngle(0); $aa = $this->img->SetAngle(0);
$grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype); $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype);
$aa = $this->img->SetAngle($aa); $aa = $this->img->SetAngle($aa);
} }
} }
   
function StrokeFrameBackground() { function StrokeFrameBackground() {
if( $this->background_image != '' && $this->background_cflag != '' ) { 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.'); JpGraphError::RaiseL(25040);//('It is not possible to specify both a background image and a background country flag.');
} }
if( $this->background_image != '' ) { if( $this->background_image != '' ) {
$bkgimg = $this->LoadBkgImage($this->background_image_format,$this->background_image); $bkgimg = $this->LoadBkgImage($this->background_image_format,$this->background_image);
} }
elseif( $this->background_cflag != '' ) { elseif( $this->background_cflag != '' ) {
if( ! class_exists('FlagImages',false) ) { if( ! class_exists('FlagImages',false) ) {
JpGraphError::RaiseL(25041);//('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.'); JpGraphError::RaiseL(25041);//('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.');
} }
$fobj = new FlagImages(FLAGSIZE4); $fobj = new FlagImages(FLAGSIZE4);
$dummy=''; $dummy='';
$bkgimg = $fobj->GetImgByName($this->background_cflag,$dummy); $bkgimg = $fobj->GetImgByName($this->background_cflag,$dummy);
$this->background_image_mix = $this->background_cflag_mix; $this->background_image_mix = $this->background_cflag_mix;
$this->background_image_type = $this->background_cflag_type; $this->background_image_type = $this->background_cflag_type;
} }
else { else {
return ; return ;
} }
   
$bw = ImageSX($bkgimg); $bw = ImageSX($bkgimg);
$bh = ImageSY($bkgimg); $bh = ImageSY($bkgimg);
   
// No matter what the angle is we always stroke the image and frame // No matter what the angle is we always stroke the image and frame
// assuming it is 0 degree // assuming it is 0 degree
$aa = $this->img->SetAngle(0); $aa = $this->img->SetAngle(0);
   
switch( $this->background_image_type ) { switch( $this->background_image_type ) {
case BGIMG_FILLPLOT: // Resize to just fill the plotarea case BGIMG_FILLPLOT: // Resize to just fill the plotarea
$this->FillMarginArea(); $this->FillMarginArea();
$this->StrokeFrame(); $this->StrokeFrame();
// Special case to hande 90 degree rotated graph corectly // Special case to hande 90 degree rotated graph corectly
if( $aa == 90 ) { if( $aa == 90 ) {
$this->img->SetAngle(90); $this->img->SetAngle(90);
$this->FillPlotArea(); $this->FillPlotArea();
$aa = $this->img->SetAngle(0); $aa = $this->img->SetAngle(0);
$adj = ($this->img->height - $this->img->width)/2; $adj = ($this->img->height - $this->img->width)/2;
$this->img->CopyMerge($bkgimg, $this->img->CopyMerge($bkgimg,
$this->img->bottom_margin-$adj,$this->img->left_margin+$adj, $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
0,0, 0,0,
$this->img->plotheight+1,$this->img->plotwidth, $this->img->plotheight+1,$this->img->plotwidth,
$bw,$bh,$this->background_image_mix); $bw,$bh,$this->background_image_mix);
} }
else { else {
$this->FillPlotArea(); $this->FillPlotArea();
$this->img->CopyMerge($bkgimg, $this->img->CopyMerge($bkgimg,
$this->img->left_margin,$this->img->top_margin+1, $this->img->left_margin,$this->img->top_margin+1,
0,0,$this->img->plotwidth+1,$this->img->plotheight, 0,0,$this->img->plotwidth+1,$this->img->plotheight,
$bw,$bh,$this->background_image_mix); $bw,$bh,$this->background_image_mix);
} }
break; break;
case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit
$hadj=0; $vadj=0; $hadj=0; $vadj=0;
if( $this->doshadow ) { if( $this->doshadow ) {
$hadj = $this->shadow_width; $hadj = $this->shadow_width;
$vadj = $this->shadow_width; $vadj = $this->shadow_width;
} }
$this->FillMarginArea(); $this->FillMarginArea();
$this->FillPlotArea(); $this->FillPlotArea();
$this->img->CopyMerge($bkgimg,0,0,0,0,$this->img->width-$hadj,$this->img->height-$vadj, $this->img->CopyMerge($bkgimg,0,0,0,0,$this->img->width-$hadj,$this->img->height-$vadj,
$bw,$bh,$this->background_image_mix); $bw,$bh,$this->background_image_mix);
$this->StrokeFrame(); $this->StrokeFrame();
break; break;
case BGIMG_COPY: // Just copy the image from left corner, no resizing case BGIMG_COPY: // Just copy the image from left corner, no resizing
$this->FillMarginArea(); $this->FillMarginArea();
$this->FillPlotArea(); $this->FillPlotArea();
$this->img->CopyMerge($bkgimg,0,0,0,0,$bw,$bh, $this->img->CopyMerge($bkgimg,0,0,0,0,$bw,$bh,
$bw,$bh,$this->background_image_mix); $bw,$bh,$this->background_image_mix);
$this->StrokeFrame(); $this->StrokeFrame();
break; break;
case BGIMG_CENTER: // Center original image in the plot area case BGIMG_CENTER: // Center original image in the plot area
$this->FillMarginArea(); $this->FillMarginArea();
$this->FillPlotArea(); $this->FillPlotArea();
$centerx = round($this->img->plotwidth/2+$this->img->left_margin-$bw/2); $centerx = round($this->img->plotwidth/2+$this->img->left_margin-$bw/2);
$centery = round($this->img->plotheight/2+$this->img->top_margin-$bh/2); $centery = round($this->img->plotheight/2+$this->img->top_margin-$bh/2);
$this->img->CopyMerge($bkgimg,$centerx,$centery,0,0,$bw,$bh, $this->img->CopyMerge($bkgimg,$centerx,$centery,0,0,$bw,$bh,
$bw,$bh,$this->background_image_mix); $bw,$bh,$this->background_image_mix);
$this->StrokeFrame(); $this->StrokeFrame();
break; break;
case BGIMG_FREE: // Just copy the image to the specified location case BGIMG_FREE: // Just copy the image to the specified location
$this->img->CopyMerge($bkgimg, $this->img->CopyMerge($bkgimg,
$this->background_image_xpos,$this->background_image_ypos, $this->background_image_xpos,$this->background_image_ypos,
0,0,$bw,$bh,$bw,$bh,$this->background_image_mix); 0,0,$bw,$bh,$bw,$bh,$this->background_image_mix);
$this->StrokeFrame(); // New $this->StrokeFrame(); // New
break; break;
default: default:
JpGraphError::RaiseL(25042);//(" Unknown background image layout"); JpGraphError::RaiseL(25042);//(" Unknown background image layout");
} }
$this->img->SetAngle($aa); $this->img->SetAngle($aa);
} }
   
// Private // Private
// Draw a frame around the image // Draw a frame around the image
function StrokeFrame() { function StrokeFrame() {
if( !$this->doframe ) return; if( !$this->doframe ) return;
   
if( $this->background_image_type <= 1 && ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_PLOT)) ) { if( $this->background_image_type <= 1 && ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_PLOT)) ) {
$c = $this->margin_color; $c = $this->margin_color;
} }
else { else {
$c = false; $c = false;
} }
   
if( $this->doshadow ) { if( $this->doshadow ) {
$this->img->SetColor($this->frame_color); $this->img->SetColor($this->frame_color);
$this->img->ShadowRectangle(0,0,$this->img->width,$this->img->height, $this->img->ShadowRectangle(0,0,$this->img->width,$this->img->height,
$c,$this->shadow_width,$this->shadow_color); $c,$this->shadow_width,$this->shadow_color);
} }
elseif( $this->framebevel ) { elseif( $this->framebevel ) {
if( $c ) { if( $c ) {
$this->img->SetColor($this->margin_color); $this->img->SetColor($this->margin_color);
$this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1); $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->img->Bevel(1,1,$this->img->width-2,$this->img->height-2,
$this->framebeveldepth, $this->framebeveldepth,
$this->framebevelcolor1,$this->framebevelcolor2); $this->framebevelcolor1,$this->framebevelcolor2);
if( $this->framebevelborder ) { if( $this->framebevelborder ) {
$this->img->SetColor($this->framebevelbordercolor); $this->img->SetColor($this->framebevelbordercolor);
$this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
} }
} }
else { else {
$this->img->SetLineWeight($this->frame_weight); $this->img->SetLineWeight($this->frame_weight);
if( $c ) { if( $c ) {
$this->img->SetColor($this->margin_color); $this->img->SetColor($this->margin_color);
$this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1); $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1);
} }
$this->img->SetColor($this->frame_color); $this->img->SetColor($this->frame_color);
$this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
} }
} }
   
function FillMarginArea() { function FillMarginArea() {
$hadj=0; $vadj=0; $hadj=0; $vadj=0;
if( $this->doshadow ) { if( $this->doshadow ) {
$hadj = $this->shadow_width; $hadj = $this->shadow_width;
$vadj = $this->shadow_width; $vadj = $this->shadow_width;
} }
   
$this->img->SetColor($this->margin_color); $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->height-1-$vadj);
   
$this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->top_margin); $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(0,$this->img->top_margin,$this->img->left_margin,$this->img->height-1-$hadj);
$this->img->FilledRectangle($this->img->left_margin+1, $this->img->FilledRectangle($this->img->left_margin+1,
$this->img->height-$this->img->bottom_margin, $this->img->height-$this->img->bottom_margin,
$this->img->width-1-$hadj, $this->img->width-1-$hadj,
$this->img->height-1-$hadj); $this->img->height-1-$hadj);
$this->img->FilledRectangle($this->img->width-$this->img->right_margin, $this->img->FilledRectangle($this->img->width-$this->img->right_margin,
$this->img->top_margin+1, $this->img->top_margin+1,
$this->img->width-1-$hadj, $this->img->width-1-$hadj,
$this->img->height-$this->img->bottom_margin-1); $this->img->height-$this->img->bottom_margin-1);
} }
   
function FillPlotArea() { function FillPlotArea() {
$this->img->PushColor($this->plotarea_color); $this->img->PushColor($this->plotarea_color);
$this->img->FilledRectangle($this->img->left_margin, $this->img->FilledRectangle($this->img->left_margin,
$this->img->top_margin, $this->img->top_margin,
$this->img->width-$this->img->right_margin, $this->img->width-$this->img->right_margin,
$this->img->height-$this->img->bottom_margin); $this->img->height-$this->img->bottom_margin);
$this->img->PopColor(); $this->img->PopColor();
} }
   
// Stroke the plot area with either a solid color or a background image // Stroke the plot area with either a solid color or a background image
function StrokePlotArea() { function StrokePlotArea() {
// Note: To be consistent we really should take a possible shadow // Note: To be consistent we really should take a possible shadow
// into account. However, that causes some problem for the LinearScale class // 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 // 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 // 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. // shadow. So, until I redesign LinearScale we can't compensate for this.
// So just set the two adjustment parameters to zero for now. // So just set the two adjustment parameters to zero for now.
$boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ; $boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ;
$adj = 0; //$this->doshadow ? $this->shadow_width : 0 ; $adj = 0; //$this->doshadow ? $this->shadow_width : 0 ;
   
if( $this->background_image != '' || $this->background_cflag != '' ) { if( $this->background_image != '' || $this->background_cflag != '' ) {
$this->StrokeFrameBackground(); $this->StrokeFrameBackground();
} }
else { else {
$aa = $this->img->SetAngle(0); $aa = $this->img->SetAngle(0);
$this->StrokeFrame(); $this->StrokeFrame();
$aa = $this->img->SetAngle($aa); $aa = $this->img->SetAngle($aa);
$this->StrokeBackgroundGrad(); $this->StrokeBackgroundGrad();
if( $this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_MARGIN) ) { if( $this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_MARGIN) ) {
$this->FillPlotArea(); $this->FillPlotArea();
} }
$this->StrokePlotGrad(); $this->StrokePlotGrad();
} }
} }
   
function StrokeIcons() { function StrokeIcons() {
$n = count($this->iIcons); $n = count($this->iIcons);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->iIcons[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); $this->iIcons[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
} }
} }
   
function StrokePlotBox() { function StrokePlotBox() {
// Should we draw a box around the plot area? // Should we draw a box around the plot area?
if( $this->boxed ) { if( $this->boxed ) {
$this->img->SetLineWeight(1); $this->img->SetLineWeight(1);
$this->img->SetLineStyle('solid'); $this->img->SetLineStyle('solid');
$this->img->SetColor($this->box_color); $this->img->SetColor($this->box_color);
for($i=0; $i < $this->box_weight; ++$i ) { for($i=0; $i < $this->box_weight; ++$i ) {
$this->img->Rectangle( $this->img->Rectangle(
$this->img->left_margin-$i,$this->img->top_margin-$i, $this->img->left_margin-$i,$this->img->top_margin-$i,
$this->img->width-$this->img->right_margin+$i, $this->img->width-$this->img->right_margin+$i,
$this->img->height-$this->img->bottom_margin+$i); $this->img->height-$this->img->bottom_margin+$i);
} }
} }
} }
   
function SetTitleBackgroundFillStyle($aStyle,$aColor1='black',$aColor2='white') { function SetTitleBackgroundFillStyle($aStyle,$aColor1='black',$aColor2='white') {
$this->titlebkg_fillstyle = $aStyle; $this->titlebkg_fillstyle = $aStyle;
$this->titlebkg_scolor1 = $aColor1; $this->titlebkg_scolor1 = $aColor1;
$this->titlebkg_scolor2 = $aColor2; $this->titlebkg_scolor2 = $aColor2;
} }
   
function SetTitleBackground($aBackColor='gray', $aStyle=TITLEBKG_STYLE1, $aFrameStyle=TITLEBKG_FRAME_NONE, $aFrameColor='black', $aFrameWeight=1, $aBevelHeight=3, $aEnable=true) { function SetTitleBackground($aBackColor='gray', $aStyle=TITLEBKG_STYLE1, $aFrameStyle=TITLEBKG_FRAME_NONE, $aFrameColor='black', $aFrameWeight=1, $aBevelHeight=3, $aEnable=true) {
$this->titlebackground = $aEnable; $this->titlebackground = $aEnable;
$this->titlebackground_color = $aBackColor; $this->titlebackground_color = $aBackColor;
$this->titlebackground_style = $aStyle; $this->titlebackground_style = $aStyle;
$this->titlebackground_framecolor = $aFrameColor; $this->titlebackground_framecolor = $aFrameColor;
$this->titlebackground_framestyle = $aFrameStyle; $this->titlebackground_framestyle = $aFrameStyle;
$this->titlebackground_frameweight = $aFrameWeight; $this->titlebackground_frameweight = $aFrameWeight;
$this->titlebackground_bevelheight = $aBevelHeight ; $this->titlebackground_bevelheight = $aBevelHeight ;
} }
   
   
function StrokeTitles() { function StrokeTitles() {
   
$margin=3; $margin=3;
   
if( $this->titlebackground ) { if( $this->titlebackground ) {
// Find out height // Find out height
$this->title->margin += 2 ; $this->title->margin += 2 ;
$h = $this->title->GetTextHeight($this->img)+$this->title->margin+$margin; $h = $this->title->GetTextHeight($this->img)+$this->title->margin+$margin;
if( $this->subtitle->t != '' && !$this->subtitle->hide ) { if( $this->subtitle->t != '' && !$this->subtitle->hide ) {
$h += $this->subtitle->GetTextHeight($this->img)+$margin+ $h += $this->subtitle->GetTextHeight($this->img)+$margin+
$this->subtitle->margin; $this->subtitle->margin;
$h += 2; $h += 2;
} }
if( $this->subsubtitle->t != '' && !$this->subsubtitle->hide ) { if( $this->subsubtitle->t != '' && !$this->subsubtitle->hide ) {
$h += $this->subsubtitle->GetTextHeight($this->img)+$margin+ $h += $this->subsubtitle->GetTextHeight($this->img)+$margin+
$this->subsubtitle->margin; $this->subsubtitle->margin;
$h += 2; $h += 2;
} }
$this->img->PushColor($this->titlebackground_color); $this->img->PushColor($this->titlebackground_color);
if( $this->titlebackground_style === TITLEBKG_STYLE1 ) { if( $this->titlebackground_style === TITLEBKG_STYLE1 ) {
// Inside the frame // Inside the frame
if( $this->framebevel ) { if( $this->framebevel ) {
$x1 = $y1 = $this->framebeveldepth + 1 ; $x1 = $y1 = $this->framebeveldepth + 1 ;
$x2 = $this->img->width - $this->framebeveldepth - 2 ; $x2 = $this->img->width - $this->framebeveldepth - 2 ;
$this->title->margin += $this->framebeveldepth + 1 ; $this->title->margin += $this->framebeveldepth + 1 ;
$h += $y1 ; $h += $y1 ;
$h += 2; $h += 2;
} }
else { else {
$x1 = $y1 = $this->frame_weight; $x1 = $y1 = $this->frame_weight;
$x2 = $this->img->width - $this->frame_weight-1; $x2 = $this->img->width - $this->frame_weight-1;
} }
} }
elseif( $this->titlebackground_style === TITLEBKG_STYLE2 ) { elseif( $this->titlebackground_style === TITLEBKG_STYLE2 ) {
// Cover the frame as well // Cover the frame as well
$x1 = $y1 = 0; $x1 = $y1 = 0;
$x2 = $this->img->width - 1 ; $x2 = $this->img->width - 1 ;
} }
elseif( $this->titlebackground_style === TITLEBKG_STYLE3 ) { elseif( $this->titlebackground_style === TITLEBKG_STYLE3 ) {
// Cover the frame as well (the difference is that // Cover the frame as well (the difference is that
// for style==3 a bevel frame border is on top // for style==3 a bevel frame border is on top
// of the title background) // of the title background)
$x1 = $y1 = 0; $x1 = $y1 = 0;
$x2 = $this->img->width - 1 ; $x2 = $this->img->width - 1 ;
$h += $this->framebeveldepth ; $h += $this->framebeveldepth ;
$this->title->margin += $this->framebeveldepth ; $this->title->margin += $this->framebeveldepth ;
} }
else { else {
JpGraphError::RaiseL(25043);//('Unknown title background style.'); JpGraphError::RaiseL(25043);//('Unknown title background style.');
} }
   
if( $this->titlebackground_framestyle === 3 ) { if( $this->titlebackground_framestyle === 3 ) {
$h += $this->titlebackground_bevelheight*2 + 1 ; $h += $this->titlebackground_bevelheight*2 + 1 ;
$this->title->margin += $this->titlebackground_bevelheight ; $this->title->margin += $this->titlebackground_bevelheight ;
} }
   
if( $this->doshadow ) { if( $this->doshadow ) {
$x2 -= $this->shadow_width ; $x2 -= $this->shadow_width ;
} }
   
$indent=0; $indent=0;
if( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) { if( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) {
$indent = $this->titlebackground_bevelheight; $indent = $this->titlebackground_bevelheight;
} }
   
if( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_HSTRIPED ) { if( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_HSTRIPED ) {
$this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent, $this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent,
$this->titlebkg_scolor1, $this->titlebkg_scolor1,
$this->titlebkg_scolor2); $this->titlebkg_scolor2);
} }
elseif( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_VSTRIPED ) { elseif( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_VSTRIPED ) {
$this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent, $this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent,
$this->titlebkg_scolor1, $this->titlebkg_scolor1,
$this->titlebkg_scolor2,2); $this->titlebkg_scolor2,2);
} }
else { else {
// Solid fill // Solid fill
$this->img->FilledRectangle($x1,$y1,$x2,$h); $this->img->FilledRectangle($x1,$y1,$x2,$h);
} }
$this->img->PopColor(); $this->img->PopColor();
   
$this->img->PushColor($this->titlebackground_framecolor); $this->img->PushColor($this->titlebackground_framecolor);
$this->img->SetLineWeight($this->titlebackground_frameweight); $this->img->SetLineWeight($this->titlebackground_frameweight);
if( $this->titlebackground_framestyle == TITLEBKG_FRAME_FULL ) { if( $this->titlebackground_framestyle == TITLEBKG_FRAME_FULL ) {
// Frame background // Frame background
$this->img->Rectangle($x1,$y1,$x2,$h); $this->img->Rectangle($x1,$y1,$x2,$h);
} }
elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM ) { elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM ) {
// Bottom line only // Bottom line only
$this->img->Line($x1,$h,$x2,$h); $this->img->Line($x1,$h,$x2,$h);
} }
elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) { elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) {
$this->img->Bevel($x1,$y1,$x2,$h,$this->titlebackground_bevelheight); $this->img->Bevel($x1,$y1,$x2,$h,$this->titlebackground_bevelheight);
} }
$this->img->PopColor(); $this->img->PopColor();
   
// This is clumsy. But we neeed to stroke the whole graph frame if it is // 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 // set to bevel to get the bevel shading on top of the text background
if( $this->framebevel && $this->doframe && $this->titlebackground_style === 3 ) { if( $this->framebevel && $this->doframe && $this->titlebackground_style === 3 ) {
$this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2, $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2,
$this->framebeveldepth, $this->framebeveldepth,
$this->framebevelcolor1,$this->framebevelcolor2); $this->framebevelcolor1,$this->framebevelcolor2);
if( $this->framebevelborder ) { if( $this->framebevelborder ) {
$this->img->SetColor($this->framebevelbordercolor); $this->img->SetColor($this->framebevelbordercolor);
$this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1); $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
} }
} }
} }
   
// Stroke title // Stroke title
$y = $this->title->margin; $y = $this->title->margin;
if( $this->title->halign == 'center' ) { if( $this->title->halign == 'center' ) {
$this->title->Center(0,$this->img->width,$y); $this->title->Center(0,$this->img->width,$y);
} }
elseif( $this->title->halign == 'left' ) { elseif( $this->title->halign == 'left' ) {
$this->title->SetPos($this->title->margin+2,$y); $this->title->SetPos($this->title->margin+2,$y);
} }
elseif( $this->title->halign == 'right' ) { elseif( $this->title->halign == 'right' ) {
$indent = 0; $indent = 0;
if( $this->doshadow ) { if( $this->doshadow ) {
$indent = $this->shadow_width+2; $indent = $this->shadow_width+2;
} }
$this->title->SetPos($this->img->width-$this->title->margin-$indent,$y,'right'); $this->title->SetPos($this->img->width-$this->title->margin-$indent,$y,'right');
} }
$this->title->Stroke($this->img); $this->title->Stroke($this->img);
   
// ... and subtitle // ... and subtitle
$y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin; $y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin;
if( $this->subtitle->halign == 'center' ) { if( $this->subtitle->halign == 'center' ) {
$this->subtitle->Center(0,$this->img->width,$y); $this->subtitle->Center(0,$this->img->width,$y);
} }
elseif( $this->subtitle->halign == 'left' ) { elseif( $this->subtitle->halign == 'left' ) {
$this->subtitle->SetPos($this->subtitle->margin+2,$y); $this->subtitle->SetPos($this->subtitle->margin+2,$y);
} }
elseif( $this->subtitle->halign == 'right' ) { elseif( $this->subtitle->halign == 'right' ) {
$indent = 0; $indent = 0;
if( $this->doshadow ) if( $this->doshadow )
$indent = $this->shadow_width+2; $indent = $this->shadow_width+2;
$this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right'); $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right');
} }
$this->subtitle->Stroke($this->img); $this->subtitle->Stroke($this->img);
   
// ... and subsubtitle // ... and subsubtitle
$y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin; $y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin;
if( $this->subsubtitle->halign == 'center' ) { if( $this->subsubtitle->halign == 'center' ) {
$this->subsubtitle->Center(0,$this->img->width,$y); $this->subsubtitle->Center(0,$this->img->width,$y);
} }
elseif( $this->subsubtitle->halign == 'left' ) { elseif( $this->subsubtitle->halign == 'left' ) {
$this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y); $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y);
} }
elseif( $this->subsubtitle->halign == 'right' ) { elseif( $this->subsubtitle->halign == 'right' ) {
$indent = 0; $indent = 0;
if( $this->doshadow ) if( $this->doshadow )
$indent = $this->shadow_width+2; $indent = $this->shadow_width+2;
$this->subsubtitle->SetPos($this->img->width-$this->subsubtitle->margin-$indent,$y,'right'); $this->subsubtitle->SetPos($this->img->width-$this->subsubtitle->margin-$indent,$y,'right');
} }
$this->subsubtitle->Stroke($this->img); $this->subsubtitle->Stroke($this->img);
   
// ... and fancy title // ... and fancy title
$this->tabtitle->Stroke($this->img); $this->tabtitle->Stroke($this->img);
   
} }
   
function StrokeTexts() { function StrokeTexts() {
// Stroke any user added text objects // Stroke any user added text objects
if( $this->texts != null ) { if( $this->texts != null ) {
for($i=0; $i < count($this->texts); ++$i) { for($i=0; $i < count($this->texts); ++$i) {
$this->texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); $this->texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
} }
} }
   
if( $this->y2texts != null && $this->y2scale != null ) { if( $this->y2texts != null && $this->y2scale != null ) {
for($i=0; $i < count($this->y2texts); ++$i) { for($i=0; $i < count($this->y2texts); ++$i) {
$this->y2texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->y2scale); $this->y2texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->y2scale);
} }
} }
   
} }
   
function StrokeTables() { function StrokeTables() {
if( $this->iTables != null ) { if( $this->iTables != null ) {
$n = count($this->iTables); $n = count($this->iTables);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->iTables[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale); $this->iTables[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
} }
} }
} }
   
function DisplayClientSideaImageMapAreas() { function DisplayClientSideaImageMapAreas() {
// Debug stuff - display the outline of the image map areas // Debug stuff - display the outline of the image map areas
$csim=''; $csim='';
foreach ($this->plots as $p) { foreach ($this->plots as $p) {
$csim.= $p->GetCSIMareas(); $csim.= $p->GetCSIMareas();
} }
$csim .= $this->legend->GetCSIMareas(); $csim .= $this->legend->GetCSIMareas();
if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) { if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
$this->img->SetColor($this->csimcolor); $this->img->SetColor($this->csimcolor);
$n = count($coords[0]); $n = count($coords[0]);
for ($i=0; $i < $n; $i++) { for ($i=0; $i < $n; $i++) {
if ( $coords[1][$i] == 'poly' ) { if ( $coords[1][$i] == 'poly' ) {
preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts); 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]); $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
$m = count($pts[0]); $m = count($pts[0]);
for ($j=0; $j < $m; $j++) { for ($j=0; $j < $m; $j++) {
$this->img->LineTo($pts[1][$j],$pts[2][$j]); $this->img->LineTo($pts[1][$j],$pts[2][$j]);
} }
} elseif ( $coords[1][$i] == 'rect' ) { } elseif ( $coords[1][$i] == 'rect' ) {
$pts = preg_split('/,/', $coords[2][$i]); $pts = preg_split('/,/', $coords[2][$i]);
$this->img->SetStartPoint($pts[0],$pts[1]); $this->img->SetStartPoint($pts[0],$pts[1]);
$this->img->LineTo($pts[2],$pts[1]); $this->img->LineTo($pts[2],$pts[1]);
$this->img->LineTo($pts[2],$pts[3]); $this->img->LineTo($pts[2],$pts[3]);
$this->img->LineTo($pts[0],$pts[3]); $this->img->LineTo($pts[0],$pts[3]);
$this->img->LineTo($pts[0],$pts[1]); $this->img->LineTo($pts[0],$pts[1]);
} }
} }
} }
} }
   
// Text scale offset in world coordinates // Text scale offset in world coordinates
function SetTextScaleOff($aOff) { function SetTextScaleOff($aOff) {
$this->text_scale_off = $aOff; $this->text_scale_off = $aOff;
$this->xscale->text_scale_off = $aOff; $this->xscale->text_scale_off = $aOff;
} }
   
// Text width of bar to be centered in absolute pixels // Text width of bar to be centered in absolute pixels
function SetTextScaleAbsCenterOff($aOff) { function SetTextScaleAbsCenterOff($aOff) {
$this->text_scale_abscenteroff = $aOff; $this->text_scale_abscenteroff = $aOff;
} }
   
// Get Y min and max values for added lines // Get Y min and max values for added lines
function GetLinesYMinMax( $aLines ) { function GetLinesYMinMax( $aLines ) {
$n = count($aLines); $n = count($aLines);
if( $n == 0 ) return false; if( $n == 0 ) return false;
$min = $aLines[0]->scaleposition ; $min = $aLines[0]->scaleposition ;
$max = $min ; $max = $min ;
$flg = false; $flg = false;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $aLines[$i]->direction == HORIZONTAL ) { if( $aLines[$i]->direction == HORIZONTAL ) {
$flg = true ; $flg = true ;
$v = $aLines[$i]->scaleposition ; $v = $aLines[$i]->scaleposition ;
if( $min > $v ) $min = $v ; if( $min > $v ) $min = $v ;
if( $max < $v ) $max = $v ; if( $max < $v ) $max = $v ;
} }
} }
return $flg ? array($min,$max) : false ; return $flg ? array($min,$max) : false ;
} }
   
// Get X min and max values for added lines // Get X min and max values for added lines
function GetLinesXMinMax( $aLines ) { function GetLinesXMinMax( $aLines ) {
$n = count($aLines); $n = count($aLines);
if( $n == 0 ) return false ; if( $n == 0 ) return false ;
$min = $aLines[0]->scaleposition ; $min = $aLines[0]->scaleposition ;
$max = $min ; $max = $min ;
$flg = false; $flg = false;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $aLines[$i]->direction == VERTICAL ) { if( $aLines[$i]->direction == VERTICAL ) {
$flg = true ; $flg = true ;
$v = $aLines[$i]->scaleposition ; $v = $aLines[$i]->scaleposition ;
if( $min > $v ) $min = $v ; if( $min > $v ) $min = $v ;
if( $max < $v ) $max = $v ; if( $max < $v ) $max = $v ;
} }
} }
return $flg ? array($min,$max) : false ; return $flg ? array($min,$max) : false ;
} }
   
// Get min and max values for all included plots // Get min and max values for all included plots
function GetPlotsYMinMax($aPlots) { function GetPlotsYMinMax($aPlots) {
$n = count($aPlots); $n = count($aPlots);
$i=0; $i=0;
do { do {
list($xmax,$max) = $aPlots[$i]->Max(); list($xmax,$max) = $aPlots[$i]->Max();
} while( ++$i < $n && !is_numeric($max) ); } while( ++$i < $n && !is_numeric($max) );
   
$i=0; $i=0;
do { do {
list($xmin,$min) = $aPlots[$i]->Min(); list($xmin,$min) = $aPlots[$i]->Min();
} while( ++$i < $n && !is_numeric($min) ); } while( ++$i < $n && !is_numeric($min) );
   
if( !is_numeric($min) || !is_numeric($max) ) { 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).'); 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 ) { for($i=0; $i < $n; ++$i ) {
list($xmax,$ymax)=$aPlots[$i]->Max(); list($xmax,$ymax)=$aPlots[$i]->Max();
list($xmin,$ymin)=$aPlots[$i]->Min(); list($xmin,$ymin)=$aPlots[$i]->Min();
if (is_numeric($ymax)) $max=max($max,$ymax); if (is_numeric($ymax)) $max=max($max,$ymax);
if (is_numeric($ymin)) $min=min($min,$ymin); if (is_numeric($ymin)) $min=min($min,$ymin);
} }
if( $min == '' ) $min = 0; if( $min == '' ) $min = 0;
if( $max == '' ) $max = 0; if( $max == '' ) $max = 0;
if( $min == 0 && $max == 0 ) { if( $min == 0 && $max == 0 ) {
// Special case if all values are 0 // Special case if all values are 0
$min=0;$max=1; $min=0;$max=1;
} }
return array($min,$max); return array($min,$max);
} }
   
} // Class } // Class
   
//=================================================== //===================================================
// CLASS LineProperty // CLASS LineProperty
// Description: Holds properties for a line // Description: Holds properties for a line
//=================================================== //===================================================
class LineProperty { class LineProperty {
public $iWeight=1, $iColor='black', $iStyle='solid', $iShow=true; public $iWeight=1, $iColor='black', $iStyle='solid', $iShow=true;
   
function __construct($aWeight=1,$aColor='black',$aStyle='solid') { function __construct($aWeight=1,$aColor='black',$aStyle='solid') {
$this->iWeight = $aWeight; $this->iWeight = $aWeight;
$this->iColor = $aColor; $this->iColor = $aColor;
$this->iStyle = $aStyle; $this->iStyle = $aStyle;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->iWeight = $aWeight; $this->iWeight = $aWeight;
} }
   
function SetStyle($aStyle) { function SetStyle($aStyle) {
$this->iStyle = $aStyle; $this->iStyle = $aStyle;
} }
   
function Show($aShow=true) { function Show($aShow=true) {
$this->iShow=$aShow; $this->iShow=$aShow;
} }
   
function Stroke($aImg,$aX1,$aY1,$aX2,$aY2) { function Stroke($aImg,$aX1,$aY1,$aX2,$aY2) {
if( $this->iShow ) { if( $this->iShow ) {
$aImg->PushColor($this->iColor); $aImg->PushColor($this->iColor);
$oldls = $aImg->line_style; $oldls = $aImg->line_style;
$oldlw = $aImg->line_weight; $oldlw = $aImg->line_weight;
$aImg->SetLineWeight($this->iWeight); $aImg->SetLineWeight($this->iWeight);
$aImg->SetLineStyle($this->iStyle); $aImg->SetLineStyle($this->iStyle);
$aImg->StyleLine($aX1,$aY1,$aX2,$aY2); $aImg->StyleLine($aX1,$aY1,$aX2,$aY2);
$aImg->PopColor($this->iColor); $aImg->PopColor($this->iColor);
$aImg->line_style = $oldls; $aImg->line_style = $oldls;
$aImg->line_weight = $oldlw; $aImg->line_weight = $oldlw;
   
} }
} }
} }
   
//=================================================== //===================================================
// CLASS GraphTabTitle // CLASS GraphTabTitle
// Description: Draw "tab" titles on top of graphs // Description: Draw "tab" titles on top of graphs
//=================================================== //===================================================
class GraphTabTitle extends Text{ class GraphTabTitle extends Text{
private $corner = 6 , $posx = 7, $posy = 4; private $corner = 6 , $posx = 7, $posy = 4;
private $fillcolor='lightyellow',$bordercolor='black'; private $fillcolor='lightyellow',$bordercolor='black';
private $align = 'left', $width=TABTITLE_WIDTHFIT; private $align = 'left', $width=TABTITLE_WIDTHFIT;
function __construct() { function __construct() {
$this->t = ''; $this->t = '';
$this->font_style = FS_BOLD; $this->font_style = FS_BOLD;
$this->hide = true; $this->hide = true;
$this->color = 'darkred'; $this->color = 'darkred';
} }
   
function SetColor($aTxtColor,$aFillColor='lightyellow',$aBorderColor='black') { function SetColor($aTxtColor,$aFillColor='lightyellow',$aBorderColor='black') {
$this->color = $aTxtColor; $this->color = $aTxtColor;
$this->fillcolor = $aFillColor; $this->fillcolor = $aFillColor;
$this->bordercolor = $aBorderColor; $this->bordercolor = $aBorderColor;
} }
   
function SetFillColor($aFillColor) { function SetFillColor($aFillColor) {
$this->fillcolor = $aFillColor; $this->fillcolor = $aFillColor;
} }
   
function SetTabAlign($aAlign) { function SetTabAlign($aAlign) {
$this->align = $aAlign; $this->align = $aAlign;
} }
   
function SetWidth($aWidth) { function SetWidth($aWidth) {
$this->width = $aWidth ; $this->width = $aWidth ;
} }
   
function Set($t) { function Set($t) {
$this->t = $t; $this->t = $t;
$this->hide = false; $this->hide = false;
} }
   
function SetCorner($aD) { function SetCorner($aD) {
$this->corner = $aD ; $this->corner = $aD ;
} }
   
function Stroke($aImg,$aDummy1=null,$aDummy2=null) { function Stroke($aImg,$aDummy1=null,$aDummy2=null) {
if( $this->hide ) if( $this->hide )
return; return;
$this->boxed = false; $this->boxed = false;
$w = $this->GetWidth($aImg) + 2*$this->posx; $w = $this->GetWidth($aImg) + 2*$this->posx;
$h = $this->GetTextHeight($aImg) + 2*$this->posy; $h = $this->GetTextHeight($aImg) + 2*$this->posy;
   
$x = $aImg->left_margin; $x = $aImg->left_margin;
$y = $aImg->top_margin; $y = $aImg->top_margin;
   
if( $this->width === TABTITLE_WIDTHFIT ) { if( $this->width === TABTITLE_WIDTHFIT ) {
if( $this->align == 'left' ) { if( $this->align == 'left' ) {
$p = array($x, $y, $p = array($x, $y,
$x, $y-$h+$this->corner, $x, $y-$h+$this->corner,
$x + $this->corner,$y-$h, $x + $this->corner,$y-$h,
$x + $w - $this->corner, $y-$h, $x + $w - $this->corner, $y-$h,
$x + $w, $y-$h+$this->corner, $x + $w, $y-$h+$this->corner,
$x + $w, $y); $x + $w, $y);
} }
elseif( $this->align == 'center' ) { elseif( $this->align == 'center' ) {
$x += round($aImg->plotwidth/2) - round($w/2); $x += round($aImg->plotwidth/2) - round($w/2);
$p = array($x, $y, $p = array($x, $y,
$x, $y-$h+$this->corner, $x, $y-$h+$this->corner,
$x + $this->corner, $y-$h, $x + $this->corner, $y-$h,
$x + $w - $this->corner, $y-$h, $x + $w - $this->corner, $y-$h,
$x + $w, $y-$h+$this->corner, $x + $w, $y-$h+$this->corner,
$x + $w, $y); $x + $w, $y);
} }
else { else {
$x += $aImg->plotwidth -$w; $x += $aImg->plotwidth -$w;
$p = array($x, $y, $p = array($x, $y,
$x, $y-$h+$this->corner, $x, $y-$h+$this->corner,
$x + $this->corner,$y-$h, $x + $this->corner,$y-$h,
$x + $w - $this->corner, $y-$h, $x + $w - $this->corner, $y-$h,
$x + $w, $y-$h+$this->corner, $x + $w, $y-$h+$this->corner,
$x + $w, $y); $x + $w, $y);
} }
} }
else { else {
if( $this->width === TABTITLE_WIDTHFULL ) { if( $this->width === TABTITLE_WIDTHFULL ) {
$w = $aImg->plotwidth ; $w = $aImg->plotwidth ;
} }
else { else {
$w = $this->width ; $w = $this->width ;
} }
   
// Make the tab fit the width of the plot area // Make the tab fit the width of the plot area
$p = array($x, $y, $p = array($x, $y,
$x, $y-$h+$this->corner, $x, $y-$h+$this->corner,
$x + $this->corner,$y-$h, $x + $this->corner,$y-$h,
$x + $w - $this->corner, $y-$h, $x + $w - $this->corner, $y-$h,
$x + $w, $y-$h+$this->corner, $x + $w, $y-$h+$this->corner,
$x + $w, $y); $x + $w, $y);
   
} }
if( $this->halign == 'left' ) { if( $this->halign == 'left' ) {
$aImg->SetTextAlign('left','bottom'); $aImg->SetTextAlign('left','bottom');
$x += $this->posx; $x += $this->posx;
$y -= $this->posy; $y -= $this->posy;
} }
elseif( $this->halign == 'center' ) { elseif( $this->halign == 'center' ) {
$aImg->SetTextAlign('center','bottom'); $aImg->SetTextAlign('center','bottom');
$x += $w/2; $x += $w/2;
$y -= $this->posy; $y -= $this->posy;
} }
else { else {
$aImg->SetTextAlign('right','bottom'); $aImg->SetTextAlign('right','bottom');
$x += $w - $this->posx; $x += $w - $this->posx;
$y -= $this->posy; $y -= $this->posy;
} }
   
$aImg->SetColor($this->fillcolor); $aImg->SetColor($this->fillcolor);
$aImg->FilledPolygon($p); $aImg->FilledPolygon($p);
   
$aImg->SetColor($this->bordercolor); $aImg->SetColor($this->bordercolor);
$aImg->Polygon($p,true); $aImg->Polygon($p,true);
   
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$aImg->StrokeText($x,$y,$this->t,0,'center'); $aImg->StrokeText($x,$y,$this->t,0,'center');
} }
   
} }
   
//=================================================== //===================================================
// CLASS SuperScriptText // CLASS SuperScriptText
// Description: Format a superscript text // Description: Format a superscript text
//=================================================== //===================================================
class SuperScriptText extends Text { class SuperScriptText extends Text {
private $iSuper=''; private $iSuper='';
private $sfont_family='',$sfont_style='',$sfont_size=8; private $sfont_family='',$sfont_style='',$sfont_size=8;
private $iSuperMargin=2,$iVertOverlap=4,$iSuperScale=0.65; private $iSuperMargin=2,$iVertOverlap=4,$iSuperScale=0.65;
private $iSDir=0; private $iSDir=0;
private $iSimple=false; private $iSimple=false;
   
function __construct($aTxt='',$aSuper='',$aXAbsPos=0,$aYAbsPos=0) { function __construct($aTxt='',$aSuper='',$aXAbsPos=0,$aYAbsPos=0) {
parent::__construct($aTxt,$aXAbsPos,$aYAbsPos); parent::__construct($aTxt,$aXAbsPos,$aYAbsPos);
$this->iSuper = $aSuper; $this->iSuper = $aSuper;
} }
   
function FromReal($aVal,$aPrecision=2) { function FromReal($aVal,$aPrecision=2) {
// Convert a floating point number to scientific notation // Convert a floating point number to scientific notation
$neg=1.0; $neg=1.0;
if( $aVal < 0 ) { if( $aVal < 0 ) {
$neg = -1.0; $neg = -1.0;
$aVal = -$aVal; $aVal = -$aVal;
} }
   
$l = floor(log10($aVal)); $l = floor(log10($aVal));
$a = sprintf("%0.".$aPrecision."f",round($aVal / pow(10,$l),$aPrecision)); $a = sprintf("%0.".$aPrecision."f",round($aVal / pow(10,$l),$aPrecision));
$a *= $neg; $a *= $neg;
if( $this->iSimple && ($a == 1 || $a==-1) ) $a = ''; if( $this->iSimple && ($a == 1 || $a==-1) ) $a = '';
   
if( $a != '' ) { if( $a != '' ) {
$this->t = $a.' * 10'; $this->t = $a.' * 10';
} }
else { else {
if( $neg == 1 ) { if( $neg == 1 ) {
$this->t = '10'; $this->t = '10';
} }
else { else {
$this->t = '-10'; $this->t = '-10';
} }
} }
$this->iSuper = $l; $this->iSuper = $l;
} }
   
function Set($aTxt,$aSuper='') { function Set($aTxt,$aSuper='') {
$this->t = $aTxt; $this->t = $aTxt;
$this->iSuper = $aSuper; $this->iSuper = $aSuper;
} }
   
function SetSuperFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=8) { function SetSuperFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=8) {
$this->sfont_family = $aFontFam; $this->sfont_family = $aFontFam;
$this->sfont_style = $aFontStyle; $this->sfont_style = $aFontStyle;
$this->sfont_size = $aFontSize; $this->sfont_size = $aFontSize;
} }
   
// Total width of text // Total width of text
function GetWidth($aImg) { function GetWidth($aImg) {
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$w = $aImg->GetTextWidth($this->t); $w = $aImg->GetTextWidth($this->t);
$aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
$w += $aImg->GetTextWidth($this->iSuper); $w += $aImg->GetTextWidth($this->iSuper);
$w += $this->iSuperMargin; $w += $this->iSuperMargin;
return $w; return $w;
} }
   
// Hight of font (approximate the height of the text) // Hight of font (approximate the height of the text)
function GetFontHeight($aImg) { function GetFontHeight($aImg) {
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$h = $aImg->GetFontHeight(); $h = $aImg->GetFontHeight();
$aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
$h += $aImg->GetFontHeight(); $h += $aImg->GetFontHeight();
return $h; return $h;
} }
   
// Hight of text // Hight of text
function GetTextHeight($aImg) { function GetTextHeight($aImg) {
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$h = $aImg->GetTextHeight($this->t); $h = $aImg->GetTextHeight($this->t);
$aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size); $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
$h += $aImg->GetTextHeight($this->iSuper); $h += $aImg->GetTextHeight($this->iSuper);
return $h; return $h;
} }
   
function Stroke($aImg,$ax=-1,$ay=-1) { function Stroke($aImg,$ax=-1,$ay=-1) {
   
// To position the super script correctly we need different // To position the super script correctly we need different
// cases to handle the alignmewnt specified since that will // cases to handle the alignmewnt specified since that will
// determine how we can interpret the x,y coordinates // determine how we can interpret the x,y coordinates
   
$w = parent::GetWidth($aImg); $w = parent::GetWidth($aImg);
$h = parent::GetTextHeight($aImg); $h = parent::GetTextHeight($aImg);
switch( $this->valign ) { switch( $this->valign ) {
case 'top': case 'top':
$sy = $this->y; $sy = $this->y;
break; break;
case 'center': case 'center':
$sy = $this->y - $h/2; $sy = $this->y - $h/2;
break; break;
case 'bottom': case 'bottom':
$sy = $this->y - $h; $sy = $this->y - $h;
break; break;
default: default:
JpGraphError::RaiseL(25052);//('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text'); JpGraphError::RaiseL(25052);//('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text');
break; break;
} }
   
switch( $this->halign ) { switch( $this->halign ) {
case 'left': case 'left':
$sx = $this->x + $w; $sx = $this->x + $w;
break; break;
case 'center': case 'center':
$sx = $this->x + $w/2; $sx = $this->x + $w/2;
break; break;
case 'right': case 'right':
$sx = $this->x; $sx = $this->x;
break; break;
default: default:
JpGraphError::RaiseL(25053);//('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text'); JpGraphError::RaiseL(25053);//('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text');
break; break;
} }
   
$sx += $this->iSuperMargin; $sx += $this->iSuperMargin;
$sy += $this->iVertOverlap; $sy += $this->iVertOverlap;
   
// Should we automatically determine the font or // Should we automatically determine the font or
// has the user specified it explicetly? // has the user specified it explicetly?
if( $this->sfont_family == '' ) { if( $this->sfont_family == '' ) {
if( $this->font_family <= FF_FONT2 ) { if( $this->font_family <= FF_FONT2 ) {
if( $this->font_family == FF_FONT0 ) { if( $this->font_family == FF_FONT0 ) {
$sff = FF_FONT0; $sff = FF_FONT0;
} }
elseif( $this->font_family == FF_FONT1 ) { elseif( $this->font_family == FF_FONT1 ) {
if( $this->font_style == FS_NORMAL ) { if( $this->font_style == FS_NORMAL ) {
$sff = FF_FONT0; $sff = FF_FONT0;
} }
else { else {
$sff = FF_FONT1; $sff = FF_FONT1;
} }
} }
else { else {
$sff = FF_FONT1; $sff = FF_FONT1;
} }
$sfs = $this->font_style; $sfs = $this->font_style;
$sfz = $this->font_size; $sfz = $this->font_size;
} }
else { else {
// TTF fonts // TTF fonts
$sff = $this->font_family; $sff = $this->font_family;
$sfs = $this->font_style; $sfs = $this->font_style;
$sfz = floor($this->font_size*$this->iSuperScale); $sfz = floor($this->font_size*$this->iSuperScale);
if( $sfz < 8 ) $sfz = 8; if( $sfz < 8 ) $sfz = 8;
} }
$this->sfont_family = $sff; $this->sfont_family = $sff;
$this->sfont_style = $sfs; $this->sfont_style = $sfs;
$this->sfont_size = $sfz; $this->sfont_size = $sfz;
} }
else { else {
$sff = $this->sfont_family; $sff = $this->sfont_family;
$sfs = $this->sfont_style; $sfs = $this->sfont_style;
$sfz = $this->sfont_size; $sfz = $this->sfont_size;
} }
   
parent::Stroke($aImg,$ax,$ay); parent::Stroke($aImg,$ax,$ay);
   
// For the builtin fonts we need to reduce the margins // For the builtin fonts we need to reduce the margins
// since the bounding bx reported for the builtin fonts // since the bounding bx reported for the builtin fonts
// are much larger than for the TTF fonts. // are much larger than for the TTF fonts.
if( $sff <= FF_FONT2 ) { if( $sff <= FF_FONT2 ) {
$sx -= 2; $sx -= 2;
$sy += 3; $sy += 3;
} }
   
$aImg->SetTextAlign('left','bottom'); $aImg->SetTextAlign('left','bottom');
$aImg->SetFont($sff,$sfs,$sfz); $aImg->SetFont($sff,$sfs,$sfz);
$aImg->PushColor($this->color); $aImg->PushColor($this->color);
$aImg->StrokeText($sx,$sy,$this->iSuper,$this->iSDir,'left'); $aImg->StrokeText($sx,$sy,$this->iSuper,$this->iSDir,'left');
$aImg->PopColor(); $aImg->PopColor();
} }
} }
   
   
//=================================================== //===================================================
// CLASS Grid // CLASS Grid
// Description: responsible for drawing grid lines in graph // Description: responsible for drawing grid lines in graph
//=================================================== //===================================================
class Grid { class Grid {
protected $img; protected $img;
protected $scale; protected $scale;
protected $majorcolor='#DDDDDD',$minorcolor='#EEEEEE'; protected $majorcolor='#DDDDDD',$minorcolor='#EEEEEE';
protected $majortype='solid',$minortype='solid'; protected $majortype='solid',$minortype='solid';
protected $show=false, $showMinor=false,$majorweight=1,$minorweight=1; protected $show=false, $showMinor=false,$majorweight=1,$minorweight=1;
protected $fill=false,$fillcolor=array('#EFEFEF','#BBCCFF'); protected $fill=false,$fillcolor=array('#EFEFEF','#BBCCFF');
   
function __construct($aAxis) { function __construct($aAxis) {
$this->scale = $aAxis->scale; $this->scale = $aAxis->scale;
$this->img = $aAxis->img; $this->img = $aAxis->img;
} }
   
function SetColor($aMajColor,$aMinColor=false) { function SetColor($aMajColor,$aMinColor=false) {
$this->majorcolor=$aMajColor; $this->majorcolor=$aMajColor;
if( $aMinColor === false ) { if( $aMinColor === false ) {
$aMinColor = $aMajColor ; $aMinColor = $aMajColor ;
} }
$this->minorcolor = $aMinColor; $this->minorcolor = $aMinColor;
} }
   
function SetWeight($aMajorWeight,$aMinorWeight=1) { function SetWeight($aMajorWeight,$aMinorWeight=1) {
$this->majorweight=$aMajorWeight; $this->majorweight=$aMajorWeight;
$this->minorweight=$aMinorWeight; $this->minorweight=$aMinorWeight;
} }
   
// Specify if grid should be dashed, dotted or solid // Specify if grid should be dashed, dotted or solid
function SetLineStyle($aMajorType,$aMinorType='solid') { function SetLineStyle($aMajorType,$aMinorType='solid') {
$this->majortype = $aMajorType; $this->majortype = $aMajorType;
$this->minortype = $aMinorType; $this->minortype = $aMinorType;
} }
   
function SetStyle($aMajorType,$aMinorType='solid') { function SetStyle($aMajorType,$aMinorType='solid') {
$this->SetLineStyle($aMajorType,$aMinorType); $this->SetLineStyle($aMajorType,$aMinorType);
} }
   
// Decide if both major and minor grid should be displayed // Decide if both major and minor grid should be displayed
function Show($aShowMajor=true,$aShowMinor=false) { function Show($aShowMajor=true,$aShowMinor=false) {
$this->show=$aShowMajor; $this->show=$aShowMajor;
$this->showMinor=$aShowMinor; $this->showMinor=$aShowMinor;
} }
   
function SetFill($aFlg=true,$aColor1='lightgray',$aColor2='lightblue') { function SetFill($aFlg=true,$aColor1='lightgray',$aColor2='lightblue') {
$this->fill = $aFlg; $this->fill = $aFlg;
$this->fillcolor = array( $aColor1, $aColor2 ); $this->fillcolor = array( $aColor1, $aColor2 );
} }
   
// Display the grid // Display the grid
function Stroke() { function Stroke() {
if( $this->showMinor && !$this->scale->textscale ) { if( $this->showMinor && !$this->scale->textscale ) {
$this->DoStroke($this->scale->ticks->ticks_pos,$this->minortype,$this->minorcolor,$this->minorweight); $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); $this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight);
} }
else { else {
$this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight); $this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight);
} }
} }
   
//-------------- //--------------
// Private methods // Private methods
// Draw the grid // Draw the grid
function DoStroke($aTicksPos,$aType,$aColor,$aWeight) { function DoStroke($aTicksPos,$aType,$aColor,$aWeight) {
if( !$this->show ) return; if( !$this->show ) return;
$nbrgrids = count($aTicksPos); $nbrgrids = count($aTicksPos);
   
if( $this->scale->type == 'y' ) { if( $this->scale->type == 'y' ) {
$xl=$this->img->left_margin; $xl=$this->img->left_margin;
$xr=$this->img->width-$this->img->right_margin; $xr=$this->img->width-$this->img->right_margin;
   
if( $this->fill ) { if( $this->fill ) {
// Draw filled areas // Draw filled areas
$y2 = $aTicksPos[0]; $y2 = $aTicksPos[0];
$i=1; $i=1;
while( $i < $nbrgrids ) { while( $i < $nbrgrids ) {
$y1 = $y2; $y1 = $y2;
$y2 = $aTicksPos[$i++]; $y2 = $aTicksPos[$i++];
$this->img->SetColor($this->fillcolor[$i & 1]); $this->img->SetColor($this->fillcolor[$i & 1]);
$this->img->FilledRectangle($xl,$y1,$xr,$y2); $this->img->FilledRectangle($xl,$y1,$xr,$y2);
} }
} }
   
$this->img->SetColor($aColor); $this->img->SetColor($aColor);
$this->img->SetLineWeight($aWeight); $this->img->SetLineWeight($aWeight);
   
// Draw grid lines // Draw grid lines
switch( $aType ) { switch( $aType ) {
case 'solid': $style = LINESTYLE_SOLID; break; case 'solid': $style = LINESTYLE_SOLID; break;
case 'dotted': $style = LINESTYLE_DOTTED; break; case 'dotted': $style = LINESTYLE_DOTTED; break;
case 'dashed': $style = LINESTYLE_DASHED; break; case 'dashed': $style = LINESTYLE_DASHED; break;
case 'longdashed': $style = LINESTYLE_LONGDASH; break; case 'longdashed': $style = LINESTYLE_LONGDASH; break;
default: default:
$style = LINESTYLE_SOLID; break; $style = LINESTYLE_SOLID; break;
} }
   
for($i=0; $i < $nbrgrids; ++$i) { for($i=0; $i < $nbrgrids; ++$i) {
$y=$aTicksPos[$i]; $y=$aTicksPos[$i];
$this->img->StyleLine($xl,$y,$xr,$y,$style); $this->img->StyleLine($xl,$y,$xr,$y,$style);
} }
} }
elseif( $this->scale->type == 'x' ) { elseif( $this->scale->type == 'x' ) {
$yu=$this->img->top_margin; $yu=$this->img->top_margin;
$yl=$this->img->height-$this->img->bottom_margin; $yl=$this->img->height-$this->img->bottom_margin;
$limit=$this->img->width-$this->img->right_margin; $limit=$this->img->width-$this->img->right_margin;
   
if( $this->fill ) { if( $this->fill ) {
// Draw filled areas // Draw filled areas
$x2 = $aTicksPos[0]; $x2 = $aTicksPos[0];
$i=1; $i=1;
while( $i < $nbrgrids ) { while( $i < $nbrgrids ) {
$x1 = $x2; $x1 = $x2;
$x2 = min($aTicksPos[$i++],$limit) ; $x2 = min($aTicksPos[$i++],$limit) ;
$this->img->SetColor($this->fillcolor[$i & 1]); $this->img->SetColor($this->fillcolor[$i & 1]);
$this->img->FilledRectangle($x1,$yu,$x2,$yl); $this->img->FilledRectangle($x1,$yu,$x2,$yl);
} }
} }
   
$this->img->SetColor($aColor); $this->img->SetColor($aColor);
$this->img->SetLineWeight($aWeight); $this->img->SetLineWeight($aWeight);
   
// We must also test for limit since we might have // We must also test for limit since we might have
// an offset and the number of ticks is calculated with // an offset and the number of ticks is calculated with
// assumption offset==0 so we might end up drawing one // assumption offset==0 so we might end up drawing one
// to many gridlines // to many gridlines
$i=0; $i=0;
$x=$aTicksPos[$i]; $x=$aTicksPos[$i];
while( $i<count($aTicksPos) && ($x=$aTicksPos[$i]) <= $limit ) { while( $i<count($aTicksPos) && ($x=$aTicksPos[$i]) <= $limit ) {
if ( $aType == 'solid' ) $this->img->Line($x,$yl,$x,$yu); if ( $aType == 'solid' ) $this->img->Line($x,$yl,$x,$yu);
elseif( $aType == 'dotted' ) $this->img->DashedLine($x,$yl,$x,$yu,1,6); elseif( $aType == 'dotted' ) $this->img->DashedLine($x,$yl,$x,$yu,1,6);
elseif( $aType == 'dashed' ) $this->img->DashedLine($x,$yl,$x,$yu,2,4); elseif( $aType == 'dashed' ) $this->img->DashedLine($x,$yl,$x,$yu,2,4);
elseif( $aType == 'longdashed' ) $this->img->DashedLine($x,$yl,$x,$yu,8,6); elseif( $aType == 'longdashed' ) $this->img->DashedLine($x,$yl,$x,$yu,8,6);
++$i; ++$i;
} }
} }
else { else {
JpGraphError::RaiseL(25054,$this->scale->type);//('Internal error: Unknown grid axis ['.$this->scale->type.']'); JpGraphError::RaiseL(25054,$this->scale->type);//('Internal error: Unknown grid axis ['.$this->scale->type.']');
} }
return true; return true;
} }
} // Class } // Class
   
//=================================================== //===================================================
// CLASS Axis // CLASS Axis
// Description: Defines X and Y axis. Notes that at the // Description: Defines X and Y axis. Notes that at the
// moment the code is not really good since the axis on // moment the code is not really good since the axis on
// several occasion must know wheter it's an X or Y axis. // several occasion must know wheter it's an X or Y axis.
// This was a design decision to make the code easier to // This was a design decision to make the code easier to
// follow. // follow.
//=================================================== //===================================================
class AxisPrototype { class AxisPrototype {
public $scale=null; public $scale=null;
public $img=null; public $img=null;
public $hide=false,$hide_labels=false; public $hide=false,$hide_labels=false;
public $title=null; public $title=null;
public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12,$label_angle=0; public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12,$label_angle=0;
public $tick_step=1; public $tick_step=1;
public $pos = false; public $pos = false;
public $ticks_label = array(); public $ticks_label = array();
   
protected $weight=1; protected $weight=1;
protected $color=array(0,0,0),$label_color=array(0,0,0); protected $color=array(0,0,0),$label_color=array(0,0,0);
protected $ticks_label_colors=null; protected $ticks_label_colors=null;
protected $show_first_label=true,$show_last_label=true; 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 protected $label_step=1; // Used by a text axis to specify what multiple of major steps
// should be labeled. // should be labeled.
protected $labelPos=0; // Which side of the axis should the labels be? protected $labelPos=0; // Which side of the axis should the labels be?
protected $title_adjust,$title_margin,$title_side=SIDE_LEFT; protected $title_adjust,$title_margin,$title_side=SIDE_LEFT;
protected $tick_label_margin=5; protected $tick_label_margin=5;
protected $label_halign = '',$label_valign = '', $label_para_align='left'; protected $label_halign = '',$label_valign = '', $label_para_align='left';
protected $hide_line=false; protected $hide_line=false;
protected $iDeltaAbsPos=0; protected $iDeltaAbsPos=0;
   
function __construct($img,$aScale,$color = array(0,0,0)) { function __construct($img,$aScale,$color = array(0,0,0)) {
$this->img = $img; $this->img = $img;
$this->scale = $aScale; $this->scale = $aScale;
$this->color = $color; $this->color = $color;
$this->title=new Text(''); $this->title=new Text('');
   
if( $aScale->type == 'y' ) { if( $aScale->type == 'y' ) {
$this->title_margin = 25; $this->title_margin = 25;
$this->title_adjust = 'middle'; $this->title_adjust = 'middle';
$this->title->SetOrientation(90); $this->title->SetOrientation(90);
$this->tick_label_margin=7; $this->tick_label_margin=7;
$this->labelPos=SIDE_LEFT; $this->labelPos=SIDE_LEFT;
} }
else { else {
$this->title_margin = 5; $this->title_margin = 5;
$this->title_adjust = 'high'; $this->title_adjust = 'high';
$this->title->SetOrientation(0); $this->title->SetOrientation(0);
$this->tick_label_margin=5; $this->tick_label_margin=5;
$this->labelPos=SIDE_DOWN; $this->labelPos=SIDE_DOWN;
$this->title_side=SIDE_DOWN; $this->title_side=SIDE_DOWN;
} }
} }
   
function SetLabelFormat($aFormStr) { function SetLabelFormat($aFormStr) {
$this->scale->ticks->SetLabelFormat($aFormStr); $this->scale->ticks->SetLabelFormat($aFormStr);
} }
   
function SetLabelFormatString($aFormStr,$aDate=false) { function SetLabelFormatString($aFormStr,$aDate=false) {
$this->scale->ticks->SetLabelFormat($aFormStr,$aDate); $this->scale->ticks->SetLabelFormat($aFormStr,$aDate);
} }
   
function SetLabelFormatCallback($aFuncName) { function SetLabelFormatCallback($aFuncName) {
$this->scale->ticks->SetFormatCallback($aFuncName); $this->scale->ticks->SetFormatCallback($aFuncName);
} }
   
function SetLabelAlign($aHAlign,$aVAlign='top',$aParagraphAlign='left') { function SetLabelAlign($aHAlign,$aVAlign='top',$aParagraphAlign='left') {
$this->label_halign = $aHAlign; $this->label_halign = $aHAlign;
$this->label_valign = $aVAlign; $this->label_valign = $aVAlign;
$this->label_para_align = $aParagraphAlign; $this->label_para_align = $aParagraphAlign;
} }
   
// Don't display the first label // Don't display the first label
function HideFirstTickLabel($aShow=false) { function HideFirstTickLabel($aShow=false) {
$this->show_first_label=$aShow; $this->show_first_label=$aShow;
} }
   
function HideLastTickLabel($aShow=false) { function HideLastTickLabel($aShow=false) {
$this->show_last_label=$aShow; $this->show_last_label=$aShow;
} }
   
// Manually specify the major and (optional) minor tick position and labels // Manually specify the major and (optional) minor tick position and labels
function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) { function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) {
$this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels); $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels);
} }
   
// Manually specify major tick positions and optional labels // Manually specify major tick positions and optional labels
function SetMajTickPositions($aMajPos,$aLabels=NULL) { function SetMajTickPositions($aMajPos,$aLabels=NULL) {
$this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels); $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels);
} }
   
// Hide minor or major tick marks // Hide minor or major tick marks
function HideTicks($aHideMinor=true,$aHideMajor=true) { function HideTicks($aHideMinor=true,$aHideMajor=true) {
$this->scale->ticks->SupressMinorTickMarks($aHideMinor); $this->scale->ticks->SupressMinorTickMarks($aHideMinor);
$this->scale->ticks->SupressTickMarks($aHideMajor); $this->scale->ticks->SupressTickMarks($aHideMajor);
} }
   
// Hide zero label // Hide zero label
function HideZeroLabel($aFlag=true) { function HideZeroLabel($aFlag=true) {
$this->scale->ticks->SupressZeroLabel(); $this->scale->ticks->SupressZeroLabel();
} }
   
function HideFirstLastLabel() { function HideFirstLastLabel() {
// The two first calls to ticks method will supress // The two first calls to ticks method will supress
// automatically generated scale values. However, that // automatically generated scale values. However, that
// will not affect manually specified value, e.g text-scales. // will not affect manually specified value, e.g text-scales.
// therefor we also make a kludge here to supress manually // therefor we also make a kludge here to supress manually
// specified scale labels. // specified scale labels.
$this->scale->ticks->SupressLast(); $this->scale->ticks->SupressLast();
$this->scale->ticks->SupressFirst(); $this->scale->ticks->SupressFirst();
$this->show_first_label = false; $this->show_first_label = false;
$this->show_last_label = false; $this->show_last_label = false;
} }
   
// Hide the axis // Hide the axis
function Hide($aHide=true) { function Hide($aHide=true) {
$this->hide=$aHide; $this->hide=$aHide;
} }
   
// Hide the actual axis-line, but still print the labels // Hide the actual axis-line, but still print the labels
function HideLine($aHide=true) { function HideLine($aHide=true) {
$this->hide_line = $aHide; $this->hide_line = $aHide;
} }
   
function HideLabels($aHide=true) { function HideLabels($aHide=true) {
$this->hide_labels = $aHide; $this->hide_labels = $aHide;
} }
   
// Weight of axis // Weight of axis
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->weight = $aWeight; $this->weight = $aWeight;
} }
   
// Axis color // Axis color
function SetColor($aColor,$aLabelColor=false) { function SetColor($aColor,$aLabelColor=false) {
$this->color = $aColor; $this->color = $aColor;
if( !$aLabelColor ) $this->label_color = $aColor; if( !$aLabelColor ) $this->label_color = $aColor;
else $this->label_color = $aLabelColor; else $this->label_color = $aLabelColor;
} }
   
// Title on axis // Title on axis
function SetTitle($aTitle,$aAdjustAlign='high') { function SetTitle($aTitle,$aAdjustAlign='high') {
$this->title->Set($aTitle); $this->title->Set($aTitle);
$this->title_adjust=$aAdjustAlign; $this->title_adjust=$aAdjustAlign;
} }
   
// Specify distance from the axis // Specify distance from the axis
function SetTitleMargin($aMargin) { function SetTitleMargin($aMargin) {
$this->title_margin=$aMargin; $this->title_margin=$aMargin;
} }
   
// Which side of the axis should the axis title be? // Which side of the axis should the axis title be?
function SetTitleSide($aSideOfAxis) { function SetTitleSide($aSideOfAxis) {
$this->title_side = $aSideOfAxis; $this->title_side = $aSideOfAxis;
} }
   
function SetTickSide($aDir) { function SetTickSide($aDir) {
$this->scale->ticks->SetSide($aDir); $this->scale->ticks->SetSide($aDir);
} }
   
function SetTickSize($aMajSize,$aMinSize=3) { function SetTickSize($aMajSize,$aMinSize=3) {
$this->scale->ticks->SetSize($aMajSize,$aMinSize=3); $this->scale->ticks->SetSize($aMajSize,$aMinSize=3);
} }
   
// Specify text labels for the ticks. One label for each data point // Specify text labels for the ticks. One label for each data point
function SetTickLabels($aLabelArray,$aLabelColorArray=null) { function SetTickLabels($aLabelArray,$aLabelColorArray=null) {
$this->ticks_label = $aLabelArray; $this->ticks_label = $aLabelArray;
$this->ticks_label_colors = $aLabelColorArray; $this->ticks_label_colors = $aLabelColorArray;
} }
   
function SetLabelMargin($aMargin) { function SetLabelMargin($aMargin) {
$this->tick_label_margin=$aMargin; $this->tick_label_margin=$aMargin;
} }
   
// Specify that every $step of the ticks should be displayed starting // Specify that every $step of the ticks should be displayed starting
// at $start // at $start
function SetTextTickInterval($aStep,$aStart=0) { function SetTextTickInterval($aStep,$aStart=0) {
$this->scale->ticks->SetTextLabelStart($aStart); $this->scale->ticks->SetTextLabelStart($aStart);
$this->tick_step=$aStep; $this->tick_step=$aStep;
} }
   
// Specify that every $step tick mark should have a label // Specify that every $step tick mark should have a label
// should be displayed starting // should be displayed starting
function SetTextLabelInterval($aStep) { function SetTextLabelInterval($aStep) {
if( $aStep < 1 ) { if( $aStep < 1 ) {
JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1."); JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1.");
} }
$this->label_step=$aStep; $this->label_step=$aStep;
} }
   
function SetLabelSide($aSidePos) { function SetLabelSide($aSidePos) {
$this->labelPos=$aSidePos; $this->labelPos=$aSidePos;
} }
   
// Set the font // Set the font
function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
$this->font_family = $aFamily; $this->font_family = $aFamily;
$this->font_style = $aStyle; $this->font_style = $aStyle;
$this->font_size = $aSize; $this->font_size = $aSize;
} }
   
// Position for axis line on the "other" scale // Position for axis line on the "other" scale
function SetPos($aPosOnOtherScale) { function SetPos($aPosOnOtherScale) {
$this->pos=$aPosOnOtherScale; $this->pos=$aPosOnOtherScale;
} }
   
// Set the position of the axis to be X-pixels delta to the right // 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) // of the max X-position (used to position the multiple Y-axis)
function SetPosAbsDelta($aDelta) { function SetPosAbsDelta($aDelta) {
$this->iDeltaAbsPos=$aDelta; $this->iDeltaAbsPos=$aDelta;
} }
   
// Specify the angle for the tick labels // Specify the angle for the tick labels
function SetLabelAngle($aAngle) { function SetLabelAngle($aAngle) {
$this->label_angle = $aAngle; $this->label_angle = $aAngle;
} }
   
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS Axis // CLASS Axis
// Description: Defines X and Y axis. Notes that at the // Description: Defines X and Y axis. Notes that at the
// moment the code is not really good since the axis on // moment the code is not really good since the axis on
// several occasion must know wheter it's an X or Y axis. // several occasion must know wheter it's an X or Y axis.
// This was a design decision to make the code easier to // This was a design decision to make the code easier to
// follow. // follow.
//=================================================== //===================================================
class Axis extends AxisPrototype { class Axis extends AxisPrototype {
   
function __construct($img,$aScale,$color='black') { function __construct($img,$aScale,$color='black') {
parent::__construct($img,$aScale,$color); parent::__construct($img,$aScale,$color);
} }
   
// Stroke the axis. // Stroke the axis.
function Stroke($aOtherAxisScale,$aStrokeLabels=true) { function Stroke($aOtherAxisScale,$aStrokeLabels=true) {
if( $this->hide ) if( $this->hide )
return; return;
if( is_numeric($this->pos) ) { if( is_numeric($this->pos) ) {
$pos=$aOtherAxisScale->Translate($this->pos); $pos=$aOtherAxisScale->Translate($this->pos);
} }
else { // Default to minimum of other scale if pos not set else { // Default to minimum of other scale if pos not set
if( ($aOtherAxisScale->GetMinVal() >= 0 && $this->pos==false) || $this->pos == 'min' ) { if( ($aOtherAxisScale->GetMinVal() >= 0 && $this->pos==false) || $this->pos == 'min' ) {
$pos = $aOtherAxisScale->scale_abs[0]; $pos = $aOtherAxisScale->scale_abs[0];
} }
elseif($this->pos == "max") { elseif($this->pos == "max") {
$pos = $aOtherAxisScale->scale_abs[1]; $pos = $aOtherAxisScale->scale_abs[1];
} }
else { // If negative set x-axis at 0 else { // If negative set x-axis at 0
$this->pos=0; $this->pos=0;
$pos=$aOtherAxisScale->Translate(0); $pos=$aOtherAxisScale->Translate(0);
} }
} }
$pos += $this->iDeltaAbsPos; $pos += $this->iDeltaAbsPos;
$this->img->SetLineWeight($this->weight); $this->img->SetLineWeight($this->weight);
$this->img->SetColor($this->color); $this->img->SetColor($this->color);
$this->img->SetFont($this->font_family,$this->font_style,$this->font_size); $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
if( $this->scale->type == "x" ) { if( $this->scale->type == "x" ) {
if( !$this->hide_line ) { if( !$this->hide_line ) {
$this->img->FilledRectangle($this->img->left_margin,$pos,$this->img->width-$this->img->right_margin,$pos+$this->weight-1); $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 ) { if( $this->title_side == SIDE_DOWN ) {
$y = $pos + $this->img->GetFontHeight() + $this->title_margin + $this->title->margin; $y = $pos + $this->img->GetFontHeight() + $this->title_margin + $this->title->margin;
$yalign = 'top'; $yalign = 'top';
} }
else { else {
$y = $pos - $this->img->GetFontHeight() - $this->title_margin - $this->title->margin; $y = $pos - $this->img->GetFontHeight() - $this->title_margin - $this->title->margin;
$yalign = 'bottom'; $yalign = 'bottom';
} }
   
if( $this->title_adjust=='high' ) { if( $this->title_adjust=='high' ) {
$this->title->SetPos($this->img->width-$this->img->right_margin,$y,'right',$yalign); $this->title->SetPos($this->img->width-$this->img->right_margin,$y,'right',$yalign);
} }
elseif( $this->title_adjust=='middle' || $this->title_adjust=='center' ) { 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); $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') { elseif($this->title_adjust=='low') {
$this->title->SetPos($this->img->left_margin,$y,'left',$yalign); $this->title->SetPos($this->img->left_margin,$y,'left',$yalign);
} }
else { else {
JpGraphError::RaiseL(25060,$this->title_adjust);//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')'); JpGraphError::RaiseL(25060,$this->title_adjust);//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')');
} }
} }
elseif( $this->scale->type == "y" ) { elseif( $this->scale->type == "y" ) {
// Add line weight to the height of the axis since // 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. // the x-axis could have a width>1 and we want the axis to fit nicely together.
if( !$this->hide_line ) { 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); $this->img->FilledRectangle($pos-$this->weight+1,$this->img->top_margin,$pos,$this->img->height-$this->img->bottom_margin+$this->weight-1);
} }
$x=$pos ; $x=$pos ;
if( $this->title_side == SIDE_LEFT ) { if( $this->title_side == SIDE_LEFT ) {
$x -= $this->title_margin; $x -= $this->title_margin;
$x -= $this->title->margin; $x -= $this->title->margin;
$halign = 'right'; $halign = 'right';
} }
else { else {
$x += $this->title_margin; $x += $this->title_margin;
$x += $this->title->margin; $x += $this->title->margin;
$halign = 'left'; $halign = 'left';
} }
// If the user has manually specified an hor. align // If the user has manually specified an hor. align
// then we override the automatic settings with this // then we override the automatic settings with this
// specifed setting. Since default is 'left' we compare // specifed setting. Since default is 'left' we compare
// with that. (This means a manually set 'left' align // with that. (This means a manually set 'left' align
// will have no effect.) // will have no effect.)
if( $this->title->halign != 'left' ) { if( $this->title->halign != 'left' ) {
$halign = $this->title->halign; $halign = $this->title->halign;
} }
if( $this->title_adjust == 'high' ) { if( $this->title_adjust == 'high' ) {
$this->title->SetPos($x,$this->img->top_margin,$halign,'top'); $this->title->SetPos($x,$this->img->top_margin,$halign,'top');
} }
elseif($this->title_adjust=='middle' || $this->title_adjust=='center') { 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"); $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') { elseif($this->title_adjust=='low') {
$this->title->SetPos($x,$this->img->height-$this->img->bottom_margin,$halign,'bottom'); $this->title->SetPos($x,$this->img->height-$this->img->bottom_margin,$halign,'bottom');
} }
else { else {
JpGraphError::RaiseL(25061,$this->title_adjust);//('Unknown alignment specified for Y-axis title. ('.$this->title_adjust.')'); 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); $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
if( $aStrokeLabels ) { if( $aStrokeLabels ) {
if( !$this->hide_labels ) { if( !$this->hide_labels ) {
$this->StrokeLabels($pos); $this->StrokeLabels($pos);
} }
$this->title->Stroke($this->img); $this->title->Stroke($this->img);
} }
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
// Draw all the tick labels on major tick marks // Draw all the tick labels on major tick marks
function StrokeLabels($aPos,$aMinor=false,$aAbsLabel=false) { function StrokeLabels($aPos,$aMinor=false,$aAbsLabel=false) {
   
if( is_array($this->label_color) && count($this->label_color) > 3 ) { if( is_array($this->label_color) && count($this->label_color) > 3 ) {
$this->ticks_label_colors = $this->label_color; $this->ticks_label_colors = $this->label_color;
$this->img->SetColor($this->label_color[0]); $this->img->SetColor($this->label_color[0]);
} }
else { else {
$this->img->SetColor($this->label_color); $this->img->SetColor($this->label_color);
} }
$this->img->SetFont($this->font_family,$this->font_style,$this->font_size); $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
$yoff=$this->img->GetFontHeight()/2; $yoff=$this->img->GetFontHeight()/2;
   
// Only draw labels at major tick marks // Only draw labels at major tick marks
$nbr = count($this->scale->ticks->maj_ticks_label); $nbr = count($this->scale->ticks->maj_ticks_label);
   
// We have the option to not-display the very first mark // We have the option to not-display the very first mark
// (Usefull when the first label might interfere with another // (Usefull when the first label might interfere with another
// axis.) // axis.)
$i = $this->show_first_label ? 0 : 1 ; $i = $this->show_first_label ? 0 : 1 ;
if( !$this->show_last_label ) { if( !$this->show_last_label ) {
--$nbr; --$nbr;
} }
// Now run through all labels making sure we don't overshoot the end // Now run through all labels making sure we don't overshoot the end
// of the scale. // of the scale.
$ncolor=0; $ncolor=0;
if( isset($this->ticks_label_colors) ) { if( isset($this->ticks_label_colors) ) {
$ncolor=count($this->ticks_label_colors); $ncolor=count($this->ticks_label_colors);
} }
while( $i < $nbr ) { while( $i < $nbr ) {
// $tpos holds the absolute text position for the label // $tpos holds the absolute text position for the label
$tpos=$this->scale->ticks->maj_ticklabels_pos[$i]; $tpos=$this->scale->ticks->maj_ticklabels_pos[$i];
   
// Note. the $limit is only used for the x axis since we // Note. the $limit is only used for the x axis since we
// might otherwise overshoot if the scale has been centered // might otherwise overshoot if the scale has been centered
// This is due to us "loosing" the last tick mark if we center. // 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 ) { if( $this->scale->type == 'x' && $tpos > $this->img->width-$this->img->right_margin+1 ) {
return; return;
} }
// we only draw every $label_step label // we only draw every $label_step label
if( ($i % $this->label_step)==0 ) { if( ($i % $this->label_step)==0 ) {
   
// Set specific label color if specified // Set specific label color if specified
if( $ncolor > 0 ) { if( $ncolor > 0 ) {
$this->img->SetColor($this->ticks_label_colors[$i % $ncolor]); $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
} }
   
// If the label has been specified use that and in other case // If the label has been specified use that and in other case
// just label the mark with the actual scale value // just label the mark with the actual scale value
$m=$this->scale->ticks->GetMajor(); $m=$this->scale->ticks->GetMajor();
   
// ticks_label has an entry for each data point and is the array // 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 // that holds the labels set by the user. If the user hasn't
// specified any values we use whats in the automatically asigned // specified any values we use whats in the automatically asigned
// labels in the maj_ticks_label // labels in the maj_ticks_label
if( isset($this->ticks_label[$i*$m]) ) { if( isset($this->ticks_label[$i*$m]) ) {
$label=$this->ticks_label[$i*$m]; $label=$this->ticks_label[$i*$m];
} }
else { else {
if( $aAbsLabel ) { if( $aAbsLabel ) {
$label=abs($this->scale->ticks->maj_ticks_label[$i]); $label=abs($this->scale->ticks->maj_ticks_label[$i]);
} }
else { else {
$label=$this->scale->ticks->maj_ticks_label[$i]; $label=$this->scale->ticks->maj_ticks_label[$i];
} }
   
// We number the scale from 1 and not from 0 so increase by one // We number the scale from 1 and not from 0 so increase by one
if( $this->scale->textscale && if( $this->scale->textscale &&
$this->scale->ticks->label_formfunc == '' && $this->scale->ticks->label_formfunc == '' &&
! $this->scale->ticks->HaveManualLabels() ) { ! $this->scale->ticks->HaveManualLabels() ) {
   
++$label; ++$label;
} }
} }
   
if( $this->scale->type == "x" ) { if( $this->scale->type == "x" ) {
if( $this->labelPos == SIDE_DOWN ) { if( $this->labelPos == SIDE_DOWN ) {
if( $this->label_angle==0 || $this->label_angle==90 ) { if( $this->label_angle==0 || $this->label_angle==90 ) {
if( $this->label_halign=='' && $this->label_valign=='') { if( $this->label_halign=='' && $this->label_valign=='') {
$this->img->SetTextAlign('center','top'); $this->img->SetTextAlign('center','top');
} }
else { else {
$this->img->SetTextAlign($this->label_halign,$this->label_valign); $this->img->SetTextAlign($this->label_halign,$this->label_valign);
} }
   
} }
else { else {
if( $this->label_halign=='' && $this->label_valign=='') { if( $this->label_halign=='' && $this->label_valign=='') {
$this->img->SetTextAlign("right","top"); $this->img->SetTextAlign("right","top");
} }
else { else {
$this->img->SetTextAlign($this->label_halign,$this->label_valign); $this->img->SetTextAlign($this->label_halign,$this->label_valign);
} }
} }
$this->img->StrokeText($tpos,$aPos+$this->tick_label_margin,$label, $this->img->StrokeText($tpos,$aPos+$this->tick_label_margin,$label,
$this->label_angle,$this->label_para_align); $this->label_angle,$this->label_para_align);
} }
else { else {
if( $this->label_angle==0 || $this->label_angle==90 ) { if( $this->label_angle==0 || $this->label_angle==90 ) {
if( $this->label_halign=='' && $this->label_valign=='') { if( $this->label_halign=='' && $this->label_valign=='') {
$this->img->SetTextAlign("center","bottom"); $this->img->SetTextAlign("center","bottom");
} }
else { else {
$this->img->SetTextAlign($this->label_halign,$this->label_valign); $this->img->SetTextAlign($this->label_halign,$this->label_valign);
} }
} }
else { else {
if( $this->label_halign=='' && $this->label_valign=='') { if( $this->label_halign=='' && $this->label_valign=='') {
$this->img->SetTextAlign("right","bottom"); $this->img->SetTextAlign("right","bottom");
} }
else { else {
$this->img->SetTextAlign($this->label_halign,$this->label_valign); $this->img->SetTextAlign($this->label_halign,$this->label_valign);
} }
} }
$this->img->StrokeText($tpos,$aPos-$this->tick_label_margin-1,$label, $this->img->StrokeText($tpos,$aPos-$this->tick_label_margin-1,$label,
$this->label_angle,$this->label_para_align); $this->label_angle,$this->label_para_align);
} }
} }
else { else {
// scale->type == "y" // scale->type == "y"
//if( $this->label_angle!=0 ) //if( $this->label_angle!=0 )
//JpGraphError::Raise(" Labels at an angle are not supported on Y-axis"); //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->labelPos == SIDE_LEFT ) { // To the left of y-axis
if( $this->label_halign=='' && $this->label_valign=='') { if( $this->label_halign=='' && $this->label_valign=='') {
$this->img->SetTextAlign("right","center"); $this->img->SetTextAlign("right","center");
} }
else { else {
$this->img->SetTextAlign($this->label_halign,$this->label_valign); $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); $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 else { // To the right of the y-axis
if( $this->label_halign=='' && $this->label_valign=='') { if( $this->label_halign=='' && $this->label_valign=='') {
$this->img->SetTextAlign("left","center"); $this->img->SetTextAlign("left","center");
} }
else { else {
$this->img->SetTextAlign($this->label_halign,$this->label_valign); $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); $this->img->StrokeText($aPos+$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align);
} }
} }
} }
++$i; ++$i;
} }
} }
   
} }
   
   
//=================================================== //===================================================
// CLASS Ticks // CLASS Ticks
// Description: Abstract base class for drawing linear and logarithmic // Description: Abstract base class for drawing linear and logarithmic
// tick marks on axis // tick marks on axis
//=================================================== //===================================================
class Ticks { class Ticks {
public $label_formatstr=''; // C-style format string to use for labels public $label_formatstr=''; // C-style format string to use for labels
public $label_formfunc=''; public $label_formfunc='';
public $label_dateformatstr=''; public $label_dateformatstr='';
public $direction=1; // Should ticks be in(=1) the plot area or outside (=-1) 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 $supress_last=false,$supress_tickmarks=false,$supress_minor_tickmarks=false;
public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(), public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(),
$ticks_pos = array(), $maj_ticks_label = array(); $ticks_pos = array(), $maj_ticks_label = array();
public $precision; public $precision;
   
protected $minor_abs_size=3, $major_abs_size=5; protected $minor_abs_size=3, $major_abs_size=5;
protected $scale; protected $scale;
protected $is_set=false; protected $is_set=false;
protected $supress_zerolabel=false,$supress_first=false; protected $supress_zerolabel=false,$supress_first=false;
protected $mincolor='',$majcolor=''; protected $mincolor='',$majcolor='';
protected $weight=1; protected $weight=1;
protected $label_usedateformat=FALSE; protected $label_usedateformat=FALSE;
   
function __construct($aScale) { function __construct($aScale) {
$this->scale=$aScale; $this->scale=$aScale;
$this->precision = -1; $this->precision = -1;
} }
   
// Set format string for automatic labels // Set format string for automatic labels
function SetLabelFormat($aFormatString,$aDate=FALSE) { function SetLabelFormat($aFormatString,$aDate=FALSE) {
$this->label_formatstr=$aFormatString; $this->label_formatstr=$aFormatString;
$this->label_usedateformat=$aDate; $this->label_usedateformat=$aDate;
} }
   
function SetLabelDateFormat($aFormatString) { function SetLabelDateFormat($aFormatString) {
$this->label_dateformatstr=$aFormatString; $this->label_dateformatstr=$aFormatString;
} }
   
function SetFormatCallback($aCallbackFuncName) { function SetFormatCallback($aCallbackFuncName) {
$this->label_formfunc = $aCallbackFuncName; $this->label_formfunc = $aCallbackFuncName;
} }
   
// Don't display the first zero label // Don't display the first zero label
function SupressZeroLabel($aFlag=true) { function SupressZeroLabel($aFlag=true) {
$this->supress_zerolabel=$aFlag; $this->supress_zerolabel=$aFlag;
} }
   
// Don't display minor tick marks // Don't display minor tick marks
function SupressMinorTickMarks($aHide=true) { function SupressMinorTickMarks($aHide=true) {
$this->supress_minor_tickmarks=$aHide; $this->supress_minor_tickmarks=$aHide;
} }
   
// Don't display major tick marks // Don't display major tick marks
function SupressTickMarks($aHide=true) { function SupressTickMarks($aHide=true) {
$this->supress_tickmarks=$aHide; $this->supress_tickmarks=$aHide;
} }
   
// Hide the first tick mark // Hide the first tick mark
function SupressFirst($aHide=true) { function SupressFirst($aHide=true) {
$this->supress_first=$aHide; $this->supress_first=$aHide;
} }
   
// Hide the last tick mark // Hide the last tick mark
function SupressLast($aHide=true) { function SupressLast($aHide=true) {
$this->supress_last=$aHide; $this->supress_last=$aHide;
} }
   
// Size (in pixels) of minor tick marks // Size (in pixels) of minor tick marks
function GetMinTickAbsSize() { function GetMinTickAbsSize() {
return $this->minor_abs_size; return $this->minor_abs_size;
} }
   
// Size (in pixels) of major tick marks // Size (in pixels) of major tick marks
function GetMajTickAbsSize() { function GetMajTickAbsSize() {
return $this->major_abs_size; return $this->major_abs_size;
} }
   
function SetSize($aMajSize,$aMinSize=3) { function SetSize($aMajSize,$aMinSize=3) {
$this->major_abs_size = $aMajSize; $this->major_abs_size = $aMajSize;
$this->minor_abs_size = $aMinSize; $this->minor_abs_size = $aMinSize;
} }
   
// Have the ticks been specified // Have the ticks been specified
function IsSpecified() { function IsSpecified() {
return $this->is_set; return $this->is_set;
} }
   
function SetSide($aSide) { function SetSide($aSide) {
$this->direction=$aSide; $this->direction=$aSide;
} }
   
// Which side of the axis should the ticks be on // Which side of the axis should the ticks be on
function SetDirection($aSide=SIDE_RIGHT) { function SetDirection($aSide=SIDE_RIGHT) {
$this->direction=$aSide; $this->direction=$aSide;
} }
   
// Set colors for major and minor tick marks // Set colors for major and minor tick marks
function SetMarkColor($aMajorColor,$aMinorColor='') { function SetMarkColor($aMajorColor,$aMinorColor='') {
$this->SetColor($aMajorColor,$aMinorColor); $this->SetColor($aMajorColor,$aMinorColor);
} }
   
function SetColor($aMajorColor,$aMinorColor='') { function SetColor($aMajorColor,$aMinorColor='') {
$this->majcolor=$aMajorColor; $this->majcolor=$aMajorColor;
   
// If not specified use same as major // If not specified use same as major
if( $aMinorColor == '' ) { if( $aMinorColor == '' ) {
$this->mincolor=$aMajorColor; $this->mincolor=$aMajorColor;
} }
else { else {
$this->mincolor=$aMinorColor; $this->mincolor=$aMinorColor;
} }
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->weight=$aWeight; $this->weight=$aWeight;
} }
   
} // Class } // Class
   
//=================================================== //===================================================
// CLASS LinearTicks // CLASS LinearTicks
// Description: Draw linear ticks on axis // Description: Draw linear ticks on axis
//=================================================== //===================================================
class LinearTicks extends Ticks { class LinearTicks extends Ticks {
public $minor_step=1, $major_step=2; public $minor_step=1, $major_step=2;
public $xlabel_offset=0,$xtick_offset=0; public $xlabel_offset=0,$xtick_offset=0;
private $label_offset=0; // What offset should the displayed label have 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 // i.e should we display 0,1,2 or 1,2,3,4 or 2,3,4 etc
private $text_label_start=0; private $text_label_start=0;
private $iManualTickPos = NULL, $iManualMinTickPos = NULL, $iManualTickLabels = NULL; 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 private $iAdjustForDST = false; // If a date falls within the DST period add one hour to the diaplyed time
   
function __construct() { function __construct() {
$this->precision = -1; $this->precision = -1;
} }
   
// Return major step size in world coordinates // Return major step size in world coordinates
function GetMajor() { function GetMajor() {
return $this->major_step; return $this->major_step;
} }
   
// Return minor step size in world coordinates // Return minor step size in world coordinates
function GetMinor() { function GetMinor() {
return $this->minor_step; return $this->minor_step;
} }
   
// Set Minor and Major ticks (in world coordinates) // Set Minor and Major ticks (in world coordinates)
function Set($aMajStep,$aMinStep=false) { function Set($aMajStep,$aMinStep=false) {
if( $aMinStep==false ) { if( $aMinStep==false ) {
$aMinStep=$aMajStep; $aMinStep=$aMajStep;
} }
   
if( $aMajStep <= 0 || $aMinStep <= 0 ) { if( $aMajStep <= 0 || $aMinStep <= 0 ) {
JpGraphError::RaiseL(25064); 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."); //(" 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->major_step=$aMajStep;
$this->minor_step=$aMinStep; $this->minor_step=$aMinStep;
$this->is_set = true; $this->is_set = true;
} }
   
function SetMajTickPositions($aMajPos,$aLabels=NULL) { function SetMajTickPositions($aMajPos,$aLabels=NULL) {
$this->SetTickPositions($aMajPos,NULL,$aLabels); $this->SetTickPositions($aMajPos,NULL,$aLabels);
} }
   
function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) { function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) {
if( !is_array($aMajPos) || ($aMinPos!==NULL && !is_array($aMinPos)) ) { if( !is_array($aMajPos) || ($aMinPos!==NULL && !is_array($aMinPos)) ) {
JpGraphError::RaiseL(25065);//('Tick positions must be specifued as an array()'); JpGraphError::RaiseL(25065);//('Tick positions must be specifued as an array()');
return; return;
} }
$n=count($aMajPos); $n=count($aMajPos);
if( is_array($aLabels) && (count($aLabels) != $n) ) { 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.'); 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->iManualTickPos = $aMajPos;
$this->iManualMinTickPos = $aMinPos; $this->iManualMinTickPos = $aMinPos;
$this->iManualTickLabels = $aLabels; $this->iManualTickLabels = $aLabels;
} }
   
function HaveManualLabels() { function HaveManualLabels() {
return count($this->iManualTickLabels) > 0; return count($this->iManualTickLabels) > 0;
} }
   
// Specify all the tick positions manually and possible also the exact labels // Specify all the tick positions manually and possible also the exact labels
function _doManualTickPos($aScale) { function _doManualTickPos($aScale) {
$n=count($this->iManualTickPos); $n=count($this->iManualTickPos);
$m=count($this->iManualMinTickPos); $m=count($this->iManualMinTickPos);
$doLbl=count($this->iManualTickLabels) > 0; $doLbl=count($this->iManualTickLabels) > 0;
   
$this->maj_ticks_pos = array(); $this->maj_ticks_pos = array();
$this->maj_ticklabels_pos = array(); $this->maj_ticklabels_pos = array();
$this->ticks_pos = array(); $this->ticks_pos = array();
   
// Now loop through the supplied positions and translate them to screen coordinates // Now loop through the supplied positions and translate them to screen coordinates
// and store them in the maj_label_positions // and store them in the maj_label_positions
$minScale = $aScale->scale[0]; $minScale = $aScale->scale[0];
$maxScale = $aScale->scale[1]; $maxScale = $aScale->scale[1];
$j=0; $j=0;
for($i=0; $i < $n ; ++$i ) { for($i=0; $i < $n ; ++$i ) {
// First make sure that the first tick is not lower than the lower scale value // 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) { if( !isset($this->iManualTickPos[$i]) || $this->iManualTickPos[$i] < $minScale || $this->iManualTickPos[$i] > $maxScale) {
continue; continue;
} }
   
$this->maj_ticks_pos[$j] = $aScale->Translate($this->iManualTickPos[$i]); $this->maj_ticks_pos[$j] = $aScale->Translate($this->iManualTickPos[$i]);
$this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j]; $this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j];
   
// Set the minor tick marks the same as major if not specified // Set the minor tick marks the same as major if not specified
if( $m <= 0 ) { if( $m <= 0 ) {
$this->ticks_pos[$j] = $this->maj_ticks_pos[$j]; $this->ticks_pos[$j] = $this->maj_ticks_pos[$j];
} }
if( $doLbl ) { if( $doLbl ) {
$this->maj_ticks_label[$j] = $this->iManualTickLabels[$i]; $this->maj_ticks_label[$j] = $this->iManualTickLabels[$i];
} }
else { else {
$this->maj_ticks_label[$j]=$this->_doLabelFormat($this->iManualTickPos[$i],$i,$n); $this->maj_ticks_label[$j]=$this->_doLabelFormat($this->iManualTickPos[$i],$i,$n);
} }
++$j; ++$j;
} }
   
// Some sanity check // Some sanity check
if( count($this->maj_ticks_pos) < 2 ) { 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.'); 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 // Setup the minor tick marks
$j=0; $j=0;
for($i=0; $i < $m; ++$i ) { for($i=0; $i < $m; ++$i ) {
if( empty($this->iManualMinTickPos[$i]) || $this->iManualMinTickPos[$i] < $minScale || $this->iManualMinTickPos[$i] > $maxScale) { if( empty($this->iManualMinTickPos[$i]) || $this->iManualMinTickPos[$i] < $minScale || $this->iManualMinTickPos[$i] > $maxScale) {
continue; continue;
} }
$this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]); $this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]);
++$j; ++$j;
} }
} }
   
function _doAutoTickPos($aScale) { function _doAutoTickPos($aScale) {
$maj_step_abs = $aScale->scale_factor*$this->major_step; $maj_step_abs = $aScale->scale_factor*$this->major_step;
$min_step_abs = $aScale->scale_factor*$this->minor_step; $min_step_abs = $aScale->scale_factor*$this->minor_step;
   
if( $min_step_abs==0 || $maj_step_abs==0 ) { 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')"); 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 // We need to make this an int since comparing it below
// with the result from round() can give wrong result, such that // with the result from round() can give wrong result, such that
// (40 < 40) == TRUE !!! // (40 < 40) == TRUE !!!
$limit = (int)$aScale->scale_abs[1]; $limit = (int)$aScale->scale_abs[1];
   
if( $aScale->textscale ) { if( $aScale->textscale ) {
// This can only be true for a X-scale (horizontal) // This can only be true for a X-scale (horizontal)
// Define ticks for a text scale. This is slightly different from a // Define ticks for a text scale. This is slightly different from a
// normal linear type of scale since the position might be adjusted // normal linear type of scale since the position might be adjusted
// and the labels start at on // and the labels start at on
$label = (float)$aScale->GetMinVal()+$this->text_label_start+$this->label_offset; $label = (float)$aScale->GetMinVal()+$this->text_label_start+$this->label_offset;
$start_abs=$aScale->scale_factor*$this->text_label_start; $start_abs=$aScale->scale_factor*$this->text_label_start;
$nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; $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; $x = $aScale->scale_abs[0]+$start_abs+$this->xlabel_offset*$min_step_abs;
for( $i=0; $label <= $aScale->GetMaxVal()+$this->label_offset; ++$i ) { for( $i=0; $label <= $aScale->GetMaxVal()+$this->label_offset; ++$i ) {
// Apply format to label // Apply format to label
$this->maj_ticks_label[$i]=$this->_doLabelFormat($label,$i,$nbrmajticks); $this->maj_ticks_label[$i]=$this->_doLabelFormat($label,$i,$nbrmajticks);
$label+=$this->major_step; $label+=$this->major_step;
   
// The x-position of the tick marks can be different from the labels. // 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 // Note that we record the tick position (not the label) so that the grid
// happen upon tick marks and not labels. // happen upon tick marks and not labels.
$xtick=$aScale->scale_abs[0]+$start_abs+$this->xtick_offset*$min_step_abs+$i*$maj_step_abs; $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_ticks_pos[$i]=$xtick;
$this->maj_ticklabels_pos[$i] = round($x); $this->maj_ticklabels_pos[$i] = round($x);
$x += $maj_step_abs; $x += $maj_step_abs;
} }
} }
else { else {
$label = $aScale->GetMinVal(); $label = $aScale->GetMinVal();
$abs_pos = $aScale->scale_abs[0]; $abs_pos = $aScale->scale_abs[0];
$j=0; $i=0; $j=0; $i=0;
$step = round($maj_step_abs/$min_step_abs); $step = round($maj_step_abs/$min_step_abs);
if( $aScale->type == "x" ) { if( $aScale->type == "x" ) {
// For a normal linear type of scale the major ticks will always be multiples // 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 // 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 // defined as every "step" minor ticks and not calculated separately
$nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1; $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
while( round($abs_pos) <= $limit ) { while( round($abs_pos) <= $limit ) {
$this->ticks_pos[] = round($abs_pos); $this->ticks_pos[] = round($abs_pos);
$this->ticks_label[] = $label; $this->ticks_label[] = $label;
if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks ) { if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks ) {
$this->maj_ticks_pos[$j] = round($abs_pos); $this->maj_ticks_pos[$j] = round($abs_pos);
$this->maj_ticklabels_pos[$j] = round($abs_pos); $this->maj_ticklabels_pos[$j] = round($abs_pos);
$this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks); $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks);
++$j; ++$j;
} }
++$i; ++$i;
$abs_pos += $min_step_abs; $abs_pos += $min_step_abs;
$label+=$this->minor_step; $label+=$this->minor_step;
} }
} }
elseif( $aScale->type == "y" ) { elseif( $aScale->type == "y" ) {
$nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal())/$this->major_step)+1; $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal())/$this->major_step)+1;
while( round($abs_pos) >= $limit ) { while( round($abs_pos) >= $limit ) {
$this->ticks_pos[$i] = round($abs_pos); $this->ticks_pos[$i] = round($abs_pos);
$this->ticks_label[$i]=$label; $this->ticks_label[$i]=$label;
if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks) { if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks) {
$this->maj_ticks_pos[$j] = round($abs_pos); $this->maj_ticks_pos[$j] = round($abs_pos);
$this->maj_ticklabels_pos[$j] = round($abs_pos); $this->maj_ticklabels_pos[$j] = round($abs_pos);
$this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks); $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks);
++$j; ++$j;
} }
++$i; ++$i;
$abs_pos += $min_step_abs; $abs_pos += $min_step_abs;
$label += $this->minor_step; $label += $this->minor_step;
} }
} }
} }
} }
   
function AdjustForDST($aFlg=true) { function AdjustForDST($aFlg=true) {
$this->iAdjustForDST = $aFlg; $this->iAdjustForDST = $aFlg;
} }
   
   
function _doLabelFormat($aVal,$aIdx,$aNbrTicks) { function _doLabelFormat($aVal,$aIdx,$aNbrTicks) {
   
// If precision hasn't been specified set it to a sensible value // If precision hasn't been specified set it to a sensible value
if( $this->precision==-1 ) { if( $this->precision==-1 ) {
$t = log10($this->minor_step); $t = log10($this->minor_step);
if( $t > 0 ) { if( $t > 0 ) {
$precision = 0; $precision = 0;
} }
else { else {
$precision = -floor($t); $precision = -floor($t);
} }
} }
else { else {
$precision = $this->precision; $precision = $this->precision;
} }
   
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f=$this->label_formfunc; $f=$this->label_formfunc;
if( $this->label_formatstr == '' ) { if( $this->label_formatstr == '' ) {
$l = call_user_func($f,$aVal); $l = call_user_func($f,$aVal);
} }
else { else {
$l = sprintf($this->label_formatstr, call_user_func($f,$aVal)); $l = sprintf($this->label_formatstr, call_user_func($f,$aVal));
} }
} }
elseif( $this->label_formatstr != '' || $this->label_dateformatstr != '' ) { elseif( $this->label_formatstr != '' || $this->label_dateformatstr != '' ) {
if( $this->label_usedateformat ) { if( $this->label_usedateformat ) {
// Adjust the value to take daylight savings into account // Adjust the value to take daylight savings into account
if (date("I",$aVal)==1 && $this->iAdjustForDST ) { if (date("I",$aVal)==1 && $this->iAdjustForDST ) {
// DST // DST
$aVal+=3600; $aVal+=3600;
} }
   
$l = date($this->label_formatstr,$aVal); $l = date($this->label_formatstr,$aVal);
if( $this->label_formatstr == 'W' ) { if( $this->label_formatstr == 'W' ) {
// If we use week formatting then add a single 'w' in front of the // If we use week formatting then add a single 'w' in front of the
// week number to differentiate it from dates // week number to differentiate it from dates
$l = 'w'.$l; $l = 'w'.$l;
} }
} }
else { else {
if( $this->label_dateformatstr !== '' ) { if( $this->label_dateformatstr !== '' ) {
// Adjust the value to take daylight savings into account // Adjust the value to take daylight savings into account
if (date("I",$aVal)==1 && $this->iAdjustForDST ) { if (date("I",$aVal)==1 && $this->iAdjustForDST ) {
// DST // DST
$aVal+=3600; $aVal+=3600;
} }
   
$l = date($this->label_dateformatstr,$aVal); $l = date($this->label_dateformatstr,$aVal);
if( $this->label_formatstr == 'W' ) { if( $this->label_formatstr == 'W' ) {
// If we use week formatting then add a single 'w' in front of the // If we use week formatting then add a single 'w' in front of the
// week number to differentiate it from dates // week number to differentiate it from dates
$l = 'w'.$l; $l = 'w'.$l;
} }
} }
else { else {
$l = sprintf($this->label_formatstr,$aVal); $l = sprintf($this->label_formatstr,$aVal);
} }
} }
} }
else { else {
$l = sprintf('%01.'.$precision.'f',round($aVal,$precision)); $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) ) { if( ($this->supress_zerolabel && $l==0) || ($this->supress_first && $aIdx==0) || ($this->supress_last && $aIdx==$aNbrTicks-1) ) {
$l=''; $l='';
} }
return $l; return $l;
} }
   
// Stroke ticks on either X or Y axis // Stroke ticks on either X or Y axis
function _StrokeTicks($aImg,$aScale,$aPos) { function _StrokeTicks($aImg,$aScale,$aPos) {
$hor = $aScale->type == 'x'; $hor = $aScale->type == 'x';
$aImg->SetLineWeight($this->weight); $aImg->SetLineWeight($this->weight);
   
// We need to make this an int since comparing it below // We need to make this an int since comparing it below
// with the result from round() can give wrong result, such that // with the result from round() can give wrong result, such that
// (40 < 40) == TRUE !!! // (40 < 40) == TRUE !!!
$limit = (int)$aScale->scale_abs[1]; $limit = (int)$aScale->scale_abs[1];
   
// A text scale doesn't have any minor ticks // A text scale doesn't have any minor ticks
if( !$aScale->textscale ) { if( !$aScale->textscale ) {
// Stroke minor ticks // Stroke minor ticks
$yu = $aPos - $this->direction*$this->GetMinTickAbsSize(); $yu = $aPos - $this->direction*$this->GetMinTickAbsSize();
$xr = $aPos + $this->direction*$this->GetMinTickAbsSize(); $xr = $aPos + $this->direction*$this->GetMinTickAbsSize();
$n = count($this->ticks_pos); $n = count($this->ticks_pos);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
if( $this->mincolor != '') { if( $this->mincolor != '') {
$aImg->PushColor($this->mincolor); $aImg->PushColor($this->mincolor);
} }
if( $hor ) { if( $hor ) {
//if( $this->ticks_pos[$i] <= $limit ) //if( $this->ticks_pos[$i] <= $limit )
$aImg->Line($this->ticks_pos[$i],$aPos,$this->ticks_pos[$i],$yu); $aImg->Line($this->ticks_pos[$i],$aPos,$this->ticks_pos[$i],$yu);
} }
else { else {
//if( $this->ticks_pos[$i] >= $limit ) //if( $this->ticks_pos[$i] >= $limit )
$aImg->Line($aPos,$this->ticks_pos[$i],$xr,$this->ticks_pos[$i]); $aImg->Line($aPos,$this->ticks_pos[$i],$xr,$this->ticks_pos[$i]);
} }
if( $this->mincolor != '' ) { if( $this->mincolor != '' ) {
$aImg->PopColor(); $aImg->PopColor();
} }
} }
} }
} }
   
// Stroke major ticks // Stroke major ticks
$yu = $aPos - $this->direction*$this->GetMajTickAbsSize(); $yu = $aPos - $this->direction*$this->GetMajTickAbsSize();
$xr = $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; $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
$n = count($this->maj_ticks_pos); $n = count($this->maj_ticks_pos);
for($i=0; $i < $n ; ++$i ) { for($i=0; $i < $n ; ++$i ) {
if(!($this->xtick_offset > 0 && $i==$nbrmajticks-1) && !$this->supress_tickmarks) { if(!($this->xtick_offset > 0 && $i==$nbrmajticks-1) && !$this->supress_tickmarks) {
if( $this->majcolor != '') { if( $this->majcolor != '') {
$aImg->PushColor($this->majcolor); $aImg->PushColor($this->majcolor);
} }
if( $hor ) { if( $hor ) {
//if( $this->maj_ticks_pos[$i] <= $limit ) //if( $this->maj_ticks_pos[$i] <= $limit )
$aImg->Line($this->maj_ticks_pos[$i],$aPos,$this->maj_ticks_pos[$i],$yu); $aImg->Line($this->maj_ticks_pos[$i],$aPos,$this->maj_ticks_pos[$i],$yu);
} }
else { else {
//if( $this->maj_ticks_pos[$i] >= $limit ) //if( $this->maj_ticks_pos[$i] >= $limit )
$aImg->Line($aPos,$this->maj_ticks_pos[$i],$xr,$this->maj_ticks_pos[$i]); $aImg->Line($aPos,$this->maj_ticks_pos[$i],$xr,$this->maj_ticks_pos[$i]);
} }
if( $this->majcolor != '') { if( $this->majcolor != '') {
$aImg->PopColor(); $aImg->PopColor();
} }
} }
} }
   
} }
   
// Draw linear ticks // Draw linear ticks
function Stroke($aImg,$aScale,$aPos) { function Stroke($aImg,$aScale,$aPos) {
if( $this->iManualTickPos != NULL ) { if( $this->iManualTickPos != NULL ) {
$this->_doManualTickPos($aScale); $this->_doManualTickPos($aScale);
} }
else { else {
$this->_doAutoTickPos($aScale); $this->_doAutoTickPos($aScale);
} }
$this->_StrokeTicks($aImg,$aScale,$aPos, $aScale->type == 'x' ); $this->_StrokeTicks($aImg,$aScale,$aPos, $aScale->type == 'x' );
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
// Spoecify the offset of the displayed tick mark with the tick "space" // 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 // Legal values for $o is [0,1] used to adjust where the tick marks and label
// should be positioned within the major tick-size // should be positioned within the major tick-size
// $lo specifies the label offset and $to specifies the tick offset // $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 // 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. // tick but have the labels displayed halfway under the bars.
function SetXLabelOffset($aLabelOff,$aTickOff=-1) { function SetXLabelOffset($aLabelOff,$aTickOff=-1) {
$this->xlabel_offset=$aLabelOff; $this->xlabel_offset=$aLabelOff;
if( $aTickOff==-1 ) { if( $aTickOff==-1 ) {
// Same as label offset // Same as label offset
$this->xtick_offset=$aLabelOff; $this->xtick_offset=$aLabelOff;
} }
else { else {
$this->xtick_offset=$aTickOff; $this->xtick_offset=$aTickOff;
} }
if( $aLabelOff>0 ) { if( $aLabelOff>0 ) {
$this->SupressLast(); // The last tick wont fit $this->SupressLast(); // The last tick wont fit
} }
} }
   
// Which tick label should we start with? // Which tick label should we start with?
function SetTextLabelStart($aTextLabelOff) { function SetTextLabelStart($aTextLabelOff) {
$this->text_label_start=$aTextLabelOff; $this->text_label_start=$aTextLabelOff;
} }
   
} // Class } // Class
   
//=================================================== //===================================================
// CLASS LinearScale // CLASS LinearScale
// Description: Handle linear scaling between screen and world // Description: Handle linear scaling between screen and world
//=================================================== //===================================================
class LinearScale { class LinearScale {
public $textscale=false; // Just a flag to let the Plot class find out if 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 // we are a textscale or not. This is a cludge since
// this information is available in Graph::axtype but // this information is available in Graph::axtype but
// we don't have access to the graph object in the Plots // we don't have access to the graph object in the Plots
// stroke method. So we let graph store the status here // stroke method. So we let graph store the status here
// when the linear scale is created. A real cludge... // when the linear scale is created. A real cludge...
public $type; // is this x or y scale ? public $type; // is this x or y scale ?
public $ticks=null; // Store ticks public $ticks=null; // Store ticks
public $text_scale_off = 0; public $text_scale_off = 0;
public $scale_abs=array(0,0); public $scale_abs=array(0,0);
public $scale_factor; // Scale factor between world and screen public $scale_factor; // Scale factor between world and screen
public $off; // Offset between image edge and plot area public $off; // Offset between image edge and plot area
public $scale=array(0,0); public $scale=array(0,0);
public $name = 'lin'; public $name = 'lin';
public $auto_ticks=false; // When using manual scale should the ticks be automatically set? 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 $world_abs_size; // Plot area size in pixels (Needed public in jpgraph_radar.php)
public $world_size; // Plot area size in world coordinates public $world_size; // Plot area size in world coordinates
public $intscale=false; // Restrict autoscale to integers public $intscale=false; // Restrict autoscale to integers
protected $autoscale_min=false; // Forced minimum value, auto determine max protected $autoscale_min=false; // Forced minimum value, auto determine max
protected $autoscale_max=false; // Forced maximum value, auto determine min protected $autoscale_max=false; // Forced maximum value, auto determine min
private $gracetop=0,$gracebottom=0; private $gracetop=0,$gracebottom=0;
   
function __construct($aMin=0,$aMax=0,$aType='y') { function __construct($aMin=0,$aMax=0,$aType='y') {
assert($aType=='x' || $aType=='y' ); assert($aType=='x' || $aType=='y' );
assert($aMin<=$aMax); assert($aMin<=$aMax);
   
$this->type=$aType; $this->type=$aType;
$this->scale=array($aMin,$aMax); $this->scale=array($aMin,$aMax);
$this->world_size=$aMax-$aMin; $this->world_size=$aMax-$aMin;
$this->ticks = new LinearTicks(); $this->ticks = new LinearTicks();
} }
   
// Check if scale is set or if we should autoscale // Check if scale is set or if we should autoscale
// We should do this is either scale or ticks has not been set // We should do this is either scale or ticks has not been set
function IsSpecified() { function IsSpecified() {
if( $this->GetMinVal()==$this->GetMaxVal() ) { // Scale not set if( $this->GetMinVal()==$this->GetMaxVal() ) { // Scale not set
return false; return false;
} }
return true; return true;
} }
   
// Set the minimum data value when the autoscaling is used. // Set the minimum data value when the autoscaling is used.
// Usefull if you want a fix minimum (like 0) but have an // Usefull if you want a fix minimum (like 0) but have an
// automatic maximum // automatic maximum
function SetAutoMin($aMin) { function SetAutoMin($aMin) {
$this->autoscale_min=$aMin; $this->autoscale_min=$aMin;
} }
   
// Set the minimum data value when the autoscaling is used. // Set the minimum data value when the autoscaling is used.
// Usefull if you want a fix minimum (like 0) but have an // Usefull if you want a fix minimum (like 0) but have an
// automatic maximum // automatic maximum
function SetAutoMax($aMax) { function SetAutoMax($aMax) {
$this->autoscale_max=$aMax; $this->autoscale_max=$aMax;
} }
   
// If the user manually specifies a scale should the ticks // If the user manually specifies a scale should the ticks
// still be set automatically? // still be set automatically?
function SetAutoTicks($aFlag=true) { function SetAutoTicks($aFlag=true) {
$this->auto_ticks = $aFlag; $this->auto_ticks = $aFlag;
} }
   
// Specify scale "grace" value (top and bottom) // Specify scale "grace" value (top and bottom)
function SetGrace($aGraceTop,$aGraceBottom=0) { function SetGrace($aGraceTop,$aGraceBottom=0) {
if( $aGraceTop<0 || $aGraceBottom < 0 ) { if( $aGraceTop<0 || $aGraceBottom < 0 ) {
JpGraphError::RaiseL(25069);//(" Grace must be larger then 0"); JpGraphError::RaiseL(25069);//(" Grace must be larger then 0");
} }
$this->gracetop=$aGraceTop; $this->gracetop=$aGraceTop;
$this->gracebottom=$aGraceBottom; $this->gracebottom=$aGraceBottom;
} }
   
// Get the minimum value in the scale // Get the minimum value in the scale
function GetMinVal() { function GetMinVal() {
return $this->scale[0]; return $this->scale[0];
} }
   
// get maximum value for scale // get maximum value for scale
function GetMaxVal() { function GetMaxVal() {
return $this->scale[1]; return $this->scale[1];
} }
   
// Specify a new min/max value for sclae // Specify a new min/max value for sclae
function Update($aImg,$aMin,$aMax) { function Update($aImg,$aMin,$aMax) {
$this->scale=array($aMin,$aMax); $this->scale=array($aMin,$aMax);
$this->world_size=$aMax-$aMin; $this->world_size=$aMax-$aMin;
$this->InitConstants($aImg); $this->InitConstants($aImg);
} }
   
// Translate between world and screen // Translate between world and screen
function Translate($aCoord) { function Translate($aCoord) {
if( !is_numeric($aCoord) ) { if( !is_numeric($aCoord) ) {
if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) { if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) {
JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.'); JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.');
} }
return 0; return 0;
} }
else { else {
return round($this->off+($aCoord - $this->scale[0]) * $this->scale_factor); return round($this->off+($aCoord - $this->scale[0]) * $this->scale_factor);
} }
} }
   
// Relative translate (don't include offset) usefull when we just want // Relative translate (don't include offset) usefull when we just want
// to know the relative position (in pixels) on the axis // to know the relative position (in pixels) on the axis
function RelTranslate($aCoord) { function RelTranslate($aCoord) {
if( !is_numeric($aCoord) ) { if( !is_numeric($aCoord) ) {
if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) { if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) {
JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.'); JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.');
} }
return 0; return 0;
} }
else { else {
return ($aCoord - $this->scale[0]) * $this->scale_factor; return ($aCoord - $this->scale[0]) * $this->scale_factor;
} }
} }
   
// Restrict autoscaling to only use integers // Restrict autoscaling to only use integers
function SetIntScale($aIntScale=true) { function SetIntScale($aIntScale=true) {
$this->intscale=$aIntScale; $this->intscale=$aIntScale;
} }
   
// Calculate an integer autoscale // Calculate an integer autoscale
function IntAutoScale($img,$min,$max,$maxsteps,$majend=true) { function IntAutoScale($img,$min,$max,$maxsteps,$majend=true) {
// Make sure limits are integers // Make sure limits are integers
$min=floor($min); $min=floor($min);
$max=ceil($max); $max=ceil($max);
if( abs($min-$max)==0 ) { if( abs($min-$max)==0 ) {
--$min; ++$max; --$min; ++$max;
} }
$maxsteps = floor($maxsteps); $maxsteps = floor($maxsteps);
   
$gracetop=round(($this->gracetop/100.0)*abs($max-$min)); $gracetop=round(($this->gracetop/100.0)*abs($max-$min));
$gracebottom=round(($this->gracebottom/100.0)*abs($max-$min)); $gracebottom=round(($this->gracebottom/100.0)*abs($max-$min));
if( is_numeric($this->autoscale_min) ) { if( is_numeric($this->autoscale_min) ) {
$min = ceil($this->autoscale_min); $min = ceil($this->autoscale_min);
if( $min >= $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.'); 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) ) { if( is_numeric($this->autoscale_max) ) {
$max = ceil($this->autoscale_max); $max = ceil($this->autoscale_max);
if( $min >= $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.'); 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 ) { if( abs($min-$max ) == 0 ) {
++$max; ++$max;
--$min; --$min;
} }
   
$min -= $gracebottom; $min -= $gracebottom;
$max += $gracetop; $max += $gracetop;
   
// First get tickmarks as multiples of 1, 10, ... // First get tickmarks as multiples of 1, 10, ...
if( $majend ) { if( $majend ) {
list($num1steps,$adj1min,$adj1max,$maj1step) = $this->IntCalcTicks($maxsteps,$min,$max,1); list($num1steps,$adj1min,$adj1max,$maj1step) = $this->IntCalcTicks($maxsteps,$min,$max,1);
} }
else { else {
$adj1min = $min; $adj1min = $min;
$adj1max = $max; $adj1max = $max;
list($num1steps,$maj1step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,1); list($num1steps,$maj1step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,1);
} }
   
if( abs($min-$max) > 2 ) { if( abs($min-$max) > 2 ) {
// Then get tick marks as 2:s 2, 20, ... // Then get tick marks as 2:s 2, 20, ...
if( $majend ) { if( $majend ) {
list($num2steps,$adj2min,$adj2max,$maj2step) = $this->IntCalcTicks($maxsteps,$min,$max,5); list($num2steps,$adj2min,$adj2max,$maj2step) = $this->IntCalcTicks($maxsteps,$min,$max,5);
} }
else { else {
$adj2min = $min; $adj2min = $min;
$adj2max = $max; $adj2max = $max;
list($num2steps,$maj2step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,5); list($num2steps,$maj2step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,5);
} }
} }
else { else {
$num2steps = 10000; // Dummy high value so we don't choose this $num2steps = 10000; // Dummy high value so we don't choose this
} }
   
if( abs($min-$max) > 5 ) { if( abs($min-$max) > 5 ) {
// Then get tickmarks as 5:s 5, 50, 500, ... // Then get tickmarks as 5:s 5, 50, 500, ...
if( $majend ) { if( $majend ) {
list($num5steps,$adj5min,$adj5max,$maj5step) = $this->IntCalcTicks($maxsteps,$min,$max,2); list($num5steps,$adj5min,$adj5max,$maj5step) = $this->IntCalcTicks($maxsteps,$min,$max,2);
} }
else { else {
$adj5min = $min; $adj5min = $min;
$adj5max = $max; $adj5max = $max;
list($num5steps,$maj5step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,2); list($num5steps,$maj5step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,2);
} }
} }
else { else {
$num5steps = 10000; // Dummy high value so we don't choose this $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 // Check to see whichof 1:s, 2:s or 5:s fit better with
// the requested number of major ticks // the requested number of major ticks
$match1=abs($num1steps-$maxsteps); $match1=abs($num1steps-$maxsteps);
$match2=abs($num2steps-$maxsteps); $match2=abs($num2steps-$maxsteps);
if( !empty($maj5step) && $maj5step > 1 ) { if( !empty($maj5step) && $maj5step > 1 ) {
$match5=abs($num5steps-$maxsteps); $match5=abs($num5steps-$maxsteps);
} }
else { else {
$match5=10000; // Dummy high value $match5=10000; // Dummy high value
} }
   
// Compare these three values and see which is the closest match // Compare these three values and see which is the closest match
// We use a 0.6 weight to gravitate towards multiple of 5:s // We use a 0.6 weight to gravitate towards multiple of 5:s
if( $match1 < $match2 ) { if( $match1 < $match2 ) {
if( $match1 < $match5 ) $r=1; if( $match1 < $match5 ) $r=1;
else $r=3; else $r=3;
} }
else { else {
if( $match2 < $match5 ) $r=2; if( $match2 < $match5 ) $r=2;
else $r=3; else $r=3;
} }
// Minsteps are always the same as maxsteps for integer scale // Minsteps are always the same as maxsteps for integer scale
switch( $r ) { switch( $r ) {
case 1: case 1:
$this->ticks->Set($maj1step,$maj1step); $this->ticks->Set($maj1step,$maj1step);
$this->Update($img,$adj1min,$adj1max); $this->Update($img,$adj1min,$adj1max);
break; break;
case 2: case 2:
$this->ticks->Set($maj2step,$maj2step); $this->ticks->Set($maj2step,$maj2step);
$this->Update($img,$adj2min,$adj2max); $this->Update($img,$adj2min,$adj2max);
break; break;
case 3: case 3:
$this->ticks->Set($maj5step,$maj5step); $this->ticks->Set($maj5step,$maj5step);
$this->Update($img,$adj5min,$adj5max); $this->Update($img,$adj5min,$adj5max);
break; break;
default: default:
JpGraphError::RaiseL(25073,$r);//('Internal error. Integer scale algorithm comparison out of bound (r=$r)'); 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 // Calculate autoscale. Used if user hasn't given a scale and ticks
// $maxsteps is the maximum number of major tickmarks allowed. // $maxsteps is the maximum number of major tickmarks allowed.
function AutoScale($img,$min,$max,$maxsteps,$majend=true) { function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
   
if( !is_numeric($min) || !is_numeric($max) ) { if( !is_numeric($min) || !is_numeric($max) ) {
JpGraphError::Raise(25044); JpGraphError::Raise(25044);
} }
   
if( $this->intscale ) { if( $this->intscale ) {
$this->IntAutoScale($img,$min,$max,$maxsteps,$majend); $this->IntAutoScale($img,$min,$max,$maxsteps,$majend);
return; return;
} }
if( abs($min-$max) < 0.00001 ) { if( abs($min-$max) < 0.00001 ) {
// We need some difference to be able to autoscale // We need some difference to be able to autoscale
// make it 5% above and 5% below value // make it 5% above and 5% below value
if( $min==0 && $max==0 ) { // Special case if( $min==0 && $max==0 ) { // Special case
$min=-1; $max=1; $min=-1; $max=1;
} }
else { else {
$delta = (abs($max)+abs($min))*0.005; $delta = (abs($max)+abs($min))*0.005;
$min -= $delta; $min -= $delta;
$max += $delta; $max += $delta;
} }
} }
   
$gracetop=($this->gracetop/100.0)*abs($max-$min); $gracetop=($this->gracetop/100.0)*abs($max-$min);
$gracebottom=($this->gracebottom/100.0)*abs($max-$min); $gracebottom=($this->gracebottom/100.0)*abs($max-$min);
if( is_numeric($this->autoscale_min) ) { if( is_numeric($this->autoscale_min) ) {
$min = $this->autoscale_min; $min = $this->autoscale_min;
if( $min >= $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.'); 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 ) { if( abs($min-$max ) < 0.001 ) {
$max *= 1.2; $max *= 1.2;
} }
} }
   
if( is_numeric($this->autoscale_max) ) { if( is_numeric($this->autoscale_max) ) {
$max = $this->autoscale_max; $max = $this->autoscale_max;
if( $min >= $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.'); 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 ) { if( abs($min-$max ) < 0.001 ) {
$min *= 0.8; $min *= 0.8;
} }
} }
   
$min -= $gracebottom; $min -= $gracebottom;
$max += $gracetop; $max += $gracetop;
   
// First get tickmarks as multiples of 0.1, 1, 10, ... // First get tickmarks as multiples of 0.1, 1, 10, ...
if( $majend ) { if( $majend ) {
list($num1steps,$adj1min,$adj1max,$min1step,$maj1step) = $this->CalcTicks($maxsteps,$min,$max,1,2); list($num1steps,$adj1min,$adj1max,$min1step,$maj1step) = $this->CalcTicks($maxsteps,$min,$max,1,2);
} }
else { else {
$adj1min=$min; $adj1min=$min;
$adj1max=$max; $adj1max=$max;
list($num1steps,$min1step,$maj1step) = $this->CalcTicksFreeze($maxsteps,$min,$max,1,2,false); list($num1steps,$min1step,$maj1step) = $this->CalcTicksFreeze($maxsteps,$min,$max,1,2,false);
} }
   
// Then get tick marks as 2:s 0.2, 2, 20, ... // Then get tick marks as 2:s 0.2, 2, 20, ...
if( $majend ) { if( $majend ) {
list($num2steps,$adj2min,$adj2max,$min2step,$maj2step) = $this->CalcTicks($maxsteps,$min,$max,5,2); list($num2steps,$adj2min,$adj2max,$min2step,$maj2step) = $this->CalcTicks($maxsteps,$min,$max,5,2);
} }
else { else {
$adj2min=$min; $adj2min=$min;
$adj2max=$max; $adj2max=$max;
list($num2steps,$min2step,$maj2step) = $this->CalcTicksFreeze($maxsteps,$min,$max,5,2,false); list($num2steps,$min2step,$maj2step) = $this->CalcTicksFreeze($maxsteps,$min,$max,5,2,false);
} }
   
// Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ... // Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ...
if( $majend ) { if( $majend ) {
list($num5steps,$adj5min,$adj5max,$min5step,$maj5step) = $this->CalcTicks($maxsteps,$min,$max,2,5); list($num5steps,$adj5min,$adj5max,$min5step,$maj5step) = $this->CalcTicks($maxsteps,$min,$max,2,5);
} }
else { else {
$adj5min=$min; $adj5min=$min;
$adj5max=$max; $adj5max=$max;
list($num5steps,$min5step,$maj5step) = $this->CalcTicksFreeze($maxsteps,$min,$max,2,5,false); 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 // Check to see whichof 1:s, 2:s or 5:s fit better with
// the requested number of major ticks // the requested number of major ticks
$match1=abs($num1steps-$maxsteps); $match1=abs($num1steps-$maxsteps);
$match2=abs($num2steps-$maxsteps); $match2=abs($num2steps-$maxsteps);
$match5=abs($num5steps-$maxsteps); $match5=abs($num5steps-$maxsteps);
   
// Compare these three values and see which is the closest match // Compare these three values and see which is the closest match
// We use a 0.8 weight to gravitate towards multiple of 5:s // We use a 0.8 weight to gravitate towards multiple of 5:s
$r=$this->MatchMin3($match1,$match2,$match5,0.8); $r=$this->MatchMin3($match1,$match2,$match5,0.8);
switch( $r ) { switch( $r ) {
case 1: case 1:
$this->Update($img,$adj1min,$adj1max); $this->Update($img,$adj1min,$adj1max);
$this->ticks->Set($maj1step,$min1step); $this->ticks->Set($maj1step,$min1step);
break; break;
case 2: case 2:
$this->Update($img,$adj2min,$adj2max); $this->Update($img,$adj2min,$adj2max);
$this->ticks->Set($maj2step,$min2step); $this->ticks->Set($maj2step,$min2step);
break; break;
case 3: case 3:
$this->Update($img,$adj5min,$adj5max); $this->Update($img,$adj5min,$adj5max);
$this->ticks->Set($maj5step,$min5step); $this->ticks->Set($maj5step,$min5step);
break; break;
} }
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
   
// This method recalculates all constants that are depending on the // This method recalculates all constants that are depending on the
// margins in the image. If the margins in the image are changed // margins in the image. If the margins in the image are changed
// this method should be called for every scale that is registred with // this method should be called for every scale that is registred with
// that image. Should really be installed as an observer of that image. // that image. Should really be installed as an observer of that image.
function InitConstants($img) { function InitConstants($img) {
if( $this->type=='x' ) { if( $this->type=='x' ) {
$this->world_abs_size=$img->width - $img->left_margin - $img->right_margin; $this->world_abs_size=$img->width - $img->left_margin - $img->right_margin;
$this->off=$img->left_margin; $this->off=$img->left_margin;
$this->scale_factor = 0; $this->scale_factor = 0;
if( $this->world_size > 0 ) { if( $this->world_size > 0 ) {
$this->scale_factor=$this->world_abs_size/($this->world_size*1.0); $this->scale_factor=$this->world_abs_size/($this->world_size*1.0);
} }
} }
else { // y scale else { // y scale
$this->world_abs_size=$img->height - $img->top_margin - $img->bottom_margin; $this->world_abs_size=$img->height - $img->top_margin - $img->bottom_margin;
$this->off=$img->top_margin+$this->world_abs_size; $this->off=$img->top_margin+$this->world_abs_size;
$this->scale_factor = 0; $this->scale_factor = 0;
if( $this->world_size > 0 ) { if( $this->world_size > 0 ) {
$this->scale_factor=-$this->world_abs_size/($this->world_size*1.0); $this->scale_factor=-$this->world_abs_size/($this->world_size*1.0);
} }
} }
$size = $this->world_size * $this->scale_factor; $size = $this->world_size * $this->scale_factor;
$this->scale_abs=array($this->off,$this->off + $size); $this->scale_abs=array($this->off,$this->off + $size);
} }
   
// Initialize the conversion constants for this scale // Initialize the conversion constants for this scale
// This tries to pre-calculate as much as possible to speed up the // This tries to pre-calculate as much as possible to speed up the
// actual conversion (with Translate()) later on // actual conversion (with Translate()) later on
// $start =scale start in absolute pixels (for x-scale this is an y-position // $start =scale start in absolute pixels (for x-scale this is an y-position
// and for an y-scale this is an x-position // and for an y-scale this is an x-position
// $len =absolute length in pixels of scale // $len =absolute length in pixels of scale
function SetConstants($aStart,$aLen) { function SetConstants($aStart,$aLen) {
$this->world_abs_size=$aLen; $this->world_abs_size=$aLen;
$this->off=$aStart; $this->off=$aStart;
   
if( $this->world_size<=0 ) { if( $this->world_size<=0 ) {
// This should never ever happen !! // This should never ever happen !!
JpGraphError::RaiseL(25074); 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] <br> Please report Bug #01 to jpgraph@aditus.nu and include the script that gave this error. This problem could potentially be caused by trying to use \"illegal\" values in the input data arrays (like trying to send in strings or only NULL values) which causes the autoscaling to fail."); //("You have unfortunately stumbled upon a bug in JpGraph. It seems like the scale range is ".$this->world_size." [for ".$this->type." scale] <br> Please report Bug #01 to jpgraph@aditus.nu and include the script that gave this error. This problem could potentially be caused by trying to use \"illegal\" values in the input data arrays (like trying to send in strings or only NULL values) which causes the autoscaling to fail.");
} }
   
// scale_factor = number of pixels per world unit // scale_factor = number of pixels per world unit
$this->scale_factor=$this->world_abs_size/($this->world_size*1.0); $this->scale_factor=$this->world_abs_size/($this->world_size*1.0);
   
// scale_abs = start and end points of scale in absolute pixels // 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); $this->scale_abs=array($this->off,$this->off+$this->world_size*$this->scale_factor);
} }
   
   
// Calculate number of ticks steps with a specific division // Calculate number of ticks steps with a specific division
// $a is the divisor of 10**x to generate the first maj tick intervall // $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=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=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,... // $a=2, $b=5 give major ticks with multiple of 5:s ...,0.5,5,50,...
// We return a vector of // We return a vector of
// [$numsteps,$adjmin,$adjmax,$minstep,$majstep] // [$numsteps,$adjmin,$adjmax,$minstep,$majstep]
// If $majend==true then the first and last marks on the axis will be major // 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 // labeled tick marks otherwise it will be adjusted to the closest min tick mark
function CalcTicks($maxsteps,$min,$max,$a,$b,$majend=true) { function CalcTicks($maxsteps,$min,$max,$a,$b,$majend=true) {
$diff=$max-$min; $diff=$max-$min;
if( $diff==0 ) { if( $diff==0 ) {
$ld=0; $ld=0;
} }
else { else {
$ld=floor(log10($diff)); $ld=floor(log10($diff));
} }
   
// Gravitate min towards zero if we are close // Gravitate min towards zero if we are close
if( $min>0 && $min < pow(10,$ld) ) $min=0; if( $min>0 && $min < pow(10,$ld) ) $min=0;
   
//$majstep=pow(10,$ld-1)/$a; //$majstep=pow(10,$ld-1)/$a;
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
$minstep=$majstep/$b; $minstep=$majstep/$b;
   
$adjmax=ceil($max/$minstep)*$minstep; $adjmax=ceil($max/$minstep)*$minstep;
$adjmin=floor($min/$minstep)*$minstep; $adjmin=floor($min/$minstep)*$minstep;
$adjdiff = $adjmax-$adjmin; $adjdiff = $adjmax-$adjmin;
$numsteps=$adjdiff/$majstep; $numsteps=$adjdiff/$majstep;
   
while( $numsteps>$maxsteps ) { while( $numsteps>$maxsteps ) {
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
$numsteps=$adjdiff/$majstep; $numsteps=$adjdiff/$majstep;
++$ld; ++$ld;
} }
   
$minstep=$majstep/$b; $minstep=$majstep/$b;
$adjmin=floor($min/$minstep)*$minstep; $adjmin=floor($min/$minstep)*$minstep;
$adjdiff = $adjmax-$adjmin; $adjdiff = $adjmax-$adjmin;
if( $majend ) { if( $majend ) {
$adjmin = floor($min/$majstep)*$majstep; $adjmin = floor($min/$majstep)*$majstep;
$adjdiff = $adjmax-$adjmin; $adjdiff = $adjmax-$adjmin;
$adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin; $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin;
} }
else { else {
$adjmax=ceil($max/$minstep)*$minstep; $adjmax=ceil($max/$minstep)*$minstep;
} }
   
return array($numsteps,$adjmin,$adjmax,$minstep,$majstep); return array($numsteps,$adjmin,$adjmax,$minstep,$majstep);
} }
   
function CalcTicksFreeze($maxsteps,$min,$max,$a,$b) { function CalcTicksFreeze($maxsteps,$min,$max,$a,$b) {
// Same as CalcTicks but don't adjust min/max values // Same as CalcTicks but don't adjust min/max values
$diff=$max-$min; $diff=$max-$min;
if( $diff==0 ) { if( $diff==0 ) {
$ld=0; $ld=0;
} }
else { else {
$ld=floor(log10($diff)); $ld=floor(log10($diff));
} }
   
//$majstep=pow(10,$ld-1)/$a; //$majstep=pow(10,$ld-1)/$a;
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
$minstep=$majstep/$b; $minstep=$majstep/$b;
$numsteps=floor($diff/$majstep); $numsteps=floor($diff/$majstep);
   
while( $numsteps > $maxsteps ) { while( $numsteps > $maxsteps ) {
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
$numsteps=floor($diff/$majstep); $numsteps=floor($diff/$majstep);
++$ld; ++$ld;
} }
$minstep=$majstep/$b; $minstep=$majstep/$b;
return array($numsteps,$minstep,$majstep); return array($numsteps,$minstep,$majstep);
} }
   
   
function IntCalcTicks($maxsteps,$min,$max,$a,$majend=true) { function IntCalcTicks($maxsteps,$min,$max,$a,$majend=true) {
$diff=$max-$min; $diff=$max-$min;
if( $diff==0 ) { if( $diff==0 ) {
JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.'); JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.');
} }
else { else {
$ld=floor(log10($diff)); $ld=floor(log10($diff));
} }
   
// Gravitate min towards zero if we are close // Gravitate min towards zero if we are close
if( $min>0 && $min < pow(10,$ld) ) { if( $min>0 && $min < pow(10,$ld) ) {
$min=0; $min=0;
} }
if( $ld == 0 ) { if( $ld == 0 ) {
$ld=1; $ld=1;
} }
if( $a == 1 ) { if( $a == 1 ) {
$majstep = 1; $majstep = 1;
} }
else { else {
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
} }
$adjmax=ceil($max/$majstep)*$majstep; $adjmax=ceil($max/$majstep)*$majstep;
   
$adjmin=floor($min/$majstep)*$majstep; $adjmin=floor($min/$majstep)*$majstep;
$adjdiff = $adjmax-$adjmin; $adjdiff = $adjmax-$adjmin;
$numsteps=$adjdiff/$majstep; $numsteps=$adjdiff/$majstep;
while( $numsteps>$maxsteps ) { while( $numsteps>$maxsteps ) {
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
$numsteps=$adjdiff/$majstep; $numsteps=$adjdiff/$majstep;
++$ld; ++$ld;
} }
   
$adjmin=floor($min/$majstep)*$majstep; $adjmin=floor($min/$majstep)*$majstep;
$adjdiff = $adjmax-$adjmin; $adjdiff = $adjmax-$adjmin;
if( $majend ) { if( $majend ) {
$adjmin = floor($min/$majstep)*$majstep; $adjmin = floor($min/$majstep)*$majstep;
$adjdiff = $adjmax-$adjmin; $adjdiff = $adjmax-$adjmin;
$adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin; $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin;
} }
else { else {
$adjmax=ceil($max/$majstep)*$majstep; $adjmax=ceil($max/$majstep)*$majstep;
} }
   
return array($numsteps,$adjmin,$adjmax,$majstep); return array($numsteps,$adjmin,$adjmax,$majstep);
} }
   
   
function IntCalcTicksFreeze($maxsteps,$min,$max,$a) { function IntCalcTicksFreeze($maxsteps,$min,$max,$a) {
// Same as IntCalcTick but don't change min/max values // Same as IntCalcTick but don't change min/max values
$diff=$max-$min; $diff=$max-$min;
if( $diff==0 ) { if( $diff==0 ) {
JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.'); JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.');
} }
else { else {
$ld=floor(log10($diff)); $ld=floor(log10($diff));
} }
if( $ld == 0 ) { if( $ld == 0 ) {
$ld=1; $ld=1;
} }
if( $a == 1 ) { if( $a == 1 ) {
$majstep = 1; $majstep = 1;
} }
else { else {
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
} }
   
$numsteps=floor($diff/$majstep); $numsteps=floor($diff/$majstep);
while( $numsteps > $maxsteps ) { while( $numsteps > $maxsteps ) {
$majstep=pow(10,$ld)/$a; $majstep=pow(10,$ld)/$a;
$numsteps=floor($diff/$majstep); $numsteps=floor($diff/$majstep);
++$ld; ++$ld;
} }
   
return array($numsteps,$majstep); return array($numsteps,$majstep);
} }
   
// Determine the minimum of three values witha weight for last value // Determine the minimum of three values witha weight for last value
function MatchMin3($a,$b,$c,$weight) { function MatchMin3($a,$b,$c,$weight) {
if( $a < $b ) { if( $a < $b ) {
if( $a < ($c*$weight) ) { if( $a < ($c*$weight) ) {
return 1; // $a smallest return 1; // $a smallest
} }
else { else {
return 3; // $c smallest return 3; // $c smallest
} }
} }
elseif( $b < ($c*$weight) ) { elseif( $b < ($c*$weight) ) {
return 2; // $b smallest return 2; // $b smallest
} }
return 3; // $c smallest return 3; // $c smallest
} }
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS DisplayValue // CLASS DisplayValue
// Description: Used to print data values at data points // Description: Used to print data values at data points
//=================================================== //===================================================
class DisplayValue { class DisplayValue {
public $margin=5; public $margin=5;
public $show=false; public $show=false;
public $valign='',$halign='center'; public $valign='',$halign='center';
public $format='%.1f',$negformat=''; public $format='%.1f',$negformat='';
private $ff=FF_FONT1,$fs=FS_NORMAL,$fsize=10; private $ff=FF_FONT1,$fs=FS_NORMAL,$fsize=10;
private $iFormCallback=''; private $iFormCallback='';
private $angle=0; private $angle=0;
private $color='navy',$negcolor=''; private $color='navy',$negcolor='';
private $iHideZero=false; private $iHideZero=false;
public $txt=null; public $txt=null;
   
function __construct() { function __construct() {
$this->txt = new Text(); $this->txt = new Text();
} }
   
function Show($aFlag=true) { function Show($aFlag=true) {
$this->show=$aFlag; $this->show=$aFlag;
} }
   
function SetColor($aColor,$aNegcolor='') { function SetColor($aColor,$aNegcolor='') {
$this->color = $aColor; $this->color = $aColor;
$this->negcolor = $aNegcolor; $this->negcolor = $aNegcolor;
} }
   
function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) { function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) {
$this->ff=$aFontFamily; $this->ff=$aFontFamily;
$this->fs=$aFontStyle; $this->fs=$aFontStyle;
$this->fsize=$aFontSize; $this->fsize=$aFontSize;
} }
   
function ApplyFont($aImg) { function ApplyFont($aImg) {
$aImg->SetFont($this->ff,$this->fs,$this->fsize); $aImg->SetFont($this->ff,$this->fs,$this->fsize);
} }
   
function SetMargin($aMargin) { function SetMargin($aMargin) {
$this->margin = $aMargin; $this->margin = $aMargin;
} }
   
function SetAngle($aAngle) { function SetAngle($aAngle) {
$this->angle = $aAngle; $this->angle = $aAngle;
} }
   
function SetAlign($aHAlign,$aVAlign='') { function SetAlign($aHAlign,$aVAlign='') {
$this->halign = $aHAlign; $this->halign = $aHAlign;
$this->valign = $aVAlign; $this->valign = $aVAlign;
} }
   
function SetFormat($aFormat,$aNegFormat='') { function SetFormat($aFormat,$aNegFormat='') {
$this->format= $aFormat; $this->format= $aFormat;
$this->negformat= $aNegFormat; $this->negformat= $aNegFormat;
} }
   
function SetFormatCallback($aFunc) { function SetFormatCallback($aFunc) {
$this->iFormCallback = $aFunc; $this->iFormCallback = $aFunc;
} }
   
function HideZero($aFlag=true) { function HideZero($aFlag=true) {
$this->iHideZero=$aFlag; $this->iHideZero=$aFlag;
} }
   
function Stroke($img,$aVal,$x,$y) { function Stroke($img,$aVal,$x,$y) {
   
if( $this->show ) if( $this->show )
{ {
if( $this->negformat=='' ) { if( $this->negformat=='' ) {
$this->negformat=$this->format; $this->negformat=$this->format;
} }
if( $this->negcolor=='' ) { if( $this->negcolor=='' ) {
$this->negcolor=$this->color; $this->negcolor=$this->color;
} }
   
if( $aVal===NULL || (is_string($aVal) && ($aVal=='' || $aVal=='-' || $aVal=='x' ) ) ) { if( $aVal===NULL || (is_string($aVal) && ($aVal=='' || $aVal=='-' || $aVal=='x' ) ) ) {
return; return;
} }
   
if( is_numeric($aVal) && $aVal==0 && $this->iHideZero ) { if( is_numeric($aVal) && $aVal==0 && $this->iHideZero ) {
return; return;
} }
   
// Since the value is used in different cirumstances we need to check what // 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 // 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 // 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. // has already specified a text string we don't fo anything.
if( $this->iFormCallback != '' ) { if( $this->iFormCallback != '' ) {
$f = $this->iFormCallback; $f = $this->iFormCallback;
$sval = call_user_func($f,$aVal); $sval = call_user_func($f,$aVal);
} }
elseif( is_numeric($aVal) ) { elseif( is_numeric($aVal) ) {
if( $aVal >= 0 ) { if( $aVal >= 0 ) {
$sval=sprintf($this->format,$aVal); $sval=sprintf($this->format,$aVal);
} }
else { else {
$sval=sprintf($this->negformat,$aVal); $sval=sprintf($this->negformat,$aVal);
} }
} }
else { else {
$sval=$aVal; $sval=$aVal;
} }
   
$y = $y-sign($aVal)*$this->margin; $y = $y-sign($aVal)*$this->margin;
   
$this->txt->Set($sval); $this->txt->Set($sval);
$this->txt->SetPos($x,$y); $this->txt->SetPos($x,$y);
$this->txt->SetFont($this->ff,$this->fs,$this->fsize); $this->txt->SetFont($this->ff,$this->fs,$this->fsize);
if( $this->valign == '' ) { if( $this->valign == '' ) {
if( $aVal >= 0 ) { if( $aVal >= 0 ) {
$valign = "bottom"; $valign = "bottom";
} }
else { else {
$valign = "top"; $valign = "top";
} }
} }
else { else {
$valign = $this->valign; $valign = $this->valign;
} }
$this->txt->Align($this->halign,$valign); $this->txt->Align($this->halign,$valign);
   
$this->txt->SetOrientation($this->angle); $this->txt->SetOrientation($this->angle);
if( $aVal > 0 ) { if( $aVal > 0 ) {
$this->txt->SetColor($this->color); $this->txt->SetColor($this->color);
} }
else { else {
$this->txt->SetColor($this->negcolor); $this->txt->SetColor($this->negcolor);
} }
$this->txt->Stroke($img); $this->txt->Stroke($img);
} }
} }
} }
   
//=================================================== //===================================================
// CLASS Plot // CLASS Plot
// Description: Abstract base class for all concrete plot classes // Description: Abstract base class for all concrete plot classes
//=================================================== //===================================================
class Plot { class Plot {
public $numpoints=0; public $numpoints=0;
public $value; public $value;
public $legend=''; public $legend='';
public $coords=array(); public $coords=array();
public $color='black'; public $color='black';
public $hidelegend=false; public $hidelegend=false;
public $line_weight=1; public $line_weight=1;
public $csimtargets=array(),$csimwintargets=array(); // Array of targets for CSIM public $csimtargets=array(),$csimwintargets=array(); // Array of targets for CSIM
public $csimareas=''; // Resultant CSIM area tags public $csimareas=''; // Resultant CSIM area tags
public $csimalts=null; // ALT:s for corresponding target public $csimalts=null; // ALT:s for corresponding target
public $legendcsimtarget='',$legendcsimwintarget=''; public $legendcsimtarget='',$legendcsimwintarget='';
public $legendcsimalt=''; public $legendcsimalt='';
protected $weight=1; protected $weight=1;
protected $center=false; protected $center=false;
   
function __construct($aDatay,$aDatax=false) { function __construct($aDatay,$aDatax=false) {
$this->numpoints = count($aDatay); $this->numpoints = count($aDatay);
if( $this->numpoints==0 ) { if( $this->numpoints==0 ) {
JpGraphError::RaiseL(25121);//("Empty input data array specified for plot. Must have at least one data point."); JpGraphError::RaiseL(25121);//("Empty input data array specified for plot. Must have at least one data point.");
} }
$this->coords[0]=$aDatay; $this->coords[0]=$aDatay;
if( is_array($aDatax) ) { if( is_array($aDatax) ) {
$this->coords[1]=$aDatax; $this->coords[1]=$aDatax;
$n = count($aDatax); $n = count($aDatax);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( !is_numeric($aDatax[$i]) ) { if( !is_numeric($aDatax[$i]) ) {
JpGraphError::RaiseL(25070); JpGraphError::RaiseL(25070);
} }
} }
} }
$this->value = new DisplayValue(); $this->value = new DisplayValue();
} }
   
// Stroke the plot // Stroke the plot
// "virtual" function which must be implemented by // "virtual" function which must be implemented by
// the subclasses // the subclasses
function Stroke($aImg,$aXScale,$aYScale) { function Stroke($aImg,$aXScale,$aYScale) {
JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot"); JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot");
} }
   
function HideLegend($f=true) { function HideLegend($f=true) {
$this->hidelegend = $f; $this->hidelegend = $f;
} }
   
function DoLegend($graph) { function DoLegend($graph) {
if( !$this->hidelegend ) if( !$this->hidelegend )
$this->Legend($graph); $this->Legend($graph);
} }
   
function StrokeDataValue($img,$aVal,$x,$y) { function StrokeDataValue($img,$aVal,$x,$y) {
$this->value->Stroke($img,$aVal,$x,$y); $this->value->Stroke($img,$aVal,$x,$y);
} }
   
// Set href targets for CSIM // Set href targets for CSIM
function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') { function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
$this->csimtargets=$aTargets; $this->csimtargets=$aTargets;
$this->csimwintargets=$aWinTargets; $this->csimwintargets=$aWinTargets;
$this->csimalts=$aAlts; $this->csimalts=$aAlts;
} }
   
// Get all created areas // Get all created areas
function GetCSIMareas() { function GetCSIMareas() {
return $this->csimareas; return $this->csimareas;
} }
   
// "Virtual" function which gets called before any scale // "Virtual" function which gets called before any scale
// or axis are stroked used to do any plot specific adjustment // or axis are stroked used to do any plot specific adjustment
function PreStrokeAdjust($aGraph) { function PreStrokeAdjust($aGraph) {
if( substr($aGraph->axtype,0,4) == "text" && (isset($this->coords[1])) ) { 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."); 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; return true;
} }
   
// Virtual function to the the concrete plot class to make any changes to the graph // Virtual function to the the concrete plot class to make any changes to the graph
// and scale before the stroke process begins // and scale before the stroke process begins
function PreScaleSetup($aGraph) { function PreScaleSetup($aGraph) {
// Empty // Empty
} }
   
// Get minimum values in plot // Get minimum values in plot
function Min() { function Min() {
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
$x=$this->coords[1]; $x=$this->coords[1];
} }
else { else {
$x=''; $x='';
} }
if( $x != '' && count($x) > 0 ) { if( $x != '' && count($x) > 0 ) {
$xm=min($x); $xm=min($x);
} }
else { else {
$xm=0; $xm=0;
} }
$y=$this->coords[0]; $y=$this->coords[0];
$cnt = count($y); $cnt = count($y);
if( $cnt > 0 ) { if( $cnt > 0 ) {
$i=0; $i=0;
while( $i<$cnt && !is_numeric($ym=$y[$i]) ) { while( $i<$cnt && !is_numeric($ym=$y[$i]) ) {
$i++; $i++;
} }
while( $i < $cnt) { while( $i < $cnt) {
if( is_numeric($y[$i]) ) { if( is_numeric($y[$i]) ) {
$ym=min($ym,$y[$i]); $ym=min($ym,$y[$i]);
} }
++$i; ++$i;
} }
} }
else { else {
$ym=''; $ym='';
} }
return array($xm,$ym); return array($xm,$ym);
} }
   
// Get maximum value in plot // Get maximum value in plot
function Max() { function Max() {
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
$x=$this->coords[1]; $x=$this->coords[1];
} }
else { else {
$x=''; $x='';
} }
   
if( $x!='' && count($x) > 0 ) { if( $x!='' && count($x) > 0 ) {
$xm=max($x); $xm=max($x);
} }
else { else {
$xm = $this->numpoints-1; $xm = $this->numpoints-1;
} }
$y=$this->coords[0]; $y=$this->coords[0];
if( count($y) > 0 ) { if( count($y) > 0 ) {
$cnt = count($y); $cnt = count($y);
$i=0; $i=0;
while( $i<$cnt && !is_numeric($ym=$y[$i]) ) { while( $i<$cnt && !is_numeric($ym=$y[$i]) ) {
$i++; $i++;
} }
while( $i < $cnt ) { while( $i < $cnt ) {
if( is_numeric($y[$i]) ) { if( is_numeric($y[$i]) ) {
$ym=max($ym,$y[$i]); $ym=max($ym,$y[$i]);
} }
++$i; ++$i;
} }
} }
else { else {
$ym=''; $ym='';
} }
return array($xm,$ym); return array($xm,$ym);
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->color=$aColor; $this->color=$aColor;
} }
   
function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') { function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') {
$this->legend = $aLegend; $this->legend = $aLegend;
$this->legendcsimtarget = $aCSIM; $this->legendcsimtarget = $aCSIM;
$this->legendcsimwintarget = $aCSIMWinTarget; $this->legendcsimwintarget = $aCSIMWinTarget;
$this->legendcsimalt = $aCSIMAlt; $this->legendcsimalt = $aCSIMAlt;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->weight=$aWeight; $this->weight=$aWeight;
} }
   
function SetLineWeight($aWeight=1) { function SetLineWeight($aWeight=1) {
$this->line_weight=$aWeight; $this->line_weight=$aWeight;
} }
   
function SetCenter($aCenter=true) { function SetCenter($aCenter=true) {
$this->center = $aCenter; $this->center = $aCenter;
} }
   
// This method gets called by Graph class to plot anything that should go // This method gets called by Graph class to plot anything that should go
// into the margin after the margin color has been set. // into the margin after the margin color has been set.
function StrokeMargin($aImg) { function StrokeMargin($aImg) {
return true; return true;
} }
   
// Framework function the chance for each plot class to set a legend // Framework function the chance for each plot class to set a legend
function Legend($aGraph) { function Legend($aGraph) {
if( $this->legend != '' ) { if( $this->legend != '' ) {
$aGraph->legend->Add($this->legend,$this->color,'',0,$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $aGraph->legend->Add($this->legend,$this->color,'',0,$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
} }
   
} // Class } // Class
   
   
// Provide a deterministic list of new colors whenever the getColor() method // Provide a deterministic list of new colors whenever the getColor() method
// is called. Used to automatically set colors of plots. // is called. Used to automatically set colors of plots.
class ColorFactory { class ColorFactory {
   
static private $iIdx = 0; static private $iIdx = 0;
static private $iColorList = array( static private $iColorList = array(
'black', 'black',
'blue', 'blue',
'orange', 'orange',
'darkgreen', 'darkgreen',
'red', 'red',
'AntiqueWhite3', 'AntiqueWhite3',
'aquamarine3', 'aquamarine3',
'azure4', 'azure4',
'brown', 'brown',
'cadetblue3', 'cadetblue3',
'chartreuse4', 'chartreuse4',
'chocolate', 'chocolate',
'darkblue', 'darkblue',
'darkgoldenrod3', 'darkgoldenrod3',
'darkorchid3', 'darkorchid3',
'darksalmon', 'darksalmon',
'darkseagreen4', 'darkseagreen4',
'deepskyblue2', 'deepskyblue2',
'dodgerblue4', 'dodgerblue4',
'gold3', 'gold3',
'hotpink', 'hotpink',
'lawngreen', 'lawngreen',
'lightcoral', 'lightcoral',
'lightpink3', 'lightpink3',
'lightseagreen', 'lightseagreen',
'lightslateblue', 'lightslateblue',
'mediumpurple', 'mediumpurple',
'olivedrab', 'olivedrab',
'orangered1', 'orangered1',
'peru', 'peru',
'slategray', 'slategray',
'yellow4', 'yellow4',
'springgreen2'); 'springgreen2');
static private $iNum = 33; static private $iNum = 33;
   
static function getColor() { static function getColor() {
if( ColorFactory::$iIdx >= ColorFactory::$iNum ) if( ColorFactory::$iIdx >= ColorFactory::$iNum )
ColorFactory::$iIdx = 0; ColorFactory::$iIdx = 0;
return ColorFactory::$iColorList[ColorFactory::$iIdx++]; return ColorFactory::$iColorList[ColorFactory::$iIdx++];
} }
   
} }
   
// <EOF> // <EOF>
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_ANTISPAM.PHP // File: JPGRAPH_ANTISPAM.PHP
// Description: Genarate anti-spam challenge // Description: Genarate anti-spam challenge
// Created: 2004-10-07 // Created: 2004-10-07
// Ver: $Id: jpgraph_antispam-digits.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_antispam-digits.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class HandDigits { class HandDigits {
public $digits = array(); public $digits = array();
public $iHeight=30, $iWidth=30; public $iHeight=30, $iWidth=30;
   
function __construct() { function __construct() {
//========================================================== //==========================================================
// d6-small.jpg // d6-small.jpg
//========================================================== //==========================================================
$this->digits['6'][0]= 645 ; $this->digits['6'][0]= 645 ;
$this->digits['6'][1]= $this->digits['6'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'.
'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'. 'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'.
'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'. 'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'.
'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'. 'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'.
'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'. 'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'.
'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'. 'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'.
'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ; 'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ;
   
//========================================================== //==========================================================
// d2-small.jpg // d2-small.jpg
//========================================================== //==========================================================
$this->digits['2'][0]= 606 ; $this->digits['2'][0]= 606 ;
$this->digits['2'][1]= $this->digits['2'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'.
'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'. 'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'.
'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'. 'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'.
'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'. 'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'.
'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'. 'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'.
'7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'. '7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'.
'DLZ6f//Z' ; 'DLZ6f//Z' ;
   
//========================================================== //==========================================================
// d9-small.jpg // d9-small.jpg
//========================================================== //==========================================================
$this->digits['9'][0]= 680 ; $this->digits['9'][0]= 680 ;
$this->digits['9'][1]= $this->digits['9'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'.
'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'. 'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'.
'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'. 'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'.
'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'. 'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'.
'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'. 'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'.
'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'. 'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'.
'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'. 'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'.
'1V1//9k=' ; '1V1//9k=' ;
   
//========================================================== //==========================================================
// d5-small.jpg // d5-small.jpg
//========================================================== //==========================================================
$this->digits['5'][0]= 632 ; $this->digits['5'][0]= 632 ;
$this->digits['5'][1]= $this->digits['5'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'.
'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'. 'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'.
'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'. 'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'.
'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'. 'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'.
'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'. 'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'.
'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'. 'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'.
'8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ; '8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ;
   
//========================================================== //==========================================================
// d1-small.jpg // d1-small.jpg
//========================================================== //==========================================================
$this->digits['1'][0]= 646 ; $this->digits['1'][0]= 646 ;
$this->digits['1'][1]= $this->digits['1'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'.
'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'. 'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'.
'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'. 'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'.
'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'. 'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'.
'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'. 'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'.
'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'. 'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'.
'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ; 'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ;
   
//========================================================== //==========================================================
// d8-small.jpg // d8-small.jpg
//========================================================== //==========================================================
$this->digits['8'][0]= 694 ; $this->digits['8'][0]= 694 ;
$this->digits['8'][1]= $this->digits['8'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'.
'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'. 'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'.
'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'. 'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'.
'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'. 'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'.
'44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'. '44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'.
'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'. 'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'.
'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'. 'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'.
'EylmLHQltptPZKQOBo1FzH//2Q==' ; 'EylmLHQltptPZKQOBo1FzH//2Q==' ;
   
//========================================================== //==========================================================
// d4-small.jpg // d4-small.jpg
//========================================================== //==========================================================
$this->digits['4'][0]= 643 ; $this->digits['4'][0]= 643 ;
$this->digits['4'][1]= $this->digits['4'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'.
'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'. 'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'.
'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'. 'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'.
'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'. 'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'.
'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'. 'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'.
'27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'. '27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'.
'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ; 'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ;
   
//========================================================== //==========================================================
// d7-small.jpg // d7-small.jpg
//========================================================== //==========================================================
$this->digits['7'][0]= 658 ; $this->digits['7'][0]= 658 ;
$this->digits['7'][1]= $this->digits['7'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'.
'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'. 'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'.
'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'. 'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'.
'19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'. '19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'.
'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'. 'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'.
'8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'. '8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'.
'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ; 'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ;
   
//========================================================== //==========================================================
// d3-small.jpg // d3-small.jpg
//========================================================== //==========================================================
$this->digits['3'][0]= 662 ; $this->digits['3'][0]= 662 ;
$this->digits['3'][1]= $this->digits['3'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'.
'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'. 'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'.
'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'. 'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'.
'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'. 'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'.
'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'. 'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'.
'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'. 'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'.
'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ; 'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ;
} }
} }
   
class AntiSpam { class AntiSpam {
   
var $iNumber=''; var $iNumber='';
   
function __construct($aNumber='') { function __construct($aNumber='') {
$this->iNumber = $aNumber; $this->iNumber = $aNumber;
} }
   
function Rand($aLen) { function Rand($aLen) {
$d=''; $d='';
for($i=0; $i < $aLen; ++$i) { for($i=0; $i < $aLen; ++$i) {
$d .= rand(1,9); $d .= rand(1,9);
} }
$this->iNumber = $d; $this->iNumber = $d;
return $d; return $d;
} }
   
function Stroke() { function Stroke() {
   
$n=strlen($this->iNumber); $n=strlen($this->iNumber);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
if( !is_numeric($this->iNumber[$i]) || $this->iNumber[$i]==0 ) { if( !is_numeric($this->iNumber[$i]) || $this->iNumber[$i]==0 ) {
return false; return false;
} }
} }
   
$dd = new HandDigits(); $dd = new HandDigits();
$n = strlen($this->iNumber); $n = strlen($this->iNumber);
$img = @imagecreatetruecolor($n*$dd->iWidth, $dd->iHeight); $img = @imagecreatetruecolor($n*$dd->iWidth, $dd->iHeight);
if( $img < 1 ) { if( $img < 1 ) {
return false; return false;
} }
$start=0; $start=0;
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$size = $dd->digits[$this->iNumber[$i]][0]; $size = $dd->digits[$this->iNumber[$i]][0];
$dimg = imagecreatefromstring(base64_decode($dd->digits[$this->iNumber[$i]][1])); $dimg = imagecreatefromstring(base64_decode($dd->digits[$this->iNumber[$i]][1]));
imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $dd->iHeight); imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $dd->iHeight);
$start += imagesx($dimg); $start += imagesx($dimg);
} }
$resimg = @imagecreatetruecolor($start+4, $dd->iHeight+4); $resimg = @imagecreatetruecolor($start+4, $dd->iHeight+4);
if( $resimg < 1 ) { if( $resimg < 1 ) {
return false; return false;
} }
imagecopy($resimg,$img,2,2,0,0,$start, $dd->iHeight); imagecopy($resimg,$img,2,2,0,0,$start, $dd->iHeight);
header("Content-type: image/jpeg"); header("Content-type: image/jpeg");
imagejpeg($resimg); imagejpeg($resimg);
return true; return true;
} }
} }
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_ANTISPAM.PHP // File: JPGRAPH_ANTISPAM.PHP
// Description: Genarate anti-spam challenge // Description: Genarate anti-spam challenge
// Created: 2004-10-07 // Created: 2004-10-07
// Ver: $Id: jpgraph_antispam.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_antispam.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
class HandDigits { class HandDigits {
public $chars = array(); public $chars = array();
public $iHeight=30, $iWidth=30; public $iHeight=30, $iWidth=30;
   
function __construct() { function __construct() {
   
//========================================================== //==========================================================
// lj-small.jpg // lj-small.jpg
//========================================================== //==========================================================
$this->chars['j'][0]= 658 ; $this->chars['j'][0]= 658 ;
$this->chars['j'][1]= $this->chars['j'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUGBAf/xAAsEAACAQMDAwMBCQAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUGBAf/xAAsEAACAQMDAwMBCQAAAAAAAAAB'.
'AgMEBREAEjEGIUEUUXGBBxMVIiNSYWKC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/8QAGhEAAwADAQAAAAAAAAAAAAAAAAECERIh'. 'AgMEBREAEjEGIUEUUXGBBxMVIiNSYWKC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/8QAGhEAAwADAQAAAAAAAAAAAAAAAAECERIh'.
'Mv/aAAwDAQACEQMRAD8A6veK2st8zRWSyV1dUBfvHaGVI4hknsS7AFv4AyM57ayWbqeS+11xtT2etttwo4YqhEqnQs5bcAfyk4AZ'. 'Mv/aAAwDAQACEQMRAD8A6veK2st8zRWSyV1dUBfvHaGVI4hknsS7AFv4AyM57ayWbqeS+11xtT2etttwo4YqhEqnQs5bcAfyk4AZ'.
'SOeD441TKRTyingUBG4/ah8j684+dSFzh/BvtaslejMUu9DPQTDnLx4lQ/ONw1TGBm0jdRWqguEMghEisWilgDmNs4Ze+MEEEH40'. 'SOeD441TKRTyingUBG4/ah8j684+dSFzh/BvtaslejMUu9DPQTDnLx4lQ/ONw1TGBm0jdRWqguEMghEisWilgDmNs4Ze+MEEEH40'.
'aUVFTa7JeLjRXu4GjhmnNbSfqFQVlA3rkckOjH/Q99Glmkl0C/Q06pvsvT9vttXHDF6T1KrWbs5gRgQJM+FDlQxPhjpF1XcVq+qe'. 'aUVFTa7JeLjRXu4GjhmnNbSfqFQVlA3rkckOjH/Q99Glmkl0C/Q06pvsvT9vttXHDF6T1KrWbs5gRgQJM+FDlQxPhjpF1XcVq+qe'.
'jEoKiOecXBqh2TDDYIXLKuP6549xk8auI6aJqV45oknWdNswkAIkGMYIxjGO2NR1F0LZY5qkWqkS1xrM0M8lMSJpY+TGrnJiQ577'. 'jEoKiOecXBqh2TDDYIXLKuP6549xk8auI6aJqV45oknWdNswkAIkGMYIxjGO2NR1F0LZY5qkWqkS1xrM0M8lMSJpY+TGrnJiQ577'.
'cEgeNHhi7D3qC3UN69M8tIakRhgrh9o748+eNGtcCiKjjpkQKlMTEg3ZwoxtHHtgfTRpYXArvp//2Q==' ; 'cEgeNHhi7D3qC3UN69M8tIakRhgrh9o748+eNGtcCiKjjpkQKlMTEg3ZwoxtHHtgfTRpYXArvp//2Q==' ;
   
//========================================================== //==========================================================
// lf-small.jpg // lf-small.jpg
//========================================================== //==========================================================
$this->chars['f'][0]= 633 ; $this->chars['f'][0]= 633 ;
$this->chars['f'][1]= $this->chars['f'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQFBgcC/8QAKxAAAgEDAwMCBQUAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQFBgcC/8QAKxAAAgEDAwMCBQUAAAAAAAAA'.
'AQIDBBEhAAUGEjFBEyIHFFFhoRUzYnGS/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQP/xAAaEQACAwEBAAAAAAAAAAAAAAAAAQIRMRIh'. 'AQIDBBEhAAUGEjFBEyIHFFFhoRUzYnGS/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQP/xAAaEQACAwEBAAAAAAAAAAAAAAAAAQIRMRIh'.
'/9oADAMBAAIRAxEAPwDcnmLoIkiSYsouC3tA++O2lU9WkqVjJ+YdhZLsQI/4/YfQm50kZP0vbmaCSU0SRNIH6sghb9INs3t38dvp'. '/9oADAMBAAIRAxEAPwDcnmLoIkiSYsouC3tA++O2lU9WkqVjJ+YdhZLsQI/4/YfQm50kZP0vbmaCSU0SRNIH6sghb9INs3t38dvp'.
'akUuz8x5DwdN5peS1jV1dSipSiVUigIcdQjQ26lIB/c6r3F86SZpE/zCFJaqsihQNhRgdj3Jyfxo0jDSbXHt9Oph9RAoV3qJGltY'. 'akUuz8x5DwdN5peS1jV1dSipSiVUigIcdQjQ26lIB/c6r3F86SZpE/zCFJaqsihQNhRgdj3Jyfxo0jDSbXHt9Oph9RAoV3qJGltY'.
'HDOxyb/nRpV0D3RXle21m48XraOk3IUSemUaV4g4Zc9ShcDtgff+tQfwvjq34Dtku7buamFqeJKemCCMxKFsEJU+/FrX8d76sEHG'. 'HDOxyb/nRpV0D3RXle21m48XraOk3IUSemUaV4g4Zc9ShcDtgff+tQfwvjq34Dtku7buamFqeJKemCCMxKFsEJU+/FrX8d76sEHG'.
'aNItzr4usVNdG3S0rmRYAVwEUmyjyQLZ11x7aF4zs9DQOyzml29I2cLa/pixIHi99DFCtU9dFuLIaijo9qiYPmR2mZmB9thgAHOD'. 'aNItzr4usVNdG3S0rmRYAVwEUmyjyQLZ11x7aF4zs9DQOyzml29I2cLa/pixIHi99DFCtU9dFuLIaijo9qiYPmR2mZmB9thgAHOD'.
'4+mjUrURyrUNMZFEkkIOFuFAbsP9d/OjVIQ6Vh4tP//Z' ; '4+mjUrURyrUNMZFEkkIOFuFAbsP9d/OjVIQ6Vh4tP//Z' ;
   
//========================================================== //==========================================================
// lb-small.jpg // lb-small.jpg
//========================================================== //==========================================================
$this->chars['b'][0]= 645 ; $this->chars['b'][0]= 645 ;
$this->chars['b'][1]= $this->chars['b'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYCAwUH/8QAKxAAAQMDAwMDAwUAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYCAwUH/8QAKxAAAQMDAwMDAwUAAAAAAAAA'.
'AQIDBAAFEQYSIRMxUSJBYQcVI2JxgqHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQL/xAAYEQEBAQEBAAAAAAAAAAAAAAAAATERYf/a'. 'AQIDBAAFEQYSIRMxUSJBYQcVI2JxgqHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQL/xAAYEQEBAQEBAAAAAAAAAAAAAAAAATERYf/a'.
'AAwDAQACEQMRAD8A6H95mxNYwLXcX+pCuilSLXJ6YSplaUELjqxwe4IJ5PIPamJ2V0bPcS7+NxCX1cHggAnIP+xSd9RyzHh2m7FQ'. 'AAwDAQACEQMRAD8A6H95mxNYwLXcX+pCuilSLXJ6YSplaUELjqxwe4IJ5PIPamJ2V0bPcS7+NxCX1cHggAnIP+xSd9RyzHh2m7FQ'.
'Q1CvMNQWTjCt+HFD+PB/Y1fI1PL1HFFt0zaGblFdJQ9cJjpZiqPJUlBAKnPcEpGB5NNRKdrOl1NlgiQol4R2w4Sc5VtGf7opZteo'. 'Q1CvMNQWTjCt+HFD+PB/Y1fI1PL1HFFt0zaGblFdJQ9cJjpZiqPJUlBAKnPcEpGB5NNRKdrOl1NlgiQol4R2w4Sc5VtGf7opZteo'.
'LhdorjUSM5FnQnlR50NeHQysYxtVxlJHIPgjtRRD3xkaghs6juumdHz4+Y7RVPnt59K2mk7W+fcKWsZ7djTXMkW+xMP3GRJjwIEN'. 'LhdorjUSM5FnQnlR50NeHQysYxtVxlJHIPgjtRRD3xkaghs6juumdHz4+Y7RVPnt59K2mk7W+fcKWsZ7djTXMkW+xMP3GRJjwIEN'.
'HTG/CWx5wPY8AADx2NYk3SL9wukvUjGobnBkORksIbjdMANozgEqSo8qJPGO/wAVO36IsjUmBIfZfuM7epZk3F9UhSSk5O0K9Kcq'. 'HTG/CWx5wPY8AADx2NYk3SL9wukvUjGobnBkORksIbjdMANozgEqSo8qJPGO/wAVO36IsjUmBIfZfuM7epZk3F9UhSSk5O0K9Kcq'.
'8AcU3UzFuhUSBFud6nRXoz96mqmJZWg7m2dqUNhWBwdqQSP1UU5c/FFCn//Z' ; '8AcU3UzFuhUSBFud6nRXoz96mqmJZWg7m2dqUNhWBwdqQSP1UU5c/FFCn//Z' ;
   
//========================================================== //==========================================================
// d6-small.jpg // d6-small.jpg
//========================================================== //==========================================================
$this->chars['6'][0]= 645 ; $this->chars['6'][0]= 645 ;
$this->chars['6'][1]= $this->chars['6'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'.
'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'. 'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'.
'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'. 'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'.
'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'. 'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'.
'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'. 'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'.
'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'. 'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'.
'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ; 'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ;
   
//========================================================== //==========================================================
// lx-small.jpg // lx-small.jpg
//========================================================== //==========================================================
$this->chars['x'][0]= 650 ; $this->chars['x'][0]= 650 ;
$this->chars['x'][1]= $this->chars['x'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABMDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUHBgj/xAApEAABAwMDAwQCAwAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABMDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUHBgj/xAApEAABAwMDAwQCAwAAAAAAAAAB'.
'AgMEBQYRACFBBxIxFCJRgRNxkcHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEQH/2gAMAwEA'. 'AgMEBQYRACFBBxIxFCJRgRNxkcHw/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEQH/2gAMAwEA'.
'AhEDEQA/AH9t3pKvO14UykVARa/HfAlxlDKXR24V2p3z7RlPwdtMep91uWdRGHWELjuTFFtLvcC4SNznnH+21O7ttiodOq1BvC0E'. 'AhEDEQA/AH9t3pKvO14UykVARa/HfAlxlDKXR24V2p3z7RlPwdtMep91uWdRGHWELjuTFFtLvcC4SNznnH+21O7ttiodOq1BvC0E'.
'p9I0lSX2kgqCSklK+5PKCMAng6zV2XRO6u3lSIURtbDRShltlZHa0tW7q/0MeTwnjxq1Jiw2xc9xTLbhSVU5iaXUFfqFFILgJOCd'. 'p9I0lSX2kgqCSklK+5PKCMAng6zV2XRO6u3lSIURtbDRShltlZHa0tW7q/0MeTwnjxq1Jiw2xc9xTLbhSVU5iaXUFfqFFILgJOCd'.
'9Gt3SXabR6REpkL8yo0RpLCFNx1qBCRjOQMHxo0pEr6o3um2LVYpMEpTVqg25lHn08dfcB9kEgfZ1LIFDuawqZRb7aQlLTzqglsg'. '9Gt3SXabR6REpkL8yo0RpLCFNx1qBCRjOQMHxo0pEr6o3um2LVYpMEpTVqg25lHn08dfcB9kEgfZ1LIFDuawqZRb7aQlLTzqglsg'.
'9wQdveOEqBIB425xqhQuk8qo9UKlPrlRblw2ZBeCSVKW6CcoSrI2AGOT41SKzT4dYtmdS5bIXDZhNoWgbZJ94x8AYT/GkM03oNUc'. '9wQdveOEqBIB425xqhQuk8qo9UKlPrlRblw2ZBeCSVKW6CcoSrI2AGOT41SKzT4dYtmdS5bIXDZhNoWgbZJ94x8AYT/GkM03oNUc'.
'uKgwqtTZDTMOU0FttqRkoHggnPkEEHRrkJ6t1SlSHYUOc6zHaWrsbQrATk5/vRqK/9k=' ; 'uKgwqtTZDTMOU0FttqRkoHggnPkEEHRrkJ6t1SlSHYUOc6zHaWrsbQrATk5/vRqK/9k=' ;
   
//========================================================== //==========================================================
// d2-small.jpg // d2-small.jpg
//========================================================== //==========================================================
$this->chars['2'][0]= 606 ; $this->chars['2'][0]= 606 ;
$this->chars['2'][1]= $this->chars['2'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'.
'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'. 'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'.
'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'. 'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'.
'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'. 'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'.
'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'. 'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'.
'7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'. '7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'.
'DLZ6f//Z' ; 'DLZ6f//Z' ;
   
//========================================================== //==========================================================
// lm-small.jpg // lm-small.jpg
//========================================================== //==========================================================
$this->chars['m'][0]= 649 ; $this->chars['m'][0]= 649 ;
$this->chars['m'][1]= $this->chars['m'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAcDBAUCBv/EAC0QAAICAQMCBAMJAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAcDBAUCBv/EAC0QAAICAQMCBAMJAAAAAAAA'.
'AAECAwQRAAUSBiETMVFhB2KhFSIyQVJxgZHB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREBAQEAAwAAAAAAAAAAAAAAAQAR'. 'AAECAwQRAAUSBiETMVFhB2KhFSIyQVJxgZHB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREBAQEAAwAAAAAAAAAAAAAAAQAR'.
'EiEx/9oADAMBAAIRAxEAPwB0MI2lIdgI0Cly3kFXLEn2zx1FDdp7rbpbjUtRWKio3hyxOGQllJzkegX66rQ2qW87Zuk9S5FNVmru'. 'EiEx/9oADAMBAAIRAxEAPwB0MI2lIdgI0Cly3kFXLEn2zx1FDdp7rbpbjUtRWKio3hyxOGQllJzkegX66rQ2qW87Zuk9S5FNVmru'.
'iywyBhjDKTkeXfSr+GRfYtq2KAO32b1BGxAZu0dyJ2DKPTxY1wPddVszycUq2Golq8jRWbcnJWwCVGMjz+VQP50atxMtm2ZUOY4l'. 'iywyBhjDKTkeXfSr+GRfYtq2KAO32b1BGxAZu0dyJ2DKPTxY1wPddVszycUq2Golq8jRWbcnJWwCVGMjz+VQP50atxMtm2ZUOY4l'.
'4qfUnBP0x/Z0amy4jJm10Tt2yddWasFmfaRfdrlG3UcgArnxKzJ+Fu4DqCMkcgNem2DoWav8PLfTm+FPEkuSNTnqueS5bnHIv6CG'. '4qfUnBP0x/Z0amy4jJm10Tt2yddWasFmfaRfdrlG3UcgArnxKzJ+Fu4DqCMkcgNem2DoWav8PLfTm+FPEkuSNTnqueS5bnHIv6CG'.
'LNjJwM99bm67NB1Ht89KSxNXnr2hNDbiUc47K4KyD2GQMfmMjUnS+7vuIktTqPCaaWCqAMMojPFyw8hyYMQBnAwNJHYGXPTsW9VN'. 'LNjJwM99bm67NB1Ht89KSxNXnr2hNDbiUc47K4KyD2GQMfmMjUnS+7vuIktTqPCaaWCqAMMojPFyw8hyYMQBnAwNJHYGXPTsW9VN'.
'jg2zf50W9zk524GAEihuz+xbIOD82jW5TkjtRPZkTkJ+4VgDhQfuj/f3OjUxl1f/2Q==' ; 'jg2zf50W9zk524GAEihuz+xbIOD82jW5TkjtRPZkTkJ+4VgDhQfuj/f3OjUxl1f/2Q==' ;
   
//========================================================== //==========================================================
// lt-small.jpg // lt-small.jpg
//========================================================== //==========================================================
$this->chars['t'][0]= 648 ; $this->chars['t'][0]= 648 ;
$this->chars['t'][1]= $this->chars['t'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAJxAAAQMDAgYDAQEAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAJxAAAQMDAgYDAQEAAAAAAAAA'.
'AQIDBAUGEQASEyExQVFhIjJxFSP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAP/xAAZEQADAQEBAAAAAAAAAAAAAAAAAREhMUH/2gAM'. 'AQIDBAUGEQASEyExQVFhIjJxFSP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAP/xAAZEQADAQEBAAAAAAAAAAAAAAAAAREhMUH/2gAM'.
'AwEAAhEDEQA/AO4BLEiEy7uG4IGxxs5IOOx76wd2XYidSp1HoD70240gcNNPbDyI6wQQpaz8E9MczkdhqtbsKYLieDk6WLKmZmmL'. 'AwEAAhEDEQA/AO4BLEiEy7uG4IGxxs5IOOx76wd2XYidSp1HoD70240gcNNPbDyI6wQQpaz8E9MczkdhqtbsKYLieDk6WLKmZmmL'.
'Hk7AHVkbkLI+RQc7uRxgkfr1tx2rGu6VbToLVKkhU+kbugGf9WfaknCk5ycaX0zmaa+3JkqvW/CmzojsB9xoF6OoFK0r6HOcEDI0'. 'Hk7AHVkbkLI+RQc7uRxgkfr1tx2rGu6VbToLVKkhU+kbugGf9WfaknCk5ycaX0zmaa+3JkqvW/CmzojsB9xoF6OoFK0r6HOcEDI0'.
'aefTuKX5ScMdC14HYq8n12zo1DEUcKTGg1Z+hyBwoPBVIiA/VQyOIgedhUCB4WMfXSV3UufVLcTUIqVf26K6mXDbPVRRzKT54iMg'. 'aefTuKX5ScMdC14HYq8n12zo1DEUcKTGg1Z+hyBwoPBVIiA/VQyOIgedhUCB4WMfXSV3UufVLcTUIqVf26K6mXDbPVRRzKT54iMg'.
'+zjtq6mtsyJjclxpKlUhSXEbkgkqWnBx4+J5e/zU0pZemPvJJQzEPDfQOrwwFY9AZ5eeYPLV6FwhoFYZuigxpkJeIjqAeIoAk9wA'. '+zjtq6mtsyJjclxpKlUhSXEbkgkqWnBx4+J5e/zU0pZemPvJJQzEPDfQOrwwFY9AZ5eeYPLV6FwhoFYZuigxpkJeIjqAeIoAk9wA'.
'D46EnuD+6Nc1smDNrTlRkxqtMo1vzKhIdYgU9YDqVpISrLhHxSSd21I0aYyqP//Z' ; 'D46EnuD+6Nc1smDNrTlRkxqtMo1vzKhIdYgU9YDqVpISrLhHxSSd21I0aYyqP//Z' ;
   
//========================================================== //==========================================================
// li-small.jpg // li-small.jpg
//========================================================== //==========================================================
$this->chars['i'][0]= 639 ; $this->chars['i'][0]= 639 ;
$this->chars['i'][1]= $this->chars['i'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABwAGBP/EACcQAAEEAQMEAgIDAAAAAAAAAAEC'. 'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABwAGBP/EACcQAAEEAQMEAgIDAAAAAAAAAAEC'.
'AwQRBQAGEiExQVEHExSBFWFx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgMB/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECMRH/2gAMAwEA'. 'AwQRBQAGEiExQVEHExSBFWFx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgMB/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECMRH/2gAMAwEA'.
'AhEDEQA/AE7c+5M9BeRG29t1WUfKFFYW+GvrI7WD3B9g140YD5T36rcErDjbUR6dCBdejsKUpxITXI2FUrooCh70yvxzHyIlMvuK'. 'AhEDEQA/AE7c+5M9BeRG29t1WUfKFFYW+GvrI7WD3B9g140YD5T36rcErDjbUR6dCBdejsKUpxITXI2FUrooCh70yvxzHyIlMvuK'.
'eVSH7IKEpJoKqu/ahddLryR/aMiO187bsmrWShhp1AZS2XHHrWhNJrzdf7f7GiVcHk3sptmHkJcJ2DIftS2FrKlJPXudWuLGYeQp'. 'eVSH7IKEpJoKqu/ahddLryR/aMiO187bsmrWShhp1AZS2XHHrWhNJrzdf7f7GiVcHk3sptmHkJcJ2DIftS2FrKlJPXudWuLGYeQp'.
't2fmEIckqIZaaKuSGG0lQ4gduRoFRHQ9AOgs2lOJbk9aSUlpjGvAWeSVH2VKq/2dFPw3IjyJe8s281ct3I9UoHJXGiQkD2STrSZ7'. 't2fmEIckqIZaaKuSGG0lQ4gduRoFRHQ9AOgs2lOJbk9aSUlpjGvAWeSVH2VKq/2dFPw3IjyJe8s281ct3I9UoHJXGiQkD2STrSZ7'.
'Yf8AOl7JTdw5eOCz0jw3+LbYCfA9nz71msb8KMxoTGTw+5srjsipAdDqFBQBIuiOl6KrdYyJMyTCshlw2G3Fr/HiNqNNAqJJUoGl'. 'Yf8AOl7JTdw5eOCz0jw3+LbYCfA9nz71msb8KMxoTGTw+5srjsipAdDqFBQBIuiOl6KrdYyJMyTCshlw2G3Fr/HiNqNNAqJJUoGl'.
'KND+h47km1bZwsvCbYYjycxIyK1qDv2yEi0hQviK8atKDcy9j//Z' ; 'KND+h47km1bZwsvCbYYjycxIyK1qDv2yEi0hQviK8atKDcy9j//Z' ;
   
   
//========================================================== //==========================================================
// lp-small.jpg // lp-small.jpg
//========================================================== //==========================================================
$this->chars['p'][0]= 700 ; $this->chars['p'][0]= 700 ;
$this->chars['p'][1]= $this->chars['p'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAECBAUGB//EAC8QAAEDAwMCBAMJAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAECBAUGB//EAC8QAAEDAwMCBAMJAAAAAAAA'.
'AAECAwQFESEABhIiMRMVUWEHFEEWIzIzcYGRocH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAcEQACAgIDAAAAAAAAAAAAAAAA'. 'AAECAwQFESEABhIiMRMVUWEHFEEWIzIzcYGRocH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAcEQACAgIDAAAAAAAAAAAAAAAA'.
'AQIxAxESIUH/2gAMAwEAAhEDEQA/AOh703xG21DMeOyqoVNDjSzERiwU6Ep5qtZNycA97HTF13d33KWtmlt9xwkLl1NkXVxIuQgK'. 'AQIxAxESIUH/2gAMAwEAAhEDEQA/AOh703xG21DMeOyqoVNDjSzERiwU6Ep5qtZNycA97HTF13d33KWtmlt9xwkLl1NkXVxIuQgK'.
'wLj+hqBvel0qmbR8GnR22nJNZiLeeKr8nDIT1OLJucX+uPbWom7iocRpafOac5MX1ALltp/Cbi+cJH++utdh+WVNL3PNdNYpdWgx'. 'wLj+hqBvel0qmbR8GnR22nJNZiLeeKr8nDIT1OLJucX+uPbWom7iocRpafOac5MX1ALltp/Cbi+cJH++utdh+WVNL3PNdNYpdWgx'.
'Y0qmLZSrwJJcQoOJ5XKlJFu4HbJOjVbt+V5nu7eopNRivqcdhK+bFnWwA1Y2AOcgjvj9dGlxy0g5y0xd+hNXoG24C4obizq3HZUh'. 'Y0qmLZSrwJJcQoOJ5XKlJFu4HbJOjVbt+V5nu7eopNRivqcdhK+bFnWwA1Y2AOcgjvj9dGlxy0g5y0xd+hNXoG24C4obizq3HZUh'.
'YHqtRHD06bG/8a0MbbG1mqekxaBSGmgkrcdcitlLfrckZIz7DUatbeFak0tyRLUwzT5vmiGm0cufEkFBJItfkD+59tKmiO12atFa'. 'YHqtRHD06bG/8a0MbbG1mqekxaBSGmgkrcdcitlLfrckZIz7DUatbeFak0tyRLUwzT5vmiGm0cufEkFBJItfkD+59tKmiO12atFa'.
'eQukO3ejUxgENqTcfnE5WbkHiOnJ76N2IqI1DibabptS+zkZhtp90F2Y0S026EkAFK/qL46cXv65NVZDfxHmVCK4DE2/RX/lRFbA'. 'eQukO3ejUxgENqTcfnE5WbkHiOnJ76N2IqI1DibabptS+zkZhtp90F2Y0S026EkAFK/qL46cXv65NVZDfxHmVCK4DE2/RX/lRFbA'.
'C5LwAyq2EtpHZI7mxPYDRqoctdESimz/2Q==' ; 'C5LwAyq2EtpHZI7mxPYDRqoctdESimz/2Q==' ;
   
//========================================================== //==========================================================
// le-small.jpg // le-small.jpg
//========================================================== //==========================================================
$this->chars['e'][0]= 700 ; $this->chars['e'][0]= 700 ;
$this->chars['e'][1]= $this->chars['e'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABgDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYEBQcB/8QAKhAAAQMCBAUEAwEAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABgDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYEBQcB/8QAKhAAAQMCBAUEAwEAAAAAAAAA'.
'AgEDBAURAAYSIQciMTJBE0JRYRQVFoH/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREAAwEBAQAAAAAAAAAAAAAAAAERAjFB'. 'AgEDBAURAAYSIQciMTJBE0JRYRQVFoH/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAgED/8QAGREAAwEBAQAAAAAAAAAAAAAAAAERAjFB'.
'/9oADAMBAAIRAxEAPwDTszvhEYCoS80BTm2bCjQRwdAzVe2yopkpJtpRUVfjEIc4V2oMerByg5Ji30oMyS3GeMunK0upfnu09MdJ'. '/9oADAMBAAIRAxEAPwDTszvhEYCoS80BTm2bCjQRwdAzVe2yopkpJtpRUVfjEIc4V2oMerByg5Ji30oMyS3GeMunK0upfnu09MdJ'.
'p2scTmWnnGfx6HThktgLfKj7xEOqyr7QBbL41LhBzpxbcOru0LKDLdSnOHoaltNqSC4qWL0x9xbJYum69caczSaHmGmTmpDUYn4l'. 'p2scTmWnnGfx6HThktgLfKj7xEOqyr7QBbL41LhBzpxbcOru0LKDLdSnOHoaltNqSC4qWL0x9xbJYum69caczSaHmGmTmpDUYn4l'.
'UiqjkynzAVtwV23Ud+X4Ibpa2DCPkjhfUaRO/p8yzpb+YHhUmhbev6ZEll1lvqK3jt2XrbBgp6HVwsK3THpfEubGSoOUyFMpbJmL'. 'UiqjkynzAVtwV23Ud+X4Ibpa2DCPkjhfUaRO/p8yzpb+YHhUmhbev6ZEll1lvqK3jt2XrbBgp6HVwsK3THpfEubGSoOUyFMpbJmL'.
'Deh6SgOGKti57EuY6l62JMWdJy7k3hg1LkOozEbVm7suQSkTiKtkEfP1pH664Za/QItccgI4bseTHdNxiXHLQ8yVl7V32XyioqL5'. 'Deh6SgOGKti57EuY6l62JMWdJy7k3hg1LkOozEbVm7suQSkTiKtkEfP1pH664Za/QItccgI4bseTHdNxiXHLQ8yVl7V32XyioqL5'.
'TGc1ng6eYs0idczXUZscBBABWgEhEtfKNuUezwPnBhEuj8X2M21z9BR6NUX211Kk/UKKAjuhkPhL7XVf8vtgw7UPJlEyrDWFSYLb'. 'TGc1ng6eYs0idczXUZscBBABWgEhEtfKNuUezwPnBhEuj8X2M21z9BR6NUX211Kk/UKKAjuhkPhL7XVf8vtgw7UPJlEyrDWFSYLb'.
'LBNF6qrzG6t0spEu6+fpL7YMXhUndp//2Q==' ; 'LBNF6qrzG6t0spEu6+fpL7YMXhUndp//2Q==' ;
   
//========================================================== //==========================================================
// la-small.jpg // la-small.jpg
//========================================================== //==========================================================
$this->chars['a'][0]= 730 ; $this->chars['a'][0]= 730 ;
$this->chars['a'][1]= $this->chars['a'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABoDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwIFAQcCBwAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABoDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwIFAQcCBwAAAAAAAAAB'.
'AgMEBREAEiExQQYHFBUiUXGBE2EyQkNSgpHh/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAMBAv/EABkRAAMBAQEAAAAAAAAAAAAAAAAB'. 'AgMEBREAEiExQQYHFBUiUXGBE2EyQkNSgpHh/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAMBAv/EABkRAAMBAQEAAAAAAAAAAAAAAAAB'.
'IQIRMf/aAAwDAQACEQMRAD8AfdQ1pxjqZMSn0mRUZRYDaklJCE3OawO2ttTxY4hl07qFMVs1Ku02kpPnRGhsAqz8W9T9wDjozq6o'. 'IQIRMf/aAAwDAQACEQMRAD8AfdQ1pxjqZMSn0mRUZRYDaklJCE3OawO2ttTxY4hl07qFMVs1Ku02kpPnRGhsAqz8W9T9wDjozq6o'.
'Q1lDrcZLGVcmUoZg0obpufxK3Ftt9ccqB1GgBcmLSqtVEqOZcr6ARm/kbXHt7DEtc7WTJKTJqEWvRKfLqL9QplSjuPtGVYOJKBrm'. 'Q1lDrcZLGVcmUoZg0obpufxK3Ftt9ccqB1GgBcmLSqtVEqOZcr6ARm/kbXHt7DEtc7WTJKTJqEWvRKfLqL9QplSjuPtGVYOJKBrm'.
't+U+n94WGStZzNypmRWqckUKTbixy6jAfxPxHtCgKqFNlU5huK6pLMndSlegG4J45N8aKmTMKQRBsCNMzwB+RbHWHGEAZlPZX2hx'. 't+U+n94WGStZzNypmRWqckUKTbixy6jAfxPxHtCgKqFNlU5huK6pLMndSlegG4J45N8aKmTMKQRBsCNMzwB+RbHWHGEAZlPZX2hx'.
'qZIC34ygZoYUbB50JSkFXFhZR9BrpheR4fIbQ6gvurJ7q02bIQTuAOAN8x40HAxRr3TrNRpBmSHVt1KMlTyJTCsqkKAPlSf28W+c'. 'qZIC34ygZoYUbB50JSkFXFhZR9BrpheR4fIbQ6gvurJ7q02bIQTuAOAN8x40HAxRr3TrNRpBmSHVt1KMlTyJTCsqkKAPlSf28W+c'.
'UGaD1c9HSR1HFUh9tJU45EBcAtcC9+P9wqbg8IAto9o81yputrVGpiUkgHKkqUTZI32+cKm1z1tIUgPBBAKQ4UBQH3uL3xmXSXep'. 'UGaD1c9HSR1HFUh9tJU45EBcAtcC9+P9wqbg8IAto9o81yputrVGpiUkgHKkqUTZI32+cKm1z1tIUgPBBAKQ4UBQH3uL3xmXSXep'.
'HVDtXStE5K5jlPU7PF3Q41+okJFkjgC+3OuNSYiSzHaLtRcW4UDMpLYSCbakDW3thhum5p//2Q==' ; 'HVDtXStE5K5jlPU7PF3Q41+okJFkjgC+3OuNSYiSzHaLtRcW4UDMpLYSCbakDW3thhum5p//2Q==' ;
   
//========================================================== //==========================================================
// d9-small.jpg // d9-small.jpg
//========================================================== //==========================================================
$this->chars['9'][0]= 680 ; $this->chars['9'][0]= 680 ;
$this->chars['9'][1]= $this->chars['9'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'.
'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'. 'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'.
'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'. 'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'.
'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'. 'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'.
'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'. 'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'.
'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'. 'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'.
'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'. 'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'.
'1V1//9k=' ; '1V1//9k=' ;
   
//========================================================== //==========================================================
// d5-small.jpg // d5-small.jpg
//========================================================== //==========================================================
$this->chars['5'][0]= 632 ; $this->chars['5'][0]= 632 ;
$this->chars['5'][1]= $this->chars['5'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'.
'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'. 'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'.
'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'. 'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'.
'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'. 'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'.
'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'. 'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'.
'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'. 'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'.
'8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ; '8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ;
   
//========================================================== //==========================================================
// d1-small.jpg // d1-small.jpg
//========================================================== //==========================================================
$this->chars['1'][0]= 646 ; $this->chars['1'][0]= 646 ;
$this->chars['1'][1]= $this->chars['1'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'.
'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'. 'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'.
'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'. 'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'.
'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'. 'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'.
'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'. 'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'.
'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'. 'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'.
'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ; 'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ;
   
//========================================================== //==========================================================
// ll-small.jpg // ll-small.jpg
//========================================================== //==========================================================
$this->chars['l'][0]= 626 ; $this->chars['l'][0]= 626 ;
$this->chars['l'][1]= $this->chars['l'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYEBQf/xAArEAACAQIFAwIGAwAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYEBQf/xAArEAACAQIFAwIGAwAAAAAAAAAB'.
'AgMEEQAFBhIhFEFREzEHFSIyYcFxgZH/xAAXAQEAAwAAAAAAAAAAAAAAAAACAAED/8QAGhEAAwEAAwAAAAAAAAAAAAAAAAECMREh'. 'AgMEEQAFBhIhFEFREzEHFSIyYcFxgZH/xAAXAQEAAwAAAAAAAAAAAAAAAAACAAED/8QAGhEAAwEAAwAAAAAAAAAAAAAAAAECMREh'.
'Qf/aAAwDAQACEQMRAD8A15Zfm1VURj1Fp5AqLKv3OARcL4W5Nzx+MLWjdRz5hqXU6TSb6OCr6WghiQbrJ91gOTy1yT5xZ55myZFk'. 'Qf/aAAwDAQACEQMRAD8A15Zfm1VURj1Fp5AqLKv3OARcL4W5Nzx+MLWjdRz5hqXU6TSb6OCr6WghiQbrJ91gOTy1yT5xZ55myZFk'.
'Gb5ozX6Ondm28XYqpQDwu7jEH4c5S2UaDy4xxrLmlUDWzk8XaQ3O49hbj+RiB85HNg8Ee3aqwIqhDuux7G/HHbvzgxEqaWOvy09R'. 'Gb5ozX6Ondm28XYqpQDwu7jEH4c5S2UaDy4xxrLmlUDWzk8XaQ3O49hbj+RiB85HNg8Ee3aqwIqhDuux7G/HHbvzgxEqaWOvy09R'.
'O0o3hjdQoUji20g+fY3wYSM6pJ4Ylr7V+Zz5PSaezHTlTRNWzxySSxt6q1MSkH6AOT2Fu3Aw7RfF/T9DEkLUeawuF2mKSgdWQj2/'. 'O0o3hjdQoUji20g+fY3wYSM6pJ4Ylr7V+Zz5PSaezHTlTRNWzxySSxt6q1MSkH6AOT2Fu3Aw7RfF/T9DEkLUeawuF2mKSgdWQj2/'.
'q3+fnDZDlqRZzQGaOGcpTOaeR1u8R+ncN3gj94so2jNWHeMNNKzorEX2qp9v3imNPoRE1zpjUtZ09HJmYq5lury0benZeTww23t3'. 'q3+fnDZDlqRZzQGaOGcpTOaeR1u8R+ncN3gj94so2jNWHeMNNKzorEX2qp9v3imNPoRE1zpjUtZ09HJmYq5lury0benZeTww23t3'.
'Ivgw+T0yRRyyxIqNfkLcA8jt7YMKcBWn/9k=' ; 'Ivgw+T0yRRyyxIqNfkLcA8jt7YMKcBWn/9k=' ;
   
   
//========================================================== //==========================================================
// ls-small.jpg // ls-small.jpg
//========================================================== //==========================================================
$this->chars['s'][0]= 701 ; $this->chars['s'][0]= 701 ;
$this->chars['s'][1]= $this->chars['s'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAMCBAUGB//EACwQAAEEAQIFAgUFAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAAAAMCBAUGB//EACwQAAEEAQIFAgUFAAAAAAAA'.
'AAECAwQFEQAGEhMUITEiYQcjQVFxFRZCUoH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAZEQADAQEBAAAAAAAAAAAAAAAAAQIR'. 'AAECAwQFEQAGEhMUITEiYQcjQVFxFRZCUoH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgH/xAAZEQADAQEBAAAAAAAAAAAAAAAAAQIR'.
'EiH/2gAMAwEAAhEDEQA/APWZMhmFXSJU+SGmWFiQtAWMJQAnJUr8Z+w/OuQk71uZnMsqnbjy9s8st9UMCQ6kZJdZaIHEkZ/JHceN'. 'EiH/2gAMAwEAAhEDEQA/APWZMhmFXSJU+SGmWFiQtAWMJQAnJUr8Z+w/OuQk71uZnMsqnbjy9s8st9UMCQ6kZJdZaIHEkZ/JHceN'.
'N3HtizuY1JLrG48yLBSC9UTFKQiY4nACir+wAOOMEe2rm2bTbzlqtE1MyBuZAPybpw85KSfDRJ4Cg+Pl/wC61hJeGjV31VuuKqwr'. 'N3HtizuY1JLrG48yLBSC9UTFKQiY4nACir+wAOOMEe2rm2bTbzlqtE1MyBuZAPybpw85KSfDRJ4Cg+Pl/wC61hJeGjV31VuuKqwr'.
'LGU+whZZK+Rw+oYJAyj3GjS4dZFpZVkqPLktdfMXNcaU2kBC1BIITkdx6c599GlnvPAa3TL2vNvU76n0063acr3YSLCEjpUpUQtW'. 'LGU+whZZK+Rw+oYJAyj3GjS4dZFpZVkqPLktdfMXNcaU2kBC1BIITkdx6c599GlnvPAa3TL2vNvU76n0063acr3YSLCEjpUpUQtW'.
'Dhf14SMEnOc57aZ8Tegm7dbrEQGZt1PeTDgc1PEW3FeXAvyAkZVkeMDOm2G3f3O7Cl/qEuqkQg4lp6CRxraWfUlRUD24kZA741Ko'. 'Dhf14SMEnOc57aZ8Tegm7dbrEQGZt1PeTDgc1PEW3FeXAvyAkZVkeMDOm2G3f3O7Cl/qEuqkQg4lp6CRxraWfUlRUD24kZA741Ko'.
'2k1HvlT3ri2sLOCgtsyJz6XEtBwZPAgJAGQMHUNPWKqWItsqh0UCFVyLeKhyLHQ2TMdHNVj+RKlAnJyfto1FW2ahgjrq6LYTFjjf'. '2k1HvlT3ri2sLOCgtsyJz6XEtBwZPAgJAGQMHUNPWKqWItsqh0UCFVyLeKhyLHQ2TMdHNVj+RKlAnJyfto1FW2ahgjrq6LYTFjjf'.
'lymUOLdWfJyoHA+gA7AAAaNPE3ysJdLT/9k=' ; 'lymUOLdWfJyoHA+gA7AAAaNPE3ysJdLT/9k=' ;
   
//========================================================== //==========================================================
// lh-small.jpg // lh-small.jpg
//========================================================== //==========================================================
$this->chars['h'][0]= 677 ; $this->chars['h'][0]= 677 ;
$this->chars['h'][1]= $this->chars['h'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAIDBAUGB//EACwQAAIBAwMCBQIHAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAIDBAUGB//EACwQAAIBAwMCBQIHAAAAAAAA'.
'AAECAwQFEQAGEiExExQiQVEVggcyU2GRocH/xAAXAQADAQAAAAAAAAAAAAAAAAAAAwQB/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQAC'. 'AAECAwQFEQAGEiExExQiQVEVggcyU2GRocH/xAAXAQADAQAAAAAAAAAAAAAAAAAAAwQB/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQAC'.
'AyEyMf/aAAwDAQACEQMRAD8A6DZb95q9bmpK6ieOCzNHJTxmE+NMhQ5fr1fLq3Ejvkak2e7ipiFsqb3R0m4qkPPJRiRXenU9VjKE'. 'AyEyMf/aAAwDAQACEQMRAD8A6DZb95q9bmpK6ieOCzNHJTxmE+NMhQ5fr1fLq3Ejvkak2e7ipiFsqb3R0m4qkPPJRiRXenU9VjKE'.
'5JVcA9R7nWc3/BUbfoKTdO3VRXhpjbZ2D8Rwk6RyZH6chB+46m7i2hDYtgA2ePlV2VkuKysoLzzRnlIScZJZeeevvjtrX7LK2rp7'. '5JVcA9R7nWc3/BUbfoKTdO3VRXhpjbZ2D8Rwk6RyZH6chB+46m7i2hDYtgA2ePlV2VkuKysoLzzRnlIScZJZeeevvjtrX7LK2rp7'.
'tTwwJ9WjhILDrTKnIdMEDl2+P80aVdJZb1QW+vgqENLPH4sBCDLIwUgnOf4GjVvDnLgUk79T81voqjb8NnuUx8pVRCiEaYUSuynl'. 'tTwwJ9WjhILDrTKnIdMEDl2+P80aVdJZb1QW+vgqENLPH4sBCDLIwUgnOf4GjVvDnLgUk79T81voqjb8NnuUx8pVRCiEaYUSuynl'.
'jHU9mOfnOoOx6hqz8PrbNdfEkMUXg1LSM3rKOUywJ7YAJ1ZTWmSpvdvlaVTDSUzJAhH5ZJBgv0x2RSAPlz21WXqoet3ba9nuW8n4'. 'jHU9mOfnOoOx6hqz8PrbNdfEkMUXg1LSM3rKOUywJ7YAJ1ZTWmSpvdvlaVTDSUzJAhH5ZJBgv0x2RSAPlz21WXqoet3ba9nuW8n4'.
'Jr6qTPqnUNxSM/f6mPvxA9zqJnExTbR+h0nkhVu1uE8j0UBRQ9PGxBKFjnkAScdsDp10a0lc7z0tI7Y5YYN+5GAf7GjVXF4Icj3f'. 'Jr6qTPqnUNxSM/f6mPvxA9zqJnExTbR+h0nkhVu1uE8j0UBRQ9PGxBKFjnkAScdsDp10a0lc7z0tI7Y5YYN+5GAf7GjVXF4Icj3f'.
'/9k=' ; '/9k=' ;
   
   
//========================================================== //==========================================================
// ld-small.jpg // ld-small.jpg
//========================================================== //==========================================================
$this->chars['d'][0]= 681 ; $this->chars['d'][0]= 681 ;
$this->chars['d'][1]= $this->chars['d'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFBgH/xAAsEAABAwMEAAQFBQAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFBgH/xAAsEAABAwMEAAQFBQAAAAAAAAAB'.
'AgMEBQYRABIhMQcTI0EUMlFhkRgicaGx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgEA/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECETH/'. 'AgMEBQYRABIhMQcTI0EUMlFhkRgicaGx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgEA/8QAGBEBAQEBAQAAAAAAAAAAAAAAAAECETH/'.
'2gAMAwEAAhEDEQA/ALUhp6h3W/X63UlypbhCY0WMjLqGzwDtPCfv/WtealNpVInuVBBqCogcdbU36YUkAkJWVHG8YPXBxxzxqPcN'. '2gAMAwEAAhEDEQA/ALUhp6h3W/X63UlypbhCY0WMjLqGzwDtPCfv/WtealNpVInuVBBqCogcdbU36YUkAkJWVHG8YPXBxxzxqPcN'.
'YtWyWnIlUeW05VEOAvrCnnSkftK1H5lKJPHsMDoDUWq+KdrSbIqsalVsImiEtLUZ2MU71bcYJWkhZ/36ayLHhi/IXZVOmzKqp5uU'. 'YtWyWnIlUeW05VEOAvrCnnSkftK1H5lKJPHsMDoDUWq+KdrSbIqsalVsImiEtLUZ2MU71bcYJWkhZ/36ayLHhi/IXZVOmzKqp5uU'.
'688hTyjuGVEFJKvoQesD86NL2jGZp1EoLDSmk+ZAQ8d7oPzp3YGesFWMfxo1YGvSzLsT9QExVX8phTlMaFOExAJIBGQjJwCcL+/e'. '688hTyjuGVEFJKvoQesD86NL2jGZp1EoLDSmk+ZAQ8d7oPzp3YGesFWMfxo1YGvSzLsT9QExVX8phTlMaFOExAJIBGQjJwCcL+/e'.
'rd+W7GuO0Kw05CQ6+ww69Gfdb2kFIKk7DgEkjgnr86rXRa9HuyP8LV4SH0sIBbWFFDiFEgDaocgdkjo8ccay0qw7ut5nyrcviQqC'. 'rd+W7GuO0Kw05CQ6+ww69Gfdb2kFIKk7DgEkjgnr86rXRa9HuyP8LV4SH0sIBbWFFDiFEgDaocgdkjo8ccay0qw7ut5nyrcviQqC'.
'slsRKo0HwlODkBRzxj2AGoXTtpzIdQ8MbffUChz4NCPRaClAo9Mn6c7T3o13wytmo0K05VIqkiPJbizFiMWs4CTgnIIHOST796NL'. 'slsRKo0HwlODkBRzxj2AGoXTtpzIdQ8MbffUChz4NCPRaClAo9Mn6c7T3o13wytmo0K05VIqkiPJbizFiMWs4CTgnIIHOST796NL'.
'Ia1JX//Z' ; 'Ia1JX//Z' ;
   
//========================================================== //==========================================================
// d8-small.jpg // d8-small.jpg
//========================================================== //==========================================================
$this->chars['8'][0]= 694 ; $this->chars['8'][0]= 694 ;
$this->chars['8'][1]= $this->chars['8'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'.
'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'. 'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'.
'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'. 'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'.
'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'. 'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'.
'44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'. '44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'.
'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'. 'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'.
'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'. 'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'.
'EylmLHQltptPZKQOBo1FzH//2Q==' ; 'EylmLHQltptPZKQOBo1FzH//2Q==' ;
   
//========================================================== //==========================================================
// lz-small.jpg // lz-small.jpg
//========================================================== //==========================================================
$this->chars['z'][0]= 690 ; $this->chars['z'][0]= 690 ;
$this->chars['z'][1]= $this->chars['z'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgAHA//EACsQAAEDAwQBAwIHAAAAAAAAAAEC'. 'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgAHA//EACsQAAEDAwQBAwIHAAAAAAAAAAEC'.
'AwQFESEABhIxBxMiQVFxCCM0UmGRof/EABYBAQEBAAAAAAAAAAAAAAAAAAECAP/EABgRAAMBAQAAAAAAAAAAAAAAAAABEVEC/9oA'. 'AwQFESEABhIxBxMiQVFxCCM0UmGRof/EABYBAQEBAAAAAAAAAAAAAAAAAAECAP/EABgRAAMBAQAAAAAAAAAAAAAAAAABEVEC/9oA'.
'DAMBAAIRAxEAPwBTWfLu1KXXZDbM4uewNvLajlwhaCbBAwDe5uehYd3xm6t6bi3jvulwqc7KgxXZZeYQLNLeF73WRg4HEdgfzrSa'. 'DAMBAAIRAxEAPwBTWfLu1KXXZDbM4uewNvLajlwhaCbBAwDe5uehYd3xm6t6bi3jvulwqc7KgxXZZeYQLNLeF73WRg4HEdgfzrSa'.
'P45pNEkznITDc9ypLShtyWhJDJyXC2qxJHZvjoZOjyVv1v8AESt6FFS4ijxvTLbawEApSccrYHJf0+OtJMQ2rNXk7GZMufJgJjTH'. 'P45pNEkznITDc9ypLShtyWhJDJyXC2qxJHZvjoZOjyVv1v8AESt6FFS4ijxvTLbawEApSccrYHJf0+OtJMQ2rNXk7GZMufJgJjTH'.
'Un9M4qzxT7hyCiThIyRnPXWrRvyLElVBUF6vlhl0lwRYCFKcQhAtyWpVhyWTx+w++rUvp4EWjOvbniUOnVatcS43BYDbJSPZyIBw'. 'Un9M4qzxT7hyCiThIyRnPXWrRvyLElVBUF6vlhl0lwRYCFKcQhAtyWpVhyWTx+w++rUvp4EWjOvbniUOnVatcS43BYDbJSPZyIBw'.
'ejclIx+3Wa+J63T6DQanuGszI0eZVJJV60p0Jum5GEi6le7l0PjvSjyRsaTvJqI1BqhhR46ksuMrQVJcUSEoUbHNr/7o7C8L7eiz'. 'ejclIx+3Wa+J63T6DQanuGszI0eZVJJV60p0Jum5GEi6le7l0PjvSjyRsaTvJqI1BqhhR46ksuMrQVJcUSEoUbHNr/7o7C8L7eiz'.
'4lLlyJk2cEqW+6V+m0AE9ISLnsj5+O9UhsFK92bZZqb9SRu9p2c4A0OCEqDbYAJSlJwAVZv3fBvbFrg/462btlhuS1RG5nL8pYkq'. '4lLlyJk2cEqW+6V+m0AE9ISLnsj5+O9UhsFK92bZZqb9SRu9p2c4A0OCEqDbYAJSlJwAVZv3fBvbFrg/462btlhuS1RG5nL8pYkq'.
'KrnsKH06I/rVrQKkf//Z' ; 'KrnsKH06I/rVrQKkf//Z' ;
   
//========================================================== //==========================================================
// d4-small.jpg // d4-small.jpg
//========================================================== //==========================================================
$this->chars['4'][0]= 643 ; $this->chars['4'][0]= 643 ;
$this->chars['4'][1]= $this->chars['4'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'.
'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'. 'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'.
'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'. 'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'.
'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'. 'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'.
'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'. 'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'.
'27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'. '27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'.
'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ; 'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ;
   
//========================================================== //==========================================================
// lv-small.jpg // lv-small.jpg
//========================================================== //==========================================================
$this->chars['v'][0]= 648 ; $this->chars['v'][0]= 648 ;
$this->chars['v'][1]= $this->chars['v'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAKBAAAQQBAwMEAgMAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQDBQYH/8QAKBAAAQQBAwMEAgMAAAAAAAAA'.
'AQIDBBEFAAYhEzFBEhQiYQdRFTKB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAERIf/aAAwD'. 'AQIDBBEFAAYhEzFBEhQiYQdRFTKB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAERIf/aAAwD'.
'AQACEQMRAD8A6Ngt1SZ4yrYgrecgTFsFJA9aGwAUrUaF2D2Avjzq6CIjiBPkB9bwQVIkIYIDae/wq+P9N+dY4SGMf+Txlev7KBmY'. 'AQACEQMRAD8A6Ngt1SZ4yrYgrecgTFsFJA9aGwAUrUaF2D2Avjzq6CIjiBPkB9bwQVIkIYIDae/wq+P9N+dY4SGMf+Txlev7KBmY'.
'PoadKRy4zxSgRxaTwO/x09u7KPYnasmHjlsyFZZXt4K23ezjvBpNGgLUrvXfVZyLLbWambiwEbKvvxYAkeotNlIJW2FEJWb7WBda'. 'PoadKRy4zxSgRxaTwO/x09u7KPYnasmHjlsyFZZXt4K23ezjvBpNGgLUrvXfVZyLLbWambiwEbKvvxYAkeotNlIJW2FEJWb7WBda'.
'NSQI0fHYyJjkrjKRDZQwnpQ1vgBIr+w8+a+9GocZr8iKkuY1eXhsKH8U8iZE9BHz6ZHUc48UfSPqzqH3kfeO9kTTDQYGGietpTaO'. 'NSQI0fHYyJjkrjKRDZQwnpQ1vgBIr+w8+a+9GocZr8iKkuY1eXhsKH8U8iZE9BHz6ZHUc48UfSPqzqH3kfeO9kTTDQYGGietpTaO'.
'shyW6AocpHNIrv8AvWzk9BUSdPdYS4BcRlomkhIV6KP0VE39V+tU2wdlRMHtZUB8NuTQ+51X27+Kr46ZPIAFV540D8zeLsJ5LMHa'. 'shyW6AocpHNIrv8AvWzk9BUSdPdYS4BcRlomkhIV6KP0VE39V+tU2wdlRMHtZUB8NuTQ+51X27+Kr46ZPIAFV540D8zeLsJ5LMHa'.
'ubmMBCVJdjx0pRyLoWR4I8aNIQ8BvZMNtMTeUcsptKfc4tC1gAkCyFC+K0aJtf/Z' ; 'ubmMBCVJdjx0pRyLoWR4I8aNIQ8BvZMNtMTeUcsptKfc4tC1gAkCyFC+K0aJtf/Z' ;
   
//========================================================== //==========================================================
// lk-small.jpg // lk-small.jpg
//========================================================== //==========================================================
$this->chars['k'][0]= 680 ; $this->chars['k'][0]= 680 ;
$this->chars['k'][1]= $this->chars['k'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBAMH/8QALhAAAQMDAwIEBAcAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABUDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBAMH/8QALhAAAQMDAwIEBAcAAAAAAAAA'.
'AQIDBAUREgAGITFBEyIyYQcVUYEUIzNicZHx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEE/8QAGxEAAwACAwAAAAAAAAAAAAAAAAEC'. 'AQIDBAUREgAGITFBEyIyYQcVUYEUIzNicZHx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEE/8QAGxEAAwACAwAAAAAAAAAAAAAAAAEC'.
'AxESMeH/2gAMAwEAAhEDEQA/APVK/V36dU6NSJDTT8esPLiqfK8S2cCoeTkKvZQ6jm2ldSqKqbu+OgMOvSX3m4UBrLnDlbqiefKl'. 'AxESMeH/2gAMAwEAAhEDEQA/APVK/V36dU6NSJDTT8esPLiqfK8S2cCoeTkKvZQ6jm2ldSqKqbu+OgMOvSX3m4UBrLnDlbqiefKl'.
'Nzz2x1m+IwNP27CkJQ7JkR6rCkMJbP5jp8S2CPfkgD6H+dJ6Ca0nerr+64rTNSqMYrg+C9mmOwhVpDfsuxSbi97DmybaoZeQ5jTl'. 'Nzz2x1m+IwNP27CkJQ7JkR6rCkMJbP5jp8S2CPfkgD6H+dJ6Ca0nerr+64rTNSqMYrg+C9mmOwhVpDfsuxSbi97DmybaoZeQ5jTl'.
'PEp18JTIfeW3kq3ly4H26aNZqvTWZsjFcZTsVtSg0G8Rio+vr2vb7g6NLPRnuXy8F+8kl+obUh4KXJdqSJJQnohlkZqJPYBXh3P+'. 'PEp18JTIfeW3kq3ly4H26aNZqvTWZsjFcZTsVtSg0G8Rio+vr2vb7g6NLPRnuXy8F+8kl+obUh4KXJdqSJJQnohlkZqJPYBXh3P+'.
'a4b5Hyp6k1bO7sOotPyXkj9NlwFl0ewstJA9ifrqkVSmET4csoS7UTHXFQ+6SQlskKUMb/tH9ddLVUmS7DqdBqD7U6OsqfS46jzl'. 'a4b5Hyp6k1bO7sOotPyXkj9NlwFl0ewstJA9ifrqkVSmET4csoS7UTHXFQ+6SQlskKUMb/tH9ddLVUmS7DqdBqD7U6OsqfS46jzl'.
'hQ5bXb1K9Scuybdxo2OTu92dwSZkWn0Sb8viQWyn8Qq5D6ifSLd0BIv7q0arTBRSKPToMZbi2GWylsvLK148Wue/XRrRjxOpT2R2'. 'hQ5bXb1K9Scuybdxo2OTu92dwSZkWn0Sb8viQWyn8Qq5D6ifSLd0BIv7q0arTBRSKPToMZbi2GWylsvLK148Wue/XRrRjxOpT2R2'.
'k9aP/9k=' ; 'k9aP/9k=' ;
   
//========================================================== //==========================================================
// lr-small.jpg // lr-small.jpg
//========================================================== //==========================================================
$this->chars['r'][0]= 681 ; $this->chars['r'][0]= 681 ;
$this->chars['r'][1]= $this->chars['r'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAGgAAAgIDAAAAAAAAAAAAAAAAAAYCBQMEB//EAC4QAAICAQIFAgMJAQAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABYDASIAAhEBAxEB/8QAGgAAAgIDAAAAAAAAAAAAAAAAAAYCBQMEB//EAC4QAAICAQIFAgMJAQAAAAAA'.
'AAECAwQRBQYAEiExQQdRFGFxEyIyM0JSYoGC8P/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/EABcRAQEBAQAAAAAAAAAAAAAAAAAB'. 'AAECAwQRBQYAEiExQQdRFGFxEyIyM0JSYoGC8P/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/EABcRAQEBAQAAAAAAAAAAAAAAAAAB'.
'EUH/2gAMAwEAAhEDEQA/AOs0ZdETU54Gt1INSmlPJEsyo7J+jlXPUYBPY9c+eE/dO9tY0a7ren6BVrW7VJTZtW5kZkjXkBSIKveQ'. 'EUH/2gAMAwEAAhEDEQA/AOs0ZdETU54Gt1INSmlPJEsyo7J+jlXPUYBPY9c+eE/dO9tY0a7ren6BVrW7VJTZtW5kZkjXkBSIKveQ'.
'gHp0AAJ4w+q2hVdT2Md0h46+saS4mr3EUK0gWTAB+vQj2PboeL/ZVOqmhaZVjkFmxdC6tctt3tM2G5/7bAx4C4+qxiWwd3prWzKe'. 'gHp0AAJ4w+q2hVdT2Md0h46+saS4mr3EUK0gWTAB+vQj2PboeL/ZVOqmhaZVjkFmxdC6tctt3tM2G5/7bAx4C4+qxiWwd3prWzKe'.
'r3IBAth5OYxozKsgc8y4GTgnJB9uncdTi6tXq2140rRVM13JMEMAVAg7sMdBjJB/18uDgRO9R2Oo6FX2vShkFzURFUq1whIj+8DI'. 'r3IBAth5OYxozKsgc8y4GTgnJB9uncdTi6tXq2140rRVM13JMEMAVAg7sMdBjJB/18uDgRO9R2Oo6FX2vShkFzURFUq1whIj+8DI'.
'7EdAFjXv7MeNb0kuStsFEmIaajZaos2fy2Q4VGH7SGxn+Rzw9yMLOm/FzRhZazmOTkP4grYyD3B8j2PTyeFfZ+z7G3BeSS8lmprl'. '7EdAFjXv7MeNb0kuStsFEmIaajZaos2fy2Q4VGH7SGxn+Rzw9yMLOm/FzRhZazmOTkP4grYyD3B8j2PTyeFfZ+z7G3BeSS8lmprl'.
'2K2qcnK0Z5S8gPjrgAY8cNEWmq7u23pEos6/Zji+Kd0rLLGWwseA3joeZj/w4OET1g0vlmrWV+ydFnkUxSgsvM4V+YYIwfHz6cHB'. '2K2qcnK0Z5S8gPjrgAY8cNEWmq7u23pEos6/Zji+Kd0rLLGWwseA3joeZj/w4OET1g0vlmrWV+ydFnkUxSgsvM4V+YYIwfHz6cHB'.
'ZeKZ1//Z' ; 'ZeKZ1//Z' ;
   
//========================================================== //==========================================================
// lg-small.jpg // lg-small.jpg
//========================================================== //==========================================================
$this->chars['g'][0]= 655 ; $this->chars['g'][0]= 655 ;
$this->chars['g'][1]= $this->chars['g'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQCBQYH/8QAJxAAAQQBAwQCAgMAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQCBQYH/8QAJxAAAQQBAwQCAgMAAAAAAAAA'.
'AQIDBBEFAAYhBxIxQRNhcYEiQlH/xAAYAQACAwAAAAAAAAAAAAAAAAACAwABBP/EABkRAAMBAQEAAAAAAAAAAAAAAAABAhEhIv/a'. 'AQIDBBEFAAYhBxIxQRNhcYEiQlH/xAAYAQACAwAAAAAAAAAAAAAAAAACAwABBP/EABkRAAMBAQEAAAAAAAAAAAAAAAABAhEhIv/a'.
'AAwDAQACEQMRAD8AayO4t6bq3hmMHtxyLi4OKeKH5jyASiiQCCQeTRNAeB61FrBb+jTGpLO+BMW24EFMhkhpQru8m7B/H70x09Yi'. 'AAwDAQACEQMRAD8AayO4t6bq3hmMHtxyLi4OKeKH5jyASiiQCCQeTRNAeB61FrBb+jTGpLO+BMW24EFMhkhpQru8m7B/H70x09Yi'.
'q3nv/vLfwpnJ7UNkqSRbngf2ofWkpXV7brymC2malLfagurjW0aHk89xPJ9cX9aprURHWbYEaMHHEBfwpv8AnXPk+/8AdGqGJOxO'. 'q3nv/vLfwpnJ7UNkqSRbngf2ofWkpXV7brymC2malLfagurjW0aHk89xPJ9cX9aprURHWbYEaMHHEBfwpv8AnXPk+/8AdGqGJOxO'.
'4YbOSxK4y4boIStUWysgkEmxY54r60aOI8oTV9MHtjJwunPUbO46WWo0HLlD8KY4goboFVoquOVEVwLT963WdnxYfT6ZJyz0JvHm'. '4YbOSxK4y4boIStUWysgkEmxY54r60aOI8oTV9MHtjJwunPUbO46WWo0HLlD8KY4goboFVoquOVEVwLT963WdnxYfT6ZJyz0JvHm'.
'KvtaSkW4tYNVSqKiTwB+fw5n9sY/cuOXCzDDcluyW3Ckd7V+0n0eNZTH9DdouFalHIOJBUhtDki0pNV3UALo81ehG6IdKjPZ6d47'. 'KvtaSkW4tYNVSqKiTwB+fw5n9sY/cuOXCzDDcluyW3Ckd7V+0n0eNZTH9DdouFalHIOJBUhtDki0pNV3UALo81ehG6IdKjPZ6d47'.
'4ywltanVJvuJI+RQs/sHRqy2r003JhsImEc/CUyhxRZBjKV2oJ8eRXNmufPnRo1WIz3DdNn/2Q==' ; '4ywltanVJvuJI+RQs/sHRqy2r003JhsImEc/CUyhxRZBjKV2oJ8eRXNmufPnRo1WIz3DdNn/2Q==' ;
   
//========================================================== //==========================================================
// lc-small.jpg // lc-small.jpg
//========================================================== //==========================================================
$this->chars['c'][0]= 629 ; $this->chars['c'][0]= 629 ;
$this->chars['c'][1]= $this->chars['c'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBwID/8QALRAAAgICAQIEBAYDAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAUGBwID/8QALRAAAgICAQIEBAYDAAAAAAAA'.
'AQIDBAURACExBhIiQRMVUWEHMkJScYFykaH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/xAAXEQEBAQEAAAAAAAAAAAAAAAAAATER'. 'AQIDBAURACExBhIiQRMVUWEHMkJScYFykaH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/xAAXEQEBAQEAAAAAAAAAAAAAAAAAATER'.
'/9oADAMBAAIRAxEAPwDcoGkmiT4Q8kWvzuPU38D2/v8A1zwrCFayq1qTaFk2H7aJHt05MeMvENzC4upDWkjW9kJXiricAJCigvJN'. '/9oADAMBAAIRAxEAPwDcoGkmiT4Q8kWvzuPU38D2/v8A1zwrCFayq1qTaFk2H7aJHt05MeMvENzC4upDWkjW9kJXiricAJCigvJN'.
'IB1IVQT5frrv24twPgunk6a288crbklUSJNNdnSTZ2STHHqOP/Eb17njdZtAoqwEvrEiGVyG117/AG6HhyV8H1sljMldoxXTksGC'. 'IB1IVQT5frrv24twPgunk6a288crbklUSJNNdnSTZ2STHHqOP/Eb17njdZtAoqwEvrEiGVyG117/AG6HhyV8H1sljMldoxXTksGC'.
'zV7M0oaWGQOVeGQ92I6EMR22D11w4LmEPjaOL51iL8ssc9Z69zHtZkYCGGeQK0ez2UEoU39wCeX1S/LLiEt+mPSbMLxsGVv2kEjR'. 'zV7M0oaWGQOVeGQ92I6EMR22D11w4LmEPjaOL51iL8ssc9Z69zHtZkYCGGeQK0ez2UEoU39wCeX1S/LLiEt+mPSbMLxsGVv2kEjR'.
'305xkaEV/GTULMUT1LD/AAGh8gIZS2jv+vpybb8NMIb0dVLWYWgiiU0vmMphOj6V0TvQI3rfsON1E6dYjGtisa0F1mAWR2NhG0WZ'. '305xkaEV/GTULMUT1LD/AAGh8gIZS2jv+vpybb8NMIb0dVLWYWgiiU0vmMphOj6V0TvQI3rfsON1E6dYjGtisa0F1mAWR2NhG0WZ'.
'3Ls3TqNs5Hc9h23w49NWL9K+Q/VD5T/zhwPH/9k=' ; '3Ls3TqNs5Hc9h23w49NWL9K+Q/VD5T/zhwPH/9k=' ;
   
//========================================================== //==========================================================
// d7-small.jpg // d7-small.jpg
//========================================================== //==========================================================
$this->chars['7'][0]= 658 ; $this->chars['7'][0]= 658 ;
$this->chars['7'][1]= $this->chars['7'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'.
'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'. 'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'.
'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'. 'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'.
'19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'. '19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'.
'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'. 'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'.
'8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'. '8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'.
'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ; 'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ;
   
//========================================================== //==========================================================
// ly-small.jpg // ly-small.jpg
//========================================================== //==========================================================
$this->chars['y'][0]= 672 ; $this->chars['y'][0]= 672 ;
$this->chars['y'][1]= $this->chars['y'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQGBQf/xAArEAABAwMEAQIFBQAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQGBQf/xAArEAABAwMEAQIFBQAAAAAAAAAB'.
'AgMEBREhAAYSEzEHIhQkQVGxQmFxgaH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAQL/xAAeEQEAAgEEAwAAAAAAAAAAAAABABECAxIh'. 'AgMEBREhAAYSEzEHIhQkQVGxQmFxgaH/xAAWAQEBAQAAAAAAAAAAAAAAAAADAQL/xAAeEQEAAgEEAwAAAAAAAAAAAAABABECAxIh'.
'MUGR8P/aAAwDAQACEQMRAD8Ar3tys07dVHohemz5dWQ7fk91MsA3IIRY8rkKFySceTqw3JVV0KhyKw+0C1CQp9aUOFSiAk4AIAvn'. 'MUGR8P/aAAwDAQACEQMRAD8Ar3tys07dVHohemz5dWQ7fk91MsA3IIRY8rkKFySceTqw3JVV0KhyKw+0C1CQp9aUOFSiAk4AIAvn'.
'76xtz0ioVvbcJ6msx2JtOfZmw1PKI5LQcJNh7UqBKcn6+NRfqPu6s1fYc6GxSJsRfWDUVSGA22ygEckJWSexRNgOP0udXzDKOJ0I'. '76xtz0ioVvbcJ6msx2JtOfZmw1PKI5LQcJNh7UqBKcn6+NRfqPu6s1fYc6GxSJsRfWDUVSGA22ygEckJWSexRNgOP0udXzDKOJ0I'.
'yo62mHm25Sy80l1Z4lSgpQvZRGLgWwPGjTjbchyLH+Ejx22EtJSgO8kki3kADA/nOjWjGzv73CyQZjUWNVp7bNSrj7qJDqflqUlQ'. 'yo62mHm25Sy80l1Z4lSgpQvZRGLgWwPGjTjbchyLH+Ejx22EtJSgO8kki3kADA/nOjWjGzv73CyQZjUWNVp7bNSrj7qJDqflqUlQ'.
'DMds24l3HvcNr3Pi9gME6T9WWVsemdYWswwC2lPta4m5WMA3OdUExCmozUJD6g84ntMjrHIFBTdQz5yLDx/WDNytpwW6nAkViqVe'. 'DMds24l3HvcNr3Pi9gME6T9WWVsemdYWswwC2lPta4m5WMA3OdUExCmozUJD6g84ntMjrHIFBTdQz5yLDx/WDNytpwW6nAkViqVe'.
'uvmXdlme6n4dCwlRBKEgA2tj99QG7Ilncp5QqpU31PMsJ6x7A32f6SPxo0hPVCD45oVyKf0MtgeT97/nRrO7UOCFla3tn//Z' ; 'uvmXdlme6n4dCwlRBKEgA2tj99QG7Ilncp5QqpU31PMsJ6x7A32f6SPxo0hPVCD45oVyKf0MtgeT97/nRrO7UOCFla3tn//Z' ;
   
//========================================================== //==========================================================
// d3-small.jpg // d3-small.jpg
//========================================================== //==========================================================
$this->chars['3'][0]= 662 ; $this->chars['3'][0]= 662 ;
$this->chars['3'][1]= $this->chars['3'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'. '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'. 'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'.
'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'. 'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'.
'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'. 'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'.
'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'. 'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'.
'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'. 'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'.
'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'. 'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'.
'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ; 'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ;
   
//========================================================== //==========================================================
// ln-small.jpg // ln-small.jpg
//========================================================== //==========================================================
$this->chars['n'][0]= 643 ; $this->chars['n'][0]= 643 ;
$this->chars['n'][1]= $this->chars['n'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGwAAAgEFAAAAAAAAAAAAAAAAAAYCAQMEBQf/xAAtEAACAQMCBAUCBwAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGwAAAgEFAAAAAAAAAAAAAAAAAAYCAQMEBQf/xAAtEAACAQMCBAUCBwAAAAAA'.
'AAABAgMEBREAIQYSE0EHIjFRcWGRIzIzQoGCwf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAP/EABkRAQEBAQEBAAAAAAAAAAAAAAEA'. 'AAABAgMEBREAIQYSE0EHIjFRcWGRIzIzQoGCwf/EABYBAQEBAAAAAAAAAAAAAAAAAAMEAP/EABkRAQEBAQEBAAAAAAAAAAAAAAEA'.
'AhEhUf/aAAwDAQACEQMRAD8A6FR3p7v4oV9rlkMQsjL00RyOss0KkFxnDcrc2PbI1NOJKyTjW+W5OmKeA0UEJx5meRZS2/8AUfbS'. 'AhEhUf/aAAwDAQACEQMRAD8A6FR3p7v4oV9rlkMQsjL00RyOss0KkFxnDcrc2PbI1NOJKyTjW+W5OmKeA0UEJx5meRZS2/8AUfbS'.
'LVGS1+K16vCzfiR3GmoqqXGyxz06hWPsFlVMfOmq1iNvE69KjBYo3oJMZ3GKeYYPxg/fW+xzZX1FLQyxwSTcpWNceu4G3+aNSmpY'. 'LVGS1+K16vCzfiR3GmoqqXGyxz06hWPsFlVMfOmq1iNvE69KjBYo3oJMZ3GKeYYPxg/fW+xzZX1FLQyxwSTcpWNceu4G3+aNSmpY'.
'qmQzzwh2k8yhv2r2H23/AJ0aoy+EWh7I1ntacR3PxDtEzhjWy0wkkIwYmanU5GO6sNh7rrU8AVdTceNbhDXxNHUQvS0tZ3DzwxVA'. 'qmQzzwh2k8yhv2r2H23/AJ0aoy+EWh7I1ntacR3PxDtEzhjWy0wkkIwYmanU5GO6sNh7rrU8AVdTceNbhDXxNHUQvS0tZ3DzwxVA'.
'fB7hj59/XJ08cPWaKj4gvlwSQiG7dCboqvLy9NOmQT9SM7ayJrBa6K5V91hjlWorp4JGUOAglRSiMMDb82/vgaBGTpVvtNUVtyJg'. 'fB7hj59/XJ08cPWaKj4gvlwSQiG7dCboqvLy9NOmQT9SM7ayJrBa6K5V91hjlWorp4JGUOAglRSiMMDb82/vgaBGTpVvtNUVtyJg'.
'5+WNAh5ZCu/r2+dGrgq0pi0DhmlRsSSAfqMd+b6ZyNu3po1Rk1yNBe3/2Q==' ; '5+WNAh5ZCu/r2+dGrgq0pi0DhmlRsSSAfqMd+b6ZyNu3po1Rk1yNBe3/2Q==' ;
   
//========================================================== //==========================================================
// lu-small.jpg // lu-small.jpg
//========================================================== //==========================================================
$this->chars['u'][0]= 671 ; $this->chars['u'][0]= 671 ;
$this->chars['u'][1]= $this->chars['u'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYDBAUH/8QAJRAAAQQBAwQDAQEAAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAYDBAUH/8QAJRAAAQQBAwQDAQEAAAAAAAAA'.
'AQIDBBEFAAYhBxMxYRJBURSB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAD/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQARITFBAv/aAAwD'. 'AQIDBBEFAAYhBxMxYRJBURSB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAD/8QAGhEBAQEAAwEAAAAAAAAAAAAAAQARITFBAv/aAAwD'.
'AQACEQMRAD8A6dLkQmJzu3WVtHIqjf0duKFNuBr5UTQ45F1R8/XI1PMmsYoJyjhS9iI7BKHeKjkXZVXqhyLHP+rrHeR1pZlx1W1M'. 'AQACEQMRAD8A6dLkQmJzu3WVtHIqjf0duKFNuBr5UTQ45F1R8/XI1PMmsYoJyjhS9iI7BKHeKjkXZVXqhyLHP+rrHeR1pZlx1W1M'.
'wTiW0ukkrS28nn5fV2SPPFfurHUKQhzYG7pLYKEfyBhaSOS7dG/YCki/uvWn3LPDOJrwa4kyEzOYeakqkpC3Hk0bNePQHgDRpchY'. 'wTiW0ukkrS28nn5fV2SPPFfurHUKQhzYG7pLYKEfyBhaSOS7dG/YCki/uvWn3LPDOJrwa4kyEzOYeakqkpC3Hk0bNePQHgDRpchY'.
'leIZwzUWauKtuPctTSUlCAUmrBHIKuAPV/ujQsmHdm7hya43UbbD3ZVElOQJsdTS6IQaQUqBHCk8E2Pocgam6oYwObHy0Zm0oi45'. 'leIZwzUWauKtuPctTSUlCAUmrBHIKuAPV/ujQsmHdm7hya43UbbD3ZVElOQJsdTS6IQaQUqBHCk8E2Pocgam6oYwObHy0Zm0oi45'.
'T1KBPdpV2f0pom/1Ws7cmPazu98Ltvcq3VzRHfehz8a4pirFEKRZo8eQT+eCdWYfS/b+WYnxpbuVcDRMdHcyTqg2fiAfiLoi+Rf+'. 'T1KBPdpV2f0pom/1Ws7cmPazu98Ltvcq3VzRHfehz8a4pirFEKRZo8eQT+eCdWYfS/b+WYnxpbuVcDRMdHcyTqg2fiAfiLoi+Rf+'.
'jT7Xc74HtOYnHyUOh8yWUvKeHhy0CiPVUAPoDRrm+OeznTva6lzsyMjCYbbaiNJjJSWElagD5tRpNUSALFeNGoOCH7Bv/9k=' ; 'jT7Xc74HtOYnHyUOh8yWUvKeHhy0CiPVUAPoDRrm+OeznTva6lzsyMjCYbbaiNJjJSWElagD5tRpNUSALFeNGoOCH7Bv/9k=' ;
   
//========================================================== //==========================================================
// lw-small.jpg // lw-small.jpg
//========================================================== //==========================================================
$this->chars['w'][0]= 673 ; $this->chars['w'][0]= 673 ;
$this->chars['w'][1]= $this->chars['w'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYDBAX/xAAtEAACAQMDAgMHBQAAAAAAAAAB'. 'MjIyMjIyMjL/wAARCAAeABcDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYDBAX/xAAtEAACAQMDAgMHBQAAAAAAAAAB'.
'AgMEBREABhIhMRMUQRUiIzJRYZEWNIGx0f/EABYBAQEBAAAAAAAAAAAAAAAAAAABA//EABoRAAICAwAAAAAAAAAAAAAAAAABERIh'. 'AgMEBREABhIhMRMUQRUiIzJRYZEWNIGx0f/EABYBAQEBAAAAAAAAAAAAAAAAAAABA//EABoRAAICAwAAAAAAAAAAAAAAAAABERIh'.
'MVH/2gAMAwEAAhEDEQA/AHXbV13ZLu6t2/uaa1JijWopVp4XUTKSAXRyc+6ehBGeoPbTSlwpql0K3GneqpZViqUhI5JzGMEZJGeh'. 'MVH/2gAMAwEAAhEDEQA/AHXbV13ZLu6t2/uaa1JijWopVp4XUTKSAXRyc+6ehBGeoPbTSlwpql0K3GneqpZViqUhI5JzGMEZJGeh'.
'GlXfaFILDf7FQzXC426rDLTojs8sLqVkXBGcfKf40twWbdWzZY75R0s90ul3jPtKjVMJDNn4DDp8iEhW+wJ1WZG2KWt3Lv26U1tv'. 'GlXfaFILDf7FQzXC426rDLTojs8sLqVkXBGcfKf40twWbdWzZY75R0s90ul3jPtKjVMJDNn4DDp8iEhW+wJ1WZG2KWt3Lv26U1tv'.
'92o7PaYkgYUbqVepYlmUBlIwqnB++O2jTDt/bBtth9jcpvEWNGqalZQryTlmeR8jPct6+mNGmRC4a1U13htzVFItB5nA/cyOUVfp'. '92o7PaYkgYUbqVepYlmUBlIwqnB++O2jTDt/bBtth9jcpvEWNGqalZQryTlmeR8jPct6+mNGmRC4a1U13htzVFItB5nA/cyOUVfp'.
'7oz/ALqitJulYJKuqvFsppHALLFb3cp9FBaXr+O51bq0q6i38KK5PDVAAxSzU6SIpz3Kjjn8jUFoS7uFmut1gq17xLFQ+DxOccj8'. '7oz/ALqitJulYJKuqvFsppHALLFb3cp9FBaXr+O51bq0q6i38KK5PDVAAxSzU6SIpz3Kjjn8jUFoS7uFmut1gq17xLFQ+DxOccj8'.
'Rsn+tVpiyJnqv09YfOXu5AycgZZQEhBZjgDBOOgwO/po0sttWHdNzqLruioa4UwmdaC3kYp4IwSvJlBHKQ4OSe3po0qxM6P/2Q==' ; 'Rsn+tVpiyJnqv09YfOXu5AycgZZQEhBZjgDBOOgwO/po0sttWHdNzqLruioa4UwmdaC3kYp4IwSvJlBHKQ4OSe3po0qxM6P/2Q==' ;
   
//========================================================== //==========================================================
// lq-small.jpg // lq-small.jpg
//========================================================== //==========================================================
$this->chars['q'][0]= 671 ; $this->chars['q'][0]= 671 ;
$this->chars['q'][1]= $this->chars['q'][1]=
'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'. '/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'. 'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAcDBAUG/8QAKRAAAQQBBAICAQQDAAAAAAAA'. 'MjIyMjIyMjL/wAARCAAeABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAcDBAUG/8QAKRAAAQQBBAICAQQDAAAAAAAA'.
'AQIDBBEFAAYSIQcxIlETCBQVgSNBYf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oADAMB'. 'AQIDBBEFAAYSIQcxIlETCBQVgSNBYf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oADAMB'.
'AAIRAxEAPwDT3H5Qz+O3LN2vtrF/y86NYLzzVlAABJITQPv2a/17vXMboz3lDEYWPuafNx7CFrS03+2jpK2bs0CUkUa7pRvrUu63'. 'AAIRAxEAPwDT3H5Qz+O3LN2vtrF/y86NYLzzVlAABJITQPv2a/17vXMboz3lDEYWPuafNx7CFrS03+2jpK2bs0CUkUa7pRvrUu63'.
'sr438yv7pLEo4XIK5Kcji0uJUkckm+uQUOVH6GsnyJv7A5vaJwuFdkONLmolgONFH4vioKRXYqyCADXvRMh0yspmZ4jyIEtDTK47'. 'sr438yv7pLEo4XIK5Kcji0uJUkckm+uQUOVH6GsnyJv7A5vaJwuFdkONLmolgONFH4vioKRXYqyCADXvRMh0yspmZ4jyIEtDTK47'.
'aiA0lQUopBJBI/7X9aNT7amRo228e3a31iO3yUzCcdSPiKAIFdCho0TIswZ7GQlO/hlRxBooih1YXzAoKUkX0LPEBX110dJ7zbuv'. 'aiA0lQUopBJBI/7X9aNT7amRo228e3a31iO3yUzCcdSPiKAIFdCho0TIswZ7GQlO/hlRxBooih1YXzAoKUkX0LPEBX110dJ7zbuv'.
'AORpO04cIpmxH23FSEIRwKuNnsdk0o31702XhFMKbuRUZJWP8LTQ6HBCuIB+iVWSR2BXuqK93/hDlvGzEphmG3Ml5JpDi1I7TzNA'. 'AORpO04cIpmxH23FSEIRwKuNnsdk0o31702XhFMKbuRUZJWP8LTQ6HBCuIB+iVWSR2BXuqK93/hDlvGzEphmG3Ml5JpDi1I7TzNA'.
'BYFlPafY+/7LBiv1CYDH4iFDOGySlMR22lFP4wCUpANfL11o1r4bxXlWMNEaE/bqlIbCFl/ANPK5Do/M0VDr2Rf3o0TX/9k=' ; 'BYFlPafY+/7LBiv1CYDH4iFDOGySlMR22lFP4wCUpANfL11o1r4bxXlWMNEaE/bqlIbCFl/ANPK5Do/M0VDr2Rf3o0TX/9k=' ;
   
   
   
} }
} }
   
class AntiSpam { class AntiSpam {
   
private $iData=''; private $iData='';
private $iDD=null; private $iDD=null;
   
function __construct($aData='') { function __construct($aData='') {
$this->iData = $aData; $this->iData = $aData;
$this->iDD = new HandDigits(); $this->iDD = new HandDigits();
} }
   
function Set($aData) { function Set($aData) {
$this->iData = $aData; $this->iData = $aData;
} }
   
function Rand($aLen) { function Rand($aLen) {
$d=''; $d='';
for($i=0; $i < $aLen; ++$i) { for($i=0; $i < $aLen; ++$i) {
if( rand(0,9) < 6 ) { if( rand(0,9) < 6 ) {
// Digits // Digits
$d .= chr( ord('1') + rand(0,8) ); $d .= chr( ord('1') + rand(0,8) );
} }
else { else {
// Letters // Letters
do { do {
$offset = rand(0,25); $offset = rand(0,25);
} while ( $offset==14 ); } while ( $offset==14 );
$d .= chr( ord('a') + $offset ); $d .= chr( ord('a') + $offset );
} }
} }
$this->iData = $d; $this->iData = $d;
return $d; return $d;
} }
   
function Stroke() { function Stroke() {
   
$n=strlen($this->iData); $n=strlen($this->iData);
if( $n==0 ) { if( $n==0 ) {
return false; return false;
} }
   
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
if( $this->iData[$i]==='0' || strtolower($this->iData[$i])==='o') { if( $this->iData[$i]==='0' || strtolower($this->iData[$i])==='o') {
return false; return false;
} }
} }
   
$img = @imagecreatetruecolor($n*$this->iDD->iWidth, $this->iDD->iHeight); $img = @imagecreatetruecolor($n*$this->iDD->iWidth, $this->iDD->iHeight);
if( $img < 1 ) { if( $img < 1 ) {
return false; return false;
} }
   
$start=0; $start=0;
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$dimg = imagecreatefromstring(base64_decode($this->iDD->chars[strtolower($this->iData[$i])][1])); $dimg = imagecreatefromstring(base64_decode($this->iDD->chars[strtolower($this->iData[$i])][1]));
imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $this->iDD->iHeight); imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $this->iDD->iHeight);
$start += imagesx($dimg); $start += imagesx($dimg);
} }
$resimg = @imagecreatetruecolor($start+4, $this->iDD->iHeight+4); $resimg = @imagecreatetruecolor($start+4, $this->iDD->iHeight+4);
if( $resimg < 1 ) { if( $resimg < 1 ) {
return false; return false;
} }
   
imagecopy($resimg,$img,2,2,0,0,$start, $this->iDD->iHeight); imagecopy($resimg,$img,2,2,0,0,$start, $this->iDD->iHeight);
header("Content-type: image/jpeg"); header("Content-type: image/jpeg");
imagejpeg($resimg); imagejpeg($resimg);
return true; return true;
} }
} }
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_BAR.PHP // File: JPGRAPH_BAR.PHP
// Description: Bar plot extension for JpGraph // Description: Bar plot extension for JpGraph
// Created: 2001-01-08 // Created: 2001-01-08
// Ver: $Id: jpgraph_bar.php 1905 2009-10-06 18:00:21Z ljp $ // Ver: $Id: jpgraph_bar.php 1905 2009-10-06 18:00:21Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
require_once('jpgraph_plotband.php'); require_once('jpgraph_plotband.php');
   
// Pattern for Bars // Pattern for Bars
DEFINE('PATTERN_DIAG1',1); DEFINE('PATTERN_DIAG1',1);
DEFINE('PATTERN_DIAG2',2); DEFINE('PATTERN_DIAG2',2);
DEFINE('PATTERN_DIAG3',3); DEFINE('PATTERN_DIAG3',3);
DEFINE('PATTERN_DIAG4',4); DEFINE('PATTERN_DIAG4',4);
DEFINE('PATTERN_CROSS1',5); DEFINE('PATTERN_CROSS1',5);
DEFINE('PATTERN_CROSS2',6); DEFINE('PATTERN_CROSS2',6);
DEFINE('PATTERN_CROSS3',7); DEFINE('PATTERN_CROSS3',7);
DEFINE('PATTERN_CROSS4',8); DEFINE('PATTERN_CROSS4',8);
DEFINE('PATTERN_STRIPE1',9); DEFINE('PATTERN_STRIPE1',9);
DEFINE('PATTERN_STRIPE2',10); DEFINE('PATTERN_STRIPE2',10);
   
//=================================================== //===================================================
// CLASS BarPlot // CLASS BarPlot
// Description: Main code to produce a bar plot // Description: Main code to produce a bar plot
//=================================================== //===================================================
class BarPlot extends Plot { class BarPlot extends Plot {
public $fill=false,$fill_color="lightblue"; // Default is to fill with light blue public $fill=false,$fill_color="lightblue"; // Default is to fill with light blue
public $iPattern=-1,$iPatternDensity=80,$iPatternColor='black'; public $iPattern=-1,$iPatternDensity=80,$iPatternColor='black';
public $valuepos='top'; public $valuepos='top';
public $grad=false,$grad_style=1; public $grad=false,$grad_style=1;
public $grad_fromcolor=array(50,50,200),$grad_tocolor=array(255,255,255); public $grad_fromcolor=array(50,50,200),$grad_tocolor=array(255,255,255);
public $ymin=0; public $ymin=0;
protected $width=0.4; // in percent of major ticks protected $width=0.4; // in percent of major ticks
protected $abswidth=-1; // Width in absolute pixels protected $abswidth=-1; // Width in absolute pixels
protected $ybase=0; // Bars start at 0 protected $ybase=0; // Bars start at 0
protected $align="center"; protected $align="center";
protected $bar_shadow=false; protected $bar_shadow=false;
protected $bar_shadow_color="black"; protected $bar_shadow_color="black";
protected $bar_shadow_hsize=3,$bar_shadow_vsize=3; protected $bar_shadow_hsize=3,$bar_shadow_vsize=3;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
++$this->numpoints; ++$this->numpoints;
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
// Set a drop shadow for the bar (or rather an "up-right" shadow) // Set a drop shadow for the bar (or rather an "up-right" shadow)
function SetShadow($aColor="black",$aHSize=3,$aVSize=3,$aShow=true) { function SetShadow($aColor="black",$aHSize=3,$aVSize=3,$aShow=true) {
$this->bar_shadow=$aShow; $this->bar_shadow=$aShow;
$this->bar_shadow_color=$aColor; $this->bar_shadow_color=$aColor;
$this->bar_shadow_vsize=$aVSize; $this->bar_shadow_vsize=$aVSize;
$this->bar_shadow_hsize=$aHSize; $this->bar_shadow_hsize=$aHSize;
   
// Adjust the value margin to compensate for shadow // Adjust the value margin to compensate for shadow
$this->value->margin += $aVSize; $this->value->margin += $aVSize;
} }
   
// DEPRECATED use SetYBase instead // DEPRECATED use SetYBase instead
function SetYMin($aYStartValue) { function SetYMin($aYStartValue) {
//die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead."); //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");
$this->ybase=$aYStartValue; $this->ybase=$aYStartValue;
} }
   
// Specify the base value for the bars // Specify the base value for the bars
function SetYBase($aYStartValue) { function SetYBase($aYStartValue) {
$this->ybase=$aYStartValue; $this->ybase=$aYStartValue;
} }
   
// The method will take the specified pattern anre // The method will take the specified pattern anre
// return a pattern index that corresponds to the original // return a pattern index that corresponds to the original
// patterm being rotated 90 degreees. This is needed when plottin // patterm being rotated 90 degreees. This is needed when plottin
// Horizontal bars // Horizontal bars
function RotatePattern($aPat,$aRotate=true) { function RotatePattern($aPat,$aRotate=true) {
$rotate = array(1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8); $rotate = array(1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8);
if( $aRotate ) { if( $aRotate ) {
return $rotate[$aPat]; return $rotate[$aPat];
} }
else { else {
return $aPat; return $aPat;
} }
} }
   
function Legend($graph) { function Legend($graph) {
if( $this->grad && $this->legend!="" && !$this->fill ) { if( $this->grad && $this->legend!="" && !$this->fill ) {
$color=array($this->grad_fromcolor,$this->grad_tocolor); $color=array($this->grad_fromcolor,$this->grad_tocolor);
// In order to differentiate between gradients and cooors specified as an RGB triple // In order to differentiate between gradients and cooors specified as an RGB triple
$graph->legend->Add($this->legend,$color,"",-$this->grad_style, $graph->legend->Add($this->legend,$color,"",-$this->grad_style,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) { elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) {
if( is_array($this->iPattern) ) { if( is_array($this->iPattern) ) {
$p1 = $this->RotatePattern( $this->iPattern[0], $graph->img->a == 90 ); $p1 = $this->RotatePattern( $this->iPattern[0], $graph->img->a == 90 );
$p2 = $this->iPatternColor[0]; $p2 = $this->iPatternColor[0];
$p3 = $this->iPatternDensity[0]; $p3 = $this->iPatternDensity[0];
} }
else { else {
$p1 = $this->RotatePattern( $this->iPattern, $graph->img->a == 90 ); $p1 = $this->RotatePattern( $this->iPattern, $graph->img->a == 90 );
$p2 = $this->iPatternColor; $p2 = $this->iPatternColor;
$p3 = $this->iPatternDensity; $p3 = $this->iPatternDensity;
} }
if( $p3 < 90 ) $p3 += 5; if( $p3 < 90 ) $p3 += 5;
$color = array($p1,$p2,$p3,$this->fill_color); $color = array($p1,$p2,$p3,$this->fill_color);
// A kludge: Too mark that we add a pattern we use a type value of < 100 // A kludge: Too mark that we add a pattern we use a type value of < 100
$graph->legend->Add($this->legend,$color,"",-101, $graph->legend->Add($this->legend,$color,"",-101,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
elseif( $this->fill_color && $this->legend!="" ) { elseif( $this->fill_color && $this->legend!="" ) {
if( is_array($this->fill_color) ) { if( is_array($this->fill_color) ) {
$graph->legend->Add($this->legend,$this->fill_color[0],"",0, $graph->legend->Add($this->legend,$this->fill_color[0],"",0,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
else { else {
$graph->legend->Add($this->legend,$this->fill_color,"",0, $graph->legend->Add($this->legend,$this->fill_color,"",0,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
} }
} }
   
// Gets called before any axis are stroked // Gets called before any axis are stroked
function PreStrokeAdjust($graph) { function PreStrokeAdjust($graph) {
parent::PreStrokeAdjust($graph); parent::PreStrokeAdjust($graph);
   
// If we are using a log Y-scale we want the base to be at the // 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 // minimum Y-value unless the user have specifically set some other
// value than the default. // value than the default.
if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 ) if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
$this->ybase = $graph->yaxis->scale->GetMinVal(); $this->ybase = $graph->yaxis->scale->GetMinVal();
   
// For a "text" X-axis scale we will adjust the // For a "text" X-axis scale we will adjust the
// display of the bars a little bit. // display of the bars a little bit.
if( substr($graph->axtype,0,3)=="tex" ) { if( substr($graph->axtype,0,3)=="tex" ) {
// Position the ticks between the bars // Position the ticks between the bars
$graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0); $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
   
// Center the bars // Center the bars
if( $this->abswidth > -1 ) { if( $this->abswidth > -1 ) {
$graph->SetTextScaleAbsCenterOff($this->abswidth); $graph->SetTextScaleAbsCenterOff($this->abswidth);
} }
else { else {
if( $this->align == "center" ) if( $this->align == "center" )
$graph->SetTextScaleOff(0.5-$this->width/2); $graph->SetTextScaleOff(0.5-$this->width/2);
elseif( $this->align == "right" ) elseif( $this->align == "right" )
$graph->SetTextScaleOff(1-$this->width); $graph->SetTextScaleOff(1-$this->width);
} }
} }
elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) { elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) {
// We only set an absolute width for linear and int scale // We only set an absolute width for linear and int scale
// for text scale the width will be set to a fraction of // for text scale the width will be set to a fraction of
// the majstep width. // the majstep width.
if( $this->abswidth == -1 ) { if( $this->abswidth == -1 ) {
// Not set // Not set
// set width to a visuable sensible default // set width to a visuable sensible default
$this->abswidth = $graph->img->plotwidth/(2*$this->numpoints); $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
} }
} }
} }
   
function Min() { function Min() {
$m = parent::Min(); $m = parent::Min();
if( $m[1] >= $this->ybase ) $m[1] = $this->ybase; if( $m[1] >= $this->ybase ) $m[1] = $this->ybase;
return $m; return $m;
} }
   
function Max() { function Max() {
$m = parent::Max(); $m = parent::Max();
if( $m[1] <= $this->ybase ) $m[1] = $this->ybase; if( $m[1] <= $this->ybase ) $m[1] = $this->ybase;
return $m; return $m;
} }
   
// Specify width as fractions of the major stepo size // Specify width as fractions of the major stepo size
function SetWidth($aWidth) { function SetWidth($aWidth) {
if( $aWidth > 1 ) { if( $aWidth > 1 ) {
// Interpret this as absolute width // Interpret this as absolute width
$this->abswidth=$aWidth; $this->abswidth=$aWidth;
} }
else { else {
$this->width=$aWidth; $this->width=$aWidth;
} }
} }
   
// Specify width in absolute pixels. If specified this // Specify width in absolute pixels. If specified this
// overrides SetWidth() // overrides SetWidth()
function SetAbsWidth($aWidth) { function SetAbsWidth($aWidth) {
$this->abswidth=$aWidth; $this->abswidth=$aWidth;
} }
   
function SetAlign($aAlign) { function SetAlign($aAlign) {
$this->align=$aAlign; $this->align=$aAlign;
} }
   
function SetNoFill() { function SetNoFill() {
$this->grad = false; $this->grad = false;
$this->fill_color=false; $this->fill_color=false;
$this->fill=false; $this->fill=false;
} }
   
function SetFillColor($aColor) { function SetFillColor($aColor) {
// Do an extra error check if the color is specified as an RGB array triple // 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 // In that case convert it to a hex string since it will otherwise be
// interpretated as an array of colors for each individual bar. // interpretated as an array of colors for each individual bar.
   
$aColor = RGB::tryHexConversion($aColor); $aColor = RGB::tryHexConversion($aColor);
$this->fill = true ; $this->fill = true ;
$this->fill_color=$aColor; $this->fill_color=$aColor;
   
} }
   
function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) { function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) {
$this->grad = true; $this->grad = true;
$this->grad_fromcolor = $aFromColor; $this->grad_fromcolor = $aFromColor;
$this->grad_tocolor = $aToColor; $this->grad_tocolor = $aToColor;
$this->grad_style = $aStyle; $this->grad_style = $aStyle;
} }
   
function SetValuePos($aPos) { function SetValuePos($aPos) {
$this->valuepos = $aPos; $this->valuepos = $aPos;
} }
   
function SetPattern($aPattern, $aColor='black'){ function SetPattern($aPattern, $aColor='black'){
if( is_array($aPattern) ) { if( is_array($aPattern) ) {
$n = count($aPattern); $n = count($aPattern);
$this->iPattern = array(); $this->iPattern = array();
$this->iPatternDensity = array(); $this->iPatternDensity = array();
if( is_array($aColor) ) { if( is_array($aColor) ) {
$this->iPatternColor = array(); $this->iPatternColor = array();
if( count($aColor) != $n ) { if( count($aColor) != $n ) {
JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()'); JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()');
} }
} }
else { else {
$this->iPatternColor = $aColor; $this->iPatternColor = $aColor;
} }
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]); $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]);
if( is_array($aColor) ) { if( is_array($aColor) ) {
$this->iPatternColor[$i] = $aColor[$i]; $this->iPatternColor[$i] = $aColor[$i];
} }
} }
} }
else { else {
$this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity); $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity);
$this->iPatternColor = $aColor; $this->iPatternColor = $aColor;
} }
} }
   
function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){ function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){
switch( $aPattern ) { switch( $aPattern ) {
case PATTERN_DIAG1: case PATTERN_DIAG1:
$aPatternValue= 1; $aPatternValue= 1;
$aDensity = 92; $aDensity = 92;
break; break;
case PATTERN_DIAG2: case PATTERN_DIAG2:
$aPatternValue= 1; $aPatternValue= 1;
$aDensity = 78; $aDensity = 78;
break; break;
case PATTERN_DIAG3: case PATTERN_DIAG3:
$aPatternValue= 2; $aPatternValue= 2;
$aDensity = 92; $aDensity = 92;
break; break;
case PATTERN_DIAG4: case PATTERN_DIAG4:
$aPatternValue= 2; $aPatternValue= 2;
$aDensity = 78; $aDensity = 78;
break; break;
case PATTERN_CROSS1: case PATTERN_CROSS1:
$aPatternValue= 8; $aPatternValue= 8;
$aDensity = 90; $aDensity = 90;
break; break;
case PATTERN_CROSS2: case PATTERN_CROSS2:
$aPatternValue= 8; $aPatternValue= 8;
$aDensity = 78; $aDensity = 78;
break; break;
case PATTERN_CROSS3: case PATTERN_CROSS3:
$aPatternValue= 8; $aPatternValue= 8;
$aDensity = 65; $aDensity = 65;
break; break;
case PATTERN_CROSS4: case PATTERN_CROSS4:
$aPatternValue= 7; $aPatternValue= 7;
$aDensity = 90; $aDensity = 90;
break; break;
case PATTERN_STRIPE1: case PATTERN_STRIPE1:
$aPatternValue= 5; $aPatternValue= 5;
$aDensity = 94; $aDensity = 94;
break; break;
case PATTERN_STRIPE2: case PATTERN_STRIPE2:
$aPatternValue= 5; $aPatternValue= 5;
$aDensity = 85; $aDensity = 85;
break; break;
default: default:
JpGraphError::RaiseL(2002); JpGraphError::RaiseL(2002);
//('Unknown pattern specified in call to BarPlot::SetPattern()'); //('Unknown pattern specified in call to BarPlot::SetPattern()');
} }
} }
   
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
   
$numpoints = count($this->coords[0]); $numpoints = count($this->coords[0]);
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
if( count($this->coords[1])!=$numpoints ) { if( count($this->coords[1])!=$numpoints ) {
JpGraphError::RaiseL(2003,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"); //"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints");
} }
else { else {
$exist_x = true; $exist_x = true;
} }
} }
else { else {
$exist_x = false; $exist_x = false;
} }
   
   
$numbars=count($this->coords[0]); $numbars=count($this->coords[0]);
   
// Use GetMinVal() instead of scale[0] directly since in the case // Use GetMinVal() instead of scale[0] directly since in the case
// of log scale we get a correct value. Log scales will have negative // of log scale we get a correct value. Log scales will have negative
// values for values < 1 while still not representing negative numbers. // values for values < 1 while still not representing negative numbers.
if( $yscale->GetMinVal() >= 0 ) if( $yscale->GetMinVal() >= 0 )
$zp=$yscale->scale_abs[0]; $zp=$yscale->scale_abs[0];
else { else {
$zp=$yscale->Translate(0); $zp=$yscale->Translate(0);
} }
   
if( $this->abswidth > -1 ) { if( $this->abswidth > -1 ) {
$abswidth=$this->abswidth; $abswidth=$this->abswidth;
} }
else { else {
$abswidth=round($this->width*$xscale->scale_factor,0); $abswidth=round($this->width*$xscale->scale_factor,0);
} }
   
// Count pontetial pattern array to avoid doing the count for each iteration // Count pontetial pattern array to avoid doing the count for each iteration
if( is_array($this->iPattern) ) { if( is_array($this->iPattern) ) {
$np = count($this->iPattern); $np = count($this->iPattern);
} }
   
$grad = null; $grad = null;
for($i=0; $i < $numbars; ++$i) { for($i=0; $i < $numbars; ++$i) {
   
// If value is NULL, or 0 then don't draw a bar at all // If value is NULL, or 0 then don't draw a bar at all
if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' ) if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' )
continue; continue;
   
if( $exist_x ) { if( $exist_x ) {
$x=$this->coords[1][$i]; $x=$this->coords[1][$i];
} }
else { else {
$x=$i; $x=$i;
} }
   
$x=$xscale->Translate($x); $x=$xscale->Translate($x);
   
// Comment Note: This confuses the positioning when using acc together with // Comment Note: This confuses the positioning when using acc together with
// grouped bars. Workaround for fixing #191 // grouped bars. Workaround for fixing #191
/* /*
if( !$xscale->textscale ) { if( !$xscale->textscale ) {
if($this->align=="center") if($this->align=="center")
$x -= $abswidth/2; $x -= $abswidth/2;
elseif($this->align=="right") elseif($this->align=="right")
$x -= $abswidth; $x -= $abswidth;
} }
*/ */
// Stroke fill color and fill gradient // Stroke fill color and fill gradient
$pts=array( $pts=array(
$x,$zp, $x,$zp,
$x,$yscale->Translate($this->coords[0][$i]), $x,$yscale->Translate($this->coords[0][$i]),
$x+$abswidth,$yscale->Translate($this->coords[0][$i]), $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
$x+$abswidth,$zp); $x+$abswidth,$zp);
if( $this->grad ) { if( $this->grad ) {
if( $grad === null ) { if( $grad === null ) {
$grad = new Gradient($img); $grad = new Gradient($img);
} }
if( is_array($this->grad_fromcolor) ) { 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 // 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 // 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 // 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 // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
// triple. // triple.
$ng = count($this->grad_fromcolor); $ng = count($this->grad_fromcolor);
if( $ng === 3 ) { if( $ng === 3 ) {
if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) { if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) {
// RGB Triple // RGB Triple
$fromcolor = $this->grad_fromcolor; $fromcolor = $this->grad_fromcolor;
$tocolor = $this->grad_tocolor; $tocolor = $this->grad_tocolor;
$style = $this->grad_style; $style = $this->grad_style;
} }
else { else {
$fromcolor = $this->grad_fromcolor[$i % $ng][0]; $fromcolor = $this->grad_fromcolor[$i % $ng][0];
$tocolor = $this->grad_fromcolor[$i % $ng][1]; $tocolor = $this->grad_fromcolor[$i % $ng][1];
$style = $this->grad_fromcolor[$i % $ng][2]; $style = $this->grad_fromcolor[$i % $ng][2];
} }
} }
else { else {
$fromcolor = $this->grad_fromcolor[$i % $ng][0]; $fromcolor = $this->grad_fromcolor[$i % $ng][0];
$tocolor = $this->grad_fromcolor[$i % $ng][1]; $tocolor = $this->grad_fromcolor[$i % $ng][1];
$style = $this->grad_fromcolor[$i % $ng][2]; $style = $this->grad_fromcolor[$i % $ng][2];
} }
$grad->FilledRectangle($pts[2],$pts[3], $grad->FilledRectangle($pts[2],$pts[3],
$pts[6],$pts[7], $pts[6],$pts[7],
$fromcolor,$tocolor,$style); $fromcolor,$tocolor,$style);
} }
else { else {
$grad->FilledRectangle($pts[2],$pts[3], $grad->FilledRectangle($pts[2],$pts[3],
$pts[6],$pts[7], $pts[6],$pts[7],
$this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style);
} }
} }
elseif( !empty($this->fill_color) ) { elseif( !empty($this->fill_color) ) {
if(is_array($this->fill_color)) { if(is_array($this->fill_color)) {
$img->PushColor($this->fill_color[$i % count($this->fill_color)]); $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
} else { } else {
$img->PushColor($this->fill_color); $img->PushColor($this->fill_color);
} }
$img->FilledPolygon($pts); $img->FilledPolygon($pts);
$img->PopColor(); $img->PopColor();
} }
   
   
// Remember value of this bar // Remember value of this bar
$val=$this->coords[0][$i]; $val=$this->coords[0][$i];
   
if( !empty($val) && !is_numeric($val) ) { if( !empty($val) && !is_numeric($val) ) {
JpGraphError::RaiseL(2004,$i,$val); JpGraphError::RaiseL(2004,$i,$val);
//'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\''); //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\'');
} }
   
// Determine the shadow // Determine the shadow
if( $this->bar_shadow && $val != 0) { if( $this->bar_shadow && $val != 0) {
   
$ssh = $this->bar_shadow_hsize; $ssh = $this->bar_shadow_hsize;
$ssv = $this->bar_shadow_vsize; $ssv = $this->bar_shadow_vsize;
// Create points to create a "upper-right" shadow // Create points to create a "upper-right" shadow
if( $val > 0 ) { if( $val > 0 ) {
$sp[0]=$pts[6]; $sp[1]=$pts[7]; $sp[0]=$pts[6]; $sp[1]=$pts[7];
$sp[2]=$pts[4]; $sp[3]=$pts[5]; $sp[2]=$pts[4]; $sp[3]=$pts[5];
$sp[4]=$pts[2]; $sp[5]=$pts[3]; $sp[4]=$pts[2]; $sp[5]=$pts[3];
$sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
$sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv; $sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv;
$sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv; $sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv;
} }
elseif( $val < 0 ) { elseif( $val < 0 ) {
$sp[0]=$pts[4]; $sp[1]=$pts[5]; $sp[0]=$pts[4]; $sp[1]=$pts[5];
$sp[2]=$pts[6]; $sp[3]=$pts[7]; $sp[2]=$pts[6]; $sp[3]=$pts[7];
$sp[4]=$pts[0]; $sp[5]=$pts[1]; $sp[4]=$pts[0]; $sp[5]=$pts[1];
$sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv; $sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv;
$sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv; $sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv;
$sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv; $sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv;
} }
if( is_array($this->bar_shadow_color) ) { if( is_array($this->bar_shadow_color) ) {
$numcolors = count($this->bar_shadow_color); $numcolors = count($this->bar_shadow_color);
if( $numcolors == 0 ) { if( $numcolors == 0 ) {
JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.'); JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.');
} }
$img->PushColor($this->bar_shadow_color[$i % $numcolors]); $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
} }
else { else {
$img->PushColor($this->bar_shadow_color); $img->PushColor($this->bar_shadow_color);
} }
$img->FilledPolygon($sp); $img->FilledPolygon($sp);
$img->PopColor(); $img->PopColor();
} }
   
// Stroke the pattern // Stroke the pattern
if( is_array($this->iPattern) ) { if( is_array($this->iPattern) ) {
$f = new RectPatternFactory(); $f = new RectPatternFactory();
if( is_array($this->iPatternColor) ) { if( is_array($this->iPatternColor) ) {
$pcolor = $this->iPatternColor[$i % $np]; $pcolor = $this->iPatternColor[$i % $np];
} }
else { else {
$pcolor = $this->iPatternColor; $pcolor = $this->iPatternColor;
} }
$prect = $f->Create($this->iPattern[$i % $np],$pcolor,1); $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1);
$prect->SetDensity($this->iPatternDensity[$i % $np]); $prect->SetDensity($this->iPatternDensity[$i % $np]);
   
if( $val < 0 ) { if( $val < 0 ) {
$rx = $pts[0]; $rx = $pts[0];
$ry = $pts[1]; $ry = $pts[1];
} }
else { else {
$rx = $pts[2]; $rx = $pts[2];
$ry = $pts[3]; $ry = $pts[3];
} }
$width = abs($pts[4]-$pts[0])+1; $width = abs($pts[4]-$pts[0])+1;
$height = abs($pts[1]-$pts[3])+1; $height = abs($pts[1]-$pts[3])+1;
$prect->SetPos(new Rectangle($rx,$ry,$width,$height)); $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
$prect->Stroke($img); $prect->Stroke($img);
} }
else { else {
if( $this->iPattern > -1 ) { if( $this->iPattern > -1 ) {
$f = new RectPatternFactory(); $f = new RectPatternFactory();
$prect = $f->Create($this->iPattern,$this->iPatternColor,1); $prect = $f->Create($this->iPattern,$this->iPatternColor,1);
$prect->SetDensity($this->iPatternDensity); $prect->SetDensity($this->iPatternDensity);
if( $val < 0 ) { if( $val < 0 ) {
$rx = $pts[0]; $rx = $pts[0];
$ry = $pts[1]; $ry = $pts[1];
} }
else { else {
$rx = $pts[2]; $rx = $pts[2];
$ry = $pts[3]; $ry = $pts[3];
} }
$width = abs($pts[4]-$pts[0])+1; $width = abs($pts[4]-$pts[0])+1;
$height = abs($pts[1]-$pts[3])+1; $height = abs($pts[1]-$pts[3])+1;
$prect->SetPos(new Rectangle($rx,$ry,$width,$height)); $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
$prect->Stroke($img); $prect->Stroke($img);
} }
} }
   
// Stroke the outline of the bar // Stroke the outline of the bar
if( is_array($this->color) ) { if( is_array($this->color) ) {
$img->SetColor($this->color[$i % count($this->color)]); $img->SetColor($this->color[$i % count($this->color)]);
} }
else { else {
$img->SetColor($this->color); $img->SetColor($this->color);
} }
   
$pts[] = $pts[0]; $pts[] = $pts[0];
$pts[] = $pts[1]; $pts[] = $pts[1];
   
if( $this->weight > 0 ) { if( $this->weight > 0 ) {
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$img->Polygon($pts); $img->Polygon($pts);
} }
   
// Determine how to best position the values of the individual bars // Determine how to best position the values of the individual bars
$x=$pts[2]+($pts[4]-$pts[2])/2; $x=$pts[2]+($pts[4]-$pts[2])/2;
$this->value->SetMargin(5); $this->value->SetMargin(5);
   
if( $this->valuepos=='top' ) { if( $this->valuepos=='top' ) {
$y=$pts[3]; $y=$pts[3];
if( $img->a === 90 ) { if( $img->a === 90 ) {
if( $val < 0 ) { if( $val < 0 ) {
$this->value->SetAlign('right','center'); $this->value->SetAlign('right','center');
} }
else { else {
$this->value->SetAlign('left','center'); $this->value->SetAlign('left','center');
} }
   
} }
else { else {
if( $val < 0 ) { if( $val < 0 ) {
$this->value->SetMargin(-5); $this->value->SetMargin(-5);
$y=$pts[1]; $y=$pts[1];
$this->value->SetAlign('center','bottom'); $this->value->SetAlign('center','bottom');
} }
else { else {
$this->value->SetAlign('center','bottom'); $this->value->SetAlign('center','bottom');
} }
   
} }
$this->value->Stroke($img,$val,$x,$y); $this->value->Stroke($img,$val,$x,$y);
} }
elseif( $this->valuepos=='max' ) { elseif( $this->valuepos=='max' ) {
$y=$pts[3]; $y=$pts[3];
if( $img->a === 90 ) { if( $img->a === 90 ) {
if( $val < 0 ) if( $val < 0 )
$this->value->SetAlign('left','center'); $this->value->SetAlign('left','center');
else else
$this->value->SetAlign('right','center'); $this->value->SetAlign('right','center');
} }
else { else {
if( $val < 0 ) { if( $val < 0 ) {
$this->value->SetAlign('center','bottom'); $this->value->SetAlign('center','bottom');
} }
else { else {
$this->value->SetAlign('center','top'); $this->value->SetAlign('center','top');
} }
} }
$this->value->SetMargin(-5); $this->value->SetMargin(-5);
$this->value->Stroke($img,$val,$x,$y); $this->value->Stroke($img,$val,$x,$y);
} }
elseif( $this->valuepos=='center' ) { elseif( $this->valuepos=='center' ) {
$y = ($pts[3] + $pts[1])/2; $y = ($pts[3] + $pts[1])/2;
$this->value->SetAlign('center','center'); $this->value->SetAlign('center','center');
$this->value->SetMargin(0); $this->value->SetMargin(0);
$this->value->Stroke($img,$val,$x,$y); $this->value->Stroke($img,$val,$x,$y);
} }
elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) { elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
$y=$pts[1]; $y=$pts[1];
if( $img->a === 90 ) { if( $img->a === 90 ) {
if( $val < 0 ) if( $val < 0 )
$this->value->SetAlign('right','center'); $this->value->SetAlign('right','center');
else else
$this->value->SetAlign('left','center'); $this->value->SetAlign('left','center');
} }
$this->value->SetMargin(3); $this->value->SetMargin(3);
$this->value->Stroke($img,$val,$x,$y); $this->value->Stroke($img,$val,$x,$y);
} }
else { else {
JpGraphError::RaiseL(2006,$this->valuepos); JpGraphError::RaiseL(2006,$this->valuepos);
//'Unknown position for values on bars :'.$this->valuepos); //'Unknown position for values on bars :'.$this->valuepos);
} }
// Create the client side image map // Create the client side image map
$rpts = $img->ArrRotate($pts); $rpts = $img->ArrRotate($pts);
$csimcoord=round($rpts[0]).", ".round($rpts[1]); $csimcoord=round($rpts[0]).", ".round($rpts[1]);
for( $j=1; $j < 4; ++$j){ for( $j=1; $j < 4; ++$j){
$csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]); $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
} }
if( !empty($this->csimtargets[$i]) ) { if( !empty($this->csimtargets[$i]) ) {
$this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" '; $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';
$this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\""; $this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\"";
   
if( !empty($this->csimwintargets[$i]) ) { if( !empty($this->csimwintargets[$i]) ) {
$this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
} }
   
$sval=''; $sval='';
if( !empty($this->csimalts[$i]) ) { if( !empty($this->csimalts[$i]) ) {
$sval=sprintf($this->csimalts[$i],$this->coords[0][$i]); $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
$this->csimareas .= " title=\"$sval\" alt=\"$sval\" "; $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
} }
return true; return true;
} }
} // Class } // Class
   
//=================================================== //===================================================
// CLASS GroupBarPlot // CLASS GroupBarPlot
// Description: Produce grouped bar plots // Description: Produce grouped bar plots
//=================================================== //===================================================
class GroupBarPlot extends BarPlot { class GroupBarPlot extends BarPlot {
private $plots, $nbrplots=0; private $plots, $nbrplots=0;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function GroupBarPlot($plots) { function GroupBarPlot($plots) {
$this->width=0.7; $this->width=0.7;
$this->plots = $plots; $this->plots = $plots;
$this->nbrplots = count($plots); $this->nbrplots = count($plots);
if( $this->nbrplots < 1 ) { if( $this->nbrplots < 1 ) {
JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.'); JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.');
} }
for($i=0; $i < $this->nbrplots; ++$i ) { for($i=0; $i < $this->nbrplots; ++$i ) {
if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty."); JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty.");
} }
} }
$this->numpoints = $plots[0]->numpoints; $this->numpoints = $plots[0]->numpoints;
$this->width=0.7; $this->width=0.7;
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Legend($graph) { function Legend($graph) {
$n = count($this->plots); $n = count($this->plots);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$c = get_class($this->plots[$i]); $c = get_class($this->plots[$i]);
if( !($this->plots[$i] instanceof BarPlot) ) { if( !($this->plots[$i] instanceof BarPlot) ) {
JpGraphError::RaiseL(2009,$c); 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.')'); //('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); $this->plots[$i]->DoLegend($graph);
} }
} }
   
function Min() { function Min() {
list($xmin,$ymin) = $this->plots[0]->Min(); list($xmin,$ymin) = $this->plots[0]->Min();
$n = count($this->plots); $n = count($this->plots);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
list($xm,$ym) = $this->plots[$i]->Min(); list($xm,$ym) = $this->plots[$i]->Min();
$xmin = max($xmin,$xm); $xmin = max($xmin,$xm);
$ymin = min($ymin,$ym); $ymin = min($ymin,$ym);
} }
return array($xmin,$ymin); return array($xmin,$ymin);
} }
   
function Max() { function Max() {
list($xmax,$ymax) = $this->plots[0]->Max(); list($xmax,$ymax) = $this->plots[0]->Max();
$n = count($this->plots); $n = count($this->plots);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
list($xm,$ym) = $this->plots[$i]->Max(); list($xm,$ym) = $this->plots[$i]->Max();
$xmax = max($xmax,$xm); $xmax = max($xmax,$xm);
$ymax = max($ymax,$ym); $ymax = max($ymax,$ym);
} }
return array($xmax,$ymax); return array($xmax,$ymax);
} }
   
function GetCSIMareas() { function GetCSIMareas() {
$n = count($this->plots); $n = count($this->plots);
$csimareas=''; $csimareas='';
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$csimareas .= $this->plots[$i]->csimareas; $csimareas .= $this->plots[$i]->csimareas;
} }
return $csimareas; return $csimareas;
} }
   
// Stroke all the bars next to each other // Stroke all the bars next to each other
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
$tmp=$xscale->off; $tmp=$xscale->off;
$n = count($this->plots); $n = count($this->plots);
$subwidth = $this->width/$this->nbrplots ; $subwidth = $this->width/$this->nbrplots ;
   
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->plots[$i]->ymin=$this->ybase; $this->plots[$i]->ymin=$this->ybase;
$this->plots[$i]->SetWidth($subwidth); $this->plots[$i]->SetWidth($subwidth);
   
// If the client have used SetTextTickInterval() then // If the client have used SetTextTickInterval() then
// major_step will be > 1 and the positioning will fail. // major_step will be > 1 and the positioning will fail.
// If we assume it is always one the positioning will work // If we assume it is always one the positioning will work
// fine with a text scale but this will not work with // fine with a text scale but this will not work with
// arbitrary linear scale // arbitrary linear scale
$xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth); $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth);
$this->plots[$i]->Stroke($img,$xscale,$yscale); $this->plots[$i]->Stroke($img,$xscale,$yscale);
} }
$xscale->off=$tmp; $xscale->off=$tmp;
} }
} // Class } // Class
   
//=================================================== //===================================================
// CLASS AccBarPlot // CLASS AccBarPlot
// Description: Produce accumulated bar plots // Description: Produce accumulated bar plots
//=================================================== //===================================================
class AccBarPlot extends BarPlot { class AccBarPlot extends BarPlot {
private $plots=null,$nbrplots=0; private $plots=null,$nbrplots=0;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($plots) { function __construct($plots) {
$this->plots = $plots; $this->plots = $plots;
$this->nbrplots = count($plots); $this->nbrplots = count($plots);
if( $this->nbrplots < 1 ) { if( $this->nbrplots < 1 ) {
JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.'); JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.');
} }
for($i=0; $i < $this->nbrplots; ++$i ) { for($i=0; $i < $this->nbrplots; ++$i ) {
if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty."); 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 // We can only allow individual plost which do not have specified X-positions
for($i=0; $i < $this->nbrplots; ++$i ) { for($i=0; $i < $this->nbrplots; ++$i ) {
if( !empty($this->plots[$i]->coords[1]) ) { if( !empty($this->plots[$i]->coords[1]) ) {
JpGraphError::RaiseL(2015); JpGraphError::RaiseL(2015);
//'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.'); //'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 // Use 0 weight by default which means that the individual bar
// weights will be used per part n the accumulated bar // weights will be used per part n the accumulated bar
$this->SetWeight(0); $this->SetWeight(0);
   
$this->numpoints = $plots[0]->numpoints; $this->numpoints = $plots[0]->numpoints;
$this->value = new DisplayValue(); $this->value = new DisplayValue();
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Legend($graph) { function Legend($graph) {
$n = count($this->plots); $n = count($this->plots);
for( $i=$n-1; $i >= 0; --$i ) { for( $i=$n-1; $i >= 0; --$i ) {
$c = get_class($this->plots[$i]); $c = get_class($this->plots[$i]);
if( !($this->plots[$i] instanceof BarPlot) ) { if( !($this->plots[$i] instanceof BarPlot) ) {
JpGraphError::RaiseL(2012,$c); 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.')'); //('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); $this->plots[$i]->DoLegend($graph);
} }
} }
   
function Max() { function Max() {
list($xmax) = $this->plots[0]->Max(); list($xmax) = $this->plots[0]->Max();
$nmax=0; $nmax=0;
for($i=0; $i < count($this->plots); ++$i) { for($i=0; $i < count($this->plots); ++$i) {
$n = count($this->plots[$i]->coords[0]); $n = count($this->plots[$i]->coords[0]);
$nmax = max($nmax,$n); $nmax = max($nmax,$n);
list($x) = $this->plots[$i]->Max(); list($x) = $this->plots[$i]->Max();
$xmax = max($xmax,$x); $xmax = max($xmax,$x);
} }
for( $i = 0; $i < $nmax; $i++ ) { for( $i = 0; $i < $nmax; $i++ ) {
// Get y-value for bar $i by adding the // Get y-value for bar $i by adding the
// individual bars from all the plots added. // individual bars from all the plots added.
// It would be wrong to just add the // It would be wrong to just add the
// individual plots max y-value since that // individual plots max y-value since that
// would in most cases give to large y-value. // would in most cases give to large y-value.
$y=0; $y=0;
if( !isset($this->plots[0]->coords[0][$i]) ) { if( !isset($this->plots[0]->coords[0][$i]) ) {
JpGraphError::RaiseL(2014); JpGraphError::RaiseL(2014);
} }
if( $this->plots[0]->coords[0][$i] > 0 ) if( $this->plots[0]->coords[0][$i] > 0 )
$y=$this->plots[0]->coords[0][$i]; $y=$this->plots[0]->coords[0][$i];
for( $j = 1; $j < $this->nbrplots; $j++ ) { for( $j = 1; $j < $this->nbrplots; $j++ ) {
if( !isset($this->plots[$j]->coords[0][$i]) ) { if( !isset($this->plots[$j]->coords[0][$i]) ) {
JpGraphError::RaiseL(2014); JpGraphError::RaiseL(2014);
} }
if( $this->plots[$j]->coords[0][$i] > 0 ) if( $this->plots[$j]->coords[0][$i] > 0 )
$y += $this->plots[$j]->coords[0][$i]; $y += $this->plots[$j]->coords[0][$i];
} }
$ymax[$i] = $y; $ymax[$i] = $y;
} }
$ymax = max($ymax); $ymax = max($ymax);
   
// Bar always start at baseline // Bar always start at baseline
if( $ymax <= $this->ybase ) if( $ymax <= $this->ybase )
$ymax = $this->ybase; $ymax = $this->ybase;
return array($xmax,$ymax); return array($xmax,$ymax);
} }
   
function Min() { function Min() {
$nmax=0; $nmax=0;
list($xmin,$ysetmin) = $this->plots[0]->Min(); list($xmin,$ysetmin) = $this->plots[0]->Min();
for($i=0; $i < count($this->plots); ++$i) { for($i=0; $i < count($this->plots); ++$i) {
$n = count($this->plots[$i]->coords[0]); $n = count($this->plots[$i]->coords[0]);
$nmax = max($nmax,$n); $nmax = max($nmax,$n);
list($x,$y) = $this->plots[$i]->Min(); list($x,$y) = $this->plots[$i]->Min();
$xmin = Min($xmin,$x); $xmin = Min($xmin,$x);
$ysetmin = Min($y,$ysetmin); $ysetmin = Min($y,$ysetmin);
} }
for( $i = 0; $i < $nmax; $i++ ) { for( $i = 0; $i < $nmax; $i++ ) {
// Get y-value for bar $i by adding the // Get y-value for bar $i by adding the
// individual bars from all the plots added. // individual bars from all the plots added.
// It would be wrong to just add the // It would be wrong to just add the
// individual plots max y-value since that // individual plots max y-value since that
// would in most cases give to large y-value. // would in most cases give to large y-value.
$y=0; $y=0;
if( $this->plots[0]->coords[0][$i] < 0 ) if( $this->plots[0]->coords[0][$i] < 0 )
$y=$this->plots[0]->coords[0][$i]; $y=$this->plots[0]->coords[0][$i];
for( $j = 1; $j < $this->nbrplots; $j++ ) { for( $j = 1; $j < $this->nbrplots; $j++ ) {
if( $this->plots[$j]->coords[0][$i] < 0 ) if( $this->plots[$j]->coords[0][$i] < 0 )
$y += $this->plots[ $j ]->coords[0][$i]; $y += $this->plots[ $j ]->coords[0][$i];
} }
$ymin[$i] = $y; $ymin[$i] = $y;
} }
$ymin = Min($ysetmin,Min($ymin)); $ymin = Min($ysetmin,Min($ymin));
// Bar always start at baseline // Bar always start at baseline
if( $ymin >= $this->ybase ) if( $ymin >= $this->ybase )
$ymin = $this->ybase; $ymin = $this->ybase;
return array($xmin,$ymin); return array($xmin,$ymin);
} }
   
// Stroke acc bar plot // Stroke acc bar plot
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
$pattern=NULL; $pattern=NULL;
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$grad=null; $grad=null;
for($i=0; $i < $this->numpoints-1; $i++) { for($i=0; $i < $this->numpoints-1; $i++) {
$accy = 0; $accy = 0;
$accy_neg = 0; $accy_neg = 0;
for($j=0; $j < $this->nbrplots; ++$j ) { for($j=0; $j < $this->nbrplots; ++$j ) {
$img->SetColor($this->plots[$j]->color); $img->SetColor($this->plots[$j]->color);
   
if ( $this->plots[$j]->coords[0][$i] >= 0) { if ( $this->plots[$j]->coords[0][$i] >= 0) {
$yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
$accyt=$yscale->Translate($accy); $accyt=$yscale->Translate($accy);
$accy+=$this->plots[$j]->coords[0][$i]; $accy+=$this->plots[$j]->coords[0][$i];
} }
else { else {
//if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) { //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
$yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
$accyt=$yscale->Translate($accy_neg); $accyt=$yscale->Translate($accy_neg);
$accy_neg+=$this->plots[$j]->coords[0][$i]; $accy_neg+=$this->plots[$j]->coords[0][$i];
} }
   
$xt=$xscale->Translate($i); $xt=$xscale->Translate($i);
   
if( $this->abswidth > -1 ) { if( $this->abswidth > -1 ) {
$abswidth=$this->abswidth; $abswidth=$this->abswidth;
} }
else { else {
$abswidth=round($this->width*$xscale->scale_factor,0); $abswidth=round($this->width*$xscale->scale_factor,0);
} }
   
$pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt); $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
   
if( $this->bar_shadow ) { if( $this->bar_shadow ) {
$ssh = $this->bar_shadow_hsize; $ssh = $this->bar_shadow_hsize;
$ssv = $this->bar_shadow_vsize; $ssv = $this->bar_shadow_vsize;
   
// We must also differ if we are a positive or negative bar. // We must also differ if we are a positive or negative bar.
if( $j === 0 ) { if( $j === 0 ) {
// This gets extra complicated since we have to // This gets extra complicated since we have to
// see all plots to see if we are negative. It could // see all plots to see if we are negative. It could
// for example be that all plots are 0 until the very // for example be that all plots are 0 until the very
// last one. We therefore need to save the initial setup // last one. We therefore need to save the initial setup
// for both the negative and positive case // for both the negative and positive case
   
// In case the final bar is positive // In case the final bar is positive
$sp[0]=$pts[6]+1; $sp[1]=$pts[7]; $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
$sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv; $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
   
// In case the final bar is negative // In case the final bar is negative
$nsp[0]=$pts[0]; $nsp[1]=$pts[1]; $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
$nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv; $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
$nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv; $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
$nsp[10]=$pts[6]+1; $nsp[11]=$pts[7]; $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
} }
   
if( $j === $this->nbrplots-1 ) { if( $j === $this->nbrplots-1 ) {
// If this is the last plot of the bar and // If this is the last plot of the bar and
// the total value is larger than 0 then we // the total value is larger than 0 then we
// add the shadow. // add the shadow.
if( is_array($this->bar_shadow_color) ) { if( is_array($this->bar_shadow_color) ) {
$numcolors = count($this->bar_shadow_color); $numcolors = count($this->bar_shadow_color);
if( $numcolors == 0 ) { if( $numcolors == 0 ) {
JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.'); JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.');
} }
$img->PushColor($this->bar_shadow_color[$i % $numcolors]); $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
} }
else { else {
$img->PushColor($this->bar_shadow_color); $img->PushColor($this->bar_shadow_color);
} }
   
if( $accy > 0 ) { if( $accy > 0 ) {
$sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv; $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
$sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
$sp[8]=$pts[2]; $sp[9]=$pts[3]-1; $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
$sp[10]=$pts[4]+1; $sp[11]=$pts[5]; $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
$img->FilledPolygon($sp,4); $img->FilledPolygon($sp,4);
} }
elseif( $accy_neg < 0 ) { elseif( $accy_neg < 0 ) {
$nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv; $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
$nsp[8]=$pts[4]+1; $nsp[9]=$pts[5]; $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
$img->FilledPolygon($nsp,4); $img->FilledPolygon($nsp,4);
} }
$img->PopColor(); $img->PopColor();
} }
} }
   
   
// If value is NULL or 0, then don't draw a bar at all // 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]->coords[0][$i] == 0 ) continue;
   
if( $this->plots[$j]->grad ) { if( $this->plots[$j]->grad ) {
if( $grad === null ) { if( $grad === null ) {
$grad = new Gradient($img); $grad = new Gradient($img);
} }
if( is_array($this->plots[$j]->grad_fromcolor) ) { 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 // 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 // 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 // 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 // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
// triple. // triple.
$ng = count($this->plots[$j]->grad_fromcolor); $ng = count($this->plots[$j]->grad_fromcolor);
if( $ng === 3 ) { if( $ng === 3 ) {
if( is_numeric($this->plots[$j]->grad_fromcolor[0]) && $this->plots[$j]->grad_fromcolor[0] > 0 && if( is_numeric($this->plots[$j]->grad_fromcolor[0]) && $this->plots[$j]->grad_fromcolor[0] > 0 &&
$this->plots[$j]->grad_fromcolor[0] < 256 ) { $this->plots[$j]->grad_fromcolor[0] < 256 ) {
// RGB Triple // RGB Triple
$fromcolor = $this->plots[$j]->grad_fromcolor; $fromcolor = $this->plots[$j]->grad_fromcolor;
$tocolor = $this->plots[$j]->grad_tocolor; $tocolor = $this->plots[$j]->grad_tocolor;
$style = $this->plots[$j]->grad_style; $style = $this->plots[$j]->grad_style;
} }
else { else {
$fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0]; $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0];
$tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1]; $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1];
$style = $this->plots[$j]->grad_fromcolor[$i % $ng][2]; $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2];
} }
} }
else { else {
$fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0]; $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0];
$tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1]; $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1];
$style = $this->plots[$j]->grad_fromcolor[$i % $ng][2]; $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2];
} }
$grad->FilledRectangle($pts[2],$pts[3], $grad->FilledRectangle($pts[2],$pts[3],
$pts[6],$pts[7], $pts[6],$pts[7],
$fromcolor,$tocolor,$style); $fromcolor,$tocolor,$style);
} }
else { else {
$grad->FilledRectangle($pts[2],$pts[3], $grad->FilledRectangle($pts[2],$pts[3],
$pts[6],$pts[7], $pts[6],$pts[7],
$this->plots[$j]->grad_fromcolor, $this->plots[$j]->grad_fromcolor,
$this->plots[$j]->grad_tocolor, $this->plots[$j]->grad_tocolor,
$this->plots[$j]->grad_style); $this->plots[$j]->grad_style);
} }
} else { } else {
if (is_array($this->plots[$j]->fill_color) ) { if (is_array($this->plots[$j]->fill_color) ) {
$numcolors = count($this->plots[$j]->fill_color); $numcolors = count($this->plots[$j]->fill_color);
$fillcolor = $this->plots[$j]->fill_color[$i % $numcolors]; $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors];
// If the bar is specified to be non filled then the fill color is false // If the bar is specified to be non filled then the fill color is false
if( $fillcolor !== false ) { if( $fillcolor !== false ) {
$img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]); $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
} }
} }
else { else {
$fillcolor = $this->plots[$j]->fill_color; $fillcolor = $this->plots[$j]->fill_color;
if( $fillcolor !== false ) { if( $fillcolor !== false ) {
$img->SetColor($this->plots[$j]->fill_color); $img->SetColor($this->plots[$j]->fill_color);
} }
} }
if( $fillcolor !== false ) { if( $fillcolor !== false ) {
$img->FilledPolygon($pts); $img->FilledPolygon($pts);
} }
} }
   
$img->SetColor($this->plots[$j]->color); $img->SetColor($this->plots[$j]->color);
   
// Stroke the pattern // Stroke the pattern
if( $this->plots[$j]->iPattern > -1 ) { if( $this->plots[$j]->iPattern > -1 ) {
if( $pattern===NULL ) { if( $pattern===NULL ) {
$pattern = new RectPatternFactory(); $pattern = new RectPatternFactory();
} }
   
$prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1); $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1);
$prect->SetDensity($this->plots[$j]->iPatternDensity); $prect->SetDensity($this->plots[$j]->iPatternDensity);
if( $this->plots[$j]->coords[0][$i] < 0 ) { if( $this->plots[$j]->coords[0][$i] < 0 ) {
$rx = $pts[0]; $rx = $pts[0];
$ry = $pts[1]; $ry = $pts[1];
} }
else { else {
$rx = $pts[2]; $rx = $pts[2];
$ry = $pts[3]; $ry = $pts[3];
} }
$width = abs($pts[4]-$pts[0])+1; $width = abs($pts[4]-$pts[0])+1;
$height = abs($pts[1]-$pts[3])+1; $height = abs($pts[1]-$pts[3])+1;
$prect->SetPos(new Rectangle($rx,$ry,$width,$height)); $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
$prect->Stroke($img); $prect->Stroke($img);
} }
   
   
// CSIM array // CSIM array
   
if( $i < count($this->plots[$j]->csimtargets) ) { if( $i < count($this->plots[$j]->csimtargets) ) {
// Create the client side image map // Create the client side image map
$rpts = $img->ArrRotate($pts); $rpts = $img->ArrRotate($pts);
$csimcoord=round($rpts[0]).", ".round($rpts[1]); $csimcoord=round($rpts[0]).", ".round($rpts[1]);
for( $k=1; $k < 4; ++$k){ for( $k=1; $k < 4; ++$k){
$csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]); $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
} }
if( ! empty($this->plots[$j]->csimtargets[$i]) ) { if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
$this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" '; $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
$this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" "; $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" ";
   
if( ! empty($this->plots[$j]->csimwintargets[$i]) ) { if( ! empty($this->plots[$j]->csimwintargets[$i]) ) {
$this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" "; $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" ";
} }
   
$sval=''; $sval='';
if( !empty($this->plots[$j]->csimalts[$i]) ) { if( !empty($this->plots[$j]->csimalts[$i]) ) {
$sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]); $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
$this->csimareas .= " title=\"$sval\" "; $this->csimareas .= " title=\"$sval\" ";
} }
$this->csimareas .= " alt=\"$sval\" />\n"; $this->csimareas .= " alt=\"$sval\" />\n";
} }
} }
   
$pts[] = $pts[0]; $pts[] = $pts[0];
$pts[] = $pts[1]; $pts[] = $pts[1];
$img->SetLineWeight($this->plots[$j]->weight); $img->SetLineWeight($this->plots[$j]->weight);
$img->Polygon($pts); $img->Polygon($pts);
$img->SetLineWeight(1); $img->SetLineWeight(1);
} }
   
// Daw potential bar around the entire accbar bar // Daw potential bar around the entire accbar bar
if( $this->weight > 0 ) { if( $this->weight > 0 ) {
$y=$yscale->Translate(0); $y=$yscale->Translate(0);
$img->SetColor($this->color); $img->SetColor($this->color);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$img->Rectangle($pts[0],$y,$pts[6],$pts[5]); $img->Rectangle($pts[0],$y,$pts[6],$pts[5]);
} }
   
// Draw labels for each acc.bar // Draw labels for each acc.bar
   
$x=$pts[2]+($pts[4]-$pts[2])/2; $x=$pts[2]+($pts[4]-$pts[2])/2;
if($this->bar_shadow) $x += $ssh; if($this->bar_shadow) $x += $ssh;
   
// First stroke the accumulated value for the entire bar // First stroke the accumulated value for the entire bar
// This value is always placed at the top/bottom of the bars // This value is always placed at the top/bottom of the bars
if( $accy_neg < 0 ) { if( $accy_neg < 0 ) {
$y=$yscale->Translate($accy_neg); $y=$yscale->Translate($accy_neg);
$this->value->Stroke($img,$accy_neg,$x,$y); $this->value->Stroke($img,$accy_neg,$x,$y);
} }
else { else {
$y=$yscale->Translate($accy); $y=$yscale->Translate($accy);
$this->value->Stroke($img,$accy,$x,$y); $this->value->Stroke($img,$accy,$x,$y);
} }
   
$accy = 0; $accy = 0;
$accy_neg = 0; $accy_neg = 0;
for($j=0; $j < $this->nbrplots; ++$j ) { for($j=0; $j < $this->nbrplots; ++$j ) {
   
// We don't print 0 values in an accumulated bar plot // 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 ) continue;
   
if ($this->plots[$j]->coords[0][$i] > 0) { if ($this->plots[$j]->coords[0][$i] > 0) {
$yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
$accyt=$yscale->Translate($accy); $accyt=$yscale->Translate($accy);
if( $this->plots[$j]->valuepos=='center' ) { if( $this->plots[$j]->valuepos=='center' ) {
$y = $accyt-($accyt-$yt)/2; $y = $accyt-($accyt-$yt)/2;
} }
elseif( $this->plots[$j]->valuepos=='bottom' ) { elseif( $this->plots[$j]->valuepos=='bottom' ) {
$y = $accyt; $y = $accyt;
} }
else { // top or max else { // top or max
$y = $accyt-($accyt-$yt); $y = $accyt-($accyt-$yt);
} }
$accy+=$this->plots[$j]->coords[0][$i]; $accy+=$this->plots[$j]->coords[0][$i];
if( $this->plots[$j]->valuepos=='center' ) { if( $this->plots[$j]->valuepos=='center' ) {
$this->plots[$j]->value->SetAlign("center","center"); $this->plots[$j]->value->SetAlign("center","center");
$this->plots[$j]->value->SetMargin(0); $this->plots[$j]->value->SetMargin(0);
} }
elseif( $this->plots[$j]->valuepos=='bottom' ) { elseif( $this->plots[$j]->valuepos=='bottom' ) {
$this->plots[$j]->value->SetAlign('center','bottom'); $this->plots[$j]->value->SetAlign('center','bottom');
$this->plots[$j]->value->SetMargin(2); $this->plots[$j]->value->SetMargin(2);
} }
else { else {
$this->plots[$j]->value->SetAlign('center','top'); $this->plots[$j]->value->SetAlign('center','top');
$this->plots[$j]->value->SetMargin(1); $this->plots[$j]->value->SetMargin(1);
} }
} else { } else {
$yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
$accyt=$yscale->Translate($accy_neg); $accyt=$yscale->Translate($accy_neg);
$accy_neg+=$this->plots[$j]->coords[0][$i]; $accy_neg+=$this->plots[$j]->coords[0][$i];
if( $this->plots[$j]->valuepos=='center' ) { if( $this->plots[$j]->valuepos=='center' ) {
$y = $accyt-($accyt-$yt)/2; $y = $accyt-($accyt-$yt)/2;
} }
elseif( $this->plots[$j]->valuepos=='bottom' ) { elseif( $this->plots[$j]->valuepos=='bottom' ) {
$y = $accyt; $y = $accyt;
} }
else { else {
$y = $accyt-($accyt-$yt); $y = $accyt-($accyt-$yt);
} }
if( $this->plots[$j]->valuepos=='center' ) { if( $this->plots[$j]->valuepos=='center' ) {
$this->plots[$j]->value->SetAlign("center","center"); $this->plots[$j]->value->SetAlign("center","center");
$this->plots[$j]->value->SetMargin(0); $this->plots[$j]->value->SetMargin(0);
} }
elseif( $this->plots[$j]->valuepos=='bottom' ) { elseif( $this->plots[$j]->valuepos=='bottom' ) {
$this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top'); $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top');
$this->plots[$j]->value->SetMargin(-2); $this->plots[$j]->value->SetMargin(-2);
} }
else { else {
$this->plots[$j]->value->SetAlign('center','bottom'); $this->plots[$j]->value->SetAlign('center','bottom');
$this->plots[$j]->value->SetMargin(-1); $this->plots[$j]->value->SetMargin(-1);
} }
} }
$this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y); $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
} }
   
} }
return true; return true;
} }
} // Class } // Class
   
/* EOF */ /* EOF */
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_CANVAS.PHP // File: JPGRAPH_CANVAS.PHP
// Description: Canvas drawing extension for JpGraph // Description: Canvas drawing extension for JpGraph
// Created: 2001-01-08 // Created: 2001-01-08
// Ver: $Id: jpgraph_canvas.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_canvas.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
//=================================================== //===================================================
// CLASS CanvasGraph // CLASS CanvasGraph
// Description: Creates a simple canvas graph which // Description: Creates a simple canvas graph which
// might be used together with the basic Image drawing // might be used together with the basic Image drawing
// primitives. Useful to auickoly produce some arbitrary // primitives. Useful to auickoly produce some arbitrary
// graphic which benefits from all the functionality in the // graphic which benefits from all the functionality in the
// graph liek caching for example. // graph liek caching for example.
//=================================================== //===================================================
class CanvasGraph extends Graph { class CanvasGraph extends Graph {
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aWidth=300,$aHeight=200,$aCachedName="",$timeout=0,$inline=1) { function __construct($aWidth=300,$aHeight=200,$aCachedName="",$timeout=0,$inline=1) {
parent::__construct($aWidth,$aHeight,$aCachedName,$timeout,$inline); parent::__construct($aWidth,$aHeight,$aCachedName,$timeout,$inline);
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
function InitFrame() { function InitFrame() {
$this->StrokePlotArea(); $this->StrokePlotArea();
} }
   
// Method description // Method description
function Stroke($aStrokeFileName="") { function Stroke($aStrokeFileName="") {
if( $this->texts != null ) { if( $this->texts != null ) {
for($i=0; $i < count($this->texts); ++$i) { for($i=0; $i < count($this->texts); ++$i) {
$this->texts[$i]->Stroke($this->img); $this->texts[$i]->Stroke($this->img);
} }
} }
if( $this->iTables !== null ) { if( $this->iTables !== null ) {
for($i=0; $i < count($this->iTables); ++$i) { for($i=0; $i < count($this->iTables); ++$i) {
$this->iTables[$i]->Stroke($this->img); $this->iTables[$i]->Stroke($this->img);
} }
} }
$this->StrokeTitles(); $this->StrokeTitles();
   
// If the filename is the predefined value = '_csim_special_' // If the filename is the predefined value = '_csim_special_'
// we assume that the call to stroke only needs to do enough // we assume that the call to stroke only needs to do enough
// to correctly generate the CSIM maps. // to correctly generate the CSIM maps.
// We use this variable to skip things we don't strictly need // We use this variable to skip things we don't strictly need
// to do to generate the image map to improve performance // 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 // a best we can. Therefor you will see a lot of tests !$_csim in the
// code below. // code below.
$_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
   
// We need to know if we have stroked the plot in the // We need to know if we have stroked the plot in the
// GetCSIMareas. Otherwise the CSIM hasn't been generated // GetCSIMareas. Otherwise the CSIM hasn't been generated
// and in the case of GetCSIM called before stroke to generate // and in the case of GetCSIM called before stroke to generate
// CSIM without storing an image to disk GetCSIM must call Stroke. // CSIM without storing an image to disk GetCSIM must call Stroke.
$this->iHasStroked = true; $this->iHasStroked = true;
   
if( !$_csim ) { if( !$_csim ) {
   
// Should we do any final image transformation // Should we do any final image transformation
if( $this->iImgTrans ) { if( $this->iImgTrans ) {
if( !class_exists('ImgTrans') ) { if( !class_exists('ImgTrans') ) {
require_once('jpgraph_imgtrans.php'); require_once('jpgraph_imgtrans.php');
} }
   
$tform = new ImgTrans($this->img->img); $tform = new ImgTrans($this->img->img);
$this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
$this->iImgTransDirection,$this->iImgTransHighQ, $this->iImgTransDirection,$this->iImgTransHighQ,
$this->iImgTransMinSize,$this->iImgTransFillColor, $this->iImgTransMinSize,$this->iImgTransFillColor,
$this->iImgTransBorder); $this->iImgTransBorder);
} }
   
   
// If the filename is given as the special _IMG_HANDLER // If the filename is given as the special _IMG_HANDLER
// then the image handler is returned and the image is NOT // then the image handler is returned and the image is NOT
// streamed back // streamed back
if( $aStrokeFileName == _IMG_HANDLER ) { if( $aStrokeFileName == _IMG_HANDLER ) {
return $this->img->img; return $this->img->img;
} }
else { else {
// Finally stream the generated picture // Finally stream the generated picture
$this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
return true; return true;
} }
} }
} }
} // Class } // Class
   
/* EOF */ /* EOF */
?> ?>
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_CANVTOOLS.PHP // File: JPGRAPH_CANVTOOLS.PHP
// Description: Some utilities for text and shape drawing on a canvas // Description: Some utilities for text and shape drawing on a canvas
// Created: 2002-08-23 // Created: 2002-08-23
// Ver: $Id: jpgraph_canvtools.php 1857 2009-09-28 14:38:14Z ljp $ // Ver: $Id: jpgraph_canvtools.php 1857 2009-09-28 14:38:14Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
define('CORNER_TOPLEFT',0); define('CORNER_TOPLEFT',0);
define('CORNER_TOPRIGHT',1); define('CORNER_TOPRIGHT',1);
define('CORNER_BOTTOMRIGHT',2); define('CORNER_BOTTOMRIGHT',2);
define('CORNER_BOTTOMLEFT',3); define('CORNER_BOTTOMLEFT',3);
   
   
//=================================================== //===================================================
// CLASS CanvasScale // CLASS CanvasScale
// Description: Define a scale for canvas so we // Description: Define a scale for canvas so we
// can abstract away with absolute pixels // can abstract away with absolute pixels
//=================================================== //===================================================
   
class CanvasScale { class CanvasScale {
private $g; private $g;
private $w,$h; private $w,$h;
private $ixmin=0,$ixmax=10,$iymin=0,$iymax=10; private $ixmin=0,$ixmax=10,$iymin=0,$iymax=10;
   
function __construct($graph,$xmin=0,$xmax=10,$ymin=0,$ymax=10) { function __construct($graph,$xmin=0,$xmax=10,$ymin=0,$ymax=10) {
$this->g = $graph; $this->g = $graph;
$this->w = $graph->img->width; $this->w = $graph->img->width;
$this->h = $graph->img->height; $this->h = $graph->img->height;
$this->ixmin = $xmin; $this->ixmin = $xmin;
$this->ixmax = $xmax; $this->ixmax = $xmax;
$this->iymin = $ymin; $this->iymin = $ymin;
$this->iymax = $ymax; $this->iymax = $ymax;
} }
   
function Set($xmin=0,$xmax=10,$ymin=0,$ymax=10) { function Set($xmin=0,$xmax=10,$ymin=0,$ymax=10) {
$this->ixmin = $xmin; $this->ixmin = $xmin;
$this->ixmax = $xmax; $this->ixmax = $xmax;
$this->iymin = $ymin; $this->iymin = $ymin;
$this->iymax = $ymax; $this->iymax = $ymax;
} }
   
function Get() { function Get() {
return array($this->ixmin,$this->ixmax,$this->iymin,$this->iymax); return array($this->ixmin,$this->ixmax,$this->iymin,$this->iymax);
} }
   
function Translate($x,$y) { function Translate($x,$y) {
$xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w); $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
$yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h); $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
return array($xp,$yp); return array($xp,$yp);
} }
   
function TranslateX($x) { function TranslateX($x) {
$xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w); $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
return $xp; return $xp;
} }
   
function TranslateY($y) { function TranslateY($y) {
$yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h); $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
return $yp; return $yp;
} }
   
} }
   
   
//=================================================== //===================================================
// CLASS Shape // CLASS Shape
// Description: Methods to draw shapes on canvas // Description: Methods to draw shapes on canvas
//=================================================== //===================================================
class Shape { class Shape {
private $img,$scale; private $img,$scale;
   
function __construct($aGraph,$scale) { function __construct($aGraph,$scale) {
$this->img = $aGraph->img; $this->img = $aGraph->img;
$this->img->SetColor('black'); $this->img->SetColor('black');
$this->scale = $scale; $this->scale = $scale;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->img->SetColor($aColor); $this->img->SetColor($aColor);
} }
   
function Line($x1,$y1,$x2,$y2) { function Line($x1,$y1,$x2,$y2) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2); list($x2,$y2) = $this->scale->Translate($x2,$y2);
$this->img->Line($x1,$y1,$x2,$y2); $this->img->Line($x1,$y1,$x2,$y2);
} }
   
function SetLineWeight($aWeight) { function SetLineWeight($aWeight) {
$this->img->SetLineWeight($aWeight); $this->img->SetLineWeight($aWeight);
} }
   
function Polygon($p,$aClosed=false) { function Polygon($p,$aClosed=false) {
$n=count($p); $n=count($p);
for($i=0; $i < $n; $i+=2 ) { for($i=0; $i < $n; $i+=2 ) {
$p[$i] = $this->scale->TranslateX($p[$i]); $p[$i] = $this->scale->TranslateX($p[$i]);
$p[$i+1] = $this->scale->TranslateY($p[$i+1]); $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
} }
$this->img->Polygon($p,$aClosed); $this->img->Polygon($p,$aClosed);
} }
   
function FilledPolygon($p) { function FilledPolygon($p) {
$n=count($p); $n=count($p);
for($i=0; $i < $n; $i+=2 ) { for($i=0; $i < $n; $i+=2 ) {
$p[$i] = $this->scale->TranslateX($p[$i]); $p[$i] = $this->scale->TranslateX($p[$i]);
$p[$i+1] = $this->scale->TranslateY($p[$i+1]); $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
} }
$this->img->FilledPolygon($p); $this->img->FilledPolygon($p);
} }
   
   
// Draw a bezier curve with defining points in the $aPnts array // Draw a bezier curve with defining points in the $aPnts array
// using $aSteps steps. // using $aSteps steps.
// 0=x0, 1=y0 // 0=x0, 1=y0
// 2=x1, 3=y1 // 2=x1, 3=y1
// 4=x2, 5=y2 // 4=x2, 5=y2
// 6=x3, 7=y3 // 6=x3, 7=y3
function Bezier($p,$aSteps=40) { function Bezier($p,$aSteps=40) {
$x0 = $p[0]; $x0 = $p[0];
$y0 = $p[1]; $y0 = $p[1];
// Calculate coefficients // Calculate coefficients
$cx = 3*($p[2]-$p[0]); $cx = 3*($p[2]-$p[0]);
$bx = 3*($p[4]-$p[2])-$cx; $bx = 3*($p[4]-$p[2])-$cx;
$ax = $p[6]-$p[0]-$cx-$bx; $ax = $p[6]-$p[0]-$cx-$bx;
$cy = 3*($p[3]-$p[1]); $cy = 3*($p[3]-$p[1]);
$by = 3*($p[5]-$p[3])-$cy; $by = 3*($p[5]-$p[3])-$cy;
$ay = $p[7]-$p[1]-$cy-$by; $ay = $p[7]-$p[1]-$cy-$by;
   
// Step size // Step size
$delta = 1.0/$aSteps; $delta = 1.0/$aSteps;
   
$x_old = $x0; $x_old = $x0;
$y_old = $y0; $y_old = $y0;
for($t=$delta; $t<=1.0; $t+=$delta) { for($t=$delta; $t<=1.0; $t+=$delta) {
$tt = $t*$t; $ttt=$tt*$t; $tt = $t*$t; $ttt=$tt*$t;
$x = $ax*$ttt + $bx*$tt + $cx*$t + $x0; $x = $ax*$ttt + $bx*$tt + $cx*$t + $x0;
$y = $ay*$ttt + $by*$tt + $cy*$t + $y0; $y = $ay*$ttt + $by*$tt + $cy*$t + $y0;
$this->Line($x_old,$y_old,$x,$y); $this->Line($x_old,$y_old,$x,$y);
$x_old = $x; $x_old = $x;
$y_old = $y; $y_old = $y;
} }
$this->Line($x_old,$y_old,$p[6],$p[7]); $this->Line($x_old,$y_old,$p[6],$p[7]);
} }
   
function Rectangle($x1,$y1,$x2,$y2) { function Rectangle($x1,$y1,$x2,$y2) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2); list($x2,$y2) = $this->scale->Translate($x2,$y2);
$this->img->Rectangle($x1,$y1,$x2,$y2); $this->img->Rectangle($x1,$y1,$x2,$y2);
} }
   
function FilledRectangle($x1,$y1,$x2,$y2) { function FilledRectangle($x1,$y1,$x2,$y2) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2); list($x2,$y2) = $this->scale->Translate($x2,$y2);
$this->img->FilledRectangle($x1,$y1,$x2,$y2); $this->img->FilledRectangle($x1,$y1,$x2,$y2);
} }
   
function Circle($x1,$y1,$r) { function Circle($x1,$y1,$r) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
if( $r >= 0 ) if( $r >= 0 )
$r = $this->scale->TranslateX($r); $r = $this->scale->TranslateX($r);
else else
$r = -$r; $r = -$r;
$this->img->Circle($x1,$y1,$r); $this->img->Circle($x1,$y1,$r);
} }
   
function FilledCircle($x1,$y1,$r) { function FilledCircle($x1,$y1,$r) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
if( $r >= 0 ) if( $r >= 0 )
$r = $this->scale->TranslateX($r); $r = $this->scale->TranslateX($r);
else else
$r = -$r; $r = -$r;
$this->img->FilledCircle($x1,$y1,$r); $this->img->FilledCircle($x1,$y1,$r);
} }
   
function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) { function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2); list($x2,$y2) = $this->scale->Translate($x2,$y2);
   
if( $r == null ) if( $r == null )
$r = 5; $r = 5;
elseif( $r >= 0 ) elseif( $r >= 0 )
$r = $this->scale->TranslateX($r); $r = $this->scale->TranslateX($r);
else else
$r = -$r; $r = -$r;
$this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r); $this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r);
} }
   
function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) { function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2); list($x2,$y2) = $this->scale->Translate($x2,$y2);
   
if( $r == null ) if( $r == null )
$r = 5; $r = 5;
elseif( $r > 0 ) elseif( $r > 0 )
$r = $this->scale->TranslateX($r); $r = $this->scale->TranslateX($r);
else else
$r = -$r; $r = -$r;
$this->img->FilledRoundedRectangle($x1,$y1,$x2,$y2,$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)) { 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($x1,$y1) = $this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2); list($x2,$y2) = $this->scale->Translate($x2,$y2);
if( $shadow_width == null ) if( $shadow_width == null )
$shadow_width=4; $shadow_width=4;
else else
$shadow_width=$this->scale->TranslateX($shadow_width); $shadow_width=$this->scale->TranslateX($shadow_width);
$this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color); $this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color);
} }
   
function SetTextAlign($halign,$valign="bottom") { function SetTextAlign($halign,$valign="bottom") {
$this->img->SetTextAlign($halign,$valign="bottom"); $this->img->SetTextAlign($halign,$valign="bottom");
} }
   
function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") { function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") {
list($x1,$y1) = $this->scale->Translate($x1,$y1); list($x1,$y1) = $this->scale->Translate($x1,$y1);
$this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align); $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align);
} }
   
// A rounded rectangle where one of the corner has been moved "into" the // A rounded rectangle where one of the corner has been moved "into" the
// rectangle 'iw' width and 'ih' height. Corners: // rectangle 'iw' width and 'ih' height. Corners:
// 0=Top left, 1=top right, 2=bottom right, 3=bottom left // 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) { function IndentedRectangle($xt,$yt,$w,$h,$iw=0,$ih=0,$aCorner=3,$aFillColor="",$r=4) {
   
list($xt,$yt) = $this->scale->Translate($xt,$yt); list($xt,$yt) = $this->scale->Translate($xt,$yt);
list($w,$h) = $this->scale->Translate($w,$h); list($w,$h) = $this->scale->Translate($w,$h);
list($iw,$ih) = $this->scale->Translate($iw,$ih); list($iw,$ih) = $this->scale->Translate($iw,$ih);
   
$xr = $xt + $w - 0; $xr = $xt + $w - 0;
$yl = $yt + $h - 0; $yl = $yt + $h - 0;
   
switch( $aCorner ) { switch( $aCorner ) {
case 0: // Upper left case 0: // Upper left
// Bottom line, left & right arc // Bottom line, left & right arc
$this->img->Line($xt+$r,$yl,$xr-$r,$yl); $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($xt+$r,$yl-$r,$r*2,$r*2,90,180);
$this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
   
// Right line, Top right arc // Right line, Top right arc
$this->img->Line($xr,$yt+$r,$xr,$yl-$r); $this->img->Line($xr,$yt+$r,$xr,$yl-$r);
$this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
   
// Top line, Top left arc // Top line, Top left arc
$this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt); $this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt);
$this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270); $this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270);
   
// Left line // Left line
$this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r); $this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r);
   
// Indent horizontal, Lower left arc // Indent horizontal, Lower left arc
$this->img->Line($xt+$r,$yt+$ih,$xt+$iw-$r,$yt+$ih); $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); $this->img->Arc($xt+$r,$yt+$ih+$r,$r*2,$r*2,180,270);
   
// Indent vertical, Indent arc // Indent vertical, Indent arc
$this->img->Line($xt+$iw,$yt+$r,$xt+$iw,$yt+$ih-$r); $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); $this->img->Arc($xt+$iw-$r,$yt+$ih-$r,$r*2,$r*2,0,90);
   
if( $aFillColor != '' ) { if( $aFillColor != '' ) {
$bc = $this->img->current_color_name; $bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor); $this->img->PushColor($aFillColor);
$this->img->FillToBorder($xr-$r,$yl-$r,$bc); $this->img->FillToBorder($xr-$r,$yl-$r,$bc);
$this->img->PopColor(); $this->img->PopColor();
} }
   
break; break;
   
case 1: // Upper right case 1: // Upper right
   
// Bottom line, left & right arc // Bottom line, left & right arc
$this->img->Line($xt+$r,$yl,$xr-$r,$yl); $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($xt+$r,$yl-$r,$r*2,$r*2,90,180);
$this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
   
// Left line, Top left arc // Left line, Top left arc
$this->img->Line($xt,$yt+$r,$xt,$yl-$r); $this->img->Line($xt,$yt+$r,$xt,$yl-$r);
$this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270); $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
   
// Top line, Top right arc // Top line, Top right arc
$this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt); $this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt);
$this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360); $this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360);
   
// Right line // Right line
$this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r); $this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r);
   
// Indent horizontal, Lower right arc // Indent horizontal, Lower right arc
$this->img->Line($xr-$iw+$r,$yt+$ih,$xr-$r,$yt+$ih); $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); $this->img->Arc($xr-$r,$yt+$ih+$r,$r*2,$r*2,270,360);
   
// Indent vertical, Indent arc // Indent vertical, Indent arc
$this->img->Line($xr-$iw,$yt+$r,$xr-$iw,$yt+$ih-$r); $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); $this->img->Arc($xr-$iw+$r,$yt+$ih-$r,$r*2,$r*2,90,180);
   
if( $aFillColor != '' ) { if( $aFillColor != '' ) {
$bc = $this->img->current_color_name; $bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor); $this->img->PushColor($aFillColor);
$this->img->FillToBorder($xt+$r,$yl-$r,$bc); $this->img->FillToBorder($xt+$r,$yl-$r,$bc);
$this->img->PopColor(); $this->img->PopColor();
} }
   
break; break;
   
case 2: // Lower right case 2: // Lower right
// Top line, Top left & Top right arc // Top line, Top left & Top right arc
$this->img->Line($xt+$r,$yt,$xr-$r,$yt); $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($xt+$r,$yt+$r,$r*2,$r*2,180,270);
$this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
   
// Left line, Bottom left arc // Left line, Bottom left arc
$this->img->Line($xt,$yt+$r,$xt,$yl-$r); $this->img->Line($xt,$yt+$r,$xt,$yl-$r);
$this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180); $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
   
// Bottom line, Bottom right arc // Bottom line, Bottom right arc
$this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl); $this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl);
$this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90); $this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90);
   
// Right line // Right line
$this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r); $this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r);
// Indent horizontal, Lower right arc // Indent horizontal, Lower right arc
$this->img->Line($xr-$r,$yl-$ih,$xr-$iw+$r,$yl-$ih); $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); $this->img->Arc($xr-$r,$yl-$ih-$r,$r*2,$r*2,0,90);
   
// Indent vertical, Indent arc // Indent vertical, Indent arc
$this->img->Line($xr-$iw,$yl-$r,$xr-$iw,$yl-$ih+$r); $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); $this->img->Arc($xr-$iw+$r,$yl-$ih+$r,$r*2,$r*2,180,270);
   
if( $aFillColor != '' ) { if( $aFillColor != '' ) {
$bc = $this->img->current_color_name; $bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor); $this->img->PushColor($aFillColor);
$this->img->FillToBorder($xt+$r,$yt+$r,$bc); $this->img->FillToBorder($xt+$r,$yt+$r,$bc);
$this->img->PopColor(); $this->img->PopColor();
} }
   
break; break;
   
case 3: // Lower left case 3: // Lower left
// Top line, Top left & Top right arc // Top line, Top left & Top right arc
$this->img->Line($xt+$r,$yt,$xr-$r,$yt); $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($xt+$r,$yt+$r,$r*2,$r*2,180,270);
$this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360); $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
   
// Right line, Bottom right arc // Right line, Bottom right arc
$this->img->Line($xr,$yt+$r,$xr,$yl-$r); $this->img->Line($xr,$yt+$r,$xr,$yl-$r);
$this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90); $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
   
// Bottom line, Bottom left arc // Bottom line, Bottom left arc
$this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl); $this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl);
$this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180); $this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180);
   
// Left line // Left line
$this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r); $this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r);
// Indent horizontal, Lower left arc // Indent horizontal, Lower left arc
$this->img->Line($xt+$r,$yl-$ih,$xt+$iw-$r,$yl-$ih); $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); $this->img->Arc($xt+$r,$yl-$ih-$r,$r*2,$r*2,90,180);
   
// Indent vertical, Indent arc // Indent vertical, Indent arc
$this->img->Line($xt+$iw,$yl-$ih+$r,$xt+$iw,$yl-$r); $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); $this->img->Arc($xt+$iw-$r,$yl-$ih+$r,$r*2,$r*2,270,360);
   
if( $aFillColor != '' ) { if( $aFillColor != '' ) {
$bc = $this->img->current_color_name; $bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor); $this->img->PushColor($aFillColor);
$this->img->FillToBorder($xr-$r,$yt+$r,$bc); $this->img->FillToBorder($xr-$r,$yt+$r,$bc);
$this->img->PopColor(); $this->img->PopColor();
} }
   
break; break;
} }
} }
} }
   
   
//=================================================== //===================================================
// CLASS RectangleText // CLASS RectangleText
// Description: Draws a text paragraph inside a // Description: Draws a text paragraph inside a
// rounded, possible filled, rectangle. // rounded, possible filled, rectangle.
//=================================================== //===================================================
class CanvasRectangleText { class CanvasRectangleText {
private $ix,$iy,$iw,$ih,$ir=4; private $ix,$iy,$iw,$ih,$ir=4;
private $iTxt,$iColor='black',$iFillColor='',$iFontColor='black'; private $iTxt,$iColor='black',$iFillColor='',$iFontColor='black';
private $iParaAlign='center'; private $iParaAlign='center';
private $iAutoBoxMargin=5; private $iAutoBoxMargin=5;
private $iShadowWidth=3,$iShadowColor=''; private $iShadowWidth=3,$iShadowColor='';
   
function __construct($aTxt='',$xl=0,$yt=0,$w=0,$h=0) { function __construct($aTxt='',$xl=0,$yt=0,$w=0,$h=0) {
$this->iTxt = new Text($aTxt); $this->iTxt = new Text($aTxt);
$this->ix = $xl; $this->ix = $xl;
$this->iy = $yt; $this->iy = $yt;
$this->iw = $w; $this->iw = $w;
$this->ih = $h; $this->ih = $h;
} }
   
function SetShadow($aColor='gray',$aWidth=3) { function SetShadow($aColor='gray',$aWidth=3) {
$this->iShadowColor = $aColor; $this->iShadowColor = $aColor;
$this->iShadowWidth = $aWidth; $this->iShadowWidth = $aWidth;
} }
   
function SetFont($FontFam,$aFontStyle,$aFontSize=12) { function SetFont($FontFam,$aFontStyle,$aFontSize=12) {
$this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize); $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize);
} }
   
function SetTxt($aTxt) { function SetTxt($aTxt) {
$this->iTxt->Set($aTxt); $this->iTxt->Set($aTxt);
} }
   
function ParagraphAlign($aParaAlign) { function ParagraphAlign($aParaAlign) {
$this->iParaAlign = $aParaAlign; $this->iParaAlign = $aParaAlign;
} }
   
function SetFillColor($aFillColor) { function SetFillColor($aFillColor) {
$this->iFillColor = $aFillColor; $this->iFillColor = $aFillColor;
} }
   
function SetAutoMargin($aMargin) { function SetAutoMargin($aMargin) {
$this->iAutoBoxMargin=$aMargin; $this->iAutoBoxMargin=$aMargin;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function SetFontColor($aColor) { function SetFontColor($aColor) {
$this->iFontColor = $aColor; $this->iFontColor = $aColor;
} }
   
function SetPos($xl=0,$yt=0,$w=0,$h=0) { function SetPos($xl=0,$yt=0,$w=0,$h=0) {
$this->ix = $xl; $this->ix = $xl;
$this->iy = $yt; $this->iy = $yt;
$this->iw = $w; $this->iw = $w;
$this->ih = $h; $this->ih = $h;
} }
   
function Pos($xl=0,$yt=0,$w=0,$h=0) { function Pos($xl=0,$yt=0,$w=0,$h=0) {
$this->ix = $xl; $this->ix = $xl;
$this->iy = $yt; $this->iy = $yt;
$this->iw = $w; $this->iw = $w;
$this->ih = $h; $this->ih = $h;
} }
   
function Set($aTxt,$xl,$yt,$w=0,$h=0) { function Set($aTxt,$xl,$yt,$w=0,$h=0) {
$this->iTxt->Set($aTxt); $this->iTxt->Set($aTxt);
$this->ix = $xl; $this->ix = $xl;
$this->iy = $yt; $this->iy = $yt;
$this->iw = $w; $this->iw = $w;
$this->ih = $h; $this->ih = $h;
} }
   
function SetCornerRadius($aRad=5) { function SetCornerRadius($aRad=5) {
$this->ir = $aRad; $this->ir = $aRad;
} }
   
function Stroke($aImg,$scale) { function Stroke($aImg,$scale) {
   
// If coordinates are specifed as negative this means we should // If coordinates are specifed as negative this means we should
// treat them as abolsute (pixels) coordinates // treat them as abolsute (pixels) coordinates
if( $this->ix > 0 ) { if( $this->ix > 0 ) {
$this->ix = $scale->TranslateX($this->ix) ; $this->ix = $scale->TranslateX($this->ix) ;
} }
else { else {
$this->ix = -$this->ix; $this->ix = -$this->ix;
} }
   
if( $this->iy > 0 ) { if( $this->iy > 0 ) {
$this->iy = $scale->TranslateY($this->iy) ; $this->iy = $scale->TranslateY($this->iy) ;
} }
else { else {
$this->iy = -$this->iy; $this->iy = -$this->iy;
} }
list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ; list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ;
   
if( $this->iw == 0 ) if( $this->iw == 0 )
$this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin); $this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin);
if( $this->ih == 0 ) { if( $this->ih == 0 ) {
$this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin); $this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin);
} }
   
if( $this->iShadowColor != '' ) { if( $this->iShadowColor != '' ) {
$aImg->PushColor($this->iShadowColor); $aImg->PushColor($this->iShadowColor);
$aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth, $aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth,
$this->iy+$this->iShadowWidth, $this->iy+$this->iShadowWidth,
$this->ix+$this->iw-1+$this->iShadowWidth, $this->ix+$this->iw-1+$this->iShadowWidth,
$this->iy+$this->ih-1+$this->iShadowWidth, $this->iy+$this->ih-1+$this->iShadowWidth,
$this->ir); $this->ir);
$aImg->PopColor(); $aImg->PopColor();
} }
   
if( $this->iFillColor != '' ) { if( $this->iFillColor != '' ) {
$aImg->PushColor($this->iFillColor); $aImg->PushColor($this->iFillColor);
$aImg->FilledRoundedRectangle($this->ix,$this->iy, $aImg->FilledRoundedRectangle($this->ix,$this->iy,
$this->ix+$this->iw-1, $this->ix+$this->iw-1,
$this->iy+$this->ih-1, $this->iy+$this->ih-1,
$this->ir); $this->ir);
$aImg->PopColor(); $aImg->PopColor();
} }
   
if( $this->iColor != '' ) { if( $this->iColor != '' ) {
$aImg->PushColor($this->iColor); $aImg->PushColor($this->iColor);
$aImg->RoundedRectangle($this->ix,$this->iy, $aImg->RoundedRectangle($this->ix,$this->iy,
$this->ix+$this->iw-1, $this->ix+$this->iw-1,
$this->iy+$this->ih-1, $this->iy+$this->ih-1,
$this->ir); $this->ir);
$aImg->PopColor(); $aImg->PopColor();
} }
   
$this->iTxt->Align('center','center'); $this->iTxt->Align('center','center');
$this->iTxt->ParagraphAlign($this->iParaAlign); $this->iTxt->ParagraphAlign($this->iParaAlign);
$this->iTxt->SetColor($this->iFontColor); $this->iTxt->SetColor($this->iFontColor);
$this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2); $this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2);
   
return array($this->iw, $this->ih); return array($this->iw, $this->ih);
   
} }
   
} }
   
   
?> ?>
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_CONTOUR.PHP // File: JPGRAPH_CONTOUR.PHP
// Description: Contour plot // Description: Contour plot
// Created: 2009-03-08 // Created: 2009-03-08
// Ver: $Id: jpgraph_contour.php 1870 2009-09-29 04:24:18Z ljp $ // Ver: $Id: jpgraph_contour.php 1870 2009-09-29 04:24:18Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
require_once('jpgraph_meshinterpolate.inc.php'); require_once('jpgraph_meshinterpolate.inc.php');
define('HORIZ_EDGE',0); define('HORIZ_EDGE',0);
define('VERT_EDGE',1); define('VERT_EDGE',1);
   
/** /**
* This class encapsulates the core contour plot algorithm. It will find the path * This class encapsulates the core contour plot algorithm. It will find the path
* of the specified isobars in the data matrix specified. It is assumed that the * of the specified isobars in the data matrix specified. It is assumed that the
* data matrix models an equspaced X-Y mesh of datavalues corresponding to the Z * data matrix models an equspaced X-Y mesh of datavalues corresponding to the Z
* values. * values.
* *
*/ */
class Contour { class Contour {
   
private $dataPoints = array(); private $dataPoints = array();
private $nbrCols=0,$nbrRows=0; private $nbrCols=0,$nbrRows=0;
private $horizEdges = array(), $vertEdges=array(); private $horizEdges = array(), $vertEdges=array();
private $isobarValues = array(); private $isobarValues = array();
private $stack = null; private $stack = null;
private $isobarCoord = array(); private $isobarCoord = array();
private $nbrIsobars = 10, $isobarColors = array(); private $nbrIsobars = 10, $isobarColors = array();
private $invert = true; private $invert = true;
private $highcontrast = false, $highcontrastbw = false; private $highcontrast = false, $highcontrastbw = false;
   
/** /**
* Create a new contour level "algorithm machine". * Create a new contour level "algorithm machine".
* @param $aMatrix The values to find the contour from * @param $aMatrix The values to find the contour from
* @param $aIsobars Mixed. If integer it determines the number of isobars to be used. The levels are determined * @param $aIsobars Mixed. If integer it determines the number of isobars to be used. The levels are determined
* automatically as equdistance between the min and max value of the matrice. * automatically as equdistance between the min and max value of the matrice.
* If $aIsobars is an array then this is interpretated as an array of values to be used as isobars in the * If $aIsobars is an array then this is interpretated as an array of values to be used as isobars in the
* contour plot. * contour plot.
* @return an instance of the contour algorithm * @return an instance of the contour algorithm
*/ */
function __construct($aMatrix,$aIsobars=10, $aColors=null) { function __construct($aMatrix,$aIsobars=10, $aColors=null) {
   
$this->nbrRows = count($aMatrix); $this->nbrRows = count($aMatrix);
$this->nbrCols = count($aMatrix[0]); $this->nbrCols = count($aMatrix[0]);
$this->dataPoints = $aMatrix; $this->dataPoints = $aMatrix;
   
if( is_array($aIsobars) ) { if( is_array($aIsobars) ) {
// use the isobar values supplied // use the isobar values supplied
$this->nbrIsobars = count($aIsobars); $this->nbrIsobars = count($aIsobars);
$this->isobarValues = $aIsobars; $this->isobarValues = $aIsobars;
} }
else { else {
// Determine the isobar values automatically // Determine the isobar values automatically
$this->nbrIsobars = $aIsobars; $this->nbrIsobars = $aIsobars;
list($min,$max) = $this->getMinMaxVal(); list($min,$max) = $this->getMinMaxVal();
$stepSize = ($max-$min) / $aIsobars ; $stepSize = ($max-$min) / $aIsobars ;
$isobar = $min+$stepSize/2; $isobar = $min+$stepSize/2;
for ($i = 0; $i < $aIsobars; $i++) { for ($i = 0; $i < $aIsobars; $i++) {
$this->isobarValues[$i] = $isobar; $this->isobarValues[$i] = $isobar;
$isobar += $stepSize; $isobar += $stepSize;
} }
} }
   
if( $aColors !== null && count($aColors) > 0 ) { if( $aColors !== null && count($aColors) > 0 ) {
   
if( !is_array($aColors) ) { if( !is_array($aColors) ) {
JpGraphError::RaiseL(28001); JpGraphError::RaiseL(28001);
//'Third argument to Contour must be an array of colors.' //'Third argument to Contour must be an array of colors.'
} }
   
if( count($aColors) != count($this->isobarValues) ) { if( count($aColors) != count($this->isobarValues) ) {
JpGraphError::RaiseL(28002); JpGraphError::RaiseL(28002);
//'Number of colors must equal the number of isobar lines specified'; //'Number of colors must equal the number of isobar lines specified';
} }
   
$this->isobarColors = $aColors; $this->isobarColors = $aColors;
} }
} }
   
/** /**
* Flip the plot around the Y-coordinate. This has the same affect as flipping the input * Flip the plot around the Y-coordinate. This has the same affect as flipping the input
* data matrice * data matrice
* *
* @param $aFlg If true the the vertice in input data matrice position (0,0) corresponds to the top left * @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) * corner of teh plot otherwise it will correspond to the bottom left corner (a horizontal flip)
*/ */
function SetInvert($aFlg=true) { function SetInvert($aFlg=true) {
$this->invert = $aFlg; $this->invert = $aFlg;
} }
   
/** /**
* Find the min and max values in the data matrice * Find the min and max values in the data matrice
* *
* @return array(min_value,max_value) * @return array(min_value,max_value)
*/ */
function getMinMaxVal() { function getMinMaxVal() {
$min = $this->dataPoints[0][0]; $min = $this->dataPoints[0][0];
$max = $this->dataPoints[0][0]; $max = $this->dataPoints[0][0];
for ($i = 0; $i < $this->nbrRows; $i++) { for ($i = 0; $i < $this->nbrRows; $i++) {
if( ($mi=min($this->dataPoints[$i])) < $min ) $min = $mi; if( ($mi=min($this->dataPoints[$i])) < $min ) $min = $mi;
if( ($ma=max($this->dataPoints[$i])) > $max ) $max = $ma; if( ($ma=max($this->dataPoints[$i])) > $max ) $max = $ma;
} }
return array($min,$max); return array($min,$max);
} }
   
/** /**
* Reset the two matrices that keeps track on where the isobars crosses the * Reset the two matrices that keeps track on where the isobars crosses the
* horizontal and vertical edges * horizontal and vertical edges
*/ */
function resetEdgeMatrices() { function resetEdgeMatrices() {
for ($k = 0; $k < 2; $k++) { for ($k = 0; $k < 2; $k++) {
for ($i = 0; $i <= $this->nbrRows; $i++) { for ($i = 0; $i <= $this->nbrRows; $i++) {
for ($j = 0; $j <= $this->nbrCols; $j++) { for ($j = 0; $j <= $this->nbrCols; $j++) {
$this->edges[$k][$i][$j] = false; $this->edges[$k][$i][$j] = false;
} }
} }
} }
} }
   
/** /**
* Determine if the specified isobar crosses the horizontal edge specified by its row and column * 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 $aRow Row index of edge to be checked
* @param $aCol Col index of edge to be checked * @param $aCol Col index of edge to be checked
* @param $aIsobar Isobar value * @param $aIsobar Isobar value
* @return true if the isobar is crossing this edge * @return true if the isobar is crossing this edge
*/ */
function isobarHCrossing($aRow,$aCol,$aIsobar) { function isobarHCrossing($aRow,$aCol,$aIsobar) {
   
if( $aCol >= $this->nbrCols-1 ) { if( $aCol >= $this->nbrCols-1 ) {
JpGraphError::RaiseL(28003,$aCol); JpGraphError::RaiseL(28003,$aCol);
//'ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)' //'ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)'
} }
if( $aRow >= $this->nbrRows ) { if( $aRow >= $this->nbrRows ) {
JpGraphError::RaiseL(28004,$aRow); JpGraphError::RaiseL(28004,$aRow);
//'ContourPlot Internal Error: isobarHCrossing: Row index too large (%d)' //'ContourPlot Internal Error: isobarHCrossing: Row index too large (%d)'
} }
   
$v1 = $this->dataPoints[$aRow][$aCol]; $v1 = $this->dataPoints[$aRow][$aCol];
$v2 = $this->dataPoints[$aRow][$aCol+1]; $v2 = $this->dataPoints[$aRow][$aCol+1];
   
return ($aIsobar-$v1)*($aIsobar-$v2) < 0 ; return ($aIsobar-$v1)*($aIsobar-$v2) < 0 ;
   
} }
   
/** /**
* Determine if the specified isobar crosses the vertical edge specified by its row and column * 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 $aRow Row index of edge to be checked
* @param $aCol Col index of edge to be checked * @param $aCol Col index of edge to be checked
* @param $aIsobar Isobar value * @param $aIsobar Isobar value
* @return true if the isobar is crossing this edge * @return true if the isobar is crossing this edge
*/ */
function isobarVCrossing($aRow,$aCol,$aIsobar) { function isobarVCrossing($aRow,$aCol,$aIsobar) {
   
if( $aRow >= $this->nbrRows-1) { if( $aRow >= $this->nbrRows-1) {
JpGraphError::RaiseL(28005,$aRow); JpGraphError::RaiseL(28005,$aRow);
//'isobarVCrossing: Row index too large //'isobarVCrossing: Row index too large
} }
if( $aCol >= $this->nbrCols ) { if( $aCol >= $this->nbrCols ) {
JpGraphError::RaiseL(28006,$aCol); JpGraphError::RaiseL(28006,$aCol);
//'isobarVCrossing: Col index too large //'isobarVCrossing: Col index too large
} }
   
$v1 = $this->dataPoints[$aRow][$aCol]; $v1 = $this->dataPoints[$aRow][$aCol];
$v2 = $this->dataPoints[$aRow+1][$aCol]; $v2 = $this->dataPoints[$aRow+1][$aCol];
   
return ($aIsobar-$v1)*($aIsobar-$v2) < 0 ; return ($aIsobar-$v1)*($aIsobar-$v2) < 0 ;
   
} }
   
/** /**
* Determine all edges, horizontal and vertical that the specified isobar crosses. The crossings * Determine all edges, horizontal and vertical that the specified isobar crosses. The crossings
* are recorded in the two edge matrices. * are recorded in the two edge matrices.
* *
* @param $aIsobar The value of the isobar to be checked * @param $aIsobar The value of the isobar to be checked
*/ */
function determineIsobarEdgeCrossings($aIsobar) { function determineIsobarEdgeCrossings($aIsobar) {
   
$ib = $this->isobarValues[$aIsobar]; $ib = $this->isobarValues[$aIsobar];
   
for ($i = 0; $i < $this->nbrRows-1; $i++) { for ($i = 0; $i < $this->nbrRows-1; $i++) {
for ($j = 0; $j < $this->nbrCols-1; $j++) { for ($j = 0; $j < $this->nbrCols-1; $j++) {
$this->edges[HORIZ_EDGE][$i][$j] = $this->isobarHCrossing($i,$j,$ib); $this->edges[HORIZ_EDGE][$i][$j] = $this->isobarHCrossing($i,$j,$ib);
$this->edges[VERT_EDGE][$i][$j] = $this->isobarVCrossing($i,$j,$ib); $this->edges[VERT_EDGE][$i][$j] = $this->isobarVCrossing($i,$j,$ib);
} }
} }
   
// We now have the bottom and rightmost edges unsearched // We now have the bottom and rightmost edges unsearched
for ($i = 0; $i < $this->nbrRows-1; $i++) { for ($i = 0; $i < $this->nbrRows-1; $i++) {
$this->edges[VERT_EDGE][$i][$j] = $this->isobarVCrossing($i,$this->nbrCols-1,$ib); $this->edges[VERT_EDGE][$i][$j] = $this->isobarVCrossing($i,$this->nbrCols-1,$ib);
} }
for ($j = 0; $j < $this->nbrCols-1; $j++) { for ($j = 0; $j < $this->nbrCols-1; $j++) {
$this->edges[HORIZ_EDGE][$i][$j] = $this->isobarHCrossing($this->nbrRows-1,$j,$ib); $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 * 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 * 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 * on each side of the edge and the value of the isobar
* *
* @param $aRow Row of edge * @param $aRow Row of edge
* @param $aCol Column of edge * @param $aCol Column of edge
* @param $aEdgeDir Determine if this is a horizontal or vertical edge * @param $aEdgeDir Determine if this is a horizontal or vertical edge
* @param $ib The isobar value * @param $ib The isobar value
* @return unknown_type * @return unknown_type
*/ */
function getCrossingCoord($aRow,$aCol,$aEdgeDir,$aIsobarVal) { function getCrossingCoord($aRow,$aCol,$aEdgeDir,$aIsobarVal) {
   
// In order to avoid numerical problem when two vertices are very close // In order to avoid numerical problem when two vertices are very close
// we have to check and avoid dividing by close to zero denumerator. // we have to check and avoid dividing by close to zero denumerator.
if( $aEdgeDir == HORIZ_EDGE ) { if( $aEdgeDir == HORIZ_EDGE ) {
$d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow][$aCol+1]); $d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow][$aCol+1]);
if( $d > 0.001 ) { if( $d > 0.001 ) {
$xcoord = $aCol + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d; $xcoord = $aCol + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d;
} }
else { else {
$xcoord = $aCol; $xcoord = $aCol;
} }
$ycoord = $aRow; $ycoord = $aRow;
} }
else { else {
$d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow+1][$aCol]); $d = abs($this->dataPoints[$aRow][$aCol] - $this->dataPoints[$aRow+1][$aCol]);
if( $d > 0.001 ) { if( $d > 0.001 ) {
$ycoord = $aRow + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d; $ycoord = $aRow + abs($aIsobarVal - $this->dataPoints[$aRow][$aCol]) / $d;
} }
else { else {
$ycoord = $aRow; $ycoord = $aRow;
} }
$xcoord = $aCol; $xcoord = $aCol;
} }
if( $this->invert ) { if( $this->invert ) {
$ycoord = $this->nbrRows-1 - $ycoord; $ycoord = $this->nbrRows-1 - $ycoord;
} }
return array($xcoord,$ycoord); return array($xcoord,$ycoord);
   
} }
   
/** /**
* In order to avoid all kinds of unpleasent extra checks and complex boundary * In order to avoid all kinds of unpleasent extra checks and complex boundary
* controls for the degenerated case where the contour levels exactly crosses * 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. * 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. * This has no visible affect but it makes the code sooooo much cleaner.
* *
*/ */
function adjustDataPointValues() { function adjustDataPointValues() {
   
$ni = count($this->isobarValues); $ni = count($this->isobarValues);
for ($k = 0; $k < $ni; $k++) { for ($k = 0; $k < $ni; $k++) {
$ib = $this->isobarValues[$k]; $ib = $this->isobarValues[$k];
for ($row = 0 ; $row < $this->nbrRows-1; ++$row) { for ($row = 0 ; $row < $this->nbrRows-1; ++$row) {
for ($col = 0 ; $col < $this->nbrCols-1; ++$col ) { for ($col = 0 ; $col < $this->nbrCols-1; ++$col ) {
if( abs($this->dataPoints[$row][$col] - $ib) < 0.0001 ) { if( abs($this->dataPoints[$row][$col] - $ib) < 0.0001 ) {
$this->dataPoints[$row][$col] += $this->dataPoints[$row][$col]*0.001; $this->dataPoints[$row][$col] += $this->dataPoints[$row][$col]*0.001;
} }
} }
} }
} }
   
} }
   
/** /**
* @param $aFlg * @param $aFlg
* @param $aBW * @param $aBW
* @return unknown_type * @return unknown_type
*/ */
function UseHighContrastColor($aFlg=true,$aBW=false) { function UseHighContrastColor($aFlg=true,$aBW=false) {
$this->highcontrast = $aFlg; $this->highcontrast = $aFlg;
$this->highcontrastbw = $aBW; $this->highcontrastbw = $aBW;
} }
   
/** /**
* Calculate suitable colors for each defined isobar * Calculate suitable colors for each defined isobar
* *
*/ */
function CalculateColors() { function CalculateColors() {
if ( $this->highcontrast ) { if ( $this->highcontrast ) {
if ( $this->highcontrastbw ) { if ( $this->highcontrastbw ) {
for ($ib = 0; $ib < $this->nbrIsobars; $ib++) { for ($ib = 0; $ib < $this->nbrIsobars; $ib++) {
$this->isobarColors[$ib] = 'black'; $this->isobarColors[$ib] = 'black';
} }
} }
else { else {
// Use only blue/red scale // Use only blue/red scale
$step = round(255/($this->nbrIsobars-1)); $step = round(255/($this->nbrIsobars-1));
for ($ib = 0; $ib < $this->nbrIsobars; $ib++) { for ($ib = 0; $ib < $this->nbrIsobars; $ib++) {
$this->isobarColors[$ib] = array($ib*$step, 50, 255-$ib*$step); $this->isobarColors[$ib] = array($ib*$step, 50, 255-$ib*$step);
} }
} }
} }
else { else {
$n = $this->nbrIsobars; $n = $this->nbrIsobars;
$v = 0; $step = 1 / ($this->nbrIsobars-1); $v = 0; $step = 1 / ($this->nbrIsobars-1);
for ($ib = 0; $ib < $this->nbrIsobars; $ib++) { for ($ib = 0; $ib < $this->nbrIsobars; $ib++) {
$this->isobarColors[$ib] = RGB::GetSpectrum($v); $this->isobarColors[$ib] = RGB::GetSpectrum($v);
$v += $step; $v += $step;
} }
} }
} }
   
/** /**
* This is where the main work is done. For each isobar the crossing of the edges are determined * 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 * 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 * 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 * the $isobarCoord will hold one arrayfor each isobar where all the line segments that makes
* up the contour plot are stored. * up the contour plot are stored.
* *
* @return array( $isobarCoord, $isobarValues, $isobarColors ) * @return array( $isobarCoord, $isobarValues, $isobarColors )
*/ */
function getIsobars() { function getIsobars() {
   
$this->adjustDataPointValues(); $this->adjustDataPointValues();
   
for ($isobar = 0; $isobar < $this->nbrIsobars; $isobar++) { for ($isobar = 0; $isobar < $this->nbrIsobars; $isobar++) {
   
$ib = $this->isobarValues[$isobar]; $ib = $this->isobarValues[$isobar];
$this->resetEdgeMatrices(); $this->resetEdgeMatrices();
$this->determineIsobarEdgeCrossings($isobar); $this->determineIsobarEdgeCrossings($isobar);
$this->isobarCoord[$isobar] = array(); $this->isobarCoord[$isobar] = array();
   
$ncoord = 0; $ncoord = 0;
   
for ($row = 0 ; $row < $this->nbrRows-1; ++$row) { for ($row = 0 ; $row < $this->nbrRows-1; ++$row) {
for ($col = 0 ; $col < $this->nbrCols-1; ++$col ) { for ($col = 0 ; $col < $this->nbrCols-1; ++$col ) {
   
// Find out how many crossings around the edges // Find out how many crossings around the edges
$n = 0; $n = 0;
if ( $this->edges[HORIZ_EDGE][$row][$col] ) $neigh[$n++] = array($row, $col, HORIZ_EDGE); 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[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] ) $neigh[$n++] = array($row, $col, VERT_EDGE);
if ( $this->edges[VERT_EDGE][$row][$col+1] ) $neigh[$n++] = array($row, $col+1,VERT_EDGE); if ( $this->edges[VERT_EDGE][$row][$col+1] ) $neigh[$n++] = array($row, $col+1,VERT_EDGE);
   
if ( $n == 2 ) { if ( $n == 2 ) {
$n1=0; $n2=1; $n1=0; $n2=1;
$this->isobarCoord[$isobar][$ncoord++] = array( $this->isobarCoord[$isobar][$ncoord++] = array(
$this->getCrossingCoord($neigh[$n1][0],$neigh[$n1][1],$neigh[$n1][2],$ib), $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->getCrossingCoord($neigh[$n2][0],$neigh[$n2][1],$neigh[$n2][2],$ib) );
} }
elseif ( $n == 4 ) { elseif ( $n == 4 ) {
// We must determine how to connect the edges either northwest->southeast or // We must determine how to connect the edges either northwest->southeast or
// northeast->southwest. We do that by calculating the imaginary middle value of // 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 // 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 // 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; $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]; $v = $this->dataPoints[$row][$col];
if( $midval == $ib ) { if( $midval == $ib ) {
// Orientation "+" // Orientation "+"
$n1=0; $n2=1; $n3=2; $n4=3; $n1=0; $n2=1; $n3=2; $n4=3;
} elseif ( ($midval > $ib && $v > $ib) || ($midval < $ib && $v < $ib) ) { } elseif ( ($midval > $ib && $v > $ib) || ($midval < $ib && $v < $ib) ) {
// Orientation of ridge/valley = "\" // Orientation of ridge/valley = "\"
$n1=0; $n2=3; $n3=2; $n4=1; $n1=0; $n2=3; $n3=2; $n4=1;
} elseif ( ($midval > $ib && $v < $ib) || ($midval < $ib && $v > $ib) ) { } elseif ( ($midval > $ib && $v < $ib) || ($midval < $ib && $v > $ib) ) {
// Orientation of ridge/valley = "/" // Orientation of ridge/valley = "/"
$n1=0; $n2=2; $n3=3; $n4=1; $n1=0; $n2=2; $n3=3; $n4=1;
} }
   
$this->isobarCoord[$isobar][$ncoord++] = array( $this->isobarCoord[$isobar][$ncoord++] = array(
$this->getCrossingCoord($neigh[$n1][0],$neigh[$n1][1],$neigh[$n1][2],$ib), $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->getCrossingCoord($neigh[$n2][0],$neigh[$n2][1],$neigh[$n2][2],$ib) );
   
$this->isobarCoord[$isobar][$ncoord++] = array( $this->isobarCoord[$isobar][$ncoord++] = array(
$this->getCrossingCoord($neigh[$n3][0],$neigh[$n3][1],$neigh[$n3][2],$ib), $this->getCrossingCoord($neigh[$n3][0],$neigh[$n3][1],$neigh[$n3][2],$ib),
$this->getCrossingCoord($neigh[$n4][0],$neigh[$n4][1],$neigh[$n4][2],$ib) ); $this->getCrossingCoord($neigh[$n4][0],$neigh[$n4][1],$neigh[$n4][2],$ib) );
   
} }
} }
} }
} }
   
if( count($this->isobarColors) == 0 ) { if( count($this->isobarColors) == 0 ) {
// No manually specified colors. Calculate them automatically. // No manually specified colors. Calculate them automatically.
$this->CalculateColors(); $this->CalculateColors();
} }
return array( $this->isobarCoord, $this->isobarValues, $this->isobarColors ); 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 * This class represent a plotting of a contour outline of data given as a X-Y matrice
* *
*/ */
class ContourPlot extends Plot { class ContourPlot extends Plot {
   
private $contour, $contourCoord, $contourVal, $contourColor; private $contour, $contourCoord, $contourVal, $contourColor;
private $nbrCountours = 0 ; private $nbrCountours = 0 ;
private $dataMatrix = array(); private $dataMatrix = array();
private $invertLegend = false; private $invertLegend = false;
private $interpFactor = 1; private $interpFactor = 1;
private $flipData = false; private $flipData = false;
private $isobar = 10; private $isobar = 10;
private $showLegend = false; private $showLegend = false;
private $highcontrast = false, $highcontrastbw = false; private $highcontrast = false, $highcontrastbw = false;
private $manualIsobarColors = array(); private $manualIsobarColors = array();
   
/** /**
* Construct a contour plotting algorithm. The end result of the algorithm is a sequence of * Construct a contour plotting algorithm. The end result of the algorithm is a sequence of
* line segments for each isobar given as two vertices. * line segments for each isobar given as two vertices.
* *
* @param $aDataMatrix The Z-data to be used * @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. * @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 * 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 * 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 * @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 * 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. * Y-value 0. In affect flipping the matrice around an imaginary horizontal axis.
* @param $aHighContrast Use high contrast colors (blue/red:ish) * @param $aHighContrast Use high contrast colors (blue/red:ish)
* @param $aHighContrastBW Use only black colors for contours * @param $aHighContrastBW Use only black colors for contours
* @return an instance of the contour plot algorithm * @return an instance of the contour plot algorithm
*/ */
function __construct($aDataMatrix, $aIsobar=10, $aFactor=1, $aInvert=false, $aIsobarColors=array()) { function __construct($aDataMatrix, $aIsobar=10, $aFactor=1, $aInvert=false, $aIsobarColors=array()) {
   
$this->dataMatrix = $aDataMatrix; $this->dataMatrix = $aDataMatrix;
$this->flipData = $aInvert; $this->flipData = $aInvert;
$this->isobar = $aIsobar; $this->isobar = $aIsobar;
$this->interpFactor = $aFactor; $this->interpFactor = $aFactor;
   
if ( $this->interpFactor > 1 ) { if ( $this->interpFactor > 1 ) {
   
if( $this->interpFactor > 5 ) { if( $this->interpFactor > 5 ) {
JpGraphError::RaiseL(28007);// ContourPlot interpolation factor is too large (>5) JpGraphError::RaiseL(28007);// ContourPlot interpolation factor is too large (>5)
} }
   
$ip = new MeshInterpolate(); $ip = new MeshInterpolate();
$this->dataMatrix = $ip->Linear($this->dataMatrix, $this->interpFactor); $this->dataMatrix = $ip->Linear($this->dataMatrix, $this->interpFactor);
} }
   
$this->contour = new Contour($this->dataMatrix,$this->isobar,$aIsobarColors); $this->contour = new Contour($this->dataMatrix,$this->isobar,$aIsobarColors);
   
if( is_array($aIsobar) ) if( is_array($aIsobar) )
$this->nbrContours = count($aIsobar); $this->nbrContours = count($aIsobar);
else else
$this->nbrContours = $aIsobar; $this->nbrContours = $aIsobar;
} }
   
   
/** /**
* Flipe the data around the center * Flipe the data around the center
* *
* @param $aFlg * @param $aFlg
* *
*/ */
function SetInvert($aFlg=true) { function SetInvert($aFlg=true) {
$this->flipData = $aFlg; $this->flipData = $aFlg;
} }
   
/** /**
* Set the colors for the isobar lines * Set the colors for the isobar lines
* *
* @param $aColorArray * @param $aColorArray
* *
*/ */
function SetIsobarColors($aColorArray) { function SetIsobarColors($aColorArray) {
$this->manualIsobarColors = $aColorArray; $this->manualIsobarColors = $aColorArray;
} }
   
/** /**
* Show the legend * Show the legend
* *
* @param $aFlg true if the legend should be shown * @param $aFlg true if the legend should be shown
* *
*/ */
function ShowLegend($aFlg=true) { function ShowLegend($aFlg=true) {
$this->showLegend = $aFlg; $this->showLegend = $aFlg;
} }
   
   
/** /**
* @param $aFlg true if the legend should start with the lowest isobar on top * @param $aFlg true if the legend should start with the lowest isobar on top
* @return unknown_type * @return unknown_type
*/ */
function Invertlegend($aFlg=true) { function Invertlegend($aFlg=true) {
$this->invertLegend = $aFlg; $this->invertLegend = $aFlg;
} }
   
/* Internal method. Give the min value to be used for the scaling /* Internal method. Give the min value to be used for the scaling
* *
*/ */
function Min() { function Min() {
return array(0,0); return array(0,0);
} }
   
/* Internal method. Give the max value to be used for the scaling /* Internal method. Give the max value to be used for the scaling
* *
*/ */
function Max() { function Max() {
return array(count($this->dataMatrix[0])-1,count($this->dataMatrix)-1); return array(count($this->dataMatrix[0])-1,count($this->dataMatrix)-1);
} }
   
/** /**
* Internal ramewrok method to setup the legend to be used for this plot. * Internal ramewrok method to setup the legend to be used for this plot.
* @param $aGraph The parent graph class * @param $aGraph The parent graph class
*/ */
function Legend($aGraph) { function Legend($aGraph) {
   
if( ! $this->showLegend ) if( ! $this->showLegend )
return; return;
   
if( $this->invertLegend ) { if( $this->invertLegend ) {
for ($i = 0; $i < $this->nbrContours; $i++) { for ($i = 0; $i < $this->nbrContours; $i++) {
$aGraph->legend->Add(sprintf('%.1f',$this->contourVal[$i]), $this->contourColor[$i]); $aGraph->legend->Add(sprintf('%.1f',$this->contourVal[$i]), $this->contourColor[$i]);
} }
} }
else { else {
for ($i = $this->nbrContours-1; $i >= 0 ; $i--) { for ($i = $this->nbrContours-1; $i >= 0 ; $i--) {
$aGraph->legend->Add(sprintf('%.1f',$this->contourVal[$i]), $this->contourColor[$i]); $aGraph->legend->Add(sprintf('%.1f',$this->contourVal[$i]), $this->contourColor[$i]);
} }
} }
} }
   
   
/** /**
* Framework function which gets called before the Stroke() method is called * Framework function which gets called before the Stroke() method is called
* *
* @see Plot#PreScaleSetup($aGraph) * @see Plot#PreScaleSetup($aGraph)
* *
*/ */
function PreScaleSetup($aGraph) { function PreScaleSetup($aGraph) {
$xn = count($this->dataMatrix[0])-1; $xn = count($this->dataMatrix[0])-1;
$yn = count($this->dataMatrix)-1; $yn = count($this->dataMatrix)-1;
   
$aGraph->xaxis->scale->Update($aGraph->img,0,$xn); $aGraph->xaxis->scale->Update($aGraph->img,0,$xn);
$aGraph->yaxis->scale->Update($aGraph->img,0,$yn); $aGraph->yaxis->scale->Update($aGraph->img,0,$yn);
   
$this->contour->SetInvert($this->flipData); $this->contour->SetInvert($this->flipData);
list($this->contourCoord,$this->contourVal,$this->contourColor) = $this->contour->getIsobars(); list($this->contourCoord,$this->contourVal,$this->contourColor) = $this->contour->getIsobars();
} }
   
/** /**
* Use high contrast color schema * Use high contrast color schema
* *
* @param $aFlg True, to use high contrast color * @param $aFlg True, to use high contrast color
* @param $aBW True, Use only black and white color schema * @param $aBW True, Use only black and white color schema
*/ */
function UseHighContrastColor($aFlg=true,$aBW=false) { function UseHighContrastColor($aFlg=true,$aBW=false) {
$this->highcontrast = $aFlg; $this->highcontrast = $aFlg;
$this->highcontrastbw = $aBW; $this->highcontrastbw = $aBW;
$this->contour->UseHighContrastColor($this->highcontrast,$this->highcontrastbw); $this->contour->UseHighContrastColor($this->highcontrast,$this->highcontrastbw);
} }
   
/** /**
* Internal method. Stroke the contour plot to the graph * Internal method. Stroke the contour plot to the graph
* *
* @param $img Image handler * @param $img Image handler
* @param $xscale Instance of the xscale to use * @param $xscale Instance of the xscale to use
* @param $yscale Instance of the yscale to use * @param $yscale Instance of the yscale to use
*/ */
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
   
if( count($this->manualIsobarColors) > 0 ) { if( count($this->manualIsobarColors) > 0 ) {
$this->contourColor = $this->manualIsobarColors; $this->contourColor = $this->manualIsobarColors;
if( count($this->manualIsobarColors) != $this->nbrContours ) { if( count($this->manualIsobarColors) != $this->nbrContours ) {
JpGraphError::RaiseL(28002); JpGraphError::RaiseL(28002);
} }
} }
   
$img->SetLineWeight($this->line_weight); $img->SetLineWeight($this->line_weight);
   
for ($c = 0; $c < $this->nbrContours; $c++) { for ($c = 0; $c < $this->nbrContours; $c++) {
   
$img->SetColor( $this->contourColor[$c] ); $img->SetColor( $this->contourColor[$c] );
   
$n = count($this->contourCoord[$c]); $n = count($this->contourCoord[$c]);
$i = 0; $i = 0;
while ( $i < $n ) { while ( $i < $n ) {
list($x1,$y1) = $this->contourCoord[$c][$i][0]; list($x1,$y1) = $this->contourCoord[$c][$i][0];
$x1t = $xscale->Translate($x1); $x1t = $xscale->Translate($x1);
$y1t = $yscale->Translate($y1); $y1t = $yscale->Translate($y1);
   
list($x2,$y2) = $this->contourCoord[$c][$i++][1]; list($x2,$y2) = $this->contourCoord[$c][$i++][1];
$x2t = $xscale->Translate($x2); $x2t = $xscale->Translate($x2);
$y2t = $yscale->Translate($y2); $y2t = $yscale->Translate($y2);
   
$img->Line($x1t,$y1t,$x2t,$y2t); $img->Line($x1t,$y1t,$x2t,$y2t);
} }
   
} }
} }
   
} }
   
// EOF // EOF
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_DATE.PHP // File: JPGRAPH_DATE.PHP
// Description: Classes to handle Date scaling // Description: Classes to handle Date scaling
// Created: 2005-05-02 // Created: 2005-05-02
// Ver: $Id: jpgraph_date.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_date.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
define('HOURADJ_1',0+30); define('HOURADJ_1',0+30);
define('HOURADJ_2',1+30); define('HOURADJ_2',1+30);
define('HOURADJ_3',2+30); define('HOURADJ_3',2+30);
define('HOURADJ_4',3+30); define('HOURADJ_4',3+30);
define('HOURADJ_6',4+30); define('HOURADJ_6',4+30);
define('HOURADJ_12',5+30); define('HOURADJ_12',5+30);
   
define('MINADJ_1',0+20); define('MINADJ_1',0+20);
define('MINADJ_5',1+20); define('MINADJ_5',1+20);
define('MINADJ_10',2+20); define('MINADJ_10',2+20);
define('MINADJ_15',3+20); define('MINADJ_15',3+20);
define('MINADJ_30',4+20); define('MINADJ_30',4+20);
   
define('SECADJ_1',0); define('SECADJ_1',0);
define('SECADJ_5',1); define('SECADJ_5',1);
define('SECADJ_10',2); define('SECADJ_10',2);
define('SECADJ_15',3); define('SECADJ_15',3);
define('SECADJ_30',4); define('SECADJ_30',4);
   
   
define('YEARADJ_1',0+30); define('YEARADJ_1',0+30);
define('YEARADJ_2',1+30); define('YEARADJ_2',1+30);
define('YEARADJ_5',2+30); define('YEARADJ_5',2+30);
   
define('MONTHADJ_1',0+20); define('MONTHADJ_1',0+20);
define('MONTHADJ_6',1+20); define('MONTHADJ_6',1+20);
   
define('DAYADJ_1',0); define('DAYADJ_1',0);
define('DAYADJ_WEEK',1); define('DAYADJ_WEEK',1);
define('DAYADJ_7',1); define('DAYADJ_7',1);
   
define('SECPERYEAR',31536000); define('SECPERYEAR',31536000);
define('SECPERDAY',86400); define('SECPERDAY',86400);
define('SECPERHOUR',3600); define('SECPERHOUR',3600);
define('SECPERMIN',60); define('SECPERMIN',60);
   
   
class DateScale extends LinearScale { class DateScale extends LinearScale {
private $date_format = ''; private $date_format = '';
private $iStartAlign = false, $iEndAlign = false; private $iStartAlign = false, $iEndAlign = false;
private $iStartTimeAlign = false, $iEndTimeAlign = false; private $iStartTimeAlign = false, $iEndTimeAlign = false;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aMin=0,$aMax=0,$aType='x') { function __construct($aMin=0,$aMax=0,$aType='x') {
assert($aType=="x"); assert($aType=="x");
assert($aMin<=$aMax); assert($aMin<=$aMax);
   
$this->type=$aType; $this->type=$aType;
$this->scale=array($aMin,$aMax); $this->scale=array($aMin,$aMax);
$this->world_size=$aMax-$aMin; $this->world_size=$aMax-$aMin;
$this->ticks = new LinearTicks(); $this->ticks = new LinearTicks();
$this->intscale=true; $this->intscale=true;
} }
   
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// Utility Function AdjDate() // Utility Function AdjDate()
// Description: Will round a given time stamp to an even year, month or day // Description: Will round a given time stamp to an even year, month or day
// argument. // argument.
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
   
function AdjDate($aTime,$aRound=0,$aYearType=false,$aMonthType=false,$aDayType=false) { 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); $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
$h=0;$i=0;$s=0; $h=0;$i=0;$s=0;
if( $aYearType !== false ) { if( $aYearType !== false ) {
$yearAdj = array(0=>1, 1=>2, 2=>5); $yearAdj = array(0=>1, 1=>2, 2=>5);
if( $aRound == 0 ) { if( $aRound == 0 ) {
$y = floor($y/$yearAdj[$aYearType])*$yearAdj[$aYearType]; $y = floor($y/$yearAdj[$aYearType])*$yearAdj[$aYearType];
} }
else { else {
++$y; ++$y;
$y = ceil($y/$yearAdj[$aYearType])*$yearAdj[$aYearType]; $y = ceil($y/$yearAdj[$aYearType])*$yearAdj[$aYearType];
} }
$m=1;$d=1; $m=1;$d=1;
} }
elseif( $aMonthType !== false ) { elseif( $aMonthType !== false ) {
$monthAdj = array(0=>1, 1=>6); $monthAdj = array(0=>1, 1=>6);
if( $aRound == 0 ) { if( $aRound == 0 ) {
$m = floor($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType]; $m = floor($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType];
$d=1; $d=1;
} }
else { else {
++$m; ++$m;
$m = ceil($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType]; $m = ceil($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType];
$d=1; $d=1;
} }
} }
elseif( $aDayType !== false ) { elseif( $aDayType !== false ) {
if( $aDayType == 0 ) { if( $aDayType == 0 ) {
if( $aRound == 1 ) { if( $aRound == 1 ) {
//++$d; //++$d;
$h=23;$i=59;$s=59; $h=23;$i=59;$s=59;
} }
} }
else { else {
// Adjust to an even week boundary. // Adjust to an even week boundary.
$w = (int)date('w',$aTime); // Day of week 0=Sun, 6=Sat $w = (int)date('w',$aTime); // Day of week 0=Sun, 6=Sat
if( true ) { // Adjust to start on Mon if( true ) { // Adjust to start on Mon
if( $w==0 ) $w=6; if( $w==0 ) $w=6;
else --$w; else --$w;
} }
if( $aRound == 0 ) { if( $aRound == 0 ) {
$d -= $w; $d -= $w;
} }
else { else {
$d += (7-$w); $d += (7-$w);
$h=23;$i=59;$s=59; $h=23;$i=59;$s=59;
} }
} }
} }
return mktime($h,$i,$s,$m,$d,$y); return mktime($h,$i,$s,$m,$d,$y);
   
} }
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// Wrapper for AdjDate that will round a timestamp to an even date rounding // Wrapper for AdjDate that will round a timestamp to an even date rounding
// it downwards. // it downwards.
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
function AdjStartDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) { function AdjStartDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) {
return $this->AdjDate($aTime,0,$aYearType,$aMonthType,$aDayType); return $this->AdjDate($aTime,0,$aYearType,$aMonthType,$aDayType);
} }
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// Wrapper for AdjDate that will round a timestamp to an even date rounding // Wrapper for AdjDate that will round a timestamp to an even date rounding
// it upwards // it upwards
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
function AdjEndDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) { function AdjEndDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) {
return $this->AdjDate($aTime,1,$aYearType,$aMonthType,$aDayType); return $this->AdjDate($aTime,1,$aYearType,$aMonthType,$aDayType);
} }
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// Utility Function AdjTime() // Utility Function AdjTime()
// Description: Will round a given time stamp to an even time according to // Description: Will round a given time stamp to an even time according to
// argument. // argument.
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
   
function AdjTime($aTime,$aRound=0,$aHourType=false,$aMinType=false,$aSecType=false) { 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); $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); $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); $s = (int)date('s',$aTime);
if( $aHourType !== false ) { if( $aHourType !== false ) {
$aHourType %= 6; $aHourType %= 6;
$hourAdj = array(0=>1, 1=>2, 2=>3, 3=>4, 4=>6, 5=>12); $hourAdj = array(0=>1, 1=>2, 2=>3, 3=>4, 4=>6, 5=>12);
if( $aRound == 0 ) if( $aRound == 0 )
$h = floor($h/$hourAdj[$aHourType])*$hourAdj[$aHourType]; $h = floor($h/$hourAdj[$aHourType])*$hourAdj[$aHourType];
else { else {
if( ($h % $hourAdj[$aHourType]==0) && ($i > 0 || $s > 0) ) { if( ($h % $hourAdj[$aHourType]==0) && ($i > 0 || $s > 0) ) {
$h++; $h++;
} }
$h = ceil($h/$hourAdj[$aHourType])*$hourAdj[$aHourType]; $h = ceil($h/$hourAdj[$aHourType])*$hourAdj[$aHourType];
if( $h >= 24 ) { if( $h >= 24 ) {
$aTime += 86400; $aTime += 86400;
$y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
$h -= 24; $h -= 24;
} }
} }
$i=0;$s=0; $i=0;$s=0;
} }
elseif( $aMinType !== false ) { elseif( $aMinType !== false ) {
$aMinType %= 5; $aMinType %= 5;
$minAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30); $minAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30);
if( $aRound == 0 ) { if( $aRound == 0 ) {
$i = floor($i/$minAdj[$aMinType])*$minAdj[$aMinType]; $i = floor($i/$minAdj[$aMinType])*$minAdj[$aMinType];
} }
else { else {
if( ($i % $minAdj[$aMinType]==0) && $s > 0 ) { if( ($i % $minAdj[$aMinType]==0) && $s > 0 ) {
$i++; $i++;
} }
$i = ceil($i/$minAdj[$aMinType])*$minAdj[$aMinType]; $i = ceil($i/$minAdj[$aMinType])*$minAdj[$aMinType];
if( $i >= 60) { if( $i >= 60) {
$aTime += 3600; $aTime += 3600;
$y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
$h = (int)date('H',$aTime); $i = 0; $h = (int)date('H',$aTime); $i = 0;
} }
} }
$s=0; $s=0;
} }
elseif( $aSecType !== false ) { elseif( $aSecType !== false ) {
$aSecType %= 5; $aSecType %= 5;
$secAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30); $secAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30);
if( $aRound == 0 ) { if( $aRound == 0 ) {
$s = floor($s/$secAdj[$aSecType])*$secAdj[$aSecType]; $s = floor($s/$secAdj[$aSecType])*$secAdj[$aSecType];
} }
else { else {
$s = ceil($s/$secAdj[$aSecType]*1.0)*$secAdj[$aSecType]; $s = ceil($s/$secAdj[$aSecType]*1.0)*$secAdj[$aSecType];
if( $s >= 60) { if( $s >= 60) {
$s=0; $s=0;
$aTime += 60; $aTime += 60;
$y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime); $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); $h = (int)date('H',$aTime); $i = (int)date('i',$aTime);
} }
} }
} }
return mktime($h,$i,$s,$m,$d,$y); return mktime($h,$i,$s,$m,$d,$y);
} }
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// Wrapper for AdjTime that will round a timestamp to an even time rounding // Wrapper for AdjTime that will round a timestamp to an even time rounding
// it downwards. // it downwards.
// Example: AdjStartTime(mktime(18,27,13,2,22,2005),false,2) => 18:20 // Example: AdjStartTime(mktime(18,27,13,2,22,2005),false,2) => 18:20
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
function AdjStartTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) { function AdjStartTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) {
return $this->AdjTime($aTime,0,$aHourType,$aMinType,$aSecType); return $this->AdjTime($aTime,0,$aHourType,$aMinType,$aSecType);
} }
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// Wrapper for AdjTime that will round a timestamp to an even time rounding // Wrapper for AdjTime that will round a timestamp to an even time rounding
// it upwards // it upwards
// Example: AdjEndTime(mktime(18,27,13,2,22,2005),false,2) => 18:30 // Example: AdjEndTime(mktime(18,27,13,2,22,2005),false,2) => 18:30
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
function AdjEndTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) { function AdjEndTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) {
return $this->AdjTime($aTime,1,$aHourType,$aMinType,$aSecType); return $this->AdjTime($aTime,1,$aHourType,$aMinType,$aSecType);
} }
   
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
// DateAutoScale // DateAutoScale
// Autoscale a date axis given start and end time // Autoscale a date axis given start and end time
// Returns an array ($start,$end,$major,$minor,$format) // Returns an array ($start,$end,$major,$minor,$format)
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
function DoDateAutoScale($aStartTime,$aEndTime,$aDensity=0,$aAdjust=true) { function DoDateAutoScale($aStartTime,$aEndTime,$aDensity=0,$aAdjust=true) {
// Format of array // Format of array
// array ( Decision point, array( array( Major-scale-step-array ), // array ( Decision point, array( array( Major-scale-step-array ),
// array( Minor-scale-step-array ), // array( Minor-scale-step-array ),
// array( 0=date-adjust, 1=time-adjust, adjustment-alignment) ) // array( 0=date-adjust, 1=time-adjust, adjustment-alignment) )
// //
$scalePoints = $scalePoints =
array( array(
/* Intervall larger than 10 years */ /* Intervall larger than 10 years */
SECPERYEAR*10,array(array(SECPERYEAR*5,SECPERYEAR*2), SECPERYEAR*10,array(array(SECPERYEAR*5,SECPERYEAR*2),
array(SECPERYEAR), array(SECPERYEAR),
array(0,YEARADJ_1, 0,YEARADJ_1) ), array(0,YEARADJ_1, 0,YEARADJ_1) ),
   
/* Intervall larger than 2 years */ /* Intervall larger than 2 years */
SECPERYEAR*2,array(array(SECPERYEAR),array(SECPERYEAR), SECPERYEAR*2,array(array(SECPERYEAR),array(SECPERYEAR),
array(0,YEARADJ_1) ), array(0,YEARADJ_1) ),
   
/* Intervall larger than 90 days (approx 3 month) */ /* Intervall larger than 90 days (approx 3 month) */
SECPERDAY*90,array(array(SECPERDAY*30,SECPERDAY*14,SECPERDAY*7,SECPERDAY), SECPERDAY*90,array(array(SECPERDAY*30,SECPERDAY*14,SECPERDAY*7,SECPERDAY),
array(SECPERDAY*5,SECPERDAY*7,SECPERDAY,SECPERDAY), array(SECPERDAY*5,SECPERDAY*7,SECPERDAY,SECPERDAY),
array(0,MONTHADJ_1, 0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1)), array(0,MONTHADJ_1, 0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1)),
   
/* Intervall larger than 30 days (approx 1 month) */ /* Intervall larger than 30 days (approx 1 month) */
SECPERDAY*30,array(array(SECPERDAY*14,SECPERDAY*7,SECPERDAY*2, SECPERDAY), SECPERDAY*30,array(array(SECPERDAY*14,SECPERDAY*7,SECPERDAY*2, SECPERDAY),
array(SECPERDAY,SECPERDAY,SECPERDAY,SECPERDAY), array(SECPERDAY,SECPERDAY,SECPERDAY,SECPERDAY),
array(0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1, 0,DAYADJ_1)), array(0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1, 0,DAYADJ_1)),
   
/* Intervall larger than 7 days */ /* Intervall larger than 7 days */
SECPERDAY*7,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2), SECPERDAY*7,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2),
array(SECPERHOUR*6,SECPERHOUR*3,SECPERHOUR,SECPERHOUR), array(SECPERHOUR*6,SECPERHOUR*3,SECPERHOUR,SECPERHOUR),
array(0,DAYADJ_1, 1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1)), array(0,DAYADJ_1, 1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1)),
   
/* Intervall larger than 1 day */ /* Intervall larger than 1 day */
SECPERDAY,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR), SECPERDAY,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR),
array(SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR,SECPERHOUR,SECPERHOUR), array(SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR,SECPERHOUR,SECPERHOUR),
array(1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1, 1,HOURADJ_1)), array(1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1, 1,HOURADJ_1)),
   
/* Intervall larger than 12 hours */ /* Intervall larger than 12 hours */
SECPERHOUR*12,array(array(SECPERHOUR*2,SECPERHOUR,SECPERMIN*30,900,600), SECPERHOUR*12,array(array(SECPERHOUR*2,SECPERHOUR,SECPERMIN*30,900,600),
array(1800,1800,900,300,300), array(1800,1800,900,300,300),
array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
   
/* Intervall larger than 2 hours */ /* Intervall larger than 2 hours */
SECPERHOUR*2,array(array(SECPERHOUR,SECPERMIN*30,900,600,300), SECPERHOUR*2,array(array(SECPERHOUR,SECPERMIN*30,900,600,300),
array(1800,900,300,120,60), array(1800,900,300,120,60),
array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ), array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
   
/* Intervall larger than 1 hours */ /* Intervall larger than 1 hours */
SECPERHOUR,array(array(SECPERMIN*30,900,600,300),array(900,300,120,60), 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) ), array(1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
   
/* Intervall larger than 30 min */ /* Intervall larger than 30 min */
SECPERMIN*30,array(array(SECPERMIN*15,SECPERMIN*10,SECPERMIN*5,SECPERMIN), SECPERMIN*30,array(array(SECPERMIN*15,SECPERMIN*10,SECPERMIN*5,SECPERMIN),
array(300,300,60,10), array(300,300,60,10),
array(1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5, 1,MINADJ_1)), array(1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5, 1,MINADJ_1)),
   
/* Intervall larger than 1 min */ /* Intervall larger than 1 min */
SECPERMIN,array(array(SECPERMIN,15,10,5), SECPERMIN,array(array(SECPERMIN,15,10,5),
array(15,5,2,1), array(15,5,2,1),
array(1,MINADJ_1, 1,SECADJ_15, 1,SECADJ_10, 1,SECADJ_5)), array(1,MINADJ_1, 1,SECADJ_15, 1,SECADJ_10, 1,SECADJ_5)),
   
/* Intervall larger than 10 sec */ /* Intervall larger than 10 sec */
10,array(array(5,2), 10,array(array(5,2),
array(1,1), array(1,1),
array(1,SECADJ_5, 1,SECADJ_1)), array(1,SECADJ_5, 1,SECADJ_1)),
   
/* Intervall larger than 1 sec */ /* Intervall larger than 1 sec */
1,array(array(1), 1,array(array(1),
array(1), array(1),
array(1,SECADJ_1)), array(1,SECADJ_1)),
); );
   
$ns = count($scalePoints); $ns = count($scalePoints);
// Establish major and minor scale units for the date scale // Establish major and minor scale units for the date scale
$diff = $aEndTime - $aStartTime; $diff = $aEndTime - $aStartTime;
if( $diff < 1 ) return false; if( $diff < 1 ) return false;
$done=false; $done=false;
$i=0; $i=0;
while( ! $done ) { while( ! $done ) {
if( $diff > $scalePoints[2*$i] ) { if( $diff > $scalePoints[2*$i] ) {
// Get major and minor scale for this intervall // Get major and minor scale for this intervall
$scaleSteps = $scalePoints[2*$i+1]; $scaleSteps = $scalePoints[2*$i+1];
$major = $scaleSteps[0][min($aDensity,count($scaleSteps[0])-1)]; $major = $scaleSteps[0][min($aDensity,count($scaleSteps[0])-1)];
// Try to find out which minor step looks best // Try to find out which minor step looks best
$minor = $scaleSteps[1][min($aDensity,count($scaleSteps[1])-1)]; $minor = $scaleSteps[1][min($aDensity,count($scaleSteps[1])-1)];
if( $aAdjust ) { if( $aAdjust ) {
// Find out how we should align the start and end timestamps // Find out how we should align the start and end timestamps
$idx = 2*min($aDensity,floor(count($scaleSteps[2])/2)-1); $idx = 2*min($aDensity,floor(count($scaleSteps[2])/2)-1);
if( $scaleSteps[2][$idx] === 0 ) { if( $scaleSteps[2][$idx] === 0 ) {
// Use date adjustment // Use date adjustment
$adj = $scaleSteps[2][$idx+1]; $adj = $scaleSteps[2][$idx+1];
if( $adj >= 30 ) { if( $adj >= 30 ) {
$start = $this->AdjStartDate($aStartTime,$adj-30); $start = $this->AdjStartDate($aStartTime,$adj-30);
$end = $this->AdjEndDate($aEndTime,$adj-30); $end = $this->AdjEndDate($aEndTime,$adj-30);
} }
elseif( $adj >= 20 ) { elseif( $adj >= 20 ) {
$start = $this->AdjStartDate($aStartTime,false,$adj-20); $start = $this->AdjStartDate($aStartTime,false,$adj-20);
$end = $this->AdjEndDate($aEndTime,false,$adj-20); $end = $this->AdjEndDate($aEndTime,false,$adj-20);
} }
else { else {
$start = $this->AdjStartDate($aStartTime,false,false,$adj); $start = $this->AdjStartDate($aStartTime,false,false,$adj);
$end = $this->AdjEndDate($aEndTime,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 // 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 // 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 // on xx:59:59 which would not draw the final major tick
$end++; $end++;
} }
} }
else { else {
// Use time adjustment // Use time adjustment
$adj = $scaleSteps[2][$idx+1]; $adj = $scaleSteps[2][$idx+1];
if( $adj >= 30 ) { if( $adj >= 30 ) {
$start = $this->AdjStartTime($aStartTime,$adj-30); $start = $this->AdjStartTime($aStartTime,$adj-30);
$end = $this->AdjEndTime($aEndTime,$adj-30); $end = $this->AdjEndTime($aEndTime,$adj-30);
} }
elseif( $adj >= 20 ) { elseif( $adj >= 20 ) {
$start = $this->AdjStartTime($aStartTime,false,$adj-20); $start = $this->AdjStartTime($aStartTime,false,$adj-20);
$end = $this->AdjEndTime($aEndTime,false,$adj-20); $end = $this->AdjEndTime($aEndTime,false,$adj-20);
} }
else { else {
$start = $this->AdjStartTime($aStartTime,false,false,$adj); $start = $this->AdjStartTime($aStartTime,false,false,$adj);
$end = $this->AdjEndTime($aEndTime,false,false,$adj); $end = $this->AdjEndTime($aEndTime,false,false,$adj);
} }
} }
} }
// If the overall date span is larger than 1 day ten we show date // If the overall date span is larger than 1 day ten we show date
$format = ''; $format = '';
if( ($end-$start) > SECPERDAY ) { if( ($end-$start) > SECPERDAY ) {
$format = 'Y-m-d '; $format = 'Y-m-d ';
} }
// If the major step is less than 1 day we need to whow hours + min // If the major step is less than 1 day we need to whow hours + min
if( $major < SECPERDAY ) { if( $major < SECPERDAY ) {
$format .= 'H:i'; $format .= 'H:i';
} }
// If the major step is less than 1 min we need to show sec // If the major step is less than 1 min we need to show sec
if( $major < 60 ) { if( $major < 60 ) {
$format .= ':s'; $format .= ':s';
} }
$done=true; $done=true;
} }
++$i; ++$i;
} }
return array($start,$end,$major,$minor,$format); return array($start,$end,$major,$minor,$format);
} }
   
// Overrides the automatic determined date format. Must be a valid date() format string // Overrides the automatic determined date format. Must be a valid date() format string
function SetDateFormat($aFormat) { function SetDateFormat($aFormat) {
$this->date_format = $aFormat; $this->date_format = $aFormat;
$this->ticks->SetLabelDateFormat($this->date_format); $this->ticks->SetLabelDateFormat($this->date_format);
} }
   
function AdjustForDST($aFlg=true) { function AdjustForDST($aFlg=true) {
$this->ticks->AdjustForDST($aFlg); $this->ticks->AdjustForDST($aFlg);
} }
   
   
function SetDateAlign($aStartAlign,$aEndAlign=false) { function SetDateAlign($aStartAlign,$aEndAlign=false) {
if( $aEndAlign === false ) { if( $aEndAlign === false ) {
$aEndAlign=$aStartAlign; $aEndAlign=$aStartAlign;
} }
$this->iStartAlign = $aStartAlign; $this->iStartAlign = $aStartAlign;
$this->iEndAlign = $aEndAlign; $this->iEndAlign = $aEndAlign;
} }
   
function SetTimeAlign($aStartAlign,$aEndAlign=false) { function SetTimeAlign($aStartAlign,$aEndAlign=false) {
if( $aEndAlign === false ) { if( $aEndAlign === false ) {
$aEndAlign=$aStartAlign; $aEndAlign=$aStartAlign;
} }
$this->iStartTimeAlign = $aStartAlign; $this->iStartTimeAlign = $aStartAlign;
$this->iEndTimeAlign = $aEndAlign; $this->iEndTimeAlign = $aEndAlign;
} }
   
   
function AutoScale($img,$aStartTime,$aEndTime,$aNumSteps,$_adummy=false) { function AutoScale($img,$aStartTime,$aEndTime,$aNumSteps,$_adummy=false) {
// We need to have one dummy argument to make the signature of AutoScale() // We need to have one dummy argument to make the signature of AutoScale()
// identical to LinearScale::AutoScale // identical to LinearScale::AutoScale
if( $aStartTime == $aEndTime ) { if( $aStartTime == $aEndTime ) {
// Special case when we only have one data point. // Special case when we only have one data point.
// Create a small artifical intervall to do the autoscaling // Create a small artifical intervall to do the autoscaling
$aStartTime -= 10; $aStartTime -= 10;
$aEndTime += 10; $aEndTime += 10;
} }
$done=false; $done=false;
$i=0; $i=0;
while( ! $done && $i < 5) { while( ! $done && $i < 5) {
list($adjstart,$adjend,$maj,$min,$format) = $this->DoDateAutoScale($aStartTime,$aEndTime,$i); list($adjstart,$adjend,$maj,$min,$format) = $this->DoDateAutoScale($aStartTime,$aEndTime,$i);
$n = floor(($adjend-$adjstart)/$maj); $n = floor(($adjend-$adjstart)/$maj);
if( $n * 1.7 > $aNumSteps ) { if( $n * 1.7 > $aNumSteps ) {
$done=true; $done=true;
} }
$i++; $i++;
} }
   
/* /*
if( 0 ) { // DEBUG if( 0 ) { // DEBUG
echo " Start =".date("Y-m-d H:i:s",$aStartTime)."<br>"; echo " Start =".date("Y-m-d H:i:s",$aStartTime)."<br>";
echo " End =".date("Y-m-d H:i:s",$aEndTime)."<br>"; echo " End =".date("Y-m-d H:i:s",$aEndTime)."<br>";
echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."<br>"; echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."<br>";
echo "Adj End =".date("Y-m-d H:i:s",$adjend)."<p>"; echo "Adj End =".date("Y-m-d H:i:s",$adjend)."<p>";
echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day<br>"; echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day<br>";
echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day<br>"; echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day<br>";
echo "Format=$format<p>"; echo "Format=$format<p>";
} }
*/ */
   
if( $this->iStartTimeAlign !== false && $this->iStartAlign !== false ) { if( $this->iStartTimeAlign !== false && $this->iStartAlign !== false ) {
JpGraphError::RaiseL(3001); JpGraphError::RaiseL(3001);
//('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both'); //('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both');
} }
   
if( $this->iStartTimeAlign !== false ) { if( $this->iStartTimeAlign !== false ) {
if( $this->iStartTimeAlign >= 30 ) { if( $this->iStartTimeAlign >= 30 ) {
$adjstart = $this->AdjStartTime($aStartTime,$this->iStartTimeAlign-30); $adjstart = $this->AdjStartTime($aStartTime,$this->iStartTimeAlign-30);
} }
elseif( $this->iStartTimeAlign >= 20 ) { elseif( $this->iStartTimeAlign >= 20 ) {
$adjstart = $this->AdjStartTime($aStartTime,false,$this->iStartTimeAlign-20); $adjstart = $this->AdjStartTime($aStartTime,false,$this->iStartTimeAlign-20);
} }
else { else {
$adjstart = $this->AdjStartTime($aStartTime,false,false,$this->iStartTimeAlign); $adjstart = $this->AdjStartTime($aStartTime,false,false,$this->iStartTimeAlign);
} }
} }
if( $this->iEndTimeAlign !== false ) { if( $this->iEndTimeAlign !== false ) {
if( $this->iEndTimeAlign >= 30 ) { if( $this->iEndTimeAlign >= 30 ) {
$adjend = $this->AdjEndTime($aEndTime,$this->iEndTimeAlign-30); $adjend = $this->AdjEndTime($aEndTime,$this->iEndTimeAlign-30);
} }
elseif( $this->iEndTimeAlign >= 20 ) { elseif( $this->iEndTimeAlign >= 20 ) {
$adjend = $this->AdjEndTime($aEndTime,false,$this->iEndTimeAlign-20); $adjend = $this->AdjEndTime($aEndTime,false,$this->iEndTimeAlign-20);
} }
else { else {
$adjend = $this->AdjEndTime($aEndTime,false,false,$this->iEndTimeAlign); $adjend = $this->AdjEndTime($aEndTime,false,false,$this->iEndTimeAlign);
} }
} }
   
   
   
if( $this->iStartAlign !== false ) { if( $this->iStartAlign !== false ) {
if( $this->iStartAlign >= 30 ) { if( $this->iStartAlign >= 30 ) {
$adjstart = $this->AdjStartDate($aStartTime,$this->iStartAlign-30); $adjstart = $this->AdjStartDate($aStartTime,$this->iStartAlign-30);
} }
elseif( $this->iStartAlign >= 20 ) { elseif( $this->iStartAlign >= 20 ) {
$adjstart = $this->AdjStartDate($aStartTime,false,$this->iStartAlign-20); $adjstart = $this->AdjStartDate($aStartTime,false,$this->iStartAlign-20);
} }
else { else {
$adjstart = $this->AdjStartDate($aStartTime,false,false,$this->iStartAlign); $adjstart = $this->AdjStartDate($aStartTime,false,false,$this->iStartAlign);
} }
} }
if( $this->iEndAlign !== false ) { if( $this->iEndAlign !== false ) {
if( $this->iEndAlign >= 30 ) { if( $this->iEndAlign >= 30 ) {
$adjend = $this->AdjEndDate($aEndTime,$this->iEndAlign-30); $adjend = $this->AdjEndDate($aEndTime,$this->iEndAlign-30);
} }
elseif( $this->iEndAlign >= 20 ) { elseif( $this->iEndAlign >= 20 ) {
$adjend = $this->AdjEndDate($aEndTime,false,$this->iEndAlign-20); $adjend = $this->AdjEndDate($aEndTime,false,$this->iEndAlign-20);
} }
else { else {
$adjend = $this->AdjEndDate($aEndTime,false,false,$this->iEndAlign); $adjend = $this->AdjEndDate($aEndTime,false,false,$this->iEndAlign);
} }
} }
$this->Update($img,$adjstart,$adjend); $this->Update($img,$adjstart,$adjend);
if( ! $this->ticks->IsSpecified() ) if( ! $this->ticks->IsSpecified() )
$this->ticks->Set($maj,$min); $this->ticks->Set($maj,$min);
if( $this->date_format == '' ) if( $this->date_format == '' )
$this->ticks->SetLabelDateFormat($format); $this->ticks->SetLabelDateFormat($format);
else else
$this->ticks->SetLabelDateFormat($this->date_format); $this->ticks->SetLabelDateFormat($this->date_format);
} }
} }
   
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_ERRHANDLER.PHP // File: JPGRAPH_ERRHANDLER.PHP
// Description: Error handler class together with handling of localized // Description: Error handler class together with handling of localized
// error messages. All localized error messages are stored // error messages. All localized error messages are stored
// in a separate file under the "lang/" subdirectory. // in a separate file under the "lang/" subdirectory.
// Created: 2006-09-24 // Created: 2006-09-24
// Ver: $Id: jpgraph_errhandler.inc.php 1801 2009-09-08 10:51:24Z ljp $ // Ver: $Id: jpgraph_errhandler.inc.php 1801 2009-09-08 10:51:24Z ljp $
// //
// Copyright 2006 (c) Aditus Consulting. All rights reserved. // Copyright 2006 (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
if( !defined('DEFAULT_ERR_LOCALE') ) { if( !defined('DEFAULT_ERR_LOCALE') ) {
define('DEFAULT_ERR_LOCALE','en'); define('DEFAULT_ERR_LOCALE','en');
} }
   
if( !defined('USE_IMAGE_ERROR_HANDLER') ) { if( !defined('USE_IMAGE_ERROR_HANDLER') ) {
define('USE_IMAGE_ERROR_HANDLER',true); define('USE_IMAGE_ERROR_HANDLER',true);
} }
   
GLOBAL $__jpg_err_locale ; GLOBAL $__jpg_err_locale ;
$__jpg_err_locale = DEFAULT_ERR_LOCALE; $__jpg_err_locale = DEFAULT_ERR_LOCALE;
   
class ErrMsgText { class ErrMsgText {
private $lt=NULL; private $lt=NULL;
function __construct() { function __construct() {
GLOBAL $__jpg_err_locale; GLOBAL $__jpg_err_locale;
$file = 'lang/'.$__jpg_err_locale.'.inc.php'; $file = 'lang/'.$__jpg_err_locale.'.inc.php';
   
// If the chosen locale doesn't exist try english // If the chosen locale doesn't exist try english
if( !file_exists(dirname(__FILE__).'/'.$file) ) { if( !file_exists(dirname(__FILE__).'/'.$file) ) {
$__jpg_err_locale = 'en'; $__jpg_err_locale = 'en';
} }
   
$file = 'lang/'.$__jpg_err_locale.'.inc.php'; $file = 'lang/'.$__jpg_err_locale.'.inc.php';
if( !file_exists(dirname(__FILE__).'/'.$file) ) { if( !file_exists(dirname(__FILE__).'/'.$file) ) {
die('Chosen locale file ("'.$file.'") for error messages does not exist or is not readable for the PHP process. Please make sure that the file exists and that the file permissions are such that the PHP process is allowed to read this file.'); die('Chosen locale file ("'.$file.'") for error messages does not exist or is not readable for the PHP process. Please make sure that the file exists and that the file permissions are such that the PHP process is allowed to read this file.');
} }
require($file); require($file);
$this->lt = $_jpg_messages; $this->lt = $_jpg_messages;
} }
   
function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
GLOBAL $__jpg_err_locale; GLOBAL $__jpg_err_locale;
if( !isset($this->lt[$errnbr]) ) { if( !isset($this->lt[$errnbr]) ) {
return 'Internal error: The specified error message ('.$errnbr.') does not exist in the chosen locale ('.$__jpg_err_locale.')'; return 'Internal error: The specified error message ('.$errnbr.') does not exist in the chosen locale ('.$__jpg_err_locale.')';
} }
$ea = $this->lt[$errnbr]; $ea = $this->lt[$errnbr];
$j=0; $j=0;
if( $a1 !== null ) { if( $a1 !== null ) {
$argv[$j++] = $a1; $argv[$j++] = $a1;
if( $a2 !== null ) { if( $a2 !== null ) {
$argv[$j++] = $a2; $argv[$j++] = $a2;
if( $a3 !== null ) { if( $a3 !== null ) {
$argv[$j++] = $a3; $argv[$j++] = $a3;
if( $a4 !== null ) { if( $a4 !== null ) {
$argv[$j++] = $a4; $argv[$j++] = $a4;
if( $a5 !== null ) { if( $a5 !== null ) {
$argv[$j++] = $a5; $argv[$j++] = $a5;
} }
} }
} }
} }
} }
$numargs = $j; $numargs = $j;
if( $ea[1] != $numargs ) { if( $ea[1] != $numargs ) {
// Error message argument count do not match. // Error message argument count do not match.
// Just return the error message without arguments. // Just return the error message without arguments.
return $ea[0]; return $ea[0];
} }
switch( $numargs ) { switch( $numargs ) {
case 1: case 1:
$msg = sprintf($ea[0],$argv[0]); $msg = sprintf($ea[0],$argv[0]);
break; break;
case 2: case 2:
$msg = sprintf($ea[0],$argv[0],$argv[1]); $msg = sprintf($ea[0],$argv[0],$argv[1]);
break; break;
case 3: case 3:
$msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]); $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]);
break; break;
case 4: case 4:
$msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]); $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]);
break; break;
case 5: case 5:
$msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]); $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]);
break; break;
case 0: case 0:
default: default:
$msg = sprintf($ea[0]); $msg = sprintf($ea[0]);
break; break;
} }
return $msg; return $msg;
} }
} }
// //
// A wrapper class that is used to access the specified error object // A wrapper class that is used to access the specified error object
// (to hide the global error parameter and avoid having a GLOBAL directive // (to hide the global error parameter and avoid having a GLOBAL directive
// in all methods. // in all methods.
// //
class JpGraphError { class JpGraphError {
private static $__iImgFlg = true; private static $__iImgFlg = true;
private static $__iLogFile = ''; private static $__iLogFile = '';
private static $__iTitle = 'JpGraph Error: '; private static $__iTitle = 'JpGraph Error: ';
public static function Raise($aMsg,$aHalt=true){ public static function Raise($aMsg,$aHalt=true){
throw new JpGraphException($aMsg); throw new JpGraphException($aMsg);
} }
public static function SetErrLocale($aLoc) { public static function SetErrLocale($aLoc) {
GLOBAL $__jpg_err_locale ; GLOBAL $__jpg_err_locale ;
$__jpg_err_locale = $aLoc; $__jpg_err_locale = $aLoc;
} }
public static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { public static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
throw new JpGraphExceptionL($errnbr,$a1,$a2,$a3,$a4,$a5); throw new JpGraphExceptionL($errnbr,$a1,$a2,$a3,$a4,$a5);
} }
public static function SetImageFlag($aFlg=true) { public static function SetImageFlag($aFlg=true) {
self::$__iImgFlg = $aFlg; self::$__iImgFlg = $aFlg;
} }
public static function GetImageFlag() { public static function GetImageFlag() {
return self::$__iImgFlg; return self::$__iImgFlg;
} }
public static function SetLogFile($aFile) { public static function SetLogFile($aFile) {
self::$__iLogFile = $aFile; self::$__iLogFile = $aFile;
} }
public static function GetLogFile() { public static function GetLogFile() {
return self::$__iLogFile; return self::$__iLogFile;
} }
public static function SetTitle($aTitle) { public static function SetTitle($aTitle) {
self::$__iTitle = $aTitle; self::$__iTitle = $aTitle;
} }
public static function GetTitle() { public static function GetTitle() {
return self::$__iTitle; return self::$__iTitle;
} }
} }
   
// Setup the default handler // Setup the default handler
global $__jpg_OldHandler; global $__jpg_OldHandler;
$__jpg_OldHandler = set_exception_handler(array('JpGraphException','defaultHandler')); $__jpg_OldHandler = set_exception_handler(array('JpGraphException','defaultHandler'));
   
class JpGraphException extends Exception { class JpGraphException extends Exception {
// Redefine the exception so message isn't optional // Redefine the exception so message isn't optional
public function __construct($message, $code = 0) { public function __construct($message, $code = 0) {
// make sure everything is assigned properly // make sure everything is assigned properly
parent::__construct($message, $code); parent::__construct($message, $code);
} }
// custom string representation of object // custom string representation of object
public function _toString() { public function _toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message} at " . basename($this->getFile()) . ":" . $this->getLine() . "\n" . $this->getTraceAsString() . "\n"; return __CLASS__ . ": [{$this->code}]: {$this->message} at " . basename($this->getFile()) . ":" . $this->getLine() . "\n" . $this->getTraceAsString() . "\n";
} }
// custom representation of error as an image // custom representation of error as an image
public function Stroke() { public function Stroke() {
if( JpGraphError::GetImageFlag() ) { if( JpGraphError::GetImageFlag() ) {
$errobj = new JpGraphErrObjectImg(); $errobj = new JpGraphErrObjectImg();
$errobj->SetTitle(JpGraphError::GetTitle()); $errobj->SetTitle(JpGraphError::GetTitle());
} }
else { else {
$errobj = new JpGraphErrObject(); $errobj = new JpGraphErrObject();
$errobj->SetTitle(JpGraphError::GetTitle()); $errobj->SetTitle(JpGraphError::GetTitle());
$errobj->SetStrokeDest(JpGraphError::GetLogFile()); $errobj->SetStrokeDest(JpGraphError::GetLogFile());
} }
$errobj->Raise($this->getMessage()); $errobj->Raise($this->getMessage());
} }
static public function defaultHandler(Exception $exception) { static public function defaultHandler(Exception $exception) {
global $__jpg_OldHandler; global $__jpg_OldHandler;
if( $exception instanceof JpGraphException ) { if( $exception instanceof JpGraphException ) {
$exception->Stroke(); $exception->Stroke();
} }
else { else {
// Restore old handler // Restore old handler
if( $__jpg_OldHandler !== NULL ) { if( $__jpg_OldHandler !== NULL ) {
set_exception_handler($__jpg_OldHandler); set_exception_handler($__jpg_OldHandler);
} }
throw $exception; throw $exception;
} }
} }
} }
   
class JpGraphExceptionL extends JpGraphException { class JpGraphExceptionL extends JpGraphException {
// Redefine the exception so message isn't optional // Redefine the exception so message isn't optional
public function __construct($errcode,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) { public function __construct($errcode,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
// make sure everything is assigned properly // make sure everything is assigned properly
$errtxt = new ErrMsgText(); $errtxt = new ErrMsgText();
JpGraphError::SetTitle('JpGraph Error: '.$errcode); JpGraphError::SetTitle('JpGraph Error: '.$errcode);
parent::__construct($errtxt->Get($errcode,$a1,$a2,$a3,$a4,$a5), 0); parent::__construct($errtxt->Get($errcode,$a1,$a2,$a3,$a4,$a5), 0);
} }
} }
   
// //
// First of all set up a default error handler // First of all set up a default error handler
// //
   
//============================================================= //=============================================================
// The default trivial text error handler. // The default trivial text error handler.
//============================================================= //=============================================================
class JpGraphErrObject { class JpGraphErrObject {
   
protected $iTitle = "JpGraph error: "; protected $iTitle = "JpGraph error: ";
protected $iDest = false; protected $iDest = false;
   
   
function __construct() { function __construct() {
// Empty. Reserved for future use // Empty. Reserved for future use
} }
   
function SetTitle($aTitle) { function SetTitle($aTitle) {
$this->iTitle = $aTitle; $this->iTitle = $aTitle;
} }
   
function SetStrokeDest($aDest) { function SetStrokeDest($aDest) {
$this->iDest = $aDest; $this->iDest = $aDest;
} }
   
// If aHalt is true then execution can't continue. Typical used for fatal errors // If aHalt is true then execution can't continue. Typical used for fatal errors
function Raise($aMsg,$aHalt=false) { function Raise($aMsg,$aHalt=false) {
if( $this->iDest != '' ) { if( $this->iDest != '' ) {
if( $this->iDest == 'syslog' ) { if( $this->iDest == 'syslog' ) {
error_log($this->iTitle.$aMsg); error_log($this->iTitle.$aMsg);
} }
else { else {
$str = '['.date('r').'] '.$this->iTitle.$aMsg."\n"; $str = '['.date('r').'] '.$this->iTitle.$aMsg."\n";
$f = @fopen($this->iDest,'a'); $f = @fopen($this->iDest,'a');
if( $f ) { if( $f ) {
@fwrite($f,$str); @fwrite($f,$str);
@fclose($f); @fclose($f);
} }
} }
} }
else { else {
$aMsg = $this->iTitle.$aMsg; $aMsg = $this->iTitle.$aMsg;
// Check SAPI and if we are called from the command line // Check SAPI and if we are called from the command line
// send the error to STDERR instead // send the error to STDERR instead
if( PHP_SAPI == 'cli' ) { if( PHP_SAPI == 'cli' ) {
fwrite(STDERR,$aMsg); fwrite(STDERR,$aMsg);
} }
else { else {
echo $aMsg; echo $aMsg;
} }
} }
if( $aHalt ) if( $aHalt )
exit(1); exit(1);
} }
} }
   
//============================================================== //==============================================================
// An image based error handler // An image based error handler
//============================================================== //==============================================================
class JpGraphErrObjectImg extends JpGraphErrObject { class JpGraphErrObjectImg extends JpGraphErrObject {
function __construct() { function __construct() {
parent::__construct(); parent::__construct();
// Empty. Reserved for future use // Empty. Reserved for future use
} }
   
function Raise($aMsg,$aHalt=true) { function Raise($aMsg,$aHalt=true) {
$img_iconerror = $img_iconerror =
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'.
'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. 'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'. 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'.
'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. 'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'. 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'. 'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'.
'2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'. '2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'.
'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'. 'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'.
'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'. 'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'.
'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'. 'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'.
'6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'. '6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'.
'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'. 'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'.
'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'. 'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'.
'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'. 'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'.
'qL72fwAAAABJRU5ErkJggg==' ; 'qL72fwAAAABJRU5ErkJggg==' ;
   
if( function_exists("imagetypes") ) { if( function_exists("imagetypes") ) {
$supported = imagetypes(); $supported = imagetypes();
} else { } else {
$supported = 0; $supported = 0;
} }
   
if( !function_exists('imagecreatefromstring') ) { if( !function_exists('imagecreatefromstring') ) {
$supported = 0; $supported = 0;
} }
if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) { if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) {
// Special case for headers already sent or that the installation doesn't support // Special case for headers already sent or that the installation doesn't support
// the PNG format (which the error icon is encoded in). // the PNG format (which the error icon is encoded in).
// Dont return an image since it can't be displayed // Dont return an image since it can't be displayed
die($this->iTitle.' '.$aMsg); die($this->iTitle.' '.$aMsg);
} }
   
$aMsg = wordwrap($aMsg,55); $aMsg = wordwrap($aMsg,55);
$lines = substr_count($aMsg,"\n"); $lines = substr_count($aMsg,"\n");
   
// Create the error icon GD // Create the error icon GD
$erricon = Image::CreateFromString(base64_decode($img_iconerror)); $erricon = Image::CreateFromString(base64_decode($img_iconerror));
   
// Create an image that contains the error text. // Create an image that contains the error text.
$w=400; $w=400;
$h=100 + 15*max(0,$lines-3); $h=100 + 15*max(0,$lines-3);
   
$img = new Image($w,$h); $img = new Image($w,$h);
   
   
// Drop shadow // Drop shadow
$img->SetColor("gray"); $img->SetColor("gray");
$img->FilledRectangle(5,5,$w-1,$h-1,10); $img->FilledRectangle(5,5,$w-1,$h-1,10);
$img->SetColor("gray:0.7"); $img->SetColor("gray:0.7");
$img->FilledRectangle(5,5,$w-3,$h-3,10); $img->FilledRectangle(5,5,$w-3,$h-3,10);
   
// Window background // Window background
$img->SetColor("lightblue"); $img->SetColor("lightblue");
$img->FilledRectangle(1,1,$w-5,$h-5); $img->FilledRectangle(1,1,$w-5,$h-5);
$img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40); $img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40);
   
// Window border // Window border
$img->SetColor("black"); $img->SetColor("black");
$img->Rectangle(1,1,$w-5,$h-5); $img->Rectangle(1,1,$w-5,$h-5);
$img->Rectangle(0,0,$w-4,$h-4); $img->Rectangle(0,0,$w-4,$h-4);
   
// Window top row // Window top row
$img->SetColor("darkred"); $img->SetColor("darkred");
for($y=3; $y < 18; $y += 2 ) for($y=3; $y < 18; $y += 2 )
$img->Line(1,$y,$w-6,$y); $img->Line(1,$y,$w-6,$y);
   
// "White shadow" // "White shadow"
$img->SetColor("white"); $img->SetColor("white");
   
// Left window edge // Left window edge
$img->Line(2,2,2,$h-5); $img->Line(2,2,2,$h-5);
$img->Line(2,2,$w-6,2); $img->Line(2,2,$w-6,2);
   
// "Gray button shadow" // "Gray button shadow"
$img->SetColor("darkgray"); $img->SetColor("darkgray");
   
// Gray window shadow // Gray window shadow
$img->Line(2,$h-6,$w-5,$h-6); $img->Line(2,$h-6,$w-5,$h-6);
$img->Line(3,$h-7,$w-5,$h-7); $img->Line(3,$h-7,$w-5,$h-7);
   
// Window title // Window title
$m = floor($w/2-5); $m = floor($w/2-5);
$l = 110; $l = 110;
$img->SetColor("lightgray:1.3"); $img->SetColor("lightgray:1.3");
$img->FilledRectangle($m-$l,2,$m+$l,16); $img->FilledRectangle($m-$l,2,$m+$l,16);
   
// Stroke text // Stroke text
$img->SetColor("darkred"); $img->SetColor("darkred");
$img->SetFont(FF_FONT2,FS_BOLD); $img->SetFont(FF_FONT2,FS_BOLD);
$img->StrokeText($m-90,15,$this->iTitle); $img->StrokeText($m-90,15,$this->iTitle);
$img->SetColor("black"); $img->SetColor("black");
$img->SetFont(FF_FONT1,FS_NORMAL); $img->SetFont(FF_FONT1,FS_NORMAL);
$txt = new Text($aMsg,52,25); $txt = new Text($aMsg,52,25);
$txt->Align("left","top"); $txt->Align("left","top");
$txt->Stroke($img); $txt->Stroke($img);
if ($this->iDest) { if ($this->iDest) {
$img->Stream($this->iDest); $img->Stream($this->iDest);
} else { } else {
$img->Headers(); $img->Headers();
$img->Stream(); $img->Stream();
} }
if( $aHalt ) if( $aHalt )
die(); die();
} }
} }
   
   
   
if( ! USE_IMAGE_ERROR_HANDLER ) { if( ! USE_IMAGE_ERROR_HANDLER ) {
JpGraphError::SetImageFlag(false); JpGraphError::SetImageFlag(false);
} }
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_ERROR.PHP // File: JPGRAPH_ERROR.PHP
// Description: Error plot extension for JpGraph // Description: Error plot extension for JpGraph
// Created: 2001-01-08 // Created: 2001-01-08
// Ver: $Id: jpgraph_error.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_error.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
//=================================================== //===================================================
// CLASS ErrorPlot // CLASS ErrorPlot
// Description: Error plot with min/max value for // Description: Error plot with min/max value for
// each datapoint // each datapoint
//=================================================== //===================================================
class ErrorPlot extends Plot { class ErrorPlot extends Plot {
private $errwidth=2; private $errwidth=2;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
$this->numpoints /= 2; $this->numpoints /= 2;
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
// Gets called before any axis are stroked // Gets called before any axis are stroked
function PreStrokeAdjust($graph) { function PreStrokeAdjust($graph) {
if( $this->center ) { if( $this->center ) {
$a=0.5; $b=0.5; $a=0.5; $b=0.5;
++$this->numpoints; ++$this->numpoints;
} else { } else {
$a=0; $b=0; $a=0; $b=0;
} }
$graph->xaxis->scale->ticks->SetXLabelOffset($a); $graph->xaxis->scale->ticks->SetXLabelOffset($a);
$graph->SetTextScaleOff($b); $graph->SetTextScaleOff($b);
//$graph->xaxis->scale->ticks->SupressMinorTickMarks(); //$graph->xaxis->scale->ticks->SupressMinorTickMarks();
} }
   
// Method description // Method description
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
$numpoints=count($this->coords[0])/2; $numpoints=count($this->coords[0])/2;
$img->SetColor($this->color); $img->SetColor($this->color);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
   
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
if( count($this->coords[1])!=$numpoints ) if( count($this->coords[1])!=$numpoints )
JpGraphError::RaiseL(2003,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"); //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
else else
$exist_x = true; $exist_x = true;
} }
else else
$exist_x = false; $exist_x = false;
   
for( $i=0; $i<$numpoints; ++$i) { for( $i=0; $i<$numpoints; ++$i) {
if( $exist_x ) if( $exist_x )
$x=$this->coords[1][$i]; $x=$this->coords[1][$i];
else else
$x=$i; $x=$i;
   
if( !is_numeric($x) || if( !is_numeric($x) ||
!is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) { !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) {
continue; continue;
} }
   
$xt = $xscale->Translate($x); $xt = $xscale->Translate($x);
$yt1 = $yscale->Translate($this->coords[0][$i*2]); $yt1 = $yscale->Translate($this->coords[0][$i*2]);
$yt2 = $yscale->Translate($this->coords[0][$i*2+1]); $yt2 = $yscale->Translate($this->coords[0][$i*2+1]);
$img->Line($xt,$yt1,$xt,$yt2); $img->Line($xt,$yt1,$xt,$yt2);
$img->Line($xt-$this->errwidth,$yt1,$xt+$this->errwidth,$yt1); $img->Line($xt-$this->errwidth,$yt1,$xt+$this->errwidth,$yt1);
$img->Line($xt-$this->errwidth,$yt2,$xt+$this->errwidth,$yt2); $img->Line($xt-$this->errwidth,$yt2,$xt+$this->errwidth,$yt2);
} }
return true; return true;
} }
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS ErrorLinePlot // CLASS ErrorLinePlot
// Description: Combine a line and error plot // Description: Combine a line and error plot
// THIS IS A DEPRECATED PLOT TYPE JUST KEPT FOR // THIS IS A DEPRECATED PLOT TYPE JUST KEPT FOR
// BACKWARD COMPATIBILITY // BACKWARD COMPATIBILITY
//=================================================== //===================================================
class ErrorLinePlot extends ErrorPlot { class ErrorLinePlot extends ErrorPlot {
public $line=null; public $line=null;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
// Calculate line coordinates as the average of the error limits // Calculate line coordinates as the average of the error limits
$n = count($datay); $n = count($datay);
for($i=0; $i < $n; $i+=2 ) { for($i=0; $i < $n; $i+=2 ) {
$ly[]=($datay[$i]+$datay[$i+1])/2; $ly[]=($datay[$i]+$datay[$i+1])/2;
} }
$this->line=new LinePlot($ly,$datax); $this->line=new LinePlot($ly,$datax);
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Legend($graph) { function Legend($graph) {
if( $this->legend != "" ) if( $this->legend != "" )
$graph->legend->Add($this->legend,$this->color); $graph->legend->Add($this->legend,$this->color);
$this->line->Legend($graph); $this->line->Legend($graph);
} }
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
parent::Stroke($img,$xscale,$yscale); parent::Stroke($img,$xscale,$yscale);
$this->line->Stroke($img,$xscale,$yscale); $this->line->Stroke($img,$xscale,$yscale);
} }
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS LineErrorPlot // CLASS LineErrorPlot
// Description: Combine a line and error plot // Description: Combine a line and error plot
//=================================================== //===================================================
class LineErrorPlot extends ErrorPlot { class LineErrorPlot extends ErrorPlot {
public $line=null; public $line=null;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
// Data is (val, errdeltamin, errdeltamax) // Data is (val, errdeltamin, errdeltamax)
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
$ly=array(); $ey=array(); $ly=array(); $ey=array();
$n = count($datay); $n = count($datay);
if( $n % 3 != 0 ) { if( $n % 3 != 0 ) {
JpGraphError::RaiseL(4002); JpGraphError::RaiseL(4002);
//('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3'); //('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3');
} }
for($i=0; $i < $n; $i+=3 ) { for($i=0; $i < $n; $i+=3 ) {
$ly[]=$datay[$i]; $ly[]=$datay[$i];
$ey[]=$datay[$i]+$datay[$i+1]; $ey[]=$datay[$i]+$datay[$i+1];
$ey[]=$datay[$i]+$datay[$i+2]; $ey[]=$datay[$i]+$datay[$i+2];
} }
parent::__construct($ey,$datax); parent::__construct($ey,$datax);
$this->line=new LinePlot($ly,$datax); $this->line=new LinePlot($ly,$datax);
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Legend($graph) { function Legend($graph) {
if( $this->legend != "" ) if( $this->legend != "" )
$graph->legend->Add($this->legend,$this->color); $graph->legend->Add($this->legend,$this->color);
$this->line->Legend($graph); $this->line->Legend($graph);
} }
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
parent::Stroke($img,$xscale,$yscale); parent::Stroke($img,$xscale,$yscale);
$this->line->Stroke($img,$xscale,$yscale); $this->line->Stroke($img,$xscale,$yscale);
} }
} // Class } // Class
   
   
/* EOF */ /* EOF */
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_FLAGS.PHP // File: JPGRAPH_FLAGS.PHP
// Description: Class Jpfile. Handles plotmarks // Description: Class Jpfile. Handles plotmarks
// Created: 2003-06-28 // Created: 2003-06-28
// Ver: $Id: jpgraph_flags.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_flags.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
//------------------------------------------------------------ //------------------------------------------------------------
// Defines for the different basic sizes of flags // Defines for the different basic sizes of flags
//------------------------------------------------------------ //------------------------------------------------------------
DEFINE('FLAGSIZE1',1); DEFINE('FLAGSIZE1',1);
DEFINE('FLAGSIZE2',2); DEFINE('FLAGSIZE2',2);
DEFINE('FLAGSIZE3',3); DEFINE('FLAGSIZE3',3);
DEFINE('FLAGSIZE4',4); DEFINE('FLAGSIZE4',4);
   
class FlagImages { class FlagImages {
   
public $iCountryNameMap = array( public $iCountryNameMap = array(
'Afghanistan' => 'afgh', 'Afghanistan' => 'afgh',
'Republic of Angola' => 'agla', 'Republic of Angola' => 'agla',
'Republic of Albania' => 'alba', 'Republic of Albania' => 'alba',
'Alderney' => 'alde', 'Alderney' => 'alde',
'Democratic and Popular Republic of Algeria' => 'alge', 'Democratic and Popular Republic of Algeria' => 'alge',
'Territory of American Samoa' => 'amsa', 'Territory of American Samoa' => 'amsa',
'Principality of Andorra' => 'andr', 'Principality of Andorra' => 'andr',
'British Overseas Territory of Anguilla' => 'angu', 'British Overseas Territory of Anguilla' => 'angu',
'Antarctica' => 'anta', 'Antarctica' => 'anta',
'Argentine Republic' => 'arge', 'Argentine Republic' => 'arge',
'League of Arab States' => 'arle', 'League of Arab States' => 'arle',
'Republic of Armenia' => 'arme', 'Republic of Armenia' => 'arme',
'Aruba' => 'arub', 'Aruba' => 'arub',
'Commonwealth of Australia' => 'astl', 'Commonwealth of Australia' => 'astl',
'Republic of Austria' => 'aust', 'Republic of Austria' => 'aust',
'Azerbaijani Republic' => 'azer', 'Azerbaijani Republic' => 'azer',
'Bangladesh' => 'bngl', 'Bangladesh' => 'bngl',
'British Antarctic Territory' => 'bant', 'British Antarctic Territory' => 'bant',
'Kingdom of Belgium' => 'belg', 'Kingdom of Belgium' => 'belg',
'British Overseas Territory of Bermuda' => 'berm', 'British Overseas Territory of Bermuda' => 'berm',
'Commonwealth of the Bahamas' => 'bhms', 'Commonwealth of the Bahamas' => 'bhms',
'Kingdom of Bahrain' => 'bhrn', 'Kingdom of Bahrain' => 'bhrn',
'Republic of Belarus' => 'blru', 'Republic of Belarus' => 'blru',
'Republic of Bolivia' => 'blva', 'Republic of Bolivia' => 'blva',
'Belize' => 'blze', 'Belize' => 'blze',
'Republic of Benin' => 'bnin', 'Republic of Benin' => 'bnin',
'Republic of Botswana' => 'bots', 'Republic of Botswana' => 'bots',
'Federative Republic of Brazil' => 'braz', 'Federative Republic of Brazil' => 'braz',
'Barbados' => 'brbd', 'Barbados' => 'brbd',
'British Indian Ocean Territory' => 'brin', 'British Indian Ocean Territory' => 'brin',
'Brunei Darussalam' => 'brun', 'Brunei Darussalam' => 'brun',
'Republic of Burkina' => 'bufa', 'Republic of Burkina' => 'bufa',
'Republic of Bulgaria' => 'bulg', 'Republic of Bulgaria' => 'bulg',
'Republic of Burundi' => 'buru', 'Republic of Burundi' => 'buru',
'Overseas Territory of the British Virgin Islands' => 'bvis', 'Overseas Territory of the British Virgin Islands' => 'bvis',
'Central African Republic' => 'cafr', 'Central African Republic' => 'cafr',
'Kingdom of Cambodia' => 'camb', 'Kingdom of Cambodia' => 'camb',
'Republic of Cameroon' => 'came', 'Republic of Cameroon' => 'came',
'Dominion of Canada' => 'cana', 'Dominion of Canada' => 'cana',
'Caribbean Community' => 'cari', 'Caribbean Community' => 'cari',
'Republic of Cape Verde' => 'cave', 'Republic of Cape Verde' => 'cave',
'Republic of Chad' => 'chad', 'Republic of Chad' => 'chad',
'Republic of Chile' => 'chil', 'Republic of Chile' => 'chil',
'Peoples Republic of China' => 'chin', 'Peoples Republic of China' => 'chin',
'Territory of Christmas Island' => 'chms', 'Territory of Christmas Island' => 'chms',
'Commonwealth of Independent States' => 'cins', 'Commonwealth of Independent States' => 'cins',
'Cook Islands' => 'ckis', 'Cook Islands' => 'ckis',
'Republic of Colombia' => 'clmb', 'Republic of Colombia' => 'clmb',
'Territory of Cocos Islands' => 'cois', 'Territory of Cocos Islands' => 'cois',
'Commonwealth' => 'comn', 'Commonwealth' => 'comn',
'Union of the Comoros' => 'como', 'Union of the Comoros' => 'como',
'Republic of the Congo' => 'cong', 'Republic of the Congo' => 'cong',
'Republic of Costa Rica' => 'corc', 'Republic of Costa Rica' => 'corc',
'Republic of Croatia' => 'croa', 'Republic of Croatia' => 'croa',
'Republic of Cuba' => 'cuba', 'Republic of Cuba' => 'cuba',
'British Overseas Territory of the Cayman Islands' => 'cyis', 'British Overseas Territory of the Cayman Islands' => 'cyis',
'Republic of Cyprus' => 'cypr', 'Republic of Cyprus' => 'cypr',
'The Czech Republic' => 'czec', 'The Czech Republic' => 'czec',
'Kingdom of Denmark' => 'denm', 'Kingdom of Denmark' => 'denm',
'Republic of Djibouti' => 'djib', 'Republic of Djibouti' => 'djib',
'Commonwealth of Dominica' => 'domn', 'Commonwealth of Dominica' => 'domn',
'Dominican Republic' => 'dore', 'Dominican Republic' => 'dore',
'Republic of Ecuador' => 'ecua', 'Republic of Ecuador' => 'ecua',
'Arab Republic of Egypt' => 'egyp', 'Arab Republic of Egypt' => 'egyp',
'Republic of El Salvador' => 'elsa', 'Republic of El Salvador' => 'elsa',
'England' => 'engl', 'England' => 'engl',
'Republic of Equatorial Guinea' => 'eqgu', 'Republic of Equatorial Guinea' => 'eqgu',
'State of Eritrea' => 'erit', 'State of Eritrea' => 'erit',
'Republic of Estonia' => 'estn', 'Republic of Estonia' => 'estn',
'Ethiopia' => 'ethp', 'Ethiopia' => 'ethp',
'European Union' => 'euun', 'European Union' => 'euun',
'British Overseas Territory of the Falkland Islands' => 'fais', 'British Overseas Territory of the Falkland Islands' => 'fais',
'International Federation of Vexillological Associations' => 'fiav', 'International Federation of Vexillological Associations' => 'fiav',
'Republic of Fiji' => 'fiji', 'Republic of Fiji' => 'fiji',
'Republic of Finland' => 'finl', 'Republic of Finland' => 'finl',
'Territory of French Polynesia' => 'fpol', 'Territory of French Polynesia' => 'fpol',
'French Republic' => 'fran', 'French Republic' => 'fran',
'Overseas Department of French Guiana' => 'frgu', 'Overseas Department of French Guiana' => 'frgu',
'Gabonese Republic' => 'gabn', 'Gabonese Republic' => 'gabn',
'Republic of the Gambia' => 'gamb', 'Republic of the Gambia' => 'gamb',
'Republic of Georgia' => 'geor', 'Republic of Georgia' => 'geor',
'Federal Republic of Germany' => 'germ', 'Federal Republic of Germany' => 'germ',
'Republic of Ghana' => 'ghan', 'Republic of Ghana' => 'ghan',
'Gibraltar' => 'gibr', 'Gibraltar' => 'gibr',
'Hellenic Republic' => 'grec', 'Hellenic Republic' => 'grec',
'State of Grenada' => 'gren', 'State of Grenada' => 'gren',
'Overseas Department of Guadeloupe' => 'guad', 'Overseas Department of Guadeloupe' => 'guad',
'Territory of Guam' => 'guam', 'Territory of Guam' => 'guam',
'Republic of Guatemala' => 'guat', 'Republic of Guatemala' => 'guat',
'The Bailiwick of Guernsey' => 'guer', 'The Bailiwick of Guernsey' => 'guer',
'Republic of Guinea' => 'guin', 'Republic of Guinea' => 'guin',
'Republic of Haiti' => 'hait', 'Republic of Haiti' => 'hait',
'Hong Kong Special Administrative Region' => 'hokn', 'Hong Kong Special Administrative Region' => 'hokn',
'Republic of Honduras' => 'hond', 'Republic of Honduras' => 'hond',
'Republic of Hungary' => 'hung', 'Republic of Hungary' => 'hung',
'Republic of Iceland' => 'icel', 'Republic of Iceland' => 'icel',
'International Committee of the Red Cross' => 'icrc', 'International Committee of the Red Cross' => 'icrc',
'Republic of India' => 'inda', 'Republic of India' => 'inda',
'Republic of Indonesia' => 'indn', 'Republic of Indonesia' => 'indn',
'Republic of Iraq' => 'iraq', 'Republic of Iraq' => 'iraq',
'Republic of Ireland' => 'irel', 'Republic of Ireland' => 'irel',
'Organization of the Islamic Conference' => 'isco', 'Organization of the Islamic Conference' => 'isco',
'Isle of Man' => 'isma', 'Isle of Man' => 'isma',
'State of Israel' => 'isra', 'State of Israel' => 'isra',
'Italian Republic' => 'ital', 'Italian Republic' => 'ital',
'Jamaica' => 'jama', 'Jamaica' => 'jama',
'Japan' => 'japa', 'Japan' => 'japa',
'The Bailiwick of Jersey' => 'jers', 'The Bailiwick of Jersey' => 'jers',
'Hashemite Kingdom of Jordan' => 'jord', 'Hashemite Kingdom of Jordan' => 'jord',
'Republic of Kazakhstan' => 'kazk', 'Republic of Kazakhstan' => 'kazk',
'Republic of Kenya' => 'keny', 'Republic of Kenya' => 'keny',
'Republic of Kiribati' => 'kirb', 'Republic of Kiribati' => 'kirb',
'State of Kuwait' => 'kuwa', 'State of Kuwait' => 'kuwa',
'Kyrgyz Republic' => 'kyrg', 'Kyrgyz Republic' => 'kyrg',
'Republic of Latvia' => 'latv', 'Republic of Latvia' => 'latv',
'Lebanese Republic' => 'leba', 'Lebanese Republic' => 'leba',
'Kingdom of Lesotho' => 'lest', 'Kingdom of Lesotho' => 'lest',
'Republic of Liberia' => 'libe', 'Republic of Liberia' => 'libe',
'Principality of Liechtenstein' => 'liec', 'Principality of Liechtenstein' => 'liec',
'Republic of Lithuania' => 'lith', 'Republic of Lithuania' => 'lith',
'Grand Duchy of Luxembourg' => 'luxe', 'Grand Duchy of Luxembourg' => 'luxe',
'Macao Special Administrative Region' => 'maca', 'Macao Special Administrative Region' => 'maca',
'Republic of Macedonia' => 'mace', 'Republic of Macedonia' => 'mace',
'Republic of Madagascar' => 'mada', 'Republic of Madagascar' => 'mada',
'Republic of the Marshall Islands' => 'mais', 'Republic of the Marshall Islands' => 'mais',
'Republic of Mali' => 'mali', 'Republic of Mali' => 'mali',
'Federation of Malaysia' => 'mals', 'Federation of Malaysia' => 'mals',
'Republic of Malta' => 'malt', 'Republic of Malta' => 'malt',
'Republic of Malawi' => 'malw', 'Republic of Malawi' => 'malw',
'Overseas Department of Martinique' => 'mart', 'Overseas Department of Martinique' => 'mart',
'Islamic Republic of Mauritania' => 'maur', 'Islamic Republic of Mauritania' => 'maur',
'Territorial Collectivity of Mayotte' => 'mayt', 'Territorial Collectivity of Mayotte' => 'mayt',
'United Mexican States' => 'mexc', 'United Mexican States' => 'mexc',
'Federated States of Micronesia' => 'micr', 'Federated States of Micronesia' => 'micr',
'Midway Islands' => 'miis', 'Midway Islands' => 'miis',
'Republic of Moldova' => 'mold', 'Republic of Moldova' => 'mold',
'Principality of Monaco' => 'mona', 'Principality of Monaco' => 'mona',
'Republic of Mongolia' => 'mong', 'Republic of Mongolia' => 'mong',
'British Overseas Territory of Montserrat' => 'mont', 'British Overseas Territory of Montserrat' => 'mont',
'Kingdom of Morocco' => 'morc', 'Kingdom of Morocco' => 'morc',
'Republic of Mozambique' => 'moza', 'Republic of Mozambique' => 'moza',
'Republic of Mauritius' => 'mrts', 'Republic of Mauritius' => 'mrts',
'Union of Myanmar' => 'myan', 'Union of Myanmar' => 'myan',
'Republic of Namibia' => 'namb', 'Republic of Namibia' => 'namb',
'North Atlantic Treaty Organization' => 'nato', 'North Atlantic Treaty Organization' => 'nato',
'Republic of Nauru' => 'naur', 'Republic of Nauru' => 'naur',
'Turkish Republic of Northern Cyprus' => 'ncyp', 'Turkish Republic of Northern Cyprus' => 'ncyp',
'Netherlands Antilles' => 'nean', 'Netherlands Antilles' => 'nean',
'Kingdom of Nepal' => 'nepa', 'Kingdom of Nepal' => 'nepa',
'Kingdom of the Netherlands' => 'neth', 'Kingdom of the Netherlands' => 'neth',
'Territory of Norfolk Island' => 'nfis', 'Territory of Norfolk Island' => 'nfis',
'Federal Republic of Nigeria' => 'ngra', 'Federal Republic of Nigeria' => 'ngra',
'Republic of Nicaragua' => 'nica', 'Republic of Nicaragua' => 'nica',
'Republic of Niger' => 'nigr', 'Republic of Niger' => 'nigr',
'Niue' => 'niue', 'Niue' => 'niue',
'Commonwealth of the Northern Mariana Islands' => 'nmar', 'Commonwealth of the Northern Mariana Islands' => 'nmar',
'Province of Northern Ireland' => 'noir', 'Province of Northern Ireland' => 'noir',
'Nordic Council' => 'nord', 'Nordic Council' => 'nord',
'Kingdom of Norway' => 'norw', 'Kingdom of Norway' => 'norw',
'Territory of New Caledonia and Dependencies' => 'nwca', 'Territory of New Caledonia and Dependencies' => 'nwca',
'New Zealand' => 'nwze', 'New Zealand' => 'nwze',
'Organization of American States' => 'oast', 'Organization of American States' => 'oast',
'Organization of African Unity' => 'oaun', 'Organization of African Unity' => 'oaun',
'International Olympic Committee' => 'olym', 'International Olympic Committee' => 'olym',
'Sultanate of Oman' => 'oman', 'Sultanate of Oman' => 'oman',
'Islamic Republic of Pakistan' => 'paks', 'Islamic Republic of Pakistan' => 'paks',
'Republic of Palau' => 'pala', 'Republic of Palau' => 'pala',
'Independent State of Papua New Guinea' => 'pang', 'Independent State of Papua New Guinea' => 'pang',
'Republic of Paraguay' => 'para', 'Republic of Paraguay' => 'para',
'Republic of Peru' => 'peru', 'Republic of Peru' => 'peru',
'Republic of the Philippines' => 'phil', 'Republic of the Philippines' => 'phil',
'British Overseas Territory of the Pitcairn Islands' => 'piis', 'British Overseas Territory of the Pitcairn Islands' => 'piis',
'Republic of Poland' => 'pola', 'Republic of Poland' => 'pola',
'Republic of Portugal' => 'port', 'Republic of Portugal' => 'port',
'Commonwealth of Puerto Rico' => 'purc', 'Commonwealth of Puerto Rico' => 'purc',
'State of Qatar' => 'qata', 'State of Qatar' => 'qata',
'Russian Federation' => 'russ', 'Russian Federation' => 'russ',
'Romania' => 'rmna', 'Romania' => 'rmna',
'Republic of Rwanda' => 'rwan', 'Republic of Rwanda' => 'rwan',
'Kingdom of Saudi Arabia' => 'saar', 'Kingdom of Saudi Arabia' => 'saar',
'Republic of San Marino' => 'sama', 'Republic of San Marino' => 'sama',
'Nordic Sami Conference' => 'sami', 'Nordic Sami Conference' => 'sami',
'Sark' => 'sark', 'Sark' => 'sark',
'Scotland' => 'scot', 'Scotland' => 'scot',
'Principality of Seborga' => 'sebo', 'Principality of Seborga' => 'sebo',
'Republic of Serbia' => 'serb', 'Republic of Serbia' => 'serb',
'Republic of Sierra Leone' => 'sile', 'Republic of Sierra Leone' => 'sile',
'Republic of Singapore' => 'sing', 'Republic of Singapore' => 'sing',
'Republic of Korea' => 'skor', 'Republic of Korea' => 'skor',
'Republic of Slovenia' => 'slva', 'Republic of Slovenia' => 'slva',
'Somali Republic' => 'smla', 'Somali Republic' => 'smla',
'Republic of Somaliland' => 'smld', 'Republic of Somaliland' => 'smld',
'Republic of South Africa' => 'soaf', 'Republic of South Africa' => 'soaf',
'Solomon Islands' => 'sois', 'Solomon Islands' => 'sois',
'Kingdom of Spain' => 'span', 'Kingdom of Spain' => 'span',
'Secretariat of the Pacific Community' => 'spco', 'Secretariat of the Pacific Community' => 'spco',
'Democratic Socialist Republic of Sri Lanka' => 'srla', 'Democratic Socialist Republic of Sri Lanka' => 'srla',
'Saint Lucia' => 'stlu', 'Saint Lucia' => 'stlu',
'Republic of the Sudan' => 'suda', 'Republic of the Sudan' => 'suda',
'Republic of Suriname' => 'surn', 'Republic of Suriname' => 'surn',
'Slovak Republic' => 'svka', 'Slovak Republic' => 'svka',
'Kingdom of Sweden' => 'swdn', 'Kingdom of Sweden' => 'swdn',
'Swiss Confederation' => 'swit', 'Swiss Confederation' => 'swit',
'Syrian Arab Republic' => 'syra', 'Syrian Arab Republic' => 'syra',
'Kingdom of Swaziland' => 'szld', 'Kingdom of Swaziland' => 'szld',
'Republic of China' => 'taiw', 'Republic of China' => 'taiw',
'Taiwan' => 'taiw', 'Taiwan' => 'taiw',
'Republic of Tajikistan' => 'tajk', 'Republic of Tajikistan' => 'tajk',
'United Republic of Tanzania' => 'tanz', 'United Republic of Tanzania' => 'tanz',
'Kingdom of Thailand' => 'thal', 'Kingdom of Thailand' => 'thal',
'Autonomous Region of Tibet' => 'tibe', 'Autonomous Region of Tibet' => 'tibe',
'Turkmenistan' => 'tkst', 'Turkmenistan' => 'tkst',
'Togolese Republic' => 'togo', 'Togolese Republic' => 'togo',
'Tokelau' => 'toke', 'Tokelau' => 'toke',
'Kingdom of Tonga' => 'tong', 'Kingdom of Tonga' => 'tong',
'Tristan da Cunha' => 'trdc', 'Tristan da Cunha' => 'trdc',
'Tromelin' => 'tris', 'Tromelin' => 'tris',
'Republic of Tunisia' => 'tuns', 'Republic of Tunisia' => 'tuns',
'Republic of Turkey' => 'turk', 'Republic of Turkey' => 'turk',
'Tuvalu' => 'tuva', 'Tuvalu' => 'tuva',
'United Arab Emirates' => 'uaem', 'United Arab Emirates' => 'uaem',
'Republic of Uganda' => 'ugan', 'Republic of Uganda' => 'ugan',
'Ukraine' => 'ukrn', 'Ukraine' => 'ukrn',
'United Kingdom of Great Britain' => 'unkg', 'United Kingdom of Great Britain' => 'unkg',
'United Nations' => 'unna', 'United Nations' => 'unna',
'United States of America' => 'unst', 'United States of America' => 'unst',
'Oriental Republic of Uruguay' => 'urgy', 'Oriental Republic of Uruguay' => 'urgy',
'Virgin Islands of the United States' => 'usvs', 'Virgin Islands of the United States' => 'usvs',
'Republic of Uzbekistan' => 'uzbk', 'Republic of Uzbekistan' => 'uzbk',
'State of the Vatican City' => 'vacy', 'State of the Vatican City' => 'vacy',
'Republic of Vanuatu' => 'vant', 'Republic of Vanuatu' => 'vant',
'Bolivarian Republic of Venezuela' => 'venz', 'Bolivarian Republic of Venezuela' => 'venz',
'Republic of Yemen' => 'yemn', 'Republic of Yemen' => 'yemn',
'Democratic Republic of Congo' => 'zare', 'Democratic Republic of Congo' => 'zare',
'Republic of Zimbabwe' => 'zbwe' ) ; 'Republic of Zimbabwe' => 'zbwe' ) ;
   
   
private $iFlagCount = -1; private $iFlagCount = -1;
private $iFlagSetMap = array( private $iFlagSetMap = array(
FLAGSIZE1 => 'flags_thumb35x35', FLAGSIZE1 => 'flags_thumb35x35',
FLAGSIZE2 => 'flags_thumb60x60', FLAGSIZE2 => 'flags_thumb60x60',
FLAGSIZE3 => 'flags_thumb100x100', FLAGSIZE3 => 'flags_thumb100x100',
FLAGSIZE4 => 'flags' FLAGSIZE4 => 'flags'
); );
   
private $iFlagData ; private $iFlagData ;
private $iOrdIdx=array(); private $iOrdIdx=array();
   
function FlagImages($aSize=FLAGSIZE1) { function FlagImages($aSize=FLAGSIZE1) {
switch($aSize) { switch($aSize) {
case FLAGSIZE1 : case FLAGSIZE1 :
case FLAGSIZE2 : case FLAGSIZE2 :
case FLAGSIZE3 : case FLAGSIZE3 :
case FLAGSIZE4 : case FLAGSIZE4 :
$file = dirname(__FILE__).'/'.$this->iFlagSetMap[$aSize].'.dat'; $file = dirname(__FILE__).'/'.$this->iFlagSetMap[$aSize].'.dat';
$fp = fopen($file,'rb'); $fp = fopen($file,'rb');
$rawdata = fread($fp,filesize($file)); $rawdata = fread($fp,filesize($file));
$this->iFlagData = unserialize($rawdata); $this->iFlagData = unserialize($rawdata);
break; break;
default: default:
JpGraphError::RaiseL(5001,$aSize); JpGraphError::RaiseL(5001,$aSize);
//('Unknown flag size. ('.$aSize.')'); //('Unknown flag size. ('.$aSize.')');
} }
$this->iFlagCount = count($this->iCountryNameMap); $this->iFlagCount = count($this->iCountryNameMap);
} }
   
function GetNum() { function GetNum() {
return $this->iFlagCount; return $this->iFlagCount;
} }
   
function GetImgByName($aName,&$outFullName) { function GetImgByName($aName,&$outFullName) {
$idx = $this->GetIdxByName($aName,$outFullName); $idx = $this->GetIdxByName($aName,$outFullName);
return $this->GetImgByIdx($idx); return $this->GetImgByIdx($idx);
} }
   
function GetImgByIdx($aIdx) { function GetImgByIdx($aIdx) {
if( array_key_exists($aIdx,$this->iFlagData) ) { if( array_key_exists($aIdx,$this->iFlagData) ) {
$d = $this->iFlagData[$aIdx][1]; $d = $this->iFlagData[$aIdx][1];
return Image::CreateFromString($d); return Image::CreateFromString($d);
} }
else { else {
JpGraphError::RaiseL(5002,$aIdx); JpGraphError::RaiseL(5002,$aIdx);
//("Flag index \"�$aIdx\" does not exist."); //("Flag index \"�$aIdx\" does not exist.");
} }
} }
   
function GetIdxByOrdinal($aOrd,&$outFullName) { function GetIdxByOrdinal($aOrd,&$outFullName) {
$aOrd--; $aOrd--;
$n = count($this->iOrdIdx); $n = count($this->iOrdIdx);
if( $n == 0 ) { if( $n == 0 ) {
reset($this->iCountryNameMap); reset($this->iCountryNameMap);
$this->iOrdIdx=array(); $this->iOrdIdx=array();
$i=0; $i=0;
while( list($key,$val) = each($this->iCountryNameMap) ) { while( list($key,$val) = each($this->iCountryNameMap) ) {
$this->iOrdIdx[$i++] = array($val,$key); $this->iOrdIdx[$i++] = array($val,$key);
} }
$tmp=$this->iOrdIdx[$aOrd]; $tmp=$this->iOrdIdx[$aOrd];
$outFullName = $tmp[1]; $outFullName = $tmp[1];
return $tmp[0]; return $tmp[0];
} }
elseif( $aOrd >= 0 && $aOrd < $n ) { elseif( $aOrd >= 0 && $aOrd < $n ) {
$tmp=$this->iOrdIdx[$aOrd]; $tmp=$this->iOrdIdx[$aOrd];
$outFullName = $tmp[1]; $outFullName = $tmp[1];
return $tmp[0]; return $tmp[0];
} }
else { else {
JpGraphError::RaiseL(5003,$aOrd); JpGraphError::RaiseL(5003,$aOrd);
//('Invalid ordinal number specified for flag index.'); //('Invalid ordinal number specified for flag index.');
} }
} }
   
function GetIdxByName($aName,&$outFullName) { function GetIdxByName($aName,&$outFullName) {
   
if( is_integer($aName) ) { if( is_integer($aName) ) {
$idx = $this->GetIdxByOrdinal($aName,$outFullName); $idx = $this->GetIdxByOrdinal($aName,$outFullName);
return $idx; return $idx;
} }
   
$found=false; $found=false;
$aName = strtolower($aName); $aName = strtolower($aName);
$nlen = strlen($aName); $nlen = strlen($aName);
reset($this->iCountryNameMap); reset($this->iCountryNameMap);
// Start by trying to match exact index name // Start by trying to match exact index name
while( list($key,$val) = each($this->iCountryNameMap) ) { while( list($key,$val) = each($this->iCountryNameMap) ) {
if( $nlen == strlen($val) && $val == $aName ) { if( $nlen == strlen($val) && $val == $aName ) {
$found=true; $found=true;
break; break;
} }
} }
if( !$found ) { if( !$found ) {
reset($this->iCountryNameMap); reset($this->iCountryNameMap);
// If the exact index doesn't work try a (partial) full name // If the exact index doesn't work try a (partial) full name
while( list($key,$val) = each($this->iCountryNameMap) ) { while( list($key,$val) = each($this->iCountryNameMap) ) {
if( strpos(strtolower($key), $aName) !== false ) { if( strpos(strtolower($key), $aName) !== false ) {
$found=true; $found=true;
break; break;
} }
} }
} }
if( $found ) { if( $found ) {
$outFullName = $key; $outFullName = $key;
return $val; return $val;
} }
else { else {
JpGraphError::RaiseL(5004,$aName); 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\"."); //("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\".");
} }
} }
} }
   
   
   
   
?> ?>
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_GANTT.PHP // File: JPGRAPH_GANTT.PHP
// Description: JpGraph Gantt plot extension // Description: JpGraph Gantt plot extension
// Created: 2001-11-12 // Created: 2001-11-12
// Ver: $Id: jpgraph_gantt.php 1809 2009-09-09 13:07:33Z ljp $ // Ver: $Id: jpgraph_gantt.php 1809 2009-09-09 13:07:33Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
require_once('jpgraph_plotband.php'); require_once('jpgraph_plotband.php');
require_once('jpgraph_iconplot.php'); require_once('jpgraph_iconplot.php');
require_once('jpgraph_plotmark.inc.php'); require_once('jpgraph_plotmark.inc.php');
   
// Maximum size for Automatic Gantt chart // Maximum size for Automatic Gantt chart
define('MAX_GANTTIMG_SIZE_W',8000); define('MAX_GANTTIMG_SIZE_W',8000);
define('MAX_GANTTIMG_SIZE_H',5000); define('MAX_GANTTIMG_SIZE_H',5000);
   
// Scale Header types // Scale Header types
define("GANTT_HDAY",1); define("GANTT_HDAY",1);
define("GANTT_HWEEK",2); define("GANTT_HWEEK",2);
define("GANTT_HMONTH",4); define("GANTT_HMONTH",4);
define("GANTT_HYEAR",8); define("GANTT_HYEAR",8);
define("GANTT_HHOUR",16); define("GANTT_HHOUR",16);
define("GANTT_HMIN",32); define("GANTT_HMIN",32);
   
// Bar patterns // Bar patterns
define("GANTT_RDIAG",BAND_RDIAG); // Right diagonal lines define("GANTT_RDIAG",BAND_RDIAG); // Right diagonal lines
define("GANTT_LDIAG",BAND_LDIAG); // Left diagonal lines define("GANTT_LDIAG",BAND_LDIAG); // Left diagonal lines
define("GANTT_SOLID",BAND_SOLID); // Solid one color define("GANTT_SOLID",BAND_SOLID); // Solid one color
define("GANTT_VLINE",BAND_VLINE); // Vertical lines define("GANTT_VLINE",BAND_VLINE); // Vertical lines
define("GANTT_HLINE",BAND_HLINE); // Horizontal lines define("GANTT_HLINE",BAND_HLINE); // Horizontal lines
define("GANTT_3DPLANE",BAND_3DPLANE); // "3D" Plane define("GANTT_3DPLANE",BAND_3DPLANE); // "3D" Plane
define("GANTT_HVCROSS",BAND_HVCROSS); // Vertical/Hor crosses define("GANTT_HVCROSS",BAND_HVCROSS); // Vertical/Hor crosses
define("GANTT_DIAGCROSS",BAND_DIAGCROSS); // Diagonal crosses define("GANTT_DIAGCROSS",BAND_DIAGCROSS); // Diagonal crosses
   
// Conversion constant // Conversion constant
define("SECPERDAY",3600*24); define("SECPERDAY",3600*24);
   
// Locales. ONLY KEPT FOR BACKWARDS COMPATIBILITY // Locales. ONLY KEPT FOR BACKWARDS COMPATIBILITY
// You should use the proper locale strings directly // You should use the proper locale strings directly
// from now on. // from now on.
define("LOCALE_EN","en_UK"); define("LOCALE_EN","en_UK");
define("LOCALE_SV","sv_SE"); define("LOCALE_SV","sv_SE");
   
// Layout of bars // Layout of bars
define("GANTT_EVEN",1); define("GANTT_EVEN",1);
define("GANTT_FROMTOP",2); define("GANTT_FROMTOP",2);
   
// Style for minute header // Style for minute header
define("MINUTESTYLE_MM",0); // 15 define("MINUTESTYLE_MM",0); // 15
define("MINUTESTYLE_CUSTOM",2); // Custom format define("MINUTESTYLE_CUSTOM",2); // Custom format
   
   
// Style for hour header // Style for hour header
define("HOURSTYLE_HM24",0); // 13:10 define("HOURSTYLE_HM24",0); // 13:10
define("HOURSTYLE_HMAMPM",1); // 1:10pm define("HOURSTYLE_HMAMPM",1); // 1:10pm
define("HOURSTYLE_H24",2); // 13 define("HOURSTYLE_H24",2); // 13
define("HOURSTYLE_HAMPM",3); // 1pm define("HOURSTYLE_HAMPM",3); // 1pm
define("HOURSTYLE_CUSTOM",4); // User defined define("HOURSTYLE_CUSTOM",4); // User defined
   
// Style for day header // Style for day header
define("DAYSTYLE_ONELETTER",0); // "M" define("DAYSTYLE_ONELETTER",0); // "M"
define("DAYSTYLE_LONG",1); // "Monday" define("DAYSTYLE_LONG",1); // "Monday"
define("DAYSTYLE_LONGDAYDATE1",2); // "Monday 23 Jun" define("DAYSTYLE_LONGDAYDATE1",2); // "Monday 23 Jun"
define("DAYSTYLE_LONGDAYDATE2",3); // "Monday 23 Jun 2003" define("DAYSTYLE_LONGDAYDATE2",3); // "Monday 23 Jun 2003"
define("DAYSTYLE_SHORT",4); // "Mon" define("DAYSTYLE_SHORT",4); // "Mon"
define("DAYSTYLE_SHORTDAYDATE1",5); // "Mon 23/6" define("DAYSTYLE_SHORTDAYDATE1",5); // "Mon 23/6"
define("DAYSTYLE_SHORTDAYDATE2",6); // "Mon 23 Jun" define("DAYSTYLE_SHORTDAYDATE2",6); // "Mon 23 Jun"
define("DAYSTYLE_SHORTDAYDATE3",7); // "Mon 23" define("DAYSTYLE_SHORTDAYDATE3",7); // "Mon 23"
define("DAYSTYLE_SHORTDATE1",8); // "23/6" define("DAYSTYLE_SHORTDATE1",8); // "23/6"
define("DAYSTYLE_SHORTDATE2",9); // "23 Jun" define("DAYSTYLE_SHORTDATE2",9); // "23 Jun"
define("DAYSTYLE_SHORTDATE3",10); // "Mon 23" define("DAYSTYLE_SHORTDATE3",10); // "Mon 23"
define("DAYSTYLE_SHORTDATE4",11); // "23" define("DAYSTYLE_SHORTDATE4",11); // "23"
define("DAYSTYLE_CUSTOM",12); // "M" define("DAYSTYLE_CUSTOM",12); // "M"
   
// Styles for week header // Styles for week header
define("WEEKSTYLE_WNBR",0); define("WEEKSTYLE_WNBR",0);
define("WEEKSTYLE_FIRSTDAY",1); define("WEEKSTYLE_FIRSTDAY",1);
define("WEEKSTYLE_FIRSTDAY2",2); define("WEEKSTYLE_FIRSTDAY2",2);
define("WEEKSTYLE_FIRSTDAYWNBR",3); define("WEEKSTYLE_FIRSTDAYWNBR",3);
define("WEEKSTYLE_FIRSTDAY2WNBR",4); define("WEEKSTYLE_FIRSTDAY2WNBR",4);
   
// Styles for month header // Styles for month header
define("MONTHSTYLE_SHORTNAME",0); define("MONTHSTYLE_SHORTNAME",0);
define("MONTHSTYLE_LONGNAME",1); define("MONTHSTYLE_LONGNAME",1);
define("MONTHSTYLE_LONGNAMEYEAR2",2); define("MONTHSTYLE_LONGNAMEYEAR2",2);
define("MONTHSTYLE_SHORTNAMEYEAR2",3); define("MONTHSTYLE_SHORTNAMEYEAR2",3);
define("MONTHSTYLE_LONGNAMEYEAR4",4); define("MONTHSTYLE_LONGNAMEYEAR4",4);
define("MONTHSTYLE_SHORTNAMEYEAR4",5); define("MONTHSTYLE_SHORTNAMEYEAR4",5);
define("MONTHSTYLE_FIRSTLETTER",6); define("MONTHSTYLE_FIRSTLETTER",6);
   
   
// Types of constrain links // Types of constrain links
define('CONSTRAIN_STARTSTART',0); define('CONSTRAIN_STARTSTART',0);
define('CONSTRAIN_STARTEND',1); define('CONSTRAIN_STARTEND',1);
define('CONSTRAIN_ENDSTART',2); define('CONSTRAIN_ENDSTART',2);
define('CONSTRAIN_ENDEND',3); define('CONSTRAIN_ENDEND',3);
   
// Arrow direction for constrain links // Arrow direction for constrain links
define('ARROW_DOWN',0); define('ARROW_DOWN',0);
define('ARROW_UP',1); define('ARROW_UP',1);
define('ARROW_LEFT',2); define('ARROW_LEFT',2);
define('ARROW_RIGHT',3); define('ARROW_RIGHT',3);
   
// Arrow type for constrain type // Arrow type for constrain type
define('ARROWT_SOLID',0); define('ARROWT_SOLID',0);
define('ARROWT_OPEN',1); define('ARROWT_OPEN',1);
   
// Arrow size for constrain lines // Arrow size for constrain lines
define('ARROW_S1',0); define('ARROW_S1',0);
define('ARROW_S2',1); define('ARROW_S2',1);
define('ARROW_S3',2); define('ARROW_S3',2);
define('ARROW_S4',3); define('ARROW_S4',3);
define('ARROW_S5',4); define('ARROW_S5',4);
   
// Activity types for use with utility method CreateSimple() // Activity types for use with utility method CreateSimple()
define('ACTYPE_NORMAL',0); define('ACTYPE_NORMAL',0);
define('ACTYPE_GROUP',1); define('ACTYPE_GROUP',1);
define('ACTYPE_MILESTONE',2); define('ACTYPE_MILESTONE',2);
   
define('ACTINFO_3D',1); define('ACTINFO_3D',1);
define('ACTINFO_2D',0); define('ACTINFO_2D',0);
   
   
// Check if array_fill() exists // Check if array_fill() exists
if (!function_exists('array_fill')) { if (!function_exists('array_fill')) {
function array_fill($iStart, $iLen, $vValue) { function array_fill($iStart, $iLen, $vValue) {
$aResult = array(); $aResult = array();
for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) { for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) {
$aResult[$iCount] = $vValue; $aResult[$iCount] = $vValue;
} }
return $aResult; return $aResult;
} }
} }
   
//=================================================== //===================================================
// CLASS GanttActivityInfo // CLASS GanttActivityInfo
// Description: // Description:
//=================================================== //===================================================
class GanttActivityInfo { class GanttActivityInfo {
public $iShow=true; public $iShow=true;
public $iLeftColMargin=4,$iRightColMargin=1,$iTopColMargin=1,$iBottomColMargin=3; public $iLeftColMargin=4,$iRightColMargin=1,$iTopColMargin=1,$iBottomColMargin=3;
public $vgrid = null; public $vgrid = null;
private $iColor='black'; private $iColor='black';
private $iBackgroundColor='lightgray'; private $iBackgroundColor='lightgray';
private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10,$iFontColor='black'; private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10,$iFontColor='black';
private $iTitles=array(); private $iTitles=array();
private $iWidth=array(),$iHeight=-1; private $iWidth=array(),$iHeight=-1;
private $iTopHeaderMargin = 4; private $iTopHeaderMargin = 4;
private $iStyle=1; private $iStyle=1;
private $iHeaderAlign='center'; private $iHeaderAlign='center';
   
function __construct() { function __construct() {
$this->vgrid = new LineProperty(); $this->vgrid = new LineProperty();
} }
   
function Hide($aF=true) { function Hide($aF=true) {
$this->iShow=!$aF; $this->iShow=!$aF;
} }
   
function Show($aF=true) { function Show($aF=true) {
$this->iShow=$aF; $this->iShow=$aF;
} }
   
// Specify font // Specify font
function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
$this->iFFamily = $aFFamily; $this->iFFamily = $aFFamily;
$this->iFStyle = $aFStyle; $this->iFStyle = $aFStyle;
$this->iFSize = $aFSize; $this->iFSize = $aFSize;
} }
   
function SetStyle($aStyle) { function SetStyle($aStyle) {
$this->iStyle = $aStyle; $this->iStyle = $aStyle;
} }
   
function SetColumnMargin($aLeft,$aRight) { function SetColumnMargin($aLeft,$aRight) {
$this->iLeftColMargin = $aLeft; $this->iLeftColMargin = $aLeft;
$this->iRightColMargin = $aRight; $this->iRightColMargin = $aRight;
} }
   
function SetFontColor($aFontColor) { function SetFontColor($aFontColor) {
$this->iFontColor = $aFontColor; $this->iFontColor = $aFontColor;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function SetBackgroundColor($aColor) { function SetBackgroundColor($aColor) {
$this->iBackgroundColor = $aColor; $this->iBackgroundColor = $aColor;
} }
   
function SetColTitles($aTitles,$aWidth=null) { function SetColTitles($aTitles,$aWidth=null) {
$this->iTitles = $aTitles; $this->iTitles = $aTitles;
$this->iWidth = $aWidth; $this->iWidth = $aWidth;
} }
   
function SetMinColWidth($aWidths) { function SetMinColWidth($aWidths) {
$n = min(count($this->iTitles),count($aWidths)); $n = min(count($this->iTitles),count($aWidths));
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
if( !empty($aWidths[$i]) ) { if( !empty($aWidths[$i]) ) {
if( empty($this->iWidth[$i]) ) { if( empty($this->iWidth[$i]) ) {
$this->iWidth[$i] = $aWidths[$i]; $this->iWidth[$i] = $aWidths[$i];
} }
else { else {
$this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]); $this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]);
} }
} }
} }
} }
   
function GetWidth($aImg) { function GetWidth($aImg) {
$txt = new TextProperty(); $txt = new TextProperty();
$txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
$n = count($this->iTitles) ; $n = count($this->iTitles) ;
$rm=$this->iRightColMargin; $rm=$this->iRightColMargin;
$w = 0; $w = 0;
for($h=0, $i=0; $i < $n; ++$i ) { for($h=0, $i=0; $i < $n; ++$i ) {
$w += $this->iLeftColMargin; $w += $this->iLeftColMargin;
$txt->Set($this->iTitles[$i]); $txt->Set($this->iTitles[$i]);
if( !empty($this->iWidth[$i]) ) { if( !empty($this->iWidth[$i]) ) {
$w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]); $w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]);
} }
else { else {
$w1 = $txt->GetWidth($aImg)+$rm; $w1 = $txt->GetWidth($aImg)+$rm;
} }
$this->iWidth[$i] = $w1; $this->iWidth[$i] = $w1;
$w += $w1; $w += $w1;
$h = max($h,$txt->GetHeight($aImg)); $h = max($h,$txt->GetHeight($aImg));
} }
$this->iHeight = $h+$this->iTopHeaderMargin; $this->iHeight = $h+$this->iTopHeaderMargin;
$txt=''; $txt='';
return $w; return $w;
} }
   
function GetColStart($aImg,&$aStart,$aAddLeftMargin=false) { function GetColStart($aImg,&$aStart,$aAddLeftMargin=false) {
$n = count($this->iTitles) ; $n = count($this->iTitles) ;
$adj = $aAddLeftMargin ? $this->iLeftColMargin : 0; $adj = $aAddLeftMargin ? $this->iLeftColMargin : 0;
$aStart=array($aImg->left_margin+$adj); $aStart=array($aImg->left_margin+$adj);
for( $i=1; $i < $n; ++$i ) { for( $i=1; $i < $n; ++$i ) {
$aStart[$i] = $aStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1]; $aStart[$i] = $aStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1];
} }
} }
   
// Adjust headers left, right or centered // Adjust headers left, right or centered
function SetHeaderAlign($aAlign) { function SetHeaderAlign($aAlign) {
$this->iHeaderAlign=$aAlign; $this->iHeaderAlign=$aAlign;
} }
   
function Stroke($aImg,$aXLeft,$aYTop,$aXRight,$aYBottom,$aUseTextHeight=false) { function Stroke($aImg,$aXLeft,$aYTop,$aXRight,$aYBottom,$aUseTextHeight=false) {
   
if( !$this->iShow ) return; if( !$this->iShow ) return;
   
$txt = new TextProperty(); $txt = new TextProperty();
$txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
$txt->SetColor($this->iFontColor); $txt->SetColor($this->iFontColor);
$txt->SetAlign($this->iHeaderAlign,'top'); $txt->SetAlign($this->iHeaderAlign,'top');
$n=count($this->iTitles); $n=count($this->iTitles);
   
if( $n == 0 ) if( $n == 0 )
return; return;
   
$x = $aXLeft; $x = $aXLeft;
$h = $this->iHeight; $h = $this->iHeight;
$yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ; $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ;
   
if( $h < 0 ) { if( $h < 0 ) {
JpGraphError::RaiseL(6001); JpGraphError::RaiseL(6001);
//('Internal error. Height for ActivityTitles is < 0'); //('Internal error. Height for ActivityTitles is < 0');
} }
   
$aImg->SetLineWeight(1); $aImg->SetLineWeight(1);
// Set background color // Set background color
$aImg->SetColor($this->iBackgroundColor); $aImg->SetColor($this->iBackgroundColor);
$aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1); $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1);
   
if( $this->iStyle == 1 ) { if( $this->iStyle == 1 ) {
// Make a 3D effect // Make a 3D effect
$aImg->SetColor('white'); $aImg->SetColor('white');
$aImg->Line($aXLeft,$yTop+1,$aXRight,$yTop+1); $aImg->Line($aXLeft,$yTop+1,$aXRight,$yTop+1);
} }
   
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
if( $this->iStyle == 1 ) { if( $this->iStyle == 1 ) {
// Make a 3D effect // Make a 3D effect
$aImg->SetColor('white'); $aImg->SetColor('white');
$aImg->Line($x+1,$yTop,$x+1,$aYBottom); $aImg->Line($x+1,$yTop,$x+1,$aYBottom);
} }
$x += $this->iLeftColMargin; $x += $this->iLeftColMargin;
$txt->Set($this->iTitles[$i]); $txt->Set($this->iTitles[$i]);
   
// Adjust the text anchor position according to the choosen alignment // Adjust the text anchor position according to the choosen alignment
$xp = $x; $xp = $x;
if( $this->iHeaderAlign == 'center' ) { if( $this->iHeaderAlign == 'center' ) {
$xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2; $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2;
} }
elseif( $this->iHeaderAlign == 'right' ) { elseif( $this->iHeaderAlign == 'right' ) {
$xp = $x +$this->iWidth[$i]-$this->iRightColMargin; $xp = $x +$this->iWidth[$i]-$this->iRightColMargin;
} }
   
$txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin); $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin);
$x += $this->iWidth[$i]; $x += $this->iWidth[$i];
if( $i < $n-1 ) { if( $i < $n-1 ) {
$aImg->SetColor($this->iColor); $aImg->SetColor($this->iColor);
$aImg->Line($x,$yTop,$x,$aYBottom); $aImg->Line($x,$yTop,$x,$aYBottom);
} }
} }
   
$aImg->SetColor($this->iColor); $aImg->SetColor($this->iColor);
$aImg->Line($aXLeft,$yTop, $aXRight,$yTop); $aImg->Line($aXLeft,$yTop, $aXRight,$yTop);
   
// Stroke vertical column dividers // Stroke vertical column dividers
$cols=array(); $cols=array();
$this->GetColStart($aImg,$cols); $this->GetColStart($aImg,$cols);
$n=count($cols); $n=count($cols);
for( $i=1; $i < $n; ++$i ) { for( $i=1; $i < $n; ++$i ) {
$this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i], $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i],
$aImg->height - $aImg->bottom_margin); $aImg->height - $aImg->bottom_margin);
} }
} }
} }
   
   
//=================================================== //===================================================
// CLASS GanttGraph // CLASS GanttGraph
// Description: Main class to handle gantt graphs // Description: Main class to handle gantt graphs
//=================================================== //===================================================
class GanttGraph extends Graph { class GanttGraph extends Graph {
public $scale; // Public accessible public $scale; // Public accessible
public $hgrid=null; public $hgrid=null;
private $iObj=array(); // Gantt objects private $iObj=array(); // Gantt objects
private $iLabelHMarginFactor=0.2; // 10% margin on each side of the labels 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 $iLabelVMarginFactor=0.4; // 40% margin on top and bottom of label
private $iLayout=GANTT_FROMTOP; // Could also be GANTT_EVEN private $iLayout=GANTT_FROMTOP; // Could also be GANTT_EVEN
private $iSimpleFont = FF_FONT1,$iSimpleFontSize=11; private $iSimpleFont = FF_FONT1,$iSimpleFontSize=11;
private $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red'; private $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red';
private $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen'; private $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen';
private $iSimpleProgressStyle=GANTT_SOLID; private $iSimpleProgressStyle=GANTT_SOLID;
private $iZoomFactor = 1.0; private $iZoomFactor = 1.0;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
// Create a new gantt graph // Create a new gantt graph
function __construct($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) { function __construct($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) {
   
// Backward compatibility // Backward compatibility
if( $aWidth == -1 ) $aWidth=0; if( $aWidth == -1 ) $aWidth=0;
if( $aHeight == -1 ) $aHeight=0; if( $aHeight == -1 ) $aHeight=0;
   
if( $aWidth< 0 || $aHeight < 0 ) { if( $aWidth< 0 || $aHeight < 0 ) {
JpgraphError::RaiseL(6002); 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."); //("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); parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline);
$this->scale = new GanttScale($this->img); $this->scale = new GanttScale($this->img);
   
// Default margins // Default margins
$this->img->SetMargin(15,17,25,15); $this->img->SetMargin(15,17,25,15);
   
$this->hgrid = new HorizontalGridLine(); $this->hgrid = new HorizontalGridLine();
   
$this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY); $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY);
$this->SetBox(); $this->SetBox();
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
// //
   
function SetSimpleFont($aFont,$aSize) { function SetSimpleFont($aFont,$aSize) {
$this->iSimpleFont = $aFont; $this->iSimpleFont = $aFont;
$this->iSimpleFontSize = $aSize; $this->iSimpleFontSize = $aSize;
} }
   
function SetSimpleStyle($aBand,$aColor,$aBkgColor) { function SetSimpleStyle($aBand,$aColor,$aBkgColor) {
$this->iSimpleStyle = $aBand; $this->iSimpleStyle = $aBand;
$this->iSimpleColor = $aColor; $this->iSimpleColor = $aColor;
$this->iSimpleBkgColor = $aBkgColor; $this->iSimpleBkgColor = $aBkgColor;
} }
   
// A utility function to help create basic Gantt charts // A utility function to help create basic Gantt charts
function CreateSimple($data,$constrains=array(),$progress=array()) { function CreateSimple($data,$constrains=array(),$progress=array()) {
$num = count($data); $num = count($data);
for( $i=0; $i < $num; ++$i) { for( $i=0; $i < $num; ++$i) {
switch( $data[$i][1] ) { switch( $data[$i][1] ) {
case ACTYPE_GROUP: case ACTYPE_GROUP:
// Create a slightly smaller height bar since the // Create a slightly smaller height bar since the
// "wings" at the end will make it look taller // "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 = 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->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize);
$a->rightMark->Show(); $a->rightMark->Show();
$a->rightMark->SetType(MARK_RIGHTTRIANGLE); $a->rightMark->SetType(MARK_RIGHTTRIANGLE);
$a->rightMark->SetWidth(8); $a->rightMark->SetWidth(8);
$a->rightMark->SetColor('black'); $a->rightMark->SetColor('black');
$a->rightMark->SetFillColor('black'); $a->rightMark->SetFillColor('black');
   
$a->leftMark->Show(); $a->leftMark->Show();
$a->leftMark->SetType(MARK_LEFTTRIANGLE); $a->leftMark->SetType(MARK_LEFTTRIANGLE);
$a->leftMark->SetWidth(8); $a->leftMark->SetWidth(8);
$a->leftMark->SetColor('black'); $a->leftMark->SetColor('black');
$a->leftMark->SetFillColor('black'); $a->leftMark->SetFillColor('black');
   
$a->SetPattern(BAND_SOLID,'black'); $a->SetPattern(BAND_SOLID,'black');
$csimpos = 6; $csimpos = 6;
break; break;
   
case ACTYPE_NORMAL: case ACTYPE_NORMAL:
$a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10); $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->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
$a->SetPattern($this->iSimpleStyle,$this->iSimpleColor); $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor);
$a->SetFillColor($this->iSimpleBkgColor); $a->SetFillColor($this->iSimpleBkgColor);
// Check if this activity should have a constrain line // Check if this activity should have a constrain line
$n = count($constrains); $n = count($constrains);
for( $j=0; $j < $n; ++$j ) { for( $j=0; $j < $n; ++$j ) {
if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) { if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) {
JpGraphError::RaiseL(6003,$j); 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)"); //("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] ) { if( $constrains[$j][0]==$data[$i][0] ) {
$a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID); $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID);
} }
} }
   
// Check if this activity have a progress bar // Check if this activity have a progress bar
$n = count($progress); $n = count($progress);
for( $j=0; $j < $n; ++$j ) { for( $j=0; $j < $n; ++$j ) {
   
if( empty($progress[$j]) || (count($progress[$j]) != 2) ) { if( empty($progress[$j]) || (count($progress[$j]) != 2) ) {
JpGraphError::RaiseL(6004,$j); 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)"); //("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] ) { if( $progress[$j][0]==$data[$i][0] ) {
$a->progress->Set($progress[$j][1]); $a->progress->Set($progress[$j][1]);
$a->progress->SetPattern($this->iSimpleProgressStyle, $a->progress->SetPattern($this->iSimpleProgressStyle,
$this->iSimpleProgressColor); $this->iSimpleProgressColor);
$a->progress->SetFillColor($this->iSimpleProgressBkgColor); $a->progress->SetFillColor($this->iSimpleProgressBkgColor);
//$a->progress->SetPattern($progress[$j][2],$progress[$j][3]); //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]);
break; break;
} }
} }
$csimpos = 6; $csimpos = 6;
break; break;
   
case ACTYPE_MILESTONE: case ACTYPE_MILESTONE:
$a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]); $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]);
$a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
$a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
$csimpos = 5; $csimpos = 5;
break; break;
default: default:
die('Unknown activity type'); die('Unknown activity type');
break; break;
} }
   
// Setup caption // Setup caption
$a->caption->Set($data[$i][$csimpos-1]); $a->caption->Set($data[$i][$csimpos-1]);
   
// Check if this activity should have a CSIM target�? // Check if this activity should have a CSIM target�?
if( !empty($data[$i][$csimpos]) ) { if( !empty($data[$i][$csimpos]) ) {
$a->SetCSIMTarget($data[$i][$csimpos]); $a->SetCSIMTarget($data[$i][$csimpos]);
$a->SetCSIMAlt($data[$i][$csimpos+1]); $a->SetCSIMAlt($data[$i][$csimpos+1]);
} }
if( !empty($data[$i][$csimpos+2]) ) { if( !empty($data[$i][$csimpos+2]) ) {
$a->title->SetCSIMTarget($data[$i][$csimpos+2]); $a->title->SetCSIMTarget($data[$i][$csimpos+2]);
$a->title->SetCSIMAlt($data[$i][$csimpos+3]); $a->title->SetCSIMAlt($data[$i][$csimpos+3]);
} }
   
$this->Add($a); $this->Add($a);
} }
} }
   
// Set user specified scale zoom factor when auto sizing is used // Set user specified scale zoom factor when auto sizing is used
function SetZoomFactor($aZoom) { function SetZoomFactor($aZoom) {
$this->iZoomFactor = $aZoom; $this->iZoomFactor = $aZoom;
} }
   
   
// Set what headers should be shown // Set what headers should be shown
function ShowHeaders($aFlg) { function ShowHeaders($aFlg) {
$this->scale->ShowHeaders($aFlg); $this->scale->ShowHeaders($aFlg);
} }
   
// Specify the fraction of the font height that should be added // Specify the fraction of the font height that should be added
// as vertical margin // as vertical margin
function SetLabelVMarginFactor($aVal) { function SetLabelVMarginFactor($aVal) {
$this->iLabelVMarginFactor = $aVal; $this->iLabelVMarginFactor = $aVal;
} }
   
// Synonym to the method above // Synonym to the method above
function SetVMarginFactor($aVal) { function SetVMarginFactor($aVal) {
$this->iLabelVMarginFactor = $aVal; $this->iLabelVMarginFactor = $aVal;
} }
   
   
// Add a new Gantt object // Add a new Gantt object
function Add($aObject) { function Add($aObject) {
if( is_array($aObject) && count($aObject) > 0 ) { if( is_array($aObject) && count($aObject) > 0 ) {
$cl = $aObject[0]; $cl = $aObject[0];
if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) { if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) {
$this->AddIcon($aObject); $this->AddIcon($aObject);
} }
elseif( class_exists('Text',false) && ($cl instanceof Text) ) { elseif( class_exists('Text',false) && ($cl instanceof Text) ) {
$this->AddText($aObject); $this->AddText($aObject);
} }
else { else {
$n = count($aObject); $n = count($aObject);
for($i=0; $i < $n; ++$i) for($i=0; $i < $n; ++$i)
$this->iObj[] = $aObject[$i]; $this->iObj[] = $aObject[$i];
} }
} }
else { else {
if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) { if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) {
$this->AddIcon($aObject); $this->AddIcon($aObject);
} }
elseif( class_exists('Text',false) && ($aObject instanceof Text) ) { elseif( class_exists('Text',false) && ($aObject instanceof Text) ) {
$this->AddText($aObject); $this->AddText($aObject);
} }
else { else {
$this->iObj[] = $aObject; $this->iObj[] = $aObject;
} }
} }
} }
   
function StrokeTexts() { function StrokeTexts() {
// Stroke any user added text objects // Stroke any user added text objects
if( $this->texts != null ) { if( $this->texts != null ) {
$n = count($this->texts); $n = count($this->texts);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $this->texts[$i]->iScalePosX !== null && $this->texts[$i]->iScalePosY !== null ) { if( $this->texts[$i]->iScalePosX !== null && $this->texts[$i]->iScalePosY !== null ) {
$x = $this->scale->TranslateDate($this->texts[$i]->iScalePosX); $x = $this->scale->TranslateDate($this->texts[$i]->iScalePosX);
$y = $this->scale->TranslateVertPos($this->texts[$i]->iScalePosY); $y = $this->scale->TranslateVertPos($this->texts[$i]->iScalePosY);
$y -= $this->scale->GetVertSpacing()/2; $y -= $this->scale->GetVertSpacing()/2;
} }
else { else {
$x = $y = null; $x = $y = null;
} }
$this->texts[$i]->Stroke($this->img,$x,$y); $this->texts[$i]->Stroke($this->img,$x,$y);
} }
} }
} }
   
// Override inherit method from Graph and give a warning message // Override inherit method from Graph and give a warning message
function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) { function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
JpGraphError::RaiseL(6005); JpGraphError::RaiseL(6005);
//("SetScale() is not meaningfull with Gantt charts."); //("SetScale() is not meaningfull with Gantt charts.");
} }
   
// Specify the date range for Gantt graphs (if this is not set it will be // Specify the date range for Gantt graphs (if this is not set it will be
// automtically determined from the input data) // automtically determined from the input data)
function SetDateRange($aStart,$aEnd) { function SetDateRange($aStart,$aEnd) {
// Adjust the start and end so that the indicate the // Adjust the start and end so that the indicate the
// begining and end of respective start and end days // begining and end of respective start and end days
if( strpos($aStart,':') === false ) if( strpos($aStart,':') === false )
$aStart = date('Y-m-d 00:00',strtotime($aStart)); $aStart = date('Y-m-d 00:00',strtotime($aStart));
if( strpos($aEnd,':') === false ) if( strpos($aEnd,':') === false )
$aEnd = date('Y-m-d 23:59',strtotime($aEnd)); $aEnd = date('Y-m-d 23:59',strtotime($aEnd));
$this->scale->SetRange($aStart,$aEnd); $this->scale->SetRange($aStart,$aEnd);
} }
   
// Get the maximum width of the activity titles columns for the bars // Get the maximum width of the activity titles columns for the bars
// The name is lightly misleading since we from now on can have // The name is lightly misleading since we from now on can have
// multiple columns in the label section. When this was first written // multiple columns in the label section. When this was first written
// it only supported a single label, hence the name. // it only supported a single label, hence the name.
function GetMaxLabelWidth() { function GetMaxLabelWidth() {
$m=10; $m=10;
if( $this->iObj != null ) { if( $this->iObj != null ) {
$marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin; $marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin;
$n = count($this->iObj); $n = count($this->iObj);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( !empty($this->iObj[$i]->title) ) { if( !empty($this->iObj[$i]->title) ) {
if( $this->iObj[$i]->title->HasTabs() ) { if( $this->iObj[$i]->title->HasTabs() ) {
list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true); list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true);
$m=max($m,$tot); $m=max($m,$tot);
} }
else else
$m=max($m,$this->iObj[$i]->title->GetWidth($this->img)); $m=max($m,$this->iObj[$i]->title->GetWidth($this->img));
} }
} }
} }
return $m; return $m;
} }
   
// Get the maximum height of the titles for the bars // Get the maximum height of the titles for the bars
function GetMaxLabelHeight() { function GetMaxLabelHeight() {
$m=10; $m=10;
if( $this->iObj != null ) { if( $this->iObj != null ) {
$n = count($this->iObj); $n = count($this->iObj);
// We can not include the title of GnttVLine since that title is stroked at the bottom // 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 // of the Gantt bar and not in the activity title columns
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( !empty($this->iObj[$i]->title) && !($this->iObj[$i] instanceof GanttVLine) ) { if( !empty($this->iObj[$i]->title) && !($this->iObj[$i] instanceof GanttVLine) ) {
$m=max($m,$this->iObj[$i]->title->GetHeight($this->img)); $m=max($m,$this->iObj[$i]->title->GetHeight($this->img));
} }
} }
} }
return $m; return $m;
} }
   
function GetMaxBarAbsHeight() { function GetMaxBarAbsHeight() {
$m=0; $m=0;
if( $this->iObj != null ) { if( $this->iObj != null ) {
$m = $this->iObj[0]->GetAbsHeight($this->img); $m = $this->iObj[0]->GetAbsHeight($this->img);
$n = count($this->iObj); $n = count($this->iObj);
for($i=1; $i < $n; ++$i) { for($i=1; $i < $n; ++$i) {
$m=max($m,$this->iObj[$i]->GetAbsHeight($this->img)); $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img));
} }
} }
return $m; return $m;
} }
   
// Get the maximum used line number (vertical position) for bars // Get the maximum used line number (vertical position) for bars
function GetBarMaxLineNumber() { function GetBarMaxLineNumber() {
$m=1; $m=1;
if( $this->iObj != null ) { if( $this->iObj != null ) {
$m = $this->iObj[0]->GetLineNbr(); $m = $this->iObj[0]->GetLineNbr();
$n = count($this->iObj); $n = count($this->iObj);
for($i=1; $i < $n; ++$i) { for($i=1; $i < $n; ++$i) {
$m=max($m,$this->iObj[$i]->GetLineNbr()); $m=max($m,$this->iObj[$i]->GetLineNbr());
} }
} }
return $m; return $m;
} }
   
// Get the minumum and maximum used dates for all bars // Get the minumum and maximum used dates for all bars
function GetBarMinMax() { function GetBarMinMax() {
$start = 0 ; $start = 0 ;
$n = count($this->iObj); $n = count($this->iObj);
while( $start < $n && $this->iObj[$start]->GetMaxDate() === false ) while( $start < $n && $this->iObj[$start]->GetMaxDate() === false )
++$start; ++$start;
if( $start >= $n ) { if( $start >= $n ) {
JpgraphError::RaiseL(6006); JpgraphError::RaiseL(6006);
//('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]'); //('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]');
} }
   
$max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate()); $max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate());
$min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate()); $min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate());
   
for($i=$start+1; $i < $n; ++$i) { for($i=$start+1; $i < $n; ++$i) {
$rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate()); $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate());
if( $rmax != false ) if( $rmax != false )
$max=Max($max,$rmax); $max=Max($max,$rmax);
$rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate()); $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate());
if( $rmin != false ) if( $rmin != false )
$min=Min($min,$rmin); $min=Min($min,$rmin);
} }
$minDate = date("Y-m-d",$min); $minDate = date("Y-m-d",$min);
$min = strtotime($minDate); $min = strtotime($minDate);
$maxDate = date("Y-m-d 23:59",$max); $maxDate = date("Y-m-d 23:59",$max);
$max = strtotime($maxDate); $max = strtotime($maxDate);
return array($min,$max); return array($min,$max);
} }
   
// Create a new auto sized canvas if the user hasn't specified a size // 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 size is determined by what scale the user has choosen and hence
// the minimum width needed to display the headers. Some margins are // the minimum width needed to display the headers. Some margins are
// also added to make it better looking. // also added to make it better looking.
function AutoSize() { function AutoSize() {
   
if( $this->img->img == null ) { if( $this->img->img == null ) {
// The predefined left, right, top, bottom margins. // The predefined left, right, top, bottom margins.
// Note that the top margin might incease depending on // Note that the top margin might incease depending on
// the title. // the title.
$hadj = $vadj = 0; $hadj = $vadj = 0;
if( $this->doshadow ) { if( $this->doshadow ) {
$hadj = $this->shadow_width; $hadj = $this->shadow_width;
$vadj = $this->shadow_width+5; $vadj = $this->shadow_width+5;
} }
   
$lm = $this->img->left_margin; $lm = $this->img->left_margin;
$rm = $this->img->right_margin +$hadj; $rm = $this->img->right_margin +$hadj;
$rm += 2 ; $rm += 2 ;
$tm = $this->img->top_margin; $tm = $this->img->top_margin;
$bm = $this->img->bottom_margin + $vadj; $bm = $this->img->bottom_margin + $vadj;
$bm += 2; $bm += 2;
   
// If there are any added GanttVLine we must make sure that the // If there are any added GanttVLine we must make sure that the
// bottom margin is wide enough to hold a title. // bottom margin is wide enough to hold a title.
$n = count($this->iObj); $n = count($this->iObj);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $this->iObj[$i] instanceof GanttVLine ) { if( $this->iObj[$i] instanceof GanttVLine ) {
$bm = max($bm,$this->iObj[$i]->title->GetHeight($this->img)+10); $bm = max($bm,$this->iObj[$i]->title->GetHeight($this->img)+10);
} }
} }
   
// First find out the height // First find out the height
$n=$this->GetBarMaxLineNumber()+1; $n=$this->GetBarMaxLineNumber()+1;
$m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
$height=$n*((1+$this->iLabelVMarginFactor)*$m); $height=$n*((1+$this->iLabelVMarginFactor)*$m);
   
// Add the height of the scale titles // Add the height of the scale titles
$h=$this->scale->GetHeaderHeight(); $h=$this->scale->GetHeaderHeight();
$height += $h; $height += $h;
   
// Calculate the top margin needed for title and subtitle // Calculate the top margin needed for title and subtitle
if( $this->title->t != "" ) { if( $this->title->t != "" ) {
$tm += $this->title->GetFontHeight($this->img); $tm += $this->title->GetFontHeight($this->img);
} }
if( $this->subtitle->t != "" ) { if( $this->subtitle->t != "" ) {
$tm += $this->subtitle->GetFontHeight($this->img); $tm += $this->subtitle->GetFontHeight($this->img);
} }
   
// ...and then take the bottom and top plot margins into account // ...and then take the bottom and top plot margins into account
$height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin; $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin;
// Now find the minimum width for the chart required // Now find the minimum width for the chart required
   
// If day scale or smaller is shown then we use the day font width // If day scale or smaller is shown then we use the day font width
// as the base size unit. // as the base size unit.
// If only weeks or above is displayed we use a modified unit to // If only weeks or above is displayed we use a modified unit to
// get a smaller image. // get a smaller image.
if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) { if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) {
// Add 2 pixel margin on each side // Add 2 pixel margin on each side
$fw=$this->scale->day->GetFontWidth($this->img)+4; $fw=$this->scale->day->GetFontWidth($this->img)+4;
} }
elseif( $this->scale->IsDisplayWeek() ) { elseif( $this->scale->IsDisplayWeek() ) {
$fw = 8; $fw = 8;
} }
elseif( $this->scale->IsDisplayMonth() ) { elseif( $this->scale->IsDisplayMonth() ) {
$fw = 4; $fw = 4;
} }
else { else {
$fw = 2; $fw = 2;
} }
   
$nd=$this->scale->GetNumberOfDays(); $nd=$this->scale->GetNumberOfDays();
   
if( $this->scale->IsDisplayDay() ) { if( $this->scale->IsDisplayDay() ) {
// If the days are displayed we also need to figure out // If the days are displayed we also need to figure out
// how much space each day's title will require. // how much space each day's title will require.
switch( $this->scale->day->iStyle ) { switch( $this->scale->day->iStyle ) {
case DAYSTYLE_LONG : case DAYSTYLE_LONG :
$txt = "Monday"; $txt = "Monday";
break; break;
case DAYSTYLE_LONGDAYDATE1 : case DAYSTYLE_LONGDAYDATE1 :
$txt = "Monday 23 Jun"; $txt = "Monday 23 Jun";
break; break;
case DAYSTYLE_LONGDAYDATE2 : case DAYSTYLE_LONGDAYDATE2 :
$txt = "Monday 23 Jun 2003"; $txt = "Monday 23 Jun 2003";
break; break;
case DAYSTYLE_SHORT : case DAYSTYLE_SHORT :
$txt = "Mon"; $txt = "Mon";
break; break;
case DAYSTYLE_SHORTDAYDATE1 : case DAYSTYLE_SHORTDAYDATE1 :
$txt = "Mon 23/6"; $txt = "Mon 23/6";
break; break;
case DAYSTYLE_SHORTDAYDATE2 : case DAYSTYLE_SHORTDAYDATE2 :
$txt = "Mon 23 Jun"; $txt = "Mon 23 Jun";
break; break;
case DAYSTYLE_SHORTDAYDATE3 : case DAYSTYLE_SHORTDAYDATE3 :
$txt = "Mon 23"; $txt = "Mon 23";
break; break;
case DAYSTYLE_SHORTDATE1 : case DAYSTYLE_SHORTDATE1 :
$txt = "23/6"; $txt = "23/6";
break; break;
case DAYSTYLE_SHORTDATE2 : case DAYSTYLE_SHORTDATE2 :
$txt = "23 Jun"; $txt = "23 Jun";
break; break;
case DAYSTYLE_SHORTDATE3 : case DAYSTYLE_SHORTDATE3 :
$txt = "Mon 23"; $txt = "Mon 23";
break; break;
case DAYSTYLE_SHORTDATE4 : case DAYSTYLE_SHORTDATE4 :
$txt = "88"; $txt = "88";
break; break;
case DAYSTYLE_CUSTOM : case DAYSTYLE_CUSTOM :
$txt = date($this->scale->day->iLabelFormStr,strtotime('2003-12-20 18:00')); $txt = date($this->scale->day->iLabelFormStr,strtotime('2003-12-20 18:00'));
break; break;
case DAYSTYLE_ONELETTER : case DAYSTYLE_ONELETTER :
default: default:
$txt = "M"; $txt = "M";
break; break;
} }
$fw = $this->scale->day->GetStrWidth($this->img,$txt)+6; $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6;
} }
   
// If we have hours enabled we must make sure that each day has enough // If we have hours enabled we must make sure that each day has enough
// space to fit the number of hours to be displayed. // space to fit the number of hours to be displayed.
if( $this->scale->IsDisplayHour() ) { if( $this->scale->IsDisplayHour() ) {
// Depending on what format the user has choose we need different amount // Depending on what format the user has choose we need different amount
// of space. We therefore create a typical string for the choosen format // of space. We therefore create a typical string for the choosen format
// and determine the length of that string. // and determine the length of that string.
switch( $this->scale->hour->iStyle ) { switch( $this->scale->hour->iStyle ) {
case HOURSTYLE_HMAMPM: case HOURSTYLE_HMAMPM:
$txt = '12:00pm'; $txt = '12:00pm';
break; break;
case HOURSTYLE_H24: case HOURSTYLE_H24:
// 13 // 13
$txt = '24'; $txt = '24';
break; break;
case HOURSTYLE_HAMPM: case HOURSTYLE_HAMPM:
$txt = '12pm'; $txt = '12pm';
break; break;
case HOURSTYLE_CUSTOM: case HOURSTYLE_CUSTOM:
$txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00')); $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00'));
break; break;
case HOURSTYLE_HM24: case HOURSTYLE_HM24:
default: default:
$txt = '24:00'; $txt = '24:00';
break; break;
} }
   
$hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6; $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6;
$mw = $hfw; $mw = $hfw;
if( $this->scale->IsDisplayMinute() ) { if( $this->scale->IsDisplayMinute() ) {
// Depending on what format the user has choose we need different amount // Depending on what format the user has choose we need different amount
// of space. We therefore create a typical string for the choosen format // of space. We therefore create a typical string for the choosen format
// and determine the length of that string. // and determine the length of that string.
switch( $this->scale->minute->iStyle ) { switch( $this->scale->minute->iStyle ) {
case HOURSTYLE_CUSTOM: case HOURSTYLE_CUSTOM:
$txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55'));
break; break;
case MINUTESTYLE_MM: case MINUTESTYLE_MM:
default: default:
$txt2 = '15'; $txt2 = '15';
break; break;
} }
   
$mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6; $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6;
$n2 = ceil(60 / $this->scale->minute->GetIntervall() ); $n2 = ceil(60 / $this->scale->minute->GetIntervall() );
$mw = $n2 * $mfw; $mw = $n2 * $mfw;
} }
$hfw = $hfw < $mw ? $mw : $hfw ; $hfw = $hfw < $mw ? $mw : $hfw ;
$n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) ); $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) );
$hw = $n * $hfw; $hw = $n * $hfw;
$fw = $fw < $hw ? $hw : $fw ; $fw = $fw < $hw ? $hw : $fw ;
} }
   
// We need to repeat this code block here as well. // We need to repeat this code block here as well.
// THIS iS NOT A MISTAKE ! // THIS iS NOT A MISTAKE !
// We really need it since we need to adjust for minutes both in the case // 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. // where hour scale is shown and when it is not shown.
   
if( $this->scale->IsDisplayMinute() ) { if( $this->scale->IsDisplayMinute() ) {
// Depending on what format the user has choose we need different amount // Depending on what format the user has choose we need different amount
// of space. We therefore create a typical string for the choosen format // of space. We therefore create a typical string for the choosen format
// and determine the length of that string. // and determine the length of that string.
switch( $this->scale->minute->iStyle ) { switch( $this->scale->minute->iStyle ) {
case HOURSTYLE_CUSTOM: case HOURSTYLE_CUSTOM:
$txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55'));
break; break;
case MINUTESTYLE_MM: case MINUTESTYLE_MM:
default: default:
$txt = '15'; $txt = '15';
break; break;
} }
   
$mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6; $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6;
$n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) ); $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) );
$mw = $n * $mfw; $mw = $n * $mfw;
$fw = $fw < $mw ? $mw : $fw ; $fw = $fw < $mw ? $mw : $fw ;
} }
   
// If we display week we must make sure that 7*$fw is enough // 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) // to fit up to 10 characters of the week font (if the week is enabled)
if( $this->scale->IsDisplayWeek() ) { if( $this->scale->IsDisplayWeek() ) {
// Depending on what format the user has choose we need different amount // Depending on what format the user has choose we need different amount
// of space // of space
$fsw = strlen($this->scale->week->iLabelFormStr); $fsw = strlen($this->scale->week->iLabelFormStr);
if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
$fsw += 8; $fsw += 8;
} }
elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) { elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) {
$fsw += 7; $fsw += 7;
} }
else { else {
$fsw += 4; $fsw += 4;
} }
   
$ww = $fsw*$this->scale->week->GetFontWidth($this->img); $ww = $fsw*$this->scale->week->GetFontWidth($this->img);
if( 7*$fw < $ww ) { if( 7*$fw < $ww ) {
$fw = ceil($ww/7); $fw = ceil($ww/7);
} }
} }
   
if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() && if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() &&
!( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
$this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) { $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) {
// If we don't display the individual days we can shrink the // If we don't display the individual days we can shrink the
// scale a little bit. This is a little bit pragmatic at the // scale a little bit. This is a little bit pragmatic at the
// moment and should be re-written to take into account // moment and should be re-written to take into account
// a) What scales exactly are shown and // a) What scales exactly are shown and
// b) what format do they use so we know how wide we need to // b) what format do they use so we know how wide we need to
// make each scale text space at minimum. // make each scale text space at minimum.
$fw /= 2; $fw /= 2;
if( !$this->scale->IsDisplayWeek() ) { if( !$this->scale->IsDisplayWeek() ) {
$fw /= 1.8; $fw /= 1.8;
} }
} }
   
$cw = $this->GetMaxActInfoColWidth() ; $cw = $this->GetMaxActInfoColWidth() ;
$this->scale->actinfo->SetMinColWidth($cw); $this->scale->actinfo->SetMinColWidth($cw);
if( $this->img->width <= 0 ) { if( $this->img->width <= 0 ) {
// Now determine the width for the activity titles column // Now determine the width for the activity titles column
   
// Firdst find out the maximum width of each object column // Firdst find out the maximum width of each object column
$titlewidth = max(max($this->GetMaxLabelWidth(), $titlewidth = max(max($this->GetMaxLabelWidth(),
$this->scale->tableTitle->GetWidth($this->img)), $this->scale->tableTitle->GetWidth($this->img)),
$this->scale->actinfo->GetWidth($this->img)); $this->scale->actinfo->GetWidth($this->img));
   
// Add the width of the vertivcal divider line // Add the width of the vertivcal divider line
$titlewidth += $this->scale->divider->iWeight*2; $titlewidth += $this->scale->divider->iWeight*2;
   
// Adjust the width by the user specified zoom factor // Adjust the width by the user specified zoom factor
$fw *= $this->iZoomFactor; $fw *= $this->iZoomFactor;
   
// Now get the total width taking // Now get the total width taking
// titlewidth, left and rigt margin, dayfont size // titlewidth, left and rigt margin, dayfont size
// into account // into account
$width = $titlewidth + $nd*$fw + $lm+$rm; $width = $titlewidth + $nd*$fw + $lm+$rm;
} }
else { else {
$width = $this->img->width; $width = $this->img->width;
} }
   
$width = round($width); $width = round($width);
$height = round($height); $height = round($height);
// Make a sanity check on image size // Make a sanity check on image size
if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) { if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) {
JpgraphError::RaiseL(6007,$width,$height); 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."); //("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->CreateImgCanvas($width,$height);
$this->img->SetMargin($lm,$rm,$tm,$bm); $this->img->SetMargin($lm,$rm,$tm,$bm);
} }
} }
   
// Return an array width the maximum width for each activity // Return an array width the maximum width for each activity
// column. This is used when we autosize the columns where we need // 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 // to find out the maximum width of each column. In order to do that we
// must walk through all the objects, sigh... // must walk through all the objects, sigh...
function GetMaxActInfoColWidth() { function GetMaxActInfoColWidth() {
$n = count($this->iObj); $n = count($this->iObj);
if( $n == 0 ) return; if( $n == 0 ) return;
$w = array(); $w = array();
$m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin; $m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin;
   
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m); $tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m);
$nn = count($tmp); $nn = count($tmp);
for( $j=0; $j < $nn; ++$j ) { for( $j=0; $j < $nn; ++$j ) {
if( empty($w[$j]) ) if( empty($w[$j]) )
$w[$j] = $tmp[$j]; $w[$j] = $tmp[$j];
else else
$w[$j] = max($w[$j],$tmp[$j]); $w[$j] = max($w[$j],$tmp[$j]);
} }
} }
return $w; return $w;
} }
   
// Stroke the gantt chart // Stroke the gantt chart
function Stroke($aStrokeFileName="") { function Stroke($aStrokeFileName="") {
   
// If the filename is the predefined value = '_csim_special_' // If the filename is the predefined value = '_csim_special_'
// we assume that the call to stroke only needs to do enough // we assume that the call to stroke only needs to do enough
// to correctly generate the CSIM maps. // to correctly generate the CSIM maps.
// We use this variable to skip things we don't strictly need // We use this variable to skip things we don't strictly need
// to do to generate the image map to improve performance // 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 // a best we can. Therefor you will see a lot of tests !$_csim in the
// code below. // code below.
$_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
   
// Should we autoscale dates? // Should we autoscale dates?
   
if( !$this->scale->IsRangeSet() ) { if( !$this->scale->IsRangeSet() ) {
list($min,$max) = $this->GetBarMinMax(); list($min,$max) = $this->GetBarMinMax();
$this->scale->SetRange($min,$max); $this->scale->SetRange($min,$max);
} }
   
$this->scale->AdjustStartEndDay(); $this->scale->AdjustStartEndDay();
   
// Check if we should autoscale the image // Check if we should autoscale the image
$this->AutoSize(); $this->AutoSize();
   
// Should we start from the top or just spread the bars out even over the // Should we start from the top or just spread the bars out even over the
// available height // available height
$this->scale->SetVertLayout($this->iLayout); $this->scale->SetVertLayout($this->iLayout);
if( $this->iLayout == GANTT_FROMTOP ) { if( $this->iLayout == GANTT_FROMTOP ) {
$maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
$this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor)); $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor));
} }
// If it hasn't been set find out the maximum line number // If it hasn't been set find out the maximum line number
if( $this->scale->iVertLines == -1 ) if( $this->scale->iVertLines == -1 )
$this->scale->iVertLines = $this->GetBarMaxLineNumber()+1; $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1;
   
$maxwidth=max($this->scale->actinfo->GetWidth($this->img), $maxwidth=max($this->scale->actinfo->GetWidth($this->img),
max($this->GetMaxLabelWidth(), max($this->GetMaxLabelWidth(),
$this->scale->tableTitle->GetWidth($this->img))); $this->scale->tableTitle->GetWidth($this->img)));
   
$this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor)); $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor));
   
if( !$_csim ) { if( !$_csim ) {
$this->StrokePlotArea(); $this->StrokePlotArea();
if( $this->iIconDepth == DEPTH_BACK ) { if( $this->iIconDepth == DEPTH_BACK ) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
} }
   
$this->scale->Stroke(); $this->scale->Stroke();
   
if( !$_csim ) { if( !$_csim ) {
// Due to a minor off by 1 bug we need to temporarily adjust the margin // Due to a minor off by 1 bug we need to temporarily adjust the margin
$this->img->right_margin--; $this->img->right_margin--;
$this->StrokePlotBox(); $this->StrokePlotBox();
$this->img->right_margin++; $this->img->right_margin++;
} }
   
// Stroke Grid line // Stroke Grid line
$this->hgrid->Stroke($this->img,$this->scale); $this->hgrid->Stroke($this->img,$this->scale);
   
$n = count($this->iObj); $n = count($this->iObj);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
//$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2)); //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2));
$this->iObj[$i]->Stroke($this->img,$this->scale); $this->iObj[$i]->Stroke($this->img,$this->scale);
} }
   
$this->StrokeTitles(); $this->StrokeTitles();
   
if( !$_csim ) { if( !$_csim ) {
$this->StrokeConstrains(); $this->StrokeConstrains();
$this->footer->Stroke($this->img); $this->footer->Stroke($this->img);
   
   
if( $this->iIconDepth == DEPTH_FRONT) { if( $this->iIconDepth == DEPTH_FRONT) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
   
// Stroke all added user texts // Stroke all added user texts
$this->StrokeTexts(); $this->StrokeTexts();
   
// Should we do any final image transformation // Should we do any final image transformation
if( $this->iImgTrans ) { if( $this->iImgTrans ) {
if( !class_exists('ImgTrans',false) ) { if( !class_exists('ImgTrans',false) ) {
require_once('jpgraph_imgtrans.php'); require_once('jpgraph_imgtrans.php');
} }
   
$tform = new ImgTrans($this->img->img); $tform = new ImgTrans($this->img->img);
$this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
$this->iImgTransDirection,$this->iImgTransHighQ, $this->iImgTransDirection,$this->iImgTransHighQ,
$this->iImgTransMinSize,$this->iImgTransFillColor, $this->iImgTransMinSize,$this->iImgTransFillColor,
$this->iImgTransBorder); $this->iImgTransBorder);
} }
   
   
// If the filename is given as the special "__handle" // If the filename is given as the special "__handle"
// then the image handler is returned and the image is NOT // then the image handler is returned and the image is NOT
// streamed back // streamed back
if( $aStrokeFileName == _IMG_HANDLER ) { if( $aStrokeFileName == _IMG_HANDLER ) {
return $this->img->img; return $this->img->img;
} }
else { else {
// Finally stream the generated picture // Finally stream the generated picture
$this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
$aStrokeFileName); $aStrokeFileName);
} }
} }
} }
   
function StrokeConstrains() { function StrokeConstrains() {
$n = count($this->iObj); $n = count($this->iObj);
   
// Stroke all constrains // Stroke all constrains
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
   
// Some gantt objects may not have constraints associated with them // Some gantt objects may not have constraints associated with them
// for example we can add IconPlots which doesn't have this property. // for example we can add IconPlots which doesn't have this property.
if( empty($this->iObj[$i]->constraints) ) continue; if( empty($this->iObj[$i]->constraints) ) continue;
   
$numConstrains = count($this->iObj[$i]->constraints); $numConstrains = count($this->iObj[$i]->constraints);
   
for( $k = 0; $k < $numConstrains; $k++ ) { for( $k = 0; $k < $numConstrains; $k++ ) {
$vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow; $vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow;
if( $vpos >= 0 ) { if( $vpos >= 0 ) {
$c1 = $this->iObj[$i]->iConstrainPos; $c1 = $this->iObj[$i]->iConstrainPos;
   
// Find out which object is on the target row // Find out which object is on the target row
$targetobj = -1; $targetobj = -1;
for( $j=0; $j < $n && $targetobj == -1; ++$j ) { for( $j=0; $j < $n && $targetobj == -1; ++$j ) {
if( $this->iObj[$j]->iVPos == $vpos ) { if( $this->iObj[$j]->iVPos == $vpos ) {
$targetobj = $j; $targetobj = $j;
} }
} }
if( $targetobj == -1 ) { if( $targetobj == -1 ) {
JpGraphError::RaiseL(6008,$this->iObj[$i]->iVPos,$vpos); 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.'); //('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; $c2 = $this->iObj[$targetobj]->iConstrainPos;
if( count($c1) == 4 && count($c2 ) == 4) { if( count($c1) == 4 && count($c2 ) == 4) {
switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) { switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) {
case CONSTRAIN_ENDSTART: case CONSTRAIN_ENDSTART:
if( $c1[1] < $c2[1] ) { if( $c1[1] < $c2[1] ) {
$link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]); $link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]);
} }
else { else {
$link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]); $link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]);
} }
$link->SetPath(3); $link->SetPath(3);
break; break;
case CONSTRAIN_STARTEND: case CONSTRAIN_STARTEND:
if( $c1[1] < $c2[1] ) { if( $c1[1] < $c2[1] ) {
$link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]); $link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]);
} }
else { else {
$link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]); $link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]);
} }
$link->SetPath(0); $link->SetPath(0);
break; break;
case CONSTRAIN_ENDEND: case CONSTRAIN_ENDEND:
if( $c1[1] < $c2[1] ) { if( $c1[1] < $c2[1] ) {
$link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]); $link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]);
} }
else { else {
$link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]); $link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]);
} }
$link->SetPath(1); $link->SetPath(1);
break; break;
case CONSTRAIN_STARTSTART: case CONSTRAIN_STARTSTART:
if( $c1[1] < $c2[1] ) { if( $c1[1] < $c2[1] ) {
$link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]); $link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]);
} }
else { else {
$link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]); $link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]);
} }
$link->SetPath(3); $link->SetPath(3);
break; break;
default: default:
JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos); JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos);
//('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos); //('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos);
break; break;
} }
   
$link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor); $link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor);
$link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize, $link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize,
$this->iObj[$i]->constraints[$k]->iConstrainArrowType); $this->iObj[$i]->constraints[$k]->iConstrainArrowType);
   
$link->Stroke($this->img); $link->Stroke($this->img);
} }
} }
} }
} }
} }
   
function GetCSIMAreas() { function GetCSIMAreas() {
if( !$this->iHasStroked ) if( !$this->iHasStroked )
$this->Stroke(_CSIM_SPECIALFILE); $this->Stroke(_CSIM_SPECIALFILE);
   
$csim = $this->title->GetCSIMAreas(); $csim = $this->title->GetCSIMAreas();
$csim .= $this->subtitle->GetCSIMAreas(); $csim .= $this->subtitle->GetCSIMAreas();
$csim .= $this->subsubtitle->GetCSIMAreas(); $csim .= $this->subsubtitle->GetCSIMAreas();
   
$n = count($this->iObj); $n = count($this->iObj);
for( $i=$n-1; $i >= 0; --$i ) for( $i=$n-1; $i >= 0; --$i )
$csim .= $this->iObj[$i]->GetCSIMArea(); $csim .= $this->iObj[$i]->GetCSIMArea();
return $csim; return $csim;
} }
} }
   
//=================================================== //===================================================
// CLASS PredefIcons // CLASS PredefIcons
// Description: Predefined icons for use with Gantt charts // Description: Predefined icons for use with Gantt charts
//=================================================== //===================================================
define('GICON_WARNINGRED',0); define('GICON_WARNINGRED',0);
define('GICON_TEXT',1); define('GICON_TEXT',1);
define('GICON_ENDCONS',2); define('GICON_ENDCONS',2);
define('GICON_MAIL',3); define('GICON_MAIL',3);
define('GICON_STARTCONS',4); define('GICON_STARTCONS',4);
define('GICON_CALC',5); define('GICON_CALC',5);
define('GICON_MAGNIFIER',6); define('GICON_MAGNIFIER',6);
define('GICON_LOCK',7); define('GICON_LOCK',7);
define('GICON_STOP',8); define('GICON_STOP',8);
define('GICON_WARNINGYELLOW',9); define('GICON_WARNINGYELLOW',9);
define('GICON_FOLDEROPEN',10); define('GICON_FOLDEROPEN',10);
define('GICON_FOLDER',11); define('GICON_FOLDER',11);
define('GICON_TEXTIMPORTANT',12); define('GICON_TEXTIMPORTANT',12);
   
class PredefIcons { class PredefIcons {
private $iBuiltinIcon = null, $iLen = -1 ; private $iBuiltinIcon = null, $iLen = -1 ;
   
function GetLen() { function GetLen() {
return $this->iLen ; return $this->iLen ;
} }
   
function GetImg($aIdx) { function GetImg($aIdx) {
if( $aIdx < 0 || $aIdx >= $this->iLen ) { if( $aIdx < 0 || $aIdx >= $this->iLen ) {
JpGraphError::RaiseL(6010,$aIdx); JpGraphError::RaiseL(6010,$aIdx);
//('Illegal icon index for Gantt builtin icon ['.$aIdx.']'); //('Illegal icon index for Gantt builtin icon ['.$aIdx.']');
} }
return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1])); return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1]));
} }
   
function __construct() { function __construct() {
//========================================================== //==========================================================
// warning.png // warning.png
//========================================================== //==========================================================
$this->iBuiltinIcon[0][0]= 1043 ; $this->iBuiltinIcon[0][0]= 1043 ;
$this->iBuiltinIcon[0][1]= $this->iBuiltinIcon[0][1]=
'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'. 'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'.
'0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'. '0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'.
'5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'. '5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'.
'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'. 'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'.
'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'. 'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'.
'/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'. '/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'.
'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'. 'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'.
'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'. 'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'.
'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'. 'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'.
'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'. 'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'.
'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'. 'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'.
'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'. 'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'.
'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ; 'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// edit.png // edit.png
//========================================================== //==========================================================
$this->iBuiltinIcon[1][0]= 959 ; $this->iBuiltinIcon[1][0]= 959 ;
$this->iBuiltinIcon[1][1]= $this->iBuiltinIcon[1][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'.
'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'. 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'.
'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'. 'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'.
'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'. 'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'.
'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'. 'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'.
'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'. 'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'.
'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'. 'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'.
'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'. 'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'.
'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'. 'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'.
'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'. 'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'.
'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'. 'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'.
'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'. 'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'.
'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ; 'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// endconstrain.png // endconstrain.png
//========================================================== //==========================================================
$this->iBuiltinIcon[2][0]= 666 ; $this->iBuiltinIcon[2][0]= 666 ;
$this->iBuiltinIcon[2][1]= $this->iBuiltinIcon[2][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'. 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'.
'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'. 'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'.
'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'. 'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'.
'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'. 'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'.
'7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'. '7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'.
'7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'. '7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'.
'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'. 'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'.
'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ; 'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// mail.png // mail.png
//========================================================== //==========================================================
$this->iBuiltinIcon[3][0]= 1122 ; $this->iBuiltinIcon[3][0]= 1122 ;
$this->iBuiltinIcon[3][1]= $this->iBuiltinIcon[3][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'. 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'.
'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'. 'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'.
'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'. 'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'.
'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'. 'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'.
'3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'. '3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'.
'7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'. '7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'.
'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'. 'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'.
'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'. 'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'.
'6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'. '6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'.
'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'. 'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'.
'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'. 'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'.
'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'. 'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'.
'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'. 'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'.
'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ; 'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// startconstrain.png // startconstrain.png
//========================================================== //==========================================================
$this->iBuiltinIcon[4][0]= 725 ; $this->iBuiltinIcon[4][0]= 725 ;
$this->iBuiltinIcon[4][1]= $this->iBuiltinIcon[4][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'. 'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'.
'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'. 'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'.
'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'. 'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'.
'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'. 'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'.
'5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'. '5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'.
'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'. 'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'.
'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'. 'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'.
'5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'. '5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'.
'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ; 'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// calc.png // calc.png
//========================================================== //==========================================================
$this->iBuiltinIcon[5][0]= 589 ; $this->iBuiltinIcon[5][0]= 589 ;
$this->iBuiltinIcon[5][1]= $this->iBuiltinIcon[5][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'.
'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'. 'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'.
'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'. 'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'.
'3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'. '3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'.
'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'. 'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'.
'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'. 'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'.
'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'. 'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'.
'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ; 'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// mag.png // mag.png
//========================================================== //==========================================================
$this->iBuiltinIcon[6][0]= 1415 ; $this->iBuiltinIcon[6][0]= 1415 ;
$this->iBuiltinIcon[6][1]= $this->iBuiltinIcon[6][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'. 'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'.
'0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'. '0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'.
'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'. 'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'.
'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'. 'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'.
'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'. 'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'.
'8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'. '8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'.
'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'. 'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'.
'/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'. '/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'.
'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'. 'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'.
'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'. 'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'.
'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'. 'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'.
'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'. 'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'.
'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'. 'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'.
'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'. 'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'.
'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'. 'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'.
'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'. 'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'.
'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'. 'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'.
'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ; 'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ;
   
//========================================================== //==========================================================
// lock.png // lock.png
//========================================================== //==========================================================
$this->iBuiltinIcon[7][0]= 963 ; $this->iBuiltinIcon[7][0]= 963 ;
$this->iBuiltinIcon[7][1]= $this->iBuiltinIcon[7][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'. 'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'.
'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'. 'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'.
'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'. 'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'.
'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'. 'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'.
'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'. 'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'.
'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'. 'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'.
'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'. 'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'.
'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'. 'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'.
'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'. 'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'.
'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'. 'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'.
'2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'. '2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'.
'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ; 'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// stop.png // stop.png
//========================================================== //==========================================================
$this->iBuiltinIcon[8][0]= 889 ; $this->iBuiltinIcon[8][0]= 889 ;
$this->iBuiltinIcon[8][1]= $this->iBuiltinIcon[8][1]=
'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'. 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'.
'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'. 'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'.
'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'. 'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'.
'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'. 'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'.
'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'. 'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'.
'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'. 'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'.
'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'. 'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'.
'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'. 'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'.
'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'. 'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'.
'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'. 'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'.
'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ; 'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// error.png // error.png
//========================================================== //==========================================================
$this->iBuiltinIcon[9][0]= 541 ; $this->iBuiltinIcon[9][0]= 541 ;
$this->iBuiltinIcon[9][1]= $this->iBuiltinIcon[9][1]=
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'. 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'.
'2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'. '2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'.
'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'. 'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'.
'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'. 'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'.
'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'. 'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'.
'iOsCHgAAAABJRU5ErkJggg==' ; 'iOsCHgAAAABJRU5ErkJggg==' ;
   
//========================================================== //==========================================================
// openfolder.png // openfolder.png
//========================================================== //==========================================================
$this->iBuiltinIcon[10][0]= 2040 ; $this->iBuiltinIcon[10][0]= 2040 ;
$this->iBuiltinIcon[10][1]= $this->iBuiltinIcon[10][1]=
'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'.
'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'. 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'.
'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'. 'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'.
'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'. 'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'.
'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'. 'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'.
'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'. 'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'.
'9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'. '9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'.
'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'. 'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'.
'4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'. '4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'.
'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'. 'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'.
'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'. 'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'.
'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'. 'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'.
'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'. 'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'.
'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'. 'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'.
'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'. 'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'.
'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'. 'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'.
'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'. 'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'.
'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'. 'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'.
'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'. 'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'.
'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'. 'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'.
'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'. 'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'.
'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'. 'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'.
'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'. 'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'.
'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'. 'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'.
'+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'. '+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'.
'4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'. '4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'.
'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'. 'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'.
'dBntAAAAAElFTkSuQmCC' ; 'dBntAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// folder.png // folder.png
//========================================================== //==========================================================
$this->iBuiltinIcon[11][0]= 1824 ; $this->iBuiltinIcon[11][0]= 1824 ;
$this->iBuiltinIcon[11][1]= $this->iBuiltinIcon[11][1]=
'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'. 'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'.
'6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'. '6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'.
'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'. 'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'.
'309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'. '309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'.
'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'. 'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'.
'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'. 'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'.
'3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'. '3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'.
'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'. 'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'.
'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'. 'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'.
'/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'. '/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'.
'4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'. '4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'.
'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'. 'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'.
'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'. 'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'.
'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'. 'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'.
'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'. 'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'.
'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'. 'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'.
'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'. 'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'.
'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'. 'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'.
'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'. 'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'.
'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'. 'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'.
'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'. 'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'.
'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'. 'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'.
'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'. 'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'.
'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ; 'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ;
   
//========================================================== //==========================================================
// file_important.png // file_important.png
//========================================================== //==========================================================
$this->iBuiltinIcon[12][0]= 1785 ; $this->iBuiltinIcon[12][0]= 1785 ;
$this->iBuiltinIcon[12][1]= $this->iBuiltinIcon[12][1]=
'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'. 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'.
'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'. 'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'.
'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'. 'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'.
'1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'. '1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'.
's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'. 's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'.
'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'. 'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'.
'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'. 'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'.
'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'. 'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'.
'73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'. '73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'.
'4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'. '4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'.
'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'. 'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'.
'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'. 'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'.
'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'. 'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'.
'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'. 'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'.
't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'. 't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'.
'9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'. '9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'.
'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'. 'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'.
'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'. 'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'.
'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'. 'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'.
'8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'. '8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'.
'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'. 'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'.
'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'. 'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'.
'7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ; '7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ;
   
$this->iLen = count($this->iBuiltinIcon); $this->iLen = count($this->iBuiltinIcon);
} }
} }
   
//=================================================== //===================================================
// Global cache for builtin images // Global cache for builtin images
//=================================================== //===================================================
$_gPredefIcons = new PredefIcons(); $_gPredefIcons = new PredefIcons();
   
//=================================================== //===================================================
// CLASS IconImage // CLASS IconImage
// Description: Holds properties for an icon image // Description: Holds properties for an icon image
//=================================================== //===================================================
class IconImage { class IconImage {
private $iGDImage=null; private $iGDImage=null;
private $iWidth,$iHeight; private $iWidth,$iHeight;
private $ixalign='left',$iyalign='center'; private $ixalign='left',$iyalign='center';
private $iScale=1.0; private $iScale=1.0;
   
function __construct($aIcon,$aScale=1) { function __construct($aIcon,$aScale=1) {
GLOBAL $_gPredefIcons ; GLOBAL $_gPredefIcons ;
if( is_string($aIcon) ) { if( is_string($aIcon) ) {
$this->iGDImage = Graph::LoadBkgImage('',$aIcon); $this->iGDImage = Graph::LoadBkgImage('',$aIcon);
} }
elseif( is_integer($aIcon) ) { elseif( is_integer($aIcon) ) {
// Builtin image // Builtin image
$this->iGDImage = $_gPredefIcons->GetImg($aIcon); $this->iGDImage = $_gPredefIcons->GetImg($aIcon);
} }
else { else {
JpGraphError::RaiseL(6011); JpGraphError::RaiseL(6011);
//('Argument to IconImage must be string or integer'); //('Argument to IconImage must be string or integer');
} }
$this->iScale = $aScale; $this->iScale = $aScale;
$this->iWidth = Image::GetWidth($this->iGDImage); $this->iWidth = Image::GetWidth($this->iGDImage);
$this->iHeight = Image::GetHeight($this->iGDImage); $this->iHeight = Image::GetHeight($this->iGDImage);
} }
   
function GetWidth() { function GetWidth() {
return round($this->iScale*$this->iWidth); return round($this->iScale*$this->iWidth);
} }
   
function GetHeight() { function GetHeight() {
return round($this->iScale*$this->iHeight); return round($this->iScale*$this->iHeight);
} }
   
function SetAlign($aX='left',$aY='center') { function SetAlign($aX='left',$aY='center') {
$this->ixalign = $aX; $this->ixalign = $aX;
$this->iyalign = $aY; $this->iyalign = $aY;
} }
   
function Stroke($aImg,$x,$y) { function Stroke($aImg,$x,$y) {
   
if( $this->ixalign == 'right' ) { if( $this->ixalign == 'right' ) {
$x -= $this->iWidth; $x -= $this->iWidth;
} }
elseif( $this->ixalign == 'center' ) { elseif( $this->ixalign == 'center' ) {
$x -= round($this->iWidth/2*$this->iScale); $x -= round($this->iWidth/2*$this->iScale);
} }
   
if( $this->iyalign == 'bottom' ) { if( $this->iyalign == 'bottom' ) {
$y -= $this->iHeight; $y -= $this->iHeight;
} }
elseif( $this->iyalign == 'center' ) { elseif( $this->iyalign == 'center' ) {
$y -= round($this->iHeight/2*$this->iScale); $y -= round($this->iHeight/2*$this->iScale);
} }
   
$aImg->Copy($this->iGDImage, $aImg->Copy($this->iGDImage,
$x,$y,0,0, $x,$y,0,0,
round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale), round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale),
$this->iWidth,$this->iHeight); $this->iWidth,$this->iHeight);
} }
} }
   
   
//=================================================== //===================================================
// CLASS TextProperty // CLASS TextProperty
// Description: Holds properties for a text // Description: Holds properties for a text
//=================================================== //===================================================
class TextProperty { class TextProperty {
public $iShow=true; public $iShow=true;
public $csimtarget='',$csimwintarget='',$csimalt=''; public $csimtarget='',$csimwintarget='',$csimalt='';
private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10; private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10;
private $iFontArray=array(); private $iFontArray=array();
private $iColor="black"; private $iColor="black";
private $iText=""; private $iText="";
private $iHAlign="left",$iVAlign="bottom"; private $iHAlign="left",$iVAlign="bottom";
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aTxt='') { function __construct($aTxt='') {
$this->iText = $aTxt; $this->iText = $aTxt;
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Set($aTxt) { function Set($aTxt) {
$this->iText = $aTxt; $this->iText = $aTxt;
} }
   
function SetCSIMTarget($aTarget,$aAltText='',$aWinTarget='') { function SetCSIMTarget($aTarget,$aAltText='',$aWinTarget='') {
if( is_string($aTarget) ) if( is_string($aTarget) )
$aTarget = array($aTarget); $aTarget = array($aTarget);
$this->csimtarget=$aTarget; $this->csimtarget=$aTarget;
   
if( is_string($aWinTarget) ) if( is_string($aWinTarget) )
$aWinTarget = array($aWinTarget); $aWinTarget = array($aWinTarget);
$this->csimwintarget=$aWinTarget; $this->csimwintarget=$aWinTarget;
   
if( is_string($aAltText) ) if( is_string($aAltText) )
$aAltText = array($aAltText); $aAltText = array($aAltText);
$this->csimalt=$aAltText; $this->csimalt=$aAltText;
   
} }
   
function SetCSIMAlt($aAltText) { function SetCSIMAlt($aAltText) {
if( is_string($aAltText) ) if( is_string($aAltText) )
$aAltText = array($aAltText); $aAltText = array($aAltText);
$this->csimalt=$aAltText; $this->csimalt=$aAltText;
} }
   
// Set text color // Set text color
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function HasTabs() { function HasTabs() {
if( is_string($this->iText) ) { if( is_string($this->iText) ) {
return substr_count($this->iText,"\t") > 0; return substr_count($this->iText,"\t") > 0;
} }
elseif( is_array($this->iText) ) { elseif( is_array($this->iText) ) {
return false; return false;
} }
} }
   
// Get number of tabs in string // Get number of tabs in string
function GetNbrTabs() { function GetNbrTabs() {
if( is_string($this->iText) ) { if( is_string($this->iText) ) {
return substr_count($this->iText,"\t") ; return substr_count($this->iText,"\t") ;
} }
else{ else{
return 0; return 0;
} }
} }
   
// Set alignment // Set alignment
function Align($aHAlign,$aVAlign="bottom") { function Align($aHAlign,$aVAlign="bottom") {
$this->iHAlign=$aHAlign; $this->iHAlign=$aHAlign;
$this->iVAlign=$aVAlign; $this->iVAlign=$aVAlign;
} }
   
// Synonym // Synonym
function SetAlign($aHAlign,$aVAlign="bottom") { function SetAlign($aHAlign,$aVAlign="bottom") {
$this->iHAlign=$aHAlign; $this->iHAlign=$aHAlign;
$this->iVAlign=$aVAlign; $this->iVAlign=$aVAlign;
} }
   
// Specify font // Specify font
function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
$this->iFFamily = $aFFamily; $this->iFFamily = $aFFamily;
$this->iFStyle = $aFStyle; $this->iFStyle = $aFStyle;
$this->iFSize = $aFSize; $this->iFSize = $aFSize;
} }
   
function SetColumnFonts($aFontArray) { function SetColumnFonts($aFontArray) {
if( !is_array($aFontArray) || count($aFontArray[0]) != 3 ) { if( !is_array($aFontArray) || count($aFontArray[0]) != 3 ) {
JpGraphError::RaiseL(6033); JpGraphError::RaiseL(6033);
// 'Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)' // 'Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)'
} }
$this->iFontArray = $aFontArray; $this->iFontArray = $aFontArray;
} }
   
   
function IsColumns() { function IsColumns() {
return is_array($this->iText) ; return is_array($this->iText) ;
} }
   
// Get width of text. If text contains several columns separated by // 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 // tabs then return both the total width as well as an array with a
// width for each column. // width for each column.
function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) { function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) {
$extra_margin=4; $extra_margin=4;
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
if( is_string($this->iText) ) { if( is_string($this->iText) ) {
if( strlen($this->iText) == 0 ) return 0; if( strlen($this->iText) == 0 ) return 0;
$tmp = preg_split('/\t/',$this->iText); $tmp = preg_split('/\t/',$this->iText);
if( count($tmp) <= 1 || !$aUseTabs ) { if( count($tmp) <= 1 || !$aUseTabs ) {
$w = $aImg->GetTextWidth($this->iText); $w = $aImg->GetTextWidth($this->iText);
return $w + 2*$extra_margin; return $w + 2*$extra_margin;
} }
else { else {
$tot=0; $tot=0;
$n = count($tmp); $n = count($tmp);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$res[$i] = $aImg->GetTextWidth($tmp[$i]); $res[$i] = $aImg->GetTextWidth($tmp[$i]);
$tot += $res[$i]*$aTabExtraMargin; $tot += $res[$i]*$aTabExtraMargin;
} }
return array(round($tot),$res); return array(round($tot),$res);
} }
} }
elseif( is_object($this->iText) ) { elseif( is_object($this->iText) ) {
// A single icon // A single icon
return $this->iText->GetWidth()+2*$extra_margin; return $this->iText->GetWidth()+2*$extra_margin;
} }
elseif( is_array($this->iText) ) { elseif( is_array($this->iText) ) {
// Must be an array of texts. In this case we return the sum of the // 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 // length + a fixed margin of 4 pixels on each text string
$n = count($this->iText); $n = count($this->iText);
$nf = count($this->iFontArray); $nf = count($this->iFontArray);
for( $i=0, $w=0; $i < $n; ++$i ) { for( $i=0, $w=0; $i < $n; ++$i ) {
if( $i < $nf ) { if( $i < $nf ) {
$aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]);
} }
else { else {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
} }
$tmp = $this->iText[$i]; $tmp = $this->iText[$i];
if( is_string($tmp) ) { if( is_string($tmp) ) {
$w += $aImg->GetTextWidth($tmp)+$extra_margin; $w += $aImg->GetTextWidth($tmp)+$extra_margin;
} }
else { else {
if( is_object($tmp) === false ) { if( is_object($tmp) === false ) {
JpGraphError::RaiseL(6012); JpGraphError::RaiseL(6012);
} }
$w += $tmp->GetWidth()+$extra_margin; $w += $tmp->GetWidth()+$extra_margin;
} }
} }
return $w; return $w;
} }
else { else {
JpGraphError::RaiseL(6012); JpGraphError::RaiseL(6012);
} }
} }
   
// for the case where we have multiple columns this function returns the width of each // 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 individually. If there is no columns just return the width of the single
// column as an array of one // column as an array of one
function GetColWidth($aImg,$aMargin=0) { function GetColWidth($aImg,$aMargin=0) {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
if( is_array($this->iText) ) { if( is_array($this->iText) ) {
$n = count($this->iText); $n = count($this->iText);
$nf = count($this->iFontArray); $nf = count($this->iFontArray);
for( $i=0, $w=array(); $i < $n; ++$i ) { for( $i=0, $w=array(); $i < $n; ++$i ) {
$tmp = $this->iText[$i]; $tmp = $this->iText[$i];
if( is_string($tmp) ) { if( is_string($tmp) ) {
if( $i < $nf ) { if( $i < $nf ) {
$aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]);
} }
else { else {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
} }
$w[$i] = $aImg->GetTextWidth($tmp)+$aMargin; $w[$i] = $aImg->GetTextWidth($tmp)+$aMargin;
} }
else { else {
if( is_object($tmp) === false ) { if( is_object($tmp) === false ) {
JpGraphError::RaiseL(6012); JpGraphError::RaiseL(6012);
} }
$w[$i] = $tmp->GetWidth()+$aMargin; $w[$i] = $tmp->GetWidth()+$aMargin;
} }
} }
return $w; return $w;
} }
else { else {
return array($this->GetWidth($aImg)); return array($this->GetWidth($aImg));
} }
} }
   
// Get total height of text // Get total height of text
function GetHeight($aImg) { function GetHeight($aImg) {
$nf = count($this->iFontArray); $nf = count($this->iFontArray);
$maxheight = -1; $maxheight = -1;
   
if( $nf > 0 ) { if( $nf > 0 ) {
// We have to find out the largest font and take that one as the // We have to find out the largest font and take that one as the
// height of the row // height of the row
for($i=0; $i < $nf; ++$i ) { for($i=0; $i < $nf; ++$i ) {
$aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]);
$height = $aImg->GetFontHeight(); $height = $aImg->GetFontHeight();
$maxheight = max($height,$maxheight); $maxheight = max($height,$maxheight);
} }
} }
   
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
$height = $aImg->GetFontHeight(); $height = $aImg->GetFontHeight();
$maxheight = max($height,$maxheight); $maxheight = max($height,$maxheight);
return $maxheight; return $maxheight;
} }
   
// Unhide/hide the text // Unhide/hide the text
function Show($aShow=true) { function Show($aShow=true) {
$this->iShow=$aShow; $this->iShow=$aShow;
} }
   
// Stroke text at (x,y) coordinates. If the text contains tabs then the // 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 // 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. // tab mark. If no array is supplied then the tabs will be ignored.
function Stroke($aImg,$aX,$aY) { function Stroke($aImg,$aX,$aY) {
if( $this->iShow ) { if( $this->iShow ) {
$aImg->SetColor($this->iColor); $aImg->SetColor($this->iColor);
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
$aImg->SetTextAlign($this->iHAlign,$this->iVAlign); $aImg->SetTextAlign($this->iHAlign,$this->iVAlign);
if( $this->GetNbrTabs() < 1 ) { if( $this->GetNbrTabs() < 1 ) {
if( is_string($this->iText) ) { if( is_string($this->iText) ) {
if( is_array($aX) ) $aX=$aX[0]; if( is_array($aX) ) $aX=$aX[0];
if( is_array($aY) ) $aY=$aY[0]; if( is_array($aY) ) $aY=$aY[0];
$aImg->StrokeText($aX,$aY,$this->iText); $aImg->StrokeText($aX,$aY,$this->iText);
} }
elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) { elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) {
$ax = is_array($aX) ; $ax = is_array($aX) ;
$ay = is_array($aY) ; $ay = is_array($aY) ;
if( $ax && $ay ) { if( $ax && $ay ) {
// Nothing; both are already arrays // Nothing; both are already arrays
} }
elseif( $ax ) { elseif( $ax ) {
$aY = array_fill(0,$n,$aY); $aY = array_fill(0,$n,$aY);
} }
elseif( $ay ) { elseif( $ay ) {
$aX = array_fill(0,$n,$aX); $aX = array_fill(0,$n,$aX);
} }
else { else {
$aX = array_fill(0,$n,$aX); $aX = array_fill(0,$n,$aX);
$aY = array_fill(0,$n,$aY); $aY = array_fill(0,$n,$aY);
} }
$n = min($n, count($aX) ) ; $n = min($n, count($aX) ) ;
$n = min($n, count($aY) ) ; $n = min($n, count($aY) ) ;
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$tmp = $this->iText[$i]; $tmp = $this->iText[$i];
if( is_object($tmp) ) { if( is_object($tmp) ) {
$tmp->Stroke($aImg,$aX[$i],$aY[$i]); $tmp->Stroke($aImg,$aX[$i],$aY[$i]);
} }
else { else {
if( $i < count($this->iFontArray) ) { if( $i < count($this->iFontArray) ) {
$font = $this->iFontArray[$i]; $font = $this->iFontArray[$i];
$aImg->SetFont($font[0],$font[1],$font[2]); $aImg->SetFont($font[0],$font[1],$font[2]);
} }
else { else {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
} }
$aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp)); $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp));
} }
} }
} }
} }
else { else {
$tmp = preg_split('/\t/',$this->iText); $tmp = preg_split('/\t/',$this->iText);
$n = min(count($tmp),count($aX)); $n = min(count($tmp),count($aX));
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $i < count($this->iFontArray) ) { if( $i < count($this->iFontArray) ) {
$font = $this->iFontArray[$i]; $font = $this->iFontArray[$i];
$aImg->SetFont($font[0],$font[1],$font[2]); $aImg->SetFont($font[0],$font[1],$font[2]);
} }
else { else {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
} }
$aImg->StrokeText($aX[$i],$aY,$tmp[$i]); $aImg->StrokeText($aX[$i],$aY,$tmp[$i]);
} }
} }
} }
} }
} }
   
//=================================================== //===================================================
// CLASS HeaderProperty // CLASS HeaderProperty
// Description: Data encapsulating class to hold property // Description: Data encapsulating class to hold property
// for each type of the scale headers // for each type of the scale headers
//=================================================== //===================================================
class HeaderProperty { class HeaderProperty {
public $grid; public $grid;
public $iShowLabels=true,$iShowGrid=true; public $iShowLabels=true,$iShowGrid=true;
public $iTitleVertMargin=3,$iFFamily=FF_FONT0,$iFStyle=FS_NORMAL,$iFSize=8; public $iTitleVertMargin=3,$iFFamily=FF_FONT0,$iFStyle=FS_NORMAL,$iFSize=8;
public $iStyle=0; public $iStyle=0;
public $iFrameColor="black",$iFrameWeight=1; public $iFrameColor="black",$iFrameWeight=1;
public $iBackgroundColor="white"; public $iBackgroundColor="white";
public $iWeekendBackgroundColor="lightgray",$iSundayTextColor="red"; // these are only used with day scale public $iWeekendBackgroundColor="lightgray",$iSundayTextColor="red"; // these are only used with day scale
public $iTextColor="black"; public $iTextColor="black";
public $iLabelFormStr="%d"; public $iLabelFormStr="%d";
public $iIntervall = 1; public $iIntervall = 1;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct() { function __construct() {
$this->grid = new LineProperty(); $this->grid = new LineProperty();
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Show($aShow=true) { function Show($aShow=true) {
$this->iShowLabels = $aShow; $this->iShowLabels = $aShow;
} }
   
function SetIntervall($aInt) { function SetIntervall($aInt) {
$this->iIntervall = $aInt; $this->iIntervall = $aInt;
} }
   
function SetInterval($aInt) { function SetInterval($aInt) {
$this->iIntervall = $aInt; $this->iIntervall = $aInt;
} }
   
function GetIntervall() { function GetIntervall() {
return $this->iIntervall ; return $this->iIntervall ;
} }
   
function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
$this->iFFamily = $aFFamily; $this->iFFamily = $aFFamily;
$this->iFStyle = $aFStyle; $this->iFStyle = $aFStyle;
$this->iFSize = $aFSize; $this->iFSize = $aFSize;
} }
   
function SetFontColor($aColor) { function SetFontColor($aColor) {
$this->iTextColor = $aColor; $this->iTextColor = $aColor;
} }
   
function GetFontHeight($aImg) { function GetFontHeight($aImg) {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
return $aImg->GetFontHeight(); return $aImg->GetFontHeight();
} }
   
function GetFontWidth($aImg) { function GetFontWidth($aImg) {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
return $aImg->GetFontWidth(); return $aImg->GetFontWidth();
} }
   
function GetStrWidth($aImg,$aStr) { function GetStrWidth($aImg,$aStr) {
$aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
return $aImg->GetTextWidth($aStr); return $aImg->GetTextWidth($aStr);
} }
   
function SetStyle($aStyle) { function SetStyle($aStyle) {
$this->iStyle = $aStyle; $this->iStyle = $aStyle;
} }
   
function SetBackgroundColor($aColor) { function SetBackgroundColor($aColor) {
$this->iBackgroundColor=$aColor; $this->iBackgroundColor=$aColor;
} }
   
function SetFrameWeight($aWeight) { function SetFrameWeight($aWeight) {
$this->iFrameWeight=$aWeight; $this->iFrameWeight=$aWeight;
} }
   
function SetFrameColor($aColor) { function SetFrameColor($aColor) {
$this->iFrameColor=$aColor; $this->iFrameColor=$aColor;
} }
   
// Only used by day scale // Only used by day scale
function SetWeekendColor($aColor) { function SetWeekendColor($aColor) {
$this->iWeekendBackgroundColor=$aColor; $this->iWeekendBackgroundColor=$aColor;
} }
   
// Only used by day scale // Only used by day scale
function SetSundayFontColor($aColor) { function SetSundayFontColor($aColor) {
$this->iSundayTextColor=$aColor; $this->iSundayTextColor=$aColor;
} }
   
function SetTitleVertMargin($aMargin) { function SetTitleVertMargin($aMargin) {
$this->iTitleVertMargin=$aMargin; $this->iTitleVertMargin=$aMargin;
} }
   
function SetLabelFormatString($aStr) { function SetLabelFormatString($aStr) {
$this->iLabelFormStr=$aStr; $this->iLabelFormStr=$aStr;
} }
   
function SetFormatString($aStr) { function SetFormatString($aStr) {
$this->SetLabelFormatString($aStr); $this->SetLabelFormatString($aStr);
} }
   
   
} }
   
//=================================================== //===================================================
// CLASS GanttScale // CLASS GanttScale
// Description: Responsible for calculating and showing // Description: Responsible for calculating and showing
// the scale in a gantt chart. This includes providing methods for // the scale in a gantt chart. This includes providing methods for
// converting dates to position in the chart as well as stroking the // converting dates to position in the chart as well as stroking the
// date headers (days, week, etc). // date headers (days, week, etc).
//=================================================== //===================================================
class GanttScale { class GanttScale {
public $minute,$hour,$day,$week,$month,$year; public $minute,$hour,$day,$week,$month,$year;
public $divider,$dividerh,$tableTitle; public $divider,$dividerh,$tableTitle;
public $iStartDate=-1,$iEndDate=-1; public $iStartDate=-1,$iEndDate=-1;
// Number of gantt bar position (n.b not necessariliy the same as the number of bars) // 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 // 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 // bars but the number of bar positions is 5
public $actinfo; public $actinfo;
public $iTopPlotMargin=10,$iBottomPlotMargin=15; public $iTopPlotMargin=10,$iBottomPlotMargin=15;
public $iVertLines=-1; public $iVertLines=-1;
public $iVertHeaderSize=-1; public $iVertHeaderSize=-1;
// The width of the labels (defaults to the widest of all labels) // The width of the labels (defaults to the widest of all labels)
private $iLabelWidth; private $iLabelWidth;
// Out image to stroke the scale to // Out image to stroke the scale to
private $iImg; private $iImg;
private $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black"; private $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black";
private $iTableHeaderFrameWeight=1; private $iTableHeaderFrameWeight=1;
private $iAvailableHeight=-1,$iVertSpacing=-1; private $iAvailableHeight=-1,$iVertSpacing=-1;
private $iDateLocale; private $iDateLocale;
private $iVertLayout=GANTT_EVEN; private $iVertLayout=GANTT_EVEN;
private $iUsePlotWeekendBackground=true; private $iUsePlotWeekendBackground=true;
private $iWeekStart = 1; // Default to have weekends start on Monday private $iWeekStart = 1; // Default to have weekends start on Monday
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aImg) { function __construct($aImg) {
$this->iImg = $aImg; $this->iImg = $aImg;
$this->iDateLocale = new DateLocale(); $this->iDateLocale = new DateLocale();
   
$this->minute = new HeaderProperty(); $this->minute = new HeaderProperty();
$this->minute->SetIntervall(15); $this->minute->SetIntervall(15);
$this->minute->SetLabelFormatString('i'); $this->minute->SetLabelFormatString('i');
$this->minute->SetFont(FF_FONT0); $this->minute->SetFont(FF_FONT0);
$this->minute->grid->SetColor("gray"); $this->minute->grid->SetColor("gray");
   
$this->hour = new HeaderProperty(); $this->hour = new HeaderProperty();
$this->hour->SetFont(FF_FONT0); $this->hour->SetFont(FF_FONT0);
$this->hour->SetIntervall(6); $this->hour->SetIntervall(6);
$this->hour->SetStyle(HOURSTYLE_HM24); $this->hour->SetStyle(HOURSTYLE_HM24);
$this->hour->SetLabelFormatString('H:i'); $this->hour->SetLabelFormatString('H:i');
$this->hour->grid->SetColor("gray"); $this->hour->grid->SetColor("gray");
   
$this->day = new HeaderProperty(); $this->day = new HeaderProperty();
$this->day->grid->SetColor("gray"); $this->day->grid->SetColor("gray");
$this->day->SetLabelFormatString('l'); $this->day->SetLabelFormatString('l');
   
$this->week = new HeaderProperty(); $this->week = new HeaderProperty();
$this->week->SetLabelFormatString("w%d"); $this->week->SetLabelFormatString("w%d");
$this->week->SetFont(FF_FONT1); $this->week->SetFont(FF_FONT1);
   
$this->month = new HeaderProperty(); $this->month = new HeaderProperty();
$this->month->SetFont(FF_FONT1,FS_BOLD); $this->month->SetFont(FF_FONT1,FS_BOLD);
   
$this->year = new HeaderProperty(); $this->year = new HeaderProperty();
$this->year->SetFont(FF_FONT1,FS_BOLD); $this->year->SetFont(FF_FONT1,FS_BOLD);
   
$this->divider=new LineProperty(); $this->divider=new LineProperty();
$this->dividerh=new LineProperty(); $this->dividerh=new LineProperty();
$this->dividerh->SetWeight(2); $this->dividerh->SetWeight(2);
$this->divider->SetWeight(6); $this->divider->SetWeight(6);
$this->divider->SetColor('gray'); $this->divider->SetColor('gray');
$this->divider->SetStyle('fancy'); $this->divider->SetStyle('fancy');
   
$this->tableTitle=new TextProperty(); $this->tableTitle=new TextProperty();
$this->tableTitle->Show(false); $this->tableTitle->Show(false);
$this->actinfo = new GanttActivityInfo(); $this->actinfo = new GanttActivityInfo();
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
// Specify what headers should be visible // Specify what headers should be visible
function ShowHeaders($aFlg) { function ShowHeaders($aFlg) {
$this->day->Show($aFlg & GANTT_HDAY); $this->day->Show($aFlg & GANTT_HDAY);
$this->week->Show($aFlg & GANTT_HWEEK); $this->week->Show($aFlg & GANTT_HWEEK);
$this->month->Show($aFlg & GANTT_HMONTH); $this->month->Show($aFlg & GANTT_HMONTH);
$this->year->Show($aFlg & GANTT_HYEAR); $this->year->Show($aFlg & GANTT_HYEAR);
$this->hour->Show($aFlg & GANTT_HHOUR); $this->hour->Show($aFlg & GANTT_HHOUR);
$this->minute->Show($aFlg & GANTT_HMIN); $this->minute->Show($aFlg & GANTT_HMIN);
   
// Make some default settings of gridlines whihc makes sense // Make some default settings of gridlines whihc makes sense
if( $aFlg & GANTT_HWEEK ) { if( $aFlg & GANTT_HWEEK ) {
$this->month->grid->Show(false); $this->month->grid->Show(false);
$this->year->grid->Show(false); $this->year->grid->Show(false);
} }
if( $aFlg & GANTT_HHOUR ) { if( $aFlg & GANTT_HHOUR ) {
$this->day->grid->SetColor("black"); $this->day->grid->SetColor("black");
} }
} }
   
// Should the weekend background stretch all the way down in the plotarea // Should the weekend background stretch all the way down in the plotarea
function UseWeekendBackground($aShow) { function UseWeekendBackground($aShow) {
$this->iUsePlotWeekendBackground = $aShow; $this->iUsePlotWeekendBackground = $aShow;
} }
   
// Have a range been specified? // Have a range been specified?
function IsRangeSet() { function IsRangeSet() {
return $this->iStartDate!=-1 && $this->iEndDate!=-1; return $this->iStartDate!=-1 && $this->iEndDate!=-1;
} }
   
// Should the layout be from top or even? // Should the layout be from top or even?
function SetVertLayout($aLayout) { function SetVertLayout($aLayout) {
$this->iVertLayout = $aLayout; $this->iVertLayout = $aLayout;
} }
   
// Which locale should be used? // Which locale should be used?
function SetDateLocale($aLocale) { function SetDateLocale($aLocale) {
$this->iDateLocale->Set($aLocale); $this->iDateLocale->Set($aLocale);
} }
   
// Number of days we are showing // Number of days we are showing
function GetNumberOfDays() { function GetNumberOfDays() {
return round(($this->iEndDate-$this->iStartDate)/SECPERDAY); return round(($this->iEndDate-$this->iStartDate)/SECPERDAY);
} }
   
// The width of the actual plot area // The width of the actual plot area
function GetPlotWidth() { function GetPlotWidth() {
$img=$this->iImg; $img=$this->iImg;
return $img->width - $img->left_margin - $img->right_margin; return $img->width - $img->left_margin - $img->right_margin;
} }
   
// Specify the width of the titles(labels) for the activities // Specify the width of the titles(labels) for the activities
// (This is by default set to the minimum width enought for the // (This is by default set to the minimum width enought for the
// widest title) // widest title)
function SetLabelWidth($aLabelWidth) { function SetLabelWidth($aLabelWidth) {
$this->iLabelWidth=$aLabelWidth; $this->iLabelWidth=$aLabelWidth;
} }
   
// Which day should the week start? // Which day should the week start?
// 0==Sun, 1==Monday, 2==Tuesday etc // 0==Sun, 1==Monday, 2==Tuesday etc
function SetWeekStart($aStartDay) { function SetWeekStart($aStartDay) {
$this->iWeekStart = $aStartDay % 7; $this->iWeekStart = $aStartDay % 7;
   
//Recalculate the startday since this will change the week start //Recalculate the startday since this will change the week start
$this->SetRange($this->iStartDate,$this->iEndDate); $this->SetRange($this->iStartDate,$this->iEndDate);
} }
   
// Do we show min scale? // Do we show min scale?
function IsDisplayMinute() { function IsDisplayMinute() {
return $this->minute->iShowLabels; return $this->minute->iShowLabels;
} }
   
// Do we show day scale? // Do we show day scale?
function IsDisplayHour() { function IsDisplayHour() {
return $this->hour->iShowLabels; return $this->hour->iShowLabels;
} }
   
   
// Do we show day scale? // Do we show day scale?
function IsDisplayDay() { function IsDisplayDay() {
return $this->day->iShowLabels; return $this->day->iShowLabels;
} }
   
// Do we show week scale? // Do we show week scale?
function IsDisplayWeek() { function IsDisplayWeek() {
return $this->week->iShowLabels; return $this->week->iShowLabels;
} }
   
// Do we show month scale? // Do we show month scale?
function IsDisplayMonth() { function IsDisplayMonth() {
return $this->month->iShowLabels; return $this->month->iShowLabels;
} }
   
// Do we show year scale? // Do we show year scale?
function IsDisplayYear() { function IsDisplayYear() {
return $this->year->iShowLabels; return $this->year->iShowLabels;
} }
   
// Specify spacing (in percent of bar height) between activity bars // Specify spacing (in percent of bar height) between activity bars
function SetVertSpacing($aSpacing) { function SetVertSpacing($aSpacing) {
$this->iVertSpacing = $aSpacing; $this->iVertSpacing = $aSpacing;
} }
   
// Specify scale min and max date either as timestamp or as date strings // Specify scale min and max date either as timestamp or as date strings
// Always round to the nearest week boundary // Always round to the nearest week boundary
function SetRange($aMin,$aMax) { function SetRange($aMin,$aMax) {
$this->iStartDate = $this->NormalizeDate($aMin); $this->iStartDate = $this->NormalizeDate($aMin);
$this->iEndDate = $this->NormalizeDate($aMax); $this->iEndDate = $this->NormalizeDate($aMax);
} }
   
   
// Adjust the start and end date so they fit to beginning/ending // Adjust the start and end date so they fit to beginning/ending
// of the week taking the specified week start day into account. // of the week taking the specified week start day into account.
function AdjustStartEndDay() { function AdjustStartEndDay() {
   
if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) { if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) {
// Don't adjust // Don't adjust
return; return;
} }
   
// Get day in week for start and ending date (Sun==0) // Get day in week for start and ending date (Sun==0)
$ds=strftime("%w",$this->iStartDate); $ds=strftime("%w",$this->iStartDate);
$de=strftime("%w",$this->iEndDate); $de=strftime("%w",$this->iEndDate);
   
// We want to start on iWeekStart day. But first we subtract a week // We want to start on iWeekStart day. But first we subtract a week
// if the startdate is "behind" the day the week start at. // if the startdate is "behind" the day the week start at.
// This way we ensure that the given start date is always included // 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 // 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. // to start at might be later than the start date.
if( $ds < $this->iWeekStart ) if( $ds < $this->iWeekStart )
$d = strtotime('-7 day',$this->iStartDate); $d = strtotime('-7 day',$this->iStartDate);
else else
$d = $this->iStartDate; $d = $this->iStartDate;
$adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ ); $adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ );
$this->iStartDate = $adjdate; $this->iStartDate = $adjdate;
   
// We want to end on the last day of the week // We want to end on the last day of the week
$preferredEndDay = ($this->iWeekStart+6)%7; $preferredEndDay = ($this->iWeekStart+6)%7;
if( $preferredEndDay != $de ) { if( $preferredEndDay != $de ) {
// Solve equivalence eq: $de + x ~ $preferredDay (mod 7) // Solve equivalence eq: $de + x ~ $preferredDay (mod 7)
$adj = (7+($preferredEndDay - $de)) % 7; $adj = (7+($preferredEndDay - $de)) % 7;
$adjdate = strtotime("+$adj day",$this->iEndDate); $adjdate = strtotime("+$adj day",$this->iEndDate);
$this->iEndDate = $adjdate; $this->iEndDate = $adjdate;
} }
} }
   
// Specify background for the table title area (upper left corner of the table) // Specify background for the table title area (upper left corner of the table)
function SetTableTitleBackground($aColor) { function SetTableTitleBackground($aColor) {
$this->iTableHeaderBackgroundColor = $aColor; $this->iTableHeaderBackgroundColor = $aColor;
} }
   
/////////////////////////////////////// ///////////////////////////////////////
// PRIVATE Methods // PRIVATE Methods
   
// Determine the height of all the scale headers combined // Determine the height of all the scale headers combined
function GetHeaderHeight() { function GetHeaderHeight() {
$img=$this->iImg; $img=$this->iImg;
$height=1; $height=1;
if( $this->minute->iShowLabels ) { if( $this->minute->iShowLabels ) {
$height += $this->minute->GetFontHeight($img); $height += $this->minute->GetFontHeight($img);
$height += $this->minute->iTitleVertMargin; $height += $this->minute->iTitleVertMargin;
} }
if( $this->hour->iShowLabels ) { if( $this->hour->iShowLabels ) {
$height += $this->hour->GetFontHeight($img); $height += $this->hour->GetFontHeight($img);
$height += $this->hour->iTitleVertMargin; $height += $this->hour->iTitleVertMargin;
} }
if( $this->day->iShowLabels ) { if( $this->day->iShowLabels ) {
$height += $this->day->GetFontHeight($img); $height += $this->day->GetFontHeight($img);
$height += $this->day->iTitleVertMargin; $height += $this->day->iTitleVertMargin;
} }
if( $this->week->iShowLabels ) { if( $this->week->iShowLabels ) {
$height += $this->week->GetFontHeight($img); $height += $this->week->GetFontHeight($img);
$height += $this->week->iTitleVertMargin; $height += $this->week->iTitleVertMargin;
} }
if( $this->month->iShowLabels ) { if( $this->month->iShowLabels ) {
$height += $this->month->GetFontHeight($img); $height += $this->month->GetFontHeight($img);
$height += $this->month->iTitleVertMargin; $height += $this->month->iTitleVertMargin;
} }
if( $this->year->iShowLabels ) { if( $this->year->iShowLabels ) {
$height += $this->year->GetFontHeight($img); $height += $this->year->GetFontHeight($img);
$height += $this->year->iTitleVertMargin; $height += $this->year->iTitleVertMargin;
} }
return $height; return $height;
} }
   
// Get width (in pixels) for a single day // Get width (in pixels) for a single day
function GetDayWidth() { function GetDayWidth() {
return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays(); return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays();
} }
   
// Get width (in pixels) for a single hour // Get width (in pixels) for a single hour
function GetHourWidth() { function GetHourWidth() {
return $this->GetDayWidth() / 24 ; return $this->GetDayWidth() / 24 ;
} }
   
function GetMinuteWidth() { function GetMinuteWidth() {
return $this->GetHourWidth() / 60 ; return $this->GetHourWidth() / 60 ;
} }
   
// Nuber of days in a year // Nuber of days in a year
function GetNumDaysInYear($aYear) { function GetNumDaysInYear($aYear) {
if( $this->IsLeap($aYear) ) if( $this->IsLeap($aYear) )
return 366; return 366;
else else
return 365; return 365;
} }
   
// Get week number // Get week number
function GetWeekNbr($aDate,$aSunStart=true) { function GetWeekNbr($aDate,$aSunStart=true) {
// We can't use the internal strftime() since it gets the weeknumber // 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 // wrong since it doesn't follow ISO on all systems since this is
// system linrary dependent. // system linrary dependent.
// Even worse is that this works differently if we are on a Windows // Even worse is that this works differently if we are on a Windows
// or UNIX box (it even differs between UNIX boxes how strftime() // or UNIX box (it even differs between UNIX boxes how strftime()
// is natively implemented) // is natively implemented)
// //
// Credit to Nicolas Hoizey <nhoizey@phpheaven.net> for this elegant // Credit to Nicolas Hoizey <nhoizey@phpheaven.net> for this elegant
// version of Week Nbr calculation. // version of Week Nbr calculation.
   
$day = $this->NormalizeDate($aDate); $day = $this->NormalizeDate($aDate);
if( $aSunStart ) if( $aSunStart )
$day += 60*60*24; $day += 60*60*24;
   
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
According to ISO-8601 : According to ISO-8601 :
"Week 01 of a year is per definition the first week that has the Thursday in this year, "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. 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 In other words, the first week of a new year is the week that has the majority of its
days in the new year." days in the new year."
   
Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!! Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!!
   
day of year = date("z", $day) + 1 day of year = date("z", $day) + 1
offset to thursday = 3 - (date("w", $day) + 6) % 7 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 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 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 $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; $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7;
   
return $week; return $week;
} }
   
// Is year a leap year? // Is year a leap year?
function IsLeap($aYear) { function IsLeap($aYear) {
// Is the year a leap year? // Is the year a leap year?
//$year = 0+date("Y",$aDate); //$year = 0+date("Y",$aDate);
if( $aYear % 4 == 0) if( $aYear % 4 == 0)
if( !($aYear % 100 == 0) || ($aYear % 400 == 0) ) if( !($aYear % 100 == 0) || ($aYear % 400 == 0) )
return true; return true;
return false; return false;
} }
   
// Get current year // Get current year
function GetYear($aDate) { function GetYear($aDate) {
return 0+Date("Y",$aDate); return 0+Date("Y",$aDate);
} }
   
// Return number of days in a year // Return number of days in a year
function GetNumDaysInMonth($aMonth,$aYear) { function GetNumDaysInMonth($aMonth,$aYear) {
$days=array(31,28,31,30,31,30,31,31,30,31,30,31); $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); $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31);
if( $this->IsLeap($aYear)) if( $this->IsLeap($aYear))
return $daysl[$aMonth]; return $daysl[$aMonth];
else else
return $days[$aMonth]; return $days[$aMonth];
} }
   
// Get day in month // Get day in month
function GetMonthDayNbr($aDate) { function GetMonthDayNbr($aDate) {
return 0+strftime("%d",$aDate); return 0+strftime("%d",$aDate);
} }
   
// Get day in year // Get day in year
function GetYearDayNbr($aDate) { function GetYearDayNbr($aDate) {
return 0+strftime("%j",$aDate); return 0+strftime("%j",$aDate);
} }
   
// Get month number // Get month number
function GetMonthNbr($aDate) { function GetMonthNbr($aDate) {
return 0+strftime("%m",$aDate); return 0+strftime("%m",$aDate);
} }
   
// Translate a date to screen coordinates (horizontal scale) // Translate a date to screen coordinates (horizontal scale)
function TranslateDate($aDate) { function TranslateDate($aDate) {
// //
// In order to handle the problem with Daylight savings time // In order to handle the problem with Daylight savings time
// the scale written with equal number of seconds per day beginning // the scale written with equal number of seconds per day beginning
// with the start date. This means that we "cement" the state of // 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 // 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 // switchover date (depends on the locale) we need to adjust back
// if the date we try to translate has a different DST status since // if the date we try to translate has a different DST status since
// we would otherwise be off by one hour. // we would otherwise be off by one hour.
$aDate = $this->NormalizeDate($aDate); $aDate = $this->NormalizeDate($aDate);
$tmp = localtime($aDate); $tmp = localtime($aDate);
$cloc = $tmp[8]; $cloc = $tmp[8];
$tmp = localtime($this->iStartDate); $tmp = localtime($this->iStartDate);
$sloc = $tmp[8]; $sloc = $tmp[8];
$offset = 0; $offset = 0;
if( $sloc != $cloc) { if( $sloc != $cloc) {
if( $sloc ) if( $sloc )
$offset = 3600; $offset = 3600;
else else
$offset = -3600; $offset = -3600;
} }
$img=$this->iImg; $img=$this->iImg;
return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;; return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;;
} }
   
// Get screen coordinatesz for the vertical position for a bar // Get screen coordinatesz for the vertical position for a bar
function TranslateVertPos($aPos,$atTop=false) { function TranslateVertPos($aPos,$atTop=false) {
$img=$this->iImg; $img=$this->iImg;
if( $aPos > $this->iVertLines ) if( $aPos > $this->iVertLines )
JpGraphError::RaiseL(6015,$aPos); JpGraphError::RaiseL(6015,$aPos);
// 'Illegal vertical position %d' // 'Illegal vertical position %d'
if( $this->iVertLayout == GANTT_EVEN ) { if( $this->iVertLayout == GANTT_EVEN ) {
// Position the top bar at 1 vert spacing from the scale // Position the top bar at 1 vert spacing from the scale
$pos = round($img->top_margin + $this->iVertHeaderSize + ($aPos+1)*$this->iVertSpacing); $pos = round($img->top_margin + $this->iVertHeaderSize + ($aPos+1)*$this->iVertSpacing);
} }
else { else {
// position the top bar at 1/2 a vert spacing from the scale // 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); $pos = round($img->top_margin + $this->iVertHeaderSize + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing);
} }
   
if( $atTop ) if( $atTop )
$pos -= $this->iVertSpacing; $pos -= $this->iVertSpacing;
   
return $pos; return $pos;
} }
   
// What is the vertical spacing? // What is the vertical spacing?
function GetVertSpacing() { function GetVertSpacing() {
return $this->iVertSpacing; return $this->iVertSpacing;
} }
   
// Convert a date to timestamp // Convert a date to timestamp
function NormalizeDate($aDate) { function NormalizeDate($aDate) {
if( $aDate === false ) return false; if( $aDate === false ) return false;
if( is_string($aDate) ) { if( is_string($aDate) ) {
$t = strtotime($aDate); $t = strtotime($aDate);
if( $t === FALSE || $t === -1 ) { if( $t === FALSE || $t === -1 ) {
JpGraphError::RaiseL(6016,$aDate); 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"); //("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; return $t;
} }
elseif( is_int($aDate) || is_float($aDate) ) elseif( is_int($aDate) || is_float($aDate) )
return $aDate; return $aDate;
else else
JpGraphError::RaiseL(6017,$aDate); JpGraphError::RaiseL(6017,$aDate);
//Unknown date format in GanttScale ($aDate)."); //Unknown date format in GanttScale ($aDate).");
} }
   
   
// Convert a time string to minutes // Convert a time string to minutes
   
function TimeToMinutes($aTimeString) { function TimeToMinutes($aTimeString) {
// Split in hours and minutes // Split in hours and minutes
$pos=strpos($aTimeString,':'); $pos=strpos($aTimeString,':');
$minint=60; $minint=60;
if( $pos === false ) { if( $pos === false ) {
$hourint = $aTimeString; $hourint = $aTimeString;
$minint = 0; $minint = 0;
} }
else { else {
$hourint = floor(substr($aTimeString,0,$pos)); $hourint = floor(substr($aTimeString,0,$pos));
$minint = floor(substr($aTimeString,$pos+1)); $minint = floor(substr($aTimeString,$pos+1));
} }
$minint += 60 * $hourint; $minint += 60 * $hourint;
return $minint; return $minint;
} }
   
// Stroke the day scale (including gridlines) // Stroke the day scale (including gridlines)
function StrokeMinutes($aYCoord,$getHeight=false) { function StrokeMinutes($aYCoord,$getHeight=false) {
$img=$this->iImg; $img=$this->iImg;
$xt=$img->left_margin+$this->iLabelWidth; $xt=$img->left_margin+$this->iLabelWidth;
$yt=$aYCoord+$img->top_margin; $yt=$aYCoord+$img->top_margin;
if( $this->minute->iShowLabels ) { if( $this->minute->iShowLabels ) {
$img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize); $img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize);
$yb = $yt + $img->GetFontHeight() + $yb = $yt + $img->GetFontHeight() +
$this->minute->iTitleVertMargin + $this->minute->iFrameWeight; $this->minute->iTitleVertMargin + $this->minute->iFrameWeight;
if( $getHeight ) { if( $getHeight ) {
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
$xb = $img->width-$img->right_margin+1; $xb = $img->width-$img->right_margin+1;
$img->SetColor($this->minute->iBackgroundColor); $img->SetColor($this->minute->iBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
   
$x = $xt; $x = $xt;
$img->SetTextAlign("center"); $img->SetTextAlign("center");
$day = date('w',$this->iStartDate); $day = date('w',$this->iStartDate);
$minint = $this->minute->GetIntervall() ; $minint = $this->minute->GetIntervall() ;
   
if( 60 % $minint !== 0 ) { if( 60 % $minint !== 0 ) {
JpGraphError::RaiseL(6018,$minint); 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.'); //'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; $n = 60 / $minint;
$datestamp = $this->iStartDate; $datestamp = $this->iStartDate;
$width = $this->GetHourWidth() / $n ; $width = $this->GetHourWidth() / $n ;
if( $width < 8 ) { if( $width < 8 ) {
// TO small width to draw minute scale // TO small width to draw minute scale
JpGraphError::RaiseL(6019,$width); 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.'); //('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()) ); $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) );
$nd = $this->GetNumberOfDays(); $nd = $this->GetNumberOfDays();
// Convert to intervall to seconds // Convert to intervall to seconds
$minint *= 60; $minint *= 60;
for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) { for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) {
for( $k=0; $k < $nh; ++$k ) { for( $k=0; $k < $nh; ++$k ) {
for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) { for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) {
if( $day==6 || $day==0 ) { if( $day==6 || $day==0 ) {
   
$img->PushColor($this->day->iWeekendBackgroundColor); $img->PushColor($this->day->iWeekendBackgroundColor);
if( $this->iUsePlotWeekendBackground ) if( $this->iUsePlotWeekendBackground )
$img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin);
else else
$img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight);
$img->PopColor(); $img->PopColor();
   
} }
   
if( $day==0 ) if( $day==0 )
$img->SetColor($this->day->iSundayTextColor); $img->SetColor($this->day->iSundayTextColor);
else else
$img->SetColor($this->day->iTextColor); $img->SetColor($this->day->iTextColor);
   
switch( $this->minute->iStyle ) { switch( $this->minute->iStyle ) {
case MINUTESTYLE_CUSTOM: case MINUTESTYLE_CUSTOM:
$txt = date($this->minute->iLabelFormStr,$datestamp); $txt = date($this->minute->iLabelFormStr,$datestamp);
break; break;
case MINUTESTYLE_MM: case MINUTESTYLE_MM:
default: default:
// 15 // 15
$txt = date('i',$datestamp); $txt = date('i',$datestamp);
break; break;
} }
$img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt); $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt);
   
// Fix a rounding problem the wrong way .. // Fix a rounding problem the wrong way ..
// If we also have hour scale then don't draw the firsta or last // 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. // 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 // 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. // 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 // The proper way to fix it would be to re-calculate the scale for each step and
// not using the additive term. // not using the additive term.
if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) { if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) {
$img->SetColor($this->minute->grid->iColor); $img->SetColor($this->minute->grid->iColor);
$img->SetLineWeight($this->minute->grid->iWeight); $img->SetLineWeight($this->minute->grid->iWeight);
$img->Line($x,$yt,$x,$yb); $img->Line($x,$yt,$x,$yb);
$this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
} }
} }
} }
} }
$img->SetColor($this->minute->iFrameColor); $img->SetColor($this->minute->iFrameColor);
$img->SetLineWeight($this->minute->iFrameWeight); $img->SetLineWeight($this->minute->iFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
return $aYCoord; return $aYCoord;
} }
   
// Stroke the day scale (including gridlines) // Stroke the day scale (including gridlines)
function StrokeHours($aYCoord,$getHeight=false) { function StrokeHours($aYCoord,$getHeight=false) {
$img=$this->iImg; $img=$this->iImg;
$xt=$img->left_margin+$this->iLabelWidth; $xt=$img->left_margin+$this->iLabelWidth;
$yt=$aYCoord+$img->top_margin; $yt=$aYCoord+$img->top_margin;
if( $this->hour->iShowLabels ) { if( $this->hour->iShowLabels ) {
$img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize); $img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize);
$yb = $yt + $img->GetFontHeight() + $yb = $yt + $img->GetFontHeight() +
$this->hour->iTitleVertMargin + $this->hour->iFrameWeight; $this->hour->iTitleVertMargin + $this->hour->iFrameWeight;
if( $getHeight ) { if( $getHeight ) {
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
$xb = $img->width-$img->right_margin+1; $xb = $img->width-$img->right_margin+1;
$img->SetColor($this->hour->iBackgroundColor); $img->SetColor($this->hour->iBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
   
$x = $xt; $x = $xt;
$img->SetTextAlign("center"); $img->SetTextAlign("center");
$tmp = $this->hour->GetIntervall() ; $tmp = $this->hour->GetIntervall() ;
$minint = $this->TimeToMinutes($tmp); $minint = $this->TimeToMinutes($tmp);
if( 1440 % $minint !== 0 ) { if( 1440 % $minint !== 0 ) {
JpGraphError::RaiseL(6020,$tmp); 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); //('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 ); $n = ceil(24*60 / $minint );
$datestamp = $this->iStartDate; $datestamp = $this->iStartDate;
$day = date('w',$this->iStartDate); $day = date('w',$this->iStartDate);
$doback = !$this->minute->iShowLabels; $doback = !$this->minute->iShowLabels;
$width = $this->GetDayWidth() / $n ; $width = $this->GetDayWidth() / $n ;
for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) { for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) {
for($i=0; $i < $n ;++$i, $x+=$width) { for($i=0; $i < $n ;++$i, $x+=$width) {
if( $day==6 || $day==0 ) { if( $day==6 || $day==0 ) {
   
$img->PushColor($this->day->iWeekendBackgroundColor); $img->PushColor($this->day->iWeekendBackgroundColor);
if( $this->iUsePlotWeekendBackground && $doback ) if( $this->iUsePlotWeekendBackground && $doback )
$img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin);
else else
$img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight);
$img->PopColor(); $img->PopColor();
   
} }
   
if( $day==0 ) if( $day==0 )
$img->SetColor($this->day->iSundayTextColor); $img->SetColor($this->day->iSundayTextColor);
else else
$img->SetColor($this->day->iTextColor); $img->SetColor($this->day->iTextColor);
   
switch( $this->hour->iStyle ) { switch( $this->hour->iStyle ) {
case HOURSTYLE_HMAMPM: case HOURSTYLE_HMAMPM:
// 1:35pm // 1:35pm
$txt = date('g:ia',$datestamp); $txt = date('g:ia',$datestamp);
break; break;
case HOURSTYLE_H24: case HOURSTYLE_H24:
// 13 // 13
$txt = date('H',$datestamp); $txt = date('H',$datestamp);
break; break;
case HOURSTYLE_HAMPM: case HOURSTYLE_HAMPM:
$txt = date('ga',$datestamp); $txt = date('ga',$datestamp);
break; break;
case HOURSTYLE_CUSTOM: case HOURSTYLE_CUSTOM:
$txt = date($this->hour->iLabelFormStr,$datestamp); $txt = date($this->hour->iLabelFormStr,$datestamp);
break; break;
case HOURSTYLE_HM24: case HOURSTYLE_HM24:
default: default:
$txt = date('H:i',$datestamp); $txt = date('H:i',$datestamp);
break; break;
} }
$img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt); $img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt);
$img->SetColor($this->hour->grid->iColor); $img->SetColor($this->hour->grid->iColor);
$img->SetLineWeight($this->hour->grid->iWeight); $img->SetLineWeight($this->hour->grid->iWeight);
$img->Line($x,$yt,$x,$yb); $img->Line($x,$yt,$x,$yb);
$this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); $this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
//$datestamp += $minint*60 //$datestamp += $minint*60
$datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0, $datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0,
date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp));
   
} }
} }
$img->SetColor($this->hour->iFrameColor); $img->SetColor($this->hour->iFrameColor);
$img->SetLineWeight($this->hour->iFrameWeight); $img->SetLineWeight($this->hour->iFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
return $aYCoord; return $aYCoord;
} }
   
   
// Stroke the day scale (including gridlines) // Stroke the day scale (including gridlines)
function StrokeDays($aYCoord,$getHeight=false) { function StrokeDays($aYCoord,$getHeight=false) {
$img=$this->iImg; $img=$this->iImg;
$daywidth=$this->GetDayWidth(); $daywidth=$this->GetDayWidth();
$xt=$img->left_margin+$this->iLabelWidth; $xt=$img->left_margin+$this->iLabelWidth;
$yt=$aYCoord+$img->top_margin; $yt=$aYCoord+$img->top_margin;
if( $this->day->iShowLabels ) { if( $this->day->iShowLabels ) {
$img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize); $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize);
$yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight; $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight;
if( $getHeight ) { if( $getHeight ) {
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
$xb=$img->width-$img->right_margin+1; $xb=$img->width-$img->right_margin+1;
$img->SetColor($this->day->iBackgroundColor); $img->SetColor($this->day->iBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
   
$x = $xt; $x = $xt;
$img->SetTextAlign("center"); $img->SetTextAlign("center");
$day = date('w',$this->iStartDate); $day = date('w',$this->iStartDate);
$datestamp = $this->iStartDate; $datestamp = $this->iStartDate;
   
$doback = !($this->hour->iShowLabels || $this->minute->iShowLabels); $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels);
   
setlocale(LC_TIME,$this->iDateLocale->iLocale); setlocale(LC_TIME,$this->iDateLocale->iLocale);
   
for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) { for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) {
if( $day==6 || $day==0 ) { if( $day==6 || $day==0 ) {
$img->SetColor($this->day->iWeekendBackgroundColor); $img->SetColor($this->day->iWeekendBackgroundColor);
if( $this->iUsePlotWeekendBackground && $doback) if( $this->iUsePlotWeekendBackground && $doback)
$img->FilledRectangle($x,$yt+$this->day->iFrameWeight, $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,
$x+$daywidth,$img->height-$img->bottom_margin); $x+$daywidth,$img->height-$img->bottom_margin);
else else
$img->FilledRectangle($x,$yt+$this->day->iFrameWeight, $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,
$x+$daywidth,$yb-$this->day->iFrameWeight); $x+$daywidth,$yb-$this->day->iFrameWeight);
} }
   
$mn = strftime('%m',$datestamp); $mn = strftime('%m',$datestamp);
if( $mn[0]=='0' ) if( $mn[0]=='0' )
$mn = $mn[1]; $mn = $mn[1];
   
switch( $this->day->iStyle ) { switch( $this->day->iStyle ) {
case DAYSTYLE_LONG: case DAYSTYLE_LONG:
// "Monday" // "Monday"
$txt = strftime('%A',$datestamp); $txt = strftime('%A',$datestamp);
break; break;
case DAYSTYLE_SHORT: case DAYSTYLE_SHORT:
// "Mon" // "Mon"
$txt = strftime('%a',$datestamp); $txt = strftime('%a',$datestamp);
break; break;
case DAYSTYLE_SHORTDAYDATE1: case DAYSTYLE_SHORTDAYDATE1:
// "Mon 23/6" // "Mon 23/6"
$txt = strftime('%a %d/'.$mn,$datestamp); $txt = strftime('%a %d/'.$mn,$datestamp);
break; break;
case DAYSTYLE_SHORTDAYDATE2: case DAYSTYLE_SHORTDAYDATE2:
// "Mon 23 Jun" // "Mon 23 Jun"
$txt = strftime('%a %d %b',$datestamp); $txt = strftime('%a %d %b',$datestamp);
break; break;
case DAYSTYLE_SHORTDAYDATE3: case DAYSTYLE_SHORTDAYDATE3:
// "Mon 23 Jun 2003" // "Mon 23 Jun 2003"
$txt = strftime('%a %d %b %Y',$datestamp); $txt = strftime('%a %d %b %Y',$datestamp);
break; break;
case DAYSTYLE_LONGDAYDATE1: case DAYSTYLE_LONGDAYDATE1:
// "Monday 23 Jun" // "Monday 23 Jun"
$txt = strftime('%A %d %b',$datestamp); $txt = strftime('%A %d %b',$datestamp);
break; break;
case DAYSTYLE_LONGDAYDATE2: case DAYSTYLE_LONGDAYDATE2:
// "Monday 23 Jun 2003" // "Monday 23 Jun 2003"
$txt = strftime('%A %d %b %Y',$datestamp); $txt = strftime('%A %d %b %Y',$datestamp);
break; break;
case DAYSTYLE_SHORTDATE1: case DAYSTYLE_SHORTDATE1:
// "23/6" // "23/6"
$txt = strftime('%d/'.$mn,$datestamp); $txt = strftime('%d/'.$mn,$datestamp);
break; break;
case DAYSTYLE_SHORTDATE2: case DAYSTYLE_SHORTDATE2:
// "23 Jun" // "23 Jun"
$txt = strftime('%d %b',$datestamp); $txt = strftime('%d %b',$datestamp);
break; break;
case DAYSTYLE_SHORTDATE3: case DAYSTYLE_SHORTDATE3:
// "Mon 23" // "Mon 23"
$txt = strftime('%a %d',$datestamp); $txt = strftime('%a %d',$datestamp);
break; break;
case DAYSTYLE_SHORTDATE4: case DAYSTYLE_SHORTDATE4:
// "23" // "23"
$txt = strftime('%d',$datestamp); $txt = strftime('%d',$datestamp);
break; break;
case DAYSTYLE_CUSTOM: case DAYSTYLE_CUSTOM:
// Custom format // Custom format
$txt = strftime($this->day->iLabelFormStr,$datestamp); $txt = strftime($this->day->iLabelFormStr,$datestamp);
break; break;
case DAYSTYLE_ONELETTER: case DAYSTYLE_ONELETTER:
default: default:
// "M" // "M"
$txt = strftime('%A',$datestamp); $txt = strftime('%A',$datestamp);
$txt = strtoupper($txt[0]); $txt = strtoupper($txt[0]);
break; break;
} }
   
if( $day==0 ) if( $day==0 )
$img->SetColor($this->day->iSundayTextColor); $img->SetColor($this->day->iSundayTextColor);
else else
$img->SetColor($this->day->iTextColor); $img->SetColor($this->day->iTextColor);
$img->StrokeText(round($x+$daywidth/2+1), $img->StrokeText(round($x+$daywidth/2+1),
round($yb-$this->day->iTitleVertMargin),$txt); round($yb-$this->day->iTitleVertMargin),$txt);
$img->SetColor($this->day->grid->iColor); $img->SetColor($this->day->grid->iColor);
$img->SetLineWeight($this->day->grid->iWeight); $img->SetLineWeight($this->day->grid->iWeight);
$img->Line($x,$yt,$x,$yb); $img->Line($x,$yt,$x,$yb);
$this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); $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 = mktime(0,0,0,date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp));
//$datestamp += SECPERDAY; //$datestamp += SECPERDAY;
   
} }
$img->SetColor($this->day->iFrameColor); $img->SetColor($this->day->iFrameColor);
$img->SetLineWeight($this->day->iFrameWeight); $img->SetLineWeight($this->day->iFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
return $aYCoord; return $aYCoord;
} }
   
// Stroke week header and grid // Stroke week header and grid
function StrokeWeeks($aYCoord,$getHeight=false) { function StrokeWeeks($aYCoord,$getHeight=false) {
if( $this->week->iShowLabels ) { if( $this->week->iShowLabels ) {
$img=$this->iImg; $img=$this->iImg;
$yt=$aYCoord+$img->top_margin; $yt=$aYCoord+$img->top_margin;
$img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize); $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize);
$yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight; $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight;
   
if( $getHeight ) { if( $getHeight ) {
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
   
$xt=$img->left_margin+$this->iLabelWidth; $xt=$img->left_margin+$this->iLabelWidth;
$weekwidth=$this->GetDayWidth()*7; $weekwidth=$this->GetDayWidth()*7;
$wdays=$this->iDateLocale->GetDayAbb(); $wdays=$this->iDateLocale->GetDayAbb();
$xb=$img->width-$img->right_margin+1; $xb=$img->width-$img->right_margin+1;
$week = $this->iStartDate; $week = $this->iStartDate;
$weeknbr=$this->GetWeekNbr($week); $weeknbr=$this->GetWeekNbr($week);
$img->SetColor($this->week->iBackgroundColor); $img->SetColor($this->week->iBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
$img->SetColor($this->week->grid->iColor); $img->SetColor($this->week->grid->iColor);
$x = $xt; $x = $xt;
if( $this->week->iStyle==WEEKSTYLE_WNBR ) { if( $this->week->iStyle==WEEKSTYLE_WNBR ) {
$img->SetTextAlign("center"); $img->SetTextAlign("center");
$txtOffset = $weekwidth/2+1; $txtOffset = $weekwidth/2+1;
} }
elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY ||
$this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ||
$this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
$this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
$img->SetTextAlign("left"); $img->SetTextAlign("left");
$txtOffset = 3; $txtOffset = 3;
} }
else { else {
JpGraphError::RaiseL(6021); JpGraphError::RaiseL(6021);
//("Unknown formatting style for week."); //("Unknown formatting style for week.");
} }
   
for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) { for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) {
$img->PushColor($this->week->iTextColor); $img->PushColor($this->week->iTextColor);
   
if( $this->week->iStyle==WEEKSTYLE_WNBR ) if( $this->week->iStyle==WEEKSTYLE_WNBR )
$txt = sprintf($this->week->iLabelFormStr,$weeknbr); $txt = sprintf($this->week->iLabelFormStr,$weeknbr);
elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY ||
$this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR )
$txt = date("j/n",$week); $txt = date("j/n",$week);
elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ||
$this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
$monthnbr = date("n",$week)-1; $monthnbr = date("n",$week)-1;
$shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr); $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr);
$txt = Date("j",$week)." ".$shortmonth; $txt = Date("j",$week)." ".$shortmonth;
} }
   
if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
$this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
$w = sprintf($this->week->iLabelFormStr,$weeknbr); $w = sprintf($this->week->iLabelFormStr,$weeknbr);
$txt .= ' '.$w; $txt .= ' '.$w;
} }
   
$img->StrokeText(round($x+$txtOffset), $img->StrokeText(round($x+$txtOffset),
round($yb-$this->week->iTitleVertMargin),$txt); round($yb-$this->week->iTitleVertMargin),$txt);
   
$week = strtotime('+7 day',$week); $week = strtotime('+7 day',$week);
$weeknbr = $this->GetWeekNbr($week); $weeknbr = $this->GetWeekNbr($week);
$img->PopColor(); $img->PopColor();
$img->SetLineWeight($this->week->grid->iWeight); $img->SetLineWeight($this->week->grid->iWeight);
$img->Line($x,$yt,$x,$yb); $img->Line($x,$yt,$x,$yb);
$this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
} }
$img->SetColor($this->week->iFrameColor); $img->SetColor($this->week->iFrameColor);
$img->SetLineWeight($this->week->iFrameWeight); $img->SetLineWeight($this->week->iFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
return $yb-$img->top_margin; return $yb-$img->top_margin;
} }
return $aYCoord; return $aYCoord;
} }
   
// Format the mont scale header string // Format the mont scale header string
function GetMonthLabel($aMonthNbr,$year) { function GetMonthLabel($aMonthNbr,$year) {
$sn = $this->iDateLocale->GetShortMonthName($aMonthNbr); $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr);
$ln = $this->iDateLocale->GetLongMonthName($aMonthNbr); $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr);
switch($this->month->iStyle) { switch($this->month->iStyle) {
case MONTHSTYLE_SHORTNAME: case MONTHSTYLE_SHORTNAME:
$m=$sn; $m=$sn;
break; break;
case MONTHSTYLE_LONGNAME: case MONTHSTYLE_LONGNAME:
$m=$ln; $m=$ln;
break; break;
case MONTHSTYLE_SHORTNAMEYEAR2: case MONTHSTYLE_SHORTNAMEYEAR2:
$m=$sn." '".substr("".$year,2); $m=$sn." '".substr("".$year,2);
break; break;
case MONTHSTYLE_SHORTNAMEYEAR4: case MONTHSTYLE_SHORTNAMEYEAR4:
$m=$sn." ".$year; $m=$sn." ".$year;
break; break;
case MONTHSTYLE_LONGNAMEYEAR2: case MONTHSTYLE_LONGNAMEYEAR2:
$m=$ln." '".substr("".$year,2); $m=$ln." '".substr("".$year,2);
break; break;
case MONTHSTYLE_LONGNAMEYEAR4: case MONTHSTYLE_LONGNAMEYEAR4:
$m=$ln." ".$year; $m=$ln." ".$year;
break; break;
case MONTHSTYLE_FIRSTLETTER: case MONTHSTYLE_FIRSTLETTER:
$m=$sn[0]; $m=$sn[0];
break; break;
} }
return $m; return $m;
} }
   
// Stroke month scale and gridlines // Stroke month scale and gridlines
function StrokeMonths($aYCoord,$getHeight=false) { function StrokeMonths($aYCoord,$getHeight=false) {
if( $this->month->iShowLabels ) { if( $this->month->iShowLabels ) {
$img=$this->iImg; $img=$this->iImg;
$img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize); $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize);
$yt=$aYCoord+$img->top_margin; $yt=$aYCoord+$img->top_margin;
$yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight; $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight;
if( $getHeight ) { if( $getHeight ) {
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
$monthnbr = $this->GetMonthNbr($this->iStartDate)-1; $monthnbr = $this->GetMonthNbr($this->iStartDate)-1;
$xt=$img->left_margin+$this->iLabelWidth; $xt=$img->left_margin+$this->iLabelWidth;
$xb=$img->width-$img->right_margin+1; $xb=$img->width-$img->right_margin+1;
   
$img->SetColor($this->month->iBackgroundColor); $img->SetColor($this->month->iBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
   
$img->SetLineWeight($this->month->grid->iWeight); $img->SetLineWeight($this->month->grid->iWeight);
$img->SetColor($this->month->iTextColor); $img->SetColor($this->month->iTextColor);
$year = 0+strftime("%Y",$this->iStartDate); $year = 0+strftime("%Y",$this->iStartDate);
$img->SetTextAlign("center"); $img->SetTextAlign("center");
if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate)
&& $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) { && $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) {
$monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1); $monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1);
} }
else { else {
$monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1); $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1);
} }
// Is it enough space to stroke the first month? // Is it enough space to stroke the first month?
$monthName = $this->GetMonthLabel($monthnbr,$year); $monthName = $this->GetMonthLabel($monthnbr,$year);
if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) { if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) {
$img->SetColor($this->month->iTextColor); $img->SetColor($this->month->iTextColor);
$img->StrokeText(round($xt+$monthwidth/2+1), $img->StrokeText(round($xt+$monthwidth/2+1),
round($yb-$this->month->iTitleVertMargin), round($yb-$this->month->iTitleVertMargin),
$monthName); $monthName);
} }
$x = $xt + $monthwidth; $x = $xt + $monthwidth;
while( $x < $xb ) { while( $x < $xb ) {
$img->SetColor($this->month->grid->iColor); $img->SetColor($this->month->grid->iColor);
$img->Line($x,$yt,$x,$yb); $img->Line($x,$yt,$x,$yb);
$this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
$monthnbr++; $monthnbr++;
if( $monthnbr==12 ) { if( $monthnbr==12 ) {
$monthnbr=0; $monthnbr=0;
$year++; $year++;
} }
$monthName = $this->GetMonthLabel($monthnbr,$year); $monthName = $this->GetMonthLabel($monthnbr,$year);
$monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year); $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year);
if( $x + $monthwidth < $xb ) if( $x + $monthwidth < $xb )
$w = $monthwidth; $w = $monthwidth;
else else
$w = $xb-$x; $w = $xb-$x;
if( $w >= 1.2*$img->GetTextWidth($monthName) ) { if( $w >= 1.2*$img->GetTextWidth($monthName) ) {
$img->SetColor($this->month->iTextColor); $img->SetColor($this->month->iTextColor);
$img->StrokeText(round($x+$w/2+1), $img->StrokeText(round($x+$w/2+1),
round($yb-$this->month->iTitleVertMargin),$monthName); round($yb-$this->month->iTitleVertMargin),$monthName);
} }
$x += $monthwidth; $x += $monthwidth;
} }
$img->SetColor($this->month->iFrameColor); $img->SetColor($this->month->iFrameColor);
$img->SetLineWeight($this->month->iFrameWeight); $img->SetLineWeight($this->month->iFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
return $yb-$img->top_margin; return $yb-$img->top_margin;
} }
return $aYCoord; return $aYCoord;
} }
   
// Stroke year scale and gridlines // Stroke year scale and gridlines
function StrokeYears($aYCoord,$getHeight=false) { function StrokeYears($aYCoord,$getHeight=false) {
if( $this->year->iShowLabels ) { if( $this->year->iShowLabels ) {
$img=$this->iImg; $img=$this->iImg;
$yt=$aYCoord+$img->top_margin; $yt=$aYCoord+$img->top_margin;
$img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize); $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize);
$yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight; $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight;
   
if( $getHeight ) { if( $getHeight ) {
return $yb - $img->top_margin; return $yb - $img->top_margin;
} }
   
$xb=$img->width-$img->right_margin+1; $xb=$img->width-$img->right_margin+1;
$xt=$img->left_margin+$this->iLabelWidth; $xt=$img->left_margin+$this->iLabelWidth;
$year = $this->GetYear($this->iStartDate); $year = $this->GetYear($this->iStartDate);
$img->SetColor($this->year->iBackgroundColor); $img->SetColor($this->year->iBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
$img->SetLineWeight($this->year->grid->iWeight); $img->SetLineWeight($this->year->grid->iWeight);
$img->SetTextAlign("center"); $img->SetTextAlign("center");
if( $year == $this->GetYear($this->iEndDate) ) if( $year == $this->GetYear($this->iEndDate) )
$yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1); $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1);
else else
$yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1); $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 // The space for a year must be at least 20% bigger than the actual text
// so we allow 10% margin on each side // so we allow 10% margin on each side
if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) { if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) {
$img->SetColor($this->year->iTextColor); $img->SetColor($this->year->iTextColor);
$img->StrokeText(round($xt+$yearwidth/2+1), $img->StrokeText(round($xt+$yearwidth/2+1),
round($yb-$this->year->iTitleVertMargin), round($yb-$this->year->iTitleVertMargin),
$year); $year);
} }
$x = $xt + $yearwidth; $x = $xt + $yearwidth;
while( $x < $xb ) { while( $x < $xb ) {
$img->SetColor($this->year->grid->iColor); $img->SetColor($this->year->grid->iColor);
$img->Line($x,$yt,$x,$yb); $img->Line($x,$yt,$x,$yb);
$this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
$year += 1; $year += 1;
$yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year); $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year);
if( $x + $yearwidth < $xb ) if( $x + $yearwidth < $xb )
$w = $yearwidth; $w = $yearwidth;
else else
$w = $xb-$x; $w = $xb-$x;
if( $w >= 1.2*$img->GetTextWidth("".$year) ) { if( $w >= 1.2*$img->GetTextWidth("".$year) ) {
$img->SetColor($this->year->iTextColor); $img->SetColor($this->year->iTextColor);
$img->StrokeText(round($x+$w/2+1), $img->StrokeText(round($x+$w/2+1),
round($yb-$this->year->iTitleVertMargin), round($yb-$this->year->iTitleVertMargin),
$year); $year);
} }
$x += $yearwidth; $x += $yearwidth;
} }
$img->SetColor($this->year->iFrameColor); $img->SetColor($this->year->iFrameColor);
$img->SetLineWeight($this->year->iFrameWeight); $img->SetLineWeight($this->year->iFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
return $yb-$img->top_margin; return $yb-$img->top_margin;
} }
return $aYCoord; return $aYCoord;
} }
   
// Stroke table title (upper left corner) // Stroke table title (upper left corner)
function StrokeTableHeaders($aYBottom) { function StrokeTableHeaders($aYBottom) {
$img=$this->iImg; $img=$this->iImg;
$xt=$img->left_margin; $xt=$img->left_margin;
$yt=$img->top_margin; $yt=$img->top_margin;
$xb=$xt+$this->iLabelWidth; $xb=$xt+$this->iLabelWidth;
$yb=$aYBottom+$img->top_margin; $yb=$aYBottom+$img->top_margin;
   
if( $this->tableTitle->iShow ) { if( $this->tableTitle->iShow ) {
$img->SetColor($this->iTableHeaderBackgroundColor); $img->SetColor($this->iTableHeaderBackgroundColor);
$img->FilledRectangle($xt,$yt,$xb,$yb); $img->FilledRectangle($xt,$yt,$xb,$yb);
$this->tableTitle->Align("center","top"); $this->tableTitle->Align("center","top");
$this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2); $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2);
$img->SetColor($this->iTableHeaderFrameColor); $img->SetColor($this->iTableHeaderFrameColor);
$img->SetLineWeight($this->iTableHeaderFrameWeight); $img->SetLineWeight($this->iTableHeaderFrameWeight);
$img->Rectangle($xt,$yt,$xb,$yb); $img->Rectangle($xt,$yt,$xb,$yb);
} }
   
$this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow); $this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow);
   
   
// Draw the horizontal dividing line // Draw the horizontal dividing line
$this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb); $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb);
   
// Draw the vertical dividing line // Draw the vertical dividing line
// We do the width "manually" since we want the line only to grow // We do the width "manually" since we want the line only to grow
// to the left // to the left
$fancy = $this->divider->iStyle == 'fancy' ; $fancy = $this->divider->iStyle == 'fancy' ;
if( $fancy ) { if( $fancy ) {
$this->divider->iStyle = 'solid'; $this->divider->iStyle = 'solid';
} }
   
$tmp = $this->divider->iWeight; $tmp = $this->divider->iWeight;
$this->divider->iWeight=1; $this->divider->iWeight=1;
$y = $img->height-$img->bottom_margin; $y = $img->height-$img->bottom_margin;
for($i=0; $i < $tmp; ++$i ) { for($i=0; $i < $tmp; ++$i ) {
$this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y); $this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y);
} }
   
// Should we draw "fancy" divider // Should we draw "fancy" divider
if( $fancy ) { if( $fancy ) {
$img->SetLineWeight(1); $img->SetLineWeight(1);
$img->SetColor($this->iTableHeaderFrameColor); $img->SetColor($this->iTableHeaderFrameColor);
$img->Line($xb,$yt,$xb,$y); $img->Line($xb,$yt,$xb,$y);
$img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y); $img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y);
$img->SetColor('white'); $img->SetColor('white');
$img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y); $img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y);
} }
} }
   
// Main entry point to stroke scale // Main entry point to stroke scale
function Stroke() { function Stroke() {
if( !$this->IsRangeSet() ) { if( !$this->IsRangeSet() ) {
JpGraphError::RaiseL(6022); JpGraphError::RaiseL(6022);
//("Gantt scale has not been specified."); //("Gantt scale has not been specified.");
} }
$img=$this->iImg; $img=$this->iImg;
   
// If minutes are displayed then hour interval must be 1 // If minutes are displayed then hour interval must be 1
if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) { if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) {
JpGraphError::RaiseL(6023); JpGraphError::RaiseL(6023);
//('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).'); //('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 // Stroke all headers. As argument we supply the offset from the
// top which depends on any previous headers // top which depends on any previous headers
   
// First find out the height of each header // First find out the height of each header
$offy=$this->StrokeYears(0,true); $offy=$this->StrokeYears(0,true);
$offm=$this->StrokeMonths($offy,true); $offm=$this->StrokeMonths($offy,true);
$offw=$this->StrokeWeeks($offm,true); $offw=$this->StrokeWeeks($offm,true);
$offd=$this->StrokeDays($offw,true); $offd=$this->StrokeDays($offw,true);
$offh=$this->StrokeHours($offd,true); $offh=$this->StrokeHours($offd,true);
$offmin=$this->StrokeMinutes($offh,true); $offmin=$this->StrokeMinutes($offh,true);
   
   
// ... then we can stroke them in the "backwards order to ensure that // ... then we can stroke them in the "backwards order to ensure that
// the larger scale gridlines is stroked over the smaller scale gridline // the larger scale gridlines is stroked over the smaller scale gridline
$this->StrokeMinutes($offh); $this->StrokeMinutes($offh);
$this->StrokeHours($offd); $this->StrokeHours($offd);
$this->StrokeDays($offw); $this->StrokeDays($offw);
$this->StrokeWeeks($offm); $this->StrokeWeeks($offm);
$this->StrokeMonths($offy); $this->StrokeMonths($offy);
$this->StrokeYears(0); $this->StrokeYears(0);
   
// Now when we now the oaverall size of the scale headers // Now when we now the oaverall size of the scale headers
// we can stroke the overall table headers // we can stroke the overall table headers
$this->StrokeTableHeaders($offmin); $this->StrokeTableHeaders($offmin);
   
// Now we can calculate the correct scaling factor for each vertical position // Now we can calculate the correct scaling factor for each vertical position
$this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd; $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd;
   
$this->iVertHeaderSize = $offmin; $this->iVertHeaderSize = $offmin;
if( $this->iVertSpacing == -1 ) if( $this->iVertSpacing == -1 )
$this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines; $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines;
} }
} }
   
   
//=================================================== //===================================================
// CLASS GanttConstraint // CLASS GanttConstraint
// Just a structure to store all the values for a constraint // Just a structure to store all the values for a constraint
//=================================================== //===================================================
class GanttConstraint { class GanttConstraint {
public $iConstrainRow; public $iConstrainRow;
public $iConstrainType; public $iConstrainType;
public $iConstrainColor; public $iConstrainColor;
public $iConstrainArrowSize; public $iConstrainArrowSize;
public $iConstrainArrowType; public $iConstrainArrowType;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aRow,$aType,$aColor,$aArrowSize,$aArrowType){ function __construct($aRow,$aType,$aColor,$aArrowSize,$aArrowType){
$this->iConstrainType = $aType; $this->iConstrainType = $aType;
$this->iConstrainRow = $aRow; $this->iConstrainRow = $aRow;
$this->iConstrainColor=$aColor; $this->iConstrainColor=$aColor;
$this->iConstrainArrowSize=$aArrowSize; $this->iConstrainArrowSize=$aArrowSize;
$this->iConstrainArrowType=$aArrowType; $this->iConstrainArrowType=$aArrowType;
} }
} }
   
   
//=================================================== //===================================================
// CLASS GanttPlotObject // CLASS GanttPlotObject
// The common signature for a Gantt object // The common signature for a Gantt object
//=================================================== //===================================================
class GanttPlotObject { class GanttPlotObject {
public $title,$caption; public $title,$caption;
public $csimarea='',$csimtarget='',$csimwintarget='',$csimalt=''; public $csimarea='',$csimtarget='',$csimwintarget='',$csimalt='';
public $constraints = array(); public $constraints = array();
public $iCaptionMargin=5; public $iCaptionMargin=5;
public $iConstrainPos=array(); public $iConstrainPos=array();
protected $iStart=""; // Start date protected $iStart=""; // Start date
public $iVPos=0; // Vertical position public $iVPos=0; // Vertical position
protected $iLabelLeftMargin=2; // Title margin protected $iLabelLeftMargin=2; // Title margin
   
function __construct() { function __construct() {
$this->title = new TextProperty(); $this->title = new TextProperty();
$this->title->Align('left','center'); $this->title->Align('left','center');
$this->caption = new TextProperty(); $this->caption = new TextProperty();
} }
   
function GetCSIMArea() { function GetCSIMArea() {
return $this->csimarea; return $this->csimarea;
} }
   
function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') { function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') {
if( !is_string($aTarget) ) { if( !is_string($aTarget) ) {
$tv = substr(var_export($aTarget,true),0,40); $tv = substr(var_export($aTarget,true),0,40);
JpGraphError::RaiseL(6024,$tv); JpGraphError::RaiseL(6024,$tv);
//('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv"); //('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv");
} }
if( !is_string($aAlt) ) { if( !is_string($aAlt) ) {
$tv = substr(var_export($aAlt,true),0,40); $tv = substr(var_export($aAlt,true),0,40);
JpGraphError::RaiseL(6025,$tv); JpGraphError::RaiseL(6025,$tv);
//('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");
} }
   
$this->csimtarget=$aTarget; $this->csimtarget=$aTarget;
$this->csimwintarget=$aWinTarget; $this->csimwintarget=$aWinTarget;
$this->csimalt=$aAlt; $this->csimalt=$aAlt;
} }
   
function SetCSIMAlt($aAlt) { function SetCSIMAlt($aAlt) {
if( !is_string($aAlt) ) { if( !is_string($aAlt) ) {
$tv = substr(var_export($aAlt,true),0,40); $tv = substr(var_export($aAlt,true),0,40);
JpGraphError::RaiseL(6025,$tv); JpGraphError::RaiseL(6025,$tv);
//('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");
} }
$this->csimalt=$aAlt; $this->csimalt=$aAlt;
} }
   
function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) { function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) {
$this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType); $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType);
} }
   
function SetConstrainPos($xt,$yt,$xb,$yb) { function SetConstrainPos($xt,$yt,$xb,$yb) {
$this->iConstrainPos = array($xt,$yt,$xb,$yb); $this->iConstrainPos = array($xt,$yt,$xb,$yb);
} }
   
function GetMinDate() { function GetMinDate() {
return $this->iStart; return $this->iStart;
} }
   
function GetMaxDate() { function GetMaxDate() {
return $this->iStart; return $this->iStart;
} }
   
function SetCaptionMargin($aMarg) { function SetCaptionMargin($aMarg) {
$this->iCaptionMargin=$aMarg; $this->iCaptionMargin=$aMarg;
} }
   
function GetAbsHeight($aImg) { function GetAbsHeight($aImg) {
return 0; return 0;
} }
   
function GetLineNbr() { function GetLineNbr() {
return $this->iVPos; return $this->iVPos;
} }
   
function SetLabelLeftMargin($aOff) { function SetLabelLeftMargin($aOff) {
$this->iLabelLeftMargin=$aOff; $this->iLabelLeftMargin=$aOff;
} }
   
function StrokeActInfo($aImg,$aScale,$aYPos) { function StrokeActInfo($aImg,$aScale,$aYPos) {
$cols=array(); $cols=array();
$aScale->actinfo->GetColStart($aImg,$cols,true); $aScale->actinfo->GetColStart($aImg,$cols,true);
$this->title->Stroke($aImg,$cols,$aYPos); $this->title->Stroke($aImg,$cols,$aYPos);
} }
} }
   
//=================================================== //===================================================
// CLASS Progress // CLASS Progress
// Holds parameters for the progress indicator // Holds parameters for the progress indicator
// displyed within a bar // displyed within a bar
//=================================================== //===================================================
class Progress { class Progress {
public $iProgress=-1; public $iProgress=-1;
public $iPattern=GANTT_SOLID; public $iPattern=GANTT_SOLID;
public $iColor="black", $iFillColor='black'; public $iColor="black", $iFillColor='black';
public $iDensity=98, $iHeight=0.65; public $iDensity=98, $iHeight=0.65;
   
function Set($aProg) { function Set($aProg) {
if( $aProg < 0.0 || $aProg > 1.0 ) { if( $aProg < 0.0 || $aProg > 1.0 ) {
JpGraphError::RaiseL(6027); JpGraphError::RaiseL(6027);
//("Progress value must in range [0, 1]"); //("Progress value must in range [0, 1]");
} }
$this->iProgress = $aProg; $this->iProgress = $aProg;
} }
   
function SetPattern($aPattern,$aColor="blue",$aDensity=98) { function SetPattern($aPattern,$aColor="blue",$aDensity=98) {
$this->iPattern = $aPattern; $this->iPattern = $aPattern;
$this->iColor = $aColor; $this->iColor = $aColor;
$this->iDensity = $aDensity; $this->iDensity = $aDensity;
} }
   
function SetFillColor($aColor) { function SetFillColor($aColor) {
$this->iFillColor = $aColor; $this->iFillColor = $aColor;
} }
   
function SetHeight($aHeight) { function SetHeight($aHeight) {
$this->iHeight = $aHeight; $this->iHeight = $aHeight;
} }
} }
   
define('GANTT_HGRID1',0); define('GANTT_HGRID1',0);
define('GANTT_HGRID2',1); define('GANTT_HGRID2',1);
   
//=================================================== //===================================================
// CLASS HorizontalGridLine // CLASS HorizontalGridLine
// Responsible for drawinf horizontal gridlines and filled alternatibg rows // Responsible for drawinf horizontal gridlines and filled alternatibg rows
//=================================================== //===================================================
class HorizontalGridLine { class HorizontalGridLine {
private $iGraph=NULL; private $iGraph=NULL;
private $iRowColor1 = '', $iRowColor2 = ''; private $iRowColor1 = '', $iRowColor2 = '';
private $iShow=false; private $iShow=false;
private $line=null; private $line=null;
private $iStart=0; // 0=from left margin, 1=just along header private $iStart=0; // 0=from left margin, 1=just along header
   
function __construct() { function __construct() {
$this->line = new LineProperty(); $this->line = new LineProperty();
$this->line->SetColor('gray@0.4'); $this->line->SetColor('gray@0.4');
$this->line->SetStyle('dashed'); $this->line->SetStyle('dashed');
} }
   
function Show($aShow=true) { function Show($aShow=true) {
$this->iShow = $aShow; $this->iShow = $aShow;
} }
   
function SetRowFillColor($aColor1,$aColor2='') { function SetRowFillColor($aColor1,$aColor2='') {
$this->iRowColor1 = $aColor1; $this->iRowColor1 = $aColor1;
$this->iRowColor2 = $aColor2; $this->iRowColor2 = $aColor2;
} }
   
function SetStart($aStart) { function SetStart($aStart) {
$this->iStart = $aStart; $this->iStart = $aStart;
} }
   
function Stroke($aImg,$aScale) { function Stroke($aImg,$aScale) {
   
if( ! $this->iShow ) return; if( ! $this->iShow ) return;
   
// Get horizontal width of line // Get horizontal width of line
/* /*
$limst = $aScale->iStartDate; $limst = $aScale->iStartDate;
$limen = $aScale->iEndDate; $limen = $aScale->iEndDate;
$xt = round($aScale->TranslateDate($aScale->iStartDate)); $xt = round($aScale->TranslateDate($aScale->iStartDate));
$xb = round($aScale->TranslateDate($limen)); $xb = round($aScale->TranslateDate($limen));
*/ */
   
if( $this->iStart === 0 ) { if( $this->iStart === 0 ) {
$xt = $aImg->left_margin-1; $xt = $aImg->left_margin-1;
} }
else { else {
$xt = round($aScale->TranslateDate($aScale->iStartDate))+1; $xt = round($aScale->TranslateDate($aScale->iStartDate))+1;
} }
   
$xb = $aImg->width-$aImg->right_margin; $xb = $aImg->width-$aImg->right_margin;
   
$yt = round($aScale->TranslateVertPos(0)); $yt = round($aScale->TranslateVertPos(0));
$yb = round($aScale->TranslateVertPos(1)); $yb = round($aScale->TranslateVertPos(1));
$height = $yb - $yt; $height = $yb - $yt;
   
// Loop around for all lines in the chart // Loop around for all lines in the chart
for($i=0; $i < $aScale->iVertLines; ++$i ) { for($i=0; $i < $aScale->iVertLines; ++$i ) {
$yb = $yt - $height; $yb = $yt - $height;
$this->line->Stroke($aImg,$xt,$yb,$xb,$yb); $this->line->Stroke($aImg,$xt,$yb,$xb,$yb);
if( $this->iRowColor1 !== '' ) { if( $this->iRowColor1 !== '' ) {
if( $i % 2 == 0 ) { if( $i % 2 == 0 ) {
$aImg->PushColor($this->iRowColor1); $aImg->PushColor($this->iRowColor1);
$aImg->FilledRectangle($xt,$yt,$xb,$yb); $aImg->FilledRectangle($xt,$yt,$xb,$yb);
$aImg->PopColor(); $aImg->PopColor();
} }
elseif( $this->iRowColor2 !== '' ) { elseif( $this->iRowColor2 !== '' ) {
$aImg->PushColor($this->iRowColor2); $aImg->PushColor($this->iRowColor2);
$aImg->FilledRectangle($xt,$yt,$xb,$yb); $aImg->FilledRectangle($xt,$yt,$xb,$yb);
$aImg->PopColor(); $aImg->PopColor();
} }
} }
$yt = round($aScale->TranslateVertPos($i+1)); $yt = round($aScale->TranslateVertPos($i+1));
} }
$yb = $yt - $height; $yb = $yt - $height;
$this->line->Stroke($aImg,$xt,$yb,$xb,$yb); $this->line->Stroke($aImg,$xt,$yb,$xb,$yb);
} }
} }
   
   
//=================================================== //===================================================
// CLASS GanttBar // CLASS GanttBar
// Responsible for formatting individual gantt bars // Responsible for formatting individual gantt bars
//=================================================== //===================================================
class GanttBar extends GanttPlotObject { class GanttBar extends GanttPlotObject {
public $progress; public $progress;
public $leftMark,$rightMark; public $leftMark,$rightMark;
private $iEnd; private $iEnd;
private $iHeightFactor=0.5; private $iHeightFactor=0.5;
private $iFillColor="white",$iFrameColor="black"; private $iFillColor="white",$iFrameColor="black";
private $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black"; private $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black";
private $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95; private $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95;
private $iBreakStyle=false, $iBreakLineStyle='dotted',$iBreakLineWeight=1; private $iBreakStyle=false, $iBreakLineStyle='dotted',$iBreakLineWeight=1;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) { function __construct($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) {
parent::__construct(); parent::__construct();
$this->iStart = $aStart; $this->iStart = $aStart;
// Is the end date given as a date or as number of days added to start date? // Is the end date given as a date or as number of days added to start date?
if( is_string($aEnd) ) { if( is_string($aEnd) ) {
// If end date has been specified without a time we will asssume // If end date has been specified without a time we will asssume
// end date is at the end of that date // end date is at the end of that date
if( strpos($aEnd,':') === false ) { if( strpos($aEnd,':') === false ) {
$this->iEnd = strtotime($aEnd)+SECPERDAY-1; $this->iEnd = strtotime($aEnd)+SECPERDAY-1;
} }
else { else {
$this->iEnd = $aEnd; $this->iEnd = $aEnd;
} }
} }
elseif(is_int($aEnd) || is_float($aEnd) ) { elseif(is_int($aEnd) || is_float($aEnd) ) {
$this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY); $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY);
} }
$this->iVPos = $aPos; $this->iVPos = $aPos;
$this->iHeightFactor = $aHeightFactor; $this->iHeightFactor = $aHeightFactor;
$this->title->Set($aLabel); $this->title->Set($aLabel);
$this->caption = new TextProperty($aCaption); $this->caption = new TextProperty($aCaption);
$this->caption->Align("left","center"); $this->caption->Align("left","center");
$this->leftMark =new PlotMark(); $this->leftMark =new PlotMark();
$this->leftMark->Hide(); $this->leftMark->Hide();
$this->rightMark=new PlotMark(); $this->rightMark=new PlotMark();
$this->rightMark->Hide(); $this->rightMark->Hide();
$this->progress = new Progress(); $this->progress = new Progress();
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function SetShadow($aShadow=true,$aColor="gray") { function SetShadow($aShadow=true,$aColor="gray") {
$this->iShadow=$aShadow; $this->iShadow=$aShadow;
$this->iShadowColor=$aColor; $this->iShadowColor=$aColor;
} }
   
function SetBreakStyle($aFlg=true,$aLineStyle='dotted',$aLineWeight=1) { function SetBreakStyle($aFlg=true,$aLineStyle='dotted',$aLineWeight=1) {
$this->iBreakStyle = $aFlg; $this->iBreakStyle = $aFlg;
$this->iBreakLineStyle = $aLineStyle; $this->iBreakLineStyle = $aLineStyle;
$this->iBreakLineWeight = $aLineWeight; $this->iBreakLineWeight = $aLineWeight;
} }
   
function GetMaxDate() { function GetMaxDate() {
return $this->iEnd; return $this->iEnd;
} }
   
function SetHeight($aHeight) { function SetHeight($aHeight) {
$this->iHeightFactor = $aHeight; $this->iHeightFactor = $aHeight;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iFrameColor = $aColor; $this->iFrameColor = $aColor;
} }
   
function SetFillColor($aColor) { function SetFillColor($aColor) {
$this->iFillColor = $aColor; $this->iFillColor = $aColor;
} }
   
function GetAbsHeight($aImg) { function GetAbsHeight($aImg) {
if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) { if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) {
$m=-1; $m=-1;
if( is_int($this->iHeightFactor) ) if( is_int($this->iHeightFactor) )
$m = $this->iHeightFactor; $m = $this->iHeightFactor;
if( $this->leftMark->show ) if( $this->leftMark->show )
$m = max($m,$this->leftMark->width*2); $m = max($m,$this->leftMark->width*2);
if( $this->rightMark->show ) if( $this->rightMark->show )
$m = max($m,$this->rightMark->width*2); $m = max($m,$this->rightMark->width*2);
return $m; return $m;
} }
else else
return -1; return -1;
} }
   
function SetPattern($aPattern,$aColor="blue",$aDensity=95) { function SetPattern($aPattern,$aColor="blue",$aDensity=95) {
$this->iPattern = $aPattern; $this->iPattern = $aPattern;
$this->iPatternColor = $aColor; $this->iPatternColor = $aColor;
$this->iPatternDensity = $aDensity; $this->iPatternDensity = $aDensity;
} }
   
function Stroke($aImg,$aScale) { function Stroke($aImg,$aScale) {
$factory = new RectPatternFactory(); $factory = new RectPatternFactory();
$prect = $factory->Create($this->iPattern,$this->iPatternColor); $prect = $factory->Create($this->iPattern,$this->iPatternColor);
$prect->SetDensity($this->iPatternDensity); $prect->SetDensity($this->iPatternDensity);
   
// If height factor is specified as a float between 0,1 then we take it as meaning // 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. // 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 it is an integer > 1 we take it to mean the absolute height in pixels
if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1) if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1)
$vs = $aScale->GetVertSpacing()*$this->iHeightFactor; $vs = $aScale->GetVertSpacing()*$this->iHeightFactor;
elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 ) elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 )
$vs = $this->iHeightFactor; $vs = $this->iHeightFactor;
else { else {
JpGraphError::RaiseL(6028,$this->iHeightFactor); JpGraphError::RaiseL(6028,$this->iHeightFactor);
// ("Specified height (".$this->iHeightFactor.") for gantt bar is out of range."); // ("Specified height (".$this->iHeightFactor.") for gantt bar is out of range.");
} }
   
// Clip date to min max dates to show // Clip date to min max dates to show
$st = $aScale->NormalizeDate($this->iStart); $st = $aScale->NormalizeDate($this->iStart);
$en = $aScale->NormalizeDate($this->iEnd); $en = $aScale->NormalizeDate($this->iEnd);
   
$limst = max($st,$aScale->iStartDate); $limst = max($st,$aScale->iStartDate);
$limen = min($en,$aScale->iEndDate); $limen = min($en,$aScale->iEndDate);
   
$xt = round($aScale->TranslateDate($limst)); $xt = round($aScale->TranslateDate($limst));
$xb = round($aScale->TranslateDate($limen)); $xb = round($aScale->TranslateDate($limen));
$yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2)); $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2));
$yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2)); $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2));
$middle = round($yt+($yb-$yt)/2); $middle = round($yt+($yb-$yt)/2);
$this->StrokeActInfo($aImg,$aScale,$middle); $this->StrokeActInfo($aImg,$aScale,$middle);
   
// CSIM for title // CSIM for title
if( ! empty($this->title->csimtarget) ) { if( ! empty($this->title->csimtarget) ) {
$colwidth = $this->title->GetColWidth($aImg); $colwidth = $this->title->GetColWidth($aImg);
$colstarts=array(); $colstarts=array();
$aScale->actinfo->GetColStart($aImg,$colstarts,true); $aScale->actinfo->GetColStart($aImg,$colstarts,true);
$n = min(count($colwidth),count($this->title->csimtarget)); $n = min(count($colwidth),count($this->title->csimtarget));
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$title_xt = $colstarts[$i]; $title_xt = $colstarts[$i];
$title_xb = $title_xt + $colwidth[$i]; $title_xb = $title_xt + $colwidth[$i];
$coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb";
   
if( ! empty($this->title->csimtarget[$i]) ) { if( ! empty($this->title->csimtarget[$i]) ) {
$this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\""; $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\"";
   
if( ! empty($this->title->csimwintarget[$i]) ) { if( ! empty($this->title->csimwintarget[$i]) ) {
$this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" "; $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" ";
} }
   
if( ! empty($this->title->csimalt[$i]) ) { if( ! empty($this->title->csimalt[$i]) ) {
$tmp = $this->title->csimalt[$i]; $tmp = $this->title->csimalt[$i];
$this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimarea .= " />\n"; $this->csimarea .= " />\n";
} }
} }
} }
   
// Check if the bar is totally outside the current scale range // Check if the bar is totally outside the current scale range
if( $en < $aScale->iStartDate || $st > $aScale->iEndDate ) if( $en < $aScale->iStartDate || $st > $aScale->iEndDate )
return; return;
   
   
// Remember the positions for the bar // Remember the positions for the bar
$this->SetConstrainPos($xt,$yt,$xb,$yb); $this->SetConstrainPos($xt,$yt,$xb,$yb);
   
   
   
$prect->ShowFrame(false); $prect->ShowFrame(false);
$prect->SetBackground($this->iFillColor); $prect->SetBackground($this->iFillColor);
if( $this->iBreakStyle ) { if( $this->iBreakStyle ) {
$aImg->SetColor($this->iFrameColor); $aImg->SetColor($this->iFrameColor);
$olds = $aImg->SetLineStyle($this->iBreakLineStyle); $olds = $aImg->SetLineStyle($this->iBreakLineStyle);
$oldw = $aImg->SetLineWeight($this->iBreakLineWeight); $oldw = $aImg->SetLineWeight($this->iBreakLineWeight);
$aImg->StyleLine($xt,$yt,$xb,$yt); $aImg->StyleLine($xt,$yt,$xb,$yt);
$aImg->StyleLine($xt,$yb,$xb,$yb); $aImg->StyleLine($xt,$yb,$xb,$yb);
$aImg->SetLineStyle($olds); $aImg->SetLineStyle($olds);
$aImg->SetLineWeight($oldw); $aImg->SetLineWeight($oldw);
} }
else { else {
if( $this->iShadow ) { if( $this->iShadow ) {
$aImg->SetColor($this->iFrameColor); $aImg->SetColor($this->iFrameColor);
$aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor); $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->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2));
$prect->Stroke($aImg); $prect->Stroke($aImg);
} }
else { else {
$prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1)); $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1));
$prect->Stroke($aImg); $prect->Stroke($aImg);
$aImg->SetColor($this->iFrameColor); $aImg->SetColor($this->iFrameColor);
$aImg->Rectangle($xt,$yt,$xb,$yb); $aImg->Rectangle($xt,$yt,$xb,$yb);
} }
} }
// CSIM for bar // CSIM for bar
if( ! empty($this->csimtarget) ) { if( ! empty($this->csimtarget) ) {
   
$coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb"; $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb";
$this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\""; $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\"";
   
if( !empty($this->csimwintarget) ) { if( !empty($this->csimwintarget) ) {
$this->csimarea .= " target=\"".$this->csimwintarget."\" "; $this->csimarea .= " target=\"".$this->csimwintarget."\" ";
} }
   
if( $this->csimalt != '' ) { if( $this->csimalt != '' ) {
$tmp = $this->csimalt; $tmp = $this->csimalt;
$this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimarea .= " />\n"; $this->csimarea .= " />\n";
} }
   
// Draw progress bar inside activity bar // Draw progress bar inside activity bar
if( $this->progress->iProgress > 0 ) { if( $this->progress->iProgress > 0 ) {
   
$xtp = $aScale->TranslateDate($st); $xtp = $aScale->TranslateDate($st);
$xbp = $aScale->TranslateDate($en); $xbp = $aScale->TranslateDate($en);
$len = ($xbp-$xtp)*$this->progress->iProgress; $len = ($xbp-$xtp)*$this->progress->iProgress;
   
$endpos = $xtp+$len; $endpos = $xtp+$len;
if( $endpos > $xt ) { if( $endpos > $xt ) {
   
// Take away the length of the progress that is not visible (before the start date) // Take away the length of the progress that is not visible (before the start date)
$len -= ($xt-$xtp); $len -= ($xt-$xtp);
   
// Is the the progress bar visible after the start date? // Is the the progress bar visible after the start date?
if( $xtp < $xt ) if( $xtp < $xt )
$xtp = $xt; $xtp = $xt;
   
// Make sure that the progess bar doesn't extend over the end date // Make sure that the progess bar doesn't extend over the end date
if( $xtp+$len-1 > $xb ) if( $xtp+$len-1 > $xb )
$len = $xb - $xtp ; $len = $xb - $xtp ;
   
$prog = $factory->Create($this->progress->iPattern,$this->progress->iColor); $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor);
$prog->SetDensity($this->progress->iDensity); $prog->SetDensity($this->progress->iDensity);
$prog->SetBackground($this->progress->iFillColor); $prog->SetBackground($this->progress->iFillColor);
$barheight = ($yb-$yt+1); $barheight = ($yb-$yt+1);
if( $this->iShadow ) if( $this->iShadow )
$barheight -= $this->iShadowWidth; $barheight -= $this->iShadowWidth;
$progressheight = floor($barheight*$this->progress->iHeight); $progressheight = floor($barheight*$this->progress->iHeight);
$marg = ceil(($barheight-$progressheight)/2); $marg = ceil(($barheight-$progressheight)/2);
$pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg); $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg);
$prog->SetPos($pos); $prog->SetPos($pos);
$prog->Stroke($aImg); $prog->Stroke($aImg);
} }
} }
   
// We don't plot the end mark if the bar has been capped // We don't plot the end mark if the bar has been capped
if( $limst == $st ) { if( $limst == $st ) {
$y = $middle; $y = $middle;
// We treat the RIGHT and LEFT triangle mark a little bi // We treat the RIGHT and LEFT triangle mark a little bi
// special so that these marks are placed right under the // special so that these marks are placed right under the
// bar. // bar.
if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) { if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) {
$y = $yb ; $y = $yb ;
} }
$this->leftMark->Stroke($aImg,$xt,$y); $this->leftMark->Stroke($aImg,$xt,$y);
} }
if( $limen == $en ) { if( $limen == $en ) {
$y = $middle; $y = $middle;
// We treat the RIGHT and LEFT triangle mark a little bi // We treat the RIGHT and LEFT triangle mark a little bi
// special so that these marks are placed right under the // special so that these marks are placed right under the
// bar. // bar.
if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) { if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) {
$y = $yb ; $y = $yb ;
} }
$this->rightMark->Stroke($aImg,$xb,$y); $this->rightMark->Stroke($aImg,$xb,$y);
   
$margin = $this->iCaptionMargin; $margin = $this->iCaptionMargin;
if( $this->rightMark->show ) if( $this->rightMark->show )
$margin += $this->rightMark->GetWidth(); $margin += $this->rightMark->GetWidth();
$this->caption->Stroke($aImg,$xb+$margin,$middle); $this->caption->Stroke($aImg,$xb+$margin,$middle);
} }
} }
} }
   
//=================================================== //===================================================
// CLASS MileStone // CLASS MileStone
// Responsible for formatting individual milestones // Responsible for formatting individual milestones
//=================================================== //===================================================
class MileStone extends GanttPlotObject { class MileStone extends GanttPlotObject {
public $mark; public $mark;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aVPos,$aLabel,$aDate,$aCaption="") { function __construct($aVPos,$aLabel,$aDate,$aCaption="") {
GanttPlotObject::__construct(); GanttPlotObject::__construct();
$this->caption->Set($aCaption); $this->caption->Set($aCaption);
$this->caption->Align("left","center"); $this->caption->Align("left","center");
$this->caption->SetFont(FF_FONT1,FS_BOLD); $this->caption->SetFont(FF_FONT1,FS_BOLD);
$this->title->Set($aLabel); $this->title->Set($aLabel);
$this->title->SetColor("darkred"); $this->title->SetColor("darkred");
$this->mark = new PlotMark(); $this->mark = new PlotMark();
$this->mark->SetWidth(10); $this->mark->SetWidth(10);
$this->mark->SetType(MARK_DIAMOND); $this->mark->SetType(MARK_DIAMOND);
$this->mark->SetColor("darkred"); $this->mark->SetColor("darkred");
$this->mark->SetFillColor("darkred"); $this->mark->SetFillColor("darkred");
$this->iVPos = $aVPos; $this->iVPos = $aVPos;
$this->iStart = $aDate; $this->iStart = $aDate;
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
function GetAbsHeight($aImg) { function GetAbsHeight($aImg) {
return max($this->title->GetHeight($aImg),$this->mark->GetWidth()); return max($this->title->GetHeight($aImg),$this->mark->GetWidth());
} }
   
function Stroke($aImg,$aScale) { function Stroke($aImg,$aScale) {
// Put the mark in the middle at the middle of the day // Put the mark in the middle at the middle of the day
$d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2; $d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2;
$x = $aScale->TranslateDate($d); $x = $aScale->TranslateDate($d);
$y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2); $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2);
   
$this->StrokeActInfo($aImg,$aScale,$y); $this->StrokeActInfo($aImg,$aScale,$y);
   
// CSIM for title // CSIM for title
if( ! empty($this->title->csimtarget) ) { if( ! empty($this->title->csimtarget) ) {
   
$yt = round($y - $this->title->GetHeight($aImg)/2); $yt = round($y - $this->title->GetHeight($aImg)/2);
$yb = round($y + $this->title->GetHeight($aImg)/2); $yb = round($y + $this->title->GetHeight($aImg)/2);
   
$colwidth = $this->title->GetColWidth($aImg); $colwidth = $this->title->GetColWidth($aImg);
$colstarts=array(); $colstarts=array();
$aScale->actinfo->GetColStart($aImg,$colstarts,true); $aScale->actinfo->GetColStart($aImg,$colstarts,true);
$n = min(count($colwidth),count($this->title->csimtarget)); $n = min(count($colwidth),count($this->title->csimtarget));
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$title_xt = $colstarts[$i]; $title_xt = $colstarts[$i];
$title_xb = $title_xt + $colwidth[$i]; $title_xb = $title_xt + $colwidth[$i];
$coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb";
   
if( !empty($this->title->csimtarget[$i]) ) { if( !empty($this->title->csimtarget[$i]) ) {
   
$this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\""; $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\"";
   
if( !empty($this->title->csimwintarget[$i]) ) { if( !empty($this->title->csimwintarget[$i]) ) {
$this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\""; $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\"";
} }
   
if( ! empty($this->title->csimalt[$i]) ) { if( ! empty($this->title->csimalt[$i]) ) {
$tmp = $this->title->csimalt[$i]; $tmp = $this->title->csimalt[$i];
$this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimarea .= " />\n"; $this->csimarea .= " />\n";
} }
} }
} }
   
if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) if( $d < $aScale->iStartDate || $d > $aScale->iEndDate )
return; return;
   
// Remember the coordinates for any constrains linking to // Remember the coordinates for any constrains linking to
// this milestone // this milestone
$w = $this->mark->GetWidth()/2; $w = $this->mark->GetWidth()/2;
$this->SetConstrainPos($x,round($y-$w),$x,round($y+$w)); $this->SetConstrainPos($x,round($y-$w),$x,round($y+$w));
   
// Setup CSIM // Setup CSIM
if( $this->csimtarget != '' ) { if( $this->csimtarget != '' ) {
$this->mark->SetCSIMTarget( $this->csimtarget ); $this->mark->SetCSIMTarget( $this->csimtarget );
$this->mark->SetCSIMAlt( $this->csimalt ); $this->mark->SetCSIMAlt( $this->csimalt );
} }
   
$this->mark->Stroke($aImg,$x,$y); $this->mark->Stroke($aImg,$x,$y);
$this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y); $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y);
   
$this->csimarea .= $this->mark->GetCSIMAreas(); $this->csimarea .= $this->mark->GetCSIMAreas();
} }
} }
   
   
//=================================================== //===================================================
// CLASS GanttVLine // CLASS GanttVLine
// Responsible for formatting individual milestones // Responsible for formatting individual milestones
//=================================================== //===================================================
   
class TextPropertyBelow extends TextProperty { class TextPropertyBelow extends TextProperty {
function __construct($aTxt='') { function __construct($aTxt='') {
parent::__construct($aTxt); parent::__construct($aTxt);
} }
   
function GetColWidth($aImg,$aMargin=0) { function GetColWidth($aImg,$aMargin=0) {
// Since we are not stroking the title in the columns // Since we are not stroking the title in the columns
// but rather under the graph we want this to return 0. // but rather under the graph we want this to return 0.
return array(0); return array(0);
} }
} }
   
class GanttVLine extends GanttPlotObject { class GanttVLine extends GanttPlotObject {
   
private $iLine,$title_margin=3, $iDayOffset=0.5; private $iLine,$title_margin=3, $iDayOffset=0.5;
private $iStartRow = -1, $iEndRow = -1; private $iStartRow = -1, $iEndRow = -1;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($aDate,$aTitle="",$aColor="darkred",$aWeight=2,$aStyle="solid") { function __construct($aDate,$aTitle="",$aColor="darkred",$aWeight=2,$aStyle="solid") {
GanttPlotObject::__construct(); GanttPlotObject::__construct();
$this->iLine = new LineProperty(); $this->iLine = new LineProperty();
$this->iLine->SetColor($aColor); $this->iLine->SetColor($aColor);
$this->iLine->SetWeight($aWeight); $this->iLine->SetWeight($aWeight);
$this->iLine->SetStyle($aStyle); $this->iLine->SetStyle($aStyle);
$this->iStart = $aDate; $this->iStart = $aDate;
$this->title = new TextPropertyBelow(); $this->title = new TextPropertyBelow();
$this->title->Set($aTitle); $this->title->Set($aTitle);
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
// Set start and end rows for the VLine. By default the entire heigh of the // Set start and end rows for the VLine. By default the entire heigh of the
// Gantt chart is used // Gantt chart is used
function SetRowSpan($aStart, $aEnd=-1) { function SetRowSpan($aStart, $aEnd=-1) {
$this->iStartRow = $aStart; $this->iStartRow = $aStart;
$this->iEndRow = $aEnd; $this->iEndRow = $aEnd;
} }
   
function SetDayOffset($aOff=0.5) { function SetDayOffset($aOff=0.5) {
if( $aOff < 0.0 || $aOff > 1.0 ) { if( $aOff < 0.0 || $aOff > 1.0 ) {
JpGraphError::RaiseL(6029); JpGraphError::RaiseL(6029);
//("Offset for vertical line must be in range [0,1]"); //("Offset for vertical line must be in range [0,1]");
} }
$this->iDayOffset = $aOff; $this->iDayOffset = $aOff;
} }
   
function SetTitleMargin($aMarg) { function SetTitleMargin($aMarg) {
$this->title_margin = $aMarg; $this->title_margin = $aMarg;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->iLine->SetWeight($aWeight); $this->iLine->SetWeight($aWeight);
} }
   
function Stroke($aImg,$aScale) { function Stroke($aImg,$aScale) {
$d = $aScale->NormalizeDate($this->iStart); $d = $aScale->NormalizeDate($this->iStart);
if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) if( $d < $aScale->iStartDate || $d > $aScale->iEndDate )
return; return;
if($this->iDayOffset != 0.0) if($this->iDayOffset != 0.0)
$d += 24*60*60*$this->iDayOffset; $d += 24*60*60*$this->iDayOffset;
$x = $aScale->TranslateDate($d);//d=1006858800, $x = $aScale->TranslateDate($d);//d=1006858800,
   
if( $this->iStartRow > -1 ) { if( $this->iStartRow > -1 ) {
$y1 = $aScale->TranslateVertPos($this->iStartRow,true) ; $y1 = $aScale->TranslateVertPos($this->iStartRow,true) ;
} }
else { else {
$y1 = $aScale->iVertHeaderSize+$aImg->top_margin; $y1 = $aScale->iVertHeaderSize+$aImg->top_margin;
} }
   
if( $this->iEndRow > -1 ) { if( $this->iEndRow > -1 ) {
$y2 = $aScale->TranslateVertPos($this->iEndRow); $y2 = $aScale->TranslateVertPos($this->iEndRow);
} }
else { else {
$y2 = $aImg->height - $aImg->bottom_margin; $y2 = $aImg->height - $aImg->bottom_margin;
} }
   
$this->iLine->Stroke($aImg,$x,$y1,$x,$y2); $this->iLine->Stroke($aImg,$x,$y1,$x,$y2);
$this->title->Align("center","top"); $this->title->Align("center","top");
$this->title->Stroke($aImg,$x,$y2+$this->title_margin); $this->title->Stroke($aImg,$x,$y2+$this->title_margin);
} }
} }
   
//=================================================== //===================================================
// CLASS LinkArrow // CLASS LinkArrow
// Handles the drawing of a an arrow // Handles the drawing of a an arrow
//=================================================== //===================================================
class LinkArrow { class LinkArrow {
private $ix,$iy; private $ix,$iy;
private $isizespec = array( private $isizespec = array(
array(2,3),array(3,5),array(3,8),array(6,15),array(8,22)); 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 $iDirection=ARROW_DOWN,$iType=ARROWT_SOLID,$iSize=ARROW_S2;
private $iColor='black'; private $iColor='black';
   
function __construct($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) { function __construct($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) {
$this->iDirection = $aDirection; $this->iDirection = $aDirection;
$this->iType = $aType; $this->iType = $aType;
$this->iSize = $aSize; $this->iSize = $aSize;
$this->ix = $x; $this->ix = $x;
$this->iy = $y; $this->iy = $y;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function SetSize($aSize) { function SetSize($aSize) {
$this->iSize = $aSize; $this->iSize = $aSize;
} }
   
function SetType($aType) { function SetType($aType) {
$this->iType = $aType; $this->iType = $aType;
} }
   
function Stroke($aImg) { function Stroke($aImg) {
list($dx,$dy) = $this->isizespec[$this->iSize]; list($dx,$dy) = $this->isizespec[$this->iSize];
$x = $this->ix; $x = $this->ix;
$y = $this->iy; $y = $this->iy;
switch ( $this->iDirection ) { switch ( $this->iDirection ) {
case ARROW_DOWN: case ARROW_DOWN:
$c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y); $c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y);
break; break;
case ARROW_UP: case ARROW_UP:
$c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y); $c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y);
break; break;
case ARROW_LEFT: case ARROW_LEFT:
$c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y); $c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y);
break; break;
case ARROW_RIGHT: case ARROW_RIGHT:
$c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y); $c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y);
break; break;
default: default:
JpGraphError::RaiseL(6030); JpGraphError::RaiseL(6030);
//('Unknown arrow direction for link.'); //('Unknown arrow direction for link.');
die(); die();
break; break;
} }
$aImg->SetColor($this->iColor); $aImg->SetColor($this->iColor);
switch( $this->iType ) { switch( $this->iType ) {
case ARROWT_SOLID: case ARROWT_SOLID:
$aImg->FilledPolygon($c); $aImg->FilledPolygon($c);
break; break;
case ARROWT_OPEN: case ARROWT_OPEN:
$aImg->Polygon($c); $aImg->Polygon($c);
break; break;
default: default:
JpGraphError::RaiseL(6031); JpGraphError::RaiseL(6031);
//('Unknown arrow type for link.'); //('Unknown arrow type for link.');
die(); die();
break; break;
} }
} }
} }
   
//=================================================== //===================================================
// CLASS GanttLink // CLASS GanttLink
// Handles the drawing of a link line between 2 points // Handles the drawing of a link line between 2 points
//=================================================== //===================================================
   
class GanttLink { class GanttLink {
private $ix1,$ix2,$iy1,$iy2; private $ix1,$ix2,$iy1,$iy2;
private $iPathType=2,$iPathExtend=15; private $iPathType=2,$iPathExtend=15;
private $iColor='black',$iWeight=1; private $iColor='black',$iWeight=1;
private $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID; private $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID;
   
function __construct($x1=0,$y1=0,$x2=0,$y2=0) { function __construct($x1=0,$y1=0,$x2=0,$y2=0) {
$this->ix1 = $x1; $this->ix1 = $x1;
$this->ix2 = $x2; $this->ix2 = $x2;
$this->iy1 = $y1; $this->iy1 = $y1;
$this->iy2 = $y2; $this->iy2 = $y2;
} }
   
function SetPos($x1,$y1,$x2,$y2) { function SetPos($x1,$y1,$x2,$y2) {
$this->ix1 = $x1; $this->ix1 = $x1;
$this->ix2 = $x2; $this->ix2 = $x2;
$this->iy1 = $y1; $this->iy1 = $y1;
$this->iy2 = $y2; $this->iy2 = $y2;
} }
   
function SetPath($aPath) { function SetPath($aPath) {
$this->iPathType = $aPath; $this->iPathType = $aPath;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function SetArrow($aSize,$aType=ARROWT_SOLID) { function SetArrow($aSize,$aType=ARROWT_SOLID) {
$this->iArrowSize = $aSize; $this->iArrowSize = $aSize;
$this->iArrowType = $aType; $this->iArrowType = $aType;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->iWeight = $aWeight; $this->iWeight = $aWeight;
} }
   
function Stroke($aImg) { function Stroke($aImg) {
// The way the path for the arrow is constructed is partly based // The way the path for the arrow is constructed is partly based
// on some heuristics. This is not an exact science but draws the // on some heuristics. This is not an exact science but draws the
// path in a way that, for me, makes esthetic sence. For example // 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 // if the start and end activities are very close we make a small
// detour to endter the target horixontally. If there are more // detour to endter the target horixontally. If there are more
// space between axctivities then no suh detour is made and the // space between axctivities then no suh detour is made and the
// target is "hit" directly vertical. I have tried to keep this // target is "hit" directly vertical. I have tried to keep this
// simple. no doubt this could become almost infinitive complex // simple. no doubt this could become almost infinitive complex
// and have some real AI. Feel free to modify this. // and have some real AI. Feel free to modify this.
// This will no-doubt be tweaked as times go by. One design aim // This will no-doubt be tweaked as times go by. One design aim
// is to avoid having the user choose what types of arrow // is to avoid having the user choose what types of arrow
// he wants. // he wants.
   
// The arrow is drawn between (x1,y1) to (x2,y2) // The arrow is drawn between (x1,y1) to (x2,y2)
$x1 = $this->ix1 ; $x1 = $this->ix1 ;
$x2 = $this->ix2 ; $x2 = $this->ix2 ;
$y1 = $this->iy1 ; $y1 = $this->iy1 ;
$y2 = $this->iy2 ; $y2 = $this->iy2 ;
   
// Depending on if the target is below or above we have to // Depending on if the target is below or above we have to
// handle thi different. // handle thi different.
if( $y2 > $y1 ) { if( $y2 > $y1 ) {
$arrowtype = ARROW_DOWN; $arrowtype = ARROW_DOWN;
$midy = round(($y2-$y1)/2+$y1); $midy = round(($y2-$y1)/2+$y1);
if( $x2 > $x1 ) { if( $x2 > $x1 ) {
switch ( $this->iPathType ) { switch ( $this->iPathType ) {
case 0: case 0:
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
break; break;
case 1: case 1:
case 2: case 2:
case 3: case 3:
$c = array($x1,$y1,$x2,$y1,$x2,$y2); $c = array($x1,$y1,$x2,$y1,$x2,$y2);
break; break;
default: default:
JpGraphError::RaiseL(6032,$this->iPathType); JpGraphError::RaiseL(6032,$this->iPathType);
//('Internal error: Unknown path type (='.$this->iPathType .') specified for link.'); //('Internal error: Unknown path type (='.$this->iPathType .') specified for link.');
exit(1); exit(1);
break; break;
} }
} }
else { else {
switch ( $this->iPathType ) { switch ( $this->iPathType ) {
case 0: case 0:
case 1: case 1:
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
break; break;
case 2: case 2:
// Always extend out horizontally a bit from the first point // Always extend out horizontally a bit from the first point
// If we draw a link back in time (end to start) and the bars // 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 // are very close we also change the path so it comes in from
// the left on the activity // the left on the activity
$c = array($x1,$y1,$x1+$this->iPathExtend,$y1, $c = array($x1,$y1,$x1+$this->iPathExtend,$y1,
$x1+$this->iPathExtend,$midy, $x1+$this->iPathExtend,$midy,
$x2,$midy,$x2,$y2); $x2,$midy,$x2,$y2);
break; break;
case 3: case 3:
if( $y2-$midy < 6 ) { if( $y2-$midy < 6 ) {
$c = array($x1,$y1,$x1,$midy, $c = array($x1,$y1,$x1,$midy,
$x2-$this->iPathExtend,$midy, $x2-$this->iPathExtend,$midy,
$x2-$this->iPathExtend,$y2, $x2-$this->iPathExtend,$y2,
$x2,$y2); $x2,$y2);
$arrowtype = ARROW_RIGHT; $arrowtype = ARROW_RIGHT;
} }
else { else {
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
} }
break; break;
default: default:
JpGraphError::RaiseL(6032,$this->iPathType); JpGraphError::RaiseL(6032,$this->iPathType);
//('Internal error: Unknown path type specified for link.'); //('Internal error: Unknown path type specified for link.');
exit(1); exit(1);
break; break;
} }
} }
$arrow = new LinkArrow($x2,$y2,$arrowtype); $arrow = new LinkArrow($x2,$y2,$arrowtype);
} }
else { else {
// Y2 < Y1 // Y2 < Y1
$arrowtype = ARROW_UP; $arrowtype = ARROW_UP;
$midy = round(($y1-$y2)/2+$y2); $midy = round(($y1-$y2)/2+$y2);
if( $x2 > $x1 ) { if( $x2 > $x1 ) {
switch ( $this->iPathType ) { switch ( $this->iPathType ) {
case 0: case 0:
case 1: case 1:
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
break; break;
case 3: case 3:
if( $midy-$y2 < 8 ) { if( $midy-$y2 < 8 ) {
$arrowtype = ARROW_RIGHT; $arrowtype = ARROW_RIGHT;
$c = array($x1,$y1,$x1,$y2,$x2,$y2); $c = array($x1,$y1,$x1,$y2,$x2,$y2);
} }
else { else {
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
} }
break; break;
default: default:
JpGraphError::RaiseL(6032,$this->iPathType); JpGraphError::RaiseL(6032,$this->iPathType);
//('Internal error: Unknown path type specified for link.'); //('Internal error: Unknown path type specified for link.');
break; break;
} }
} }
else { else {
switch ( $this->iPathType ) { switch ( $this->iPathType ) {
case 0: case 0:
case 1: case 1:
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
break; break;
case 2: case 2:
// Always extend out horizontally a bit from the first point // Always extend out horizontally a bit from the first point
$c = array($x1,$y1,$x1+$this->iPathExtend,$y1, $c = array($x1,$y1,$x1+$this->iPathExtend,$y1,
$x1+$this->iPathExtend,$midy, $x1+$this->iPathExtend,$midy,
$x2,$midy,$x2,$y2); $x2,$midy,$x2,$y2);
break; break;
case 3: case 3:
if( $midy-$y2 < 16 ) { if( $midy-$y2 < 16 ) {
$arrowtype = ARROW_RIGHT; $arrowtype = ARROW_RIGHT;
$c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy, $c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy,
$x2-$this->iPathExtend,$y2, $x2-$this->iPathExtend,$y2,
$x2,$y2); $x2,$y2);
} }
else { else {
$c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
} }
break; break;
default: default:
JpGraphError::RaiseL(6032,$this->iPathType); JpGraphError::RaiseL(6032,$this->iPathType);
//('Internal error: Unknown path type specified for link.'); //('Internal error: Unknown path type specified for link.');
break; break;
} }
} }
$arrow = new LinkArrow($x2,$y2,$arrowtype); $arrow = new LinkArrow($x2,$y2,$arrowtype);
} }
$aImg->SetColor($this->iColor); $aImg->SetColor($this->iColor);
$aImg->SetLineWeight($this->iWeight); $aImg->SetLineWeight($this->iWeight);
$aImg->Polygon($c); $aImg->Polygon($c);
$aImg->SetLineWeight(1); $aImg->SetLineWeight(1);
$arrow->SetColor($this->iColor); $arrow->SetColor($this->iColor);
$arrow->SetSize($this->iArrowSize); $arrow->SetSize($this->iArrowSize);
$arrow->SetType($this->iArrowType); $arrow->SetType($this->iArrowType);
$arrow->Stroke($aImg); $arrow->Stroke($aImg);
} }
} }
   
// <EOF> // <EOF>
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_GB2312.PHP // File: JPGRAPH_GB2312.PHP
// Description: Chinese font conversions // Description: Chinese font conversions
// Created: 2003-05-30 // Created: 2003-05-30
// Ver: $Id: jpgraph_gb2312.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_gb2312.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
class GB2312toUTF8 { class GB2312toUTF8 {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// This code table is used to translate GB2312 code (key) to // This code table is used to translate GB2312 code (key) to
// it's corresponding Unicode value (data) // it's corresponding Unicode value (data)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
private $codetable = array( private $codetable = array(
8481 => 12288, 8482 => 12289, 8483 => 12290, 8484 => 12539, 8485 => 713, 8481 => 12288, 8482 => 12289, 8483 => 12290, 8484 => 12539, 8485 => 713,
8486 => 711, 8487 => 168, 8488 => 12291, 8489 => 12293, 8490 => 8213, 8486 => 711, 8487 => 168, 8488 => 12291, 8489 => 12293, 8490 => 8213,
8491 => 65374, 8492 => 8214, 8493 => 8230, 8494 => 8216, 8495 => 8217, 8491 => 65374, 8492 => 8214, 8493 => 8230, 8494 => 8216, 8495 => 8217,
8496 => 8220, 8497 => 8221, 8498 => 12308, 8499 => 12309, 8500 => 12296, 8496 => 8220, 8497 => 8221, 8498 => 12308, 8499 => 12309, 8500 => 12296,
8501 => 12297, 8502 => 12298, 8503 => 12299, 8504 => 12300, 8505 => 12301, 8501 => 12297, 8502 => 12298, 8503 => 12299, 8504 => 12300, 8505 => 12301,
8506 => 12302, 8507 => 12303, 8508 => 12310, 8509 => 12311, 8510 => 12304, 8506 => 12302, 8507 => 12303, 8508 => 12310, 8509 => 12311, 8510 => 12304,
8511 => 12305, 8512 => 177, 8513 => 215, 8514 => 247, 8515 => 8758, 8511 => 12305, 8512 => 177, 8513 => 215, 8514 => 247, 8515 => 8758,
8516 => 8743, 8517 => 8744, 8518 => 8721, 8519 => 8719, 8520 => 8746, 8516 => 8743, 8517 => 8744, 8518 => 8721, 8519 => 8719, 8520 => 8746,
8521 => 8745, 8522 => 8712, 8523 => 8759, 8524 => 8730, 8525 => 8869, 8521 => 8745, 8522 => 8712, 8523 => 8759, 8524 => 8730, 8525 => 8869,
8526 => 8741, 8527 => 8736, 8528 => 8978, 8529 => 8857, 8530 => 8747, 8526 => 8741, 8527 => 8736, 8528 => 8978, 8529 => 8857, 8530 => 8747,
8531 => 8750, 8532 => 8801, 8533 => 8780, 8534 => 8776, 8535 => 8765, 8531 => 8750, 8532 => 8801, 8533 => 8780, 8534 => 8776, 8535 => 8765,
8536 => 8733, 8537 => 8800, 8538 => 8814, 8539 => 8815, 8540 => 8804, 8536 => 8733, 8537 => 8800, 8538 => 8814, 8539 => 8815, 8540 => 8804,
8541 => 8805, 8542 => 8734, 8543 => 8757, 8544 => 8756, 8545 => 9794, 8541 => 8805, 8542 => 8734, 8543 => 8757, 8544 => 8756, 8545 => 9794,
8546 => 9792, 8547 => 176, 8548 => 8242, 8549 => 8243, 8550 => 8451, 8546 => 9792, 8547 => 176, 8548 => 8242, 8549 => 8243, 8550 => 8451,
8551 => 65284, 8552 => 164, 8553 => 65504, 8554 => 65505, 8555 => 8240, 8551 => 65284, 8552 => 164, 8553 => 65504, 8554 => 65505, 8555 => 8240,
8556 => 167, 8557 => 8470, 8558 => 9734, 8559 => 9733, 8560 => 9675, 8556 => 167, 8557 => 8470, 8558 => 9734, 8559 => 9733, 8560 => 9675,
8561 => 9679, 8562 => 9678, 8563 => 9671, 8564 => 9670, 8565 => 9633, 8561 => 9679, 8562 => 9678, 8563 => 9671, 8564 => 9670, 8565 => 9633,
8566 => 9632, 8567 => 9651, 8568 => 9650, 8569 => 8251, 8570 => 8594, 8566 => 9632, 8567 => 9651, 8568 => 9650, 8569 => 8251, 8570 => 8594,
8571 => 8592, 8572 => 8593, 8573 => 8595, 8574 => 12307, 8753 => 9352, 8571 => 8592, 8572 => 8593, 8573 => 8595, 8574 => 12307, 8753 => 9352,
8754 => 9353, 8755 => 9354, 8756 => 9355, 8757 => 9356, 8758 => 9357, 8754 => 9353, 8755 => 9354, 8756 => 9355, 8757 => 9356, 8758 => 9357,
8759 => 9358, 8760 => 9359, 8761 => 9360, 8762 => 9361, 8763 => 9362, 8759 => 9358, 8760 => 9359, 8761 => 9360, 8762 => 9361, 8763 => 9362,
8764 => 9363, 8765 => 9364, 8766 => 9365, 8767 => 9366, 8768 => 9367, 8764 => 9363, 8765 => 9364, 8766 => 9365, 8767 => 9366, 8768 => 9367,
8769 => 9368, 8770 => 9369, 8771 => 9370, 8772 => 9371, 8773 => 9332, 8769 => 9368, 8770 => 9369, 8771 => 9370, 8772 => 9371, 8773 => 9332,
8774 => 9333, 8775 => 9334, 8776 => 9335, 8777 => 9336, 8778 => 9337, 8774 => 9333, 8775 => 9334, 8776 => 9335, 8777 => 9336, 8778 => 9337,
8779 => 9338, 8780 => 9339, 8781 => 9340, 8782 => 9341, 8783 => 9342, 8779 => 9338, 8780 => 9339, 8781 => 9340, 8782 => 9341, 8783 => 9342,
8784 => 9343, 8785 => 9344, 8786 => 9345, 8787 => 9346, 8788 => 9347, 8784 => 9343, 8785 => 9344, 8786 => 9345, 8787 => 9346, 8788 => 9347,
8789 => 9348, 8790 => 9349, 8791 => 9350, 8792 => 9351, 8793 => 9312, 8789 => 9348, 8790 => 9349, 8791 => 9350, 8792 => 9351, 8793 => 9312,
8794 => 9313, 8795 => 9314, 8796 => 9315, 8797 => 9316, 8798 => 9317, 8794 => 9313, 8795 => 9314, 8796 => 9315, 8797 => 9316, 8798 => 9317,
8799 => 9318, 8800 => 9319, 8801 => 9320, 8802 => 9321, 8805 => 12832, 8799 => 9318, 8800 => 9319, 8801 => 9320, 8802 => 9321, 8805 => 12832,
8806 => 12833, 8807 => 12834, 8808 => 12835, 8809 => 12836, 8810 => 12837, 8806 => 12833, 8807 => 12834, 8808 => 12835, 8809 => 12836, 8810 => 12837,
8811 => 12838, 8812 => 12839, 8813 => 12840, 8814 => 12841, 8817 => 8544, 8811 => 12838, 8812 => 12839, 8813 => 12840, 8814 => 12841, 8817 => 8544,
8818 => 8545, 8819 => 8546, 8820 => 8547, 8821 => 8548, 8822 => 8549, 8818 => 8545, 8819 => 8546, 8820 => 8547, 8821 => 8548, 8822 => 8549,
8823 => 8550, 8824 => 8551, 8825 => 8552, 8826 => 8553, 8827 => 8554, 8823 => 8550, 8824 => 8551, 8825 => 8552, 8826 => 8553, 8827 => 8554,
8828 => 8555, 8993 => 65281, 8994 => 65282, 8995 => 65283, 8996 => 65509, 8828 => 8555, 8993 => 65281, 8994 => 65282, 8995 => 65283, 8996 => 65509,
8997 => 65285, 8998 => 65286, 8999 => 65287, 9000 => 65288, 9001 => 65289, 8997 => 65285, 8998 => 65286, 8999 => 65287, 9000 => 65288, 9001 => 65289,
9002 => 65290, 9003 => 65291, 9004 => 65292, 9005 => 65293, 9006 => 65294, 9002 => 65290, 9003 => 65291, 9004 => 65292, 9005 => 65293, 9006 => 65294,
9007 => 65295, 9008 => 65296, 9009 => 65297, 9010 => 65298, 9011 => 65299, 9007 => 65295, 9008 => 65296, 9009 => 65297, 9010 => 65298, 9011 => 65299,
9012 => 65300, 9013 => 65301, 9014 => 65302, 9015 => 65303, 9016 => 65304, 9012 => 65300, 9013 => 65301, 9014 => 65302, 9015 => 65303, 9016 => 65304,
9017 => 65305, 9018 => 65306, 9019 => 65307, 9020 => 65308, 9021 => 65309, 9017 => 65305, 9018 => 65306, 9019 => 65307, 9020 => 65308, 9021 => 65309,
9022 => 65310, 9023 => 65311, 9024 => 65312, 9025 => 65313, 9026 => 65314, 9022 => 65310, 9023 => 65311, 9024 => 65312, 9025 => 65313, 9026 => 65314,
9027 => 65315, 9028 => 65316, 9029 => 65317, 9030 => 65318, 9031 => 65319, 9027 => 65315, 9028 => 65316, 9029 => 65317, 9030 => 65318, 9031 => 65319,
9032 => 65320, 9033 => 65321, 9034 => 65322, 9035 => 65323, 9036 => 65324, 9032 => 65320, 9033 => 65321, 9034 => 65322, 9035 => 65323, 9036 => 65324,
9037 => 65325, 9038 => 65326, 9039 => 65327, 9040 => 65328, 9041 => 65329, 9037 => 65325, 9038 => 65326, 9039 => 65327, 9040 => 65328, 9041 => 65329,
9042 => 65330, 9043 => 65331, 9044 => 65332, 9045 => 65333, 9046 => 65334, 9042 => 65330, 9043 => 65331, 9044 => 65332, 9045 => 65333, 9046 => 65334,
9047 => 65335, 9048 => 65336, 9049 => 65337, 9050 => 65338, 9051 => 65339, 9047 => 65335, 9048 => 65336, 9049 => 65337, 9050 => 65338, 9051 => 65339,
9052 => 65340, 9053 => 65341, 9054 => 65342, 9055 => 65343, 9056 => 65344, 9052 => 65340, 9053 => 65341, 9054 => 65342, 9055 => 65343, 9056 => 65344,
9057 => 65345, 9058 => 65346, 9059 => 65347, 9060 => 65348, 9061 => 65349, 9057 => 65345, 9058 => 65346, 9059 => 65347, 9060 => 65348, 9061 => 65349,
9062 => 65350, 9063 => 65351, 9064 => 65352, 9065 => 65353, 9066 => 65354, 9062 => 65350, 9063 => 65351, 9064 => 65352, 9065 => 65353, 9066 => 65354,
9067 => 65355, 9068 => 65356, 9069 => 65357, 9070 => 65358, 9071 => 65359, 9067 => 65355, 9068 => 65356, 9069 => 65357, 9070 => 65358, 9071 => 65359,
9072 => 65360, 9073 => 65361, 9074 => 65362, 9075 => 65363, 9076 => 65364, 9072 => 65360, 9073 => 65361, 9074 => 65362, 9075 => 65363, 9076 => 65364,
9077 => 65365, 9078 => 65366, 9079 => 65367, 9080 => 65368, 9081 => 65369, 9077 => 65365, 9078 => 65366, 9079 => 65367, 9080 => 65368, 9081 => 65369,
9082 => 65370, 9083 => 65371, 9084 => 65372, 9085 => 65373, 9086 => 65507, 9082 => 65370, 9083 => 65371, 9084 => 65372, 9085 => 65373, 9086 => 65507,
9249 => 12353, 9250 => 12354, 9251 => 12355, 9252 => 12356, 9253 => 12357, 9249 => 12353, 9250 => 12354, 9251 => 12355, 9252 => 12356, 9253 => 12357,
9254 => 12358, 9255 => 12359, 9256 => 12360, 9257 => 12361, 9258 => 12362, 9254 => 12358, 9255 => 12359, 9256 => 12360, 9257 => 12361, 9258 => 12362,
9259 => 12363, 9260 => 12364, 9261 => 12365, 9262 => 12366, 9263 => 12367, 9259 => 12363, 9260 => 12364, 9261 => 12365, 9262 => 12366, 9263 => 12367,
9264 => 12368, 9265 => 12369, 9266 => 12370, 9267 => 12371, 9268 => 12372, 9264 => 12368, 9265 => 12369, 9266 => 12370, 9267 => 12371, 9268 => 12372,
9269 => 12373, 9270 => 12374, 9271 => 12375, 9272 => 12376, 9273 => 12377, 9269 => 12373, 9270 => 12374, 9271 => 12375, 9272 => 12376, 9273 => 12377,
9274 => 12378, 9275 => 12379, 9276 => 12380, 9277 => 12381, 9278 => 12382, 9274 => 12378, 9275 => 12379, 9276 => 12380, 9277 => 12381, 9278 => 12382,
9279 => 12383, 9280 => 12384, 9281 => 12385, 9282 => 12386, 9283 => 12387, 9279 => 12383, 9280 => 12384, 9281 => 12385, 9282 => 12386, 9283 => 12387,
9284 => 12388, 9285 => 12389, 9286 => 12390, 9287 => 12391, 9288 => 12392, 9284 => 12388, 9285 => 12389, 9286 => 12390, 9287 => 12391, 9288 => 12392,
9289 => 12393, 9290 => 12394, 9291 => 12395, 9292 => 12396, 9293 => 12397, 9289 => 12393, 9290 => 12394, 9291 => 12395, 9292 => 12396, 9293 => 12397,
9294 => 12398, 9295 => 12399, 9296 => 12400, 9297 => 12401, 9298 => 12402, 9294 => 12398, 9295 => 12399, 9296 => 12400, 9297 => 12401, 9298 => 12402,
9299 => 12403, 9300 => 12404, 9301 => 12405, 9302 => 12406, 9303 => 12407, 9299 => 12403, 9300 => 12404, 9301 => 12405, 9302 => 12406, 9303 => 12407,
9304 => 12408, 9305 => 12409, 9306 => 12410, 9307 => 12411, 9308 => 12412, 9304 => 12408, 9305 => 12409, 9306 => 12410, 9307 => 12411, 9308 => 12412,
9309 => 12413, 9310 => 12414, 9311 => 12415, 9312 => 12416, 9313 => 12417, 9309 => 12413, 9310 => 12414, 9311 => 12415, 9312 => 12416, 9313 => 12417,
9314 => 12418, 9315 => 12419, 9316 => 12420, 9317 => 12421, 9318 => 12422, 9314 => 12418, 9315 => 12419, 9316 => 12420, 9317 => 12421, 9318 => 12422,
9319 => 12423, 9320 => 12424, 9321 => 12425, 9322 => 12426, 9323 => 12427, 9319 => 12423, 9320 => 12424, 9321 => 12425, 9322 => 12426, 9323 => 12427,
9324 => 12428, 9325 => 12429, 9326 => 12430, 9327 => 12431, 9328 => 12432, 9324 => 12428, 9325 => 12429, 9326 => 12430, 9327 => 12431, 9328 => 12432,
9329 => 12433, 9330 => 12434, 9331 => 12435, 9505 => 12449, 9506 => 12450, 9329 => 12433, 9330 => 12434, 9331 => 12435, 9505 => 12449, 9506 => 12450,
9507 => 12451, 9508 => 12452, 9509 => 12453, 9510 => 12454, 9511 => 12455, 9507 => 12451, 9508 => 12452, 9509 => 12453, 9510 => 12454, 9511 => 12455,
9512 => 12456, 9513 => 12457, 9514 => 12458, 9515 => 12459, 9516 => 12460, 9512 => 12456, 9513 => 12457, 9514 => 12458, 9515 => 12459, 9516 => 12460,
9517 => 12461, 9518 => 12462, 9519 => 12463, 9520 => 12464, 9521 => 12465, 9517 => 12461, 9518 => 12462, 9519 => 12463, 9520 => 12464, 9521 => 12465,
9522 => 12466, 9523 => 12467, 9524 => 12468, 9525 => 12469, 9526 => 12470, 9522 => 12466, 9523 => 12467, 9524 => 12468, 9525 => 12469, 9526 => 12470,
9527 => 12471, 9528 => 12472, 9529 => 12473, 9530 => 12474, 9531 => 12475, 9527 => 12471, 9528 => 12472, 9529 => 12473, 9530 => 12474, 9531 => 12475,
9532 => 12476, 9533 => 12477, 9534 => 12478, 9535 => 12479, 9536 => 12480, 9532 => 12476, 9533 => 12477, 9534 => 12478, 9535 => 12479, 9536 => 12480,
9537 => 12481, 9538 => 12482, 9539 => 12483, 9540 => 12484, 9541 => 12485, 9537 => 12481, 9538 => 12482, 9539 => 12483, 9540 => 12484, 9541 => 12485,
9542 => 12486, 9543 => 12487, 9544 => 12488, 9545 => 12489, 9546 => 12490, 9542 => 12486, 9543 => 12487, 9544 => 12488, 9545 => 12489, 9546 => 12490,
9547 => 12491, 9548 => 12492, 9549 => 12493, 9550 => 12494, 9551 => 12495, 9547 => 12491, 9548 => 12492, 9549 => 12493, 9550 => 12494, 9551 => 12495,
9552 => 12496, 9553 => 12497, 9554 => 12498, 9555 => 12499, 9556 => 12500, 9552 => 12496, 9553 => 12497, 9554 => 12498, 9555 => 12499, 9556 => 12500,
9557 => 12501, 9558 => 12502, 9559 => 12503, 9560 => 12504, 9561 => 12505, 9557 => 12501, 9558 => 12502, 9559 => 12503, 9560 => 12504, 9561 => 12505,
9562 => 12506, 9563 => 12507, 9564 => 12508, 9565 => 12509, 9566 => 12510, 9562 => 12506, 9563 => 12507, 9564 => 12508, 9565 => 12509, 9566 => 12510,
9567 => 12511, 9568 => 12512, 9569 => 12513, 9570 => 12514, 9571 => 12515, 9567 => 12511, 9568 => 12512, 9569 => 12513, 9570 => 12514, 9571 => 12515,
9572 => 12516, 9573 => 12517, 9574 => 12518, 9575 => 12519, 9576 => 12520, 9572 => 12516, 9573 => 12517, 9574 => 12518, 9575 => 12519, 9576 => 12520,
9577 => 12521, 9578 => 12522, 9579 => 12523, 9580 => 12524, 9581 => 12525, 9577 => 12521, 9578 => 12522, 9579 => 12523, 9580 => 12524, 9581 => 12525,
9582 => 12526, 9583 => 12527, 9584 => 12528, 9585 => 12529, 9586 => 12530, 9582 => 12526, 9583 => 12527, 9584 => 12528, 9585 => 12529, 9586 => 12530,
9587 => 12531, 9588 => 12532, 9589 => 12533, 9590 => 12534, 9761 => 913, 9587 => 12531, 9588 => 12532, 9589 => 12533, 9590 => 12534, 9761 => 913,
9762 => 914, 9763 => 915, 9764 => 916, 9765 => 917, 9766 => 918, 9762 => 914, 9763 => 915, 9764 => 916, 9765 => 917, 9766 => 918,
9767 => 919, 9768 => 920, 9769 => 921, 9770 => 922, 9771 => 923, 9767 => 919, 9768 => 920, 9769 => 921, 9770 => 922, 9771 => 923,
9772 => 924, 9773 => 925, 9774 => 926, 9775 => 927, 9776 => 928, 9772 => 924, 9773 => 925, 9774 => 926, 9775 => 927, 9776 => 928,
9777 => 929, 9778 => 931, 9779 => 932, 9780 => 933, 9781 => 934, 9777 => 929, 9778 => 931, 9779 => 932, 9780 => 933, 9781 => 934,
9782 => 935, 9783 => 936, 9784 => 937, 9793 => 945, 9794 => 946, 9782 => 935, 9783 => 936, 9784 => 937, 9793 => 945, 9794 => 946,
9795 => 947, 9796 => 948, 9797 => 949, 9798 => 950, 9799 => 951, 9795 => 947, 9796 => 948, 9797 => 949, 9798 => 950, 9799 => 951,
9800 => 952, 9801 => 953, 9802 => 954, 9803 => 955, 9804 => 956, 9800 => 952, 9801 => 953, 9802 => 954, 9803 => 955, 9804 => 956,
9805 => 957, 9806 => 958, 9807 => 959, 9808 => 960, 9809 => 961, 9805 => 957, 9806 => 958, 9807 => 959, 9808 => 960, 9809 => 961,
9810 => 963, 9811 => 964, 9812 => 965, 9813 => 966, 9814 => 967, 9810 => 963, 9811 => 964, 9812 => 965, 9813 => 966, 9814 => 967,
9815 => 968, 9816 => 969, 10017 => 1040, 10018 => 1041, 10019 => 1042, 9815 => 968, 9816 => 969, 10017 => 1040, 10018 => 1041, 10019 => 1042,
10020 => 1043, 10021 => 1044, 10022 => 1045, 10023 => 1025, 10024 => 1046, 10020 => 1043, 10021 => 1044, 10022 => 1045, 10023 => 1025, 10024 => 1046,
10025 => 1047, 10026 => 1048, 10027 => 1049, 10028 => 1050, 10029 => 1051, 10025 => 1047, 10026 => 1048, 10027 => 1049, 10028 => 1050, 10029 => 1051,
10030 => 1052, 10031 => 1053, 10032 => 1054, 10033 => 1055, 10034 => 1056, 10030 => 1052, 10031 => 1053, 10032 => 1054, 10033 => 1055, 10034 => 1056,
10035 => 1057, 10036 => 1058, 10037 => 1059, 10038 => 1060, 10039 => 1061, 10035 => 1057, 10036 => 1058, 10037 => 1059, 10038 => 1060, 10039 => 1061,
10040 => 1062, 10041 => 1063, 10042 => 1064, 10043 => 1065, 10044 => 1066, 10040 => 1062, 10041 => 1063, 10042 => 1064, 10043 => 1065, 10044 => 1066,
10045 => 1067, 10046 => 1068, 10047 => 1069, 10048 => 1070, 10049 => 1071, 10045 => 1067, 10046 => 1068, 10047 => 1069, 10048 => 1070, 10049 => 1071,
10065 => 1072, 10066 => 1073, 10067 => 1074, 10068 => 1075, 10069 => 1076, 10065 => 1072, 10066 => 1073, 10067 => 1074, 10068 => 1075, 10069 => 1076,
10070 => 1077, 10071 => 1105, 10072 => 1078, 10073 => 1079, 10074 => 1080, 10070 => 1077, 10071 => 1105, 10072 => 1078, 10073 => 1079, 10074 => 1080,
10075 => 1081, 10076 => 1082, 10077 => 1083, 10078 => 1084, 10079 => 1085, 10075 => 1081, 10076 => 1082, 10077 => 1083, 10078 => 1084, 10079 => 1085,
10080 => 1086, 10081 => 1087, 10082 => 1088, 10083 => 1089, 10084 => 1090, 10080 => 1086, 10081 => 1087, 10082 => 1088, 10083 => 1089, 10084 => 1090,
10085 => 1091, 10086 => 1092, 10087 => 1093, 10088 => 1094, 10089 => 1095, 10085 => 1091, 10086 => 1092, 10087 => 1093, 10088 => 1094, 10089 => 1095,
10090 => 1096, 10091 => 1097, 10092 => 1098, 10093 => 1099, 10094 => 1100, 10090 => 1096, 10091 => 1097, 10092 => 1098, 10093 => 1099, 10094 => 1100,
10095 => 1101, 10096 => 1102, 10097 => 1103, 10273 => 257, 10274 => 225, 10095 => 1101, 10096 => 1102, 10097 => 1103, 10273 => 257, 10274 => 225,
10275 => 462, 10276 => 224, 10277 => 275, 10278 => 233, 10279 => 283, 10275 => 462, 10276 => 224, 10277 => 275, 10278 => 233, 10279 => 283,
10280 => 232, 10281 => 299, 10282 => 237, 10283 => 464, 10284 => 236, 10280 => 232, 10281 => 299, 10282 => 237, 10283 => 464, 10284 => 236,
10285 => 333, 10286 => 243, 10287 => 466, 10288 => 242, 10289 => 363, 10285 => 333, 10286 => 243, 10287 => 466, 10288 => 242, 10289 => 363,
10290 => 250, 10291 => 468, 10292 => 249, 10293 => 470, 10294 => 472, 10290 => 250, 10291 => 468, 10292 => 249, 10293 => 470, 10294 => 472,
10295 => 474, 10296 => 476, 10297 => 252, 10298 => 234, 10309 => 12549, 10295 => 474, 10296 => 476, 10297 => 252, 10298 => 234, 10309 => 12549,
10310 => 12550, 10311 => 12551, 10312 => 12552, 10313 => 12553, 10314 => 12554, 10310 => 12550, 10311 => 12551, 10312 => 12552, 10313 => 12553, 10314 => 12554,
10315 => 12555, 10316 => 12556, 10317 => 12557, 10318 => 12558, 10319 => 12559, 10315 => 12555, 10316 => 12556, 10317 => 12557, 10318 => 12558, 10319 => 12559,
10320 => 12560, 10321 => 12561, 10322 => 12562, 10323 => 12563, 10324 => 12564, 10320 => 12560, 10321 => 12561, 10322 => 12562, 10323 => 12563, 10324 => 12564,
10325 => 12565, 10326 => 12566, 10327 => 12567, 10328 => 12568, 10329 => 12569, 10325 => 12565, 10326 => 12566, 10327 => 12567, 10328 => 12568, 10329 => 12569,
10330 => 12570, 10331 => 12571, 10332 => 12572, 10333 => 12573, 10334 => 12574, 10330 => 12570, 10331 => 12571, 10332 => 12572, 10333 => 12573, 10334 => 12574,
10335 => 12575, 10336 => 12576, 10337 => 12577, 10338 => 12578, 10339 => 12579, 10335 => 12575, 10336 => 12576, 10337 => 12577, 10338 => 12578, 10339 => 12579,
10340 => 12580, 10341 => 12581, 10342 => 12582, 10343 => 12583, 10344 => 12584, 10340 => 12580, 10341 => 12581, 10342 => 12582, 10343 => 12583, 10344 => 12584,
10345 => 12585, 10532 => 9472, 10533 => 9473, 10534 => 9474, 10535 => 9475, 10345 => 12585, 10532 => 9472, 10533 => 9473, 10534 => 9474, 10535 => 9475,
10536 => 9476, 10537 => 9477, 10538 => 9478, 10539 => 9479, 10540 => 9480, 10536 => 9476, 10537 => 9477, 10538 => 9478, 10539 => 9479, 10540 => 9480,
10541 => 9481, 10542 => 9482, 10543 => 9483, 10544 => 9484, 10545 => 9485, 10541 => 9481, 10542 => 9482, 10543 => 9483, 10544 => 9484, 10545 => 9485,
10546 => 9486, 10547 => 9487, 10548 => 9488, 10549 => 9489, 10550 => 9490, 10546 => 9486, 10547 => 9487, 10548 => 9488, 10549 => 9489, 10550 => 9490,
10551 => 9491, 10552 => 9492, 10553 => 9493, 10554 => 9494, 10555 => 9495, 10551 => 9491, 10552 => 9492, 10553 => 9493, 10554 => 9494, 10555 => 9495,
10556 => 9496, 10557 => 9497, 10558 => 9498, 10559 => 9499, 10560 => 9500, 10556 => 9496, 10557 => 9497, 10558 => 9498, 10559 => 9499, 10560 => 9500,
10561 => 9501, 10562 => 9502, 10563 => 9503, 10564 => 9504, 10565 => 9505, 10561 => 9501, 10562 => 9502, 10563 => 9503, 10564 => 9504, 10565 => 9505,
10566 => 9506, 10567 => 9507, 10568 => 9508, 10569 => 9509, 10570 => 9510, 10566 => 9506, 10567 => 9507, 10568 => 9508, 10569 => 9509, 10570 => 9510,
10571 => 9511, 10572 => 9512, 10573 => 9513, 10574 => 9514, 10575 => 9515, 10571 => 9511, 10572 => 9512, 10573 => 9513, 10574 => 9514, 10575 => 9515,
10576 => 9516, 10577 => 9517, 10578 => 9518, 10579 => 9519, 10580 => 9520, 10576 => 9516, 10577 => 9517, 10578 => 9518, 10579 => 9519, 10580 => 9520,
10581 => 9521, 10582 => 9522, 10583 => 9523, 10584 => 9524, 10585 => 9525, 10581 => 9521, 10582 => 9522, 10583 => 9523, 10584 => 9524, 10585 => 9525,
10586 => 9526, 10587 => 9527, 10588 => 9528, 10589 => 9529, 10590 => 9530, 10586 => 9526, 10587 => 9527, 10588 => 9528, 10589 => 9529, 10590 => 9530,
10591 => 9531, 10592 => 9532, 10593 => 9533, 10594 => 9534, 10595 => 9535, 10591 => 9531, 10592 => 9532, 10593 => 9533, 10594 => 9534, 10595 => 9535,
10596 => 9536, 10597 => 9537, 10598 => 9538, 10599 => 9539, 10600 => 9540, 10596 => 9536, 10597 => 9537, 10598 => 9538, 10599 => 9539, 10600 => 9540,
10601 => 9541, 10602 => 9542, 10603 => 9543, 10604 => 9544, 10605 => 9545, 10601 => 9541, 10602 => 9542, 10603 => 9543, 10604 => 9544, 10605 => 9545,
10606 => 9546, 10607 => 9547, 12321 => 21834, 12322 => 38463, 12323 => 22467, 10606 => 9546, 10607 => 9547, 12321 => 21834, 12322 => 38463, 12323 => 22467,
12324 => 25384, 12325 => 21710, 12326 => 21769, 12327 => 21696, 12328 => 30353, 12324 => 25384, 12325 => 21710, 12326 => 21769, 12327 => 21696, 12328 => 30353,
12329 => 30284, 12330 => 34108, 12331 => 30702, 12332 => 33406, 12333 => 30861, 12329 => 30284, 12330 => 34108, 12331 => 30702, 12332 => 33406, 12333 => 30861,
12334 => 29233, 12335 => 38552, 12336 => 38797, 12337 => 27688, 12338 => 23433, 12334 => 29233, 12335 => 38552, 12336 => 38797, 12337 => 27688, 12338 => 23433,
12339 => 20474, 12340 => 25353, 12341 => 26263, 12342 => 23736, 12343 => 33018, 12339 => 20474, 12340 => 25353, 12341 => 26263, 12342 => 23736, 12343 => 33018,
12344 => 26696, 12345 => 32942, 12346 => 26114, 12347 => 30414, 12348 => 20985, 12344 => 26696, 12345 => 32942, 12346 => 26114, 12347 => 30414, 12348 => 20985,
12349 => 25942, 12350 => 29100, 12351 => 32753, 12352 => 34948, 12353 => 20658, 12349 => 25942, 12350 => 29100, 12351 => 32753, 12352 => 34948, 12353 => 20658,
12354 => 22885, 12355 => 25034, 12356 => 28595, 12357 => 33453, 12358 => 25420, 12354 => 22885, 12355 => 25034, 12356 => 28595, 12357 => 33453, 12358 => 25420,
12359 => 25170, 12360 => 21485, 12361 => 21543, 12362 => 31494, 12363 => 20843, 12359 => 25170, 12360 => 21485, 12361 => 21543, 12362 => 31494, 12363 => 20843,
12364 => 30116, 12365 => 24052, 12366 => 25300, 12367 => 36299, 12368 => 38774, 12364 => 30116, 12365 => 24052, 12366 => 25300, 12367 => 36299, 12368 => 38774,
12369 => 25226, 12370 => 32793, 12371 => 22365, 12372 => 38712, 12373 => 32610, 12369 => 25226, 12370 => 32793, 12371 => 22365, 12372 => 38712, 12373 => 32610,
12374 => 29240, 12375 => 30333, 12376 => 26575, 12377 => 30334, 12378 => 25670, 12374 => 29240, 12375 => 30333, 12376 => 26575, 12377 => 30334, 12378 => 25670,
12379 => 20336, 12380 => 36133, 12381 => 25308, 12382 => 31255, 12383 => 26001, 12379 => 20336, 12380 => 36133, 12381 => 25308, 12382 => 31255, 12383 => 26001,
12384 => 29677, 12385 => 25644, 12386 => 25203, 12387 => 33324, 12388 => 39041, 12384 => 29677, 12385 => 25644, 12386 => 25203, 12387 => 33324, 12388 => 39041,
12389 => 26495, 12390 => 29256, 12391 => 25198, 12392 => 25292, 12393 => 20276, 12389 => 26495, 12390 => 29256, 12391 => 25198, 12392 => 25292, 12393 => 20276,
12394 => 29923, 12395 => 21322, 12396 => 21150, 12397 => 32458, 12398 => 37030, 12394 => 29923, 12395 => 21322, 12396 => 21150, 12397 => 32458, 12398 => 37030,
12399 => 24110, 12400 => 26758, 12401 => 27036, 12402 => 33152, 12403 => 32465, 12399 => 24110, 12400 => 26758, 12401 => 27036, 12402 => 33152, 12403 => 32465,
12404 => 26834, 12405 => 30917, 12406 => 34444, 12407 => 38225, 12408 => 20621, 12404 => 26834, 12405 => 30917, 12406 => 34444, 12407 => 38225, 12408 => 20621,
12409 => 35876, 12410 => 33502, 12411 => 32990, 12412 => 21253, 12413 => 35090, 12409 => 35876, 12410 => 33502, 12411 => 32990, 12412 => 21253, 12413 => 35090,
12414 => 21093, 12577 => 34180, 12578 => 38649, 12579 => 20445, 12580 => 22561, 12414 => 21093, 12577 => 34180, 12578 => 38649, 12579 => 20445, 12580 => 22561,
12581 => 39281, 12582 => 23453, 12583 => 25265, 12584 => 25253, 12585 => 26292, 12581 => 39281, 12582 => 23453, 12583 => 25265, 12584 => 25253, 12585 => 26292,
12586 => 35961, 12587 => 40077, 12588 => 29190, 12589 => 26479, 12590 => 30865, 12586 => 35961, 12587 => 40077, 12588 => 29190, 12589 => 26479, 12590 => 30865,
12591 => 24754, 12592 => 21329, 12593 => 21271, 12594 => 36744, 12595 => 32972, 12591 => 24754, 12592 => 21329, 12593 => 21271, 12594 => 36744, 12595 => 32972,
12596 => 36125, 12597 => 38049, 12598 => 20493, 12599 => 29384, 12600 => 22791, 12596 => 36125, 12597 => 38049, 12598 => 20493, 12599 => 29384, 12600 => 22791,
12601 => 24811, 12602 => 28953, 12603 => 34987, 12604 => 22868, 12605 => 33519, 12601 => 24811, 12602 => 28953, 12603 => 34987, 12604 => 22868, 12605 => 33519,
12606 => 26412, 12607 => 31528, 12608 => 23849, 12609 => 32503, 12610 => 29997, 12606 => 26412, 12607 => 31528, 12608 => 23849, 12609 => 32503, 12610 => 29997,
12611 => 27893, 12612 => 36454, 12613 => 36856, 12614 => 36924, 12615 => 40763, 12611 => 27893, 12612 => 36454, 12613 => 36856, 12614 => 36924, 12615 => 40763,
12616 => 27604, 12617 => 37145, 12618 => 31508, 12619 => 24444, 12620 => 30887, 12616 => 27604, 12617 => 37145, 12618 => 31508, 12619 => 24444, 12620 => 30887,
12621 => 34006, 12622 => 34109, 12623 => 27605, 12624 => 27609, 12625 => 27606, 12621 => 34006, 12622 => 34109, 12623 => 27605, 12624 => 27609, 12625 => 27606,
12626 => 24065, 12627 => 24199, 12628 => 30201, 12629 => 38381, 12630 => 25949, 12626 => 24065, 12627 => 24199, 12628 => 30201, 12629 => 38381, 12630 => 25949,
12631 => 24330, 12632 => 24517, 12633 => 36767, 12634 => 22721, 12635 => 33218, 12631 => 24330, 12632 => 24517, 12633 => 36767, 12634 => 22721, 12635 => 33218,
12636 => 36991, 12637 => 38491, 12638 => 38829, 12639 => 36793, 12640 => 32534, 12636 => 36991, 12637 => 38491, 12638 => 38829, 12639 => 36793, 12640 => 32534,
12641 => 36140, 12642 => 25153, 12643 => 20415, 12644 => 21464, 12645 => 21342, 12641 => 36140, 12642 => 25153, 12643 => 20415, 12644 => 21464, 12645 => 21342,
12646 => 36776, 12647 => 36777, 12648 => 36779, 12649 => 36941, 12650 => 26631, 12646 => 36776, 12647 => 36777, 12648 => 36779, 12649 => 36941, 12650 => 26631,
12651 => 24426, 12652 => 33176, 12653 => 34920, 12654 => 40150, 12655 => 24971, 12651 => 24426, 12652 => 33176, 12653 => 34920, 12654 => 40150, 12655 => 24971,
12656 => 21035, 12657 => 30250, 12658 => 24428, 12659 => 25996, 12660 => 28626, 12656 => 21035, 12657 => 30250, 12658 => 24428, 12659 => 25996, 12660 => 28626,
12661 => 28392, 12662 => 23486, 12663 => 25672, 12664 => 20853, 12665 => 20912, 12661 => 28392, 12662 => 23486, 12663 => 25672, 12664 => 20853, 12665 => 20912,
12666 => 26564, 12667 => 19993, 12668 => 31177, 12669 => 39292, 12670 => 28851, 12666 => 26564, 12667 => 19993, 12668 => 31177, 12669 => 39292, 12670 => 28851,
12833 => 30149, 12834 => 24182, 12835 => 29627, 12836 => 33760, 12837 => 25773, 12833 => 30149, 12834 => 24182, 12835 => 29627, 12836 => 33760, 12837 => 25773,
12838 => 25320, 12839 => 38069, 12840 => 27874, 12841 => 21338, 12842 => 21187, 12838 => 25320, 12839 => 38069, 12840 => 27874, 12841 => 21338, 12842 => 21187,
12843 => 25615, 12844 => 38082, 12845 => 31636, 12846 => 20271, 12847 => 24091, 12843 => 25615, 12844 => 38082, 12845 => 31636, 12846 => 20271, 12847 => 24091,
12848 => 33334, 12849 => 33046, 12850 => 33162, 12851 => 28196, 12852 => 27850, 12848 => 33334, 12849 => 33046, 12850 => 33162, 12851 => 28196, 12852 => 27850,
12853 => 39539, 12854 => 25429, 12855 => 21340, 12856 => 21754, 12857 => 34917, 12853 => 39539, 12854 => 25429, 12855 => 21340, 12856 => 21754, 12857 => 34917,
12858 => 22496, 12859 => 19981, 12860 => 24067, 12861 => 27493, 12862 => 31807, 12858 => 22496, 12859 => 19981, 12860 => 24067, 12861 => 27493, 12862 => 31807,
12863 => 37096, 12864 => 24598, 12865 => 25830, 12866 => 29468, 12867 => 35009, 12863 => 37096, 12864 => 24598, 12865 => 25830, 12866 => 29468, 12867 => 35009,
12868 => 26448, 12869 => 25165, 12870 => 36130, 12871 => 30572, 12872 => 36393, 12868 => 26448, 12869 => 25165, 12870 => 36130, 12871 => 30572, 12872 => 36393,
12873 => 37319, 12874 => 24425, 12875 => 33756, 12876 => 34081, 12877 => 39184, 12873 => 37319, 12874 => 24425, 12875 => 33756, 12876 => 34081, 12877 => 39184,
12878 => 21442, 12879 => 34453, 12880 => 27531, 12881 => 24813, 12882 => 24808, 12878 => 21442, 12879 => 34453, 12880 => 27531, 12881 => 24813, 12882 => 24808,
12883 => 28799, 12884 => 33485, 12885 => 33329, 12886 => 20179, 12887 => 27815, 12883 => 28799, 12884 => 33485, 12885 => 33329, 12886 => 20179, 12887 => 27815,
12888 => 34255, 12889 => 25805, 12890 => 31961, 12891 => 27133, 12892 => 26361, 12888 => 34255, 12889 => 25805, 12890 => 31961, 12891 => 27133, 12892 => 26361,
12893 => 33609, 12894 => 21397, 12895 => 31574, 12896 => 20391, 12897 => 20876, 12893 => 33609, 12894 => 21397, 12895 => 31574, 12896 => 20391, 12897 => 20876,
12898 => 27979, 12899 => 23618, 12900 => 36461, 12901 => 25554, 12902 => 21449, 12898 => 27979, 12899 => 23618, 12900 => 36461, 12901 => 25554, 12902 => 21449,
12903 => 33580, 12904 => 33590, 12905 => 26597, 12906 => 30900, 12907 => 25661, 12903 => 33580, 12904 => 33590, 12905 => 26597, 12906 => 30900, 12907 => 25661,
12908 => 23519, 12909 => 23700, 12910 => 24046, 12911 => 35815, 12912 => 25286, 12908 => 23519, 12909 => 23700, 12910 => 24046, 12911 => 35815, 12912 => 25286,
12913 => 26612, 12914 => 35962, 12915 => 25600, 12916 => 25530, 12917 => 34633, 12913 => 26612, 12914 => 35962, 12915 => 25600, 12916 => 25530, 12917 => 34633,
12918 => 39307, 12919 => 35863, 12920 => 32544, 12921 => 38130, 12922 => 20135, 12918 => 39307, 12919 => 35863, 12920 => 32544, 12921 => 38130, 12922 => 20135,
12923 => 38416, 12924 => 39076, 12925 => 26124, 12926 => 29462, 13089 => 22330, 12923 => 38416, 12924 => 39076, 12925 => 26124, 12926 => 29462, 13089 => 22330,
13090 => 23581, 13091 => 24120, 13092 => 38271, 13093 => 20607, 13094 => 32928, 13090 => 23581, 13091 => 24120, 13092 => 38271, 13093 => 20607, 13094 => 32928,
13095 => 21378, 13096 => 25950, 13097 => 30021, 13098 => 21809, 13099 => 20513, 13095 => 21378, 13096 => 25950, 13097 => 30021, 13098 => 21809, 13099 => 20513,
13100 => 36229, 13101 => 25220, 13102 => 38046, 13103 => 26397, 13104 => 22066, 13100 => 36229, 13101 => 25220, 13102 => 38046, 13103 => 26397, 13104 => 22066,
13105 => 28526, 13106 => 24034, 13107 => 21557, 13108 => 28818, 13109 => 36710, 13105 => 28526, 13106 => 24034, 13107 => 21557, 13108 => 28818, 13109 => 36710,
13110 => 25199, 13111 => 25764, 13112 => 25507, 13113 => 24443, 13114 => 28552, 13110 => 25199, 13111 => 25764, 13112 => 25507, 13113 => 24443, 13114 => 28552,
13115 => 37108, 13116 => 33251, 13117 => 36784, 13118 => 23576, 13119 => 26216, 13115 => 37108, 13116 => 33251, 13117 => 36784, 13118 => 23576, 13119 => 26216,
13120 => 24561, 13121 => 27785, 13122 => 38472, 13123 => 36225, 13124 => 34924, 13120 => 24561, 13121 => 27785, 13122 => 38472, 13123 => 36225, 13124 => 34924,
13125 => 25745, 13126 => 31216, 13127 => 22478, 13128 => 27225, 13129 => 25104, 13125 => 25745, 13126 => 31216, 13127 => 22478, 13128 => 27225, 13129 => 25104,
13130 => 21576, 13131 => 20056, 13132 => 31243, 13133 => 24809, 13134 => 28548, 13130 => 21576, 13131 => 20056, 13132 => 31243, 13133 => 24809, 13134 => 28548,
13135 => 35802, 13136 => 25215, 13137 => 36894, 13138 => 39563, 13139 => 31204, 13135 => 35802, 13136 => 25215, 13137 => 36894, 13138 => 39563, 13139 => 31204,
13140 => 21507, 13141 => 30196, 13142 => 25345, 13143 => 21273, 13144 => 27744, 13140 => 21507, 13141 => 30196, 13142 => 25345, 13143 => 21273, 13144 => 27744,
13145 => 36831, 13146 => 24347, 13147 => 39536, 13148 => 32827, 13149 => 40831, 13145 => 36831, 13146 => 24347, 13147 => 39536, 13148 => 32827, 13149 => 40831,
13150 => 20360, 13151 => 23610, 13152 => 36196, 13153 => 32709, 13154 => 26021, 13150 => 20360, 13151 => 23610, 13152 => 36196, 13153 => 32709, 13154 => 26021,
13155 => 28861, 13156 => 20805, 13157 => 20914, 13158 => 34411, 13159 => 23815, 13155 => 28861, 13156 => 20805, 13157 => 20914, 13158 => 34411, 13159 => 23815,
13160 => 23456, 13161 => 25277, 13162 => 37228, 13163 => 30068, 13164 => 36364, 13160 => 23456, 13161 => 25277, 13162 => 37228, 13163 => 30068, 13164 => 36364,
13165 => 31264, 13166 => 24833, 13167 => 31609, 13168 => 20167, 13169 => 32504, 13165 => 31264, 13166 => 24833, 13167 => 31609, 13168 => 20167, 13169 => 32504,
13170 => 30597, 13171 => 19985, 13172 => 33261, 13173 => 21021, 13174 => 20986, 13170 => 30597, 13171 => 19985, 13172 => 33261, 13173 => 21021, 13174 => 20986,
13175 => 27249, 13176 => 21416, 13177 => 36487, 13178 => 38148, 13179 => 38607, 13175 => 27249, 13176 => 21416, 13177 => 36487, 13178 => 38148, 13179 => 38607,
13180 => 28353, 13181 => 38500, 13182 => 26970, 13345 => 30784, 13346 => 20648, 13180 => 28353, 13181 => 38500, 13182 => 26970, 13345 => 30784, 13346 => 20648,
13347 => 30679, 13348 => 25616, 13349 => 35302, 13350 => 22788, 13351 => 25571, 13347 => 30679, 13348 => 25616, 13349 => 35302, 13350 => 22788, 13351 => 25571,
13352 => 24029, 13353 => 31359, 13354 => 26941, 13355 => 20256, 13356 => 33337, 13352 => 24029, 13353 => 31359, 13354 => 26941, 13355 => 20256, 13356 => 33337,
13357 => 21912, 13358 => 20018, 13359 => 30126, 13360 => 31383, 13361 => 24162, 13357 => 21912, 13358 => 20018, 13359 => 30126, 13360 => 31383, 13361 => 24162,
13362 => 24202, 13363 => 38383, 13364 => 21019, 13365 => 21561, 13366 => 28810, 13362 => 24202, 13363 => 38383, 13364 => 21019, 13365 => 21561, 13366 => 28810,
13367 => 25462, 13368 => 38180, 13369 => 22402, 13370 => 26149, 13371 => 26943, 13367 => 25462, 13368 => 38180, 13369 => 22402, 13370 => 26149, 13371 => 26943,
13372 => 37255, 13373 => 21767, 13374 => 28147, 13375 => 32431, 13376 => 34850, 13372 => 37255, 13373 => 21767, 13374 => 28147, 13375 => 32431, 13376 => 34850,
13377 => 25139, 13378 => 32496, 13379 => 30133, 13380 => 33576, 13381 => 30913, 13377 => 25139, 13378 => 32496, 13379 => 30133, 13380 => 33576, 13381 => 30913,
13382 => 38604, 13383 => 36766, 13384 => 24904, 13385 => 29943, 13386 => 35789, 13382 => 38604, 13383 => 36766, 13384 => 24904, 13385 => 29943, 13386 => 35789,
13387 => 27492, 13388 => 21050, 13389 => 36176, 13390 => 27425, 13391 => 32874, 13387 => 27492, 13388 => 21050, 13389 => 36176, 13390 => 27425, 13391 => 32874,
13392 => 33905, 13393 => 22257, 13394 => 21254, 13395 => 20174, 13396 => 19995, 13392 => 33905, 13393 => 22257, 13394 => 21254, 13395 => 20174, 13396 => 19995,
13397 => 20945, 13398 => 31895, 13399 => 37259, 13400 => 31751, 13401 => 20419, 13397 => 20945, 13398 => 31895, 13399 => 37259, 13400 => 31751, 13401 => 20419,
13402 => 36479, 13403 => 31713, 13404 => 31388, 13405 => 25703, 13406 => 23828, 13402 => 36479, 13403 => 31713, 13404 => 31388, 13405 => 25703, 13406 => 23828,
13407 => 20652, 13408 => 33030, 13409 => 30209, 13410 => 31929, 13411 => 28140, 13407 => 20652, 13408 => 33030, 13409 => 30209, 13410 => 31929, 13411 => 28140,
13412 => 32736, 13413 => 26449, 13414 => 23384, 13415 => 23544, 13416 => 30923, 13412 => 32736, 13413 => 26449, 13414 => 23384, 13415 => 23544, 13416 => 30923,
13417 => 25774, 13418 => 25619, 13419 => 25514, 13420 => 25387, 13421 => 38169, 13417 => 25774, 13418 => 25619, 13419 => 25514, 13420 => 25387, 13421 => 38169,
13422 => 25645, 13423 => 36798, 13424 => 31572, 13425 => 30249, 13426 => 25171, 13422 => 25645, 13423 => 36798, 13424 => 31572, 13425 => 30249, 13426 => 25171,
13427 => 22823, 13428 => 21574, 13429 => 27513, 13430 => 20643, 13431 => 25140, 13427 => 22823, 13428 => 21574, 13429 => 27513, 13430 => 20643, 13431 => 25140,
13432 => 24102, 13433 => 27526, 13434 => 20195, 13435 => 36151, 13436 => 34955, 13432 => 24102, 13433 => 27526, 13434 => 20195, 13435 => 36151, 13436 => 34955,
13437 => 24453, 13438 => 36910, 13601 => 24608, 13602 => 32829, 13603 => 25285, 13437 => 24453, 13438 => 36910, 13601 => 24608, 13602 => 32829, 13603 => 25285,
13604 => 20025, 13605 => 21333, 13606 => 37112, 13607 => 25528, 13608 => 32966, 13604 => 20025, 13605 => 21333, 13606 => 37112, 13607 => 25528, 13608 => 32966,
13609 => 26086, 13610 => 27694, 13611 => 20294, 13612 => 24814, 13613 => 28129, 13609 => 26086, 13610 => 27694, 13611 => 20294, 13612 => 24814, 13613 => 28129,
13614 => 35806, 13615 => 24377, 13616 => 34507, 13617 => 24403, 13618 => 25377, 13614 => 35806, 13615 => 24377, 13616 => 34507, 13617 => 24403, 13618 => 25377,
13619 => 20826, 13620 => 33633, 13621 => 26723, 13622 => 20992, 13623 => 25443, 13619 => 20826, 13620 => 33633, 13621 => 26723, 13622 => 20992, 13623 => 25443,
13624 => 36424, 13625 => 20498, 13626 => 23707, 13627 => 31095, 13628 => 23548, 13624 => 36424, 13625 => 20498, 13626 => 23707, 13627 => 31095, 13628 => 23548,
13629 => 21040, 13630 => 31291, 13631 => 24764, 13632 => 36947, 13633 => 30423, 13629 => 21040, 13630 => 31291, 13631 => 24764, 13632 => 36947, 13633 => 30423,
13634 => 24503, 13635 => 24471, 13636 => 30340, 13637 => 36460, 13638 => 28783, 13634 => 24503, 13635 => 24471, 13636 => 30340, 13637 => 36460, 13638 => 28783,
13639 => 30331, 13640 => 31561, 13641 => 30634, 13642 => 20979, 13643 => 37011, 13639 => 30331, 13640 => 31561, 13641 => 30634, 13642 => 20979, 13643 => 37011,
13644 => 22564, 13645 => 20302, 13646 => 28404, 13647 => 36842, 13648 => 25932, 13644 => 22564, 13645 => 20302, 13646 => 28404, 13647 => 36842, 13648 => 25932,
13649 => 31515, 13650 => 29380, 13651 => 28068, 13652 => 32735, 13653 => 23265, 13649 => 31515, 13650 => 29380, 13651 => 28068, 13652 => 32735, 13653 => 23265,
13654 => 25269, 13655 => 24213, 13656 => 22320, 13657 => 33922, 13658 => 31532, 13654 => 25269, 13655 => 24213, 13656 => 22320, 13657 => 33922, 13658 => 31532,
13659 => 24093, 13660 => 24351, 13661 => 36882, 13662 => 32532, 13663 => 39072, 13659 => 24093, 13660 => 24351, 13661 => 36882, 13662 => 32532, 13663 => 39072,
13664 => 25474, 13665 => 28359, 13666 => 30872, 13667 => 28857, 13668 => 20856, 13664 => 25474, 13665 => 28359, 13666 => 30872, 13667 => 28857, 13668 => 20856,
13669 => 38747, 13670 => 22443, 13671 => 30005, 13672 => 20291, 13673 => 30008, 13669 => 38747, 13670 => 22443, 13671 => 30005, 13672 => 20291, 13673 => 30008,
13674 => 24215, 13675 => 24806, 13676 => 22880, 13677 => 28096, 13678 => 27583, 13674 => 24215, 13675 => 24806, 13676 => 22880, 13677 => 28096, 13678 => 27583,
13679 => 30857, 13680 => 21500, 13681 => 38613, 13682 => 20939, 13683 => 20993, 13679 => 30857, 13680 => 21500, 13681 => 38613, 13682 => 20939, 13683 => 20993,
13684 => 25481, 13685 => 21514, 13686 => 38035, 13687 => 35843, 13688 => 36300, 13684 => 25481, 13685 => 21514, 13686 => 38035, 13687 => 35843, 13688 => 36300,
13689 => 29241, 13690 => 30879, 13691 => 34678, 13692 => 36845, 13693 => 35853, 13689 => 29241, 13690 => 30879, 13691 => 34678, 13692 => 36845, 13693 => 35853,
13694 => 21472, 13857 => 19969, 13858 => 30447, 13859 => 21486, 13860 => 38025, 13694 => 21472, 13857 => 19969, 13858 => 30447, 13859 => 21486, 13860 => 38025,
13861 => 39030, 13862 => 40718, 13863 => 38189, 13864 => 23450, 13865 => 35746, 13861 => 39030, 13862 => 40718, 13863 => 38189, 13864 => 23450, 13865 => 35746,
13866 => 20002, 13867 => 19996, 13868 => 20908, 13869 => 33891, 13870 => 25026, 13866 => 20002, 13867 => 19996, 13868 => 20908, 13869 => 33891, 13870 => 25026,
13871 => 21160, 13872 => 26635, 13873 => 20375, 13874 => 24683, 13875 => 20923, 13871 => 21160, 13872 => 26635, 13873 => 20375, 13874 => 24683, 13875 => 20923,
13876 => 27934, 13877 => 20828, 13878 => 25238, 13879 => 26007, 13880 => 38497, 13876 => 27934, 13877 => 20828, 13878 => 25238, 13879 => 26007, 13880 => 38497,
13881 => 35910, 13882 => 36887, 13883 => 30168, 13884 => 37117, 13885 => 30563, 13881 => 35910, 13882 => 36887, 13883 => 30168, 13884 => 37117, 13885 => 30563,
13886 => 27602, 13887 => 29322, 13888 => 29420, 13889 => 35835, 13890 => 22581, 13886 => 27602, 13887 => 29322, 13888 => 29420, 13889 => 35835, 13890 => 22581,
13891 => 30585, 13892 => 36172, 13893 => 26460, 13894 => 38208, 13895 => 32922, 13891 => 30585, 13892 => 36172, 13893 => 26460, 13894 => 38208, 13895 => 32922,
13896 => 24230, 13897 => 28193, 13898 => 22930, 13899 => 31471, 13900 => 30701, 13896 => 24230, 13897 => 28193, 13898 => 22930, 13899 => 31471, 13900 => 30701,
13901 => 38203, 13902 => 27573, 13903 => 26029, 13904 => 32526, 13905 => 22534, 13901 => 38203, 13902 => 27573, 13903 => 26029, 13904 => 32526, 13905 => 22534,
13906 => 20817, 13907 => 38431, 13908 => 23545, 13909 => 22697, 13910 => 21544, 13906 => 20817, 13907 => 38431, 13908 => 23545, 13909 => 22697, 13910 => 21544,
13911 => 36466, 13912 => 25958, 13913 => 39039, 13914 => 22244, 13915 => 38045, 13911 => 36466, 13912 => 25958, 13913 => 39039, 13914 => 22244, 13915 => 38045,
13916 => 30462, 13917 => 36929, 13918 => 25479, 13919 => 21702, 13920 => 22810, 13916 => 30462, 13917 => 36929, 13918 => 25479, 13919 => 21702, 13920 => 22810,
13921 => 22842, 13922 => 22427, 13923 => 36530, 13924 => 26421, 13925 => 36346, 13921 => 22842, 13922 => 22427, 13923 => 36530, 13924 => 26421, 13925 => 36346,
13926 => 33333, 13927 => 21057, 13928 => 24816, 13929 => 22549, 13930 => 34558, 13926 => 33333, 13927 => 21057, 13928 => 24816, 13929 => 22549, 13930 => 34558,
13931 => 23784, 13932 => 40517, 13933 => 20420, 13934 => 39069, 13935 => 35769, 13931 => 23784, 13932 => 40517, 13933 => 20420, 13934 => 39069, 13935 => 35769,
13936 => 23077, 13937 => 24694, 13938 => 21380, 13939 => 25212, 13940 => 36943, 13936 => 23077, 13937 => 24694, 13938 => 21380, 13939 => 25212, 13940 => 36943,
13941 => 37122, 13942 => 39295, 13943 => 24681, 13944 => 32780, 13945 => 20799, 13941 => 37122, 13942 => 39295, 13943 => 24681, 13944 => 32780, 13945 => 20799,
13946 => 32819, 13947 => 23572, 13948 => 39285, 13949 => 27953, 13950 => 20108, 13946 => 32819, 13947 => 23572, 13948 => 39285, 13949 => 27953, 13950 => 20108,
14113 => 36144, 14114 => 21457, 14115 => 32602, 14116 => 31567, 14117 => 20240, 14113 => 36144, 14114 => 21457, 14115 => 32602, 14116 => 31567, 14117 => 20240,
14118 => 20047, 14119 => 38400, 14120 => 27861, 14121 => 29648, 14122 => 34281, 14118 => 20047, 14119 => 38400, 14120 => 27861, 14121 => 29648, 14122 => 34281,
14123 => 24070, 14124 => 30058, 14125 => 32763, 14126 => 27146, 14127 => 30718, 14123 => 24070, 14124 => 30058, 14125 => 32763, 14126 => 27146, 14127 => 30718,
14128 => 38034, 14129 => 32321, 14130 => 20961, 14131 => 28902, 14132 => 21453, 14128 => 38034, 14129 => 32321, 14130 => 20961, 14131 => 28902, 14132 => 21453,
14133 => 36820, 14134 => 33539, 14135 => 36137, 14136 => 29359, 14137 => 39277, 14133 => 36820, 14134 => 33539, 14135 => 36137, 14136 => 29359, 14137 => 39277,
14138 => 27867, 14139 => 22346, 14140 => 33459, 14141 => 26041, 14142 => 32938, 14138 => 27867, 14139 => 22346, 14140 => 33459, 14141 => 26041, 14142 => 32938,
14143 => 25151, 14144 => 38450, 14145 => 22952, 14146 => 20223, 14147 => 35775, 14143 => 25151, 14144 => 38450, 14145 => 22952, 14146 => 20223, 14147 => 35775,
14148 => 32442, 14149 => 25918, 14150 => 33778, 14151 => 38750, 14152 => 21857, 14148 => 32442, 14149 => 25918, 14150 => 33778, 14151 => 38750, 14152 => 21857,
14153 => 39134, 14154 => 32933, 14155 => 21290, 14156 => 35837, 14157 => 21536, 14153 => 39134, 14154 => 32933, 14155 => 21290, 14156 => 35837, 14157 => 21536,
14158 => 32954, 14159 => 24223, 14160 => 27832, 14161 => 36153, 14162 => 33452, 14158 => 32954, 14159 => 24223, 14160 => 27832, 14161 => 36153, 14162 => 33452,
14163 => 37210, 14164 => 21545, 14165 => 27675, 14166 => 20998, 14167 => 32439, 14163 => 37210, 14164 => 21545, 14165 => 27675, 14166 => 20998, 14167 => 32439,
14168 => 22367, 14169 => 28954, 14170 => 27774, 14171 => 31881, 14172 => 22859, 14168 => 22367, 14169 => 28954, 14170 => 27774, 14171 => 31881, 14172 => 22859,
14173 => 20221, 14174 => 24575, 14175 => 24868, 14176 => 31914, 14177 => 20016, 14173 => 20221, 14174 => 24575, 14175 => 24868, 14176 => 31914, 14177 => 20016,
14178 => 23553, 14179 => 26539, 14180 => 34562, 14181 => 23792, 14182 => 38155, 14178 => 23553, 14179 => 26539, 14180 => 34562, 14181 => 23792, 14182 => 38155,
14183 => 39118, 14184 => 30127, 14185 => 28925, 14186 => 36898, 14187 => 20911, 14183 => 39118, 14184 => 30127, 14185 => 28925, 14186 => 36898, 14187 => 20911,
14188 => 32541, 14189 => 35773, 14190 => 22857, 14191 => 20964, 14192 => 20315, 14188 => 32541, 14189 => 35773, 14190 => 22857, 14191 => 20964, 14192 => 20315,
14193 => 21542, 14194 => 22827, 14195 => 25975, 14196 => 32932, 14197 => 23413, 14193 => 21542, 14194 => 22827, 14195 => 25975, 14196 => 32932, 14197 => 23413,
14198 => 25206, 14199 => 25282, 14200 => 36752, 14201 => 24133, 14202 => 27679, 14198 => 25206, 14199 => 25282, 14200 => 36752, 14201 => 24133, 14202 => 27679,
14203 => 31526, 14204 => 20239, 14205 => 20440, 14206 => 26381, 14369 => 28014, 14203 => 31526, 14204 => 20239, 14205 => 20440, 14206 => 26381, 14369 => 28014,
14370 => 28074, 14371 => 31119, 14372 => 34993, 14373 => 24343, 14374 => 29995, 14370 => 28074, 14371 => 31119, 14372 => 34993, 14373 => 24343, 14374 => 29995,
14375 => 25242, 14376 => 36741, 14377 => 20463, 14378 => 37340, 14379 => 26023, 14375 => 25242, 14376 => 36741, 14377 => 20463, 14378 => 37340, 14379 => 26023,
14380 => 33071, 14381 => 33105, 14382 => 24220, 14383 => 33104, 14384 => 36212, 14380 => 33071, 14381 => 33105, 14382 => 24220, 14383 => 33104, 14384 => 36212,
14385 => 21103, 14386 => 35206, 14387 => 36171, 14388 => 22797, 14389 => 20613, 14385 => 21103, 14386 => 35206, 14387 => 36171, 14388 => 22797, 14389 => 20613,
14390 => 20184, 14391 => 38428, 14392 => 29238, 14393 => 33145, 14394 => 36127, 14390 => 20184, 14391 => 38428, 14392 => 29238, 14393 => 33145, 14394 => 36127,
14395 => 23500, 14396 => 35747, 14397 => 38468, 14398 => 22919, 14399 => 32538, 14395 => 23500, 14396 => 35747, 14397 => 38468, 14398 => 22919, 14399 => 32538,
14400 => 21648, 14401 => 22134, 14402 => 22030, 14403 => 35813, 14404 => 25913, 14400 => 21648, 14401 => 22134, 14402 => 22030, 14403 => 35813, 14404 => 25913,
14405 => 27010, 14406 => 38041, 14407 => 30422, 14408 => 28297, 14409 => 24178, 14405 => 27010, 14406 => 38041, 14407 => 30422, 14408 => 28297, 14409 => 24178,
14410 => 29976, 14411 => 26438, 14412 => 26577, 14413 => 31487, 14414 => 32925, 14410 => 29976, 14411 => 26438, 14412 => 26577, 14413 => 31487, 14414 => 32925,
14415 => 36214, 14416 => 24863, 14417 => 31174, 14418 => 25954, 14419 => 36195, 14415 => 36214, 14416 => 24863, 14417 => 31174, 14418 => 25954, 14419 => 36195,
14420 => 20872, 14421 => 21018, 14422 => 38050, 14423 => 32568, 14424 => 32923, 14420 => 20872, 14421 => 21018, 14422 => 38050, 14423 => 32568, 14424 => 32923,
14425 => 32434, 14426 => 23703, 14427 => 28207, 14428 => 26464, 14429 => 31705, 14425 => 32434, 14426 => 23703, 14427 => 28207, 14428 => 26464, 14429 => 31705,
14430 => 30347, 14431 => 39640, 14432 => 33167, 14433 => 32660, 14434 => 31957, 14430 => 30347, 14431 => 39640, 14432 => 33167, 14433 => 32660, 14434 => 31957,
14435 => 25630, 14436 => 38224, 14437 => 31295, 14438 => 21578, 14439 => 21733, 14435 => 25630, 14436 => 38224, 14437 => 31295, 14438 => 21578, 14439 => 21733,
14440 => 27468, 14441 => 25601, 14442 => 25096, 14443 => 40509, 14444 => 33011, 14440 => 27468, 14441 => 25601, 14442 => 25096, 14443 => 40509, 14444 => 33011,
14445 => 30105, 14446 => 21106, 14447 => 38761, 14448 => 33883, 14449 => 26684, 14445 => 30105, 14446 => 21106, 14447 => 38761, 14448 => 33883, 14449 => 26684,
14450 => 34532, 14451 => 38401, 14452 => 38548, 14453 => 38124, 14454 => 20010, 14450 => 34532, 14451 => 38401, 14452 => 38548, 14453 => 38124, 14454 => 20010,
14455 => 21508, 14456 => 32473, 14457 => 26681, 14458 => 36319, 14459 => 32789, 14455 => 21508, 14456 => 32473, 14457 => 26681, 14458 => 36319, 14459 => 32789,
14460 => 26356, 14461 => 24218, 14462 => 32697, 14625 => 22466, 14626 => 32831, 14460 => 26356, 14461 => 24218, 14462 => 32697, 14625 => 22466, 14626 => 32831,
14627 => 26775, 14628 => 24037, 14629 => 25915, 14630 => 21151, 14631 => 24685, 14627 => 26775, 14628 => 24037, 14629 => 25915, 14630 => 21151, 14631 => 24685,
14632 => 40858, 14633 => 20379, 14634 => 36524, 14635 => 20844, 14636 => 23467, 14632 => 40858, 14633 => 20379, 14634 => 36524, 14635 => 20844, 14636 => 23467,
14637 => 24339, 14638 => 24041, 14639 => 27742, 14640 => 25329, 14641 => 36129, 14637 => 24339, 14638 => 24041, 14639 => 27742, 14640 => 25329, 14641 => 36129,
14642 => 20849, 14643 => 38057, 14644 => 21246, 14645 => 27807, 14646 => 33503, 14642 => 20849, 14643 => 38057, 14644 => 21246, 14645 => 27807, 14646 => 33503,
14647 => 29399, 14648 => 22434, 14649 => 26500, 14650 => 36141, 14651 => 22815, 14647 => 29399, 14648 => 22434, 14649 => 26500, 14650 => 36141, 14651 => 22815,
14652 => 36764, 14653 => 33735, 14654 => 21653, 14655 => 31629, 14656 => 20272, 14652 => 36764, 14653 => 33735, 14654 => 21653, 14655 => 31629, 14656 => 20272,
14657 => 27837, 14658 => 23396, 14659 => 22993, 14660 => 40723, 14661 => 21476, 14657 => 27837, 14658 => 23396, 14659 => 22993, 14660 => 40723, 14661 => 21476,
14662 => 34506, 14663 => 39592, 14664 => 35895, 14665 => 32929, 14666 => 25925, 14662 => 34506, 14663 => 39592, 14664 => 35895, 14665 => 32929, 14666 => 25925,
14667 => 39038, 14668 => 22266, 14669 => 38599, 14670 => 21038, 14671 => 29916, 14667 => 39038, 14668 => 22266, 14669 => 38599, 14670 => 21038, 14671 => 29916,
14672 => 21072, 14673 => 23521, 14674 => 25346, 14675 => 35074, 14676 => 20054, 14672 => 21072, 14673 => 23521, 14674 => 25346, 14675 => 35074, 14676 => 20054,
14677 => 25296, 14678 => 24618, 14679 => 26874, 14680 => 20851, 14681 => 23448, 14677 => 25296, 14678 => 24618, 14679 => 26874, 14680 => 20851, 14681 => 23448,
14682 => 20896, 14683 => 35266, 14684 => 31649, 14685 => 39302, 14686 => 32592, 14682 => 20896, 14683 => 35266, 14684 => 31649, 14685 => 39302, 14686 => 32592,
14687 => 24815, 14688 => 28748, 14689 => 36143, 14690 => 20809, 14691 => 24191, 14687 => 24815, 14688 => 28748, 14689 => 36143, 14690 => 20809, 14691 => 24191,
14692 => 36891, 14693 => 29808, 14694 => 35268, 14695 => 22317, 14696 => 30789, 14692 => 36891, 14693 => 29808, 14694 => 35268, 14695 => 22317, 14696 => 30789,
14697 => 24402, 14698 => 40863, 14699 => 38394, 14700 => 36712, 14701 => 39740, 14697 => 24402, 14698 => 40863, 14699 => 38394, 14700 => 36712, 14701 => 39740,
14702 => 35809, 14703 => 30328, 14704 => 26690, 14705 => 26588, 14706 => 36330, 14702 => 35809, 14703 => 30328, 14704 => 26690, 14705 => 26588, 14706 => 36330,
14707 => 36149, 14708 => 21053, 14709 => 36746, 14710 => 28378, 14711 => 26829, 14707 => 36149, 14708 => 21053, 14709 => 36746, 14710 => 28378, 14711 => 26829,
14712 => 38149, 14713 => 37101, 14714 => 22269, 14715 => 26524, 14716 => 35065, 14712 => 38149, 14713 => 37101, 14714 => 22269, 14715 => 26524, 14716 => 35065,
14717 => 36807, 14718 => 21704, 14881 => 39608, 14882 => 23401, 14883 => 28023, 14717 => 36807, 14718 => 21704, 14881 => 39608, 14882 => 23401, 14883 => 28023,
14884 => 27686, 14885 => 20133, 14886 => 23475, 14887 => 39559, 14888 => 37219, 14884 => 27686, 14885 => 20133, 14886 => 23475, 14887 => 39559, 14888 => 37219,
14889 => 25000, 14890 => 37039, 14891 => 38889, 14892 => 21547, 14893 => 28085, 14889 => 25000, 14890 => 37039, 14891 => 38889, 14892 => 21547, 14893 => 28085,
14894 => 23506, 14895 => 20989, 14896 => 21898, 14897 => 32597, 14898 => 32752, 14894 => 23506, 14895 => 20989, 14896 => 21898, 14897 => 32597, 14898 => 32752,
14899 => 25788, 14900 => 25421, 14901 => 26097, 14902 => 25022, 14903 => 24717, 14899 => 25788, 14900 => 25421, 14901 => 26097, 14902 => 25022, 14903 => 24717,
14904 => 28938, 14905 => 27735, 14906 => 27721, 14907 => 22831, 14908 => 26477, 14904 => 28938, 14905 => 27735, 14906 => 27721, 14907 => 22831, 14908 => 26477,
14909 => 33322, 14910 => 22741, 14911 => 22158, 14912 => 35946, 14913 => 27627, 14909 => 33322, 14910 => 22741, 14911 => 22158, 14912 => 35946, 14913 => 27627,
14914 => 37085, 14915 => 22909, 14916 => 32791, 14917 => 21495, 14918 => 28009, 14914 => 37085, 14915 => 22909, 14916 => 32791, 14917 => 21495, 14918 => 28009,
14919 => 21621, 14920 => 21917, 14921 => 33655, 14922 => 33743, 14923 => 26680, 14919 => 21621, 14920 => 21917, 14921 => 33655, 14922 => 33743, 14923 => 26680,
14924 => 31166, 14925 => 21644, 14926 => 20309, 14927 => 21512, 14928 => 30418, 14924 => 31166, 14925 => 21644, 14926 => 20309, 14927 => 21512, 14928 => 30418,
14929 => 35977, 14930 => 38402, 14931 => 27827, 14932 => 28088, 14933 => 36203, 14929 => 35977, 14930 => 38402, 14931 => 27827, 14932 => 28088, 14933 => 36203,
14934 => 35088, 14935 => 40548, 14936 => 36154, 14937 => 22079, 14938 => 40657, 14934 => 35088, 14935 => 40548, 14936 => 36154, 14937 => 22079, 14938 => 40657,
14939 => 30165, 14940 => 24456, 14941 => 29408, 14942 => 24680, 14943 => 21756, 14939 => 30165, 14940 => 24456, 14941 => 29408, 14942 => 24680, 14943 => 21756,
14944 => 20136, 14945 => 27178, 14946 => 34913, 14947 => 24658, 14948 => 36720, 14944 => 20136, 14945 => 27178, 14946 => 34913, 14947 => 24658, 14948 => 36720,
14949 => 21700, 14950 => 28888, 14951 => 34425, 14952 => 40511, 14953 => 27946, 14949 => 21700, 14950 => 28888, 14951 => 34425, 14952 => 40511, 14953 => 27946,
14954 => 23439, 14955 => 24344, 14956 => 32418, 14957 => 21897, 14958 => 20399, 14954 => 23439, 14955 => 24344, 14956 => 32418, 14957 => 21897, 14958 => 20399,
14959 => 29492, 14960 => 21564, 14961 => 21402, 14962 => 20505, 14963 => 21518, 14959 => 29492, 14960 => 21564, 14961 => 21402, 14962 => 20505, 14963 => 21518,
14964 => 21628, 14965 => 20046, 14966 => 24573, 14967 => 29786, 14968 => 22774, 14964 => 21628, 14965 => 20046, 14966 => 24573, 14967 => 29786, 14968 => 22774,
14969 => 33899, 14970 => 32993, 14971 => 34676, 14972 => 29392, 14973 => 31946, 14969 => 33899, 14970 => 32993, 14971 => 34676, 14972 => 29392, 14973 => 31946,
14974 => 28246, 15137 => 24359, 15138 => 34382, 15139 => 21804, 15140 => 25252, 14974 => 28246, 15137 => 24359, 15138 => 34382, 15139 => 21804, 15140 => 25252,
15141 => 20114, 15142 => 27818, 15143 => 25143, 15144 => 33457, 15145 => 21719, 15141 => 20114, 15142 => 27818, 15143 => 25143, 15144 => 33457, 15145 => 21719,
15146 => 21326, 15147 => 29502, 15148 => 28369, 15149 => 30011, 15150 => 21010, 15146 => 21326, 15147 => 29502, 15148 => 28369, 15149 => 30011, 15150 => 21010,
15151 => 21270, 15152 => 35805, 15153 => 27088, 15154 => 24458, 15155 => 24576, 15151 => 21270, 15152 => 35805, 15153 => 27088, 15154 => 24458, 15155 => 24576,
15156 => 28142, 15157 => 22351, 15158 => 27426, 15159 => 29615, 15160 => 26707, 15156 => 28142, 15157 => 22351, 15158 => 27426, 15159 => 29615, 15160 => 26707,
15161 => 36824, 15162 => 32531, 15163 => 25442, 15164 => 24739, 15165 => 21796, 15161 => 36824, 15162 => 32531, 15163 => 25442, 15164 => 24739, 15165 => 21796,
15166 => 30186, 15167 => 35938, 15168 => 28949, 15169 => 28067, 15170 => 23462, 15166 => 30186, 15167 => 35938, 15168 => 28949, 15169 => 28067, 15170 => 23462,
15171 => 24187, 15172 => 33618, 15173 => 24908, 15174 => 40644, 15175 => 30970, 15171 => 24187, 15172 => 33618, 15173 => 24908, 15174 => 40644, 15175 => 30970,
15176 => 34647, 15177 => 31783, 15178 => 30343, 15179 => 20976, 15180 => 24822, 15176 => 34647, 15177 => 31783, 15178 => 30343, 15179 => 20976, 15180 => 24822,
15181 => 29004, 15182 => 26179, 15183 => 24140, 15184 => 24653, 15185 => 35854, 15181 => 29004, 15182 => 26179, 15183 => 24140, 15184 => 24653, 15185 => 35854,
15186 => 28784, 15187 => 25381, 15188 => 36745, 15189 => 24509, 15190 => 24674, 15186 => 28784, 15187 => 25381, 15188 => 36745, 15189 => 24509, 15190 => 24674,
15191 => 34516, 15192 => 22238, 15193 => 27585, 15194 => 24724, 15195 => 24935, 15191 => 34516, 15192 => 22238, 15193 => 27585, 15194 => 24724, 15195 => 24935,
15196 => 21321, 15197 => 24800, 15198 => 26214, 15199 => 36159, 15200 => 31229, 15196 => 21321, 15197 => 24800, 15198 => 26214, 15199 => 36159, 15200 => 31229,
15201 => 20250, 15202 => 28905, 15203 => 27719, 15204 => 35763, 15205 => 35826, 15201 => 20250, 15202 => 28905, 15203 => 27719, 15204 => 35763, 15205 => 35826,
15206 => 32472, 15207 => 33636, 15208 => 26127, 15209 => 23130, 15210 => 39746, 15206 => 32472, 15207 => 33636, 15208 => 26127, 15209 => 23130, 15210 => 39746,
15211 => 27985, 15212 => 28151, 15213 => 35905, 15214 => 27963, 15215 => 20249, 15211 => 27985, 15212 => 28151, 15213 => 35905, 15214 => 27963, 15215 => 20249,
15216 => 28779, 15217 => 33719, 15218 => 25110, 15219 => 24785, 15220 => 38669, 15216 => 28779, 15217 => 33719, 15218 => 25110, 15219 => 24785, 15220 => 38669,
15221 => 36135, 15222 => 31096, 15223 => 20987, 15224 => 22334, 15225 => 22522, 15221 => 36135, 15222 => 31096, 15223 => 20987, 15224 => 22334, 15225 => 22522,
15226 => 26426, 15227 => 30072, 15228 => 31293, 15229 => 31215, 15230 => 31637, 15226 => 26426, 15227 => 30072, 15228 => 31293, 15229 => 31215, 15230 => 31637,
15393 => 32908, 15394 => 39269, 15395 => 36857, 15396 => 28608, 15397 => 35749, 15393 => 32908, 15394 => 39269, 15395 => 36857, 15396 => 28608, 15397 => 35749,
15398 => 40481, 15399 => 23020, 15400 => 32489, 15401 => 32521, 15402 => 21513, 15398 => 40481, 15399 => 23020, 15400 => 32489, 15401 => 32521, 15402 => 21513,
15403 => 26497, 15404 => 26840, 15405 => 36753, 15406 => 31821, 15407 => 38598, 15403 => 26497, 15404 => 26840, 15405 => 36753, 15406 => 31821, 15407 => 38598,
15408 => 21450, 15409 => 24613, 15410 => 30142, 15411 => 27762, 15412 => 21363, 15408 => 21450, 15409 => 24613, 15410 => 30142, 15411 => 27762, 15412 => 21363,
15413 => 23241, 15414 => 32423, 15415 => 25380, 15416 => 20960, 15417 => 33034, 15413 => 23241, 15414 => 32423, 15415 => 25380, 15416 => 20960, 15417 => 33034,
15418 => 24049, 15419 => 34015, 15420 => 25216, 15421 => 20864, 15422 => 23395, 15418 => 24049, 15419 => 34015, 15420 => 25216, 15421 => 20864, 15422 => 23395,
15423 => 20238, 15424 => 31085, 15425 => 21058, 15426 => 24760, 15427 => 27982, 15423 => 20238, 15424 => 31085, 15425 => 21058, 15426 => 24760, 15427 => 27982,
15428 => 23492, 15429 => 23490, 15430 => 35745, 15431 => 35760, 15432 => 26082, 15428 => 23492, 15429 => 23490, 15430 => 35745, 15431 => 35760, 15432 => 26082,
15433 => 24524, 15434 => 38469, 15435 => 22931, 15436 => 32487, 15437 => 32426, 15433 => 24524, 15434 => 38469, 15435 => 22931, 15436 => 32487, 15437 => 32426,
15438 => 22025, 15439 => 26551, 15440 => 22841, 15441 => 20339, 15442 => 23478, 15438 => 22025, 15439 => 26551, 15440 => 22841, 15441 => 20339, 15442 => 23478,
15443 => 21152, 15444 => 33626, 15445 => 39050, 15446 => 36158, 15447 => 30002, 15443 => 21152, 15444 => 33626, 15445 => 39050, 15446 => 36158, 15447 => 30002,
15448 => 38078, 15449 => 20551, 15450 => 31292, 15451 => 20215, 15452 => 26550, 15448 => 38078, 15449 => 20551, 15450 => 31292, 15451 => 20215, 15452 => 26550,
15453 => 39550, 15454 => 23233, 15455 => 27516, 15456 => 30417, 15457 => 22362, 15453 => 39550, 15454 => 23233, 15455 => 27516, 15456 => 30417, 15457 => 22362,
15458 => 23574, 15459 => 31546, 15460 => 38388, 15461 => 29006, 15462 => 20860, 15458 => 23574, 15459 => 31546, 15460 => 38388, 15461 => 29006, 15462 => 20860,
15463 => 32937, 15464 => 33392, 15465 => 22904, 15466 => 32516, 15467 => 33575, 15463 => 32937, 15464 => 33392, 15465 => 22904, 15466 => 32516, 15467 => 33575,
15468 => 26816, 15469 => 26604, 15470 => 30897, 15471 => 30839, 15472 => 25315, 15468 => 26816, 15469 => 26604, 15470 => 30897, 15471 => 30839, 15472 => 25315,
15473 => 25441, 15474 => 31616, 15475 => 20461, 15476 => 21098, 15477 => 20943, 15473 => 25441, 15474 => 31616, 15475 => 20461, 15476 => 21098, 15477 => 20943,
15478 => 33616, 15479 => 27099, 15480 => 37492, 15481 => 36341, 15482 => 36145, 15478 => 33616, 15479 => 27099, 15480 => 37492, 15481 => 36341, 15482 => 36145,
15483 => 35265, 15484 => 38190, 15485 => 31661, 15486 => 20214, 15649 => 20581, 15483 => 35265, 15484 => 38190, 15485 => 31661, 15486 => 20214, 15649 => 20581,
15650 => 33328, 15651 => 21073, 15652 => 39279, 15653 => 28176, 15654 => 28293, 15650 => 33328, 15651 => 21073, 15652 => 39279, 15653 => 28176, 15654 => 28293,
15655 => 28071, 15656 => 24314, 15657 => 20725, 15658 => 23004, 15659 => 23558, 15655 => 28071, 15656 => 24314, 15657 => 20725, 15658 => 23004, 15659 => 23558,
15660 => 27974, 15661 => 27743, 15662 => 30086, 15663 => 33931, 15664 => 26728, 15660 => 27974, 15661 => 27743, 15662 => 30086, 15663 => 33931, 15664 => 26728,
15665 => 22870, 15666 => 35762, 15667 => 21280, 15668 => 37233, 15669 => 38477, 15665 => 22870, 15666 => 35762, 15667 => 21280, 15668 => 37233, 15669 => 38477,
15670 => 34121, 15671 => 26898, 15672 => 30977, 15673 => 28966, 15674 => 33014, 15670 => 34121, 15671 => 26898, 15672 => 30977, 15673 => 28966, 15674 => 33014,
15675 => 20132, 15676 => 37066, 15677 => 27975, 15678 => 39556, 15679 => 23047, 15675 => 20132, 15676 => 37066, 15677 => 27975, 15678 => 39556, 15679 => 23047,
15680 => 22204, 15681 => 25605, 15682 => 38128, 15683 => 30699, 15684 => 20389, 15680 => 22204, 15681 => 25605, 15682 => 38128, 15683 => 30699, 15684 => 20389,
15685 => 33050, 15686 => 29409, 15687 => 35282, 15688 => 39290, 15689 => 32564, 15685 => 33050, 15686 => 29409, 15687 => 35282, 15688 => 39290, 15689 => 32564,
15690 => 32478, 15691 => 21119, 15692 => 25945, 15693 => 37237, 15694 => 36735, 15690 => 32478, 15691 => 21119, 15692 => 25945, 15693 => 37237, 15694 => 36735,
15695 => 36739, 15696 => 21483, 15697 => 31382, 15698 => 25581, 15699 => 25509, 15695 => 36739, 15696 => 21483, 15697 => 31382, 15698 => 25581, 15699 => 25509,
15700 => 30342, 15701 => 31224, 15702 => 34903, 15703 => 38454, 15704 => 25130, 15700 => 30342, 15701 => 31224, 15702 => 34903, 15703 => 38454, 15704 => 25130,
15705 => 21163, 15706 => 33410, 15707 => 26708, 15708 => 26480, 15709 => 25463, 15705 => 21163, 15706 => 33410, 15707 => 26708, 15708 => 26480, 15709 => 25463,
15710 => 30571, 15711 => 31469, 15712 => 27905, 15713 => 32467, 15714 => 35299, 15710 => 30571, 15711 => 31469, 15712 => 27905, 15713 => 32467, 15714 => 35299,
15715 => 22992, 15716 => 25106, 15717 => 34249, 15718 => 33445, 15719 => 30028, 15715 => 22992, 15716 => 25106, 15717 => 34249, 15718 => 33445, 15719 => 30028,
15720 => 20511, 15721 => 20171, 15722 => 30117, 15723 => 35819, 15724 => 23626, 15720 => 20511, 15721 => 20171, 15722 => 30117, 15723 => 35819, 15724 => 23626,
15725 => 24062, 15726 => 31563, 15727 => 26020, 15728 => 37329, 15729 => 20170, 15725 => 24062, 15726 => 31563, 15727 => 26020, 15728 => 37329, 15729 => 20170,
15730 => 27941, 15731 => 35167, 15732 => 32039, 15733 => 38182, 15734 => 20165, 15730 => 27941, 15731 => 35167, 15732 => 32039, 15733 => 38182, 15734 => 20165,
15735 => 35880, 15736 => 36827, 15737 => 38771, 15738 => 26187, 15739 => 31105, 15735 => 35880, 15736 => 36827, 15737 => 38771, 15738 => 26187, 15739 => 31105,
15740 => 36817, 15741 => 28908, 15742 => 28024, 15905 => 23613, 15906 => 21170, 15740 => 36817, 15741 => 28908, 15742 => 28024, 15905 => 23613, 15906 => 21170,
15907 => 33606, 15908 => 20834, 15909 => 33550, 15910 => 30555, 15911 => 26230, 15907 => 33606, 15908 => 20834, 15909 => 33550, 15910 => 30555, 15911 => 26230,
15912 => 40120, 15913 => 20140, 15914 => 24778, 15915 => 31934, 15916 => 31923, 15912 => 40120, 15913 => 20140, 15914 => 24778, 15915 => 31934, 15916 => 31923,
15917 => 32463, 15918 => 20117, 15919 => 35686, 15920 => 26223, 15921 => 39048, 15917 => 32463, 15918 => 20117, 15919 => 35686, 15920 => 26223, 15921 => 39048,
15922 => 38745, 15923 => 22659, 15924 => 25964, 15925 => 38236, 15926 => 24452, 15922 => 38745, 15923 => 22659, 15924 => 25964, 15925 => 38236, 15926 => 24452,
15927 => 30153, 15928 => 38742, 15929 => 31455, 15930 => 31454, 15931 => 20928, 15927 => 30153, 15928 => 38742, 15929 => 31455, 15930 => 31454, 15931 => 20928,
15932 => 28847, 15933 => 31384, 15934 => 25578, 15935 => 31350, 15936 => 32416, 15932 => 28847, 15933 => 31384, 15934 => 25578, 15935 => 31350, 15936 => 32416,
15937 => 29590, 15938 => 38893, 15939 => 20037, 15940 => 28792, 15941 => 20061, 15937 => 29590, 15938 => 38893, 15939 => 20037, 15940 => 28792, 15941 => 20061,
15942 => 37202, 15943 => 21417, 15944 => 25937, 15945 => 26087, 15946 => 33276, 15942 => 37202, 15943 => 21417, 15944 => 25937, 15945 => 26087, 15946 => 33276,
15947 => 33285, 15948 => 21646, 15949 => 23601, 15950 => 30106, 15951 => 38816, 15947 => 33285, 15948 => 21646, 15949 => 23601, 15950 => 30106, 15951 => 38816,
15952 => 25304, 15953 => 29401, 15954 => 30141, 15955 => 23621, 15956 => 39545, 15952 => 25304, 15953 => 29401, 15954 => 30141, 15955 => 23621, 15956 => 39545,
15957 => 33738, 15958 => 23616, 15959 => 21632, 15960 => 30697, 15961 => 20030, 15957 => 33738, 15958 => 23616, 15959 => 21632, 15960 => 30697, 15961 => 20030,
15962 => 27822, 15963 => 32858, 15964 => 25298, 15965 => 25454, 15966 => 24040, 15962 => 27822, 15963 => 32858, 15964 => 25298, 15965 => 25454, 15966 => 24040,
15967 => 20855, 15968 => 36317, 15969 => 36382, 15970 => 38191, 15971 => 20465, 15967 => 20855, 15968 => 36317, 15969 => 36382, 15970 => 38191, 15971 => 20465,
15972 => 21477, 15973 => 24807, 15974 => 28844, 15975 => 21095, 15976 => 25424, 15972 => 21477, 15973 => 24807, 15974 => 28844, 15975 => 21095, 15976 => 25424,
15977 => 40515, 15978 => 23071, 15979 => 20518, 15980 => 30519, 15981 => 21367, 15977 => 40515, 15978 => 23071, 15979 => 20518, 15980 => 30519, 15981 => 21367,
15982 => 32482, 15983 => 25733, 15984 => 25899, 15985 => 25225, 15986 => 25496, 15982 => 32482, 15983 => 25733, 15984 => 25899, 15985 => 25225, 15986 => 25496,
15987 => 20500, 15988 => 29237, 15989 => 35273, 15990 => 20915, 15991 => 35776, 15987 => 20500, 15988 => 29237, 15989 => 35273, 15990 => 20915, 15991 => 35776,
15992 => 32477, 15993 => 22343, 15994 => 33740, 15995 => 38055, 15996 => 20891, 15992 => 32477, 15993 => 22343, 15994 => 33740, 15995 => 38055, 15996 => 20891,
15997 => 21531, 15998 => 23803, 16161 => 20426, 16162 => 31459, 16163 => 27994, 15997 => 21531, 15998 => 23803, 16161 => 20426, 16162 => 31459, 16163 => 27994,
16164 => 37089, 16165 => 39567, 16166 => 21888, 16167 => 21654, 16168 => 21345, 16164 => 37089, 16165 => 39567, 16166 => 21888, 16167 => 21654, 16168 => 21345,
16169 => 21679, 16170 => 24320, 16171 => 25577, 16172 => 26999, 16173 => 20975, 16169 => 21679, 16170 => 24320, 16171 => 25577, 16172 => 26999, 16173 => 20975,
16174 => 24936, 16175 => 21002, 16176 => 22570, 16177 => 21208, 16178 => 22350, 16174 => 24936, 16175 => 21002, 16176 => 22570, 16177 => 21208, 16178 => 22350,
16179 => 30733, 16180 => 30475, 16181 => 24247, 16182 => 24951, 16183 => 31968, 16179 => 30733, 16180 => 30475, 16181 => 24247, 16182 => 24951, 16183 => 31968,
16184 => 25179, 16185 => 25239, 16186 => 20130, 16187 => 28821, 16188 => 32771, 16184 => 25179, 16185 => 25239, 16186 => 20130, 16187 => 28821, 16188 => 32771,
16189 => 25335, 16190 => 28900, 16191 => 38752, 16192 => 22391, 16193 => 33499, 16189 => 25335, 16190 => 28900, 16191 => 38752, 16192 => 22391, 16193 => 33499,
16194 => 26607, 16195 => 26869, 16196 => 30933, 16197 => 39063, 16198 => 31185, 16194 => 26607, 16195 => 26869, 16196 => 30933, 16197 => 39063, 16198 => 31185,
16199 => 22771, 16200 => 21683, 16201 => 21487, 16202 => 28212, 16203 => 20811, 16199 => 22771, 16200 => 21683, 16201 => 21487, 16202 => 28212, 16203 => 20811,
16204 => 21051, 16205 => 23458, 16206 => 35838, 16207 => 32943, 16208 => 21827, 16204 => 21051, 16205 => 23458, 16206 => 35838, 16207 => 32943, 16208 => 21827,
16209 => 22438, 16210 => 24691, 16211 => 22353, 16212 => 21549, 16213 => 31354, 16209 => 22438, 16210 => 24691, 16211 => 22353, 16212 => 21549, 16213 => 31354,
16214 => 24656, 16215 => 23380, 16216 => 25511, 16217 => 25248, 16218 => 21475, 16214 => 24656, 16215 => 23380, 16216 => 25511, 16217 => 25248, 16218 => 21475,
16219 => 25187, 16220 => 23495, 16221 => 26543, 16222 => 21741, 16223 => 31391, 16219 => 25187, 16220 => 23495, 16221 => 26543, 16222 => 21741, 16223 => 31391,
16224 => 33510, 16225 => 37239, 16226 => 24211, 16227 => 35044, 16228 => 22840, 16224 => 33510, 16225 => 37239, 16226 => 24211, 16227 => 35044, 16228 => 22840,
16229 => 22446, 16230 => 25358, 16231 => 36328, 16232 => 33007, 16233 => 22359, 16229 => 22446, 16230 => 25358, 16231 => 36328, 16232 => 33007, 16233 => 22359,
16234 => 31607, 16235 => 20393, 16236 => 24555, 16237 => 23485, 16238 => 27454, 16234 => 31607, 16235 => 20393, 16236 => 24555, 16237 => 23485, 16238 => 27454,
16239 => 21281, 16240 => 31568, 16241 => 29378, 16242 => 26694, 16243 => 30719, 16239 => 21281, 16240 => 31568, 16241 => 29378, 16242 => 26694, 16243 => 30719,
16244 => 30518, 16245 => 26103, 16246 => 20917, 16247 => 20111, 16248 => 30420, 16244 => 30518, 16245 => 26103, 16246 => 20917, 16247 => 20111, 16248 => 30420,
16249 => 23743, 16250 => 31397, 16251 => 33909, 16252 => 22862, 16253 => 39745, 16249 => 23743, 16250 => 31397, 16251 => 33909, 16252 => 22862, 16253 => 39745,
16254 => 20608, 16417 => 39304, 16418 => 24871, 16419 => 28291, 16420 => 22372, 16254 => 20608, 16417 => 39304, 16418 => 24871, 16419 => 28291, 16420 => 22372,
16421 => 26118, 16422 => 25414, 16423 => 22256, 16424 => 25324, 16425 => 25193, 16421 => 26118, 16422 => 25414, 16423 => 22256, 16424 => 25324, 16425 => 25193,
16426 => 24275, 16427 => 38420, 16428 => 22403, 16429 => 25289, 16430 => 21895, 16426 => 24275, 16427 => 38420, 16428 => 22403, 16429 => 25289, 16430 => 21895,
16431 => 34593, 16432 => 33098, 16433 => 36771, 16434 => 21862, 16435 => 33713, 16431 => 34593, 16432 => 33098, 16433 => 36771, 16434 => 21862, 16435 => 33713,
16436 => 26469, 16437 => 36182, 16438 => 34013, 16439 => 23146, 16440 => 26639, 16436 => 26469, 16437 => 36182, 16438 => 34013, 16439 => 23146, 16440 => 26639,
16441 => 25318, 16442 => 31726, 16443 => 38417, 16444 => 20848, 16445 => 28572, 16441 => 25318, 16442 => 31726, 16443 => 38417, 16444 => 20848, 16445 => 28572,
16446 => 35888, 16447 => 25597, 16448 => 35272, 16449 => 25042, 16450 => 32518, 16446 => 35888, 16447 => 25597, 16448 => 35272, 16449 => 25042, 16450 => 32518,
16451 => 28866, 16452 => 28389, 16453 => 29701, 16454 => 27028, 16455 => 29436, 16451 => 28866, 16452 => 28389, 16453 => 29701, 16454 => 27028, 16455 => 29436,
16456 => 24266, 16457 => 37070, 16458 => 26391, 16459 => 28010, 16460 => 25438, 16456 => 24266, 16457 => 37070, 16458 => 26391, 16459 => 28010, 16460 => 25438,
16461 => 21171, 16462 => 29282, 16463 => 32769, 16464 => 20332, 16465 => 23013, 16461 => 21171, 16462 => 29282, 16463 => 32769, 16464 => 20332, 16465 => 23013,
16466 => 37226, 16467 => 28889, 16468 => 28061, 16469 => 21202, 16470 => 20048, 16466 => 37226, 16467 => 28889, 16468 => 28061, 16469 => 21202, 16470 => 20048,
16471 => 38647, 16472 => 38253, 16473 => 34174, 16474 => 30922, 16475 => 32047, 16471 => 38647, 16472 => 38253, 16473 => 34174, 16474 => 30922, 16475 => 32047,
16476 => 20769, 16477 => 22418, 16478 => 25794, 16479 => 32907, 16480 => 31867, 16476 => 20769, 16477 => 22418, 16478 => 25794, 16479 => 32907, 16480 => 31867,
16481 => 27882, 16482 => 26865, 16483 => 26974, 16484 => 20919, 16485 => 21400, 16481 => 27882, 16482 => 26865, 16483 => 26974, 16484 => 20919, 16485 => 21400,
16486 => 26792, 16487 => 29313, 16488 => 40654, 16489 => 31729, 16490 => 29432, 16486 => 26792, 16487 => 29313, 16488 => 40654, 16489 => 31729, 16490 => 29432,
16491 => 31163, 16492 => 28435, 16493 => 29702, 16494 => 26446, 16495 => 37324, 16491 => 31163, 16492 => 28435, 16493 => 29702, 16494 => 26446, 16495 => 37324,
16496 => 40100, 16497 => 31036, 16498 => 33673, 16499 => 33620, 16500 => 21519, 16496 => 40100, 16497 => 31036, 16498 => 33673, 16499 => 33620, 16500 => 21519,
16501 => 26647, 16502 => 20029, 16503 => 21385, 16504 => 21169, 16505 => 30782, 16501 => 26647, 16502 => 20029, 16503 => 21385, 16504 => 21169, 16505 => 30782,
16506 => 21382, 16507 => 21033, 16508 => 20616, 16509 => 20363, 16510 => 20432, 16506 => 21382, 16507 => 21033, 16508 => 20616, 16509 => 20363, 16510 => 20432,
16673 => 30178, 16674 => 31435, 16675 => 31890, 16676 => 27813, 16677 => 38582, 16673 => 30178, 16674 => 31435, 16675 => 31890, 16676 => 27813, 16677 => 38582,
16678 => 21147, 16679 => 29827, 16680 => 21737, 16681 => 20457, 16682 => 32852, 16678 => 21147, 16679 => 29827, 16680 => 21737, 16681 => 20457, 16682 => 32852,
16683 => 33714, 16684 => 36830, 16685 => 38256, 16686 => 24265, 16687 => 24604, 16683 => 33714, 16684 => 36830, 16685 => 38256, 16686 => 24265, 16687 => 24604,
16688 => 28063, 16689 => 24088, 16690 => 25947, 16691 => 33080, 16692 => 38142, 16688 => 28063, 16689 => 24088, 16690 => 25947, 16691 => 33080, 16692 => 38142,
16693 => 24651, 16694 => 28860, 16695 => 32451, 16696 => 31918, 16697 => 20937, 16693 => 24651, 16694 => 28860, 16695 => 32451, 16696 => 31918, 16697 => 20937,
16698 => 26753, 16699 => 31921, 16700 => 33391, 16701 => 20004, 16702 => 36742, 16698 => 26753, 16699 => 31921, 16700 => 33391, 16701 => 20004, 16702 => 36742,
16703 => 37327, 16704 => 26238, 16705 => 20142, 16706 => 35845, 16707 => 25769, 16703 => 37327, 16704 => 26238, 16705 => 20142, 16706 => 35845, 16707 => 25769,
16708 => 32842, 16709 => 20698, 16710 => 30103, 16711 => 29134, 16712 => 23525, 16708 => 32842, 16709 => 20698, 16710 => 30103, 16711 => 29134, 16712 => 23525,
16713 => 36797, 16714 => 28518, 16715 => 20102, 16716 => 25730, 16717 => 38243, 16713 => 36797, 16714 => 28518, 16715 => 20102, 16716 => 25730, 16717 => 38243,
16718 => 24278, 16719 => 26009, 16720 => 21015, 16721 => 35010, 16722 => 28872, 16718 => 24278, 16719 => 26009, 16720 => 21015, 16721 => 35010, 16722 => 28872,
16723 => 21155, 16724 => 29454, 16725 => 29747, 16726 => 26519, 16727 => 30967, 16723 => 21155, 16724 => 29454, 16725 => 29747, 16726 => 26519, 16727 => 30967,
16728 => 38678, 16729 => 20020, 16730 => 37051, 16731 => 40158, 16732 => 28107, 16728 => 38678, 16729 => 20020, 16730 => 37051, 16731 => 40158, 16732 => 28107,
16733 => 20955, 16734 => 36161, 16735 => 21533, 16736 => 25294, 16737 => 29618, 16733 => 20955, 16734 => 36161, 16735 => 21533, 16736 => 25294, 16737 => 29618,
16738 => 33777, 16739 => 38646, 16740 => 40836, 16741 => 38083, 16742 => 20278, 16738 => 33777, 16739 => 38646, 16740 => 40836, 16741 => 38083, 16742 => 20278,
16743 => 32666, 16744 => 20940, 16745 => 28789, 16746 => 38517, 16747 => 23725, 16743 => 32666, 16744 => 20940, 16745 => 28789, 16746 => 38517, 16747 => 23725,
16748 => 39046, 16749 => 21478, 16750 => 20196, 16751 => 28316, 16752 => 29705, 16748 => 39046, 16749 => 21478, 16750 => 20196, 16751 => 28316, 16752 => 29705,
16753 => 27060, 16754 => 30827, 16755 => 39311, 16756 => 30041, 16757 => 21016, 16753 => 27060, 16754 => 30827, 16755 => 39311, 16756 => 30041, 16757 => 21016,
16758 => 30244, 16759 => 27969, 16760 => 26611, 16761 => 20845, 16762 => 40857, 16758 => 30244, 16759 => 27969, 16760 => 26611, 16761 => 20845, 16762 => 40857,
16763 => 32843, 16764 => 21657, 16765 => 31548, 16766 => 31423, 16929 => 38534, 16763 => 32843, 16764 => 21657, 16765 => 31548, 16766 => 31423, 16929 => 38534,
16930 => 22404, 16931 => 25314, 16932 => 38471, 16933 => 27004, 16934 => 23044, 16930 => 22404, 16931 => 25314, 16932 => 38471, 16933 => 27004, 16934 => 23044,
16935 => 25602, 16936 => 31699, 16937 => 28431, 16938 => 38475, 16939 => 33446, 16935 => 25602, 16936 => 31699, 16937 => 28431, 16938 => 38475, 16939 => 33446,
16940 => 21346, 16941 => 39045, 16942 => 24208, 16943 => 28809, 16944 => 25523, 16940 => 21346, 16941 => 39045, 16942 => 24208, 16943 => 28809, 16944 => 25523,
16945 => 21348, 16946 => 34383, 16947 => 40065, 16948 => 40595, 16949 => 30860, 16945 => 21348, 16946 => 34383, 16947 => 40065, 16948 => 40595, 16949 => 30860,
16950 => 38706, 16951 => 36335, 16952 => 36162, 16953 => 40575, 16954 => 28510, 16950 => 38706, 16951 => 36335, 16952 => 36162, 16953 => 40575, 16954 => 28510,
16955 => 31108, 16956 => 24405, 16957 => 38470, 16958 => 25134, 16959 => 39540, 16955 => 31108, 16956 => 24405, 16957 => 38470, 16958 => 25134, 16959 => 39540,
16960 => 21525, 16961 => 38109, 16962 => 20387, 16963 => 26053, 16964 => 23653, 16960 => 21525, 16961 => 38109, 16962 => 20387, 16963 => 26053, 16964 => 23653,
16965 => 23649, 16966 => 32533, 16967 => 34385, 16968 => 27695, 16969 => 24459, 16965 => 23649, 16966 => 32533, 16967 => 34385, 16968 => 27695, 16969 => 24459,
16970 => 29575, 16971 => 28388, 16972 => 32511, 16973 => 23782, 16974 => 25371, 16970 => 29575, 16971 => 28388, 16972 => 32511, 16973 => 23782, 16974 => 25371,
16975 => 23402, 16976 => 28390, 16977 => 21365, 16978 => 20081, 16979 => 25504, 16975 => 23402, 16976 => 28390, 16977 => 21365, 16978 => 20081, 16979 => 25504,
16980 => 30053, 16981 => 25249, 16982 => 36718, 16983 => 20262, 16984 => 20177, 16980 => 30053, 16981 => 25249, 16982 => 36718, 16983 => 20262, 16984 => 20177,
16985 => 27814, 16986 => 32438, 16987 => 35770, 16988 => 33821, 16989 => 34746, 16985 => 27814, 16986 => 32438, 16987 => 35770, 16988 => 33821, 16989 => 34746,
16990 => 32599, 16991 => 36923, 16992 => 38179, 16993 => 31657, 16994 => 39585, 16990 => 32599, 16991 => 36923, 16992 => 38179, 16993 => 31657, 16994 => 39585,
16995 => 35064, 16996 => 33853, 16997 => 27931, 16998 => 39558, 16999 => 32476, 16995 => 35064, 16996 => 33853, 16997 => 27931, 16998 => 39558, 16999 => 32476,
17000 => 22920, 17001 => 40635, 17002 => 29595, 17003 => 30721, 17004 => 34434, 17000 => 22920, 17001 => 40635, 17002 => 29595, 17003 => 30721, 17004 => 34434,
17005 => 39532, 17006 => 39554, 17007 => 22043, 17008 => 21527, 17009 => 22475, 17005 => 39532, 17006 => 39554, 17007 => 22043, 17008 => 21527, 17009 => 22475,
17010 => 20080, 17011 => 40614, 17012 => 21334, 17013 => 36808, 17014 => 33033, 17010 => 20080, 17011 => 40614, 17012 => 21334, 17013 => 36808, 17014 => 33033,
17015 => 30610, 17016 => 39314, 17017 => 34542, 17018 => 28385, 17019 => 34067, 17015 => 30610, 17016 => 39314, 17017 => 34542, 17018 => 28385, 17019 => 34067,
17020 => 26364, 17021 => 24930, 17022 => 28459, 17185 => 35881, 17186 => 33426, 17020 => 26364, 17021 => 24930, 17022 => 28459, 17185 => 35881, 17186 => 33426,
17187 => 33579, 17188 => 30450, 17189 => 27667, 17190 => 24537, 17191 => 33725, 17187 => 33579, 17188 => 30450, 17189 => 27667, 17190 => 24537, 17191 => 33725,
17192 => 29483, 17193 => 33541, 17194 => 38170, 17195 => 27611, 17196 => 30683, 17192 => 29483, 17193 => 33541, 17194 => 38170, 17195 => 27611, 17196 => 30683,
17197 => 38086, 17198 => 21359, 17199 => 33538, 17200 => 20882, 17201 => 24125, 17197 => 38086, 17198 => 21359, 17199 => 33538, 17200 => 20882, 17201 => 24125,
17202 => 35980, 17203 => 36152, 17204 => 20040, 17205 => 29611, 17206 => 26522, 17202 => 35980, 17203 => 36152, 17204 => 20040, 17205 => 29611, 17206 => 26522,
17207 => 26757, 17208 => 37238, 17209 => 38665, 17210 => 29028, 17211 => 27809, 17207 => 26757, 17208 => 37238, 17209 => 38665, 17210 => 29028, 17211 => 27809,
17212 => 30473, 17213 => 23186, 17214 => 38209, 17215 => 27599, 17216 => 32654, 17212 => 30473, 17213 => 23186, 17214 => 38209, 17215 => 27599, 17216 => 32654,
17217 => 26151, 17218 => 23504, 17219 => 22969, 17220 => 23194, 17221 => 38376, 17217 => 26151, 17218 => 23504, 17219 => 22969, 17220 => 23194, 17221 => 38376,
17222 => 38391, 17223 => 20204, 17224 => 33804, 17225 => 33945, 17226 => 27308, 17222 => 38391, 17223 => 20204, 17224 => 33804, 17225 => 33945, 17226 => 27308,
17227 => 30431, 17228 => 38192, 17229 => 29467, 17230 => 26790, 17231 => 23391, 17227 => 30431, 17228 => 38192, 17229 => 29467, 17230 => 26790, 17231 => 23391,
17232 => 30511, 17233 => 37274, 17234 => 38753, 17235 => 31964, 17236 => 36855, 17232 => 30511, 17233 => 37274, 17234 => 38753, 17235 => 31964, 17236 => 36855,
17237 => 35868, 17238 => 24357, 17239 => 31859, 17240 => 31192, 17241 => 35269, 17237 => 35868, 17238 => 24357, 17239 => 31859, 17240 => 31192, 17241 => 35269,
17242 => 27852, 17243 => 34588, 17244 => 23494, 17245 => 24130, 17246 => 26825, 17242 => 27852, 17243 => 34588, 17244 => 23494, 17245 => 24130, 17246 => 26825,
17247 => 30496, 17248 => 32501, 17249 => 20885, 17250 => 20813, 17251 => 21193, 17247 => 30496, 17248 => 32501, 17249 => 20885, 17250 => 20813, 17251 => 21193,
17252 => 23081, 17253 => 32517, 17254 => 38754, 17255 => 33495, 17256 => 25551, 17252 => 23081, 17253 => 32517, 17254 => 38754, 17255 => 33495, 17256 => 25551,
17257 => 30596, 17258 => 34256, 17259 => 31186, 17260 => 28218, 17261 => 24217, 17257 => 30596, 17258 => 34256, 17259 => 31186, 17260 => 28218, 17261 => 24217,
17262 => 22937, 17263 => 34065, 17264 => 28781, 17265 => 27665, 17266 => 25279, 17262 => 22937, 17263 => 34065, 17264 => 28781, 17265 => 27665, 17266 => 25279,
17267 => 30399, 17268 => 25935, 17269 => 24751, 17270 => 38397, 17271 => 26126, 17267 => 30399, 17268 => 25935, 17269 => 24751, 17270 => 38397, 17271 => 26126,
17272 => 34719, 17273 => 40483, 17274 => 38125, 17275 => 21517, 17276 => 21629, 17272 => 34719, 17273 => 40483, 17274 => 38125, 17275 => 21517, 17276 => 21629,
17277 => 35884, 17278 => 25720, 17441 => 25721, 17442 => 34321, 17443 => 27169, 17277 => 35884, 17278 => 25720, 17441 => 25721, 17442 => 34321, 17443 => 27169,
17444 => 33180, 17445 => 30952, 17446 => 25705, 17447 => 39764, 17448 => 25273, 17444 => 33180, 17445 => 30952, 17446 => 25705, 17447 => 39764, 17448 => 25273,
17449 => 26411, 17450 => 33707, 17451 => 22696, 17452 => 40664, 17453 => 27819, 17449 => 26411, 17450 => 33707, 17451 => 22696, 17452 => 40664, 17453 => 27819,
17454 => 28448, 17455 => 23518, 17456 => 38476, 17457 => 35851, 17458 => 29279, 17454 => 28448, 17455 => 23518, 17456 => 38476, 17457 => 35851, 17458 => 29279,
17459 => 26576, 17460 => 25287, 17461 => 29281, 17462 => 20137, 17463 => 22982, 17459 => 26576, 17460 => 25287, 17461 => 29281, 17462 => 20137, 17463 => 22982,
17464 => 27597, 17465 => 22675, 17466 => 26286, 17467 => 24149, 17468 => 21215, 17464 => 27597, 17465 => 22675, 17466 => 26286, 17467 => 24149, 17468 => 21215,
17469 => 24917, 17470 => 26408, 17471 => 30446, 17472 => 30566, 17473 => 29287, 17469 => 24917, 17470 => 26408, 17471 => 30446, 17472 => 30566, 17473 => 29287,
17474 => 31302, 17475 => 25343, 17476 => 21738, 17477 => 21584, 17478 => 38048, 17474 => 31302, 17475 => 25343, 17476 => 21738, 17477 => 21584, 17478 => 38048,
17479 => 37027, 17480 => 23068, 17481 => 32435, 17482 => 27670, 17483 => 20035, 17479 => 37027, 17480 => 23068, 17481 => 32435, 17482 => 27670, 17483 => 20035,
17484 => 22902, 17485 => 32784, 17486 => 22856, 17487 => 21335, 17488 => 30007, 17484 => 22902, 17485 => 32784, 17486 => 22856, 17487 => 21335, 17488 => 30007,
17489 => 38590, 17490 => 22218, 17491 => 25376, 17492 => 33041, 17493 => 24700, 17489 => 38590, 17490 => 22218, 17491 => 25376, 17492 => 33041, 17493 => 24700,
17494 => 38393, 17495 => 28118, 17496 => 21602, 17497 => 39297, 17498 => 20869, 17494 => 38393, 17495 => 28118, 17496 => 21602, 17497 => 39297, 17498 => 20869,
17499 => 23273, 17500 => 33021, 17501 => 22958, 17502 => 38675, 17503 => 20522, 17499 => 23273, 17500 => 33021, 17501 => 22958, 17502 => 38675, 17503 => 20522,
17504 => 27877, 17505 => 23612, 17506 => 25311, 17507 => 20320, 17508 => 21311, 17504 => 27877, 17505 => 23612, 17506 => 25311, 17507 => 20320, 17508 => 21311,
17509 => 33147, 17510 => 36870, 17511 => 28346, 17512 => 34091, 17513 => 25288, 17509 => 33147, 17510 => 36870, 17511 => 28346, 17512 => 34091, 17513 => 25288,
17514 => 24180, 17515 => 30910, 17516 => 25781, 17517 => 25467, 17518 => 24565, 17514 => 24180, 17515 => 30910, 17516 => 25781, 17517 => 25467, 17518 => 24565,
17519 => 23064, 17520 => 37247, 17521 => 40479, 17522 => 23615, 17523 => 25423, 17519 => 23064, 17520 => 37247, 17521 => 40479, 17522 => 23615, 17523 => 25423,
17524 => 32834, 17525 => 23421, 17526 => 21870, 17527 => 38218, 17528 => 38221, 17524 => 32834, 17525 => 23421, 17526 => 21870, 17527 => 38218, 17528 => 38221,
17529 => 28037, 17530 => 24744, 17531 => 26592, 17532 => 29406, 17533 => 20957, 17529 => 28037, 17530 => 24744, 17531 => 26592, 17532 => 29406, 17533 => 20957,
17534 => 23425, 17697 => 25319, 17698 => 27870, 17699 => 29275, 17700 => 25197, 17534 => 23425, 17697 => 25319, 17698 => 27870, 17699 => 29275, 17700 => 25197,
17701 => 38062, 17702 => 32445, 17703 => 33043, 17704 => 27987, 17705 => 20892, 17701 => 38062, 17702 => 32445, 17703 => 33043, 17704 => 27987, 17705 => 20892,
17706 => 24324, 17707 => 22900, 17708 => 21162, 17709 => 24594, 17710 => 22899, 17706 => 24324, 17707 => 22900, 17708 => 21162, 17709 => 24594, 17710 => 22899,
17711 => 26262, 17712 => 34384, 17713 => 30111, 17714 => 25386, 17715 => 25062, 17711 => 26262, 17712 => 34384, 17713 => 30111, 17714 => 25386, 17715 => 25062,
17716 => 31983, 17717 => 35834, 17718 => 21734, 17719 => 27431, 17720 => 40485, 17716 => 31983, 17717 => 35834, 17718 => 21734, 17719 => 27431, 17720 => 40485,
17721 => 27572, 17722 => 34261, 17723 => 21589, 17724 => 20598, 17725 => 27812, 17721 => 27572, 17722 => 34261, 17723 => 21589, 17724 => 20598, 17725 => 27812,
17726 => 21866, 17727 => 36276, 17728 => 29228, 17729 => 24085, 17730 => 24597, 17726 => 21866, 17727 => 36276, 17728 => 29228, 17729 => 24085, 17730 => 24597,
17731 => 29750, 17732 => 25293, 17733 => 25490, 17734 => 29260, 17735 => 24472, 17731 => 29750, 17732 => 25293, 17733 => 25490, 17734 => 29260, 17735 => 24472,
17736 => 28227, 17737 => 27966, 17738 => 25856, 17739 => 28504, 17740 => 30424, 17736 => 28227, 17737 => 27966, 17738 => 25856, 17739 => 28504, 17740 => 30424,
17741 => 30928, 17742 => 30460, 17743 => 30036, 17744 => 21028, 17745 => 21467, 17741 => 30928, 17742 => 30460, 17743 => 30036, 17744 => 21028, 17745 => 21467,
17746 => 20051, 17747 => 24222, 17748 => 26049, 17749 => 32810, 17750 => 32982, 17746 => 20051, 17747 => 24222, 17748 => 26049, 17749 => 32810, 17750 => 32982,
17751 => 25243, 17752 => 21638, 17753 => 21032, 17754 => 28846, 17755 => 34957, 17751 => 25243, 17752 => 21638, 17753 => 21032, 17754 => 28846, 17755 => 34957,
17756 => 36305, 17757 => 27873, 17758 => 21624, 17759 => 32986, 17760 => 22521, 17756 => 36305, 17757 => 27873, 17758 => 21624, 17759 => 32986, 17760 => 22521,
17761 => 35060, 17762 => 36180, 17763 => 38506, 17764 => 37197, 17765 => 20329, 17761 => 35060, 17762 => 36180, 17763 => 38506, 17764 => 37197, 17765 => 20329,
17766 => 27803, 17767 => 21943, 17768 => 30406, 17769 => 30768, 17770 => 25256, 17766 => 27803, 17767 => 21943, 17768 => 30406, 17769 => 30768, 17770 => 25256,
17771 => 28921, 17772 => 28558, 17773 => 24429, 17774 => 34028, 17775 => 26842, 17771 => 28921, 17772 => 28558, 17773 => 24429, 17774 => 34028, 17775 => 26842,
17776 => 30844, 17777 => 31735, 17778 => 33192, 17779 => 26379, 17780 => 40527, 17776 => 30844, 17777 => 31735, 17778 => 33192, 17779 => 26379, 17780 => 40527,
17781 => 25447, 17782 => 30896, 17783 => 22383, 17784 => 30738, 17785 => 38713, 17781 => 25447, 17782 => 30896, 17783 => 22383, 17784 => 30738, 17785 => 38713,
17786 => 25209, 17787 => 25259, 17788 => 21128, 17789 => 29749, 17790 => 27607, 17786 => 25209, 17787 => 25259, 17788 => 21128, 17789 => 29749, 17790 => 27607,
17953 => 21860, 17954 => 33086, 17955 => 30130, 17956 => 30382, 17957 => 21305, 17953 => 21860, 17954 => 33086, 17955 => 30130, 17956 => 30382, 17957 => 21305,
17958 => 30174, 17959 => 20731, 17960 => 23617, 17961 => 35692, 17962 => 31687, 17958 => 30174, 17959 => 20731, 17960 => 23617, 17961 => 35692, 17962 => 31687,
17963 => 20559, 17964 => 29255, 17965 => 39575, 17966 => 39128, 17967 => 28418, 17963 => 20559, 17964 => 29255, 17965 => 39575, 17966 => 39128, 17967 => 28418,
17968 => 29922, 17969 => 31080, 17970 => 25735, 17971 => 30629, 17972 => 25340, 17968 => 29922, 17969 => 31080, 17970 => 25735, 17971 => 30629, 17972 => 25340,
17973 => 39057, 17974 => 36139, 17975 => 21697, 17976 => 32856, 17977 => 20050, 17973 => 39057, 17974 => 36139, 17975 => 21697, 17976 => 32856, 17977 => 20050,
17978 => 22378, 17979 => 33529, 17980 => 33805, 17981 => 24179, 17982 => 20973, 17978 => 22378, 17979 => 33529, 17980 => 33805, 17981 => 24179, 17982 => 20973,
17983 => 29942, 17984 => 35780, 17985 => 23631, 17986 => 22369, 17987 => 27900, 17983 => 29942, 17984 => 35780, 17985 => 23631, 17986 => 22369, 17987 => 27900,
17988 => 39047, 17989 => 23110, 17990 => 30772, 17991 => 39748, 17992 => 36843, 17988 => 39047, 17989 => 23110, 17990 => 30772, 17991 => 39748, 17992 => 36843,
17993 => 31893, 17994 => 21078, 17995 => 25169, 17996 => 38138, 17997 => 20166, 17993 => 31893, 17994 => 21078, 17995 => 25169, 17996 => 38138, 17997 => 20166,
17998 => 33670, 17999 => 33889, 18000 => 33769, 18001 => 33970, 18002 => 22484, 17998 => 33670, 17999 => 33889, 18000 => 33769, 18001 => 33970, 18002 => 22484,
18003 => 26420, 18004 => 22275, 18005 => 26222, 18006 => 28006, 18007 => 35889, 18003 => 26420, 18004 => 22275, 18005 => 26222, 18006 => 28006, 18007 => 35889,
18008 => 26333, 18009 => 28689, 18010 => 26399, 18011 => 27450, 18012 => 26646, 18008 => 26333, 18009 => 28689, 18010 => 26399, 18011 => 27450, 18012 => 26646,
18013 => 25114, 18014 => 22971, 18015 => 19971, 18016 => 20932, 18017 => 28422, 18013 => 25114, 18014 => 22971, 18015 => 19971, 18016 => 20932, 18017 => 28422,
18018 => 26578, 18019 => 27791, 18020 => 20854, 18021 => 26827, 18022 => 22855, 18018 => 26578, 18019 => 27791, 18020 => 20854, 18021 => 26827, 18022 => 22855,
18023 => 27495, 18024 => 30054, 18025 => 23822, 18026 => 33040, 18027 => 40784, 18023 => 27495, 18024 => 30054, 18025 => 23822, 18026 => 33040, 18027 => 40784,
18028 => 26071, 18029 => 31048, 18030 => 31041, 18031 => 39569, 18032 => 36215, 18028 => 26071, 18029 => 31048, 18030 => 31041, 18031 => 39569, 18032 => 36215,
18033 => 23682, 18034 => 20062, 18035 => 20225, 18036 => 21551, 18037 => 22865, 18033 => 23682, 18034 => 20062, 18035 => 20225, 18036 => 21551, 18037 => 22865,
18038 => 30732, 18039 => 22120, 18040 => 27668, 18041 => 36804, 18042 => 24323, 18038 => 30732, 18039 => 22120, 18040 => 27668, 18041 => 36804, 18042 => 24323,
18043 => 27773, 18044 => 27875, 18045 => 35755, 18046 => 25488, 18209 => 24688, 18043 => 27773, 18044 => 27875, 18045 => 35755, 18046 => 25488, 18209 => 24688,
18210 => 27965, 18211 => 29301, 18212 => 25190, 18213 => 38030, 18214 => 38085, 18210 => 27965, 18211 => 29301, 18212 => 25190, 18213 => 38030, 18214 => 38085,
18215 => 21315, 18216 => 36801, 18217 => 31614, 18218 => 20191, 18219 => 35878, 18215 => 21315, 18216 => 36801, 18217 => 31614, 18218 => 20191, 18219 => 35878,
18220 => 20094, 18221 => 40660, 18222 => 38065, 18223 => 38067, 18224 => 21069, 18220 => 20094, 18221 => 40660, 18222 => 38065, 18223 => 38067, 18224 => 21069,
18225 => 28508, 18226 => 36963, 18227 => 27973, 18228 => 35892, 18229 => 22545, 18225 => 28508, 18226 => 36963, 18227 => 27973, 18228 => 35892, 18229 => 22545,
18230 => 23884, 18231 => 27424, 18232 => 27465, 18233 => 26538, 18234 => 21595, 18230 => 23884, 18231 => 27424, 18232 => 27465, 18233 => 26538, 18234 => 21595,
18235 => 33108, 18236 => 32652, 18237 => 22681, 18238 => 34103, 18239 => 24378, 18235 => 33108, 18236 => 32652, 18237 => 22681, 18238 => 34103, 18239 => 24378,
18240 => 25250, 18241 => 27207, 18242 => 38201, 18243 => 25970, 18244 => 24708, 18240 => 25250, 18241 => 27207, 18242 => 38201, 18243 => 25970, 18244 => 24708,
18245 => 26725, 18246 => 30631, 18247 => 20052, 18248 => 20392, 18249 => 24039, 18245 => 26725, 18246 => 30631, 18247 => 20052, 18248 => 20392, 18249 => 24039,
18250 => 38808, 18251 => 25772, 18252 => 32728, 18253 => 23789, 18254 => 20431, 18250 => 38808, 18251 => 25772, 18252 => 32728, 18253 => 23789, 18254 => 20431,
18255 => 31373, 18256 => 20999, 18257 => 33540, 18258 => 19988, 18259 => 24623, 18255 => 31373, 18256 => 20999, 18257 => 33540, 18258 => 19988, 18259 => 24623,
18260 => 31363, 18261 => 38054, 18262 => 20405, 18263 => 20146, 18264 => 31206, 18260 => 31363, 18261 => 38054, 18262 => 20405, 18263 => 20146, 18264 => 31206,
18265 => 29748, 18266 => 21220, 18267 => 33465, 18268 => 25810, 18269 => 31165, 18265 => 29748, 18266 => 21220, 18267 => 33465, 18268 => 25810, 18269 => 31165,
18270 => 23517, 18271 => 27777, 18272 => 38738, 18273 => 36731, 18274 => 27682, 18270 => 23517, 18271 => 27777, 18272 => 38738, 18273 => 36731, 18274 => 27682,
18275 => 20542, 18276 => 21375, 18277 => 28165, 18278 => 25806, 18279 => 26228, 18275 => 20542, 18276 => 21375, 18277 => 28165, 18278 => 25806, 18279 => 26228,
18280 => 27696, 18281 => 24773, 18282 => 39031, 18283 => 35831, 18284 => 24198, 18280 => 27696, 18281 => 24773, 18282 => 39031, 18283 => 35831, 18284 => 24198,
18285 => 29756, 18286 => 31351, 18287 => 31179, 18288 => 19992, 18289 => 37041, 18285 => 29756, 18286 => 31351, 18287 => 31179, 18288 => 19992, 18289 => 37041,
18290 => 29699, 18291 => 27714, 18292 => 22234, 18293 => 37195, 18294 => 27845, 18290 => 29699, 18291 => 27714, 18292 => 22234, 18293 => 37195, 18294 => 27845,
18295 => 36235, 18296 => 21306, 18297 => 34502, 18298 => 26354, 18299 => 36527, 18295 => 36235, 18296 => 21306, 18297 => 34502, 18298 => 26354, 18299 => 36527,
18300 => 23624, 18301 => 39537, 18302 => 28192, 18465 => 21462, 18466 => 23094, 18300 => 23624, 18301 => 39537, 18302 => 28192, 18465 => 21462, 18466 => 23094,
18467 => 40843, 18468 => 36259, 18469 => 21435, 18470 => 22280, 18471 => 39079, 18467 => 40843, 18468 => 36259, 18469 => 21435, 18470 => 22280, 18471 => 39079,
18472 => 26435, 18473 => 37275, 18474 => 27849, 18475 => 20840, 18476 => 30154, 18472 => 26435, 18473 => 37275, 18474 => 27849, 18475 => 20840, 18476 => 30154,
18477 => 25331, 18478 => 29356, 18479 => 21048, 18480 => 21149, 18481 => 32570, 18477 => 25331, 18478 => 29356, 18479 => 21048, 18480 => 21149, 18481 => 32570,
18482 => 28820, 18483 => 30264, 18484 => 21364, 18485 => 40522, 18486 => 27063, 18482 => 28820, 18483 => 30264, 18484 => 21364, 18485 => 40522, 18486 => 27063,
18487 => 30830, 18488 => 38592, 18489 => 35033, 18490 => 32676, 18491 => 28982, 18487 => 30830, 18488 => 38592, 18489 => 35033, 18490 => 32676, 18491 => 28982,
18492 => 29123, 18493 => 20873, 18494 => 26579, 18495 => 29924, 18496 => 22756, 18492 => 29123, 18493 => 20873, 18494 => 26579, 18495 => 29924, 18496 => 22756,
18497 => 25880, 18498 => 22199, 18499 => 35753, 18500 => 39286, 18501 => 25200, 18497 => 25880, 18498 => 22199, 18499 => 35753, 18500 => 39286, 18501 => 25200,
18502 => 32469, 18503 => 24825, 18504 => 28909, 18505 => 22764, 18506 => 20161, 18502 => 32469, 18503 => 24825, 18504 => 28909, 18505 => 22764, 18506 => 20161,
18507 => 20154, 18508 => 24525, 18509 => 38887, 18510 => 20219, 18511 => 35748, 18507 => 20154, 18508 => 24525, 18509 => 38887, 18510 => 20219, 18511 => 35748,
18512 => 20995, 18513 => 22922, 18514 => 32427, 18515 => 25172, 18516 => 20173, 18512 => 20995, 18513 => 22922, 18514 => 32427, 18515 => 25172, 18516 => 20173,
18517 => 26085, 18518 => 25102, 18519 => 33592, 18520 => 33993, 18521 => 33635, 18517 => 26085, 18518 => 25102, 18519 => 33592, 18520 => 33993, 18521 => 33635,
18522 => 34701, 18523 => 29076, 18524 => 28342, 18525 => 23481, 18526 => 32466, 18522 => 34701, 18523 => 29076, 18524 => 28342, 18525 => 23481, 18526 => 32466,
18527 => 20887, 18528 => 25545, 18529 => 26580, 18530 => 32905, 18531 => 33593, 18527 => 20887, 18528 => 25545, 18529 => 26580, 18530 => 32905, 18531 => 33593,
18532 => 34837, 18533 => 20754, 18534 => 23418, 18535 => 22914, 18536 => 36785, 18532 => 34837, 18533 => 20754, 18534 => 23418, 18535 => 22914, 18536 => 36785,
18537 => 20083, 18538 => 27741, 18539 => 20837, 18540 => 35109, 18541 => 36719, 18537 => 20083, 18538 => 27741, 18539 => 20837, 18540 => 35109, 18541 => 36719,
18542 => 38446, 18543 => 34122, 18544 => 29790, 18545 => 38160, 18546 => 38384, 18542 => 38446, 18543 => 34122, 18544 => 29790, 18545 => 38160, 18546 => 38384,
18547 => 28070, 18548 => 33509, 18549 => 24369, 18550 => 25746, 18551 => 27922, 18547 => 28070, 18548 => 33509, 18549 => 24369, 18550 => 25746, 18551 => 27922,
18552 => 33832, 18553 => 33134, 18554 => 40131, 18555 => 22622, 18556 => 36187, 18552 => 33832, 18553 => 33134, 18554 => 40131, 18555 => 22622, 18556 => 36187,
18557 => 19977, 18558 => 21441, 18721 => 20254, 18722 => 25955, 18723 => 26705, 18557 => 19977, 18558 => 21441, 18721 => 20254, 18722 => 25955, 18723 => 26705,
18724 => 21971, 18725 => 20007, 18726 => 25620, 18727 => 39578, 18728 => 25195, 18724 => 21971, 18725 => 20007, 18726 => 25620, 18727 => 39578, 18728 => 25195,
18729 => 23234, 18730 => 29791, 18731 => 33394, 18732 => 28073, 18733 => 26862, 18729 => 23234, 18730 => 29791, 18731 => 33394, 18732 => 28073, 18733 => 26862,
18734 => 20711, 18735 => 33678, 18736 => 30722, 18737 => 26432, 18738 => 21049, 18734 => 20711, 18735 => 33678, 18736 => 30722, 18737 => 26432, 18738 => 21049,
18739 => 27801, 18740 => 32433, 18741 => 20667, 18742 => 21861, 18743 => 29022, 18739 => 27801, 18740 => 32433, 18741 => 20667, 18742 => 21861, 18743 => 29022,
18744 => 31579, 18745 => 26194, 18746 => 29642, 18747 => 33515, 18748 => 26441, 18744 => 31579, 18745 => 26194, 18746 => 29642, 18747 => 33515, 18748 => 26441,
18749 => 23665, 18750 => 21024, 18751 => 29053, 18752 => 34923, 18753 => 38378, 18749 => 23665, 18750 => 21024, 18751 => 29053, 18752 => 34923, 18753 => 38378,
18754 => 38485, 18755 => 25797, 18756 => 36193, 18757 => 33203, 18758 => 21892, 18754 => 38485, 18755 => 25797, 18756 => 36193, 18757 => 33203, 18758 => 21892,
18759 => 27733, 18760 => 25159, 18761 => 32558, 18762 => 22674, 18763 => 20260, 18759 => 27733, 18760 => 25159, 18761 => 32558, 18762 => 22674, 18763 => 20260,
18764 => 21830, 18765 => 36175, 18766 => 26188, 18767 => 19978, 18768 => 23578, 18764 => 21830, 18765 => 36175, 18766 => 26188, 18767 => 19978, 18768 => 23578,
18769 => 35059, 18770 => 26786, 18771 => 25422, 18772 => 31245, 18773 => 28903, 18769 => 35059, 18770 => 26786, 18771 => 25422, 18772 => 31245, 18773 => 28903,
18774 => 33421, 18775 => 21242, 18776 => 38902, 18777 => 23569, 18778 => 21736, 18774 => 33421, 18775 => 21242, 18776 => 38902, 18777 => 23569, 18778 => 21736,
18779 => 37045, 18780 => 32461, 18781 => 22882, 18782 => 36170, 18783 => 34503, 18779 => 37045, 18780 => 32461, 18781 => 22882, 18782 => 36170, 18783 => 34503,
18784 => 33292, 18785 => 33293, 18786 => 36198, 18787 => 25668, 18788 => 23556, 18784 => 33292, 18785 => 33293, 18786 => 36198, 18787 => 25668, 18788 => 23556,
18789 => 24913, 18790 => 28041, 18791 => 31038, 18792 => 35774, 18793 => 30775, 18789 => 24913, 18790 => 28041, 18791 => 31038, 18792 => 35774, 18793 => 30775,
18794 => 30003, 18795 => 21627, 18796 => 20280, 18797 => 36523, 18798 => 28145, 18794 => 30003, 18795 => 21627, 18796 => 20280, 18797 => 36523, 18798 => 28145,
18799 => 23072, 18800 => 32453, 18801 => 31070, 18802 => 27784, 18803 => 23457, 18799 => 23072, 18800 => 32453, 18801 => 31070, 18802 => 27784, 18803 => 23457,
18804 => 23158, 18805 => 29978, 18806 => 32958, 18807 => 24910, 18808 => 28183, 18804 => 23158, 18805 => 29978, 18806 => 32958, 18807 => 24910, 18808 => 28183,
18809 => 22768, 18810 => 29983, 18811 => 29989, 18812 => 29298, 18813 => 21319, 18809 => 22768, 18810 => 29983, 18811 => 29989, 18812 => 29298, 18813 => 21319,
18814 => 32499, 18977 => 30465, 18978 => 30427, 18979 => 21097, 18980 => 32988, 18814 => 32499, 18977 => 30465, 18978 => 30427, 18979 => 21097, 18980 => 32988,
18981 => 22307, 18982 => 24072, 18983 => 22833, 18984 => 29422, 18985 => 26045, 18981 => 22307, 18982 => 24072, 18983 => 22833, 18984 => 29422, 18985 => 26045,
18986 => 28287, 18987 => 35799, 18988 => 23608, 18989 => 34417, 18990 => 21313, 18986 => 28287, 18987 => 35799, 18988 => 23608, 18989 => 34417, 18990 => 21313,
18991 => 30707, 18992 => 25342, 18993 => 26102, 18994 => 20160, 18995 => 39135, 18991 => 30707, 18992 => 25342, 18993 => 26102, 18994 => 20160, 18995 => 39135,
18996 => 34432, 18997 => 23454, 18998 => 35782, 18999 => 21490, 19000 => 30690, 18996 => 34432, 18997 => 23454, 18998 => 35782, 18999 => 21490, 19000 => 30690,
19001 => 20351, 19002 => 23630, 19003 => 39542, 19004 => 22987, 19005 => 24335, 19001 => 20351, 19002 => 23630, 19003 => 39542, 19004 => 22987, 19005 => 24335,
19006 => 31034, 19007 => 22763, 19008 => 19990, 19009 => 26623, 19010 => 20107, 19006 => 31034, 19007 => 22763, 19008 => 19990, 19009 => 26623, 19010 => 20107,
19011 => 25325, 19012 => 35475, 19013 => 36893, 19014 => 21183, 19015 => 26159, 19011 => 25325, 19012 => 35475, 19013 => 36893, 19014 => 21183, 19015 => 26159,
19016 => 21980, 19017 => 22124, 19018 => 36866, 19019 => 20181, 19020 => 20365, 19016 => 21980, 19017 => 22124, 19018 => 36866, 19019 => 20181, 19020 => 20365,
19021 => 37322, 19022 => 39280, 19023 => 27663, 19024 => 24066, 19025 => 24643, 19021 => 37322, 19022 => 39280, 19023 => 27663, 19024 => 24066, 19025 => 24643,
19026 => 23460, 19027 => 35270, 19028 => 35797, 19029 => 25910, 19030 => 25163, 19026 => 23460, 19027 => 35270, 19028 => 35797, 19029 => 25910, 19030 => 25163,
19031 => 39318, 19032 => 23432, 19033 => 23551, 19034 => 25480, 19035 => 21806, 19031 => 39318, 19032 => 23432, 19033 => 23551, 19034 => 25480, 19035 => 21806,
19036 => 21463, 19037 => 30246, 19038 => 20861, 19039 => 34092, 19040 => 26530, 19036 => 21463, 19037 => 30246, 19038 => 20861, 19039 => 34092, 19040 => 26530,
19041 => 26803, 19042 => 27530, 19043 => 25234, 19044 => 36755, 19045 => 21460, 19041 => 26803, 19042 => 27530, 19043 => 25234, 19044 => 36755, 19045 => 21460,
19046 => 33298, 19047 => 28113, 19048 => 30095, 19049 => 20070, 19050 => 36174, 19046 => 33298, 19047 => 28113, 19048 => 30095, 19049 => 20070, 19050 => 36174,
19051 => 23408, 19052 => 29087, 19053 => 34223, 19054 => 26257, 19055 => 26329, 19051 => 23408, 19052 => 29087, 19053 => 34223, 19054 => 26257, 19055 => 26329,
19056 => 32626, 19057 => 34560, 19058 => 40653, 19059 => 40736, 19060 => 23646, 19056 => 32626, 19057 => 34560, 19058 => 40653, 19059 => 40736, 19060 => 23646,
19061 => 26415, 19062 => 36848, 19063 => 26641, 19064 => 26463, 19065 => 25101, 19061 => 26415, 19062 => 36848, 19063 => 26641, 19064 => 26463, 19065 => 25101,
19066 => 31446, 19067 => 22661, 19068 => 24246, 19069 => 25968, 19070 => 28465, 19066 => 31446, 19067 => 22661, 19068 => 24246, 19069 => 25968, 19070 => 28465,
19233 => 24661, 19234 => 21047, 19235 => 32781, 19236 => 25684, 19237 => 34928, 19233 => 24661, 19234 => 21047, 19235 => 32781, 19236 => 25684, 19237 => 34928,
19238 => 29993, 19239 => 24069, 19240 => 26643, 19241 => 25332, 19242 => 38684, 19238 => 29993, 19239 => 24069, 19240 => 26643, 19241 => 25332, 19242 => 38684,
19243 => 21452, 19244 => 29245, 19245 => 35841, 19246 => 27700, 19247 => 30561, 19243 => 21452, 19244 => 29245, 19245 => 35841, 19246 => 27700, 19247 => 30561,
19248 => 31246, 19249 => 21550, 19250 => 30636, 19251 => 39034, 19252 => 33308, 19248 => 31246, 19249 => 21550, 19250 => 30636, 19251 => 39034, 19252 => 33308,
19253 => 35828, 19254 => 30805, 19255 => 26388, 19256 => 28865, 19257 => 26031, 19253 => 35828, 19254 => 30805, 19255 => 26388, 19256 => 28865, 19257 => 26031,
19258 => 25749, 19259 => 22070, 19260 => 24605, 19261 => 31169, 19262 => 21496, 19258 => 25749, 19259 => 22070, 19260 => 24605, 19261 => 31169, 19262 => 21496,
19263 => 19997, 19264 => 27515, 19265 => 32902, 19266 => 23546, 19267 => 21987, 19263 => 19997, 19264 => 27515, 19265 => 32902, 19266 => 23546, 19267 => 21987,
19268 => 22235, 19269 => 20282, 19270 => 20284, 19271 => 39282, 19272 => 24051, 19268 => 22235, 19269 => 20282, 19270 => 20284, 19271 => 39282, 19272 => 24051,
19273 => 26494, 19274 => 32824, 19275 => 24578, 19276 => 39042, 19277 => 36865, 19273 => 26494, 19274 => 32824, 19275 => 24578, 19276 => 39042, 19277 => 36865,
19278 => 23435, 19279 => 35772, 19280 => 35829, 19281 => 25628, 19282 => 33368, 19278 => 23435, 19279 => 35772, 19280 => 35829, 19281 => 25628, 19282 => 33368,
19283 => 25822, 19284 => 22013, 19285 => 33487, 19286 => 37221, 19287 => 20439, 19283 => 25822, 19284 => 22013, 19285 => 33487, 19286 => 37221, 19287 => 20439,
19288 => 32032, 19289 => 36895, 19290 => 31903, 19291 => 20723, 19292 => 22609, 19288 => 32032, 19289 => 36895, 19290 => 31903, 19291 => 20723, 19292 => 22609,
19293 => 28335, 19294 => 23487, 19295 => 35785, 19296 => 32899, 19297 => 37240, 19293 => 28335, 19294 => 23487, 19295 => 35785, 19296 => 32899, 19297 => 37240,
19298 => 33948, 19299 => 31639, 19300 => 34429, 19301 => 38539, 19302 => 38543, 19298 => 33948, 19299 => 31639, 19300 => 34429, 19301 => 38539, 19302 => 38543,
19303 => 32485, 19304 => 39635, 19305 => 30862, 19306 => 23681, 19307 => 31319, 19303 => 32485, 19304 => 39635, 19305 => 30862, 19306 => 23681, 19307 => 31319,
19308 => 36930, 19309 => 38567, 19310 => 31071, 19311 => 23385, 19312 => 25439, 19308 => 36930, 19309 => 38567, 19310 => 31071, 19311 => 23385, 19312 => 25439,
19313 => 31499, 19314 => 34001, 19315 => 26797, 19316 => 21766, 19317 => 32553, 19313 => 31499, 19314 => 34001, 19315 => 26797, 19316 => 21766, 19317 => 32553,
19318 => 29712, 19319 => 32034, 19320 => 38145, 19321 => 25152, 19322 => 22604, 19318 => 29712, 19319 => 32034, 19320 => 38145, 19321 => 25152, 19322 => 22604,
19323 => 20182, 19324 => 23427, 19325 => 22905, 19326 => 22612, 19489 => 29549, 19323 => 20182, 19324 => 23427, 19325 => 22905, 19326 => 22612, 19489 => 29549,
19490 => 25374, 19491 => 36427, 19492 => 36367, 19493 => 32974, 19494 => 33492, 19490 => 25374, 19491 => 36427, 19492 => 36367, 19493 => 32974, 19494 => 33492,
19495 => 25260, 19496 => 21488, 19497 => 27888, 19498 => 37214, 19499 => 22826, 19495 => 25260, 19496 => 21488, 19497 => 27888, 19498 => 37214, 19499 => 22826,
19500 => 24577, 19501 => 27760, 19502 => 22349, 19503 => 25674, 19504 => 36138, 19500 => 24577, 19501 => 27760, 19502 => 22349, 19503 => 25674, 19504 => 36138,
19505 => 30251, 19506 => 28393, 19507 => 22363, 19508 => 27264, 19509 => 30192, 19505 => 30251, 19506 => 28393, 19507 => 22363, 19508 => 27264, 19509 => 30192,
19510 => 28525, 19511 => 35885, 19512 => 35848, 19513 => 22374, 19514 => 27631, 19510 => 28525, 19511 => 35885, 19512 => 35848, 19513 => 22374, 19514 => 27631,
19515 => 34962, 19516 => 30899, 19517 => 25506, 19518 => 21497, 19519 => 28845, 19515 => 34962, 19516 => 30899, 19517 => 25506, 19518 => 21497, 19519 => 28845,
19520 => 27748, 19521 => 22616, 19522 => 25642, 19523 => 22530, 19524 => 26848, 19520 => 27748, 19521 => 22616, 19522 => 25642, 19523 => 22530, 19524 => 26848,
19525 => 33179, 19526 => 21776, 19527 => 31958, 19528 => 20504, 19529 => 36538, 19525 => 33179, 19526 => 21776, 19527 => 31958, 19528 => 20504, 19529 => 36538,
19530 => 28108, 19531 => 36255, 19532 => 28907, 19533 => 25487, 19534 => 28059, 19530 => 28108, 19531 => 36255, 19532 => 28907, 19533 => 25487, 19534 => 28059,
19535 => 28372, 19536 => 32486, 19537 => 33796, 19538 => 26691, 19539 => 36867, 19535 => 28372, 19536 => 32486, 19537 => 33796, 19538 => 26691, 19539 => 36867,
19540 => 28120, 19541 => 38518, 19542 => 35752, 19543 => 22871, 19544 => 29305, 19540 => 28120, 19541 => 38518, 19542 => 35752, 19543 => 22871, 19544 => 29305,
19545 => 34276, 19546 => 33150, 19547 => 30140, 19548 => 35466, 19549 => 26799, 19545 => 34276, 19546 => 33150, 19547 => 30140, 19548 => 35466, 19549 => 26799,
19550 => 21076, 19551 => 36386, 19552 => 38161, 19553 => 25552, 19554 => 39064, 19550 => 21076, 19551 => 36386, 19552 => 38161, 19553 => 25552, 19554 => 39064,
19555 => 36420, 19556 => 21884, 19557 => 20307, 19558 => 26367, 19559 => 22159, 19555 => 36420, 19556 => 21884, 19557 => 20307, 19558 => 26367, 19559 => 22159,
19560 => 24789, 19561 => 28053, 19562 => 21059, 19563 => 23625, 19564 => 22825, 19560 => 24789, 19561 => 28053, 19562 => 21059, 19563 => 23625, 19564 => 22825,
19565 => 28155, 19566 => 22635, 19567 => 30000, 19568 => 29980, 19569 => 24684, 19565 => 28155, 19566 => 22635, 19567 => 30000, 19568 => 29980, 19569 => 24684,
19570 => 33300, 19571 => 33094, 19572 => 25361, 19573 => 26465, 19574 => 36834, 19570 => 33300, 19571 => 33094, 19572 => 25361, 19573 => 26465, 19574 => 36834,
19575 => 30522, 19576 => 36339, 19577 => 36148, 19578 => 38081, 19579 => 24086, 19575 => 30522, 19576 => 36339, 19577 => 36148, 19578 => 38081, 19579 => 24086,
19580 => 21381, 19581 => 21548, 19582 => 28867, 19745 => 27712, 19746 => 24311, 19580 => 21381, 19581 => 21548, 19582 => 28867, 19745 => 27712, 19746 => 24311,
19747 => 20572, 19748 => 20141, 19749 => 24237, 19750 => 25402, 19751 => 33351, 19747 => 20572, 19748 => 20141, 19749 => 24237, 19750 => 25402, 19751 => 33351,
19752 => 36890, 19753 => 26704, 19754 => 37230, 19755 => 30643, 19756 => 21516, 19752 => 36890, 19753 => 26704, 19754 => 37230, 19755 => 30643, 19756 => 21516,
19757 => 38108, 19758 => 24420, 19759 => 31461, 19760 => 26742, 19761 => 25413, 19757 => 38108, 19758 => 24420, 19759 => 31461, 19760 => 26742, 19761 => 25413,
19762 => 31570, 19763 => 32479, 19764 => 30171, 19765 => 20599, 19766 => 25237, 19762 => 31570, 19763 => 32479, 19764 => 30171, 19765 => 20599, 19766 => 25237,
19767 => 22836, 19768 => 36879, 19769 => 20984, 19770 => 31171, 19771 => 31361, 19767 => 22836, 19768 => 36879, 19769 => 20984, 19770 => 31171, 19771 => 31361,
19772 => 22270, 19773 => 24466, 19774 => 36884, 19775 => 28034, 19776 => 23648, 19772 => 22270, 19773 => 24466, 19774 => 36884, 19775 => 28034, 19776 => 23648,
19777 => 22303, 19778 => 21520, 19779 => 20820, 19780 => 28237, 19781 => 22242, 19777 => 22303, 19778 => 21520, 19779 => 20820, 19780 => 28237, 19781 => 22242,
19782 => 25512, 19783 => 39059, 19784 => 33151, 19785 => 34581, 19786 => 35114, 19782 => 25512, 19783 => 39059, 19784 => 33151, 19785 => 34581, 19786 => 35114,
19787 => 36864, 19788 => 21534, 19789 => 23663, 19790 => 33216, 19791 => 25302, 19787 => 36864, 19788 => 21534, 19789 => 23663, 19790 => 33216, 19791 => 25302,
19792 => 25176, 19793 => 33073, 19794 => 40501, 19795 => 38464, 19796 => 39534, 19792 => 25176, 19793 => 33073, 19794 => 40501, 19795 => 38464, 19796 => 39534,
19797 => 39548, 19798 => 26925, 19799 => 22949, 19800 => 25299, 19801 => 21822, 19797 => 39548, 19798 => 26925, 19799 => 22949, 19800 => 25299, 19801 => 21822,
19802 => 25366, 19803 => 21703, 19804 => 34521, 19805 => 27964, 19806 => 23043, 19802 => 25366, 19803 => 21703, 19804 => 34521, 19805 => 27964, 19806 => 23043,
19807 => 29926, 19808 => 34972, 19809 => 27498, 19810 => 22806, 19811 => 35916, 19807 => 29926, 19808 => 34972, 19809 => 27498, 19810 => 22806, 19811 => 35916,
19812 => 24367, 19813 => 28286, 19814 => 29609, 19815 => 39037, 19816 => 20024, 19812 => 24367, 19813 => 28286, 19814 => 29609, 19815 => 39037, 19816 => 20024,
19817 => 28919, 19818 => 23436, 19819 => 30871, 19820 => 25405, 19821 => 26202, 19817 => 28919, 19818 => 23436, 19819 => 30871, 19820 => 25405, 19821 => 26202,
19822 => 30358, 19823 => 24779, 19824 => 23451, 19825 => 23113, 19826 => 19975, 19822 => 30358, 19823 => 24779, 19824 => 23451, 19825 => 23113, 19826 => 19975,
19827 => 33109, 19828 => 27754, 19829 => 29579, 19830 => 20129, 19831 => 26505, 19827 => 33109, 19828 => 27754, 19829 => 29579, 19830 => 20129, 19831 => 26505,
19832 => 32593, 19833 => 24448, 19834 => 26106, 19835 => 26395, 19836 => 24536, 19832 => 32593, 19833 => 24448, 19834 => 26106, 19835 => 26395, 19836 => 24536,
19837 => 22916, 19838 => 23041, 20001 => 24013, 20002 => 24494, 20003 => 21361, 19837 => 22916, 19838 => 23041, 20001 => 24013, 20002 => 24494, 20003 => 21361,
20004 => 38886, 20005 => 36829, 20006 => 26693, 20007 => 22260, 20008 => 21807, 20004 => 38886, 20005 => 36829, 20006 => 26693, 20007 => 22260, 20008 => 21807,
20009 => 24799, 20010 => 20026, 20011 => 28493, 20012 => 32500, 20013 => 33479, 20009 => 24799, 20010 => 20026, 20011 => 28493, 20012 => 32500, 20013 => 33479,
20014 => 33806, 20015 => 22996, 20016 => 20255, 20017 => 20266, 20018 => 23614, 20014 => 33806, 20015 => 22996, 20016 => 20255, 20017 => 20266, 20018 => 23614,
20019 => 32428, 20020 => 26410, 20021 => 34074, 20022 => 21619, 20023 => 30031, 20019 => 32428, 20020 => 26410, 20021 => 34074, 20022 => 21619, 20023 => 30031,
20024 => 32963, 20025 => 21890, 20026 => 39759, 20027 => 20301, 20028 => 28205, 20024 => 32963, 20025 => 21890, 20026 => 39759, 20027 => 20301, 20028 => 28205,
20029 => 35859, 20030 => 23561, 20031 => 24944, 20032 => 21355, 20033 => 30239, 20029 => 35859, 20030 => 23561, 20031 => 24944, 20032 => 21355, 20033 => 30239,
20034 => 28201, 20035 => 34442, 20036 => 25991, 20037 => 38395, 20038 => 32441, 20034 => 28201, 20035 => 34442, 20036 => 25991, 20037 => 38395, 20038 => 32441,
20039 => 21563, 20040 => 31283, 20041 => 32010, 20042 => 38382, 20043 => 21985, 20039 => 21563, 20040 => 31283, 20041 => 32010, 20042 => 38382, 20043 => 21985,
20044 => 32705, 20045 => 29934, 20046 => 25373, 20047 => 34583, 20048 => 28065, 20044 => 32705, 20045 => 29934, 20046 => 25373, 20047 => 34583, 20048 => 28065,
20049 => 31389, 20050 => 25105, 20051 => 26017, 20052 => 21351, 20053 => 25569, 20049 => 31389, 20050 => 25105, 20051 => 26017, 20052 => 21351, 20053 => 25569,
20054 => 27779, 20055 => 24043, 20056 => 21596, 20057 => 38056, 20058 => 20044, 20054 => 27779, 20055 => 24043, 20056 => 21596, 20057 => 38056, 20058 => 20044,
20059 => 27745, 20060 => 35820, 20061 => 23627, 20062 => 26080, 20063 => 33436, 20059 => 27745, 20060 => 35820, 20061 => 23627, 20062 => 26080, 20063 => 33436,
20064 => 26791, 20065 => 21566, 20066 => 21556, 20067 => 27595, 20068 => 27494, 20064 => 26791, 20065 => 21566, 20066 => 21556, 20067 => 27595, 20068 => 27494,
20069 => 20116, 20070 => 25410, 20071 => 21320, 20072 => 33310, 20073 => 20237, 20069 => 20116, 20070 => 25410, 20071 => 21320, 20072 => 33310, 20073 => 20237,
20074 => 20398, 20075 => 22366, 20076 => 25098, 20077 => 38654, 20078 => 26212, 20074 => 20398, 20075 => 22366, 20076 => 25098, 20077 => 38654, 20078 => 26212,
20079 => 29289, 20080 => 21247, 20081 => 21153, 20082 => 24735, 20083 => 35823, 20079 => 29289, 20080 => 21247, 20081 => 21153, 20082 => 24735, 20083 => 35823,
20084 => 26132, 20085 => 29081, 20086 => 26512, 20087 => 35199, 20088 => 30802, 20084 => 26132, 20085 => 29081, 20086 => 26512, 20087 => 35199, 20088 => 30802,
20089 => 30717, 20090 => 26224, 20091 => 22075, 20092 => 21560, 20093 => 38177, 20089 => 30717, 20090 => 26224, 20091 => 22075, 20092 => 21560, 20093 => 38177,
20094 => 29306, 20257 => 31232, 20258 => 24687, 20259 => 24076, 20260 => 24713, 20094 => 29306, 20257 => 31232, 20258 => 24687, 20259 => 24076, 20260 => 24713,
20261 => 33181, 20262 => 22805, 20263 => 24796, 20264 => 29060, 20265 => 28911, 20261 => 33181, 20262 => 22805, 20263 => 24796, 20264 => 29060, 20265 => 28911,
20266 => 28330, 20267 => 27728, 20268 => 29312, 20269 => 27268, 20270 => 34989, 20266 => 28330, 20267 => 27728, 20268 => 29312, 20269 => 27268, 20270 => 34989,
20271 => 24109, 20272 => 20064, 20273 => 23219, 20274 => 21916, 20275 => 38115, 20271 => 24109, 20272 => 20064, 20273 => 23219, 20274 => 21916, 20275 => 38115,
20276 => 27927, 20277 => 31995, 20278 => 38553, 20279 => 25103, 20280 => 32454, 20276 => 27927, 20277 => 31995, 20278 => 38553, 20279 => 25103, 20280 => 32454,
20281 => 30606, 20282 => 34430, 20283 => 21283, 20284 => 38686, 20285 => 36758, 20281 => 30606, 20282 => 34430, 20283 => 21283, 20284 => 38686, 20285 => 36758,
20286 => 26247, 20287 => 23777, 20288 => 20384, 20289 => 29421, 20290 => 19979, 20286 => 26247, 20287 => 23777, 20288 => 20384, 20289 => 29421, 20290 => 19979,
20291 => 21414, 20292 => 22799, 20293 => 21523, 20294 => 25472, 20295 => 38184, 20291 => 21414, 20292 => 22799, 20293 => 21523, 20294 => 25472, 20295 => 38184,
20296 => 20808, 20297 => 20185, 20298 => 40092, 20299 => 32420, 20300 => 21688, 20296 => 20808, 20297 => 20185, 20298 => 40092, 20299 => 32420, 20300 => 21688,
20301 => 36132, 20302 => 34900, 20303 => 33335, 20304 => 38386, 20305 => 28046, 20301 => 36132, 20302 => 34900, 20303 => 33335, 20304 => 38386, 20305 => 28046,
20306 => 24358, 20307 => 23244, 20308 => 26174, 20309 => 38505, 20310 => 29616, 20306 => 24358, 20307 => 23244, 20308 => 26174, 20309 => 38505, 20310 => 29616,
20311 => 29486, 20312 => 21439, 20313 => 33146, 20314 => 39301, 20315 => 32673, 20311 => 29486, 20312 => 21439, 20313 => 33146, 20314 => 39301, 20315 => 32673,
20316 => 23466, 20317 => 38519, 20318 => 38480, 20319 => 32447, 20320 => 30456, 20316 => 23466, 20317 => 38519, 20318 => 38480, 20319 => 32447, 20320 => 30456,
20321 => 21410, 20322 => 38262, 20323 => 39321, 20324 => 31665, 20325 => 35140, 20321 => 21410, 20322 => 38262, 20323 => 39321, 20324 => 31665, 20325 => 35140,
20326 => 28248, 20327 => 20065, 20328 => 32724, 20329 => 31077, 20330 => 35814, 20326 => 28248, 20327 => 20065, 20328 => 32724, 20329 => 31077, 20330 => 35814,
20331 => 24819, 20332 => 21709, 20333 => 20139, 20334 => 39033, 20335 => 24055, 20331 => 24819, 20332 => 21709, 20333 => 20139, 20334 => 39033, 20335 => 24055,
20336 => 27233, 20337 => 20687, 20338 => 21521, 20339 => 35937, 20340 => 33831, 20336 => 27233, 20337 => 20687, 20338 => 21521, 20339 => 35937, 20340 => 33831,
20341 => 30813, 20342 => 38660, 20343 => 21066, 20344 => 21742, 20345 => 22179, 20341 => 30813, 20342 => 38660, 20343 => 21066, 20344 => 21742, 20345 => 22179,
20346 => 38144, 20347 => 28040, 20348 => 23477, 20349 => 28102, 20350 => 26195, 20346 => 38144, 20347 => 28040, 20348 => 23477, 20349 => 28102, 20350 => 26195,
20513 => 23567, 20514 => 23389, 20515 => 26657, 20516 => 32918, 20517 => 21880, 20513 => 23567, 20514 => 23389, 20515 => 26657, 20516 => 32918, 20517 => 21880,
20518 => 31505, 20519 => 25928, 20520 => 26964, 20521 => 20123, 20522 => 27463, 20518 => 31505, 20519 => 25928, 20520 => 26964, 20521 => 20123, 20522 => 27463,
20523 => 34638, 20524 => 38795, 20525 => 21327, 20526 => 25375, 20527 => 25658, 20523 => 34638, 20524 => 38795, 20525 => 21327, 20526 => 25375, 20527 => 25658,
20528 => 37034, 20529 => 26012, 20530 => 32961, 20531 => 35856, 20532 => 20889, 20528 => 37034, 20529 => 26012, 20530 => 32961, 20531 => 35856, 20532 => 20889,
20533 => 26800, 20534 => 21368, 20535 => 34809, 20536 => 25032, 20537 => 27844, 20533 => 26800, 20534 => 21368, 20535 => 34809, 20536 => 25032, 20537 => 27844,
20538 => 27899, 20539 => 35874, 20540 => 23633, 20541 => 34218, 20542 => 33455, 20538 => 27899, 20539 => 35874, 20540 => 23633, 20541 => 34218, 20542 => 33455,
20543 => 38156, 20544 => 27427, 20545 => 36763, 20546 => 26032, 20547 => 24571, 20543 => 38156, 20544 => 27427, 20545 => 36763, 20546 => 26032, 20547 => 24571,
20548 => 24515, 20549 => 20449, 20550 => 34885, 20551 => 26143, 20552 => 33125, 20548 => 24515, 20549 => 20449, 20550 => 34885, 20551 => 26143, 20552 => 33125,
20553 => 29481, 20554 => 24826, 20555 => 20852, 20556 => 21009, 20557 => 22411, 20553 => 29481, 20554 => 24826, 20555 => 20852, 20556 => 21009, 20557 => 22411,
20558 => 24418, 20559 => 37026, 20560 => 34892, 20561 => 37266, 20562 => 24184, 20558 => 24418, 20559 => 37026, 20560 => 34892, 20561 => 37266, 20562 => 24184,
20563 => 26447, 20564 => 24615, 20565 => 22995, 20566 => 20804, 20567 => 20982, 20563 => 26447, 20564 => 24615, 20565 => 22995, 20566 => 20804, 20567 => 20982,
20568 => 33016, 20569 => 21256, 20570 => 27769, 20571 => 38596, 20572 => 29066, 20568 => 33016, 20569 => 21256, 20570 => 27769, 20571 => 38596, 20572 => 29066,
20573 => 20241, 20574 => 20462, 20575 => 32670, 20576 => 26429, 20577 => 21957, 20573 => 20241, 20574 => 20462, 20575 => 32670, 20576 => 26429, 20577 => 21957,
20578 => 38152, 20579 => 31168, 20580 => 34966, 20581 => 32483, 20582 => 22687, 20578 => 38152, 20579 => 31168, 20580 => 34966, 20581 => 32483, 20582 => 22687,
20583 => 25100, 20584 => 38656, 20585 => 34394, 20586 => 22040, 20587 => 39035, 20583 => 25100, 20584 => 38656, 20585 => 34394, 20586 => 22040, 20587 => 39035,
20588 => 24464, 20589 => 35768, 20590 => 33988, 20591 => 37207, 20592 => 21465, 20588 => 24464, 20589 => 35768, 20590 => 33988, 20591 => 37207, 20592 => 21465,
20593 => 26093, 20594 => 24207, 20595 => 30044, 20596 => 24676, 20597 => 32110, 20593 => 26093, 20594 => 24207, 20595 => 30044, 20596 => 24676, 20597 => 32110,
20598 => 23167, 20599 => 32490, 20600 => 32493, 20601 => 36713, 20602 => 21927, 20598 => 23167, 20599 => 32490, 20600 => 32493, 20601 => 36713, 20602 => 21927,
20603 => 23459, 20604 => 24748, 20605 => 26059, 20606 => 29572, 20769 => 36873, 20603 => 23459, 20604 => 24748, 20605 => 26059, 20606 => 29572, 20769 => 36873,
20770 => 30307, 20771 => 30505, 20772 => 32474, 20773 => 38772, 20774 => 34203, 20770 => 30307, 20771 => 30505, 20772 => 32474, 20773 => 38772, 20774 => 34203,
20775 => 23398, 20776 => 31348, 20777 => 38634, 20778 => 34880, 20779 => 21195, 20775 => 23398, 20776 => 31348, 20777 => 38634, 20778 => 34880, 20779 => 21195,
20780 => 29071, 20781 => 24490, 20782 => 26092, 20783 => 35810, 20784 => 23547, 20780 => 29071, 20781 => 24490, 20782 => 26092, 20783 => 35810, 20784 => 23547,
20785 => 39535, 20786 => 24033, 20787 => 27529, 20788 => 27739, 20789 => 35757, 20785 => 39535, 20786 => 24033, 20787 => 27529, 20788 => 27739, 20789 => 35757,
20790 => 35759, 20791 => 36874, 20792 => 36805, 20793 => 21387, 20794 => 25276, 20790 => 35759, 20791 => 36874, 20792 => 36805, 20793 => 21387, 20794 => 25276,
20795 => 40486, 20796 => 40493, 20797 => 21568, 20798 => 20011, 20799 => 33469, 20795 => 40486, 20796 => 40493, 20797 => 21568, 20798 => 20011, 20799 => 33469,
20800 => 29273, 20801 => 34460, 20802 => 23830, 20803 => 34905, 20804 => 28079, 20800 => 29273, 20801 => 34460, 20802 => 23830, 20803 => 34905, 20804 => 28079,
20805 => 38597, 20806 => 21713, 20807 => 20122, 20808 => 35766, 20809 => 28937, 20805 => 38597, 20806 => 21713, 20807 => 20122, 20808 => 35766, 20809 => 28937,
20810 => 21693, 20811 => 38409, 20812 => 28895, 20813 => 28153, 20814 => 30416, 20810 => 21693, 20811 => 38409, 20812 => 28895, 20813 => 28153, 20814 => 30416,
20815 => 20005, 20816 => 30740, 20817 => 34578, 20818 => 23721, 20819 => 24310, 20815 => 20005, 20816 => 30740, 20817 => 34578, 20818 => 23721, 20819 => 24310,
20820 => 35328, 20821 => 39068, 20822 => 38414, 20823 => 28814, 20824 => 27839, 20820 => 35328, 20821 => 39068, 20822 => 38414, 20823 => 28814, 20824 => 27839,
20825 => 22852, 20826 => 25513, 20827 => 30524, 20828 => 34893, 20829 => 28436, 20825 => 22852, 20826 => 25513, 20827 => 30524, 20828 => 34893, 20829 => 28436,
20830 => 33395, 20831 => 22576, 20832 => 29141, 20833 => 21388, 20834 => 30746, 20830 => 33395, 20831 => 22576, 20832 => 29141, 20833 => 21388, 20834 => 30746,
20835 => 38593, 20836 => 21761, 20837 => 24422, 20838 => 28976, 20839 => 23476, 20835 => 38593, 20836 => 21761, 20837 => 24422, 20838 => 28976, 20839 => 23476,
20840 => 35866, 20841 => 39564, 20842 => 27523, 20843 => 22830, 20844 => 40495, 20840 => 35866, 20841 => 39564, 20842 => 27523, 20843 => 22830, 20844 => 40495,
20845 => 31207, 20846 => 26472, 20847 => 25196, 20848 => 20335, 20849 => 30113, 20845 => 31207, 20846 => 26472, 20847 => 25196, 20848 => 20335, 20849 => 30113,
20850 => 32650, 20851 => 27915, 20852 => 38451, 20853 => 27687, 20854 => 20208, 20850 => 32650, 20851 => 27915, 20852 => 38451, 20853 => 27687, 20854 => 20208,
20855 => 30162, 20856 => 20859, 20857 => 26679, 20858 => 28478, 20859 => 36992, 20855 => 30162, 20856 => 20859, 20857 => 26679, 20858 => 28478, 20859 => 36992,
20860 => 33136, 20861 => 22934, 20862 => 29814, 21025 => 25671, 21026 => 23591, 20860 => 33136, 20861 => 22934, 20862 => 29814, 21025 => 25671, 21026 => 23591,
21027 => 36965, 21028 => 31377, 21029 => 35875, 21030 => 23002, 21031 => 21676, 21027 => 36965, 21028 => 31377, 21029 => 35875, 21030 => 23002, 21031 => 21676,
21032 => 33280, 21033 => 33647, 21034 => 35201, 21035 => 32768, 21036 => 26928, 21032 => 33280, 21033 => 33647, 21034 => 35201, 21035 => 32768, 21036 => 26928,
21037 => 22094, 21038 => 32822, 21039 => 29239, 21040 => 37326, 21041 => 20918, 21037 => 22094, 21038 => 32822, 21039 => 29239, 21040 => 37326, 21041 => 20918,
21042 => 20063, 21043 => 39029, 21044 => 25494, 21045 => 19994, 21046 => 21494, 21042 => 20063, 21043 => 39029, 21044 => 25494, 21045 => 19994, 21046 => 21494,
21047 => 26355, 21048 => 33099, 21049 => 22812, 21050 => 28082, 21051 => 19968, 21047 => 26355, 21048 => 33099, 21049 => 22812, 21050 => 28082, 21051 => 19968,
21052 => 22777, 21053 => 21307, 21054 => 25558, 21055 => 38129, 21056 => 20381, 21052 => 22777, 21053 => 21307, 21054 => 25558, 21055 => 38129, 21056 => 20381,
21057 => 20234, 21058 => 34915, 21059 => 39056, 21060 => 22839, 21061 => 36951, 21057 => 20234, 21058 => 34915, 21059 => 39056, 21060 => 22839, 21061 => 36951,
21062 => 31227, 21063 => 20202, 21064 => 33008, 21065 => 30097, 21066 => 27778, 21062 => 31227, 21063 => 20202, 21064 => 33008, 21065 => 30097, 21066 => 27778,
21067 => 23452, 21068 => 23016, 21069 => 24413, 21070 => 26885, 21071 => 34433, 21067 => 23452, 21068 => 23016, 21069 => 24413, 21070 => 26885, 21071 => 34433,
21072 => 20506, 21073 => 24050, 21074 => 20057, 21075 => 30691, 21076 => 20197, 21072 => 20506, 21073 => 24050, 21074 => 20057, 21075 => 30691, 21076 => 20197,
21077 => 33402, 21078 => 25233, 21079 => 26131, 21080 => 37009, 21081 => 23673, 21077 => 33402, 21078 => 25233, 21079 => 26131, 21080 => 37009, 21081 => 23673,
21082 => 20159, 21083 => 24441, 21084 => 33222, 21085 => 36920, 21086 => 32900, 21082 => 20159, 21083 => 24441, 21084 => 33222, 21085 => 36920, 21086 => 32900,
21087 => 30123, 21088 => 20134, 21089 => 35028, 21090 => 24847, 21091 => 27589, 21087 => 30123, 21088 => 20134, 21089 => 35028, 21090 => 24847, 21091 => 27589,
21092 => 24518, 21093 => 20041, 21094 => 30410, 21095 => 28322, 21096 => 35811, 21092 => 24518, 21093 => 20041, 21094 => 30410, 21095 => 28322, 21096 => 35811,
21097 => 35758, 21098 => 35850, 21099 => 35793, 21100 => 24322, 21101 => 32764, 21097 => 35758, 21098 => 35850, 21099 => 35793, 21100 => 24322, 21101 => 32764,
21102 => 32716, 21103 => 32462, 21104 => 33589, 21105 => 33643, 21106 => 22240, 21102 => 32716, 21103 => 32462, 21104 => 33589, 21105 => 33643, 21106 => 22240,
21107 => 27575, 21108 => 38899, 21109 => 38452, 21110 => 23035, 21111 => 21535, 21107 => 27575, 21108 => 38899, 21109 => 38452, 21110 => 23035, 21111 => 21535,
21112 => 38134, 21113 => 28139, 21114 => 23493, 21115 => 39278, 21116 => 23609, 21112 => 38134, 21113 => 28139, 21114 => 23493, 21115 => 39278, 21116 => 23609,
21117 => 24341, 21118 => 38544, 21281 => 21360, 21282 => 33521, 21283 => 27185, 21117 => 24341, 21118 => 38544, 21281 => 21360, 21282 => 33521, 21283 => 27185,
21284 => 23156, 21285 => 40560, 21286 => 24212, 21287 => 32552, 21288 => 33721, 21284 => 23156, 21285 => 40560, 21286 => 24212, 21287 => 32552, 21288 => 33721,
21289 => 33828, 21290 => 33829, 21291 => 33639, 21292 => 34631, 21293 => 36814, 21289 => 33828, 21290 => 33829, 21291 => 33639, 21292 => 34631, 21293 => 36814,
21294 => 36194, 21295 => 30408, 21296 => 24433, 21297 => 39062, 21298 => 30828, 21294 => 36194, 21295 => 30408, 21296 => 24433, 21297 => 39062, 21298 => 30828,
21299 => 26144, 21300 => 21727, 21301 => 25317, 21302 => 20323, 21303 => 33219, 21299 => 26144, 21300 => 21727, 21301 => 25317, 21302 => 20323, 21303 => 33219,
21304 => 30152, 21305 => 24248, 21306 => 38605, 21307 => 36362, 21308 => 34553, 21304 => 30152, 21305 => 24248, 21306 => 38605, 21307 => 36362, 21308 => 34553,
21309 => 21647, 21310 => 27891, 21311 => 28044, 21312 => 27704, 21313 => 24703, 21309 => 21647, 21310 => 27891, 21311 => 28044, 21312 => 27704, 21313 => 24703,
21314 => 21191, 21315 => 29992, 21316 => 24189, 21317 => 20248, 21318 => 24736, 21314 => 21191, 21315 => 29992, 21316 => 24189, 21317 => 20248, 21318 => 24736,
21319 => 24551, 21320 => 23588, 21321 => 30001, 21322 => 37038, 21323 => 38080, 21319 => 24551, 21320 => 23588, 21321 => 30001, 21322 => 37038, 21323 => 38080,
21324 => 29369, 21325 => 27833, 21326 => 28216, 21327 => 37193, 21328 => 26377, 21324 => 29369, 21325 => 27833, 21326 => 28216, 21327 => 37193, 21328 => 26377,
21329 => 21451, 21330 => 21491, 21331 => 20305, 21332 => 37321, 21333 => 35825, 21329 => 21451, 21330 => 21491, 21331 => 20305, 21332 => 37321, 21333 => 35825,
21334 => 21448, 21335 => 24188, 21336 => 36802, 21337 => 28132, 21338 => 20110, 21334 => 21448, 21335 => 24188, 21336 => 36802, 21337 => 28132, 21338 => 20110,
21339 => 30402, 21340 => 27014, 21341 => 34398, 21342 => 24858, 21343 => 33286, 21339 => 30402, 21340 => 27014, 21341 => 34398, 21342 => 24858, 21343 => 33286,
21344 => 20313, 21345 => 20446, 21346 => 36926, 21347 => 40060, 21348 => 24841, 21344 => 20313, 21345 => 20446, 21346 => 36926, 21347 => 40060, 21348 => 24841,
21349 => 28189, 21350 => 28180, 21351 => 38533, 21352 => 20104, 21353 => 23089, 21349 => 28189, 21350 => 28180, 21351 => 38533, 21352 => 20104, 21353 => 23089,
21354 => 38632, 21355 => 19982, 21356 => 23679, 21357 => 31161, 21358 => 23431, 21354 => 38632, 21355 => 19982, 21356 => 23679, 21357 => 31161, 21358 => 23431,
21359 => 35821, 21360 => 32701, 21361 => 29577, 21362 => 22495, 21363 => 33419, 21359 => 35821, 21360 => 32701, 21361 => 29577, 21362 => 22495, 21363 => 33419,
21364 => 37057, 21365 => 21505, 21366 => 36935, 21367 => 21947, 21368 => 23786, 21364 => 37057, 21365 => 21505, 21366 => 36935, 21367 => 21947, 21368 => 23786,
21369 => 24481, 21370 => 24840, 21371 => 27442, 21372 => 29425, 21373 => 32946, 21369 => 24481, 21370 => 24840, 21371 => 27442, 21372 => 29425, 21373 => 32946,
21374 => 35465, 21537 => 28020, 21538 => 23507, 21539 => 35029, 21540 => 39044, 21374 => 35465, 21537 => 28020, 21538 => 23507, 21539 => 35029, 21540 => 39044,
21541 => 35947, 21542 => 39533, 21543 => 40499, 21544 => 28170, 21545 => 20900, 21541 => 35947, 21542 => 39533, 21543 => 40499, 21544 => 28170, 21545 => 20900,
21546 => 20803, 21547 => 22435, 21548 => 34945, 21549 => 21407, 21550 => 25588, 21546 => 20803, 21547 => 22435, 21548 => 34945, 21549 => 21407, 21550 => 25588,
21551 => 36757, 21552 => 22253, 21553 => 21592, 21554 => 22278, 21555 => 29503, 21551 => 36757, 21552 => 22253, 21553 => 21592, 21554 => 22278, 21555 => 29503,
21556 => 28304, 21557 => 32536, 21558 => 36828, 21559 => 33489, 21560 => 24895, 21556 => 28304, 21557 => 32536, 21558 => 36828, 21559 => 33489, 21560 => 24895,
21561 => 24616, 21562 => 38498, 21563 => 26352, 21564 => 32422, 21565 => 36234, 21561 => 24616, 21562 => 38498, 21563 => 26352, 21564 => 32422, 21565 => 36234,
21566 => 36291, 21567 => 38053, 21568 => 23731, 21569 => 31908, 21570 => 26376, 21566 => 36291, 21567 => 38053, 21568 => 23731, 21569 => 31908, 21570 => 26376,
21571 => 24742, 21572 => 38405, 21573 => 32792, 21574 => 20113, 21575 => 37095, 21571 => 24742, 21572 => 38405, 21573 => 32792, 21574 => 20113, 21575 => 37095,
21576 => 21248, 21577 => 38504, 21578 => 20801, 21579 => 36816, 21580 => 34164, 21576 => 21248, 21577 => 38504, 21578 => 20801, 21579 => 36816, 21580 => 34164,
21581 => 37213, 21582 => 26197, 21583 => 38901, 21584 => 23381, 21585 => 21277, 21581 => 37213, 21582 => 26197, 21583 => 38901, 21584 => 23381, 21585 => 21277,
21586 => 30776, 21587 => 26434, 21588 => 26685, 21589 => 21705, 21590 => 28798, 21586 => 30776, 21587 => 26434, 21588 => 26685, 21589 => 21705, 21590 => 28798,
21591 => 23472, 21592 => 36733, 21593 => 20877, 21594 => 22312, 21595 => 21681, 21591 => 23472, 21592 => 36733, 21593 => 20877, 21594 => 22312, 21595 => 21681,
21596 => 25874, 21597 => 26242, 21598 => 36190, 21599 => 36163, 21600 => 33039, 21596 => 25874, 21597 => 26242, 21598 => 36190, 21599 => 36163, 21600 => 33039,
21601 => 33900, 21602 => 36973, 21603 => 31967, 21604 => 20991, 21605 => 34299, 21601 => 33900, 21602 => 36973, 21603 => 31967, 21604 => 20991, 21605 => 34299,
21606 => 26531, 21607 => 26089, 21608 => 28577, 21609 => 34468, 21610 => 36481, 21606 => 26531, 21607 => 26089, 21608 => 28577, 21609 => 34468, 21610 => 36481,
21611 => 22122, 21612 => 36896, 21613 => 30338, 21614 => 28790, 21615 => 29157, 21611 => 22122, 21612 => 36896, 21613 => 30338, 21614 => 28790, 21615 => 29157,
21616 => 36131, 21617 => 25321, 21618 => 21017, 21619 => 27901, 21620 => 36156, 21616 => 36131, 21617 => 25321, 21618 => 21017, 21619 => 27901, 21620 => 36156,
21621 => 24590, 21622 => 22686, 21623 => 24974, 21624 => 26366, 21625 => 36192, 21621 => 24590, 21622 => 22686, 21623 => 24974, 21624 => 26366, 21625 => 36192,
21626 => 25166, 21627 => 21939, 21628 => 28195, 21629 => 26413, 21630 => 36711, 21626 => 25166, 21627 => 21939, 21628 => 28195, 21629 => 26413, 21630 => 36711,
21793 => 38113, 21794 => 38392, 21795 => 30504, 21796 => 26629, 21797 => 27048, 21793 => 38113, 21794 => 38392, 21795 => 30504, 21796 => 26629, 21797 => 27048,
21798 => 21643, 21799 => 20045, 21800 => 28856, 21801 => 35784, 21802 => 25688, 21798 => 21643, 21799 => 20045, 21800 => 28856, 21801 => 35784, 21802 => 25688,
21803 => 25995, 21804 => 23429, 21805 => 31364, 21806 => 20538, 21807 => 23528, 21803 => 25995, 21804 => 23429, 21805 => 31364, 21806 => 20538, 21807 => 23528,
21808 => 30651, 21809 => 27617, 21810 => 35449, 21811 => 31896, 21812 => 27838, 21808 => 30651, 21809 => 27617, 21810 => 35449, 21811 => 31896, 21812 => 27838,
21813 => 30415, 21814 => 26025, 21815 => 36759, 21816 => 23853, 21817 => 23637, 21813 => 30415, 21814 => 26025, 21815 => 36759, 21816 => 23853, 21817 => 23637,
21818 => 34360, 21819 => 26632, 21820 => 21344, 21821 => 25112, 21822 => 31449, 21818 => 34360, 21819 => 26632, 21820 => 21344, 21821 => 25112, 21822 => 31449,
21823 => 28251, 21824 => 32509, 21825 => 27167, 21826 => 31456, 21827 => 24432, 21823 => 28251, 21824 => 32509, 21825 => 27167, 21826 => 31456, 21827 => 24432,
21828 => 28467, 21829 => 24352, 21830 => 25484, 21831 => 28072, 21832 => 26454, 21828 => 28467, 21829 => 24352, 21830 => 25484, 21831 => 28072, 21832 => 26454,
21833 => 19976, 21834 => 24080, 21835 => 36134, 21836 => 20183, 21837 => 32960, 21833 => 19976, 21834 => 24080, 21835 => 36134, 21836 => 20183, 21837 => 32960,
21838 => 30260, 21839 => 38556, 21840 => 25307, 21841 => 26157, 21842 => 25214, 21838 => 30260, 21839 => 38556, 21840 => 25307, 21841 => 26157, 21842 => 25214,
21843 => 27836, 21844 => 36213, 21845 => 29031, 21846 => 32617, 21847 => 20806, 21843 => 27836, 21844 => 36213, 21845 => 29031, 21846 => 32617, 21847 => 20806,
21848 => 32903, 21849 => 21484, 21850 => 36974, 21851 => 25240, 21852 => 21746, 21848 => 32903, 21849 => 21484, 21850 => 36974, 21851 => 25240, 21852 => 21746,
21853 => 34544, 21854 => 36761, 21855 => 32773, 21856 => 38167, 21857 => 34071, 21853 => 34544, 21854 => 36761, 21855 => 32773, 21856 => 38167, 21857 => 34071,
21858 => 36825, 21859 => 27993, 21860 => 29645, 21861 => 26015, 21862 => 30495, 21858 => 36825, 21859 => 27993, 21860 => 29645, 21861 => 26015, 21862 => 30495,
21863 => 29956, 21864 => 30759, 21865 => 33275, 21866 => 36126, 21867 => 38024, 21863 => 29956, 21864 => 30759, 21865 => 33275, 21866 => 36126, 21867 => 38024,
21868 => 20390, 21869 => 26517, 21870 => 30137, 21871 => 35786, 21872 => 38663, 21868 => 20390, 21869 => 26517, 21870 => 30137, 21871 => 35786, 21872 => 38663,
21873 => 25391, 21874 => 38215, 21875 => 38453, 21876 => 33976, 21877 => 25379, 21873 => 25391, 21874 => 38215, 21875 => 38453, 21876 => 33976, 21877 => 25379,
21878 => 30529, 21879 => 24449, 21880 => 29424, 21881 => 20105, 21882 => 24596, 21878 => 30529, 21879 => 24449, 21880 => 29424, 21881 => 20105, 21882 => 24596,
21883 => 25972, 21884 => 25327, 21885 => 27491, 21886 => 25919, 22049 => 24103, 21883 => 25972, 21884 => 25327, 21885 => 27491, 21886 => 25919, 22049 => 24103,
22050 => 30151, 22051 => 37073, 22052 => 35777, 22053 => 33437, 22054 => 26525, 22050 => 30151, 22051 => 37073, 22052 => 35777, 22053 => 33437, 22054 => 26525,
22055 => 25903, 22056 => 21553, 22057 => 34584, 22058 => 30693, 22059 => 32930, 22055 => 25903, 22056 => 21553, 22057 => 34584, 22058 => 30693, 22059 => 32930,
22060 => 33026, 22061 => 27713, 22062 => 20043, 22063 => 32455, 22064 => 32844, 22060 => 33026, 22061 => 27713, 22062 => 20043, 22063 => 32455, 22064 => 32844,
22065 => 30452, 22066 => 26893, 22067 => 27542, 22068 => 25191, 22069 => 20540, 22065 => 30452, 22066 => 26893, 22067 => 27542, 22068 => 25191, 22069 => 20540,
22070 => 20356, 22071 => 22336, 22072 => 25351, 22073 => 27490, 22074 => 36286, 22070 => 20356, 22071 => 22336, 22072 => 25351, 22073 => 27490, 22074 => 36286,
22075 => 21482, 22076 => 26088, 22077 => 32440, 22078 => 24535, 22079 => 25370, 22075 => 21482, 22076 => 26088, 22077 => 32440, 22078 => 24535, 22079 => 25370,
22080 => 25527, 22081 => 33267, 22082 => 33268, 22083 => 32622, 22084 => 24092, 22080 => 25527, 22081 => 33267, 22082 => 33268, 22083 => 32622, 22084 => 24092,
22085 => 23769, 22086 => 21046, 22087 => 26234, 22088 => 31209, 22089 => 31258, 22085 => 23769, 22086 => 21046, 22087 => 26234, 22088 => 31209, 22089 => 31258,
22090 => 36136, 22091 => 28825, 22092 => 30164, 22093 => 28382, 22094 => 27835, 22090 => 36136, 22091 => 28825, 22092 => 30164, 22093 => 28382, 22094 => 27835,
22095 => 31378, 22096 => 20013, 22097 => 30405, 22098 => 24544, 22099 => 38047, 22095 => 31378, 22096 => 20013, 22097 => 30405, 22098 => 24544, 22099 => 38047,
22100 => 34935, 22101 => 32456, 22102 => 31181, 22103 => 32959, 22104 => 37325, 22100 => 34935, 22101 => 32456, 22102 => 31181, 22103 => 32959, 22104 => 37325,
22105 => 20210, 22106 => 20247, 22107 => 33311, 22108 => 21608, 22109 => 24030, 22105 => 20210, 22106 => 20247, 22107 => 33311, 22108 => 21608, 22109 => 24030,
22110 => 27954, 22111 => 35788, 22112 => 31909, 22113 => 36724, 22114 => 32920, 22110 => 27954, 22111 => 35788, 22112 => 31909, 22113 => 36724, 22114 => 32920,
22115 => 24090, 22116 => 21650, 22117 => 30385, 22118 => 23449, 22119 => 26172, 22115 => 24090, 22116 => 21650, 22117 => 30385, 22118 => 23449, 22119 => 26172,
22120 => 39588, 22121 => 29664, 22122 => 26666, 22123 => 34523, 22124 => 26417, 22120 => 39588, 22121 => 29664, 22122 => 26666, 22123 => 34523, 22124 => 26417,
22125 => 29482, 22126 => 35832, 22127 => 35803, 22128 => 36880, 22129 => 31481, 22125 => 29482, 22126 => 35832, 22127 => 35803, 22128 => 36880, 22129 => 31481,
22130 => 28891, 22131 => 29038, 22132 => 25284, 22133 => 30633, 22134 => 22065, 22130 => 28891, 22131 => 29038, 22132 => 25284, 22133 => 30633, 22134 => 22065,
22135 => 20027, 22136 => 33879, 22137 => 26609, 22138 => 21161, 22139 => 34496, 22135 => 20027, 22136 => 33879, 22137 => 26609, 22138 => 21161, 22139 => 34496,
22140 => 36142, 22141 => 38136, 22142 => 31569, 22305 => 20303, 22306 => 27880, 22140 => 36142, 22141 => 38136, 22142 => 31569, 22305 => 20303, 22306 => 27880,
22307 => 31069, 22308 => 39547, 22309 => 25235, 22310 => 29226, 22311 => 25341, 22307 => 31069, 22308 => 39547, 22309 => 25235, 22310 => 29226, 22311 => 25341,
22312 => 19987, 22313 => 30742, 22314 => 36716, 22315 => 25776, 22316 => 36186, 22312 => 19987, 22313 => 30742, 22314 => 36716, 22315 => 25776, 22316 => 36186,
22317 => 31686, 22318 => 26729, 22319 => 24196, 22320 => 35013, 22321 => 22918, 22317 => 31686, 22318 => 26729, 22319 => 24196, 22320 => 35013, 22321 => 22918,
22322 => 25758, 22323 => 22766, 22324 => 29366, 22325 => 26894, 22326 => 38181, 22322 => 25758, 22323 => 22766, 22324 => 29366, 22325 => 26894, 22326 => 38181,
22327 => 36861, 22328 => 36184, 22329 => 22368, 22330 => 32512, 22331 => 35846, 22327 => 36861, 22328 => 36184, 22329 => 22368, 22330 => 32512, 22331 => 35846,
22332 => 20934, 22333 => 25417, 22334 => 25305, 22335 => 21331, 22336 => 26700, 22332 => 20934, 22333 => 25417, 22334 => 25305, 22335 => 21331, 22336 => 26700,
22337 => 29730, 22338 => 33537, 22339 => 37196, 22340 => 21828, 22341 => 30528, 22337 => 29730, 22338 => 33537, 22339 => 37196, 22340 => 21828, 22341 => 30528,
22342 => 28796, 22343 => 27978, 22344 => 20857, 22345 => 21672, 22346 => 36164, 22342 => 28796, 22343 => 27978, 22344 => 20857, 22345 => 21672, 22346 => 36164,
22347 => 23039, 22348 => 28363, 22349 => 28100, 22350 => 23388, 22351 => 32043, 22347 => 23039, 22348 => 28363, 22349 => 28100, 22350 => 23388, 22351 => 32043,
22352 => 20180, 22353 => 31869, 22354 => 28371, 22355 => 23376, 22356 => 33258, 22352 => 20180, 22353 => 31869, 22354 => 28371, 22355 => 23376, 22356 => 33258,
22357 => 28173, 22358 => 23383, 22359 => 39683, 22360 => 26837, 22361 => 36394, 22357 => 28173, 22358 => 23383, 22359 => 39683, 22360 => 26837, 22361 => 36394,
22362 => 23447, 22363 => 32508, 22364 => 24635, 22365 => 32437, 22366 => 37049, 22362 => 23447, 22363 => 32508, 22364 => 24635, 22365 => 32437, 22366 => 37049,
22367 => 36208, 22368 => 22863, 22369 => 25549, 22370 => 31199, 22371 => 36275, 22367 => 36208, 22368 => 22863, 22369 => 25549, 22370 => 31199, 22371 => 36275,
22372 => 21330, 22373 => 26063, 22374 => 31062, 22375 => 35781, 22376 => 38459, 22372 => 21330, 22373 => 26063, 22374 => 31062, 22375 => 35781, 22376 => 38459,
22377 => 32452, 22378 => 38075, 22379 => 32386, 22380 => 22068, 22381 => 37257, 22377 => 32452, 22378 => 38075, 22379 => 32386, 22380 => 22068, 22381 => 37257,
22382 => 26368, 22383 => 32618, 22384 => 23562, 22385 => 36981, 22386 => 26152, 22382 => 26368, 22383 => 32618, 22384 => 23562, 22385 => 36981, 22386 => 26152,
22387 => 24038, 22388 => 20304, 22389 => 26590, 22390 => 20570, 22391 => 20316, 22387 => 24038, 22388 => 20304, 22389 => 26590, 22390 => 20570, 22391 => 20316,
22392 => 22352, 22393 => 24231, 22561 => 20109, 22562 => 19980, 22563 => 20800, 22392 => 22352, 22393 => 24231, 22561 => 20109, 22562 => 19980, 22563 => 20800,
22564 => 19984, 22565 => 24319, 22566 => 21317, 22567 => 19989, 22568 => 20120, 22564 => 19984, 22565 => 24319, 22566 => 21317, 22567 => 19989, 22568 => 20120,
22569 => 19998, 22570 => 39730, 22571 => 23404, 22572 => 22121, 22573 => 20008, 22569 => 19998, 22570 => 39730, 22571 => 23404, 22572 => 22121, 22573 => 20008,
22574 => 31162, 22575 => 20031, 22576 => 21269, 22577 => 20039, 22578 => 22829, 22574 => 31162, 22575 => 20031, 22576 => 21269, 22577 => 20039, 22578 => 22829,
22579 => 29243, 22580 => 21358, 22581 => 27664, 22582 => 22239, 22583 => 32996, 22579 => 29243, 22580 => 21358, 22581 => 27664, 22582 => 22239, 22583 => 32996,
22584 => 39319, 22585 => 27603, 22586 => 30590, 22587 => 40727, 22588 => 20022, 22584 => 39319, 22585 => 27603, 22586 => 30590, 22587 => 40727, 22588 => 20022,
22589 => 20127, 22590 => 40720, 22591 => 20060, 22592 => 20073, 22593 => 20115, 22589 => 20127, 22590 => 40720, 22591 => 20060, 22592 => 20073, 22593 => 20115,
22594 => 33416, 22595 => 23387, 22596 => 21868, 22597 => 22031, 22598 => 20164, 22594 => 33416, 22595 => 23387, 22596 => 21868, 22597 => 22031, 22598 => 20164,
22599 => 21389, 22600 => 21405, 22601 => 21411, 22602 => 21413, 22603 => 21422, 22599 => 21389, 22600 => 21405, 22601 => 21411, 22602 => 21413, 22603 => 21422,
22604 => 38757, 22605 => 36189, 22606 => 21274, 22607 => 21493, 22608 => 21286, 22604 => 38757, 22605 => 36189, 22606 => 21274, 22607 => 21493, 22608 => 21286,
22609 => 21294, 22610 => 21310, 22611 => 36188, 22612 => 21350, 22613 => 21347, 22609 => 21294, 22610 => 21310, 22611 => 36188, 22612 => 21350, 22613 => 21347,
22614 => 20994, 22615 => 21000, 22616 => 21006, 22617 => 21037, 22618 => 21043, 22614 => 20994, 22615 => 21000, 22616 => 21006, 22617 => 21037, 22618 => 21043,
22619 => 21055, 22620 => 21056, 22621 => 21068, 22622 => 21086, 22623 => 21089, 22619 => 21055, 22620 => 21056, 22621 => 21068, 22622 => 21086, 22623 => 21089,
22624 => 21084, 22625 => 33967, 22626 => 21117, 22627 => 21122, 22628 => 21121, 22624 => 21084, 22625 => 33967, 22626 => 21117, 22627 => 21122, 22628 => 21121,
22629 => 21136, 22630 => 21139, 22631 => 20866, 22632 => 32596, 22633 => 20155, 22629 => 21136, 22630 => 21139, 22631 => 20866, 22632 => 32596, 22633 => 20155,
22634 => 20163, 22635 => 20169, 22636 => 20162, 22637 => 20200, 22638 => 20193, 22634 => 20163, 22635 => 20169, 22636 => 20162, 22637 => 20200, 22638 => 20193,
22639 => 20203, 22640 => 20190, 22641 => 20251, 22642 => 20211, 22643 => 20258, 22639 => 20203, 22640 => 20190, 22641 => 20251, 22642 => 20211, 22643 => 20258,
22644 => 20324, 22645 => 20213, 22646 => 20261, 22647 => 20263, 22648 => 20233, 22644 => 20324, 22645 => 20213, 22646 => 20261, 22647 => 20263, 22648 => 20233,
22649 => 20267, 22650 => 20318, 22651 => 20327, 22652 => 25912, 22653 => 20314, 22649 => 20267, 22650 => 20318, 22651 => 20327, 22652 => 25912, 22653 => 20314,
22654 => 20317, 22817 => 20319, 22818 => 20311, 22819 => 20274, 22820 => 20285, 22654 => 20317, 22817 => 20319, 22818 => 20311, 22819 => 20274, 22820 => 20285,
22821 => 20342, 22822 => 20340, 22823 => 20369, 22824 => 20361, 22825 => 20355, 22821 => 20342, 22822 => 20340, 22823 => 20369, 22824 => 20361, 22825 => 20355,
22826 => 20367, 22827 => 20350, 22828 => 20347, 22829 => 20394, 22830 => 20348, 22826 => 20367, 22827 => 20350, 22828 => 20347, 22829 => 20394, 22830 => 20348,
22831 => 20396, 22832 => 20372, 22833 => 20454, 22834 => 20456, 22835 => 20458, 22831 => 20396, 22832 => 20372, 22833 => 20454, 22834 => 20456, 22835 => 20458,
22836 => 20421, 22837 => 20442, 22838 => 20451, 22839 => 20444, 22840 => 20433, 22836 => 20421, 22837 => 20442, 22838 => 20451, 22839 => 20444, 22840 => 20433,
22841 => 20447, 22842 => 20472, 22843 => 20521, 22844 => 20556, 22845 => 20467, 22841 => 20447, 22842 => 20472, 22843 => 20521, 22844 => 20556, 22845 => 20467,
22846 => 20524, 22847 => 20495, 22848 => 20526, 22849 => 20525, 22850 => 20478, 22846 => 20524, 22847 => 20495, 22848 => 20526, 22849 => 20525, 22850 => 20478,
22851 => 20508, 22852 => 20492, 22853 => 20517, 22854 => 20520, 22855 => 20606, 22851 => 20508, 22852 => 20492, 22853 => 20517, 22854 => 20520, 22855 => 20606,
22856 => 20547, 22857 => 20565, 22858 => 20552, 22859 => 20558, 22860 => 20588, 22856 => 20547, 22857 => 20565, 22858 => 20552, 22859 => 20558, 22860 => 20588,
22861 => 20603, 22862 => 20645, 22863 => 20647, 22864 => 20649, 22865 => 20666, 22861 => 20603, 22862 => 20645, 22863 => 20647, 22864 => 20649, 22865 => 20666,
22866 => 20694, 22867 => 20742, 22868 => 20717, 22869 => 20716, 22870 => 20710, 22866 => 20694, 22867 => 20742, 22868 => 20717, 22869 => 20716, 22870 => 20710,
22871 => 20718, 22872 => 20743, 22873 => 20747, 22874 => 20189, 22875 => 27709, 22871 => 20718, 22872 => 20743, 22873 => 20747, 22874 => 20189, 22875 => 27709,
22876 => 20312, 22877 => 20325, 22878 => 20430, 22879 => 40864, 22880 => 27718, 22876 => 20312, 22877 => 20325, 22878 => 20430, 22879 => 40864, 22880 => 27718,
22881 => 31860, 22882 => 20846, 22883 => 24061, 22884 => 40649, 22885 => 39320, 22881 => 31860, 22882 => 20846, 22883 => 24061, 22884 => 40649, 22885 => 39320,
22886 => 20865, 22887 => 22804, 22888 => 21241, 22889 => 21261, 22890 => 35335, 22886 => 20865, 22887 => 22804, 22888 => 21241, 22889 => 21261, 22890 => 35335,
22891 => 21264, 22892 => 20971, 22893 => 22809, 22894 => 20821, 22895 => 20128, 22891 => 21264, 22892 => 20971, 22893 => 22809, 22894 => 20821, 22895 => 20128,
22896 => 20822, 22897 => 20147, 22898 => 34926, 22899 => 34980, 22900 => 20149, 22896 => 20822, 22897 => 20147, 22898 => 34926, 22899 => 34980, 22900 => 20149,
22901 => 33044, 22902 => 35026, 22903 => 31104, 22904 => 23348, 22905 => 34819, 22901 => 33044, 22902 => 35026, 22903 => 31104, 22904 => 23348, 22905 => 34819,
22906 => 32696, 22907 => 20907, 22908 => 20913, 22909 => 20925, 22910 => 20924, 22906 => 32696, 22907 => 20907, 22908 => 20913, 22909 => 20925, 22910 => 20924,
23073 => 20935, 23074 => 20886, 23075 => 20898, 23076 => 20901, 23077 => 35744, 23073 => 20935, 23074 => 20886, 23075 => 20898, 23076 => 20901, 23077 => 35744,
23078 => 35750, 23079 => 35751, 23080 => 35754, 23081 => 35764, 23082 => 35765, 23078 => 35750, 23079 => 35751, 23080 => 35754, 23081 => 35764, 23082 => 35765,
23083 => 35767, 23084 => 35778, 23085 => 35779, 23086 => 35787, 23087 => 35791, 23083 => 35767, 23084 => 35778, 23085 => 35779, 23086 => 35787, 23087 => 35791,
23088 => 35790, 23089 => 35794, 23090 => 35795, 23091 => 35796, 23092 => 35798, 23088 => 35790, 23089 => 35794, 23090 => 35795, 23091 => 35796, 23092 => 35798,
23093 => 35800, 23094 => 35801, 23095 => 35804, 23096 => 35807, 23097 => 35808, 23093 => 35800, 23094 => 35801, 23095 => 35804, 23096 => 35807, 23097 => 35808,
23098 => 35812, 23099 => 35816, 23100 => 35817, 23101 => 35822, 23102 => 35824, 23098 => 35812, 23099 => 35816, 23100 => 35817, 23101 => 35822, 23102 => 35824,
23103 => 35827, 23104 => 35830, 23105 => 35833, 23106 => 35836, 23107 => 35839, 23103 => 35827, 23104 => 35830, 23105 => 35833, 23106 => 35836, 23107 => 35839,
23108 => 35840, 23109 => 35842, 23110 => 35844, 23111 => 35847, 23112 => 35852, 23108 => 35840, 23109 => 35842, 23110 => 35844, 23111 => 35847, 23112 => 35852,
23113 => 35855, 23114 => 35857, 23115 => 35858, 23116 => 35860, 23117 => 35861, 23113 => 35855, 23114 => 35857, 23115 => 35858, 23116 => 35860, 23117 => 35861,
23118 => 35862, 23119 => 35865, 23120 => 35867, 23121 => 35864, 23122 => 35869, 23118 => 35862, 23119 => 35865, 23120 => 35867, 23121 => 35864, 23122 => 35869,
23123 => 35871, 23124 => 35872, 23125 => 35873, 23126 => 35877, 23127 => 35879, 23123 => 35871, 23124 => 35872, 23125 => 35873, 23126 => 35877, 23127 => 35879,
23128 => 35882, 23129 => 35883, 23130 => 35886, 23131 => 35887, 23132 => 35890, 23128 => 35882, 23129 => 35883, 23130 => 35886, 23131 => 35887, 23132 => 35890,
23133 => 35891, 23134 => 35893, 23135 => 35894, 23136 => 21353, 23137 => 21370, 23133 => 35891, 23134 => 35893, 23135 => 35894, 23136 => 21353, 23137 => 21370,
23138 => 38429, 23139 => 38434, 23140 => 38433, 23141 => 38449, 23142 => 38442, 23138 => 38429, 23139 => 38434, 23140 => 38433, 23141 => 38449, 23142 => 38442,
23143 => 38461, 23144 => 38460, 23145 => 38466, 23146 => 38473, 23147 => 38484, 23143 => 38461, 23144 => 38460, 23145 => 38466, 23146 => 38473, 23147 => 38484,
23148 => 38495, 23149 => 38503, 23150 => 38508, 23151 => 38514, 23152 => 38516, 23148 => 38495, 23149 => 38503, 23150 => 38508, 23151 => 38514, 23152 => 38516,
23153 => 38536, 23154 => 38541, 23155 => 38551, 23156 => 38576, 23157 => 37015, 23153 => 38536, 23154 => 38541, 23155 => 38551, 23156 => 38576, 23157 => 37015,
23158 => 37019, 23159 => 37021, 23160 => 37017, 23161 => 37036, 23162 => 37025, 23158 => 37019, 23159 => 37021, 23160 => 37017, 23161 => 37036, 23162 => 37025,
23163 => 37044, 23164 => 37043, 23165 => 37046, 23166 => 37050, 23329 => 37048, 23163 => 37044, 23164 => 37043, 23165 => 37046, 23166 => 37050, 23329 => 37048,
23330 => 37040, 23331 => 37071, 23332 => 37061, 23333 => 37054, 23334 => 37072, 23330 => 37040, 23331 => 37071, 23332 => 37061, 23333 => 37054, 23334 => 37072,
23335 => 37060, 23336 => 37063, 23337 => 37075, 23338 => 37094, 23339 => 37090, 23335 => 37060, 23336 => 37063, 23337 => 37075, 23338 => 37094, 23339 => 37090,
23340 => 37084, 23341 => 37079, 23342 => 37083, 23343 => 37099, 23344 => 37103, 23340 => 37084, 23341 => 37079, 23342 => 37083, 23343 => 37099, 23344 => 37103,
23345 => 37118, 23346 => 37124, 23347 => 37154, 23348 => 37150, 23349 => 37155, 23345 => 37118, 23346 => 37124, 23347 => 37154, 23348 => 37150, 23349 => 37155,
23350 => 37169, 23351 => 37167, 23352 => 37177, 23353 => 37187, 23354 => 37190, 23350 => 37169, 23351 => 37167, 23352 => 37177, 23353 => 37187, 23354 => 37190,
23355 => 21005, 23356 => 22850, 23357 => 21154, 23358 => 21164, 23359 => 21165, 23355 => 21005, 23356 => 22850, 23357 => 21154, 23358 => 21164, 23359 => 21165,
23360 => 21182, 23361 => 21759, 23362 => 21200, 23363 => 21206, 23364 => 21232, 23360 => 21182, 23361 => 21759, 23362 => 21200, 23363 => 21206, 23364 => 21232,
23365 => 21471, 23366 => 29166, 23367 => 30669, 23368 => 24308, 23369 => 20981, 23365 => 21471, 23366 => 29166, 23367 => 30669, 23368 => 24308, 23369 => 20981,
23370 => 20988, 23371 => 39727, 23372 => 21430, 23373 => 24321, 23374 => 30042, 23370 => 20988, 23371 => 39727, 23372 => 21430, 23373 => 24321, 23374 => 30042,
23375 => 24047, 23376 => 22348, 23377 => 22441, 23378 => 22433, 23379 => 22654, 23375 => 24047, 23376 => 22348, 23377 => 22441, 23378 => 22433, 23379 => 22654,
23380 => 22716, 23381 => 22725, 23382 => 22737, 23383 => 22313, 23384 => 22316, 23380 => 22716, 23381 => 22725, 23382 => 22737, 23383 => 22313, 23384 => 22316,
23385 => 22314, 23386 => 22323, 23387 => 22329, 23388 => 22318, 23389 => 22319, 23385 => 22314, 23386 => 22323, 23387 => 22329, 23388 => 22318, 23389 => 22319,
23390 => 22364, 23391 => 22331, 23392 => 22338, 23393 => 22377, 23394 => 22405, 23390 => 22364, 23391 => 22331, 23392 => 22338, 23393 => 22377, 23394 => 22405,
23395 => 22379, 23396 => 22406, 23397 => 22396, 23398 => 22395, 23399 => 22376, 23395 => 22379, 23396 => 22406, 23397 => 22396, 23398 => 22395, 23399 => 22376,
23400 => 22381, 23401 => 22390, 23402 => 22387, 23403 => 22445, 23404 => 22436, 23400 => 22381, 23401 => 22390, 23402 => 22387, 23403 => 22445, 23404 => 22436,
23405 => 22412, 23406 => 22450, 23407 => 22479, 23408 => 22439, 23409 => 22452, 23405 => 22412, 23406 => 22450, 23407 => 22479, 23408 => 22439, 23409 => 22452,
23410 => 22419, 23411 => 22432, 23412 => 22485, 23413 => 22488, 23414 => 22490, 23410 => 22419, 23411 => 22432, 23412 => 22485, 23413 => 22488, 23414 => 22490,
23415 => 22489, 23416 => 22482, 23417 => 22456, 23418 => 22516, 23419 => 22511, 23415 => 22489, 23416 => 22482, 23417 => 22456, 23418 => 22516, 23419 => 22511,
23420 => 22520, 23421 => 22500, 23422 => 22493, 23585 => 22539, 23586 => 22541, 23420 => 22520, 23421 => 22500, 23422 => 22493, 23585 => 22539, 23586 => 22541,
23587 => 22525, 23588 => 22509, 23589 => 22528, 23590 => 22558, 23591 => 22553, 23587 => 22525, 23588 => 22509, 23589 => 22528, 23590 => 22558, 23591 => 22553,
23592 => 22596, 23593 => 22560, 23594 => 22629, 23595 => 22636, 23596 => 22657, 23592 => 22596, 23593 => 22560, 23594 => 22629, 23595 => 22636, 23596 => 22657,
23597 => 22665, 23598 => 22682, 23599 => 22656, 23600 => 39336, 23601 => 40729, 23597 => 22665, 23598 => 22682, 23599 => 22656, 23600 => 39336, 23601 => 40729,
23602 => 25087, 23603 => 33401, 23604 => 33405, 23605 => 33407, 23606 => 33423, 23602 => 25087, 23603 => 33401, 23604 => 33405, 23605 => 33407, 23606 => 33423,
23607 => 33418, 23608 => 33448, 23609 => 33412, 23610 => 33422, 23611 => 33425, 23607 => 33418, 23608 => 33448, 23609 => 33412, 23610 => 33422, 23611 => 33425,
23612 => 33431, 23613 => 33433, 23614 => 33451, 23615 => 33464, 23616 => 33470, 23612 => 33431, 23613 => 33433, 23614 => 33451, 23615 => 33464, 23616 => 33470,
23617 => 33456, 23618 => 33480, 23619 => 33482, 23620 => 33507, 23621 => 33432, 23617 => 33456, 23618 => 33480, 23619 => 33482, 23620 => 33507, 23621 => 33432,
23622 => 33463, 23623 => 33454, 23624 => 33483, 23625 => 33484, 23626 => 33473, 23622 => 33463, 23623 => 33454, 23624 => 33483, 23625 => 33484, 23626 => 33473,
23627 => 33449, 23628 => 33460, 23629 => 33441, 23630 => 33450, 23631 => 33439, 23627 => 33449, 23628 => 33460, 23629 => 33441, 23630 => 33450, 23631 => 33439,
23632 => 33476, 23633 => 33486, 23634 => 33444, 23635 => 33505, 23636 => 33545, 23632 => 33476, 23633 => 33486, 23634 => 33444, 23635 => 33505, 23636 => 33545,
23637 => 33527, 23638 => 33508, 23639 => 33551, 23640 => 33543, 23641 => 33500, 23637 => 33527, 23638 => 33508, 23639 => 33551, 23640 => 33543, 23641 => 33500,
23642 => 33524, 23643 => 33490, 23644 => 33496, 23645 => 33548, 23646 => 33531, 23642 => 33524, 23643 => 33490, 23644 => 33496, 23645 => 33548, 23646 => 33531,
23647 => 33491, 23648 => 33553, 23649 => 33562, 23650 => 33542, 23651 => 33556, 23647 => 33491, 23648 => 33553, 23649 => 33562, 23650 => 33542, 23651 => 33556,
23652 => 33557, 23653 => 33504, 23654 => 33493, 23655 => 33564, 23656 => 33617, 23652 => 33557, 23653 => 33504, 23654 => 33493, 23655 => 33564, 23656 => 33617,
23657 => 33627, 23658 => 33628, 23659 => 33544, 23660 => 33682, 23661 => 33596, 23657 => 33627, 23658 => 33628, 23659 => 33544, 23660 => 33682, 23661 => 33596,
23662 => 33588, 23663 => 33585, 23664 => 33691, 23665 => 33630, 23666 => 33583, 23662 => 33588, 23663 => 33585, 23664 => 33691, 23665 => 33630, 23666 => 33583,
23667 => 33615, 23668 => 33607, 23669 => 33603, 23670 => 33631, 23671 => 33600, 23667 => 33615, 23668 => 33607, 23669 => 33603, 23670 => 33631, 23671 => 33600,
23672 => 33559, 23673 => 33632, 23674 => 33581, 23675 => 33594, 23676 => 33587, 23672 => 33559, 23673 => 33632, 23674 => 33581, 23675 => 33594, 23676 => 33587,
23677 => 33638, 23678 => 33637, 23841 => 33640, 23842 => 33563, 23843 => 33641, 23677 => 33638, 23678 => 33637, 23841 => 33640, 23842 => 33563, 23843 => 33641,
23844 => 33644, 23845 => 33642, 23846 => 33645, 23847 => 33646, 23848 => 33712, 23844 => 33644, 23845 => 33642, 23846 => 33645, 23847 => 33646, 23848 => 33712,
23849 => 33656, 23850 => 33715, 23851 => 33716, 23852 => 33696, 23853 => 33706, 23849 => 33656, 23850 => 33715, 23851 => 33716, 23852 => 33696, 23853 => 33706,
23854 => 33683, 23855 => 33692, 23856 => 33669, 23857 => 33660, 23858 => 33718, 23854 => 33683, 23855 => 33692, 23856 => 33669, 23857 => 33660, 23858 => 33718,
23859 => 33705, 23860 => 33661, 23861 => 33720, 23862 => 33659, 23863 => 33688, 23859 => 33705, 23860 => 33661, 23861 => 33720, 23862 => 33659, 23863 => 33688,
23864 => 33694, 23865 => 33704, 23866 => 33722, 23867 => 33724, 23868 => 33729, 23864 => 33694, 23865 => 33704, 23866 => 33722, 23867 => 33724, 23868 => 33729,
23869 => 33793, 23870 => 33765, 23871 => 33752, 23872 => 22535, 23873 => 33816, 23869 => 33793, 23870 => 33765, 23871 => 33752, 23872 => 22535, 23873 => 33816,
23874 => 33803, 23875 => 33757, 23876 => 33789, 23877 => 33750, 23878 => 33820, 23874 => 33803, 23875 => 33757, 23876 => 33789, 23877 => 33750, 23878 => 33820,
23879 => 33848, 23880 => 33809, 23881 => 33798, 23882 => 33748, 23883 => 33759, 23879 => 33848, 23880 => 33809, 23881 => 33798, 23882 => 33748, 23883 => 33759,
23884 => 33807, 23885 => 33795, 23886 => 33784, 23887 => 33785, 23888 => 33770, 23884 => 33807, 23885 => 33795, 23886 => 33784, 23887 => 33785, 23888 => 33770,
23889 => 33733, 23890 => 33728, 23891 => 33830, 23892 => 33776, 23893 => 33761, 23889 => 33733, 23890 => 33728, 23891 => 33830, 23892 => 33776, 23893 => 33761,
23894 => 33884, 23895 => 33873, 23896 => 33882, 23897 => 33881, 23898 => 33907, 23894 => 33884, 23895 => 33873, 23896 => 33882, 23897 => 33881, 23898 => 33907,
23899 => 33927, 23900 => 33928, 23901 => 33914, 23902 => 33929, 23903 => 33912, 23899 => 33927, 23900 => 33928, 23901 => 33914, 23902 => 33929, 23903 => 33912,
23904 => 33852, 23905 => 33862, 23906 => 33897, 23907 => 33910, 23908 => 33932, 23904 => 33852, 23905 => 33862, 23906 => 33897, 23907 => 33910, 23908 => 33932,
23909 => 33934, 23910 => 33841, 23911 => 33901, 23912 => 33985, 23913 => 33997, 23909 => 33934, 23910 => 33841, 23911 => 33901, 23912 => 33985, 23913 => 33997,
23914 => 34000, 23915 => 34022, 23916 => 33981, 23917 => 34003, 23918 => 33994, 23914 => 34000, 23915 => 34022, 23916 => 33981, 23917 => 34003, 23918 => 33994,
23919 => 33983, 23920 => 33978, 23921 => 34016, 23922 => 33953, 23923 => 33977, 23919 => 33983, 23920 => 33978, 23921 => 34016, 23922 => 33953, 23923 => 33977,
23924 => 33972, 23925 => 33943, 23926 => 34021, 23927 => 34019, 23928 => 34060, 23924 => 33972, 23925 => 33943, 23926 => 34021, 23927 => 34019, 23928 => 34060,
23929 => 29965, 23930 => 34104, 23931 => 34032, 23932 => 34105, 23933 => 34079, 23929 => 29965, 23930 => 34104, 23931 => 34032, 23932 => 34105, 23933 => 34079,
23934 => 34106, 24097 => 34134, 24098 => 34107, 24099 => 34047, 24100 => 34044, 23934 => 34106, 24097 => 34134, 24098 => 34107, 24099 => 34047, 24100 => 34044,
24101 => 34137, 24102 => 34120, 24103 => 34152, 24104 => 34148, 24105 => 34142, 24101 => 34137, 24102 => 34120, 24103 => 34152, 24104 => 34148, 24105 => 34142,
24106 => 34170, 24107 => 30626, 24108 => 34115, 24109 => 34162, 24110 => 34171, 24106 => 34170, 24107 => 30626, 24108 => 34115, 24109 => 34162, 24110 => 34171,
24111 => 34212, 24112 => 34216, 24113 => 34183, 24114 => 34191, 24115 => 34169, 24111 => 34212, 24112 => 34216, 24113 => 34183, 24114 => 34191, 24115 => 34169,
24116 => 34222, 24117 => 34204, 24118 => 34181, 24119 => 34233, 24120 => 34231, 24116 => 34222, 24117 => 34204, 24118 => 34181, 24119 => 34233, 24120 => 34231,
24121 => 34224, 24122 => 34259, 24123 => 34241, 24124 => 34268, 24125 => 34303, 24121 => 34224, 24122 => 34259, 24123 => 34241, 24124 => 34268, 24125 => 34303,
24126 => 34343, 24127 => 34309, 24128 => 34345, 24129 => 34326, 24130 => 34364, 24126 => 34343, 24127 => 34309, 24128 => 34345, 24129 => 34326, 24130 => 34364,
24131 => 24318, 24132 => 24328, 24133 => 22844, 24134 => 22849, 24135 => 32823, 24131 => 24318, 24132 => 24328, 24133 => 22844, 24134 => 22849, 24135 => 32823,
24136 => 22869, 24137 => 22874, 24138 => 22872, 24139 => 21263, 24140 => 23586, 24136 => 22869, 24137 => 22874, 24138 => 22872, 24139 => 21263, 24140 => 23586,
24141 => 23589, 24142 => 23596, 24143 => 23604, 24144 => 25164, 24145 => 25194, 24141 => 23589, 24142 => 23596, 24143 => 23604, 24144 => 25164, 24145 => 25194,
24146 => 25247, 24147 => 25275, 24148 => 25290, 24149 => 25306, 24150 => 25303, 24146 => 25247, 24147 => 25275, 24148 => 25290, 24149 => 25306, 24150 => 25303,
24151 => 25326, 24152 => 25378, 24153 => 25334, 24154 => 25401, 24155 => 25419, 24151 => 25326, 24152 => 25378, 24153 => 25334, 24154 => 25401, 24155 => 25419,
24156 => 25411, 24157 => 25517, 24158 => 25590, 24159 => 25457, 24160 => 25466, 24156 => 25411, 24157 => 25517, 24158 => 25590, 24159 => 25457, 24160 => 25466,
24161 => 25486, 24162 => 25524, 24163 => 25453, 24164 => 25516, 24165 => 25482, 24161 => 25486, 24162 => 25524, 24163 => 25453, 24164 => 25516, 24165 => 25482,
24166 => 25449, 24167 => 25518, 24168 => 25532, 24169 => 25586, 24170 => 25592, 24166 => 25449, 24167 => 25518, 24168 => 25532, 24169 => 25586, 24170 => 25592,
24171 => 25568, 24172 => 25599, 24173 => 25540, 24174 => 25566, 24175 => 25550, 24171 => 25568, 24172 => 25599, 24173 => 25540, 24174 => 25566, 24175 => 25550,
24176 => 25682, 24177 => 25542, 24178 => 25534, 24179 => 25669, 24180 => 25665, 24176 => 25682, 24177 => 25542, 24178 => 25534, 24179 => 25669, 24180 => 25665,
24181 => 25611, 24182 => 25627, 24183 => 25632, 24184 => 25612, 24185 => 25638, 24181 => 25611, 24182 => 25627, 24183 => 25632, 24184 => 25612, 24185 => 25638,
24186 => 25633, 24187 => 25694, 24188 => 25732, 24189 => 25709, 24190 => 25750, 24186 => 25633, 24187 => 25694, 24188 => 25732, 24189 => 25709, 24190 => 25750,
24353 => 25722, 24354 => 25783, 24355 => 25784, 24356 => 25753, 24357 => 25786, 24353 => 25722, 24354 => 25783, 24355 => 25784, 24356 => 25753, 24357 => 25786,
24358 => 25792, 24359 => 25808, 24360 => 25815, 24361 => 25828, 24362 => 25826, 24358 => 25792, 24359 => 25808, 24360 => 25815, 24361 => 25828, 24362 => 25826,
24363 => 25865, 24364 => 25893, 24365 => 25902, 24366 => 24331, 24367 => 24530, 24363 => 25865, 24364 => 25893, 24365 => 25902, 24366 => 24331, 24367 => 24530,
24368 => 29977, 24369 => 24337, 24370 => 21343, 24371 => 21489, 24372 => 21501, 24368 => 29977, 24369 => 24337, 24370 => 21343, 24371 => 21489, 24372 => 21501,
24373 => 21481, 24374 => 21480, 24375 => 21499, 24376 => 21522, 24377 => 21526, 24373 => 21481, 24374 => 21480, 24375 => 21499, 24376 => 21522, 24377 => 21526,
24378 => 21510, 24379 => 21579, 24380 => 21586, 24381 => 21587, 24382 => 21588, 24378 => 21510, 24379 => 21579, 24380 => 21586, 24381 => 21587, 24382 => 21588,
24383 => 21590, 24384 => 21571, 24385 => 21537, 24386 => 21591, 24387 => 21593, 24383 => 21590, 24384 => 21571, 24385 => 21537, 24386 => 21591, 24387 => 21593,
24388 => 21539, 24389 => 21554, 24390 => 21634, 24391 => 21652, 24392 => 21623, 24388 => 21539, 24389 => 21554, 24390 => 21634, 24391 => 21652, 24392 => 21623,
24393 => 21617, 24394 => 21604, 24395 => 21658, 24396 => 21659, 24397 => 21636, 24393 => 21617, 24394 => 21604, 24395 => 21658, 24396 => 21659, 24397 => 21636,
24398 => 21622, 24399 => 21606, 24400 => 21661, 24401 => 21712, 24402 => 21677, 24398 => 21622, 24399 => 21606, 24400 => 21661, 24401 => 21712, 24402 => 21677,
24403 => 21698, 24404 => 21684, 24405 => 21714, 24406 => 21671, 24407 => 21670, 24403 => 21698, 24404 => 21684, 24405 => 21714, 24406 => 21671, 24407 => 21670,
24408 => 21715, 24409 => 21716, 24410 => 21618, 24411 => 21667, 24412 => 21717, 24408 => 21715, 24409 => 21716, 24410 => 21618, 24411 => 21667, 24412 => 21717,
24413 => 21691, 24414 => 21695, 24415 => 21708, 24416 => 21721, 24417 => 21722, 24413 => 21691, 24414 => 21695, 24415 => 21708, 24416 => 21721, 24417 => 21722,
24418 => 21724, 24419 => 21673, 24420 => 21674, 24421 => 21668, 24422 => 21725, 24418 => 21724, 24419 => 21673, 24420 => 21674, 24421 => 21668, 24422 => 21725,
24423 => 21711, 24424 => 21726, 24425 => 21787, 24426 => 21735, 24427 => 21792, 24423 => 21711, 24424 => 21726, 24425 => 21787, 24426 => 21735, 24427 => 21792,
24428 => 21757, 24429 => 21780, 24430 => 21747, 24431 => 21794, 24432 => 21795, 24428 => 21757, 24429 => 21780, 24430 => 21747, 24431 => 21794, 24432 => 21795,
24433 => 21775, 24434 => 21777, 24435 => 21799, 24436 => 21802, 24437 => 21863, 24433 => 21775, 24434 => 21777, 24435 => 21799, 24436 => 21802, 24437 => 21863,
24438 => 21903, 24439 => 21941, 24440 => 21833, 24441 => 21869, 24442 => 21825, 24438 => 21903, 24439 => 21941, 24440 => 21833, 24441 => 21869, 24442 => 21825,
24443 => 21845, 24444 => 21823, 24445 => 21840, 24446 => 21820, 24609 => 21815, 24443 => 21845, 24444 => 21823, 24445 => 21840, 24446 => 21820, 24609 => 21815,
24610 => 21846, 24611 => 21877, 24612 => 21878, 24613 => 21879, 24614 => 21811, 24610 => 21846, 24611 => 21877, 24612 => 21878, 24613 => 21879, 24614 => 21811,
24615 => 21808, 24616 => 21852, 24617 => 21899, 24618 => 21970, 24619 => 21891, 24615 => 21808, 24616 => 21852, 24617 => 21899, 24618 => 21970, 24619 => 21891,
24620 => 21937, 24621 => 21945, 24622 => 21896, 24623 => 21889, 24624 => 21919, 24620 => 21937, 24621 => 21945, 24622 => 21896, 24623 => 21889, 24624 => 21919,
24625 => 21886, 24626 => 21974, 24627 => 21905, 24628 => 21883, 24629 => 21983, 24625 => 21886, 24626 => 21974, 24627 => 21905, 24628 => 21883, 24629 => 21983,
24630 => 21949, 24631 => 21950, 24632 => 21908, 24633 => 21913, 24634 => 21994, 24630 => 21949, 24631 => 21950, 24632 => 21908, 24633 => 21913, 24634 => 21994,
24635 => 22007, 24636 => 21961, 24637 => 22047, 24638 => 21969, 24639 => 21995, 24635 => 22007, 24636 => 21961, 24637 => 22047, 24638 => 21969, 24639 => 21995,
24640 => 21996, 24641 => 21972, 24642 => 21990, 24643 => 21981, 24644 => 21956, 24640 => 21996, 24641 => 21972, 24642 => 21990, 24643 => 21981, 24644 => 21956,
24645 => 21999, 24646 => 21989, 24647 => 22002, 24648 => 22003, 24649 => 21964, 24645 => 21999, 24646 => 21989, 24647 => 22002, 24648 => 22003, 24649 => 21964,
24650 => 21965, 24651 => 21992, 24652 => 22005, 24653 => 21988, 24654 => 36756, 24650 => 21965, 24651 => 21992, 24652 => 22005, 24653 => 21988, 24654 => 36756,
24655 => 22046, 24656 => 22024, 24657 => 22028, 24658 => 22017, 24659 => 22052, 24655 => 22046, 24656 => 22024, 24657 => 22028, 24658 => 22017, 24659 => 22052,
24660 => 22051, 24661 => 22014, 24662 => 22016, 24663 => 22055, 24664 => 22061, 24660 => 22051, 24661 => 22014, 24662 => 22016, 24663 => 22055, 24664 => 22061,
24665 => 22104, 24666 => 22073, 24667 => 22103, 24668 => 22060, 24669 => 22093, 24665 => 22104, 24666 => 22073, 24667 => 22103, 24668 => 22060, 24669 => 22093,
24670 => 22114, 24671 => 22105, 24672 => 22108, 24673 => 22092, 24674 => 22100, 24670 => 22114, 24671 => 22105, 24672 => 22108, 24673 => 22092, 24674 => 22100,
24675 => 22150, 24676 => 22116, 24677 => 22129, 24678 => 22123, 24679 => 22139, 24675 => 22150, 24676 => 22116, 24677 => 22129, 24678 => 22123, 24679 => 22139,
24680 => 22140, 24681 => 22149, 24682 => 22163, 24683 => 22191, 24684 => 22228, 24680 => 22140, 24681 => 22149, 24682 => 22163, 24683 => 22191, 24684 => 22228,
24685 => 22231, 24686 => 22237, 24687 => 22241, 24688 => 22261, 24689 => 22251, 24685 => 22231, 24686 => 22237, 24687 => 22241, 24688 => 22261, 24689 => 22251,
24690 => 22265, 24691 => 22271, 24692 => 22276, 24693 => 22282, 24694 => 22281, 24690 => 22265, 24691 => 22271, 24692 => 22276, 24693 => 22282, 24694 => 22281,
24695 => 22300, 24696 => 24079, 24697 => 24089, 24698 => 24084, 24699 => 24081, 24695 => 22300, 24696 => 24079, 24697 => 24089, 24698 => 24084, 24699 => 24081,
24700 => 24113, 24701 => 24123, 24702 => 24124, 24865 => 24119, 24866 => 24132, 24700 => 24113, 24701 => 24123, 24702 => 24124, 24865 => 24119, 24866 => 24132,
24867 => 24148, 24868 => 24155, 24869 => 24158, 24870 => 24161, 24871 => 23692, 24867 => 24148, 24868 => 24155, 24869 => 24158, 24870 => 24161, 24871 => 23692,
24872 => 23674, 24873 => 23693, 24874 => 23696, 24875 => 23702, 24876 => 23688, 24872 => 23674, 24873 => 23693, 24874 => 23696, 24875 => 23702, 24876 => 23688,
24877 => 23704, 24878 => 23705, 24879 => 23697, 24880 => 23706, 24881 => 23708, 24877 => 23704, 24878 => 23705, 24879 => 23697, 24880 => 23706, 24881 => 23708,
24882 => 23733, 24883 => 23714, 24884 => 23741, 24885 => 23724, 24886 => 23723, 24882 => 23733, 24883 => 23714, 24884 => 23741, 24885 => 23724, 24886 => 23723,
24887 => 23729, 24888 => 23715, 24889 => 23745, 24890 => 23735, 24891 => 23748, 24887 => 23729, 24888 => 23715, 24889 => 23745, 24890 => 23735, 24891 => 23748,
24892 => 23762, 24893 => 23780, 24894 => 23755, 24895 => 23781, 24896 => 23810, 24892 => 23762, 24893 => 23780, 24894 => 23755, 24895 => 23781, 24896 => 23810,
24897 => 23811, 24898 => 23847, 24899 => 23846, 24900 => 23854, 24901 => 23844, 24897 => 23811, 24898 => 23847, 24899 => 23846, 24900 => 23854, 24901 => 23844,
24902 => 23838, 24903 => 23814, 24904 => 23835, 24905 => 23896, 24906 => 23870, 24902 => 23838, 24903 => 23814, 24904 => 23835, 24905 => 23896, 24906 => 23870,
24907 => 23860, 24908 => 23869, 24909 => 23916, 24910 => 23899, 24911 => 23919, 24907 => 23860, 24908 => 23869, 24909 => 23916, 24910 => 23899, 24911 => 23919,
24912 => 23901, 24913 => 23915, 24914 => 23883, 24915 => 23882, 24916 => 23913, 24912 => 23901, 24913 => 23915, 24914 => 23883, 24915 => 23882, 24916 => 23913,
24917 => 23924, 24918 => 23938, 24919 => 23961, 24920 => 23965, 24921 => 35955, 24917 => 23924, 24918 => 23938, 24919 => 23961, 24920 => 23965, 24921 => 35955,
24922 => 23991, 24923 => 24005, 24924 => 24435, 24925 => 24439, 24926 => 24450, 24922 => 23991, 24923 => 24005, 24924 => 24435, 24925 => 24439, 24926 => 24450,
24927 => 24455, 24928 => 24457, 24929 => 24460, 24930 => 24469, 24931 => 24473, 24927 => 24455, 24928 => 24457, 24929 => 24460, 24930 => 24469, 24931 => 24473,
24932 => 24476, 24933 => 24488, 24934 => 24493, 24935 => 24501, 24936 => 24508, 24932 => 24476, 24933 => 24488, 24934 => 24493, 24935 => 24501, 24936 => 24508,
24937 => 34914, 24938 => 24417, 24939 => 29357, 24940 => 29360, 24941 => 29364, 24937 => 34914, 24938 => 24417, 24939 => 29357, 24940 => 29360, 24941 => 29364,
24942 => 29367, 24943 => 29368, 24944 => 29379, 24945 => 29377, 24946 => 29390, 24942 => 29367, 24943 => 29368, 24944 => 29379, 24945 => 29377, 24946 => 29390,
24947 => 29389, 24948 => 29394, 24949 => 29416, 24950 => 29423, 24951 => 29417, 24947 => 29389, 24948 => 29394, 24949 => 29416, 24950 => 29423, 24951 => 29417,
24952 => 29426, 24953 => 29428, 24954 => 29431, 24955 => 29441, 24956 => 29427, 24952 => 29426, 24953 => 29428, 24954 => 29431, 24955 => 29441, 24956 => 29427,
24957 => 29443, 24958 => 29434, 25121 => 29435, 25122 => 29463, 25123 => 29459, 24957 => 29443, 24958 => 29434, 25121 => 29435, 25122 => 29463, 25123 => 29459,
25124 => 29473, 25125 => 29450, 25126 => 29470, 25127 => 29469, 25128 => 29461, 25124 => 29473, 25125 => 29450, 25126 => 29470, 25127 => 29469, 25128 => 29461,
25129 => 29474, 25130 => 29497, 25131 => 29477, 25132 => 29484, 25133 => 29496, 25129 => 29474, 25130 => 29497, 25131 => 29477, 25132 => 29484, 25133 => 29496,
25134 => 29489, 25135 => 29520, 25136 => 29517, 25137 => 29527, 25138 => 29536, 25134 => 29489, 25135 => 29520, 25136 => 29517, 25137 => 29527, 25138 => 29536,
25139 => 29548, 25140 => 29551, 25141 => 29566, 25142 => 33307, 25143 => 22821, 25139 => 29548, 25140 => 29551, 25141 => 29566, 25142 => 33307, 25143 => 22821,
25144 => 39143, 25145 => 22820, 25146 => 22786, 25147 => 39267, 25148 => 39271, 25144 => 39143, 25145 => 22820, 25146 => 22786, 25147 => 39267, 25148 => 39271,
25149 => 39272, 25150 => 39273, 25151 => 39274, 25152 => 39275, 25153 => 39276, 25149 => 39272, 25150 => 39273, 25151 => 39274, 25152 => 39275, 25153 => 39276,
25154 => 39284, 25155 => 39287, 25156 => 39293, 25157 => 39296, 25158 => 39300, 25154 => 39284, 25155 => 39287, 25156 => 39293, 25157 => 39296, 25158 => 39300,
25159 => 39303, 25160 => 39306, 25161 => 39309, 25162 => 39312, 25163 => 39313, 25159 => 39303, 25160 => 39306, 25161 => 39309, 25162 => 39312, 25163 => 39313,
25164 => 39315, 25165 => 39316, 25166 => 39317, 25167 => 24192, 25168 => 24209, 25164 => 39315, 25165 => 39316, 25166 => 39317, 25167 => 24192, 25168 => 24209,
25169 => 24203, 25170 => 24214, 25171 => 24229, 25172 => 24224, 25173 => 24249, 25169 => 24203, 25170 => 24214, 25171 => 24229, 25172 => 24224, 25173 => 24249,
25174 => 24245, 25175 => 24254, 25176 => 24243, 25177 => 36179, 25178 => 24274, 25174 => 24245, 25175 => 24254, 25176 => 24243, 25177 => 36179, 25178 => 24274,
25179 => 24273, 25180 => 24283, 25181 => 24296, 25182 => 24298, 25183 => 33210, 25179 => 24273, 25180 => 24283, 25181 => 24296, 25182 => 24298, 25183 => 33210,
25184 => 24516, 25185 => 24521, 25186 => 24534, 25187 => 24527, 25188 => 24579, 25184 => 24516, 25185 => 24521, 25186 => 24534, 25187 => 24527, 25188 => 24579,
25189 => 24558, 25190 => 24580, 25191 => 24545, 25192 => 24548, 25193 => 24574, 25189 => 24558, 25190 => 24580, 25191 => 24545, 25192 => 24548, 25193 => 24574,
25194 => 24581, 25195 => 24582, 25196 => 24554, 25197 => 24557, 25198 => 24568, 25194 => 24581, 25195 => 24582, 25196 => 24554, 25197 => 24557, 25198 => 24568,
25199 => 24601, 25200 => 24629, 25201 => 24614, 25202 => 24603, 25203 => 24591, 25199 => 24601, 25200 => 24629, 25201 => 24614, 25202 => 24603, 25203 => 24591,
25204 => 24589, 25205 => 24617, 25206 => 24619, 25207 => 24586, 25208 => 24639, 25204 => 24589, 25205 => 24617, 25206 => 24619, 25207 => 24586, 25208 => 24639,
25209 => 24609, 25210 => 24696, 25211 => 24697, 25212 => 24699, 25213 => 24698, 25209 => 24609, 25210 => 24696, 25211 => 24697, 25212 => 24699, 25213 => 24698,
25214 => 24642, 25377 => 24682, 25378 => 24701, 25379 => 24726, 25380 => 24730, 25214 => 24642, 25377 => 24682, 25378 => 24701, 25379 => 24726, 25380 => 24730,
25381 => 24749, 25382 => 24733, 25383 => 24707, 25384 => 24722, 25385 => 24716, 25381 => 24749, 25382 => 24733, 25383 => 24707, 25384 => 24722, 25385 => 24716,
25386 => 24731, 25387 => 24812, 25388 => 24763, 25389 => 24753, 25390 => 24797, 25386 => 24731, 25387 => 24812, 25388 => 24763, 25389 => 24753, 25390 => 24797,
25391 => 24792, 25392 => 24774, 25393 => 24794, 25394 => 24756, 25395 => 24864, 25391 => 24792, 25392 => 24774, 25393 => 24794, 25394 => 24756, 25395 => 24864,
25396 => 24870, 25397 => 24853, 25398 => 24867, 25399 => 24820, 25400 => 24832, 25396 => 24870, 25397 => 24853, 25398 => 24867, 25399 => 24820, 25400 => 24832,
25401 => 24846, 25402 => 24875, 25403 => 24906, 25404 => 24949, 25405 => 25004, 25401 => 24846, 25402 => 24875, 25403 => 24906, 25404 => 24949, 25405 => 25004,
25406 => 24980, 25407 => 24999, 25408 => 25015, 25409 => 25044, 25410 => 25077, 25406 => 24980, 25407 => 24999, 25408 => 25015, 25409 => 25044, 25410 => 25077,
25411 => 24541, 25412 => 38579, 25413 => 38377, 25414 => 38379, 25415 => 38385, 25411 => 24541, 25412 => 38579, 25413 => 38377, 25414 => 38379, 25415 => 38385,
25416 => 38387, 25417 => 38389, 25418 => 38390, 25419 => 38396, 25420 => 38398, 25416 => 38387, 25417 => 38389, 25418 => 38390, 25419 => 38396, 25420 => 38398,
25421 => 38403, 25422 => 38404, 25423 => 38406, 25424 => 38408, 25425 => 38410, 25421 => 38403, 25422 => 38404, 25423 => 38406, 25424 => 38408, 25425 => 38410,
25426 => 38411, 25427 => 38412, 25428 => 38413, 25429 => 38415, 25430 => 38418, 25426 => 38411, 25427 => 38412, 25428 => 38413, 25429 => 38415, 25430 => 38418,
25431 => 38421, 25432 => 38422, 25433 => 38423, 25434 => 38425, 25435 => 38426, 25431 => 38421, 25432 => 38422, 25433 => 38423, 25434 => 38425, 25435 => 38426,
25436 => 20012, 25437 => 29247, 25438 => 25109, 25439 => 27701, 25440 => 27732, 25436 => 20012, 25437 => 29247, 25438 => 25109, 25439 => 27701, 25440 => 27732,
25441 => 27740, 25442 => 27722, 25443 => 27811, 25444 => 27781, 25445 => 27792, 25441 => 27740, 25442 => 27722, 25443 => 27811, 25444 => 27781, 25445 => 27792,
25446 => 27796, 25447 => 27788, 25448 => 27752, 25449 => 27753, 25450 => 27764, 25446 => 27796, 25447 => 27788, 25448 => 27752, 25449 => 27753, 25450 => 27764,
25451 => 27766, 25452 => 27782, 25453 => 27817, 25454 => 27856, 25455 => 27860, 25451 => 27766, 25452 => 27782, 25453 => 27817, 25454 => 27856, 25455 => 27860,
25456 => 27821, 25457 => 27895, 25458 => 27896, 25459 => 27889, 25460 => 27863, 25456 => 27821, 25457 => 27895, 25458 => 27896, 25459 => 27889, 25460 => 27863,
25461 => 27826, 25462 => 27872, 25463 => 27862, 25464 => 27898, 25465 => 27883, 25461 => 27826, 25462 => 27872, 25463 => 27862, 25464 => 27898, 25465 => 27883,
25466 => 27886, 25467 => 27825, 25468 => 27859, 25469 => 27887, 25470 => 27902, 25466 => 27886, 25467 => 27825, 25468 => 27859, 25469 => 27887, 25470 => 27902,
25633 => 27961, 25634 => 27943, 25635 => 27916, 25636 => 27971, 25637 => 27976, 25633 => 27961, 25634 => 27943, 25635 => 27916, 25636 => 27971, 25637 => 27976,
25638 => 27911, 25639 => 27908, 25640 => 27929, 25641 => 27918, 25642 => 27947, 25638 => 27911, 25639 => 27908, 25640 => 27929, 25641 => 27918, 25642 => 27947,
25643 => 27981, 25644 => 27950, 25645 => 27957, 25646 => 27930, 25647 => 27983, 25643 => 27981, 25644 => 27950, 25645 => 27957, 25646 => 27930, 25647 => 27983,
25648 => 27986, 25649 => 27988, 25650 => 27955, 25651 => 28049, 25652 => 28015, 25648 => 27986, 25649 => 27988, 25650 => 27955, 25651 => 28049, 25652 => 28015,
25653 => 28062, 25654 => 28064, 25655 => 27998, 25656 => 28051, 25657 => 28052, 25653 => 28062, 25654 => 28064, 25655 => 27998, 25656 => 28051, 25657 => 28052,
25658 => 27996, 25659 => 28000, 25660 => 28028, 25661 => 28003, 25662 => 28186, 25658 => 27996, 25659 => 28000, 25660 => 28028, 25661 => 28003, 25662 => 28186,
25663 => 28103, 25664 => 28101, 25665 => 28126, 25666 => 28174, 25667 => 28095, 25663 => 28103, 25664 => 28101, 25665 => 28126, 25666 => 28174, 25667 => 28095,
25668 => 28128, 25669 => 28177, 25670 => 28134, 25671 => 28125, 25672 => 28121, 25668 => 28128, 25669 => 28177, 25670 => 28134, 25671 => 28125, 25672 => 28121,
25673 => 28182, 25674 => 28075, 25675 => 28172, 25676 => 28078, 25677 => 28203, 25673 => 28182, 25674 => 28075, 25675 => 28172, 25676 => 28078, 25677 => 28203,
25678 => 28270, 25679 => 28238, 25680 => 28267, 25681 => 28338, 25682 => 28255, 25678 => 28270, 25679 => 28238, 25680 => 28267, 25681 => 28338, 25682 => 28255,
25683 => 28294, 25684 => 28243, 25685 => 28244, 25686 => 28210, 25687 => 28197, 25683 => 28294, 25684 => 28243, 25685 => 28244, 25686 => 28210, 25687 => 28197,
25688 => 28228, 25689 => 28383, 25690 => 28337, 25691 => 28312, 25692 => 28384, 25688 => 28228, 25689 => 28383, 25690 => 28337, 25691 => 28312, 25692 => 28384,
25693 => 28461, 25694 => 28386, 25695 => 28325, 25696 => 28327, 25697 => 28349, 25693 => 28461, 25694 => 28386, 25695 => 28325, 25696 => 28327, 25697 => 28349,
25698 => 28347, 25699 => 28343, 25700 => 28375, 25701 => 28340, 25702 => 28367, 25698 => 28347, 25699 => 28343, 25700 => 28375, 25701 => 28340, 25702 => 28367,
25703 => 28303, 25704 => 28354, 25705 => 28319, 25706 => 28514, 25707 => 28486, 25703 => 28303, 25704 => 28354, 25705 => 28319, 25706 => 28514, 25707 => 28486,
25708 => 28487, 25709 => 28452, 25710 => 28437, 25711 => 28409, 25712 => 28463, 25708 => 28487, 25709 => 28452, 25710 => 28437, 25711 => 28409, 25712 => 28463,
25713 => 28470, 25714 => 28491, 25715 => 28532, 25716 => 28458, 25717 => 28425, 25713 => 28470, 25714 => 28491, 25715 => 28532, 25716 => 28458, 25717 => 28425,
25718 => 28457, 25719 => 28553, 25720 => 28557, 25721 => 28556, 25722 => 28536, 25718 => 28457, 25719 => 28553, 25720 => 28557, 25721 => 28556, 25722 => 28536,
25723 => 28530, 25724 => 28540, 25725 => 28538, 25726 => 28625, 25889 => 28617, 25723 => 28530, 25724 => 28540, 25725 => 28538, 25726 => 28625, 25889 => 28617,
25890 => 28583, 25891 => 28601, 25892 => 28598, 25893 => 28610, 25894 => 28641, 25890 => 28583, 25891 => 28601, 25892 => 28598, 25893 => 28610, 25894 => 28641,
25895 => 28654, 25896 => 28638, 25897 => 28640, 25898 => 28655, 25899 => 28698, 25895 => 28654, 25896 => 28638, 25897 => 28640, 25898 => 28655, 25899 => 28698,
25900 => 28707, 25901 => 28699, 25902 => 28729, 25903 => 28725, 25904 => 28751, 25900 => 28707, 25901 => 28699, 25902 => 28729, 25903 => 28725, 25904 => 28751,
25905 => 28766, 25906 => 23424, 25907 => 23428, 25908 => 23445, 25909 => 23443, 25905 => 28766, 25906 => 23424, 25907 => 23428, 25908 => 23445, 25909 => 23443,
25910 => 23461, 25911 => 23480, 25912 => 29999, 25913 => 39582, 25914 => 25652, 25910 => 23461, 25911 => 23480, 25912 => 29999, 25913 => 39582, 25914 => 25652,
25915 => 23524, 25916 => 23534, 25917 => 35120, 25918 => 23536, 25919 => 36423, 25915 => 23524, 25916 => 23534, 25917 => 35120, 25918 => 23536, 25919 => 36423,
25920 => 35591, 25921 => 36790, 25922 => 36819, 25923 => 36821, 25924 => 36837, 25920 => 35591, 25921 => 36790, 25922 => 36819, 25923 => 36821, 25924 => 36837,
25925 => 36846, 25926 => 36836, 25927 => 36841, 25928 => 36838, 25929 => 36851, 25925 => 36846, 25926 => 36836, 25927 => 36841, 25928 => 36838, 25929 => 36851,
25930 => 36840, 25931 => 36869, 25932 => 36868, 25933 => 36875, 25934 => 36902, 25930 => 36840, 25931 => 36869, 25932 => 36868, 25933 => 36875, 25934 => 36902,
25935 => 36881, 25936 => 36877, 25937 => 36886, 25938 => 36897, 25939 => 36917, 25935 => 36881, 25936 => 36877, 25937 => 36886, 25938 => 36897, 25939 => 36917,
25940 => 36918, 25941 => 36909, 25942 => 36911, 25943 => 36932, 25944 => 36945, 25940 => 36918, 25941 => 36909, 25942 => 36911, 25943 => 36932, 25944 => 36945,
25945 => 36946, 25946 => 36944, 25947 => 36968, 25948 => 36952, 25949 => 36962, 25945 => 36946, 25946 => 36944, 25947 => 36968, 25948 => 36952, 25949 => 36962,
25950 => 36955, 25951 => 26297, 25952 => 36980, 25953 => 36989, 25954 => 36994, 25950 => 36955, 25951 => 26297, 25952 => 36980, 25953 => 36989, 25954 => 36994,
25955 => 37000, 25956 => 36995, 25957 => 37003, 25958 => 24400, 25959 => 24407, 25955 => 37000, 25956 => 36995, 25957 => 37003, 25958 => 24400, 25959 => 24407,
25960 => 24406, 25961 => 24408, 25962 => 23611, 25963 => 21675, 25964 => 23632, 25960 => 24406, 25961 => 24408, 25962 => 23611, 25963 => 21675, 25964 => 23632,
25965 => 23641, 25966 => 23409, 25967 => 23651, 25968 => 23654, 25969 => 32700, 25965 => 23641, 25966 => 23409, 25967 => 23651, 25968 => 23654, 25969 => 32700,
25970 => 24362, 25971 => 24361, 25972 => 24365, 25973 => 33396, 25974 => 24380, 25970 => 24362, 25971 => 24361, 25972 => 24365, 25973 => 33396, 25974 => 24380,
25975 => 39739, 25976 => 23662, 25977 => 22913, 25978 => 22915, 25979 => 22925, 25975 => 39739, 25976 => 23662, 25977 => 22913, 25978 => 22915, 25979 => 22925,
25980 => 22953, 25981 => 22954, 25982 => 22947, 26145 => 22935, 26146 => 22986, 25980 => 22953, 25981 => 22954, 25982 => 22947, 26145 => 22935, 26146 => 22986,
26147 => 22955, 26148 => 22942, 26149 => 22948, 26150 => 22994, 26151 => 22962, 26147 => 22955, 26148 => 22942, 26149 => 22948, 26150 => 22994, 26151 => 22962,
26152 => 22959, 26153 => 22999, 26154 => 22974, 26155 => 23045, 26156 => 23046, 26152 => 22959, 26153 => 22999, 26154 => 22974, 26155 => 23045, 26156 => 23046,
26157 => 23005, 26158 => 23048, 26159 => 23011, 26160 => 23000, 26161 => 23033, 26157 => 23005, 26158 => 23048, 26159 => 23011, 26160 => 23000, 26161 => 23033,
26162 => 23052, 26163 => 23049, 26164 => 23090, 26165 => 23092, 26166 => 23057, 26162 => 23052, 26163 => 23049, 26164 => 23090, 26165 => 23092, 26166 => 23057,
26167 => 23075, 26168 => 23059, 26169 => 23104, 26170 => 23143, 26171 => 23114, 26167 => 23075, 26168 => 23059, 26169 => 23104, 26170 => 23143, 26171 => 23114,
26172 => 23125, 26173 => 23100, 26174 => 23138, 26175 => 23157, 26176 => 33004, 26172 => 23125, 26173 => 23100, 26174 => 23138, 26175 => 23157, 26176 => 33004,
26177 => 23210, 26178 => 23195, 26179 => 23159, 26180 => 23162, 26181 => 23230, 26177 => 23210, 26178 => 23195, 26179 => 23159, 26180 => 23162, 26181 => 23230,
26182 => 23275, 26183 => 23218, 26184 => 23250, 26185 => 23252, 26186 => 23224, 26182 => 23275, 26183 => 23218, 26184 => 23250, 26185 => 23252, 26186 => 23224,
26187 => 23264, 26188 => 23267, 26189 => 23281, 26190 => 23254, 26191 => 23270, 26187 => 23264, 26188 => 23267, 26189 => 23281, 26190 => 23254, 26191 => 23270,
26192 => 23256, 26193 => 23260, 26194 => 23305, 26195 => 23319, 26196 => 23318, 26192 => 23256, 26193 => 23260, 26194 => 23305, 26195 => 23319, 26196 => 23318,
26197 => 23346, 26198 => 23351, 26199 => 23360, 26200 => 23573, 26201 => 23580, 26197 => 23346, 26198 => 23351, 26199 => 23360, 26200 => 23573, 26201 => 23580,
26202 => 23386, 26203 => 23397, 26204 => 23411, 26205 => 23377, 26206 => 23379, 26202 => 23386, 26203 => 23397, 26204 => 23411, 26205 => 23377, 26206 => 23379,
26207 => 23394, 26208 => 39541, 26209 => 39543, 26210 => 39544, 26211 => 39546, 26207 => 23394, 26208 => 39541, 26209 => 39543, 26210 => 39544, 26211 => 39546,
26212 => 39551, 26213 => 39549, 26214 => 39552, 26215 => 39553, 26216 => 39557, 26212 => 39551, 26213 => 39549, 26214 => 39552, 26215 => 39553, 26216 => 39557,
26217 => 39560, 26218 => 39562, 26219 => 39568, 26220 => 39570, 26221 => 39571, 26217 => 39560, 26218 => 39562, 26219 => 39568, 26220 => 39570, 26221 => 39571,
26222 => 39574, 26223 => 39576, 26224 => 39579, 26225 => 39580, 26226 => 39581, 26222 => 39574, 26223 => 39576, 26224 => 39579, 26225 => 39580, 26226 => 39581,
26227 => 39583, 26228 => 39584, 26229 => 39586, 26230 => 39587, 26231 => 39589, 26227 => 39583, 26228 => 39584, 26229 => 39586, 26230 => 39587, 26231 => 39589,
26232 => 39591, 26233 => 32415, 26234 => 32417, 26235 => 32419, 26236 => 32421, 26232 => 39591, 26233 => 32415, 26234 => 32417, 26235 => 32419, 26236 => 32421,
26237 => 32424, 26238 => 32425, 26401 => 32429, 26402 => 32432, 26403 => 32446, 26237 => 32424, 26238 => 32425, 26401 => 32429, 26402 => 32432, 26403 => 32446,
26404 => 32448, 26405 => 32449, 26406 => 32450, 26407 => 32457, 26408 => 32459, 26404 => 32448, 26405 => 32449, 26406 => 32450, 26407 => 32457, 26408 => 32459,
26409 => 32460, 26410 => 32464, 26411 => 32468, 26412 => 32471, 26413 => 32475, 26409 => 32460, 26410 => 32464, 26411 => 32468, 26412 => 32471, 26413 => 32475,
26414 => 32480, 26415 => 32481, 26416 => 32488, 26417 => 32491, 26418 => 32494, 26414 => 32480, 26415 => 32481, 26416 => 32488, 26417 => 32491, 26418 => 32494,
26419 => 32495, 26420 => 32497, 26421 => 32498, 26422 => 32525, 26423 => 32502, 26419 => 32495, 26420 => 32497, 26421 => 32498, 26422 => 32525, 26423 => 32502,
26424 => 32506, 26425 => 32507, 26426 => 32510, 26427 => 32513, 26428 => 32514, 26424 => 32506, 26425 => 32507, 26426 => 32510, 26427 => 32513, 26428 => 32514,
26429 => 32515, 26430 => 32519, 26431 => 32520, 26432 => 32523, 26433 => 32524, 26429 => 32515, 26430 => 32519, 26431 => 32520, 26432 => 32523, 26433 => 32524,
26434 => 32527, 26435 => 32529, 26436 => 32530, 26437 => 32535, 26438 => 32537, 26434 => 32527, 26435 => 32529, 26436 => 32530, 26437 => 32535, 26438 => 32537,
26439 => 32540, 26440 => 32539, 26441 => 32543, 26442 => 32545, 26443 => 32546, 26439 => 32540, 26440 => 32539, 26441 => 32543, 26442 => 32545, 26443 => 32546,
26444 => 32547, 26445 => 32548, 26446 => 32549, 26447 => 32550, 26448 => 32551, 26444 => 32547, 26445 => 32548, 26446 => 32549, 26447 => 32550, 26448 => 32551,
26449 => 32554, 26450 => 32555, 26451 => 32556, 26452 => 32557, 26453 => 32559, 26449 => 32554, 26450 => 32555, 26451 => 32556, 26452 => 32557, 26453 => 32559,
26454 => 32560, 26455 => 32561, 26456 => 32562, 26457 => 32563, 26458 => 32565, 26454 => 32560, 26455 => 32561, 26456 => 32562, 26457 => 32563, 26458 => 32565,
26459 => 24186, 26460 => 30079, 26461 => 24027, 26462 => 30014, 26463 => 37013, 26459 => 24186, 26460 => 30079, 26461 => 24027, 26462 => 30014, 26463 => 37013,
26464 => 29582, 26465 => 29585, 26466 => 29614, 26467 => 29602, 26468 => 29599, 26464 => 29582, 26465 => 29585, 26466 => 29614, 26467 => 29602, 26468 => 29599,
26469 => 29647, 26470 => 29634, 26471 => 29649, 26472 => 29623, 26473 => 29619, 26469 => 29647, 26470 => 29634, 26471 => 29649, 26472 => 29623, 26473 => 29619,
26474 => 29632, 26475 => 29641, 26476 => 29640, 26477 => 29669, 26478 => 29657, 26474 => 29632, 26475 => 29641, 26476 => 29640, 26477 => 29669, 26478 => 29657,
26479 => 39036, 26480 => 29706, 26481 => 29673, 26482 => 29671, 26483 => 29662, 26479 => 39036, 26480 => 29706, 26481 => 29673, 26482 => 29671, 26483 => 29662,
26484 => 29626, 26485 => 29682, 26486 => 29711, 26487 => 29738, 26488 => 29787, 26484 => 29626, 26485 => 29682, 26486 => 29711, 26487 => 29738, 26488 => 29787,
26489 => 29734, 26490 => 29733, 26491 => 29736, 26492 => 29744, 26493 => 29742, 26489 => 29734, 26490 => 29733, 26491 => 29736, 26492 => 29744, 26493 => 29742,
26494 => 29740, 26657 => 29723, 26658 => 29722, 26659 => 29761, 26660 => 29788, 26494 => 29740, 26657 => 29723, 26658 => 29722, 26659 => 29761, 26660 => 29788,
26661 => 29783, 26662 => 29781, 26663 => 29785, 26664 => 29815, 26665 => 29805, 26661 => 29783, 26662 => 29781, 26663 => 29785, 26664 => 29815, 26665 => 29805,
26666 => 29822, 26667 => 29852, 26668 => 29838, 26669 => 29824, 26670 => 29825, 26666 => 29822, 26667 => 29852, 26668 => 29838, 26669 => 29824, 26670 => 29825,
26671 => 29831, 26672 => 29835, 26673 => 29854, 26674 => 29864, 26675 => 29865, 26671 => 29831, 26672 => 29835, 26673 => 29854, 26674 => 29864, 26675 => 29865,
26676 => 29840, 26677 => 29863, 26678 => 29906, 26679 => 29882, 26680 => 38890, 26676 => 29840, 26677 => 29863, 26678 => 29906, 26679 => 29882, 26680 => 38890,
26681 => 38891, 26682 => 38892, 26683 => 26444, 26684 => 26451, 26685 => 26462, 26681 => 38891, 26682 => 38892, 26683 => 26444, 26684 => 26451, 26685 => 26462,
26686 => 26440, 26687 => 26473, 26688 => 26533, 26689 => 26503, 26690 => 26474, 26686 => 26440, 26687 => 26473, 26688 => 26533, 26689 => 26503, 26690 => 26474,
26691 => 26483, 26692 => 26520, 26693 => 26535, 26694 => 26485, 26695 => 26536, 26691 => 26483, 26692 => 26520, 26693 => 26535, 26694 => 26485, 26695 => 26536,
26696 => 26526, 26697 => 26541, 26698 => 26507, 26699 => 26487, 26700 => 26492, 26696 => 26526, 26697 => 26541, 26698 => 26507, 26699 => 26487, 26700 => 26492,
26701 => 26608, 26702 => 26633, 26703 => 26584, 26704 => 26634, 26705 => 26601, 26701 => 26608, 26702 => 26633, 26703 => 26584, 26704 => 26634, 26705 => 26601,
26706 => 26544, 26707 => 26636, 26708 => 26585, 26709 => 26549, 26710 => 26586, 26706 => 26544, 26707 => 26636, 26708 => 26585, 26709 => 26549, 26710 => 26586,
26711 => 26547, 26712 => 26589, 26713 => 26624, 26714 => 26563, 26715 => 26552, 26711 => 26547, 26712 => 26589, 26713 => 26624, 26714 => 26563, 26715 => 26552,
26716 => 26594, 26717 => 26638, 26718 => 26561, 26719 => 26621, 26720 => 26674, 26716 => 26594, 26717 => 26638, 26718 => 26561, 26719 => 26621, 26720 => 26674,
26721 => 26675, 26722 => 26720, 26723 => 26721, 26724 => 26702, 26725 => 26722, 26721 => 26675, 26722 => 26720, 26723 => 26721, 26724 => 26702, 26725 => 26722,
26726 => 26692, 26727 => 26724, 26728 => 26755, 26729 => 26653, 26730 => 26709, 26726 => 26692, 26727 => 26724, 26728 => 26755, 26729 => 26653, 26730 => 26709,
26731 => 26726, 26732 => 26689, 26733 => 26727, 26734 => 26688, 26735 => 26686, 26731 => 26726, 26732 => 26689, 26733 => 26727, 26734 => 26688, 26735 => 26686,
26736 => 26698, 26737 => 26697, 26738 => 26665, 26739 => 26805, 26740 => 26767, 26736 => 26698, 26737 => 26697, 26738 => 26665, 26739 => 26805, 26740 => 26767,
26741 => 26740, 26742 => 26743, 26743 => 26771, 26744 => 26731, 26745 => 26818, 26741 => 26740, 26742 => 26743, 26743 => 26771, 26744 => 26731, 26745 => 26818,
26746 => 26990, 26747 => 26876, 26748 => 26911, 26749 => 26912, 26750 => 26873, 26746 => 26990, 26747 => 26876, 26748 => 26911, 26749 => 26912, 26750 => 26873,
26913 => 26916, 26914 => 26864, 26915 => 26891, 26916 => 26881, 26917 => 26967, 26913 => 26916, 26914 => 26864, 26915 => 26891, 26916 => 26881, 26917 => 26967,
26918 => 26851, 26919 => 26896, 26920 => 26993, 26921 => 26937, 26922 => 26976, 26918 => 26851, 26919 => 26896, 26920 => 26993, 26921 => 26937, 26922 => 26976,
26923 => 26946, 26924 => 26973, 26925 => 27012, 26926 => 26987, 26927 => 27008, 26923 => 26946, 26924 => 26973, 26925 => 27012, 26926 => 26987, 26927 => 27008,
26928 => 27032, 26929 => 27000, 26930 => 26932, 26931 => 27084, 26932 => 27015, 26928 => 27032, 26929 => 27000, 26930 => 26932, 26931 => 27084, 26932 => 27015,
26933 => 27016, 26934 => 27086, 26935 => 27017, 26936 => 26982, 26937 => 26979, 26933 => 27016, 26934 => 27086, 26935 => 27017, 26936 => 26982, 26937 => 26979,
26938 => 27001, 26939 => 27035, 26940 => 27047, 26941 => 27067, 26942 => 27051, 26938 => 27001, 26939 => 27035, 26940 => 27047, 26941 => 27067, 26942 => 27051,
26943 => 27053, 26944 => 27092, 26945 => 27057, 26946 => 27073, 26947 => 27082, 26943 => 27053, 26944 => 27092, 26945 => 27057, 26946 => 27073, 26947 => 27082,
26948 => 27103, 26949 => 27029, 26950 => 27104, 26951 => 27021, 26952 => 27135, 26948 => 27103, 26949 => 27029, 26950 => 27104, 26951 => 27021, 26952 => 27135,
26953 => 27183, 26954 => 27117, 26955 => 27159, 26956 => 27160, 26957 => 27237, 26953 => 27183, 26954 => 27117, 26955 => 27159, 26956 => 27160, 26957 => 27237,
26958 => 27122, 26959 => 27204, 26960 => 27198, 26961 => 27296, 26962 => 27216, 26958 => 27122, 26959 => 27204, 26960 => 27198, 26961 => 27296, 26962 => 27216,
26963 => 27227, 26964 => 27189, 26965 => 27278, 26966 => 27257, 26967 => 27197, 26963 => 27227, 26964 => 27189, 26965 => 27278, 26966 => 27257, 26967 => 27197,
26968 => 27176, 26969 => 27224, 26970 => 27260, 26971 => 27281, 26972 => 27280, 26968 => 27176, 26969 => 27224, 26970 => 27260, 26971 => 27281, 26972 => 27280,
26973 => 27305, 26974 => 27287, 26975 => 27307, 26976 => 29495, 26977 => 29522, 26973 => 27305, 26974 => 27287, 26975 => 27307, 26976 => 29495, 26977 => 29522,
26978 => 27521, 26979 => 27522, 26980 => 27527, 26981 => 27524, 26982 => 27538, 26978 => 27521, 26979 => 27522, 26980 => 27527, 26981 => 27524, 26982 => 27538,
26983 => 27539, 26984 => 27533, 26985 => 27546, 26986 => 27547, 26987 => 27553, 26983 => 27539, 26984 => 27533, 26985 => 27546, 26986 => 27547, 26987 => 27553,
26988 => 27562, 26989 => 36715, 26990 => 36717, 26991 => 36721, 26992 => 36722, 26988 => 27562, 26989 => 36715, 26990 => 36717, 26991 => 36721, 26992 => 36722,
26993 => 36723, 26994 => 36725, 26995 => 36726, 26996 => 36728, 26997 => 36727, 26993 => 36723, 26994 => 36725, 26995 => 36726, 26996 => 36728, 26997 => 36727,
26998 => 36729, 26999 => 36730, 27000 => 36732, 27001 => 36734, 27002 => 36737, 26998 => 36729, 26999 => 36730, 27000 => 36732, 27001 => 36734, 27002 => 36737,
27003 => 36738, 27004 => 36740, 27005 => 36743, 27006 => 36747, 27169 => 36749, 27003 => 36738, 27004 => 36740, 27005 => 36743, 27006 => 36747, 27169 => 36749,
27170 => 36750, 27171 => 36751, 27172 => 36760, 27173 => 36762, 27174 => 36558, 27170 => 36750, 27171 => 36751, 27172 => 36760, 27173 => 36762, 27174 => 36558,
27175 => 25099, 27176 => 25111, 27177 => 25115, 27178 => 25119, 27179 => 25122, 27175 => 25099, 27176 => 25111, 27177 => 25115, 27178 => 25119, 27179 => 25122,
27180 => 25121, 27181 => 25125, 27182 => 25124, 27183 => 25132, 27184 => 33255, 27180 => 25121, 27181 => 25125, 27182 => 25124, 27183 => 25132, 27184 => 33255,
27185 => 29935, 27186 => 29940, 27187 => 29951, 27188 => 29967, 27189 => 29969, 27185 => 29935, 27186 => 29940, 27187 => 29951, 27188 => 29967, 27189 => 29969,
27190 => 29971, 27191 => 25908, 27192 => 26094, 27193 => 26095, 27194 => 26096, 27190 => 29971, 27191 => 25908, 27192 => 26094, 27193 => 26095, 27194 => 26096,
27195 => 26122, 27196 => 26137, 27197 => 26482, 27198 => 26115, 27199 => 26133, 27195 => 26122, 27196 => 26137, 27197 => 26482, 27198 => 26115, 27199 => 26133,
27200 => 26112, 27201 => 28805, 27202 => 26359, 27203 => 26141, 27204 => 26164, 27200 => 26112, 27201 => 28805, 27202 => 26359, 27203 => 26141, 27204 => 26164,
27205 => 26161, 27206 => 26166, 27207 => 26165, 27208 => 32774, 27209 => 26207, 27205 => 26161, 27206 => 26166, 27207 => 26165, 27208 => 32774, 27209 => 26207,
27210 => 26196, 27211 => 26177, 27212 => 26191, 27213 => 26198, 27214 => 26209, 27210 => 26196, 27211 => 26177, 27212 => 26191, 27213 => 26198, 27214 => 26209,
27215 => 26199, 27216 => 26231, 27217 => 26244, 27218 => 26252, 27219 => 26279, 27215 => 26199, 27216 => 26231, 27217 => 26244, 27218 => 26252, 27219 => 26279,
27220 => 26269, 27221 => 26302, 27222 => 26331, 27223 => 26332, 27224 => 26342, 27220 => 26269, 27221 => 26302, 27222 => 26331, 27223 => 26332, 27224 => 26342,
27225 => 26345, 27226 => 36146, 27227 => 36147, 27228 => 36150, 27229 => 36155, 27225 => 26345, 27226 => 36146, 27227 => 36147, 27228 => 36150, 27229 => 36155,
27230 => 36157, 27231 => 36160, 27232 => 36165, 27233 => 36166, 27234 => 36168, 27230 => 36157, 27231 => 36160, 27232 => 36165, 27233 => 36166, 27234 => 36168,
27235 => 36169, 27236 => 36167, 27237 => 36173, 27238 => 36181, 27239 => 36185, 27235 => 36169, 27236 => 36167, 27237 => 36173, 27238 => 36181, 27239 => 36185,
27240 => 35271, 27241 => 35274, 27242 => 35275, 27243 => 35276, 27244 => 35278, 27240 => 35271, 27241 => 35274, 27242 => 35275, 27243 => 35276, 27244 => 35278,
27245 => 35279, 27246 => 35280, 27247 => 35281, 27248 => 29294, 27249 => 29343, 27245 => 35279, 27246 => 35280, 27247 => 35281, 27248 => 29294, 27249 => 29343,
27250 => 29277, 27251 => 29286, 27252 => 29295, 27253 => 29310, 27254 => 29311, 27250 => 29277, 27251 => 29286, 27252 => 29295, 27253 => 29310, 27254 => 29311,
27255 => 29316, 27256 => 29323, 27257 => 29325, 27258 => 29327, 27259 => 29330, 27255 => 29316, 27256 => 29323, 27257 => 29325, 27258 => 29327, 27259 => 29330,
27260 => 25352, 27261 => 25394, 27262 => 25520, 27425 => 25663, 27426 => 25816, 27260 => 25352, 27261 => 25394, 27262 => 25520, 27425 => 25663, 27426 => 25816,
27427 => 32772, 27428 => 27626, 27429 => 27635, 27430 => 27645, 27431 => 27637, 27427 => 32772, 27428 => 27626, 27429 => 27635, 27430 => 27645, 27431 => 27637,
27432 => 27641, 27433 => 27653, 27434 => 27655, 27435 => 27654, 27436 => 27661, 27432 => 27641, 27433 => 27653, 27434 => 27655, 27435 => 27654, 27436 => 27661,
27437 => 27669, 27438 => 27672, 27439 => 27673, 27440 => 27674, 27441 => 27681, 27437 => 27669, 27438 => 27672, 27439 => 27673, 27440 => 27674, 27441 => 27681,
27442 => 27689, 27443 => 27684, 27444 => 27690, 27445 => 27698, 27446 => 25909, 27442 => 27689, 27443 => 27684, 27444 => 27690, 27445 => 27698, 27446 => 25909,
27447 => 25941, 27448 => 25963, 27449 => 29261, 27450 => 29266, 27451 => 29270, 27447 => 25941, 27448 => 25963, 27449 => 29261, 27450 => 29266, 27451 => 29270,
27452 => 29232, 27453 => 34402, 27454 => 21014, 27455 => 32927, 27456 => 32924, 27452 => 29232, 27453 => 34402, 27454 => 21014, 27455 => 32927, 27456 => 32924,
27457 => 32915, 27458 => 32956, 27459 => 26378, 27460 => 32957, 27461 => 32945, 27457 => 32915, 27458 => 32956, 27459 => 26378, 27460 => 32957, 27461 => 32945,
27462 => 32939, 27463 => 32941, 27464 => 32948, 27465 => 32951, 27466 => 32999, 27462 => 32939, 27463 => 32941, 27464 => 32948, 27465 => 32951, 27466 => 32999,
27467 => 33000, 27468 => 33001, 27469 => 33002, 27470 => 32987, 27471 => 32962, 27467 => 33000, 27468 => 33001, 27469 => 33002, 27470 => 32987, 27471 => 32962,
27472 => 32964, 27473 => 32985, 27474 => 32973, 27475 => 32983, 27476 => 26384, 27472 => 32964, 27473 => 32985, 27474 => 32973, 27475 => 32983, 27476 => 26384,
27477 => 32989, 27478 => 33003, 27479 => 33009, 27480 => 33012, 27481 => 33005, 27477 => 32989, 27478 => 33003, 27479 => 33009, 27480 => 33012, 27481 => 33005,
27482 => 33037, 27483 => 33038, 27484 => 33010, 27485 => 33020, 27486 => 26389, 27482 => 33037, 27483 => 33038, 27484 => 33010, 27485 => 33020, 27486 => 26389,
27487 => 33042, 27488 => 35930, 27489 => 33078, 27490 => 33054, 27491 => 33068, 27487 => 33042, 27488 => 35930, 27489 => 33078, 27490 => 33054, 27491 => 33068,
27492 => 33048, 27493 => 33074, 27494 => 33096, 27495 => 33100, 27496 => 33107, 27492 => 33048, 27493 => 33074, 27494 => 33096, 27495 => 33100, 27496 => 33107,
27497 => 33140, 27498 => 33113, 27499 => 33114, 27500 => 33137, 27501 => 33120, 27497 => 33140, 27498 => 33113, 27499 => 33114, 27500 => 33137, 27501 => 33120,
27502 => 33129, 27503 => 33148, 27504 => 33149, 27505 => 33133, 27506 => 33127, 27502 => 33129, 27503 => 33148, 27504 => 33149, 27505 => 33133, 27506 => 33127,
27507 => 22605, 27508 => 23221, 27509 => 33160, 27510 => 33154, 27511 => 33169, 27507 => 22605, 27508 => 23221, 27509 => 33160, 27510 => 33154, 27511 => 33169,
27512 => 28373, 27513 => 33187, 27514 => 33194, 27515 => 33228, 27516 => 26406, 27512 => 28373, 27513 => 33187, 27514 => 33194, 27515 => 33228, 27516 => 26406,
27517 => 33226, 27518 => 33211, 27681 => 33217, 27682 => 33190, 27683 => 27428, 27517 => 33226, 27518 => 33211, 27681 => 33217, 27682 => 33190, 27683 => 27428,
27684 => 27447, 27685 => 27449, 27686 => 27459, 27687 => 27462, 27688 => 27481, 27684 => 27447, 27685 => 27449, 27686 => 27459, 27687 => 27462, 27688 => 27481,
27689 => 39121, 27690 => 39122, 27691 => 39123, 27692 => 39125, 27693 => 39129, 27689 => 39121, 27690 => 39122, 27691 => 39123, 27692 => 39125, 27693 => 39129,
27694 => 39130, 27695 => 27571, 27696 => 24384, 27697 => 27586, 27698 => 35315, 27694 => 39130, 27695 => 27571, 27696 => 24384, 27697 => 27586, 27698 => 35315,
27699 => 26000, 27700 => 40785, 27701 => 26003, 27702 => 26044, 27703 => 26054, 27699 => 26000, 27700 => 40785, 27701 => 26003, 27702 => 26044, 27703 => 26054,
27704 => 26052, 27705 => 26051, 27706 => 26060, 27707 => 26062, 27708 => 26066, 27704 => 26052, 27705 => 26051, 27706 => 26060, 27707 => 26062, 27708 => 26066,
27709 => 26070, 27710 => 28800, 27711 => 28828, 27712 => 28822, 27713 => 28829, 27709 => 26070, 27710 => 28800, 27711 => 28828, 27712 => 28822, 27713 => 28829,
27714 => 28859, 27715 => 28864, 27716 => 28855, 27717 => 28843, 27718 => 28849, 27714 => 28859, 27715 => 28864, 27716 => 28855, 27717 => 28843, 27718 => 28849,
27719 => 28904, 27720 => 28874, 27721 => 28944, 27722 => 28947, 27723 => 28950, 27719 => 28904, 27720 => 28874, 27721 => 28944, 27722 => 28947, 27723 => 28950,
27724 => 28975, 27725 => 28977, 27726 => 29043, 27727 => 29020, 27728 => 29032, 27724 => 28975, 27725 => 28977, 27726 => 29043, 27727 => 29020, 27728 => 29032,
27729 => 28997, 27730 => 29042, 27731 => 29002, 27732 => 29048, 27733 => 29050, 27729 => 28997, 27730 => 29042, 27731 => 29002, 27732 => 29048, 27733 => 29050,
27734 => 29080, 27735 => 29107, 27736 => 29109, 27737 => 29096, 27738 => 29088, 27734 => 29080, 27735 => 29107, 27736 => 29109, 27737 => 29096, 27738 => 29088,
27739 => 29152, 27740 => 29140, 27741 => 29159, 27742 => 29177, 27743 => 29213, 27739 => 29152, 27740 => 29140, 27741 => 29159, 27742 => 29177, 27743 => 29213,
27744 => 29224, 27745 => 28780, 27746 => 28952, 27747 => 29030, 27748 => 29113, 27744 => 29224, 27745 => 28780, 27746 => 28952, 27747 => 29030, 27748 => 29113,
27749 => 25150, 27750 => 25149, 27751 => 25155, 27752 => 25160, 27753 => 25161, 27749 => 25150, 27750 => 25149, 27751 => 25155, 27752 => 25160, 27753 => 25161,
27754 => 31035, 27755 => 31040, 27756 => 31046, 27757 => 31049, 27758 => 31067, 27754 => 31035, 27755 => 31040, 27756 => 31046, 27757 => 31049, 27758 => 31067,
27759 => 31068, 27760 => 31059, 27761 => 31066, 27762 => 31074, 27763 => 31063, 27759 => 31068, 27760 => 31059, 27761 => 31066, 27762 => 31074, 27763 => 31063,
27764 => 31072, 27765 => 31087, 27766 => 31079, 27767 => 31098, 27768 => 31109, 27764 => 31072, 27765 => 31087, 27766 => 31079, 27767 => 31098, 27768 => 31109,
27769 => 31114, 27770 => 31130, 27771 => 31143, 27772 => 31155, 27773 => 24529, 27769 => 31114, 27770 => 31130, 27771 => 31143, 27772 => 31155, 27773 => 24529,
27774 => 24528, 27937 => 24636, 27938 => 24669, 27939 => 24666, 27940 => 24679, 27774 => 24528, 27937 => 24636, 27938 => 24669, 27939 => 24666, 27940 => 24679,
27941 => 24641, 27942 => 24665, 27943 => 24675, 27944 => 24747, 27945 => 24838, 27941 => 24641, 27942 => 24665, 27943 => 24675, 27944 => 24747, 27945 => 24838,
27946 => 24845, 27947 => 24925, 27948 => 25001, 27949 => 24989, 27950 => 25035, 27946 => 24845, 27947 => 24925, 27948 => 25001, 27949 => 24989, 27950 => 25035,
27951 => 25041, 27952 => 25094, 27953 => 32896, 27954 => 32895, 27955 => 27795, 27951 => 25041, 27952 => 25094, 27953 => 32896, 27954 => 32895, 27955 => 27795,
27956 => 27894, 27957 => 28156, 27958 => 30710, 27959 => 30712, 27960 => 30720, 27956 => 27894, 27957 => 28156, 27958 => 30710, 27959 => 30712, 27960 => 30720,
27961 => 30729, 27962 => 30743, 27963 => 30744, 27964 => 30737, 27965 => 26027, 27961 => 30729, 27962 => 30743, 27963 => 30744, 27964 => 30737, 27965 => 26027,
27966 => 30765, 27967 => 30748, 27968 => 30749, 27969 => 30777, 27970 => 30778, 27966 => 30765, 27967 => 30748, 27968 => 30749, 27969 => 30777, 27970 => 30778,
27971 => 30779, 27972 => 30751, 27973 => 30780, 27974 => 30757, 27975 => 30764, 27971 => 30779, 27972 => 30751, 27973 => 30780, 27974 => 30757, 27975 => 30764,
27976 => 30755, 27977 => 30761, 27978 => 30798, 27979 => 30829, 27980 => 30806, 27976 => 30755, 27977 => 30761, 27978 => 30798, 27979 => 30829, 27980 => 30806,
27981 => 30807, 27982 => 30758, 27983 => 30800, 27984 => 30791, 27985 => 30796, 27981 => 30807, 27982 => 30758, 27983 => 30800, 27984 => 30791, 27985 => 30796,
27986 => 30826, 27987 => 30875, 27988 => 30867, 27989 => 30874, 27990 => 30855, 27986 => 30826, 27987 => 30875, 27988 => 30867, 27989 => 30874, 27990 => 30855,
27991 => 30876, 27992 => 30881, 27993 => 30883, 27994 => 30898, 27995 => 30905, 27991 => 30876, 27992 => 30881, 27993 => 30883, 27994 => 30898, 27995 => 30905,
27996 => 30885, 27997 => 30932, 27998 => 30937, 27999 => 30921, 28000 => 30956, 27996 => 30885, 27997 => 30932, 27998 => 30937, 27999 => 30921, 28000 => 30956,
28001 => 30962, 28002 => 30981, 28003 => 30964, 28004 => 30995, 28005 => 31012, 28001 => 30962, 28002 => 30981, 28003 => 30964, 28004 => 30995, 28005 => 31012,
28006 => 31006, 28007 => 31028, 28008 => 40859, 28009 => 40697, 28010 => 40699, 28006 => 31006, 28007 => 31028, 28008 => 40859, 28009 => 40697, 28010 => 40699,
28011 => 40700, 28012 => 30449, 28013 => 30468, 28014 => 30477, 28015 => 30457, 28011 => 40700, 28012 => 30449, 28013 => 30468, 28014 => 30477, 28015 => 30457,
28016 => 30471, 28017 => 30472, 28018 => 30490, 28019 => 30498, 28020 => 30489, 28016 => 30471, 28017 => 30472, 28018 => 30490, 28019 => 30498, 28020 => 30489,
28021 => 30509, 28022 => 30502, 28023 => 30517, 28024 => 30520, 28025 => 30544, 28021 => 30509, 28022 => 30502, 28023 => 30517, 28024 => 30520, 28025 => 30544,
28026 => 30545, 28027 => 30535, 28028 => 30531, 28029 => 30554, 28030 => 30568, 28026 => 30545, 28027 => 30535, 28028 => 30531, 28029 => 30554, 28030 => 30568,
28193 => 30562, 28194 => 30565, 28195 => 30591, 28196 => 30605, 28197 => 30589, 28193 => 30562, 28194 => 30565, 28195 => 30591, 28196 => 30605, 28197 => 30589,
28198 => 30592, 28199 => 30604, 28200 => 30609, 28201 => 30623, 28202 => 30624, 28198 => 30592, 28199 => 30604, 28200 => 30609, 28201 => 30623, 28202 => 30624,
28203 => 30640, 28204 => 30645, 28205 => 30653, 28206 => 30010, 28207 => 30016, 28203 => 30640, 28204 => 30645, 28205 => 30653, 28206 => 30010, 28207 => 30016,
28208 => 30030, 28209 => 30027, 28210 => 30024, 28211 => 30043, 28212 => 30066, 28208 => 30030, 28209 => 30027, 28210 => 30024, 28211 => 30043, 28212 => 30066,
28213 => 30073, 28214 => 30083, 28215 => 32600, 28216 => 32609, 28217 => 32607, 28213 => 30073, 28214 => 30083, 28215 => 32600, 28216 => 32609, 28217 => 32607,
28218 => 35400, 28219 => 32616, 28220 => 32628, 28221 => 32625, 28222 => 32633, 28218 => 35400, 28219 => 32616, 28220 => 32628, 28221 => 32625, 28222 => 32633,
28223 => 32641, 28224 => 32638, 28225 => 30413, 28226 => 30437, 28227 => 34866, 28223 => 32641, 28224 => 32638, 28225 => 30413, 28226 => 30437, 28227 => 34866,
28228 => 38021, 28229 => 38022, 28230 => 38023, 28231 => 38027, 28232 => 38026, 28228 => 38021, 28229 => 38022, 28230 => 38023, 28231 => 38027, 28232 => 38026,
28233 => 38028, 28234 => 38029, 28235 => 38031, 28236 => 38032, 28237 => 38036, 28233 => 38028, 28234 => 38029, 28235 => 38031, 28236 => 38032, 28237 => 38036,
28238 => 38039, 28239 => 38037, 28240 => 38042, 28241 => 38043, 28242 => 38044, 28238 => 38039, 28239 => 38037, 28240 => 38042, 28241 => 38043, 28242 => 38044,
28243 => 38051, 28244 => 38052, 28245 => 38059, 28246 => 38058, 28247 => 38061, 28243 => 38051, 28244 => 38052, 28245 => 38059, 28246 => 38058, 28247 => 38061,
28248 => 38060, 28249 => 38063, 28250 => 38064, 28251 => 38066, 28252 => 38068, 28248 => 38060, 28249 => 38063, 28250 => 38064, 28251 => 38066, 28252 => 38068,
28253 => 38070, 28254 => 38071, 28255 => 38072, 28256 => 38073, 28257 => 38074, 28253 => 38070, 28254 => 38071, 28255 => 38072, 28256 => 38073, 28257 => 38074,
28258 => 38076, 28259 => 38077, 28260 => 38079, 28261 => 38084, 28262 => 38088, 28258 => 38076, 28259 => 38077, 28260 => 38079, 28261 => 38084, 28262 => 38088,
28263 => 38089, 28264 => 38090, 28265 => 38091, 28266 => 38092, 28267 => 38093, 28263 => 38089, 28264 => 38090, 28265 => 38091, 28266 => 38092, 28267 => 38093,
28268 => 38094, 28269 => 38096, 28270 => 38097, 28271 => 38098, 28272 => 38101, 28268 => 38094, 28269 => 38096, 28270 => 38097, 28271 => 38098, 28272 => 38101,
28273 => 38102, 28274 => 38103, 28275 => 38105, 28276 => 38104, 28277 => 38107, 28273 => 38102, 28274 => 38103, 28275 => 38105, 28276 => 38104, 28277 => 38107,
28278 => 38110, 28279 => 38111, 28280 => 38112, 28281 => 38114, 28282 => 38116, 28278 => 38110, 28279 => 38111, 28280 => 38112, 28281 => 38114, 28282 => 38116,
28283 => 38117, 28284 => 38119, 28285 => 38120, 28286 => 38122, 28449 => 38121, 28283 => 38117, 28284 => 38119, 28285 => 38120, 28286 => 38122, 28449 => 38121,
28450 => 38123, 28451 => 38126, 28452 => 38127, 28453 => 38131, 28454 => 38132, 28450 => 38123, 28451 => 38126, 28452 => 38127, 28453 => 38131, 28454 => 38132,
28455 => 38133, 28456 => 38135, 28457 => 38137, 28458 => 38140, 28459 => 38141, 28455 => 38133, 28456 => 38135, 28457 => 38137, 28458 => 38140, 28459 => 38141,
28460 => 38143, 28461 => 38147, 28462 => 38146, 28463 => 38150, 28464 => 38151, 28460 => 38143, 28461 => 38147, 28462 => 38146, 28463 => 38150, 28464 => 38151,
28465 => 38153, 28466 => 38154, 28467 => 38157, 28468 => 38158, 28469 => 38159, 28465 => 38153, 28466 => 38154, 28467 => 38157, 28468 => 38158, 28469 => 38159,
28470 => 38162, 28471 => 38163, 28472 => 38164, 28473 => 38165, 28474 => 38166, 28470 => 38162, 28471 => 38163, 28472 => 38164, 28473 => 38165, 28474 => 38166,
28475 => 38168, 28476 => 38171, 28477 => 38173, 28478 => 38174, 28479 => 38175, 28475 => 38168, 28476 => 38171, 28477 => 38173, 28478 => 38174, 28479 => 38175,
28480 => 38178, 28481 => 38186, 28482 => 38187, 28483 => 38185, 28484 => 38188, 28480 => 38178, 28481 => 38186, 28482 => 38187, 28483 => 38185, 28484 => 38188,
28485 => 38193, 28486 => 38194, 28487 => 38196, 28488 => 38198, 28489 => 38199, 28485 => 38193, 28486 => 38194, 28487 => 38196, 28488 => 38198, 28489 => 38199,
28490 => 38200, 28491 => 38204, 28492 => 38206, 28493 => 38207, 28494 => 38210, 28490 => 38200, 28491 => 38204, 28492 => 38206, 28493 => 38207, 28494 => 38210,
28495 => 38197, 28496 => 38212, 28497 => 38213, 28498 => 38214, 28499 => 38217, 28495 => 38197, 28496 => 38212, 28497 => 38213, 28498 => 38214, 28499 => 38217,
28500 => 38220, 28501 => 38222, 28502 => 38223, 28503 => 38226, 28504 => 38227, 28500 => 38220, 28501 => 38222, 28502 => 38223, 28503 => 38226, 28504 => 38227,
28505 => 38228, 28506 => 38230, 28507 => 38231, 28508 => 38232, 28509 => 38233, 28505 => 38228, 28506 => 38230, 28507 => 38231, 28508 => 38232, 28509 => 38233,
28510 => 38235, 28511 => 38238, 28512 => 38239, 28513 => 38237, 28514 => 38241, 28510 => 38235, 28511 => 38238, 28512 => 38239, 28513 => 38237, 28514 => 38241,
28515 => 38242, 28516 => 38244, 28517 => 38245, 28518 => 38246, 28519 => 38247, 28515 => 38242, 28516 => 38244, 28517 => 38245, 28518 => 38246, 28519 => 38247,
28520 => 38248, 28521 => 38249, 28522 => 38250, 28523 => 38251, 28524 => 38252, 28520 => 38248, 28521 => 38249, 28522 => 38250, 28523 => 38251, 28524 => 38252,
28525 => 38255, 28526 => 38257, 28527 => 38258, 28528 => 38259, 28529 => 38202, 28525 => 38255, 28526 => 38257, 28527 => 38258, 28528 => 38259, 28529 => 38202,
28530 => 30695, 28531 => 30700, 28532 => 38601, 28533 => 31189, 28534 => 31213, 28530 => 30695, 28531 => 30700, 28532 => 38601, 28533 => 31189, 28534 => 31213,
28535 => 31203, 28536 => 31211, 28537 => 31238, 28538 => 23879, 28539 => 31235, 28535 => 31203, 28536 => 31211, 28537 => 31238, 28538 => 23879, 28539 => 31235,
28540 => 31234, 28541 => 31262, 28542 => 31252, 28705 => 31289, 28706 => 31287, 28540 => 31234, 28541 => 31262, 28542 => 31252, 28705 => 31289, 28706 => 31287,
28707 => 31313, 28708 => 40655, 28709 => 39333, 28710 => 31344, 28711 => 30344, 28707 => 31313, 28708 => 40655, 28709 => 39333, 28710 => 31344, 28711 => 30344,
28712 => 30350, 28713 => 30355, 28714 => 30361, 28715 => 30372, 28716 => 29918, 28712 => 30350, 28713 => 30355, 28714 => 30361, 28715 => 30372, 28716 => 29918,
28717 => 29920, 28718 => 29996, 28719 => 40480, 28720 => 40482, 28721 => 40488, 28717 => 29920, 28718 => 29996, 28719 => 40480, 28720 => 40482, 28721 => 40488,
28722 => 40489, 28723 => 40490, 28724 => 40491, 28725 => 40492, 28726 => 40498, 28722 => 40489, 28723 => 40490, 28724 => 40491, 28725 => 40492, 28726 => 40498,
28727 => 40497, 28728 => 40502, 28729 => 40504, 28730 => 40503, 28731 => 40505, 28727 => 40497, 28728 => 40502, 28729 => 40504, 28730 => 40503, 28731 => 40505,
28732 => 40506, 28733 => 40510, 28734 => 40513, 28735 => 40514, 28736 => 40516, 28732 => 40506, 28733 => 40510, 28734 => 40513, 28735 => 40514, 28736 => 40516,
28737 => 40518, 28738 => 40519, 28739 => 40520, 28740 => 40521, 28741 => 40523, 28737 => 40518, 28738 => 40519, 28739 => 40520, 28740 => 40521, 28741 => 40523,
28742 => 40524, 28743 => 40526, 28744 => 40529, 28745 => 40533, 28746 => 40535, 28742 => 40524, 28743 => 40526, 28744 => 40529, 28745 => 40533, 28746 => 40535,
28747 => 40538, 28748 => 40539, 28749 => 40540, 28750 => 40542, 28751 => 40547, 28747 => 40538, 28748 => 40539, 28749 => 40540, 28750 => 40542, 28751 => 40547,
28752 => 40550, 28753 => 40551, 28754 => 40552, 28755 => 40553, 28756 => 40554, 28752 => 40550, 28753 => 40551, 28754 => 40552, 28755 => 40553, 28756 => 40554,
28757 => 40555, 28758 => 40556, 28759 => 40561, 28760 => 40557, 28761 => 40563, 28757 => 40555, 28758 => 40556, 28759 => 40561, 28760 => 40557, 28761 => 40563,
28762 => 30098, 28763 => 30100, 28764 => 30102, 28765 => 30112, 28766 => 30109, 28762 => 30098, 28763 => 30100, 28764 => 30102, 28765 => 30112, 28766 => 30109,
28767 => 30124, 28768 => 30115, 28769 => 30131, 28770 => 30132, 28771 => 30136, 28767 => 30124, 28768 => 30115, 28769 => 30131, 28770 => 30132, 28771 => 30136,
28772 => 30148, 28773 => 30129, 28774 => 30128, 28775 => 30147, 28776 => 30146, 28772 => 30148, 28773 => 30129, 28774 => 30128, 28775 => 30147, 28776 => 30146,
28777 => 30166, 28778 => 30157, 28779 => 30179, 28780 => 30184, 28781 => 30182, 28777 => 30166, 28778 => 30157, 28779 => 30179, 28780 => 30184, 28781 => 30182,
28782 => 30180, 28783 => 30187, 28784 => 30183, 28785 => 30211, 28786 => 30193, 28782 => 30180, 28783 => 30187, 28784 => 30183, 28785 => 30211, 28786 => 30193,
28787 => 30204, 28788 => 30207, 28789 => 30224, 28790 => 30208, 28791 => 30213, 28787 => 30204, 28788 => 30207, 28789 => 30224, 28790 => 30208, 28791 => 30213,
28792 => 30220, 28793 => 30231, 28794 => 30218, 28795 => 30245, 28796 => 30232, 28792 => 30220, 28793 => 30231, 28794 => 30218, 28795 => 30245, 28796 => 30232,
28797 => 30229, 28798 => 30233, 28961 => 30235, 28962 => 30268, 28963 => 30242, 28797 => 30229, 28798 => 30233, 28961 => 30235, 28962 => 30268, 28963 => 30242,
28964 => 30240, 28965 => 30272, 28966 => 30253, 28967 => 30256, 28968 => 30271, 28964 => 30240, 28965 => 30272, 28966 => 30253, 28967 => 30256, 28968 => 30271,
28969 => 30261, 28970 => 30275, 28971 => 30270, 28972 => 30259, 28973 => 30285, 28969 => 30261, 28970 => 30275, 28971 => 30270, 28972 => 30259, 28973 => 30285,
28974 => 30302, 28975 => 30292, 28976 => 30300, 28977 => 30294, 28978 => 30315, 28974 => 30302, 28975 => 30292, 28976 => 30300, 28977 => 30294, 28978 => 30315,
28979 => 30319, 28980 => 32714, 28981 => 31462, 28982 => 31352, 28983 => 31353, 28979 => 30319, 28980 => 32714, 28981 => 31462, 28982 => 31352, 28983 => 31353,
28984 => 31360, 28985 => 31366, 28986 => 31368, 28987 => 31381, 28988 => 31398, 28984 => 31360, 28985 => 31366, 28986 => 31368, 28987 => 31381, 28988 => 31398,
28989 => 31392, 28990 => 31404, 28991 => 31400, 28992 => 31405, 28993 => 31411, 28989 => 31392, 28990 => 31404, 28991 => 31400, 28992 => 31405, 28993 => 31411,
28994 => 34916, 28995 => 34921, 28996 => 34930, 28997 => 34941, 28998 => 34943, 28994 => 34916, 28995 => 34921, 28996 => 34930, 28997 => 34941, 28998 => 34943,
28999 => 34946, 29000 => 34978, 29001 => 35014, 29002 => 34999, 29003 => 35004, 28999 => 34946, 29000 => 34978, 29001 => 35014, 29002 => 34999, 29003 => 35004,
29004 => 35017, 29005 => 35042, 29006 => 35022, 29007 => 35043, 29008 => 35045, 29004 => 35017, 29005 => 35042, 29006 => 35022, 29007 => 35043, 29008 => 35045,
29009 => 35057, 29010 => 35098, 29011 => 35068, 29012 => 35048, 29013 => 35070, 29009 => 35057, 29010 => 35098, 29011 => 35068, 29012 => 35048, 29013 => 35070,
29014 => 35056, 29015 => 35105, 29016 => 35097, 29017 => 35091, 29018 => 35099, 29014 => 35056, 29015 => 35105, 29016 => 35097, 29017 => 35091, 29018 => 35099,
29019 => 35082, 29020 => 35124, 29021 => 35115, 29022 => 35126, 29023 => 35137, 29019 => 35082, 29020 => 35124, 29021 => 35115, 29022 => 35126, 29023 => 35137,
29024 => 35174, 29025 => 35195, 29026 => 30091, 29027 => 32997, 29028 => 30386, 29024 => 35174, 29025 => 35195, 29026 => 30091, 29027 => 32997, 29028 => 30386,
29029 => 30388, 29030 => 30684, 29031 => 32786, 29032 => 32788, 29033 => 32790, 29029 => 30388, 29030 => 30684, 29031 => 32786, 29032 => 32788, 29033 => 32790,
29034 => 32796, 29035 => 32800, 29036 => 32802, 29037 => 32805, 29038 => 32806, 29034 => 32796, 29035 => 32800, 29036 => 32802, 29037 => 32805, 29038 => 32806,
29039 => 32807, 29040 => 32809, 29041 => 32808, 29042 => 32817, 29043 => 32779, 29039 => 32807, 29040 => 32809, 29041 => 32808, 29042 => 32817, 29043 => 32779,
29044 => 32821, 29045 => 32835, 29046 => 32838, 29047 => 32845, 29048 => 32850, 29044 => 32821, 29045 => 32835, 29046 => 32838, 29047 => 32845, 29048 => 32850,
29049 => 32873, 29050 => 32881, 29051 => 35203, 29052 => 39032, 29053 => 39040, 29049 => 32873, 29050 => 32881, 29051 => 35203, 29052 => 39032, 29053 => 39040,
29054 => 39043, 29217 => 39049, 29218 => 39052, 29219 => 39053, 29220 => 39055, 29054 => 39043, 29217 => 39049, 29218 => 39052, 29219 => 39053, 29220 => 39055,
29221 => 39060, 29222 => 39066, 29223 => 39067, 29224 => 39070, 29225 => 39071, 29221 => 39060, 29222 => 39066, 29223 => 39067, 29224 => 39070, 29225 => 39071,
29226 => 39073, 29227 => 39074, 29228 => 39077, 29229 => 39078, 29230 => 34381, 29226 => 39073, 29227 => 39074, 29228 => 39077, 29229 => 39078, 29230 => 34381,
29231 => 34388, 29232 => 34412, 29233 => 34414, 29234 => 34431, 29235 => 34426, 29231 => 34388, 29232 => 34412, 29233 => 34414, 29234 => 34431, 29235 => 34426,
29236 => 34428, 29237 => 34427, 29238 => 34472, 29239 => 34445, 29240 => 34443, 29236 => 34428, 29237 => 34427, 29238 => 34472, 29239 => 34445, 29240 => 34443,
29241 => 34476, 29242 => 34461, 29243 => 34471, 29244 => 34467, 29245 => 34474, 29241 => 34476, 29242 => 34461, 29243 => 34471, 29244 => 34467, 29245 => 34474,
29246 => 34451, 29247 => 34473, 29248 => 34486, 29249 => 34500, 29250 => 34485, 29246 => 34451, 29247 => 34473, 29248 => 34486, 29249 => 34500, 29250 => 34485,
29251 => 34510, 29252 => 34480, 29253 => 34490, 29254 => 34481, 29255 => 34479, 29251 => 34510, 29252 => 34480, 29253 => 34490, 29254 => 34481, 29255 => 34479,
29256 => 34505, 29257 => 34511, 29258 => 34484, 29259 => 34537, 29260 => 34545, 29256 => 34505, 29257 => 34511, 29258 => 34484, 29259 => 34537, 29260 => 34545,
29261 => 34546, 29262 => 34541, 29263 => 34547, 29264 => 34512, 29265 => 34579, 29261 => 34546, 29262 => 34541, 29263 => 34547, 29264 => 34512, 29265 => 34579,
29266 => 34526, 29267 => 34548, 29268 => 34527, 29269 => 34520, 29270 => 34513, 29266 => 34526, 29267 => 34548, 29268 => 34527, 29269 => 34520, 29270 => 34513,
29271 => 34563, 29272 => 34567, 29273 => 34552, 29274 => 34568, 29275 => 34570, 29271 => 34563, 29272 => 34567, 29273 => 34552, 29274 => 34568, 29275 => 34570,
29276 => 34573, 29277 => 34569, 29278 => 34595, 29279 => 34619, 29280 => 34590, 29276 => 34573, 29277 => 34569, 29278 => 34595, 29279 => 34619, 29280 => 34590,
29281 => 34597, 29282 => 34606, 29283 => 34586, 29284 => 34622, 29285 => 34632, 29281 => 34597, 29282 => 34606, 29283 => 34586, 29284 => 34622, 29285 => 34632,
29286 => 34612, 29287 => 34609, 29288 => 34601, 29289 => 34615, 29290 => 34623, 29286 => 34612, 29287 => 34609, 29288 => 34601, 29289 => 34615, 29290 => 34623,
29291 => 34690, 29292 => 34594, 29293 => 34685, 29294 => 34686, 29295 => 34683, 29291 => 34690, 29292 => 34594, 29293 => 34685, 29294 => 34686, 29295 => 34683,
29296 => 34656, 29297 => 34672, 29298 => 34636, 29299 => 34670, 29300 => 34699, 29296 => 34656, 29297 => 34672, 29298 => 34636, 29299 => 34670, 29300 => 34699,
29301 => 34643, 29302 => 34659, 29303 => 34684, 29304 => 34660, 29305 => 34649, 29301 => 34643, 29302 => 34659, 29303 => 34684, 29304 => 34660, 29305 => 34649,
29306 => 34661, 29307 => 34707, 29308 => 34735, 29309 => 34728, 29310 => 34770, 29306 => 34661, 29307 => 34707, 29308 => 34735, 29309 => 34728, 29310 => 34770,
29473 => 34758, 29474 => 34696, 29475 => 34693, 29476 => 34733, 29477 => 34711, 29473 => 34758, 29474 => 34696, 29475 => 34693, 29476 => 34733, 29477 => 34711,
29478 => 34691, 29479 => 34731, 29480 => 34789, 29481 => 34732, 29482 => 34741, 29478 => 34691, 29479 => 34731, 29480 => 34789, 29481 => 34732, 29482 => 34741,
29483 => 34739, 29484 => 34763, 29485 => 34771, 29486 => 34749, 29487 => 34769, 29483 => 34739, 29484 => 34763, 29485 => 34771, 29486 => 34749, 29487 => 34769,
29488 => 34752, 29489 => 34762, 29490 => 34779, 29491 => 34794, 29492 => 34784, 29488 => 34752, 29489 => 34762, 29490 => 34779, 29491 => 34794, 29492 => 34784,
29493 => 34798, 29494 => 34838, 29495 => 34835, 29496 => 34814, 29497 => 34826, 29493 => 34798, 29494 => 34838, 29495 => 34835, 29496 => 34814, 29497 => 34826,
29498 => 34843, 29499 => 34849, 29500 => 34873, 29501 => 34876, 29502 => 32566, 29498 => 34843, 29499 => 34849, 29500 => 34873, 29501 => 34876, 29502 => 32566,
29503 => 32578, 29504 => 32580, 29505 => 32581, 29506 => 33296, 29507 => 31482, 29503 => 32578, 29504 => 32580, 29505 => 32581, 29506 => 33296, 29507 => 31482,
29508 => 31485, 29509 => 31496, 29510 => 31491, 29511 => 31492, 29512 => 31509, 29508 => 31485, 29509 => 31496, 29510 => 31491, 29511 => 31492, 29512 => 31509,
29513 => 31498, 29514 => 31531, 29515 => 31503, 29516 => 31559, 29517 => 31544, 29513 => 31498, 29514 => 31531, 29515 => 31503, 29516 => 31559, 29517 => 31544,
29518 => 31530, 29519 => 31513, 29520 => 31534, 29521 => 31537, 29522 => 31520, 29518 => 31530, 29519 => 31513, 29520 => 31534, 29521 => 31537, 29522 => 31520,
29523 => 31525, 29524 => 31524, 29525 => 31539, 29526 => 31550, 29527 => 31518, 29523 => 31525, 29524 => 31524, 29525 => 31539, 29526 => 31550, 29527 => 31518,
29528 => 31576, 29529 => 31578, 29530 => 31557, 29531 => 31605, 29532 => 31564, 29528 => 31576, 29529 => 31578, 29530 => 31557, 29531 => 31605, 29532 => 31564,
29533 => 31581, 29534 => 31584, 29535 => 31598, 29536 => 31611, 29537 => 31586, 29533 => 31581, 29534 => 31584, 29535 => 31598, 29536 => 31611, 29537 => 31586,
29538 => 31602, 29539 => 31601, 29540 => 31632, 29541 => 31654, 29542 => 31655, 29538 => 31602, 29539 => 31601, 29540 => 31632, 29541 => 31654, 29542 => 31655,
29543 => 31672, 29544 => 31660, 29545 => 31645, 29546 => 31656, 29547 => 31621, 29543 => 31672, 29544 => 31660, 29545 => 31645, 29546 => 31656, 29547 => 31621,
29548 => 31658, 29549 => 31644, 29550 => 31650, 29551 => 31659, 29552 => 31668, 29548 => 31658, 29549 => 31644, 29550 => 31650, 29551 => 31659, 29552 => 31668,
29553 => 31697, 29554 => 31681, 29555 => 31692, 29556 => 31709, 29557 => 31706, 29553 => 31697, 29554 => 31681, 29555 => 31692, 29556 => 31709, 29557 => 31706,
29558 => 31717, 29559 => 31718, 29560 => 31722, 29561 => 31756, 29562 => 31742, 29558 => 31717, 29559 => 31718, 29560 => 31722, 29561 => 31756, 29562 => 31742,
29563 => 31740, 29564 => 31759, 29565 => 31766, 29566 => 31755, 29729 => 31775, 29563 => 31740, 29564 => 31759, 29565 => 31766, 29566 => 31755, 29729 => 31775,
29730 => 31786, 29731 => 31782, 29732 => 31800, 29733 => 31809, 29734 => 31808, 29730 => 31786, 29731 => 31782, 29732 => 31800, 29733 => 31809, 29734 => 31808,
29735 => 33278, 29736 => 33281, 29737 => 33282, 29738 => 33284, 29739 => 33260, 29735 => 33278, 29736 => 33281, 29737 => 33282, 29738 => 33284, 29739 => 33260,
29740 => 34884, 29741 => 33313, 29742 => 33314, 29743 => 33315, 29744 => 33325, 29740 => 34884, 29741 => 33313, 29742 => 33314, 29743 => 33315, 29744 => 33325,
29745 => 33327, 29746 => 33320, 29747 => 33323, 29748 => 33336, 29749 => 33339, 29745 => 33327, 29746 => 33320, 29747 => 33323, 29748 => 33336, 29749 => 33339,
29750 => 33331, 29751 => 33332, 29752 => 33342, 29753 => 33348, 29754 => 33353, 29750 => 33331, 29751 => 33332, 29752 => 33342, 29753 => 33348, 29754 => 33353,
29755 => 33355, 29756 => 33359, 29757 => 33370, 29758 => 33375, 29759 => 33384, 29755 => 33355, 29756 => 33359, 29757 => 33370, 29758 => 33375, 29759 => 33384,
29760 => 34942, 29761 => 34949, 29762 => 34952, 29763 => 35032, 29764 => 35039, 29760 => 34942, 29761 => 34949, 29762 => 34952, 29763 => 35032, 29764 => 35039,
29765 => 35166, 29766 => 32669, 29767 => 32671, 29768 => 32679, 29769 => 32687, 29765 => 35166, 29766 => 32669, 29767 => 32671, 29768 => 32679, 29769 => 32687,
29770 => 32688, 29771 => 32690, 29772 => 31868, 29773 => 25929, 29774 => 31889, 29770 => 32688, 29771 => 32690, 29772 => 31868, 29773 => 25929, 29774 => 31889,
29775 => 31901, 29776 => 31900, 29777 => 31902, 29778 => 31906, 29779 => 31922, 29775 => 31901, 29776 => 31900, 29777 => 31902, 29778 => 31906, 29779 => 31922,
29780 => 31932, 29781 => 31933, 29782 => 31937, 29783 => 31943, 29784 => 31948, 29780 => 31932, 29781 => 31933, 29782 => 31937, 29783 => 31943, 29784 => 31948,
29785 => 31949, 29786 => 31944, 29787 => 31941, 29788 => 31959, 29789 => 31976, 29785 => 31949, 29786 => 31944, 29787 => 31941, 29788 => 31959, 29789 => 31976,
29790 => 33390, 29791 => 26280, 29792 => 32703, 29793 => 32718, 29794 => 32725, 29790 => 33390, 29791 => 26280, 29792 => 32703, 29793 => 32718, 29794 => 32725,
29795 => 32741, 29796 => 32737, 29797 => 32742, 29798 => 32745, 29799 => 32750, 29795 => 32741, 29796 => 32737, 29797 => 32742, 29798 => 32745, 29799 => 32750,
29800 => 32755, 29801 => 31992, 29802 => 32119, 29803 => 32166, 29804 => 32174, 29800 => 32755, 29801 => 31992, 29802 => 32119, 29803 => 32166, 29804 => 32174,
29805 => 32327, 29806 => 32411, 29807 => 40632, 29808 => 40628, 29809 => 36211, 29805 => 32327, 29806 => 32411, 29807 => 40632, 29808 => 40628, 29809 => 36211,
29810 => 36228, 29811 => 36244, 29812 => 36241, 29813 => 36273, 29814 => 36199, 29810 => 36228, 29811 => 36244, 29812 => 36241, 29813 => 36273, 29814 => 36199,
29815 => 36205, 29816 => 35911, 29817 => 35913, 29818 => 37194, 29819 => 37200, 29815 => 36205, 29816 => 35911, 29817 => 35913, 29818 => 37194, 29819 => 37200,
29820 => 37198, 29821 => 37199, 29822 => 37220, 29985 => 37218, 29986 => 37217, 29820 => 37198, 29821 => 37199, 29822 => 37220, 29985 => 37218, 29986 => 37217,
29987 => 37232, 29988 => 37225, 29989 => 37231, 29990 => 37245, 29991 => 37246, 29987 => 37232, 29988 => 37225, 29989 => 37231, 29990 => 37245, 29991 => 37246,
29992 => 37234, 29993 => 37236, 29994 => 37241, 29995 => 37260, 29996 => 37253, 29992 => 37234, 29993 => 37236, 29994 => 37241, 29995 => 37260, 29996 => 37253,
29997 => 37264, 29998 => 37261, 29999 => 37265, 30000 => 37282, 30001 => 37283, 29997 => 37264, 29998 => 37261, 29999 => 37265, 30000 => 37282, 30001 => 37283,
30002 => 37290, 30003 => 37293, 30004 => 37294, 30005 => 37295, 30006 => 37301, 30002 => 37290, 30003 => 37293, 30004 => 37294, 30005 => 37295, 30006 => 37301,
30007 => 37300, 30008 => 37306, 30009 => 35925, 30010 => 40574, 30011 => 36280, 30007 => 37300, 30008 => 37306, 30009 => 35925, 30010 => 40574, 30011 => 36280,
30012 => 36331, 30013 => 36357, 30014 => 36441, 30015 => 36457, 30016 => 36277, 30012 => 36331, 30013 => 36357, 30014 => 36441, 30015 => 36457, 30016 => 36277,
30017 => 36287, 30018 => 36284, 30019 => 36282, 30020 => 36292, 30021 => 36310, 30017 => 36287, 30018 => 36284, 30019 => 36282, 30020 => 36292, 30021 => 36310,
30022 => 36311, 30023 => 36314, 30024 => 36318, 30025 => 36302, 30026 => 36303, 30022 => 36311, 30023 => 36314, 30024 => 36318, 30025 => 36302, 30026 => 36303,
30027 => 36315, 30028 => 36294, 30029 => 36332, 30030 => 36343, 30031 => 36344, 30027 => 36315, 30028 => 36294, 30029 => 36332, 30030 => 36343, 30031 => 36344,
30032 => 36323, 30033 => 36345, 30034 => 36347, 30035 => 36324, 30036 => 36361, 30032 => 36323, 30033 => 36345, 30034 => 36347, 30035 => 36324, 30036 => 36361,
30037 => 36349, 30038 => 36372, 30039 => 36381, 30040 => 36383, 30041 => 36396, 30037 => 36349, 30038 => 36372, 30039 => 36381, 30040 => 36383, 30041 => 36396,
30042 => 36398, 30043 => 36387, 30044 => 36399, 30045 => 36410, 30046 => 36416, 30042 => 36398, 30043 => 36387, 30044 => 36399, 30045 => 36410, 30046 => 36416,
30047 => 36409, 30048 => 36405, 30049 => 36413, 30050 => 36401, 30051 => 36425, 30047 => 36409, 30048 => 36405, 30049 => 36413, 30050 => 36401, 30051 => 36425,
30052 => 36417, 30053 => 36418, 30054 => 36433, 30055 => 36434, 30056 => 36426, 30052 => 36417, 30053 => 36418, 30054 => 36433, 30055 => 36434, 30056 => 36426,
30057 => 36464, 30058 => 36470, 30059 => 36476, 30060 => 36463, 30061 => 36468, 30057 => 36464, 30058 => 36470, 30059 => 36476, 30060 => 36463, 30061 => 36468,
30062 => 36485, 30063 => 36495, 30064 => 36500, 30065 => 36496, 30066 => 36508, 30062 => 36485, 30063 => 36495, 30064 => 36500, 30065 => 36496, 30066 => 36508,
30067 => 36510, 30068 => 35960, 30069 => 35970, 30070 => 35978, 30071 => 35973, 30067 => 36510, 30068 => 35960, 30069 => 35970, 30070 => 35978, 30071 => 35973,
30072 => 35992, 30073 => 35988, 30074 => 26011, 30075 => 35286, 30076 => 35294, 30072 => 35992, 30073 => 35988, 30074 => 26011, 30075 => 35286, 30076 => 35294,
30077 => 35290, 30078 => 35292, 30241 => 35301, 30242 => 35307, 30243 => 35311, 30077 => 35290, 30078 => 35292, 30241 => 35301, 30242 => 35307, 30243 => 35311,
30244 => 35390, 30245 => 35622, 30246 => 38739, 30247 => 38633, 30248 => 38643, 30244 => 35390, 30245 => 35622, 30246 => 38739, 30247 => 38633, 30248 => 38643,
30249 => 38639, 30250 => 38662, 30251 => 38657, 30252 => 38664, 30253 => 38671, 30249 => 38639, 30250 => 38662, 30251 => 38657, 30252 => 38664, 30253 => 38671,
30254 => 38670, 30255 => 38698, 30256 => 38701, 30257 => 38704, 30258 => 38718, 30254 => 38670, 30255 => 38698, 30256 => 38701, 30257 => 38704, 30258 => 38718,
30259 => 40832, 30260 => 40835, 30261 => 40837, 30262 => 40838, 30263 => 40839, 30259 => 40832, 30260 => 40835, 30261 => 40837, 30262 => 40838, 30263 => 40839,
30264 => 40840, 30265 => 40841, 30266 => 40842, 30267 => 40844, 30268 => 40702, 30264 => 40840, 30265 => 40841, 30266 => 40842, 30267 => 40844, 30268 => 40702,
30269 => 40715, 30270 => 40717, 30271 => 38585, 30272 => 38588, 30273 => 38589, 30269 => 40715, 30270 => 40717, 30271 => 38585, 30272 => 38588, 30273 => 38589,
30274 => 38606, 30275 => 38610, 30276 => 30655, 30277 => 38624, 30278 => 37518, 30274 => 38606, 30275 => 38610, 30276 => 30655, 30277 => 38624, 30278 => 37518,
30279 => 37550, 30280 => 37576, 30281 => 37694, 30282 => 37738, 30283 => 37834, 30279 => 37550, 30280 => 37576, 30281 => 37694, 30282 => 37738, 30283 => 37834,
30284 => 37775, 30285 => 37950, 30286 => 37995, 30287 => 40063, 30288 => 40066, 30284 => 37775, 30285 => 37950, 30286 => 37995, 30287 => 40063, 30288 => 40066,
30289 => 40069, 30290 => 40070, 30291 => 40071, 30292 => 40072, 30293 => 31267, 30289 => 40069, 30290 => 40070, 30291 => 40071, 30292 => 40072, 30293 => 31267,
30294 => 40075, 30295 => 40078, 30296 => 40080, 30297 => 40081, 30298 => 40082, 30294 => 40075, 30295 => 40078, 30296 => 40080, 30297 => 40081, 30298 => 40082,
30299 => 40084, 30300 => 40085, 30301 => 40090, 30302 => 40091, 30303 => 40094, 30299 => 40084, 30300 => 40085, 30301 => 40090, 30302 => 40091, 30303 => 40094,
30304 => 40095, 30305 => 40096, 30306 => 40097, 30307 => 40098, 30308 => 40099, 30304 => 40095, 30305 => 40096, 30306 => 40097, 30307 => 40098, 30308 => 40099,
30309 => 40101, 30310 => 40102, 30311 => 40103, 30312 => 40104, 30313 => 40105, 30309 => 40101, 30310 => 40102, 30311 => 40103, 30312 => 40104, 30313 => 40105,
30314 => 40107, 30315 => 40109, 30316 => 40110, 30317 => 40112, 30318 => 40113, 30314 => 40107, 30315 => 40109, 30316 => 40110, 30317 => 40112, 30318 => 40113,
30319 => 40114, 30320 => 40115, 30321 => 40116, 30322 => 40117, 30323 => 40118, 30319 => 40114, 30320 => 40115, 30321 => 40116, 30322 => 40117, 30323 => 40118,
30324 => 40119, 30325 => 40122, 30326 => 40123, 30327 => 40124, 30328 => 40125, 30324 => 40119, 30325 => 40122, 30326 => 40123, 30327 => 40124, 30328 => 40125,
30329 => 40132, 30330 => 40133, 30331 => 40134, 30332 => 40135, 30333 => 40138, 30329 => 40132, 30330 => 40133, 30331 => 40134, 30332 => 40135, 30333 => 40138,
30334 => 40139, 30497 => 40140, 30498 => 40141, 30499 => 40142, 30500 => 40143, 30334 => 40139, 30497 => 40140, 30498 => 40141, 30499 => 40142, 30500 => 40143,
30501 => 40144, 30502 => 40147, 30503 => 40148, 30504 => 40149, 30505 => 40151, 30501 => 40144, 30502 => 40147, 30503 => 40148, 30504 => 40149, 30505 => 40151,
30506 => 40152, 30507 => 40153, 30508 => 40156, 30509 => 40157, 30510 => 40159, 30506 => 40152, 30507 => 40153, 30508 => 40156, 30509 => 40157, 30510 => 40159,
30511 => 40162, 30512 => 38780, 30513 => 38789, 30514 => 38801, 30515 => 38802, 30511 => 40162, 30512 => 38780, 30513 => 38789, 30514 => 38801, 30515 => 38802,
30516 => 38804, 30517 => 38831, 30518 => 38827, 30519 => 38819, 30520 => 38834, 30516 => 38804, 30517 => 38831, 30518 => 38827, 30519 => 38819, 30520 => 38834,
30521 => 38836, 30522 => 39601, 30523 => 39600, 30524 => 39607, 30525 => 40536, 30521 => 38836, 30522 => 39601, 30523 => 39600, 30524 => 39607, 30525 => 40536,
30526 => 39606, 30527 => 39610, 30528 => 39612, 30529 => 39617, 30530 => 39616, 30526 => 39606, 30527 => 39610, 30528 => 39612, 30529 => 39617, 30530 => 39616,
30531 => 39621, 30532 => 39618, 30533 => 39627, 30534 => 39628, 30535 => 39633, 30531 => 39621, 30532 => 39618, 30533 => 39627, 30534 => 39628, 30535 => 39633,
30536 => 39749, 30537 => 39747, 30538 => 39751, 30539 => 39753, 30540 => 39752, 30536 => 39749, 30537 => 39747, 30538 => 39751, 30539 => 39753, 30540 => 39752,
30541 => 39757, 30542 => 39761, 30543 => 39144, 30544 => 39181, 30545 => 39214, 30541 => 39757, 30542 => 39761, 30543 => 39144, 30544 => 39181, 30545 => 39214,
30546 => 39253, 30547 => 39252, 30548 => 39647, 30549 => 39649, 30550 => 39654, 30546 => 39253, 30547 => 39252, 30548 => 39647, 30549 => 39649, 30550 => 39654,
30551 => 39663, 30552 => 39659, 30553 => 39675, 30554 => 39661, 30555 => 39673, 30551 => 39663, 30552 => 39659, 30553 => 39675, 30554 => 39661, 30555 => 39673,
30556 => 39688, 30557 => 39695, 30558 => 39699, 30559 => 39711, 30560 => 39715, 30556 => 39688, 30557 => 39695, 30558 => 39699, 30559 => 39711, 30560 => 39715,
30561 => 40637, 30562 => 40638, 30563 => 32315, 30564 => 40578, 30565 => 40583, 30561 => 40637, 30562 => 40638, 30563 => 32315, 30564 => 40578, 30565 => 40583,
30566 => 40584, 30567 => 40587, 30568 => 40594, 30569 => 37846, 30570 => 40605, 30566 => 40584, 30567 => 40587, 30568 => 40594, 30569 => 37846, 30570 => 40605,
30571 => 40607, 30572 => 40667, 30573 => 40668, 30574 => 40669, 30575 => 40672, 30571 => 40607, 30572 => 40667, 30573 => 40668, 30574 => 40669, 30575 => 40672,
30576 => 40671, 30577 => 40674, 30578 => 40681, 30579 => 40679, 30580 => 40677, 30576 => 40671, 30577 => 40674, 30578 => 40681, 30579 => 40679, 30580 => 40677,
30581 => 40682, 30582 => 40687, 30583 => 40738, 30584 => 40748, 30585 => 40751, 30581 => 40682, 30582 => 40687, 30583 => 40738, 30584 => 40748, 30585 => 40751,
30586 => 40761, 30587 => 40759, 30588 => 40765, 30589 => 40766, 30590 => 40772, 30586 => 40761, 30587 => 40759, 30588 => 40765, 30589 => 40766, 30590 => 40772,
0 => 0 ); 0 => 0 );
   
function gb2utf8($gb) { function gb2utf8($gb) {
if( !trim($gb) ) return $gb; if( !trim($gb) ) return $gb;
$utf8=''; $utf8='';
while($gb) { while($gb) {
if( ord(substr($gb,0,1)) > 127 ) { if( ord(substr($gb,0,1)) > 127 ) {
$t=substr($gb,0,2); $t=substr($gb,0,2);
$gb=substr($gb,2); $gb=substr($gb,2);
$utf8 .= $this->u2utf8($this->codetable[hexdec(bin2hex($t))-0x8080]); $utf8 .= $this->u2utf8($this->codetable[hexdec(bin2hex($t))-0x8080]);
} }
else { else {
$t=substr($gb,0,1); $t=substr($gb,0,1);
$gb=substr($gb,1); $gb=substr($gb,1);
$utf8 .= $this->u2utf8($t); $utf8 .= $this->u2utf8($t);
} }
} }
return $utf8; return $utf8;
} }
   
function u2utf8($c) { function u2utf8($c) {
$str=''; $str='';
if ($c < 0x80) { if ($c < 0x80) {
$str.=$c; $str.=$c;
} }
else if ($c < 0x800) { else if ($c < 0x800) {
$str.=chr(0xC0 | $c>>6); $str.=chr(0xC0 | $c>>6);
$str.=chr(0x80 | $c & 0x3F); $str.=chr(0x80 | $c & 0x3F);
} }
else if ($c < 0x10000) { else if ($c < 0x10000) {
$str.=chr(0xE0 | $c>>12); $str.=chr(0xE0 | $c>>12);
$str.=chr(0x80 | $c>>6 & 0x3F); $str.=chr(0x80 | $c>>6 & 0x3F);
$str.=chr(0x80 | $c & 0x3F); $str.=chr(0x80 | $c & 0x3F);
} }
else if ($c < 0x200000) { else if ($c < 0x200000) {
$str.=chr(0xF0 | $c>>18); $str.=chr(0xF0 | $c>>18);
$str.=chr(0x80 | $c>>12 & 0x3F); $str.=chr(0x80 | $c>>12 & 0x3F);
$str.=chr(0x80 | $c>>6 & 0x3F); $str.=chr(0x80 | $c>>6 & 0x3F);
$str.=chr(0x80 | $c & 0x3F); $str.=chr(0x80 | $c & 0x3F);
} }
return $str; return $str;
} }
   
} // END Class } // END Class
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_GRADIENT.PHP // File: JPGRAPH_GRADIENT.PHP
// Description: Create a color gradient // Description: Create a color gradient
// Created: 2003-02-01 // Created: 2003-02-01
// Ver: $Id: jpgraph_gradient.php 1761 2009-08-01 08:31:28Z ljp $ // Ver: $Id: jpgraph_gradient.php 1761 2009-08-01 08:31:28Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
// Styles for gradient color fill // Styles for gradient color fill
define("GRAD_VER",1); define("GRAD_VER",1);
define("GRAD_VERT",1); define("GRAD_VERT",1);
define("GRAD_HOR",2); define("GRAD_HOR",2);
define("GRAD_MIDHOR",3); define("GRAD_MIDHOR",3);
define("GRAD_MIDVER",4); define("GRAD_MIDVER",4);
define("GRAD_CENTER",5); define("GRAD_CENTER",5);
define("GRAD_WIDE_MIDVER",6); define("GRAD_WIDE_MIDVER",6);
define("GRAD_WIDE_MIDHOR",7); define("GRAD_WIDE_MIDHOR",7);
define("GRAD_LEFT_REFLECTION",8); define("GRAD_LEFT_REFLECTION",8);
define("GRAD_RIGHT_REFLECTION",9); define("GRAD_RIGHT_REFLECTION",9);
define("GRAD_RAISED_PANEL",10); define("GRAD_RAISED_PANEL",10);
define("GRAD_DIAGONAL",11); define("GRAD_DIAGONAL",11);
   
//=================================================== //===================================================
// CLASS Gradient // CLASS Gradient
// Description: Handles gradient fills. This is to be // Description: Handles gradient fills. This is to be
// considered a "friend" class of Class Image. // considered a "friend" class of Class Image.
//=================================================== //===================================================
class Gradient { class Gradient {
private $img=null, $numcolors=100; private $img=null, $numcolors=100;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct(&$img) { function __construct(&$img) {
$this->img = $img; $this->img = $img;
} }
   
   
function SetNumColors($aNum) { function SetNumColors($aNum) {
$this->numcolors=$aNum; $this->numcolors=$aNum;
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
// Produce a gradient filled rectangle with a smooth transition between // Produce a gradient filled rectangle with a smooth transition between
// two colors. // two colors.
// ($xl,$yt) Top left corner // ($xl,$yt) Top left corner
// ($xr,$yb) Bottom right // ($xr,$yb) Bottom right
// $from_color Starting color in gradient // $from_color Starting color in gradient
// $to_color End color in the gradient // $to_color End color in the gradient
// $style Which way is the gradient oriented? // $style Which way is the gradient oriented?
function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) { function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) {
$this->img->SetLineWeight(1); $this->img->SetLineWeight(1);
switch( $style ) { switch( $style ) {
case GRAD_VER: case GRAD_VER:
$steps = ceil(abs($xr-$xl)+1); $steps = ceil(abs($xr-$xl)+1);
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
$this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
for( $i=0, $x=$xl; $i < $steps; ++$i ) { for( $i=0, $x=$xl; $i < $steps; ++$i ) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yt,$x,$yb); $this->img->Line($x,$yt,$x,$yb);
$x += $delta; $x += $delta;
} }
break; break;
   
case GRAD_HOR: case GRAD_HOR:
$steps = ceil(abs($yb-$yt)+1); $steps = ceil(abs($yb-$yt)+1);
$delta = $yb >= $yt ? 1 : -1; $delta = $yb >= $yt ? 1 : -1;
$this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
for($i=0,$y=$yt; $i < $steps; ++$i) { for($i=0,$y=$yt; $i < $steps; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
$y += $delta; $y += $delta;
} }
break; break;
   
case GRAD_MIDHOR: case GRAD_MIDHOR:
$steps = ceil(abs($yb-$yt)/2); $steps = ceil(abs($yb-$yt)/2);
$delta = $yb >= $yt ? 1 : -1; $delta = $yb >= $yt ? 1 : -1;
$this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
for($y=$yt, $i=0; $i < $steps; ++$i) { for($y=$yt, $i=0; $i < $steps; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
$y += $delta; $y += $delta;
} }
--$i; --$i;
if( abs($yb-$yt) % 2 == 1 ) { if( abs($yb-$yt) % 2 == 1 ) {
--$steps; --$steps;
} }
for($j=0; $j < $steps; ++$j, --$i) { for($j=0; $j < $steps; ++$j, --$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
$y += $delta; $y += $delta;
} }
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
break; break;
   
case GRAD_MIDVER: case GRAD_MIDVER:
$steps = ceil(abs($xr-$xl)/2); $steps = ceil(abs($xr-$xl)/2);
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
$this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
for($x=$xl, $i=0; $i < $steps; ++$i) { for($x=$xl, $i=0; $i < $steps; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
--$i; --$i;
if( abs($xr-$xl) % 2 == 1 ) { if( abs($xr-$xl) % 2 == 1 ) {
--$steps; --$steps;
} }
for($j=0; $j < $steps; ++$j, --$i) { for($j=0; $j < $steps; ++$j, --$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
break; break;
   
case GRAD_WIDE_MIDVER: case GRAD_WIDE_MIDVER:
$diff = ceil(abs($xr-$xl)); $diff = ceil(abs($xr-$xl));
$steps = floor(abs($diff)/3); $steps = floor(abs($diff)/3);
$firststep = $diff - 2*$steps ; $firststep = $diff - 2*$steps ;
$delta = $xr >= $xl ? 1 : -1; $delta = $xr >= $xl ? 1 : -1;
$this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
for($x=$xl, $i=0; $i < $firststep; ++$i) { for($x=$xl, $i=0; $i < $firststep; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
--$i; --$i;
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
for($j=0; $j< $steps; ++$j) { for($j=0; $j< $steps; ++$j) {
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
   
for($j=0; $j < $steps; ++$j, --$i) { for($j=0; $j < $steps; ++$j, --$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
break; break;
   
case GRAD_WIDE_MIDHOR: case GRAD_WIDE_MIDHOR:
$diff = ceil(abs($yb-$yt)); $diff = ceil(abs($yb-$yt));
$steps = floor(abs($diff)/3); $steps = floor(abs($diff)/3);
$firststep = $diff - 2*$steps ; $firststep = $diff - 2*$steps ;
$delta = $yb >= $yt? 1 : -1; $delta = $yb >= $yt? 1 : -1;
$this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
for($y=$yt, $i=0; $i < $firststep; ++$i) { for($y=$yt, $i=0; $i < $firststep; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
$y += $delta; $y += $delta;
} }
--$i; --$i;
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
for($j=0; $j < $steps; ++$j) { for($j=0; $j < $steps; ++$j) {
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
$y += $delta; $y += $delta;
} }
for($j=0; $j < $steps; ++$j, --$i) { for($j=0; $j < $steps; ++$j, --$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($xl,$y,$xr,$y); $this->img->Line($xl,$y,$xr,$y);
$y += $delta; $y += $delta;
} }
break; break;
   
case GRAD_LEFT_REFLECTION: case GRAD_LEFT_REFLECTION:
$steps1 = ceil(0.3*abs($xr-$xl)); $steps1 = ceil(0.3*abs($xr-$xl));
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
   
$from_color = $this->img->rgb->Color($from_color); $from_color = $this->img->rgb->Color($from_color);
$adj = 1.4; $adj = 1.4;
$m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2])))); $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), $from_color2 = array(min(255,$from_color[0]+$m),
min(255,$from_color[1]+$m), min(255,$from_color[2]+$m)); min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));
   
$this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors); $this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
$steps2 = max(1,ceil(0.08*abs($xr-$xl))); $steps2 = max(1,ceil(0.08*abs($xr-$xl)));
$this->img->SetColor($to_color); $this->img->SetColor($to_color);
for($j=0; $j< $steps2; ++$j) { for($j=0; $j< $steps2; ++$j) {
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
$steps = abs($xr-$xl)-$steps1-$steps2; $steps = abs($xr-$xl)-$steps1-$steps2;
$this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors); $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
for($i=0; $i < $steps && $i < $n; ++$i) { for($i=0; $i < $steps && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
break; break;
   
case GRAD_RIGHT_REFLECTION: case GRAD_RIGHT_REFLECTION:
$steps1 = ceil(0.7*abs($xr-$xl)); $steps1 = ceil(0.7*abs($xr-$xl));
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
   
$this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
$steps2 = max(1,ceil(0.08*abs($xr-$xl))); $steps2 = max(1,ceil(0.08*abs($xr-$xl)));
$this->img->SetColor($to_color); $this->img->SetColor($to_color);
for($j=0; $j< $steps2; ++$j) { for($j=0; $j< $steps2; ++$j) {
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
   
$from_color = $this->img->rgb->Color($from_color); $from_color = $this->img->rgb->Color($from_color);
$adj = 1.4; $adj = 1.4;
$m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2])))); $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), $from_color = array(min(255,$from_color[0]+$m),
min(255,$from_color[1]+$m), min(255,$from_color[2]+$m)); min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));
   
$steps = abs($xr-$xl)-$steps1-$steps2; $steps = abs($xr-$xl)-$steps1-$steps2;
$this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors); $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
for($i=0; $i < $steps && $i < $n; ++$i) { for($i=0; $i < $steps && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
break; break;
   
case GRAD_CENTER: case GRAD_CENTER:
$steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2); $steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2);
$this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
$dx = ($xr-$xl)/2; $dx = ($xr-$xl)/2;
$dy = ($yb-$yt)/2; $dy = ($yb-$yt)/2;
$x=$xl;$y=$yt;$x2=$xr;$y2=$yb; $x=$xl;$y=$yt;$x2=$xr;$y2=$yb;
$n = count($colors); $n = count($colors);
for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) { 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->current_color = $colors[$i];
$this->img->Rectangle($x,$y,$x2,$y2); $this->img->Rectangle($x,$y,$x2,$y2);
} }
$this->img->Line($x,$y,$x2,$y2); $this->img->Line($x,$y,$x2,$y2);
break; break;
   
case GRAD_RAISED_PANEL: case GRAD_RAISED_PANEL:
// right to left // right to left
$steps1 = $xr-$xl; $steps1 = $xr-$xl;
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
$this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors); $this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) { for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
   
// left to right // left to right
$xr -= 3; $xr -= 3;
$xl += 3; $xl += 3;
$yb -= 3; $yb -= 3;
$yt += 3; $yt += 3;
$steps2 = $xr-$xl; $steps2 = $xr-$xl;
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
for($x=$xl, $j=$steps2; $j >= 0; --$j) { for($x=$xl, $j=$steps2; $j >= 0; --$j) {
$this->img->current_color = $colors[$j]; $this->img->current_color = $colors[$j];
$this->img->Line($x,$yb,$x,$yt); $this->img->Line($x,$yb,$x,$yt);
$x += $delta; $x += $delta;
} }
break; break;
   
case GRAD_DIAGONAL: case GRAD_DIAGONAL:
// use the longer dimension to determine the required number of steps. // use the longer dimension to determine the required number of steps.
// first loop draws from one corner to the mid-diagonal and the second // first loop draws from one corner to the mid-diagonal and the second
// loop draws from the mid-diagonal to the opposing corner. // loop draws from the mid-diagonal to the opposing corner.
if($xr-$xl > $yb - $yt) { if($xr-$xl > $yb - $yt) {
// width is greater than height -> use x-dimension for steps // width is greater than height -> use x-dimension for steps
$steps = $xr-$xl; $steps = $xr-$xl;
$delta = $xr>=$xl ? 1 : -1; $delta = $xr>=$xl ? 1 : -1;
$this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
   
for($x=$xl, $i=0; $i < $steps && $i < $n; ++$i) { for($x=$xl, $i=0; $i < $steps && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$y = $yt+($i/$steps)*($yb-$yt)*$delta; $y = $yt+($i/$steps)*($yb-$yt)*$delta;
$this->img->Line($x,$yt,$xl,$y); $this->img->Line($x,$yt,$xl,$y);
$x += $delta; $x += $delta;
} }
   
for($x=$xl, $i = 0; $i < $steps && $i < $n; ++$i) { for($x=$xl, $i = 0; $i < $steps && $i < $n; ++$i) {
$this->img->current_color = $colors[$steps+$i]; $this->img->current_color = $colors[$steps+$i];
$y = $yt+($i/$steps)*($yb-$yt)*$delta; $y = $yt+($i/$steps)*($yb-$yt)*$delta;
$this->img->Line($x,$yb,$xr,$y); $this->img->Line($x,$yb,$xr,$y);
$x += $delta; $x += $delta;
} }
} else { } else {
// height is greater than width -> use y-dimension for steps // height is greater than width -> use y-dimension for steps
$steps = $yb-$yt; $steps = $yb-$yt;
$delta = $yb>=$yt ? 1 : -1; $delta = $yb>=$yt ? 1 : -1;
$this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors);
$n = count($colors); $n = count($colors);
   
for($y=$yt, $i=0; $i < $steps && $i < $n; ++$i) { for($y=$yt, $i=0; $i < $steps && $i < $n; ++$i) {
$this->img->current_color = $colors[$i]; $this->img->current_color = $colors[$i];
$x = $xl+($i/$steps)*($xr-$xl)*$delta; $x = $xl+($i/$steps)*($xr-$xl)*$delta;
$this->img->Line($x,$yt,$xl,$y); $this->img->Line($x,$yt,$xl,$y);
$y += $delta; $y += $delta;
} }
   
for($y=$yt, $i = 0; $i < $steps && $i < $n; ++$i) { for($y=$yt, $i = 0; $i < $steps && $i < $n; ++$i) {
$this->img->current_color = $colors[$steps+$i]; $this->img->current_color = $colors[$steps+$i];
$x = $xl+($i/$steps)*($xr-$xl)*$delta; $x = $xl+($i/$steps)*($xr-$xl)*$delta;
$this->img->Line($x,$yb,$xr,$y); $this->img->Line($x,$yb,$xr,$y);
$x += $delta; $x += $delta;
} }
   
} }
break; break;
   
default: default:
JpGraphError::RaiseL(7001,$style); JpGraphError::RaiseL(7001,$style);
//("Unknown gradient style (=$style)."); //("Unknown gradient style (=$style).");
break; break;
} }
} }
   
// Fill a special case of a polygon with a flat bottom // Fill a special case of a polygon with a flat bottom
// with a gradient. Can be used for filled line plots. // with a gradient. Can be used for filled line plots.
// Please note that this is NOT a generic gradient polygon fill // Please note that this is NOT a generic gradient polygon fill
// routine. It assumes that the bottom is flat (like a drawing // routine. It assumes that the bottom is flat (like a drawing
// of a mountain) // of a mountain)
function FilledFlatPolygon($pts,$from_color,$to_color) { function FilledFlatPolygon($pts,$from_color,$to_color) {
if( count($pts) == 0 ) return; if( count($pts) == 0 ) return;
   
$maxy=$pts[1]; $maxy=$pts[1];
$miny=$pts[1]; $miny=$pts[1];
$n = count($pts) ; $n = count($pts) ;
for( $i=0, $idx=0; $i < $n; $i += 2) { for( $i=0, $idx=0; $i < $n; $i += 2) {
$x = round($pts[$i]); $x = round($pts[$i]);
$y = round($pts[$i+1]); $y = round($pts[$i+1]);
$miny = min($miny,$y); $miny = min($miny,$y);
$maxy = max($maxy,$y); $maxy = max($maxy,$y);
} }
   
$colors = array(); $colors = array();
$this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors); $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
for($i=$miny, $idx=0; $i <= $maxy; ++$i ) { for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
$colmap[$i] = $colors[$idx++]; $colmap[$i] = $colors[$idx++];
} }
   
$n = count($pts)/2 ; $n = count($pts)/2 ;
$idx = 0 ; $idx = 0 ;
while( $idx < $n-1 ) { while( $idx < $n-1 ) {
$p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1])); $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
$p2 = 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 // Find the largest rectangle we can fill
$y = max($p1[1],$p2[1]) ; $y = max($p1[1],$p2[1]) ;
for($yy=$maxy; $yy > $y; --$yy) { for($yy=$maxy; $yy > $y; --$yy) {
$this->img->current_color = $colmap[$yy]; $this->img->current_color = $colmap[$yy];
$this->img->Line($p1[0],$yy,$p2[0]-1,$yy); $this->img->Line($p1[0],$yy,$p2[0]-1,$yy);
} }
   
if( $p1[1] == $p2[1] ) { if( $p1[1] == $p2[1] ) {
continue; continue;
} }
   
// Fill the rest using lines (slow...) // Fill the rest using lines (slow...)
$slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]); $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
$x1 = $p1[0]; $x1 = $p1[0];
$x2 = $p2[0]-1; $x2 = $p2[0]-1;
$start = $y; $start = $y;
if( $p1[1] > $p2[1] ) { if( $p1[1] > $p2[1] ) {
while( $y >= $p2[1] ) { while( $y >= $p2[1] ) {
$x1=$slope*($start-$y)+$p1[0]; $x1=$slope*($start-$y)+$p1[0];
$this->img->current_color = $colmap[$y]; $this->img->current_color = $colmap[$y];
$this->img->Line($x1,$y,$x2,$y); $this->img->Line($x1,$y,$x2,$y);
--$y; --$y;
} }
} }
else { else {
while( $y >= $p1[1] ) { while( $y >= $p1[1] ) {
$x2=$p2[0]+$slope*($start-$y); $x2=$p2[0]+$slope*($start-$y);
$this->img->current_color = $colmap[$y]; $this->img->current_color = $colmap[$y];
$this->img->Line($x1,$y,$x2,$y); $this->img->Line($x1,$y,$x2,$y);
--$y; --$y;
} }
} }
} }
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
// Add to the image color map the necessary colors to do the transition // Add to the image color map the necessary colors to do the transition
// between the two colors using $numcolors intermediate colors // between the two colors using $numcolors intermediate colors
function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) { function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) {
if( $arr_size==0 ) { if( $arr_size==0 ) {
return; return;
} }
   
// If color is given as text get it's corresponding r,g,b values // If color is given as text get it's corresponding r,g,b values
$from_color = $this->img->rgb->Color($from_color); $from_color = $this->img->rgb->Color($from_color);
$to_color = $this->img->rgb->Color($to_color); $to_color = $this->img->rgb->Color($to_color);
   
$rdelta=($to_color[0]-$from_color[0])/$numcols; $rdelta=($to_color[0]-$from_color[0])/$numcols;
$gdelta=($to_color[1]-$from_color[1])/$numcols; $gdelta=($to_color[1]-$from_color[1])/$numcols;
$bdelta=($to_color[2]-$from_color[2])/$numcols; $bdelta=($to_color[2]-$from_color[2])/$numcols;
$colorsperstep = $numcols/$arr_size; $colorsperstep = $numcols/$arr_size;
$prevcolnum = -1; $prevcolnum = -1;
$from_alpha = $from_color[3]; $from_alpha = $from_color[3];
$to_alpha = $to_color[3]; $to_alpha = $to_color[3];
$adelta = ( $to_alpha - $from_alpha ) / $numcols ; $adelta = ( $to_alpha - $from_alpha ) / $numcols ;
for ($i=0; $i < $arr_size; ++$i) { for ($i=0; $i < $arr_size; ++$i) {
$colnum = floor($colorsperstep*$i); $colnum = floor($colorsperstep*$i);
if ( $colnum == $prevcolnum ) { if ( $colnum == $prevcolnum ) {
$colors[$i] = $colidx; $colors[$i] = $colidx;
} }
else { else {
$r = floor($from_color[0] + $colnum*$rdelta); $r = floor($from_color[0] + $colnum*$rdelta);
$g = floor($from_color[1] + $colnum*$gdelta); $g = floor($from_color[1] + $colnum*$gdelta);
$b = floor($from_color[2] + $colnum*$bdelta); $b = floor($from_color[2] + $colnum*$bdelta);
$alpha = $from_alpha + $colnum*$adelta; $alpha = $from_alpha + $colnum*$adelta;
$colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha); $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha);
$colors[$i] = $colidx; $colors[$i] = $colidx;
} }
$prevcolnum = $colnum; $prevcolnum = $colnum;
} }
} }
} // Class } // Class
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_ICONPLOT.PHP // File: JPGRAPH_ICONPLOT.PHP
// Description: Extension module to add icons to plots // Description: Extension module to add icons to plots
// Created: 2004-02-18 // Created: 2004-02-18
// Ver: $Id: jpgraph_iconplot.php 1404 2009-06-28 15:25:41Z ljp $ // Ver: $Id: jpgraph_iconplot.php 1404 2009-06-28 15:25:41Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
//=================================================== //===================================================
// CLASS IconPlot // CLASS IconPlot
// Description: Make it possible to add a (small) image // Description: Make it possible to add a (small) image
// to the graph // to the graph
//=================================================== //===================================================
class IconPlot { class IconPlot {
public $iX=0,$iY=0,$iScale=1.0,$iMix=100; public $iX=0,$iY=0,$iScale=1.0,$iMix=100;
private $iHorAnchor='left',$iVertAnchor='top'; private $iHorAnchor='left',$iVertAnchor='top';
private $iFile=''; private $iFile='';
private $iAnchors = array('left','right','top','bottom','center'); private $iAnchors = array('left','right','top','bottom','center');
private $iCountryFlag='',$iCountryStdSize=3; private $iCountryFlag='',$iCountryStdSize=3;
private $iScalePosY=null,$iScalePosX=null; private $iScalePosY=null,$iScalePosX=null;
private $iImgString=''; private $iImgString='';
   
   
function __construct($aFile="",$aX=0,$aY=0,$aScale=1.0,$aMix=100) { function __construct($aFile="",$aX=0,$aY=0,$aScale=1.0,$aMix=100) {
$this->iFile = $aFile; $this->iFile = $aFile;
$this->iX=$aX; $this->iX=$aX;
$this->iY=$aY; $this->iY=$aY;
$this->iScale= $aScale; $this->iScale= $aScale;
if( $aMix < 0 || $aMix > 100 ) { if( $aMix < 0 || $aMix > 100 ) {
JpGraphError::RaiseL(8001); //('Mix value for icon must be between 0 and 100.'); JpGraphError::RaiseL(8001); //('Mix value for icon must be between 0 and 100.');
} }
$this->iMix = $aMix ; $this->iMix = $aMix ;
} }
   
function SetCountryFlag($aFlag,$aX=0,$aY=0,$aScale=1.0,$aMix=100,$aStdSize=3) { function SetCountryFlag($aFlag,$aX=0,$aY=0,$aScale=1.0,$aMix=100,$aStdSize=3) {
$this->iCountryFlag = $aFlag; $this->iCountryFlag = $aFlag;
$this->iX=$aX; $this->iX=$aX;
$this->iY=$aY; $this->iY=$aY;
$this->iScale= $aScale; $this->iScale= $aScale;
if( $aMix < 0 || $aMix > 100 ) { if( $aMix < 0 || $aMix > 100 ) {
JpGraphError::RaiseL(8001);//'Mix value for icon must be between 0 and 100.'); JpGraphError::RaiseL(8001);//'Mix value for icon must be between 0 and 100.');
} }
$this->iMix = $aMix; $this->iMix = $aMix;
$this->iCountryStdSize = $aStdSize; $this->iCountryStdSize = $aStdSize;
} }
   
function SetPos($aX,$aY) { function SetPos($aX,$aY) {
$this->iX=$aX; $this->iX=$aX;
$this->iY=$aY; $this->iY=$aY;
} }
   
function CreateFromString($aStr) { function CreateFromString($aStr) {
$this->iImgString = $aStr; $this->iImgString = $aStr;
} }
   
function SetScalePos($aX,$aY) { function SetScalePos($aX,$aY) {
$this->iScalePosX = $aX; $this->iScalePosX = $aX;
$this->iScalePosY = $aY; $this->iScalePosY = $aY;
} }
   
function SetScale($aScale) { function SetScale($aScale) {
$this->iScale = $aScale; $this->iScale = $aScale;
} }
   
function SetMix($aMix) { function SetMix($aMix) {
if( $aMix < 0 || $aMix > 100 ) { if( $aMix < 0 || $aMix > 100 ) {
JpGraphError::RaiseL(8001);//('Mix value for icon must be between 0 and 100.'); JpGraphError::RaiseL(8001);//('Mix value for icon must be between 0 and 100.');
} }
$this->iMix = $aMix ; $this->iMix = $aMix ;
} }
   
function SetAnchor($aXAnchor='left',$aYAnchor='center') { function SetAnchor($aXAnchor='left',$aYAnchor='center') {
if( !in_array($aXAnchor,$this->iAnchors) || if( !in_array($aXAnchor,$this->iAnchors) ||
!in_array($aYAnchor,$this->iAnchors) ) { !in_array($aYAnchor,$this->iAnchors) ) {
JpGraphError::RaiseL(8002);//("Anchor position for icons must be one of 'top', 'bottom', 'left', 'right' or 'center'"); JpGraphError::RaiseL(8002);//("Anchor position for icons must be one of 'top', 'bottom', 'left', 'right' or 'center'");
} }
$this->iHorAnchor=$aXAnchor; $this->iHorAnchor=$aXAnchor;
$this->iVertAnchor=$aYAnchor; $this->iVertAnchor=$aYAnchor;
} }
   
function PreStrokeAdjust($aGraph) { function PreStrokeAdjust($aGraph) {
// Nothing to do ... // Nothing to do ...
} }
   
function DoLegend($aGraph) { function DoLegend($aGraph) {
// Nothing to do ... // Nothing to do ...
} }
   
function Max() { function Max() {
return array(false,false); return array(false,false);
} }
   
   
// The next four function are framework function tht gets called // The next four function are framework function tht gets called
// from Gantt and is not menaiungfull in the context of Icons but // from Gantt and is not menaiungfull in the context of Icons but
// they must be implemented to avoid errors. // they must be implemented to avoid errors.
function GetMaxDate() { return false; } function GetMaxDate() { return false; }
function GetMinDate() { return false; } function GetMinDate() { return false; }
function GetLineNbr() { return 0; } function GetLineNbr() { return 0; }
function GetAbsHeight() {return 0; } function GetAbsHeight() {return 0; }
   
   
function Min() { function Min() {
return array(false,false); return array(false,false);
} }
   
function StrokeMargin(&$aImg) { function StrokeMargin(&$aImg) {
return true; return true;
} }
   
function Stroke($aImg,$axscale=null,$ayscale=null) { function Stroke($aImg,$axscale=null,$ayscale=null) {
$this->StrokeWithScale($aImg,$axscale,$ayscale); $this->StrokeWithScale($aImg,$axscale,$ayscale);
} }
   
function StrokeWithScale($aImg,$axscale,$ayscale) { function StrokeWithScale($aImg,$axscale,$ayscale) {
if( $this->iScalePosX === null || $this->iScalePosY === null || if( $this->iScalePosX === null || $this->iScalePosY === null ||
$axscale === null || $ayscale === null ) { $axscale === null || $ayscale === null ) {
$this->_Stroke($aImg); $this->_Stroke($aImg);
} }
else { else {
$this->_Stroke($aImg, $this->_Stroke($aImg,
round($axscale->Translate($this->iScalePosX)), round($axscale->Translate($this->iScalePosX)),
round($ayscale->Translate($this->iScalePosY))); round($ayscale->Translate($this->iScalePosY)));
} }
} }
   
function GetWidthHeight() { function GetWidthHeight() {
$dummy=0; $dummy=0;
return $this->_Stroke($dummy,null,null,true); return $this->_Stroke($dummy,null,null,true);
} }
   
function _Stroke($aImg,$x=null,$y=null,$aReturnWidthHeight=false) { function _Stroke($aImg,$x=null,$y=null,$aReturnWidthHeight=false) {
if( $this->iFile != '' && $this->iCountryFlag != '' ) { 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.'); JpGraphError::RaiseL(8003);//('It is not possible to specify both an image file and a country flag for the same icon.');
} }
if( $this->iFile != '' ) { if( $this->iFile != '' ) {
$gdimg = Graph::LoadBkgImage('',$this->iFile); $gdimg = Graph::LoadBkgImage('',$this->iFile);
} }
elseif( $this->iImgString != '') { elseif( $this->iImgString != '') {
$gdimg = Image::CreateFromString($this->iImgString); $gdimg = Image::CreateFromString($this->iImgString);
} }
   
else { else {
if( ! class_exists('FlagImages',false) ) { if( ! class_exists('FlagImages',false) ) {
JpGraphError::RaiseL(8004);//('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.'); JpGraphError::RaiseL(8004);//('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.');
} }
$fobj = new FlagImages($this->iCountryStdSize); $fobj = new FlagImages($this->iCountryStdSize);
$dummy=''; $dummy='';
$gdimg = $fobj->GetImgByName($this->iCountryFlag,$dummy); $gdimg = $fobj->GetImgByName($this->iCountryFlag,$dummy);
} }
   
$iconw = imagesx($gdimg); $iconw = imagesx($gdimg);
$iconh = imagesy($gdimg); $iconh = imagesy($gdimg);
   
if( $aReturnWidthHeight ) { if( $aReturnWidthHeight ) {
return array(round($iconw*$this->iScale),round($iconh*$this->iScale)); return array(round($iconw*$this->iScale),round($iconh*$this->iScale));
} }
   
if( $x !== null && $y !== null ) { if( $x !== null && $y !== null ) {
$this->iX = $x; $this->iY = $y; $this->iX = $x; $this->iY = $y;
} }
if( $this->iX >= 0 && $this->iX <= 1.0 ) { if( $this->iX >= 0 && $this->iX <= 1.0 ) {
$w = imagesx($aImg->img); $w = imagesx($aImg->img);
$this->iX = round($w*$this->iX); $this->iX = round($w*$this->iX);
} }
if( $this->iY >= 0 && $this->iY <= 1.0 ) { if( $this->iY >= 0 && $this->iY <= 1.0 ) {
$h = imagesy($aImg->img); $h = imagesy($aImg->img);
$this->iY = round($h*$this->iY); $this->iY = round($h*$this->iY);
} }
   
if( $this->iHorAnchor == 'center' ) if( $this->iHorAnchor == 'center' )
$this->iX -= round($iconw*$this->iScale/2); $this->iX -= round($iconw*$this->iScale/2);
if( $this->iHorAnchor == 'right' ) if( $this->iHorAnchor == 'right' )
$this->iX -= round($iconw*$this->iScale); $this->iX -= round($iconw*$this->iScale);
if( $this->iVertAnchor == 'center' ) if( $this->iVertAnchor == 'center' )
$this->iY -= round($iconh*$this->iScale/2); $this->iY -= round($iconh*$this->iScale/2);
if( $this->iVertAnchor == 'bottom' ) if( $this->iVertAnchor == 'bottom' )
$this->iY -= round($iconh*$this->iScale); $this->iY -= round($iconh*$this->iScale);
   
$aImg->CopyMerge($gdimg,$this->iX,$this->iY,0,0, $aImg->CopyMerge($gdimg,$this->iX,$this->iY,0,0,
round($iconw*$this->iScale),round($iconh*$this->iScale), round($iconw*$this->iScale),round($iconh*$this->iScale),
$iconw,$iconh, $iconw,$iconh,
$this->iMix); $this->iMix);
} }
} }
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_IMGTRANS.PHP // File: JPGRAPH_IMGTRANS.PHP
// Description: Extension for JpGraph to do some simple img transformations // Description: Extension for JpGraph to do some simple img transformations
// Created: 2003-09-06 // Created: 2003-09-06
// Ver: $Id: jpgraph_imgtrans.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_imgtrans.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Class ImgTrans // Class ImgTrans
// Perform some simple image transformations. // Perform some simple image transformations.
//------------------------------------------------------------------------ //------------------------------------------------------------------------
class ImgTrans { class ImgTrans {
private $gdImg=null; private $gdImg=null;
   
function __construct($aGdImg) { function __construct($aGdImg) {
// Constructor // Constructor
$this->gdImg = $aGdImg; $this->gdImg = $aGdImg;
} }
   
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// _TransVert3D() and _TransHor3D() are helper methods to // _TransVert3D() and _TransHor3D() are helper methods to
// Skew3D(). // Skew3D().
// -------------------------------------------------------------------- // --------------------------------------------------------------------
function _TransVert3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_DOWN,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) { function _TransVert3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_DOWN,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) {
   
   
// Parameter check // Parameter check
if( $aHorizonPos < 0 || $aHorizonPos > 1.0 ) { if( $aHorizonPos < 0 || $aHorizonPos > 1.0 ) {
JpGraphError::RaiseL(9001); JpGraphError::RaiseL(9001);
//("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1."); //("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1.");
} }
   
$w = imagesx($aGdImg); $w = imagesx($aGdImg);
$h = imagesy($aGdImg); $h = imagesy($aGdImg);
   
// Create new image // Create new image
$ww = $w; $ww = $w;
if( $aMinSize ) if( $aMinSize )
$hh = ceil($h * $aHorizon / ($aSkewDist+$h)); $hh = ceil($h * $aHorizon / ($aSkewDist+$h));
else else
$hh = $h; $hh = $h;
   
$newgdh = imagecreatetruecolor($ww,$hh); $newgdh = imagecreatetruecolor($ww,$hh);
$crgb = new RGB( $newgdh ); $crgb = new RGB( $newgdh );
$fillColor = $crgb->Allocate($aFillColor); $fillColor = $crgb->Allocate($aFillColor);
imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor); imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor);
   
if( $aBorder ) { if( $aBorder ) {
$colidx = $crgb->Allocate($aBorder); $colidx = $crgb->Allocate($aBorder);
imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx); imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx);
} }
   
$mid = round($w * $aHorizonPos); $mid = round($w * $aHorizonPos);
   
$last=$h; $last=$h;
for($y=0; $y < $h; ++$y) { for($y=0; $y < $h; ++$y) {
   
$yp = $h-$y-1; $yp = $h-$y-1;
$yt = floor($yp * $aHorizon / ($aSkewDist + $yp)); $yt = floor($yp * $aHorizon / ($aSkewDist + $yp));
   
if( !$aQuality ) { if( !$aQuality ) {
if( $last <= $yt ) continue ; if( $last <= $yt ) continue ;
$last = $yt; $last = $yt;
} }
   
for($x=0; $x < $w; ++$x) { for($x=0; $x < $w; ++$x) {
$xt = ($x-$mid) * $aSkewDist / ($aSkewDist + $yp); $xt = ($x-$mid) * $aSkewDist / ($aSkewDist + $yp);
if( $aDir == SKEW3D_UP ) if( $aDir == SKEW3D_UP )
$rgb = imagecolorat($aGdImg,$x,$h-$y-1); $rgb = imagecolorat($aGdImg,$x,$h-$y-1);
else else
$rgb = imagecolorat($aGdImg,$x,$y); $rgb = imagecolorat($aGdImg,$x,$y);
$r = ($rgb >> 16) & 0xFF; $r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF; $g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF; $b = $rgb & 0xFF;
$colidx = imagecolorallocate($newgdh,$r,$g,$b); $colidx = imagecolorallocate($newgdh,$r,$g,$b);
$xt = round($xt+$mid); $xt = round($xt+$mid);
if( $aDir == SKEW3D_UP ) { if( $aDir == SKEW3D_UP ) {
$syt = $yt; $syt = $yt;
} }
else { else {
$syt = $hh-$yt-1; $syt = $hh-$yt-1;
} }
   
if( !empty($set[$yt]) ) { if( !empty($set[$yt]) ) {
$nrgb = imagecolorat($newgdh,$xt,$syt); $nrgb = imagecolorat($newgdh,$xt,$syt);
$nr = ($nrgb >> 16) & 0xFF; $nr = ($nrgb >> 16) & 0xFF;
$ng = ($nrgb >> 8) & 0xFF; $ng = ($nrgb >> 8) & 0xFF;
$nb = $nrgb & 0xFF; $nb = $nrgb & 0xFF;
$colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2), $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2),
floor(($g+$ng)/2),floor(($b+$nb)/2)); floor(($g+$ng)/2),floor(($b+$nb)/2));
} }
   
imagesetpixel($newgdh,$xt,$syt,$colidx); imagesetpixel($newgdh,$xt,$syt,$colidx);
} }
   
$set[$yt] = true; $set[$yt] = true;
} }
   
return $newgdh; return $newgdh;
} }
   
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// _TransVert3D() and _TransHor3D() are helper methods to // _TransVert3D() and _TransHor3D() are helper methods to
// Skew3D(). // Skew3D().
// -------------------------------------------------------------------- // --------------------------------------------------------------------
function _TransHor3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_LEFT,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) { function _TransHor3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_LEFT,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) {
   
$w = imagesx($aGdImg); $w = imagesx($aGdImg);
$h = imagesy($aGdImg); $h = imagesy($aGdImg);
   
// Create new image // Create new image
$hh = $h; $hh = $h;
if( $aMinSize ) if( $aMinSize )
$ww = ceil($w * $aHorizon / ($aSkewDist+$w)); $ww = ceil($w * $aHorizon / ($aSkewDist+$w));
else else
$ww = $w; $ww = $w;
   
$newgdh = imagecreatetruecolor($ww,$hh); $newgdh = imagecreatetruecolor($ww,$hh);
$crgb = new RGB( $newgdh ); $crgb = new RGB( $newgdh );
$fillColor = $crgb->Allocate($aFillColor); $fillColor = $crgb->Allocate($aFillColor);
imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor); imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor);
   
if( $aBorder ) { if( $aBorder ) {
$colidx = $crgb->Allocate($aBorder); $colidx = $crgb->Allocate($aBorder);
imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx); imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx);
} }
   
$mid = round($h * $aHorizonPos); $mid = round($h * $aHorizonPos);
   
$last = -1; $last = -1;
for($x=0; $x < $w-1; ++$x) { for($x=0; $x < $w-1; ++$x) {
$xt = floor($x * $aHorizon / ($aSkewDist + $x)); $xt = floor($x * $aHorizon / ($aSkewDist + $x));
if( !$aQuality ) { if( !$aQuality ) {
if( $last >= $xt ) continue ; if( $last >= $xt ) continue ;
$last = $xt; $last = $xt;
} }
   
for($y=0; $y < $h; ++$y) { for($y=0; $y < $h; ++$y) {
$yp = $h-$y-1; $yp = $h-$y-1;
$yt = ($yp-$mid) * $aSkewDist / ($aSkewDist + $x); $yt = ($yp-$mid) * $aSkewDist / ($aSkewDist + $x);
   
if( $aDir == SKEW3D_RIGHT ) if( $aDir == SKEW3D_RIGHT )
$rgb = imagecolorat($aGdImg,$w-$x-1,$y); $rgb = imagecolorat($aGdImg,$w-$x-1,$y);
else else
$rgb = imagecolorat($aGdImg,$x,$y); $rgb = imagecolorat($aGdImg,$x,$y);
$r = ($rgb >> 16) & 0xFF; $r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF; $g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF; $b = $rgb & 0xFF;
$colidx = imagecolorallocate($newgdh,$r,$g,$b); $colidx = imagecolorallocate($newgdh,$r,$g,$b);
$yt = floor($hh-$yt-$mid-1); $yt = floor($hh-$yt-$mid-1);
if( $aDir == SKEW3D_RIGHT ) { if( $aDir == SKEW3D_RIGHT ) {
$sxt = $ww-$xt-1; $sxt = $ww-$xt-1;
} }
else else
$sxt = $xt ; $sxt = $xt ;
   
if( !empty($set[$xt]) ) { if( !empty($set[$xt]) ) {
$nrgb = imagecolorat($newgdh,$sxt,$yt); $nrgb = imagecolorat($newgdh,$sxt,$yt);
$nr = ($nrgb >> 16) & 0xFF; $nr = ($nrgb >> 16) & 0xFF;
$ng = ($nrgb >> 8) & 0xFF; $ng = ($nrgb >> 8) & 0xFF;
$nb = $nrgb & 0xFF; $nb = $nrgb & 0xFF;
$colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2), $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2),
floor(($g+$ng)/2),floor(($b+$nb)/2)); floor(($g+$ng)/2),floor(($b+$nb)/2));
} }
imagesetpixel($newgdh,$sxt,$yt,$colidx); imagesetpixel($newgdh,$sxt,$yt,$colidx);
} }
   
$set[$xt] = true; $set[$xt] = true;
} }
   
return $newgdh; return $newgdh;
} }
   
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Skew image for the apperance of a 3D effect // Skew image for the apperance of a 3D effect
// This transforms an image into a 3D-skewed version // This transforms an image into a 3D-skewed version
// of the image. The transformation is specified by giving the height // of the image. The transformation is specified by giving the height
// of the artificial horizon and specifying a "skew" factor which // of the artificial horizon and specifying a "skew" factor which
// is the distance on the horizon line between the point of // is the distance on the horizon line between the point of
// convergence and perspective line. // convergence and perspective line.
// //
// The function returns the GD handle of the transformed image // The function returns the GD handle of the transformed image
// leaving the original image untouched. // leaving the original image untouched.
// //
// Parameters: // Parameters:
// * $aGdImg, GD handle to the image to be transformed // * $aGdImg, GD handle to the image to be transformed
// * $aHorizon, Distance to the horizon // * $aHorizon, Distance to the horizon
// * $aSkewDist, Distance from the horizon point of convergence // * $aSkewDist, Distance from the horizon point of convergence
// on the horizon line to the perspective points. A larger // on the horizon line to the perspective points. A larger
// value will fore-shorten the image more // value will fore-shorten the image more
// * $aDir, parameter specifies type of convergence. This of this // * $aDir, parameter specifies type of convergence. This of this
// as the walls in a room you are looking at. This specifies if the // 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. // image should be applied on the left,right,top or bottom walls.
// * $aMinSize, true=make the new image just as big as needed, // * $aMinSize, true=make the new image just as big as needed,
// false = keep the image the same size as the original image // false = keep the image the same size as the original image
// * $aFillColor, Background fill color in the image // * $aFillColor, Background fill color in the image
// * $aHiQuality, true=performa some interpolation that improves // * $aHiQuality, true=performa some interpolation that improves
// the image quality but at the expense of performace. Enabling // the image quality but at the expense of performace. Enabling
// high quality will have a dramatic effect on the time it takes // high quality will have a dramatic effect on the time it takes
// to transform an image. // to transform an image.
// * $aBorder, if set to anything besides false this will draw a // * $aBorder, if set to anything besides false this will draw a
// a border of the speciied color around the image // 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) { 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, return $this->_Skew3D($this->gdImg,$aHorizon,$aSkewDist,$aDir,$aHiQuality,
$aMinSize,$aFillColor,$aBorder); $aMinSize,$aFillColor,$aBorder);
} }
   
function _Skew3D($aGdImg,$aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) { 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 ) if( $aDir == SKEW3D_DOWN || $aDir == SKEW3D_UP )
return $this->_TransVert3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder); return $this->_TransVert3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder);
else else
return $this->_TransHor3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder); return $this->_TransHor3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder);
   
} }
   
} }
   
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_LED.PHP // File: JPGRAPH_LED.PHP
// Description: Module to generate Dotted LED-like digits // Description: Module to generate Dotted LED-like digits
// Created: 2006-11-26 // Created: 2006-11-26
// Ver: $Id: jpgraph_led.php 1674 2009-07-22 19:42:23Z ljp $ // Ver: $Id: jpgraph_led.php 1674 2009-07-22 19:42:23Z ljp $
// //
// Copyright 2006 (c) Aditus Consulting. All rights reserved. // Copyright 2006 (c) Aditus Consulting. All rights reserved.
// //
// Changed: 2007-08-06 by Alexander Kurochkin (inspector@list.ru) // Changed: 2007-08-06 by Alexander Kurochkin (inspector@list.ru)
//======================================================================== //========================================================================
   
// Constants for color schema // Constants for color schema
DEFINE('LEDC_RED', 0); DEFINE('LEDC_RED', 0);
DEFINE('LEDC_GREEN', 1); DEFINE('LEDC_GREEN', 1);
DEFINE('LEDC_BLUE', 2); DEFINE('LEDC_BLUE', 2);
DEFINE('LEDC_YELLOW', 3); DEFINE('LEDC_YELLOW', 3);
DEFINE('LEDC_GRAY', 4); DEFINE('LEDC_GRAY', 4);
DEFINE('LEDC_CHOCOLATE', 5); DEFINE('LEDC_CHOCOLATE', 5);
DEFINE('LEDC_PERU', 6); DEFINE('LEDC_PERU', 6);
DEFINE('LEDC_GOLDENROD', 7); DEFINE('LEDC_GOLDENROD', 7);
DEFINE('LEDC_KHAKI', 8); DEFINE('LEDC_KHAKI', 8);
DEFINE('LEDC_OLIVE', 9); DEFINE('LEDC_OLIVE', 9);
DEFINE('LEDC_LIMEGREEN', 10); DEFINE('LEDC_LIMEGREEN', 10);
DEFINE('LEDC_FORESTGREEN', 11); DEFINE('LEDC_FORESTGREEN', 11);
DEFINE('LEDC_TEAL', 12); DEFINE('LEDC_TEAL', 12);
DEFINE('LEDC_STEELBLUE', 13); DEFINE('LEDC_STEELBLUE', 13);
DEFINE('LEDC_NAVY', 14); DEFINE('LEDC_NAVY', 14);
DEFINE('LEDC_INVERTGRAY', 15); DEFINE('LEDC_INVERTGRAY', 15);
   
// Check that mb_strlen() is available // Check that mb_strlen() is available
if( ! function_exists('mb_strlen') ) { if( ! function_exists('mb_strlen') ) {
JpGraphError::RaiseL(25500); JpGraphError::RaiseL(25500);
//'Multibyte strings must be enabled in the PHP installation in order to run the LED module //'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.' // so that the function mb_strlen() is available. See PHP documentation for more information.'
} }
   
//======================================================================== //========================================================================
// CLASS DigitalLED74 // CLASS DigitalLED74
// Description: // Description:
// Construct a number as an image that looks like LED numbers in a // Construct a number as an image that looks like LED numbers in a
// 7x4 digital matrix // 7x4 digital matrix
//======================================================================== //========================================================================
class DigitalLED74 class DigitalLED74
{ {
private $iLED_X = 4, $iLED_Y=7, private $iLED_X = 4, $iLED_Y=7,
   
// fg-up, fg-down, bg // fg-up, fg-down, bg
$iColorSchema = array( $iColorSchema = array(
LEDC_RED => array('red','darkred:0.9','red:0.3'),// 0 LEDC_RED => array('red','darkred:0.9','red:0.3'),// 0
LEDC_GREEN => array('green','darkgreen','green:0.3'),// 1 LEDC_GREEN => array('green','darkgreen','green:0.3'),// 1
LEDC_BLUE => array('lightblue:0.9','darkblue:0.85','darkblue:0.7'),// 2 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_YELLOW => array('yellow','yellow:0.4','yellow:0.3'),// 3
LEDC_GRAY => array('gray:1.4','darkgray:0.85','darkgray:0.7'), LEDC_GRAY => array('gray:1.4','darkgray:0.85','darkgray:0.7'),
LEDC_CHOCOLATE => array('chocolate','chocolate:0.7','chocolate:0.5'), LEDC_CHOCOLATE => array('chocolate','chocolate:0.7','chocolate:0.5'),
LEDC_PERU => array('peru:0.95','peru:0.6','peru: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_GOLDENROD => array('goldenrod','goldenrod:0.6','goldenrod:0.5'),
LEDC_KHAKI => array('khaki:0.7','khaki:0.4','khaki:0.3'), LEDC_KHAKI => array('khaki:0.7','khaki:0.4','khaki:0.3'),
LEDC_OLIVE => array('#808000','#808000:0.7','#808000:0.6'), LEDC_OLIVE => array('#808000','#808000:0.7','#808000:0.6'),
LEDC_LIMEGREEN => array('limegreen:0.9','limegreen:0.5','limegreen:0.4'), LEDC_LIMEGREEN => array('limegreen:0.9','limegreen:0.5','limegreen:0.4'),
LEDC_FORESTGREEN => array('forestgreen','forestgreen:0.7','forestgreen:0.5'), LEDC_FORESTGREEN => array('forestgreen','forestgreen:0.7','forestgreen:0.5'),
LEDC_TEAL => array('teal','teal:0.7','teal:0.5'), LEDC_TEAL => array('teal','teal:0.7','teal:0.5'),
LEDC_STEELBLUE => array('steelblue','steelblue:0.65','steelblue: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_NAVY => array('navy:1.3','navy:0.95','navy:0.8'),//14
LEDC_INVERTGRAY => array('darkgray','lightgray:1.5','white')//15 LEDC_INVERTGRAY => array('darkgray','lightgray:1.5','white')//15
), ),
   
/* Each line of the character is encoded as a 4 bit value /* Each line of the character is encoded as a 4 bit value
0 ____ 0 ____
1 ___x 1 ___x
2 __x_ 2 __x_
3 __xx 3 __xx
4 _x__ 4 _x__
5 _x_x 5 _x_x
6 _xx_ 6 _xx_
7 _xxx 7 _xxx
8 x___ 8 x___
9 x__x 9 x__x
10 x_x_ 10 x_x_
11 x_xx 11 x_xx
12 xx__ 12 xx__
13 xx_x 13 xx_x
14 xxx_ 14 xxx_
15 xxxx 15 xxxx
*/ */
   
$iLEDSpec = array( $iLEDSpec = array(
0 => array(6,9,11,15,13,9,6), 0 => array(6,9,11,15,13,9,6),
1 => array(2,6,10,2,2,2,2), 1 => array(2,6,10,2,2,2,2),
2 => array(6,9,1,2,4,8,15), 2 => array(6,9,1,2,4,8,15),
3 => array(6,9,1,6,1,9,6), 3 => array(6,9,1,6,1,9,6),
4 => array(1,3,5,9,15,1,1), 4 => array(1,3,5,9,15,1,1),
5 => array(15,8,8,14,1,9,6), 5 => array(15,8,8,14,1,9,6),
6 => array(6,8,8,14,9,9,6), 6 => array(6,8,8,14,9,9,6),
7 => array(15,1,1,2,4,4,4), 7 => array(15,1,1,2,4,4,4),
8 => array(6,9,9,6,9,9,6), 8 => array(6,9,9,6,9,9,6),
9 => array(6,9,9,7,1,1,6), 9 => array(6,9,9,7,1,1,6),
'!' => array(4,4,4,4,4,0,4), '!' => array(4,4,4,4,4,0,4),
'?' => array(6,9,1,2,2,0,2), '?' => array(6,9,1,2,2,0,2),
'#' => array(0,9,15,9,15,9,0), '#' => array(0,9,15,9,15,9,0),
'@' => array(6,9,11,11,10,9,6), '@' => array(6,9,11,11,10,9,6),
'-' => array(0,0,0,15,0,0,0), '-' => array(0,0,0,15,0,0,0),
'_' => array(0,0,0,0,0,0,15), '_' => array(0,0,0,0,0,0,15),
'=' => array(0,0,15,0,15,0,0), '=' => array(0,0,15,0,15,0,0),
'+' => array(0,0,4,14,4,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(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,4),
'.' => array(0,0,0,0,0,12,12), '.' => array(0,0,0,0,0,12,12),
':' => array(12,12,0,0,0,12,12), ':' => array(12,12,0,0,0,12,12),
';' => array(12,12,0,0,0,12,4), ';' => array(12,12,0,0,0,12,4),
'[' => array(3,2,2,2,2,2,3), '[' => array(3,2,2,2,2,2,3),
']' => array(12,4,4,4,4,4,12), ']' => array(12,4,4,4,4,4,12),
'(' => array(1,2,2,2,2,2,1), '(' => array(1,2,2,2,2,2,1),
')' => array(8,4,4,4,4,4,8), ')' => array(8,4,4,4,4,4,8),
'{' => array(3,2,2,6,2,2,3), '{' => array(3,2,2,6,2,2,3),
'}' => array(12,4,4,6,4,4,12), '}' => array(12,4,4,6,4,4,12),
'<' => array(1,2,4,8,4,2,1), '<' => array(1,2,4,8,4,2,1),
'>' => array(8,4,2,1,2,4,8), '>' => array(8,4,2,1,2,4,8),
'*' => array(9,6,15,6,9,0,0), '*' => array(9,6,15,6,9,0,0),
'"' => array(10,10,0,0,0,0,0), '"' => array(10,10,0,0,0,0,0),
'\'' => array(4,4,0,0,0,0,0), '\'' => array(4,4,0,0,0,0,0),
'`' => array(4,2,0,0,0,0,0), '`' => array(4,2,0,0,0,0,0),
'~' => array(13,11,0,0,0,0,0), '~' => array(13,11,0,0,0,0,0),
'^' => array(4,10,0,0,0,0,0), '^' => array(4,10,0,0,0,0,0),
'\\' => array(8,8,4,6,2,1,1), '\\' => array(8,8,4,6,2,1,1),
'/' => array(1,1,2,6,4,8,8), '/' => array(1,1,2,6,4,8,8),
'%' => array(1,9,2,6,4,9,8), '%' => array(1,9,2,6,4,9,8),
'&' => array(0,4,10,4,11,10,5), '&' => array(0,4,10,4,11,10,5),
'$' => array(2,7,8,6,1,14,4), '$' => array(2,7,8,6,1,14,4),
' ' => array(0,0,0,0,0,0,0), ' ' => array(0,0,0,0,0,0,0),
'•' => array(0,0,6,6,0,0,0), //149 '•' => array(0,0,6,6,0,0,0), //149
'°' => array(14,10,14,0,0,0,0), //176 '°' => array(14,10,14,0,0,0,0), //176
'†' => array(4,4,14,4,4,4,4), //134 '†' => array(4,4,14,4,4,4,4), //134
'‡' => array(4,4,14,4,14,4,4), //135 '‡' => array(4,4,14,4,14,4,4), //135
'±' => array(0,4,14,4,0,14,0), //177 '±' => array(0,4,14,4,0,14,0), //177
'‰' => array(0,4,2,15,2,4,0), //137 show right arrow '‰' => 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,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 'Ф' 'Ў' => 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 'У' "\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 'М','Ш' ,'Щ' "\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 'Ж' "\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(10,5,10,5,10,5,10), //chess
"µ" => array(15,0,15,0,15,0,15), //4 horizontal lines "µ" => array(15,0,15,0,15,0,15), //4 horizontal lines
// latin // latin
'A' => array(6,9,9,15,9,9,9), 'A' => array(6,9,9,15,9,9,9),
'B' => array(14,9,9,14,9,9,14), 'B' => array(14,9,9,14,9,9,14),
'C' => array(6,9,8,8,8,9,6), 'C' => array(6,9,8,8,8,9,6),
'D' => array(14,9,9,9,9,9,14), 'D' => array(14,9,9,9,9,9,14),
'E' => array(15,8,8,14,8,8,15), 'E' => array(15,8,8,14,8,8,15),
'F' => array(15,8,8,14,8,8,8), 'F' => array(15,8,8,14,8,8,8),
'G' => array(6,9,8,8,11,9,6), 'G' => array(6,9,8,8,11,9,6),
'H' => array(9,9,9,15,9,9,9), 'H' => array(9,9,9,15,9,9,9),
'I' => array(14,4,4,4,4,4,14), 'I' => array(14,4,4,4,4,4,14),
'J' => array(15,1,1,1,1,9,6), 'J' => array(15,1,1,1,1,9,6),
'K' => array(8,9,10,12,12,10,9), 'K' => array(8,9,10,12,12,10,9),
'L' => array(8,8,8,8,8,8,15), 'L' => array(8,8,8,8,8,8,15),
'M' => array(8,13,10,8,8,8,8),// need to add \r 'M' => array(8,13,10,8,8,8,8),// need to add \r
'N' => array(9,9,13,11,9,9,9), 'N' => array(9,9,13,11,9,9,9),
'O' => array(6,9,9,9,9,9,6), 'O' => array(6,9,9,9,9,9,6),
'P' => array(14,9,9,14,8,8,8), 'P' => array(14,9,9,14,8,8,8),
'Q' => array(6,9,9,9,13,11,6), 'Q' => array(6,9,9,9,13,11,6),
'R' => array(14,9,9,14,12,10,9), 'R' => array(14,9,9,14,12,10,9),
'S' => array(6,9,8,6,1,9,6), 'S' => array(6,9,8,6,1,9,6),
'T' => array(14,4,4,4,4,4,4), 'T' => array(14,4,4,4,4,4,4),
'U' => array(9,9,9,9,9,9,6), 'U' => array(9,9,9,9,9,9,6),
'V' => array(0,0,0,10,10,10,4), 'V' => array(0,0,0,10,10,10,4),
'W' => array(8,8,8,8,10,13,8),// need to add \r 'W' => array(8,8,8,8,10,13,8),// need to add \r
'X' => array(9,9,6,6,6,9,9), 'X' => array(9,9,6,6,6,9,9),
'Y' => array(10,10,10,10,4,4,4), 'Y' => array(10,10,10,10,4,4,4),
'Z' => array(15,1,2,6,4,8,15), 'Z' => array(15,1,2,6,4,8,15),
// russian utf-8 // russian utf-8
'А' => array(6,9,9,15,9,9,9), 'А' => array(6,9,9,15,9,9,9),
'Б' => array(14,8,8,14,9,9,14), 'Б' => array(14,8,8,14,9,9,14),
'В' => array(14,9,9,14,9,9,14), 'В' => array(14,9,9,14,9,9,14),
'Г' => array(15,8,8,8,8,8,8), 'Г' => array(15,8,8,8,8,8,8),
'Д' => array(14,9,9,9,9,9,14), 'Д' => array(14,9,9,9,9,9,14),
'Е' => array(15,8,8,14,8,8,15), 'Е' => array(15,8,8,14,8,8,15),
'Ё' => array(6,15,8,14,8,8,15), 'Ё' => array(6,15,8,14,8,8,15),
//Ж is combine: >\n< //Ж is combine: >\n<
'З' => array(6,9,1,2,1,9,6), 'З' => array(6,9,1,2,1,9,6),
'И' => array(9,9,9,11,13,9,9), 'И' => array(9,9,9,11,13,9,9),
'Й' => array(13,9,9,11,13,9,9), 'Й' => array(13,9,9,11,13,9,9),
'К' => array(9,10,12,10,9,9,9), 'К' => array(9,10,12,10,9,9,9),
'Л' => array(7,9,9,9,9,9,9), 'Л' => array(7,9,9,9,9,9,9),
'М' => array(8,13,10,8,8,8,8),// need to add \r 'М' => array(8,13,10,8,8,8,8),// need to add \r
'Н' => array(9,9,9,15,9,9,9), 'Н' => array(9,9,9,15,9,9,9),
'О' => array(6,9,9,9,9,9,6), 'О' => array(6,9,9,9,9,9,6),
'П' => array(15,9,9,9,9,9,9), 'П' => array(15,9,9,9,9,9,9),
'Р' => array(14,9,9,14,8,8,8), 'Р' => array(14,9,9,14,8,8,8),
'С' => array(6,9,8,8,8,9,6), 'С' => array(6,9,8,8,8,9,6),
'Т' => array(14,4,4,4,4,4,4), 'Т' => array(14,4,4,4,4,4,4),
'У' => array(9,9,9,7,1,9,6), 'У' => array(9,9,9,7,1,9,6),
'Ф' => array(2,7,10,10,7,2,2),// need to add Ў 'Ф' => array(2,7,10,10,7,2,2),// need to add Ў
'Х' => array(9,9,6,6,6,9,9), 'Х' => array(9,9,6,6,6,9,9),
'Ц' => array(10,10,10,10,10,15,1), 'Ц' => array(10,10,10,10,10,15,1),
'Ч' => array(9,9,9,7,1,1,1), 'Ч' => array(9,9,9,7,1,1,1),
'Ш' => array(10,10,10,10,10,10,15),// \r 'Ш' => array(10,10,10,10,10,10,15),// \r
'Щ' => array(10,10,10,10,10,15,0),// need to add \r 'Щ' => array(10,10,10,10,10,15,0),// need to add \r
'Ъ' => array(12,4,4,6,5,5,6), 'Ъ' => 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),// need to add |
'Ь' => array(8,8,8,14,9,9,14), 'Ь' => array(8,8,8,14,9,9,14),
'Э' => array(6,9,1,7,1,9,6), 'Э' => array(6,9,1,7,1,9,6),
'Ю' => array(2,2,2,3,2,2,2),// need to add O 'Ю' => array(2,2,2,3,2,2,2),// need to add O
'Я' => array(7,9,9,7,3,5,9) 'Я' => array(7,9,9,7,3,5,9)
), ),
   
$iSuperSampling = 3, $iMarg = 1, $iRad = 4; $iSuperSampling = 3, $iMarg = 1, $iRad = 4;
   
function __construct($aRadius = 2, $aMargin= 0.6) { function __construct($aRadius = 2, $aMargin= 0.6) {
$this->iRad = $aRadius; $this->iRad = $aRadius;
$this->iMarg = $aMargin; $this->iMarg = $aMargin;
} }
   
function SetSupersampling($aSuperSampling = 2) { function SetSupersampling($aSuperSampling = 2) {
$this->iSuperSampling = $aSuperSampling; $this->iSuperSampling = $aSuperSampling;
} }
   
function _GetLED($aLedIdx, $aColor = 0) { function _GetLED($aLedIdx, $aColor = 0) {
$width= $this->iLED_X*$this->iRad*2 + ($this->iLED_X+1)*$this->iMarg + $this->iRad ; $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; $height= $this->iLED_Y*$this->iRad*2 + ($this->iLED_Y)*$this->iMarg + $this->iRad * 2;
   
// Adjust radious for supersampling // Adjust radious for supersampling
$rad = $this->iRad * $this->iSuperSampling; $rad = $this->iRad * $this->iSuperSampling;
   
// Margin in between "Led" dots // Margin in between "Led" dots
$marg = $this->iMarg * $this->iSuperSampling; $marg = $this->iMarg * $this->iSuperSampling;
   
$swidth = $width*$this->iSuperSampling; $swidth = $width*$this->iSuperSampling;
$sheight = $height*$this->iSuperSampling; $sheight = $height*$this->iSuperSampling;
   
$simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false); $simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false);
$simg->SetColor($this->iColorSchema[$aColor][2]); $simg->SetColor($this->iColorSchema[$aColor][2]);
$simg->FilledRectangle(0, 0, $swidth-1, $sheight-1); $simg->FilledRectangle(0, 0, $swidth-1, $sheight-1);
   
if( array_key_exists($aLedIdx, $this->iLEDSpec) ) { if( array_key_exists($aLedIdx, $this->iLEDSpec) ) {
$d = $this->iLEDSpec[$aLedIdx]; $d = $this->iLEDSpec[$aLedIdx];
} }
else { else {
$d = array(0,0,0,0,0,0,0); $d = array(0,0,0,0,0,0,0);
} }
   
for($r = 0; $r < 7; ++$r) { for($r = 0; $r < 7; ++$r) {
$dr = $d[$r]; $dr = $d[$r];
for($c = 0; $c < 4; ++$c) { for($c = 0; $c < 4; ++$c) {
if( ($dr & pow(2,3-$c)) !== 0 ) { if( ($dr & pow(2,3-$c)) !== 0 ) {
$color = $this->iColorSchema[$aColor][0]; $color = $this->iColorSchema[$aColor][0];
} }
else { else {
$color = $this->iColorSchema[$aColor][1]; $color = $this->iColorSchema[$aColor][1];
} }
   
$x = 2*$rad*$c+$rad + ($c+1)*$marg + $rad ; $x = 2*$rad*$c+$rad + ($c+1)*$marg + $rad ;
$y = 2*$rad*$r+$rad + ($r+1)*$marg + $rad ; $y = 2*$rad*$r+$rad + ($r+1)*$marg + $rad ;
   
$simg->SetColor($color); $simg->SetColor($color);
$simg->FilledCircle($x,$y,$rad); $simg->FilledCircle($x,$y,$rad);
} }
} }
   
$img = new Image($width, $height, DEFAULT_GFORMAT, false); $img = new Image($width, $height, DEFAULT_GFORMAT, false);
$img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight); $img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight);
$simg->Destroy(); $simg->Destroy();
unset($simg); unset($simg);
return $img; return $img;
} }
   
   
function Stroke($aValStr, $aColor = 0, $aFileName = '') { function Stroke($aValStr, $aColor = 0, $aFileName = '') {
$this->StrokeNumber($aValStr, $aColor, $aFileName); $this->StrokeNumber($aValStr, $aColor, $aFileName);
} }
   
   
function StrokeNumber($aValStr, $aColor = 0, $aFileName = '') { function StrokeNumber($aValStr, $aColor = 0, $aFileName = '') {
if( $aColor < 0 || $aColor >= sizeof($this->iColorSchema) ) { if( $aColor < 0 || $aColor >= sizeof($this->iColorSchema) ) {
$aColor = 0; $aColor = 0;
} }
   
if(($n = mb_strlen($aValStr,'utf8')) == 0) { if(($n = mb_strlen($aValStr,'utf8')) == 0) {
$aValStr = ' '; $aValStr = ' ';
$n = 1; $n = 1;
} }
   
for($i = 0; $i < $n; ++$i) { for($i = 0; $i < $n; ++$i) {
$d = mb_substr($aValStr, $i, 1, 'utf8'); $d = mb_substr($aValStr, $i, 1, 'utf8');
if( ctype_digit($d) ) { if( ctype_digit($d) ) {
$d = (int)$d; $d = (int)$d;
} }
else { else {
$d = strtoupper($d); $d = strtoupper($d);
} }
$digit_img[$i] = $this->_GetLED($d, $aColor); $digit_img[$i] = $this->_GetLED($d, $aColor);
} }
   
$w = imagesx($digit_img[0]->img); $w = imagesx($digit_img[0]->img);
$h = imagesy($digit_img[0]->img); $h = imagesy($digit_img[0]->img);
   
$number_img = new Image($w*$n, $h, DEFAULT_GFORMAT, false); $number_img = new Image($w*$n, $h, DEFAULT_GFORMAT, false);
   
for($i = 0; $i < $n; ++$i) { for($i = 0; $i < $n; ++$i) {
$number_img->Copy($digit_img[$i]->img, $i*$w, 0, 0, 0, $w, $h, $w, $h); $number_img->Copy($digit_img[$i]->img, $i*$w, 0, 0, 0, $w, $h, $w, $h);
} }
   
if( $aFileName != '' ) { if( $aFileName != '' ) {
$number_img->Stream($aFileName); $number_img->Stream($aFileName);
} else { } else {
$number_img->Headers(); $number_img->Headers();
$number_img->Stream(); $number_img->Stream();
} }
} }
} }
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_LEGEND.INC.PHP // File: JPGRAPH_LEGEND.INC.PHP
// Description: Class to handle the legend box in the graph that gives // Description: Class to handle the legend box in the graph that gives
// names on the data series. The number of rows and columns // names on the data series. The number of rows and columns
// in the legend are user specifyable. // in the legend are user specifyable.
// Created: 2001-01-08 (Refactored to separate file 2008-08-01) // Created: 2001-01-08 (Refactored to separate file 2008-08-01)
// Ver: $Id: jpgraph_legend.inc.php 1911 2009-10-09 17:33:14Z ljp $ // Ver: $Id: jpgraph_legend.inc.php 1911 2009-10-09 17:33:14Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
DEFINE('_DEFAULT_LPM_SIZE',8); // Default Legend Plot Mark size DEFINE('_DEFAULT_LPM_SIZE',8); // Default Legend Plot Mark size
   
   
//=================================================== //===================================================
// CLASS Legend // CLASS Legend
// Description: Responsible for drawing the box containing // Description: Responsible for drawing the box containing
// all the legend text for the graph // all the legend text for the graph
//=================================================== //===================================================
   
class Legend { class Legend {
public $txtcol=array(); public $txtcol=array();
public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12; public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12;
private $color=array(0,0,0); // Default fram color private $color=array(0,0,0); // Default fram color
private $fill_color=array(235,235,235); // Default fill color private $fill_color=array(235,235,235); // Default fill color
private $shadow=true; // Shadow around legend "box" private $shadow=true; // Shadow around legend "box"
private $shadow_color='darkgray'; private $shadow_color='darkgray';
private $mark_abs_hsize=_DEFAULT_LPM_SIZE,$mark_abs_vsize=_DEFAULT_LPM_SIZE; private $mark_abs_hsize=_DEFAULT_LPM_SIZE,$mark_abs_vsize=_DEFAULT_LPM_SIZE;
private $xmargin=10,$ymargin=0,$shadow_width=2; private $xmargin=10,$ymargin=0,$shadow_width=2;
private $xlmargin=4; private $xlmargin=4;
private $ylinespacing=2; private $ylinespacing=2;
// We need a separate margin since the baseline of the last text would coincide with the bottom otherwise // We need a separate margin since the baseline of the last text would coincide with the bottom otherwise
private $ybottom_margin = 8; private $ybottom_margin = 8;
private $xpos=0.05, $ypos=0.15, $xabspos=-1, $yabspos=-1; private $xpos=0.05, $ypos=0.15, $xabspos=-1, $yabspos=-1;
private $halign="right", $valign="top"; private $halign="right", $valign="top";
private $font_color='black'; private $font_color='black';
private $hide=false,$layout_n=1; private $hide=false,$layout_n=1;
private $weight=1,$frameweight=1; private $weight=1,$frameweight=1;
private $csimareas=''; private $csimareas='';
private $reverse = false ; private $reverse = false ;
private $bkg_gradtype=-1, $bkg_gradfrom='lightgray', $bkg_gradto='gray'; private $bkg_gradtype=-1, $bkg_gradfrom='lightgray', $bkg_gradto='gray';
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct() { function __construct() {
// Empty // Empty
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Hide($aHide=true) { function Hide($aHide=true) {
$this->hide=$aHide; $this->hide=$aHide;
} }
   
function SetHColMargin($aXMarg) { function SetHColMargin($aXMarg) {
$this->xmargin = $aXMarg; $this->xmargin = $aXMarg;
} }
   
function SetVColMargin($aSpacing) { function SetVColMargin($aSpacing) {
$this->ylinespacing = $aSpacing ; $this->ylinespacing = $aSpacing ;
} }
   
function SetLeftMargin($aXMarg) { function SetLeftMargin($aXMarg) {
$this->xlmargin = $aXMarg; $this->xlmargin = $aXMarg;
} }
   
// Synonym // Synonym
function SetLineSpacing($aSpacing) { function SetLineSpacing($aSpacing) {
$this->ylinespacing = $aSpacing ; $this->ylinespacing = $aSpacing ;
} }
   
function SetShadow($aShow='gray',$aWidth=4) { function SetShadow($aShow='gray',$aWidth=4) {
if( is_string($aShow) ) { if( is_string($aShow) ) {
$this->shadow_color = $aShow; $this->shadow_color = $aShow;
$this->shadow=true; $this->shadow=true;
} }
else { else {
$this->shadow = $aShow; $this->shadow = $aShow;
} }
$this->shadow_width = $aWidth; $this->shadow_width = $aWidth;
} }
   
function SetMarkAbsSize($aSize) { function SetMarkAbsSize($aSize) {
$this->mark_abs_vsize = $aSize ; $this->mark_abs_vsize = $aSize ;
$this->mark_abs_hsize = $aSize ; $this->mark_abs_hsize = $aSize ;
} }
   
function SetMarkAbsVSize($aSize) { function SetMarkAbsVSize($aSize) {
$this->mark_abs_vsize = $aSize ; $this->mark_abs_vsize = $aSize ;
} }
   
function SetMarkAbsHSize($aSize) { function SetMarkAbsHSize($aSize) {
$this->mark_abs_hsize = $aSize ; $this->mark_abs_hsize = $aSize ;
} }
   
function SetLineWeight($aWeight) { function SetLineWeight($aWeight) {
$this->weight = $aWeight; $this->weight = $aWeight;
} }
   
function SetFrameWeight($aWeight) { function SetFrameWeight($aWeight) {
$this->frameweight = $aWeight; $this->frameweight = $aWeight;
} }
   
function SetLayout($aDirection=LEGEND_VERT) { function SetLayout($aDirection=LEGEND_VERT) {
$this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ; $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ;
} }
   
function SetColumns($aCols) { function SetColumns($aCols) {
$this->layout_n = $aCols ; $this->layout_n = $aCols ;
} }
   
function SetReverse($f=true) { function SetReverse($f=true) {
$this->reverse = $f ; $this->reverse = $f ;
} }
   
// Set color on frame around box // Set color on frame around box
function SetColor($aFontColor,$aColor='black') { function SetColor($aFontColor,$aColor='black') {
$this->font_color=$aFontColor; $this->font_color=$aFontColor;
$this->color=$aColor; $this->color=$aColor;
} }
   
function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
$this->font_family = $aFamily; $this->font_family = $aFamily;
$this->font_style = $aStyle; $this->font_style = $aStyle;
$this->font_size = $aSize; $this->font_size = $aSize;
} }
   
function SetPos($aX,$aY,$aHAlign='right',$aVAlign='top') { function SetPos($aX,$aY,$aHAlign='right',$aVAlign='top') {
$this->Pos($aX,$aY,$aHAlign,$aVAlign); $this->Pos($aX,$aY,$aHAlign,$aVAlign);
} }
   
function SetAbsPos($aX,$aY,$aHAlign='right',$aVAlign='top') { function SetAbsPos($aX,$aY,$aHAlign='right',$aVAlign='top') {
$this->xabspos=$aX; $this->xabspos=$aX;
$this->yabspos=$aY; $this->yabspos=$aY;
$this->halign=$aHAlign; $this->halign=$aHAlign;
$this->valign=$aVAlign; $this->valign=$aVAlign;
} }
   
function Pos($aX,$aY,$aHAlign='right',$aVAlign='top') { function Pos($aX,$aY,$aHAlign='right',$aVAlign='top') {
if( !($aX<1 && $aY<1) ) { if( !($aX<1 && $aY<1) ) {
JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1"); JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1");
} }
$this->xpos=$aX; $this->xpos=$aX;
$this->ypos=$aY; $this->ypos=$aY;
$this->halign=$aHAlign; $this->halign=$aHAlign;
$this->valign=$aVAlign; $this->valign=$aVAlign;
} }
   
function SetFillColor($aColor) { function SetFillColor($aColor) {
$this->fill_color=$aColor; $this->fill_color=$aColor;
} }
   
function Clear() { function Clear() {
$this->txtcol = array(); $this->txtcol = array();
} }
   
function Add($aTxt,$aColor,$aPlotmark='',$aLinestyle=0,$csimtarget='',$csimalt='',$csimwintarget='') { function Add($aTxt,$aColor,$aPlotmark='',$aLinestyle=0,$csimtarget='',$csimalt='',$csimwintarget='') {
$this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget); $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget);
} }
   
function GetCSIMAreas() { function GetCSIMAreas() {
return $this->csimareas; return $this->csimareas;
} }
   
function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2) { function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2) {
$this->bkg_gradtype=$aGradType; $this->bkg_gradtype=$aGradType;
$this->bkg_gradfrom = $aFrom; $this->bkg_gradfrom = $aFrom;
$this->bkg_gradto = $aTo; $this->bkg_gradto = $aTo;
} }
   
function Stroke($aImg) { function Stroke($aImg) {
// Constant // Constant
$fillBoxFrameWeight=1; $fillBoxFrameWeight=1;
   
if( $this->hide ) return; if( $this->hide ) return;
   
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
   
if( $this->reverse ) { if( $this->reverse ) {
$this->txtcol = array_reverse($this->txtcol); $this->txtcol = array_reverse($this->txtcol);
} }
   
$n=count($this->txtcol); $n=count($this->txtcol);
if( $n == 0 ) return; if( $n == 0 ) return;
   
// Find out the max width and height of each column to be able // Find out the max width and height of each column to be able
// to size the legend box. // to size the legend box.
$numcolumns = ($n > $this->layout_n ? $this->layout_n : $n); $numcolumns = ($n > $this->layout_n ? $this->layout_n : $n);
for( $i=0; $i < $numcolumns; ++$i ) { for( $i=0; $i < $numcolumns; ++$i ) {
$colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) + $colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) +
2*$this->xmargin + 2*$this->mark_abs_hsize; 2*$this->xmargin + 2*$this->mark_abs_hsize;
$colheight[$i] = 0; $colheight[$i] = 0;
   
} }
   
// Find our maximum height in each row // Find our maximum height in each row
$rows = 0 ; $rowheight[0] = 0; $rows = 0 ; $rowheight[0] = 0;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$h = max($this->mark_abs_vsize, $h = max($this->mark_abs_vsize,
$aImg->GetTextHeight($this->txtcol[$i][0]))+$this->ylinespacing; $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 // 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 // between two vertical legend entries
//$h = round(max($h,$this->mark_abs_vsize+$this->ymargin)); //$h = round(max($h,$this->mark_abs_vsize+$this->ymargin));
//echo "Textheight #$i: tetxheight=".$aImg->GetTextHeight($this->txtcol[$i][0]).', '; //echo "Textheight #$i: tetxheight=".$aImg->GetTextHeight($this->txtcol[$i][0]).', ';
//echo "h=$h ({$this->mark_abs_vsize},{$this->ymargin})<br>"; //echo "h=$h ({$this->mark_abs_vsize},{$this->ymargin})<br>";
if( $i % $numcolumns == 0 ) { if( $i % $numcolumns == 0 ) {
$rows++; $rows++;
$rowheight[$rows-1] = 0; $rowheight[$rows-1] = 0;
} }
$rowheight[$rows-1] = max($rowheight[$rows-1],$h); $rowheight[$rows-1] = max($rowheight[$rows-1],$h);
} }
   
$abs_height = 0; $abs_height = 0;
for( $i=0; $i < $rows; ++$i ) { for( $i=0; $i < $rows; ++$i ) {
$abs_height += $rowheight[$i] ; $abs_height += $rowheight[$i] ;
} }
   
// Make sure that the height is at least as high as mark size + ymargin // 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 = max($abs_height,$this->mark_abs_vsize);
$abs_height += $this->ybottom_margin; $abs_height += $this->ybottom_margin;
   
// Find out the maximum width in each column // Find out the maximum width in each column
for( $i=$numcolumns; $i < $n; ++$i ) { for( $i=$numcolumns; $i < $n; ++$i ) {
$colwidth[$i % $numcolumns] = max( $colwidth[$i % $numcolumns] = max(
$aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize, $aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize,
$colwidth[$i % $numcolumns]); $colwidth[$i % $numcolumns]);
} }
   
// Get the total width // Get the total width
$mtw = 0; $mtw = 0;
for( $i=0; $i < $numcolumns; ++$i ) { for( $i=0; $i < $numcolumns; ++$i ) {
$mtw += $colwidth[$i] ; $mtw += $colwidth[$i] ;
} }
   
// Find out maximum width we need for legend box // Find out maximum width we need for legend box
$abs_width = $mtw+$this->xlmargin+($numcolumns-1)*$this->mark_abs_hsize; $abs_width = $mtw+$this->xlmargin+($numcolumns-1)*$this->mark_abs_hsize;
   
if( $this->xabspos === -1 && $this->yabspos === -1 ) { if( $this->xabspos === -1 && $this->yabspos === -1 ) {
$this->xabspos = $this->xpos*$aImg->width ; $this->xabspos = $this->xpos*$aImg->width ;
$this->yabspos = $this->ypos*$aImg->height ; $this->yabspos = $this->ypos*$aImg->height ;
} }
   
// Positioning of the legend box // Positioning of the legend box
if( $this->halign == 'left' ) { if( $this->halign == 'left' ) {
$xp = $this->xabspos; $xp = $this->xabspos;
} }
elseif( $this->halign == 'center' ) { elseif( $this->halign == 'center' ) {
$xp = $this->xabspos - $abs_width/2; $xp = $this->xabspos - $abs_width/2;
} }
else { else {
$xp = $aImg->width - $this->xabspos - $abs_width; $xp = $aImg->width - $this->xabspos - $abs_width;
} }
   
$yp=$this->yabspos; $yp=$this->yabspos;
if( $this->valign == 'center' ) { if( $this->valign == 'center' ) {
$yp-=$abs_height/2; $yp-=$abs_height/2;
} }
elseif( $this->valign == 'bottom' ) { elseif( $this->valign == 'bottom' ) {
$yp-=$abs_height; $yp-=$abs_height;
} }
   
// Stroke legend box // Stroke legend box
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->SetLineWeight($this->frameweight); $aImg->SetLineWeight($this->frameweight);
$aImg->SetLineStyle('solid'); $aImg->SetLineStyle('solid');
   
if( $this->shadow ) { if( $this->shadow ) {
$aImg->ShadowRectangle($xp,$yp, $aImg->ShadowRectangle($xp,$yp,
$xp+$abs_width+$this->shadow_width+2, $xp+$abs_width+$this->shadow_width+2,
$yp+$abs_height+$this->shadow_width+2, $yp+$abs_height+$this->shadow_width+2,
$this->fill_color,$this->shadow_width+2,$this->shadow_color); $this->fill_color,$this->shadow_width+2,$this->shadow_color);
} }
else { else {
$aImg->SetColor($this->fill_color); $aImg->SetColor($this->fill_color);
$aImg->FilledRectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height); $aImg->FilledRectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height);
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->Rectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height); $aImg->Rectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height);
} }
   
if( $this->bkg_gradtype >= 0 ) { if( $this->bkg_gradtype >= 0 ) {
$grad = new Gradient($aImg); $grad = new Gradient($aImg);
$grad->FilledRectangle($xp+1, $yp+1, $grad->FilledRectangle($xp+1, $yp+1,
$xp+$abs_width-3, $yp+$abs_height-3, $xp+$abs_width-3, $yp+$abs_height-3,
$this->bkg_gradfrom, $this->bkg_gradto, $this->bkg_gradfrom, $this->bkg_gradto,
$this->bkg_gradtype); $this->bkg_gradtype);
} }
   
// x1,y1 is the position for the legend marker + text // x1,y1 is the position for the legend marker + text
// The vertical position is the baseline position for the text // The vertical position is the baseline position for the text
// and every marker is adjusted acording to that. // and every marker is adjusted acording to that.
$x1 = $xp + $this->xlmargin; $x1 = $xp + $this->xlmargin;
$y1 = $yp + $rowheight[0]; // The ymargin is included in rowheight $y1 = $yp + $rowheight[0]; // The ymargin is included in rowheight
   
$grad = new Gradient($aImg); $grad = new Gradient($aImg);
$patternFactory = null; $patternFactory = null;
   
// Now stroke each legend in turn // Now stroke each legend in turn
// Each plot has added the following information to the legend // Each plot has added the following information to the legend
// p[0] = Legend text // p[0] = Legend text
// p[1] = Color, // p[1] = Color,
// p[2] = For markers a reference to the PlotMark object // p[2] = For markers a reference to the PlotMark object
// p[3] = For lines the line style, for gradient the negative gradient style // p[3] = For lines the line style, for gradient the negative gradient style
// p[4] = CSIM target // p[4] = CSIM target
// p[5] = CSIM Alt text // p[5] = CSIM Alt text
$i = 1 ; $row = 0; $i = 1 ; $row = 0;
foreach($this->txtcol as $p) { foreach($this->txtcol as $p) {
   
// STROKE DEBUG BOX // STROKE DEBUG BOX
if( _JPG_DEBUG ) { if( _JPG_DEBUG ) {
$aImg->SetLineWeight(1); $aImg->SetLineWeight(1);
$aImg->SetColor('red'); $aImg->SetColor('red');
$aImg->SetLineStyle('solid'); $aImg->SetLineStyle('solid');
//$aImg->Rectangle($x1,$y1,$xp+$abs_width,$y1+$rowheight[$row]); //$aImg->Rectangle($x1,$y1,$xp+$abs_width,$y1+$rowheight[$row]);
$aImg->Rectangle($x1,$y1,$xp+$abs_width-1,$y1-$rowheight[$row]); $aImg->Rectangle($x1,$y1,$xp+$abs_width-1,$y1-$rowheight[$row]);
} }
   
$aImg->SetLineWeight($this->weight); $aImg->SetLineWeight($this->weight);
$x1 = round($x1)+1; // We add one to not collide with the border $x1 = round($x1)+1; // We add one to not collide with the border
$y1=round($y1); $y1=round($y1);
   
// This is the center offset up from the baseline which is // This is the center offset up from the baseline which is
// considered the "center" of the marks. This gets slightly complicated since // 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 // 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 // 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 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 // 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 // case we center the mark in the middle of the paragraph
if( !preg_match('/\n/',$p[0]) ) { if( !preg_match('/\n/',$p[0]) ) {
// Single line // Single line
$marky = ceil($y1-$this->mark_abs_vsize/2)-1; $marky = ceil($y1-$this->mark_abs_vsize/2)-1;
} else { } else {
// Paragraph // Paragraph
$marky = $y1 - $aImg->GetTextHeight($p[0])/2; $marky = $y1 - $aImg->GetTextHeight($p[0])/2;
} }
   
$x1 += $this->mark_abs_hsize; $x1 += $this->mark_abs_hsize;
if ( !empty($p[2]) && $p[2]->GetType() > -1 ) { if ( !empty($p[2]) && $p[2]->GetType() > -1 ) {
   
   
// Make a plot mark legend. This is constructed with a mark which // Make a plot mark legend. This is constructed with a mark which
// is run through with a line // is run through with a line
   
// First construct a bit of the line that looks exactly like the // First construct a bit of the line that looks exactly like the
// line in the plot // line in the plot
$aImg->SetColor($p[1]); $aImg->SetColor($p[1]);
if( is_string($p[3]) || $p[3]>0 ) { if( is_string($p[3]) || $p[3]>0 ) {
$aImg->SetLineStyle($p[3]); $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,$x1+$this->mark_abs_hsize,$marky);
} }
   
// Stroke a mark with the standard size // Stroke a mark with the standard size
// (As long as it is not an image mark ) // (As long as it is not an image mark )
if( $p[2]->GetType() != MARK_IMG ) { if( $p[2]->GetType() != MARK_IMG ) {
   
// Clear any user callbacks since we ont want them called for // Clear any user callbacks since we ont want them called for
// the legend marks // the legend marks
$p[2]->iFormatCallback = ''; $p[2]->iFormatCallback = '';
$p[2]->iFormatCallback2 = ''; $p[2]->iFormatCallback2 = '';
   
// Since size for circles is specified as the radius // Since size for circles is specified as the radius
// this means that we must half the size to make the total // this means that we must half the size to make the total
// width behave as the other marks // width behave as the other marks
if( $p[2]->GetType() == MARK_FILLEDCIRCLE || $p[2]->GetType() == MARK_CIRCLE ) { 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]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)/2);
$p[2]->Stroke($aImg,$x1,$marky); $p[2]->Stroke($aImg,$x1,$marky);
} }
else { else {
$p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)); $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize));
$p[2]->Stroke($aImg,$x1,$marky); $p[2]->Stroke($aImg,$x1,$marky);
} }
} }
} }
elseif ( !empty($p[2]) && (is_string($p[3]) || $p[3]>0 ) ) { elseif ( !empty($p[2]) && (is_string($p[3]) || $p[3]>0 ) ) {
// Draw a styled line // Draw a styled line
$aImg->SetColor($p[1]); $aImg->SetColor($p[1]);
$aImg->SetLineStyle($p[3]); $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,$x1+$this->mark_abs_hsize,$marky);
$aImg->StyleLine($x1-$this->mark_abs_hsize,$marky+1,$x1+$this->mark_abs_hsize,$marky+1); $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky+1,$x1+$this->mark_abs_hsize,$marky+1);
} }
else { else {
// Draw a colored box // Draw a colored box
$color = $p[1] ; $color = $p[1] ;
   
// We make boxes slightly larger to better show // We make boxes slightly larger to better show
$boxsize = max($this->mark_abs_vsize,$this->mark_abs_hsize) + 2 ; $boxsize = max($this->mark_abs_vsize,$this->mark_abs_hsize) + 2 ;
   
$ym = $marky-ceil($boxsize/2) ; // Marker y-coordinate $ym = $marky-ceil($boxsize/2) ; // Marker y-coordinate
   
// We either need to plot a gradient or a // We either need to plot a gradient or a
// pattern. To differentiate we use a kludge. // pattern. To differentiate we use a kludge.
// Patterns have a p[3] value of < -100 // Patterns have a p[3] value of < -100
if( $p[3] < -100 ) { if( $p[3] < -100 ) {
// p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity // p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity
if( $patternFactory == null ) { if( $patternFactory == null ) {
$patternFactory = new RectPatternFactory(); $patternFactory = new RectPatternFactory();
} }
$prect = $patternFactory->Create($p[1][0],$p[1][1],1); $prect = $patternFactory->Create($p[1][0],$p[1][1],1);
$prect->SetBackground($p[1][3]); $prect->SetBackground($p[1][3]);
$prect->SetDensity($p[1][2]+1); $prect->SetDensity($p[1][2]+1);
$prect->SetPos(new Rectangle($x1,$ym,$boxsize,$boxsize)); $prect->SetPos(new Rectangle($x1,$ym,$boxsize,$boxsize));
$prect->Stroke($aImg); $prect->Stroke($aImg);
$prect=null; $prect=null;
} }
else { else {
if( is_array($color) && count($color)==2 ) { if( is_array($color) && count($color)==2 ) {
// The client want a gradient color // The client want a gradient color
$grad->FilledRectangle($x1-$boxsize/2,$ym, $grad->FilledRectangle($x1-$boxsize/2,$ym,
$x1+$boxsize/2,$ym+$boxsize, $x1+$boxsize/2,$ym+$boxsize,
$color[0],$color[1],-$p[3]); $color[0],$color[1],-$p[3]);
} }
else { else {
$aImg->SetColor($p[1]); $aImg->SetColor($p[1]);
$aImg->FilledRectangle($x1-$boxsize/2,$ym, $aImg->FilledRectangle($x1-$boxsize/2,$ym,
$x1+$boxsize/2,$ym+$boxsize); $x1+$boxsize/2,$ym+$boxsize);
} }
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->SetLineWeight($fillBoxFrameWeight); $aImg->SetLineWeight($fillBoxFrameWeight);
$aImg->Rectangle($x1-$boxsize/2,$ym, $aImg->Rectangle($x1-$boxsize/2,$ym,
$x1+$boxsize/2,$ym+$boxsize); $x1+$boxsize/2,$ym+$boxsize);
} }
} }
$aImg->SetColor($this->font_color); $aImg->SetColor($this->font_color);
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$aImg->SetTextAlign('left','baseline'); $aImg->SetTextAlign('left','baseline');
   
$aImg->StrokeText($x1+$this->mark_abs_hsize+$this->xmargin,$y1,$p[0]); $aImg->StrokeText($x1+$this->mark_abs_hsize+$this->xmargin,$y1,$p[0]);
   
// Add CSIM for Legend if defined // Add CSIM for Legend if defined
if( !empty($p[4]) ) { if( !empty($p[4]) ) {
   
$xs = $x1 - $this->mark_abs_hsize; $xs = $x1 - $this->mark_abs_hsize;
$ys = $y1 + 1 ; $ys = $y1 + 1 ;
$xe = $x1 + $aImg->GetTextWidth($p[0]) ; $xe = $x1 + $aImg->GetTextWidth($p[0]) ;
$ye = $y1-$rowheight[$row]; $ye = $y1-$rowheight[$row];
$coords = "$xs,$ys,$xe,$y1,$xe,$ye,$x1,$ye"; $coords = "$xs,$ys,$xe,$y1,$xe,$ye,$x1,$ye";
if( ! empty($p[4]) ) { if( ! empty($p[4]) ) {
$this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($p[4])."\""; $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($p[4])."\"";
   
if( !empty($p[6]) ) { if( !empty($p[6]) ) {
$this->csimareas .= " target=\"".$p[6]."\""; $this->csimareas .= " target=\"".$p[6]."\"";
} }
   
if( !empty($p[5]) ) { if( !empty($p[5]) ) {
$tmp=sprintf($p[5],$p[0]); $tmp=sprintf($p[5],$p[0]);
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
} }
   
if( $i >= $this->layout_n ) { if( $i >= $this->layout_n ) {
$x1 = $xp+$this->xlmargin; $x1 = $xp+$this->xlmargin;
$y1 += $rowheight[$row++]; $y1 += $rowheight[$row++];
$i = 1; $i = 1;
} }
else { else {
$x1 += $colwidth[($i-1) % $numcolumns] ; $x1 += $colwidth[($i-1) % $numcolumns] ;
++$i; ++$i;
} }
} }
} }
} // Class } // Class
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_LINE.PHP // File: JPGRAPH_LINE.PHP
// Description: Line plot extension for JpGraph // Description: Line plot extension for JpGraph
// Created: 2001-01-08 // Created: 2001-01-08
// Ver: $Id: jpgraph_line.php 1896 2009-10-03 13:02:34Z ljp $ // Ver: $Id: jpgraph_line.php 1896 2009-10-03 13:02:34Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
require_once ('jpgraph_plotmark.inc.php'); require_once ('jpgraph_plotmark.inc.php');
   
// constants for the (filled) area // constants for the (filled) area
DEFINE("LP_AREA_FILLED", true); DEFINE("LP_AREA_FILLED", true);
DEFINE("LP_AREA_NOT_FILLED", false); DEFINE("LP_AREA_NOT_FILLED", false);
DEFINE("LP_AREA_BORDER",false); DEFINE("LP_AREA_BORDER",false);
DEFINE("LP_AREA_NO_BORDER",true); DEFINE("LP_AREA_NO_BORDER",true);
   
//=================================================== //===================================================
// CLASS LinePlot // CLASS LinePlot
// Description: // Description:
//=================================================== //===================================================
class LinePlot extends Plot{ class LinePlot extends Plot{
public $mark=null; public $mark=null;
protected $filled=false; protected $filled=false;
protected $fill_color='blue'; protected $fill_color='blue';
protected $step_style=false, $center=false; protected $step_style=false, $center=false;
protected $line_style=1; // Default to solid protected $line_style=1; // Default to solid
protected $filledAreas = array(); // array of arrays(with min,max,col,filled in them) protected $filledAreas = array(); // array of arrays(with min,max,col,filled in them)
public $barcenter=false; // When we mix line and bar. Should we center the line in the bar. public $barcenter=false; // When we mix line and bar. Should we center the line in the bar.
protected $fillFromMin = false, $fillFromMax = false; protected $fillFromMin = false, $fillFromMax = false;
protected $fillgrad=false,$fillgrad_fromcolor='navy',$fillgrad_tocolor='silver',$fillgrad_numcolors=100; protected $fillgrad=false,$fillgrad_fromcolor='navy',$fillgrad_tocolor='silver',$fillgrad_numcolors=100;
protected $iFastStroke=false; protected $iFastStroke=false;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function LinePlot($datay,$datax=false) { function LinePlot($datay,$datax=false) {
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
$this->mark = new PlotMark() ; $this->mark = new PlotMark() ;
$this->color = ColorFactory::getColor(); $this->color = ColorFactory::getColor();
$this->fill_color = $this->color; $this->fill_color = $this->color;
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
function SetFilled($aFlg=true) { function SetFilled($aFlg=true) {
$this->filled = $aFlg; $this->filled = $aFlg;
} }
   
function SetBarCenter($aFlag=true) { function SetBarCenter($aFlag=true) {
$this->barcenter=$aFlag; $this->barcenter=$aFlag;
} }
   
function SetStyle($aStyle) { function SetStyle($aStyle) {
$this->line_style=$aStyle; $this->line_style=$aStyle;
} }
   
function SetStepStyle($aFlag=true) { function SetStepStyle($aFlag=true) {
$this->step_style = $aFlag; $this->step_style = $aFlag;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
parent::SetColor($aColor); parent::SetColor($aColor);
} }
   
function SetFillFromYMin($f=true) { function SetFillFromYMin($f=true) {
$this->fillFromMin = $f ; $this->fillFromMin = $f ;
} }
   
function SetFillFromYMax($f=true) { function SetFillFromYMax($f=true) {
$this->fillFromMax = $f ; $this->fillFromMax = $f ;
} }
   
function SetFillColor($aColor,$aFilled=true) { function SetFillColor($aColor,$aFilled=true) {
//$this->color = $aColor; //$this->color = $aColor;
$this->fill_color=$aColor; $this->fill_color=$aColor;
$this->filled=$aFilled; $this->filled=$aFilled;
} }
   
function SetFillGradient($aFromColor,$aToColor,$aNumColors=100,$aFilled=true) { function SetFillGradient($aFromColor,$aToColor,$aNumColors=100,$aFilled=true) {
$this->fillgrad_fromcolor = $aFromColor; $this->fillgrad_fromcolor = $aFromColor;
$this->fillgrad_tocolor = $aToColor; $this->fillgrad_tocolor = $aToColor;
$this->fillgrad_numcolors = $aNumColors; $this->fillgrad_numcolors = $aNumColors;
$this->filled = $aFilled; $this->filled = $aFilled;
$this->fillgrad = true; $this->fillgrad = true;
} }
   
function Legend($graph) { function Legend($graph) {
if( $this->legend!="" ) { if( $this->legend!="" ) {
if( $this->filled && !$this->fillgrad ) { if( $this->filled && !$this->fillgrad ) {
$graph->legend->Add($this->legend, $graph->legend->Add($this->legend,
$this->fill_color,$this->mark,0, $this->fill_color,$this->mark,0,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
elseif( $this->fillgrad ) { elseif( $this->fillgrad ) {
$color=array($this->fillgrad_fromcolor,$this->fillgrad_tocolor); $color=array($this->fillgrad_fromcolor,$this->fillgrad_tocolor);
// In order to differentiate between gradients and cooors specified as an RGB triple // In order to differentiate between gradients and cooors specified as an RGB triple
$graph->legend->Add($this->legend,$color,"",-2 /* -GRAD_HOR */, $graph->legend->Add($this->legend,$color,"",-2 /* -GRAD_HOR */,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} else { } else {
$graph->legend->Add($this->legend, $graph->legend->Add($this->legend,
$this->color,$this->mark,$this->line_style, $this->color,$this->mark,$this->line_style,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
} }
} }
   
function AddArea($aMin=0,$aMax=0,$aFilled=LP_AREA_NOT_FILLED,$aColor="gray9",$aBorder=LP_AREA_BORDER) { function AddArea($aMin=0,$aMax=0,$aFilled=LP_AREA_NOT_FILLED,$aColor="gray9",$aBorder=LP_AREA_BORDER) {
if($aMin > $aMax) { if($aMin > $aMax) {
// swap // swap
$tmp = $aMin; $tmp = $aMin;
$aMin = $aMax; $aMin = $aMax;
$aMax = $tmp; $aMax = $tmp;
} }
$this->filledAreas[] = array($aMin,$aMax,$aColor,$aFilled,$aBorder); $this->filledAreas[] = array($aMin,$aMax,$aColor,$aFilled,$aBorder);
} }
   
// Gets called before any axis are stroked // Gets called before any axis are stroked
function PreStrokeAdjust($graph) { function PreStrokeAdjust($graph) {
   
// If another plot type have already adjusted the // If another plot type have already adjusted the
// offset we don't touch it. // offset we don't touch it.
// (We check for empty in case the scale is a log scale // (We check for empty in case the scale is a log scale
// and hence doesn't contain any xlabel_offset) // and hence doesn't contain any xlabel_offset)
if( empty($graph->xaxis->scale->ticks->xlabel_offset) || $graph->xaxis->scale->ticks->xlabel_offset == 0 ) { if( empty($graph->xaxis->scale->ticks->xlabel_offset) || $graph->xaxis->scale->ticks->xlabel_offset == 0 ) {
if( $this->center ) { if( $this->center ) {
++$this->numpoints; ++$this->numpoints;
$a=0.5; $b=0.5; $a=0.5; $b=0.5;
} else { } else {
$a=0; $b=0; $a=0; $b=0;
} }
$graph->xaxis->scale->ticks->SetXLabelOffset($a); $graph->xaxis->scale->ticks->SetXLabelOffset($a);
$graph->SetTextScaleOff($b); $graph->SetTextScaleOff($b);
//$graph->xaxis->scale->ticks->SupressMinorTickMarks(); //$graph->xaxis->scale->ticks->SupressMinorTickMarks();
} }
} }
   
function SetFastStroke($aFlg=true) { function SetFastStroke($aFlg=true) {
$this->iFastStroke = $aFlg; $this->iFastStroke = $aFlg;
} }
   
function FastStroke($img,$xscale,$yscale,$aStartPoint=0,$exist_x=true) { function FastStroke($img,$xscale,$yscale,$aStartPoint=0,$exist_x=true) {
// An optimized stroke for many data points with no extra // An optimized stroke for many data points with no extra
// features but 60% faster. You can't have values or line styles, or null // features but 60% faster. You can't have values or line styles, or null
// values in plots. // values in plots.
$numpoints=count($this->coords[0]); $numpoints=count($this->coords[0]);
if( $this->barcenter ) { if( $this->barcenter ) {
$textadj = 0.5-$xscale->text_scale_off; $textadj = 0.5-$xscale->text_scale_off;
} }
else { else {
$textadj = 0; $textadj = 0;
} }
   
$img->SetColor($this->color); $img->SetColor($this->color);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$pnts=$aStartPoint; $pnts=$aStartPoint;
while( $pnts < $numpoints ) { while( $pnts < $numpoints ) {
if( $exist_x ) { if( $exist_x ) {
$x=$this->coords[1][$pnts]; $x=$this->coords[1][$pnts];
} }
else { else {
$x=$pnts+$textadj; $x=$pnts+$textadj;
} }
$xt = $xscale->Translate($x); $xt = $xscale->Translate($x);
$y=$this->coords[0][$pnts]; $y=$this->coords[0][$pnts];
$yt = $yscale->Translate($y); $yt = $yscale->Translate($y);
if( is_numeric($y) ) { if( is_numeric($y) ) {
$cord[] = $xt; $cord[] = $xt;
$cord[] = $yt; $cord[] = $yt;
} }
elseif( $y == '-' && $pnts > 0 ) { elseif( $y == '-' && $pnts > 0 ) {
// Just ignore // Just ignore
} }
else { else {
JpGraphError::RaiseL(10002);//('Plot too complicated for fast line Stroke. Use standard Stroke()'); JpGraphError::RaiseL(10002);//('Plot too complicated for fast line Stroke. Use standard Stroke()');
} }
++$pnts; ++$pnts;
} // WHILE } // WHILE
   
$img->Polygon($cord,false,true); $img->Polygon($cord,false,true);
} }
   
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
$idx=0; $idx=0;
$numpoints=count($this->coords[0]); $numpoints=count($this->coords[0]);
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
if( count($this->coords[1])!=$numpoints ) { if( count($this->coords[1])!=$numpoints ) {
JpGraphError::RaiseL(2003,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"); //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
} }
else { else {
$exist_x = true; $exist_x = true;
} }
} }
else { else {
$exist_x = false; $exist_x = false;
} }
   
if( $this->barcenter ) { if( $this->barcenter ) {
$textadj = 0.5-$xscale->text_scale_off; $textadj = 0.5-$xscale->text_scale_off;
} }
else { else {
$textadj = 0; $textadj = 0;
} }
   
// Find the first numeric data point // Find the first numeric data point
$startpoint=0; $startpoint=0;
while( $startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint]) ) { while( $startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint]) ) {
++$startpoint; ++$startpoint;
} }
   
// Bail out if no data points // Bail out if no data points
if( $startpoint == $numpoints ) return; if( $startpoint == $numpoints ) return;
   
if( $this->iFastStroke ) { if( $this->iFastStroke ) {
$this->FastStroke($img,$xscale,$yscale,$startpoint,$exist_x); $this->FastStroke($img,$xscale,$yscale,$startpoint,$exist_x);
return; return;
} }
   
if( $exist_x ) { if( $exist_x ) {
$xs=$this->coords[1][$startpoint]; $xs=$this->coords[1][$startpoint];
} }
else { else {
$xs= $textadj+$startpoint; $xs= $textadj+$startpoint;
} }
   
$img->SetStartPoint($xscale->Translate($xs), $img->SetStartPoint($xscale->Translate($xs),
$yscale->Translate($this->coords[0][$startpoint])); $yscale->Translate($this->coords[0][$startpoint]));
   
if( $this->filled ) { if( $this->filled ) {
if( $this->fillFromMax ) { if( $this->fillFromMax ) {
//$max = $yscale->GetMaxVal(); //$max = $yscale->GetMaxVal();
$cord[$idx++] = $xscale->Translate($xs); $cord[$idx++] = $xscale->Translate($xs);
$cord[$idx++] = $yscale->scale_abs[1]; $cord[$idx++] = $yscale->scale_abs[1];
} }
else { else {
$min = $yscale->GetMinVal(); $min = $yscale->GetMinVal();
if( $min > 0 || $this->fillFromMin ) { if( $min > 0 || $this->fillFromMin ) {
$fillmin = $yscale->scale_abs[0];//Translate($min); $fillmin = $yscale->scale_abs[0];//Translate($min);
} }
else { else {
$fillmin = $yscale->Translate(0); $fillmin = $yscale->Translate(0);
} }
   
$cord[$idx++] = $xscale->Translate($xs); $cord[$idx++] = $xscale->Translate($xs);
$cord[$idx++] = $fillmin; $cord[$idx++] = $fillmin;
} }
} }
$xt = $xscale->Translate($xs); $xt = $xscale->Translate($xs);
$yt = $yscale->Translate($this->coords[0][$startpoint]); $yt = $yscale->Translate($this->coords[0][$startpoint]);
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $yt; $cord[$idx++] = $yt;
$yt_old = $yt; $yt_old = $yt;
$xt_old = $xt; $xt_old = $xt;
$y_old = $this->coords[0][$startpoint]; $y_old = $this->coords[0][$startpoint];
   
$this->value->Stroke($img,$this->coords[0][$startpoint],$xt,$yt); $this->value->Stroke($img,$this->coords[0][$startpoint],$xt,$yt);
   
$img->SetColor($this->color); $img->SetColor($this->color);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$img->SetLineStyle($this->line_style); $img->SetLineStyle($this->line_style);
$pnts=$startpoint+1; $pnts=$startpoint+1;
$firstnonumeric = false; $firstnonumeric = false;
   
   
while( $pnts < $numpoints ) { while( $pnts < $numpoints ) {
   
if( $exist_x ) { if( $exist_x ) {
$x=$this->coords[1][$pnts]; $x=$this->coords[1][$pnts];
} }
else { else {
$x=$pnts+$textadj; $x=$pnts+$textadj;
} }
$xt = $xscale->Translate($x); $xt = $xscale->Translate($x);
$yt = $yscale->Translate($this->coords[0][$pnts]); $yt = $yscale->Translate($this->coords[0][$pnts]);
   
$y=$this->coords[0][$pnts]; $y=$this->coords[0][$pnts];
if( $this->step_style ) { if( $this->step_style ) {
// To handle null values within step style we need to record the // 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 // first non numeric value so we know from where to start if the
// non value is '-'. // non value is '-'.
if( is_numeric($y) ) { if( is_numeric($y) ) {
$firstnonumeric = false; $firstnonumeric = false;
if( is_numeric($y_old) ) { if( is_numeric($y_old) ) {
$img->StyleLine($xt_old,$yt_old,$xt,$yt_old); $img->StyleLine($xt_old,$yt_old,$xt,$yt_old);
$img->StyleLine($xt,$yt_old,$xt,$yt); $img->StyleLine($xt,$yt_old,$xt,$yt);
} }
elseif( $y_old == '-' ) { elseif( $y_old == '-' ) {
$img->StyleLine($xt_first,$yt_first,$xt,$yt_first); $img->StyleLine($xt_first,$yt_first,$xt,$yt_first);
$img->StyleLine($xt,$yt_first,$xt,$yt); $img->StyleLine($xt,$yt_first,$xt,$yt);
} }
else { else {
$yt_old = $yt; $yt_old = $yt;
$xt_old = $xt; $xt_old = $xt;
} }
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $yt_old; $cord[$idx++] = $yt_old;
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $yt; $cord[$idx++] = $yt;
} }
elseif( $firstnonumeric==false ) { elseif( $firstnonumeric==false ) {
$firstnonumeric = true; $firstnonumeric = true;
$yt_first = $yt_old; $yt_first = $yt_old;
$xt_first = $xt_old; $xt_first = $xt_old;
} }
} }
else { else {
$tmp1=$y; $tmp1=$y;
$prev=$this->coords[0][$pnts-1]; $prev=$this->coords[0][$pnts-1];
if( $tmp1==='' || $tmp1===NULL || $tmp1==='X' ) $tmp1 = 'x'; if( $tmp1==='' || $tmp1===NULL || $tmp1==='X' ) $tmp1 = 'x';
if( $prev==='' || $prev===null || $prev==='X' ) $prev = 'x'; if( $prev==='' || $prev===null || $prev==='X' ) $prev = 'x';
   
if( is_numeric($y) || (is_string($y) && $y != '-') ) { if( is_numeric($y) || (is_string($y) && $y != '-') ) {
if( is_numeric($y) && (is_numeric($prev) || $prev === '-' ) ) { if( is_numeric($y) && (is_numeric($prev) || $prev === '-' ) ) {
$img->StyleLineTo($xt,$yt); $img->StyleLineTo($xt,$yt);
} }
else { else {
$img->SetStartPoint($xt,$yt); $img->SetStartPoint($xt,$yt);
} }
} }
if( $this->filled && $tmp1 !== '-' ) { if( $this->filled && $tmp1 !== '-' ) {
if( $tmp1 === 'x' ) { if( $tmp1 === 'x' ) {
$cord[$idx++] = $cord[$idx-3]; $cord[$idx++] = $cord[$idx-3];
$cord[$idx++] = $fillmin; $cord[$idx++] = $fillmin;
} }
elseif( $prev === 'x' ) { elseif( $prev === 'x' ) {
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $fillmin; $cord[$idx++] = $fillmin;
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $yt; $cord[$idx++] = $yt;
} }
else { else {
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $yt; $cord[$idx++] = $yt;
} }
} }
else { else {
if( is_numeric($tmp1) && (is_numeric($prev) || $prev === '-' ) ) { if( is_numeric($tmp1) && (is_numeric($prev) || $prev === '-' ) ) {
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
$cord[$idx++] = $yt; $cord[$idx++] = $yt;
} }
} }
} }
$yt_old = $yt; $yt_old = $yt;
$xt_old = $xt; $xt_old = $xt;
$y_old = $y; $y_old = $y;
   
$this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt); $this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt);
   
++$pnts; ++$pnts;
} }
   
if( $this->filled ) { if( $this->filled ) {
$cord[$idx++] = $xt; $cord[$idx++] = $xt;
if( $this->fillFromMax ) { if( $this->fillFromMax ) {
$cord[$idx++] = $yscale->scale_abs[1]; $cord[$idx++] = $yscale->scale_abs[1];
} }
else { else {
if( $min > 0 || $this->fillFromMin ) { if( $min > 0 || $this->fillFromMin ) {
$cord[$idx++] = $yscale->Translate($min); $cord[$idx++] = $yscale->Translate($min);
} }
else { else {
$cord[$idx++] = $yscale->Translate(0); $cord[$idx++] = $yscale->Translate(0);
} }
} }
if( $this->fillgrad ) { if( $this->fillgrad ) {
$img->SetLineWeight(1); $img->SetLineWeight(1);
$grad = new Gradient($img); $grad = new Gradient($img);
$grad->SetNumColors($this->fillgrad_numcolors); $grad->SetNumColors($this->fillgrad_numcolors);
$grad->FilledFlatPolygon($cord,$this->fillgrad_fromcolor,$this->fillgrad_tocolor); $grad->FilledFlatPolygon($cord,$this->fillgrad_fromcolor,$this->fillgrad_tocolor);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
} }
else { else {
$img->SetColor($this->fill_color); $img->SetColor($this->fill_color);
$img->FilledPolygon($cord); $img->FilledPolygon($cord);
} }
if( $this->weight > 0 ) { if( $this->weight > 0 ) {
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$img->SetColor($this->color); $img->SetColor($this->color);
// Remove first and last coordinate before drawing the line // Remove first and last coordinate before drawing the line
// sine we otherwise get the vertical start and end lines which // sine we otherwise get the vertical start and end lines which
// doesn't look appropriate // doesn't look appropriate
$img->Polygon(array_slice( array_slice($cord,2), count($cord)-4 )); $img->Polygon(array_slice( array_slice($cord,2), count($cord)-4 ));
} }
} }
   
if(!empty($this->filledAreas)) { if(!empty($this->filledAreas)) {
   
$minY = $yscale->Translate($yscale->GetMinVal()); $minY = $yscale->Translate($yscale->GetMinVal());
$factor = ($this->step_style ? 4 : 2); $factor = ($this->step_style ? 4 : 2);
   
for($i = 0; $i < sizeof($this->filledAreas); ++$i) { for($i = 0; $i < sizeof($this->filledAreas); ++$i) {
// go through all filled area elements ordered by insertion // go through all filled area elements ordered by insertion
// fill polygon array // fill polygon array
$areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor]; $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor];
$areaCoords[] = $minY; $areaCoords[] = $minY;
   
$areaCoords = $areaCoords =
array_merge($areaCoords, array_merge($areaCoords,
array_slice($cord, array_slice($cord,
$this->filledAreas[$i][0] * $factor, $this->filledAreas[$i][0] * $factor,
($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1)) * $factor)); ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1)) * $factor));
$areaCoords[] = $areaCoords[sizeof($areaCoords)-2]; // last x $areaCoords[] = $areaCoords[sizeof($areaCoords)-2]; // last x
$areaCoords[] = $minY; // last y $areaCoords[] = $minY; // last y
   
if($this->filledAreas[$i][3]) { if($this->filledAreas[$i][3]) {
$img->SetColor($this->filledAreas[$i][2]); $img->SetColor($this->filledAreas[$i][2]);
$img->FilledPolygon($areaCoords); $img->FilledPolygon($areaCoords);
$img->SetColor($this->color); $img->SetColor($this->color);
} }
// Check if we should draw the frame. // Check if we should draw the frame.
// If not we still re-draw the line since it might have been // If not we still re-draw the line since it might have been
// partially overwritten by the filled area and it doesn't look // partially overwritten by the filled area and it doesn't look
// very good. // very good.
if( $this->filledAreas[$i][4] ) { if( $this->filledAreas[$i][4] ) {
$img->Polygon($areaCoords); $img->Polygon($areaCoords);
} }
else { else {
$img->Polygon($cord); $img->Polygon($cord);
} }
   
$areaCoords = array(); $areaCoords = array();
} }
} }
   
if( $this->mark->type == -1 || $this->mark->show == false ) if( $this->mark->type == -1 || $this->mark->show == false )
return; return;
   
for( $pnts=0; $pnts<$numpoints; ++$pnts) { for( $pnts=0; $pnts<$numpoints; ++$pnts) {
   
if( $exist_x ) { if( $exist_x ) {
$x=$this->coords[1][$pnts]; $x=$this->coords[1][$pnts];
} }
else { else {
$x=$pnts+$textadj; $x=$pnts+$textadj;
} }
$xt = $xscale->Translate($x); $xt = $xscale->Translate($x);
$yt = $yscale->Translate($this->coords[0][$pnts]); $yt = $yscale->Translate($this->coords[0][$pnts]);
   
if( is_numeric($this->coords[0][$pnts]) ) { if( is_numeric($this->coords[0][$pnts]) ) {
if( !empty($this->csimtargets[$pnts]) ) { if( !empty($this->csimtargets[$pnts]) ) {
if( !empty($this->csimwintargets[$pnts]) ) { if( !empty($this->csimwintargets[$pnts]) ) {
$this->mark->SetCSIMTarget($this->csimtargets[$pnts],$this->csimwintargets[$pnts]); $this->mark->SetCSIMTarget($this->csimtargets[$pnts],$this->csimwintargets[$pnts]);
} }
else { else {
$this->mark->SetCSIMTarget($this->csimtargets[$pnts]); $this->mark->SetCSIMTarget($this->csimtargets[$pnts]);
} }
$this->mark->SetCSIMAlt($this->csimalts[$pnts]); $this->mark->SetCSIMAlt($this->csimalts[$pnts]);
} }
if( $exist_x ) { if( $exist_x ) {
$x=$this->coords[1][$pnts]; $x=$this->coords[1][$pnts];
} }
else { else {
$x=$pnts; $x=$pnts;
} }
$this->mark->SetCSIMAltVal($this->coords[0][$pnts],$x); $this->mark->SetCSIMAltVal($this->coords[0][$pnts],$x);
$this->mark->Stroke($img,$xt,$yt); $this->mark->Stroke($img,$xt,$yt);
$this->csimareas .= $this->mark->GetCSIMAreas(); $this->csimareas .= $this->mark->GetCSIMAreas();
} }
} }
} }
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS AccLinePlot // CLASS AccLinePlot
// Description: // Description:
//=================================================== //===================================================
class AccLinePlot extends Plot { class AccLinePlot extends Plot {
protected $plots=null,$nbrplots=0; protected $plots=null,$nbrplots=0;
private $iStartEndZero=true; private $iStartEndZero=true;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($plots) { function __construct($plots) {
$this->plots = $plots; $this->plots = $plots;
$this->nbrplots = count($plots); $this->nbrplots = count($plots);
$this->numpoints = $plots[0]->numpoints; $this->numpoints = $plots[0]->numpoints;
   
// Verify that all plots have the same number of data points // Verify that all plots have the same number of data points
for( $i=1; $i < $this->nbrplots; ++$i ) { for( $i=1; $i < $this->nbrplots; ++$i ) {
if( $plots[$i]->numpoints != $this->numpoints ) { if( $plots[$i]->numpoints != $this->numpoints ) {
JpGraphError::RaiseL(10003);//('Each plot in an accumulated lineplot must have the same number of data points',0) 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 ) { for($i=0; $i < $this->nbrplots; ++$i ) {
$this->LineInterpolate($this->plots[$i]->coords[0]); $this->LineInterpolate($this->plots[$i]->coords[0]);
} }
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Legend($graph) { function Legend($graph) {
foreach( $this->plots as $p ) { foreach( $this->plots as $p ) {
$p->DoLegend($graph); $p->DoLegend($graph);
} }
} }
   
function Max() { function Max() {
list($xmax) = $this->plots[0]->Max(); list($xmax) = $this->plots[0]->Max();
$nmax=0; $nmax=0;
$n = count($this->plots); $n = count($this->plots);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$nc = count($this->plots[$i]->coords[0]); $nc = count($this->plots[$i]->coords[0]);
$nmax = max($nmax,$nc); $nmax = max($nmax,$nc);
list($x) = $this->plots[$i]->Max(); list($x) = $this->plots[$i]->Max();
$xmax = Max($xmax,$x); $xmax = Max($xmax,$x);
} }
for( $i = 0; $i < $nmax; $i++ ) { for( $i = 0; $i < $nmax; $i++ ) {
// Get y-value for line $i by adding the // Get y-value for line $i by adding the
// individual bars from all the plots added. // individual bars from all the plots added.
// It would be wrong to just add the // It would be wrong to just add the
// individual plots max y-value since that // individual plots max y-value since that
// would in most cases give to large y-value. // would in most cases give to large y-value.
$y=$this->plots[0]->coords[0][$i]; $y=$this->plots[0]->coords[0][$i];
for( $j = 1; $j < $this->nbrplots; $j++ ) { for( $j = 1; $j < $this->nbrplots; $j++ ) {
$y += $this->plots[ $j ]->coords[0][$i]; $y += $this->plots[ $j ]->coords[0][$i];
} }
$ymax[$i] = $y; $ymax[$i] = $y;
} }
$ymax = max($ymax); $ymax = max($ymax);
return array($xmax,$ymax); return array($xmax,$ymax);
} }
   
function Min() { function Min() {
$nmax=0; $nmax=0;
list($xmin,$ysetmin) = $this->plots[0]->Min(); list($xmin,$ysetmin) = $this->plots[0]->Min();
$n = count($this->plots); $n = count($this->plots);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$nc = count($this->plots[$i]->coords[0]); $nc = count($this->plots[$i]->coords[0]);
$nmax = max($nmax,$nc); $nmax = max($nmax,$nc);
list($x,$y) = $this->plots[$i]->Min(); list($x,$y) = $this->plots[$i]->Min();
$xmin = Min($xmin,$x); $xmin = Min($xmin,$x);
$ysetmin = Min($y,$ysetmin); $ysetmin = Min($y,$ysetmin);
} }
for( $i = 0; $i < $nmax; $i++ ) { for( $i = 0; $i < $nmax; $i++ ) {
// Get y-value for line $i by adding the // Get y-value for line $i by adding the
// individual bars from all the plots added. // individual bars from all the plots added.
// It would be wrong to just add the // It would be wrong to just add the
// individual plots min y-value since that // individual plots min y-value since that
// would in most cases give to small y-value. // would in most cases give to small y-value.
$y=$this->plots[0]->coords[0][$i]; $y=$this->plots[0]->coords[0][$i];
for( $j = 1; $j < $this->nbrplots; $j++ ) { for( $j = 1; $j < $this->nbrplots; $j++ ) {
$y += $this->plots[ $j ]->coords[0][$i]; $y += $this->plots[ $j ]->coords[0][$i];
} }
$ymin[$i] = $y; $ymin[$i] = $y;
} }
$ymin = Min($ysetmin,Min($ymin)); $ymin = Min($ysetmin,Min($ymin));
return array($xmin,$ymin); return array($xmin,$ymin);
} }
   
// Gets called before any axis are stroked // Gets called before any axis are stroked
function PreStrokeAdjust($graph) { function PreStrokeAdjust($graph) {
   
// If another plot type have already adjusted the // If another plot type have already adjusted the
// offset we don't touch it. // offset we don't touch it.
// (We check for empty in case the scale is a log scale // (We check for empty in case the scale is a log scale
// and hence doesn't contain any xlabel_offset) // and hence doesn't contain any xlabel_offset)
   
if( empty($graph->xaxis->scale->ticks->xlabel_offset) || if( empty($graph->xaxis->scale->ticks->xlabel_offset) ||
$graph->xaxis->scale->ticks->xlabel_offset == 0 ) { $graph->xaxis->scale->ticks->xlabel_offset == 0 ) {
if( $this->center ) { if( $this->center ) {
++$this->numpoints; ++$this->numpoints;
$a=0.5; $b=0.5; $a=0.5; $b=0.5;
} else { } else {
$a=0; $b=0; $a=0; $b=0;
} }
$graph->xaxis->scale->ticks->SetXLabelOffset($a); $graph->xaxis->scale->ticks->SetXLabelOffset($a);
$graph->SetTextScaleOff($b); $graph->SetTextScaleOff($b);
$graph->xaxis->scale->ticks->SupressMinorTickMarks(); $graph->xaxis->scale->ticks->SupressMinorTickMarks();
} }
   
} }
   
function SetInterpolateMode($aIntMode) { function SetInterpolateMode($aIntMode) {
$this->iStartEndZero=$aIntMode; $this->iStartEndZero=$aIntMode;
} }
   
// Replace all '-' with an interpolated value. We use straightforward // Replace all '-' with an interpolated value. We use straightforward
// linear interpolation. If the data starts with one or several '-' they // linear interpolation. If the data starts with one or several '-' they
// will be replaced by the the first valid data point // will be replaced by the the first valid data point
function LineInterpolate(&$aData) { function LineInterpolate(&$aData) {
   
$n=count($aData); $n=count($aData);
$i=0; $i=0;
   
// If first point is undefined we will set it to the same as the first // If first point is undefined we will set it to the same as the first
// valid data // valid data
if( $aData[$i]==='-' ) { if( $aData[$i]==='-' ) {
// Find the first valid data // Find the first valid data
while( $i < $n && $aData[$i]==='-' ) { while( $i < $n && $aData[$i]==='-' ) {
++$i; ++$i;
} }
if( $i < $n ) { if( $i < $n ) {
for($j=0; $j < $i; ++$j ) { for($j=0; $j < $i; ++$j ) {
if( $this->iStartEndZero ) if( $this->iStartEndZero )
$aData[$i] = 0; $aData[$i] = 0;
else else
$aData[$j] = $aData[$i]; $aData[$j] = $aData[$i];
} }
} }
else { else {
// All '-' => Error // All '-' => Error
return false; return false;
} }
} }
   
while($i < $n) { while($i < $n) {
while( $i < $n && $aData[$i] !== '-' ) { while( $i < $n && $aData[$i] !== '-' ) {
++$i; ++$i;
} }
if( $i < $n ) { if( $i < $n ) {
$pstart=$i-1; $pstart=$i-1;
   
// Now see how long this segment of '-' are // Now see how long this segment of '-' are
while( $i < $n && $aData[$i] === '-' ) { while( $i < $n && $aData[$i] === '-' ) {
++$i; ++$i;
} }
if( $i < $n ) { if( $i < $n ) {
$pend=$i; $pend=$i;
$size=$pend-$pstart; $size=$pend-$pstart;
$k=($aData[$pend]-$aData[$pstart])/$size; $k=($aData[$pend]-$aData[$pstart])/$size;
// Replace the segment of '-' with a linear interpolated value. // Replace the segment of '-' with a linear interpolated value.
for($j=1; $j < $size; ++$j ) { for($j=1; $j < $size; ++$j ) {
$aData[$pstart+$j] = $aData[$pstart] + $j*$k ; $aData[$pstart+$j] = $aData[$pstart] + $j*$k ;
} }
} }
else { else {
// There are no valid end point. The '-' goes all the way to the end // 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 // In that case we just set all the remaining values the the same as the
// last valid data point. // last valid data point.
for( $j=$pstart+1; $j < $n; ++$j ) for( $j=$pstart+1; $j < $n; ++$j )
if( $this->iStartEndZero ) { if( $this->iStartEndZero ) {
$aData[$j] = 0; $aData[$j] = 0;
} }
else { else {
$aData[$j] = $aData[$pstart] ; $aData[$j] = $aData[$pstart] ;
} }
} }
} }
} }
return true; return true;
} }
   
// To avoid duplicate of line drawing code here we just // To avoid duplicate of line drawing code here we just
// change the y-values for each plot and then restore it // change the y-values for each plot and then restore it
// after we have made the stroke. We must do this copy since // after we have made the stroke. We must do this copy since
// it wouldn't be possible to create an acc line plot // it wouldn't be possible to create an acc line plot
// with the same graphs, i.e AccLinePlot(array($pl,$pl,$pl)); // with the same graphs, i.e AccLinePlot(array($pl,$pl,$pl));
// since this method would have a side effect. // since this method would have a side effect.
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$this->numpoints = count($this->plots[0]->coords[0]); $this->numpoints = count($this->plots[0]->coords[0]);
// Allocate array // Allocate array
$coords[$this->nbrplots][$this->numpoints]=0; $coords[$this->nbrplots][$this->numpoints]=0;
for($i=0; $i<$this->numpoints; $i++) { for($i=0; $i<$this->numpoints; $i++) {
$coords[0][$i]=$this->plots[0]->coords[0][$i]; $coords[0][$i]=$this->plots[0]->coords[0][$i];
$accy=$coords[0][$i]; $accy=$coords[0][$i];
for($j=1; $j<$this->nbrplots; ++$j ) { for($j=1; $j<$this->nbrplots; ++$j ) {
$coords[$j][$i] = $this->plots[$j]->coords[0][$i]+$accy; $coords[$j][$i] = $this->plots[$j]->coords[0][$i]+$accy;
$accy = $coords[$j][$i]; $accy = $coords[$j][$i];
} }
} }
for($j=$this->nbrplots-1; $j>=0; --$j) { for($j=$this->nbrplots-1; $j>=0; --$j) {
$p=$this->plots[$j]; $p=$this->plots[$j];
for( $i=0; $i<$this->numpoints; ++$i) { for( $i=0; $i<$this->numpoints; ++$i) {
$tmp[$i]=$p->coords[0][$i]; $tmp[$i]=$p->coords[0][$i];
$p->coords[0][$i]=$coords[$j][$i]; $p->coords[0][$i]=$coords[$j][$i];
} }
$p->Stroke($img,$xscale,$yscale); $p->Stroke($img,$xscale,$yscale);
for( $i=0; $i<$this->numpoints; ++$i) { for( $i=0; $i<$this->numpoints; ++$i) {
$p->coords[0][$i]=$tmp[$i]; $p->coords[0][$i]=$tmp[$i];
} }
$p->coords[0][]=$tmp; $p->coords[0][]=$tmp;
} }
} }
} // Class } // Class
   
   
/* EOF */ /* EOF */
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_LOG.PHP // File: JPGRAPH_LOG.PHP
// Description: Log scale plot extension for JpGraph // Description: Log scale plot extension for JpGraph
// Created: 2001-01-08 // Created: 2001-01-08
// Ver: $Id: jpgraph_log.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_log.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
DEFINE('LOGLABELS_PLAIN',0); DEFINE('LOGLABELS_PLAIN',0);
DEFINE('LOGLABELS_MAGNITUDE',1); DEFINE('LOGLABELS_MAGNITUDE',1);
   
//=================================================== //===================================================
// CLASS LogScale // CLASS LogScale
// Description: Logarithmic scale between world and screen // Description: Logarithmic scale between world and screen
//=================================================== //===================================================
class LogScale extends LinearScale { class LogScale extends LinearScale {
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
   
// Log scale is specified using the log of min and max // Log scale is specified using the log of min and max
function __construct($min,$max,$type="y") { function __construct($min,$max,$type="y") {
parent::__construct($min,$max,$type); parent::__construct($min,$max,$type);
$this->ticks = new LogTicks(); $this->ticks = new LogTicks();
$this->name = 'log'; $this->name = 'log';
} }
   
//---------------- //----------------
// PUBLIC METHODS // PUBLIC METHODS
   
// Translate between world and screen // Translate between world and screen
function Translate($a) { function Translate($a) {
if( !is_numeric($a) ) { if( !is_numeric($a) ) {
if( $a != '' && $a != '-' && $a != 'x' ) { if( $a != '' && $a != '-' && $a != 'x' ) {
JpGraphError::RaiseL(11001); JpGraphError::RaiseL(11001);
// ('Your data contains non-numeric values.'); // ('Your data contains non-numeric values.');
} }
return 1; return 1;
} }
if( $a < 0 ) { if( $a < 0 ) {
JpGraphError::RaiseL(11002); JpGraphError::RaiseL(11002);
//("Negative data values can not be used in a log scale."); //("Negative data values can not be used in a log scale.");
exit(1); exit(1);
} }
if( $a==0 ) $a=1; if( $a==0 ) $a=1;
$a=log10($a); $a=log10($a);
return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor); return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);
} }
   
// Relative translate (don't include offset) usefull when we just want // Relative translate (don't include offset) usefull when we just want
// to know the relative position (in pixels) on the axis // to know the relative position (in pixels) on the axis
function RelTranslate($a) { function RelTranslate($a) {
if( !is_numeric($a) ) { if( !is_numeric($a) ) {
if( $a != '' && $a != '-' && $a != 'x' ) { if( $a != '' && $a != '-' && $a != 'x' ) {
JpGraphError::RaiseL(11001); JpGraphError::RaiseL(11001);
//('Your data contains non-numeric values.'); //('Your data contains non-numeric values.');
} }
return 1; return 1;
} }
if( $a==0 ) { if( $a==0 ) {
$a=1; $a=1;
} }
$a=log10($a); $a=log10($a);
return round(($a*1.0 - $this->scale[0]) * $this->scale_factor); return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);
} }
   
// Use bcpow() for increased precision // Use bcpow() for increased precision
function GetMinVal() { function GetMinVal() {
if( function_exists("bcpow") ) { if( function_exists("bcpow") ) {
return round(bcpow(10,$this->scale[0],15),14); return round(bcpow(10,$this->scale[0],15),14);
} }
else { else {
return round(pow(10,$this->scale[0]),14); return round(pow(10,$this->scale[0]),14);
} }
} }
   
function GetMaxVal() { function GetMaxVal() {
if( function_exists("bcpow") ) { if( function_exists("bcpow") ) {
return round(bcpow(10,$this->scale[1],15),14); return round(bcpow(10,$this->scale[1],15),14);
} }
else { else {
return round(pow(10,$this->scale[1]),14); return round(pow(10,$this->scale[1]),14);
} }
} }
   
// Logarithmic autoscaling is much simplier since we just // Logarithmic autoscaling is much simplier since we just
// set the min and max to logs of the min and max values. // set the min and max to logs of the min and max values.
// Note that for log autoscale the "maxstep" the fourth argument // Note that for log autoscale the "maxstep" the fourth argument
// isn't used. This is just included to give the method the same // isn't used. This is just included to give the method the same
// signature as the linear counterpart. // signature as the linear counterpart.
function AutoScale($img,$min,$max,$maxsteps,$majend=true) { function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
if( $min==0 ) $min=1; if( $min==0 ) $min=1;
   
if( $max <= 0 ) { if( $max <= 0 ) {
JpGraphError::RaiseL(11004); 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.'); //('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) ) { if( is_numeric($this->autoscale_min) ) {
$smin = round($this->autoscale_min); $smin = round($this->autoscale_min);
$smax = ceil(log10($max)); $smax = ceil(log10($max));
if( $min >= $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.'); 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 { else {
$smin = floor(log10($min)); $smin = floor(log10($min));
if( is_numeric($this->autoscale_max) ) { if( is_numeric($this->autoscale_max) ) {
$smax = round($this->autoscale_max); $smax = round($this->autoscale_max);
if( $smin >= $smax ) { 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.'); 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 else
$smax = ceil(log10($max)); $smax = ceil(log10($max));
} }
   
$this->Update($img,$smin,$smax); $this->Update($img,$smin,$smax);
} }
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
} // Class } // Class
   
//=================================================== //===================================================
// CLASS LogTicks // CLASS LogTicks
// Description: // Description:
//=================================================== //===================================================
class LogTicks extends Ticks{ class LogTicks extends Ticks{
private $label_logtype=LOGLABELS_MAGNITUDE; private $label_logtype=LOGLABELS_MAGNITUDE;
private $ticklabels_pos = array(); private $ticklabels_pos = array();
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function LogTicks() { function LogTicks() {
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function IsSpecified() { function IsSpecified() {
return true; return true;
} }
   
function SetLabelLogType($aType) { function SetLabelLogType($aType) {
$this->label_logtype = $aType; $this->label_logtype = $aType;
} }
   
// For log scale it's meaningless to speak about a major step // For log scale it's meaningless to speak about a major step
// We just return -1 to make the framework happy (specifically // We just return -1 to make the framework happy (specifically
// StrokeLabels() ) // StrokeLabels() )
function GetMajor() { function GetMajor() {
return -1; return -1;
} }
   
function SetTextLabelStart($aStart) { function SetTextLabelStart($aStart) {
JpGraphError::RaiseL(11005); JpGraphError::RaiseL(11005);
//('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.'); //('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');
} }
   
function SetXLabelOffset($dummy) { function SetXLabelOffset($dummy) {
// For log scales we dont care about XLabel offset // For log scales we dont care about XLabel offset
} }
   
// Draw ticks on image "img" using scale "scale". The axis absolute // 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 // 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 // it specifies the absolute y-coord and for Y-ticks it specified the
// absolute x-position. // absolute x-position.
function Stroke($img,$scale,$pos) { function Stroke($img,$scale,$pos) {
$start = $scale->GetMinVal(); $start = $scale->GetMinVal();
$limit = $scale->GetMaxVal(); $limit = $scale->GetMaxVal();
$nextMajor = 10*$start; $nextMajor = 10*$start;
$step = $nextMajor / 10.0; $step = $nextMajor / 10.0;
   
   
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
   
if( $scale->type == "y" ) { if( $scale->type == "y" ) {
// member direction specified if the ticks should be on // member direction specified if the ticks should be on
// left or right side. // left or right side.
$a=$pos + $this->direction*$this->GetMinTickAbsSize(); $a=$pos + $this->direction*$this->GetMinTickAbsSize();
$a2=$pos + $this->direction*$this->GetMajTickAbsSize(); $a2=$pos + $this->direction*$this->GetMajTickAbsSize();
$count=1; $count=1;
$this->maj_ticks_pos[0]=$scale->Translate($start); $this->maj_ticks_pos[0]=$scale->Translate($start);
$this->maj_ticklabels_pos[0]=$scale->Translate($start); $this->maj_ticklabels_pos[0]=$scale->Translate($start);
if( $this->supress_first ) if( $this->supress_first )
$this->maj_ticks_label[0]=""; $this->maj_ticks_label[0]="";
else { else {
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f = $this->label_formfunc; $f = $this->label_formfunc;
$this->maj_ticks_label[0]=call_user_func($f,$start); $this->maj_ticks_label[0]=call_user_func($f,$start);
} }
elseif( $this->label_logtype == LOGLABELS_PLAIN ) { elseif( $this->label_logtype == LOGLABELS_PLAIN ) {
$this->maj_ticks_label[0]=$start; $this->maj_ticks_label[0]=$start;
} }
else { else {
$this->maj_ticks_label[0]='10^'.round(log10($start)); $this->maj_ticks_label[0]='10^'.round(log10($start));
} }
} }
$i=1; $i=1;
for($y=$start; $y<=$limit; $y+=$step,++$count ) { for($y=$start; $y<=$limit; $y+=$step,++$count ) {
$ys=$scale->Translate($y); $ys=$scale->Translate($y);
$this->ticks_pos[]=$ys; $this->ticks_pos[]=$ys;
$this->ticklabels_pos[]=$ys; $this->ticklabels_pos[]=$ys;
if( $count % 10 == 0 ) { if( $count % 10 == 0 ) {
if( !$this->supress_tickmarks ) { if( !$this->supress_tickmarks ) {
if( $this->majcolor!="" ) { if( $this->majcolor!="" ) {
$img->PushColor($this->majcolor); $img->PushColor($this->majcolor);
$img->Line($pos,$ys,$a2,$ys); $img->Line($pos,$ys,$a2,$ys);
$img->PopColor(); $img->PopColor();
} }
else { else {
$img->Line($pos,$ys,$a2,$ys); $img->Line($pos,$ys,$a2,$ys);
} }
} }
   
$this->maj_ticks_pos[$i]=$ys; $this->maj_ticks_pos[$i]=$ys;
$this->maj_ticklabels_pos[$i]=$ys; $this->maj_ticklabels_pos[$i]=$ys;
   
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f = $this->label_formfunc; $f = $this->label_formfunc;
$this->maj_ticks_label[$i]=call_user_func($f,$nextMajor); $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
} }
elseif( $this->label_logtype == 0 ) { elseif( $this->label_logtype == 0 ) {
$this->maj_ticks_label[$i]=$nextMajor; $this->maj_ticks_label[$i]=$nextMajor;
} }
else { else {
$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor)); $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
} }
++$i; ++$i;
$nextMajor *= 10; $nextMajor *= 10;
$step *= 10; $step *= 10;
$count=1; $count=1;
} }
else { else {
if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
if( $this->mincolor!="" ) { if( $this->mincolor!="" ) {
$img->PushColor($this->mincolor); $img->PushColor($this->mincolor);
} }
$img->Line($pos,$ys,$a,$ys); $img->Line($pos,$ys,$a,$ys);
if( $this->mincolor!="" ) { if( $this->mincolor!="" ) {
$img->PopColor(); $img->PopColor();
} }
} }
} }
} }
} }
else { else {
$a=$pos - $this->direction*$this->GetMinTickAbsSize(); $a=$pos - $this->direction*$this->GetMinTickAbsSize();
$a2=$pos - $this->direction*$this->GetMajTickAbsSize(); $a2=$pos - $this->direction*$this->GetMajTickAbsSize();
$count=1; $count=1;
$this->maj_ticks_pos[0]=$scale->Translate($start); $this->maj_ticks_pos[0]=$scale->Translate($start);
$this->maj_ticklabels_pos[0]=$scale->Translate($start); $this->maj_ticklabels_pos[0]=$scale->Translate($start);
if( $this->supress_first ) { if( $this->supress_first ) {
$this->maj_ticks_label[0]=""; $this->maj_ticks_label[0]="";
} }
else { else {
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f = $this->label_formfunc; $f = $this->label_formfunc;
$this->maj_ticks_label[0]=call_user_func($f,$start); $this->maj_ticks_label[0]=call_user_func($f,$start);
} }
elseif( $this->label_logtype == 0 ) { elseif( $this->label_logtype == 0 ) {
$this->maj_ticks_label[0]=$start; $this->maj_ticks_label[0]=$start;
} }
else { else {
$this->maj_ticks_label[0]='10^'.round(log10($start)); $this->maj_ticks_label[0]='10^'.round(log10($start));
} }
} }
$i=1; $i=1;
for($x=$start; $x<=$limit; $x+=$step,++$count ) { for($x=$start; $x<=$limit; $x+=$step,++$count ) {
$xs=$scale->Translate($x); $xs=$scale->Translate($x);
$this->ticks_pos[]=$xs; $this->ticks_pos[]=$xs;
$this->ticklabels_pos[]=$xs; $this->ticklabels_pos[]=$xs;
if( $count % 10 == 0 ) { if( $count % 10 == 0 ) {
if( !$this->supress_tickmarks ) { if( !$this->supress_tickmarks ) {
$img->Line($xs,$pos,$xs,$a2); $img->Line($xs,$pos,$xs,$a2);
} }
$this->maj_ticks_pos[$i]=$xs; $this->maj_ticks_pos[$i]=$xs;
$this->maj_ticklabels_pos[$i]=$xs; $this->maj_ticklabels_pos[$i]=$xs;
   
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f = $this->label_formfunc; $f = $this->label_formfunc;
$this->maj_ticks_label[$i]=call_user_func($f,$nextMajor); $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
} }
elseif( $this->label_logtype == 0 ) { elseif( $this->label_logtype == 0 ) {
$this->maj_ticks_label[$i]=$nextMajor; $this->maj_ticks_label[$i]=$nextMajor;
} }
else { else {
$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor)); $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
} }
++$i; ++$i;
$nextMajor *= 10; $nextMajor *= 10;
$step *= 10; $step *= 10;
$count=1; $count=1;
} }
else { else {
if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
$img->Line($xs,$pos,$xs,$a); $img->Line($xs,$pos,$xs,$a);
} }
} }
} }
} }
return true; return true;
} }
} // Class } // Class
/* EOF */ /* EOF */
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_MESHINTERPOLATE.INC.PHP // File: JPGRAPH_MESHINTERPOLATE.INC.PHP
// Description: Utility class to do mesh linear interpolation of a matrix // Description: Utility class to do mesh linear interpolation of a matrix
// Created: 2009-03-09 // Created: 2009-03-09
// Ver: $Id: jpgraph_meshinterpolate.inc.php 1709 2009-07-30 08:00:08Z ljp $ // Ver: $Id: jpgraph_meshinterpolate.inc.php 1709 2009-07-30 08:00:08Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
/** /**
* Utility function to do linear mesh interpolation * Utility function to do linear mesh interpolation
* @param $aDat Matrix to interpolate * @param $aDat Matrix to interpolate
* @param $aFactor Interpolation factor * @param $aFactor Interpolation factor
*/ */
function doMeshInterpolate( &$aData, $aFactor ) { function doMeshInterpolate( &$aData, $aFactor ) {
$m = new MeshInterpolate(); $m = new MeshInterpolate();
$aData = $m->Linear($aData,$aFactor); $aData = $m->Linear($aData,$aFactor);
} }
   
/** /**
* Utility class to interpolate a given data matrix * Utility class to interpolate a given data matrix
* *
*/ */
class MeshInterpolate { class MeshInterpolate {
private $data = array(); private $data = array();
   
/** /**
* Calculate the mid points of the given rectangle which has its top left * 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. * corner at $row,$col. The $aFactordecides how many spliots should be done.
* i.e. how many more divisions should be done recursively * i.e. how many more divisions should be done recursively
* *
* @param $row Top left corner of square to work with * @param $row Top left corner of square to work with
* @param $col 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 * $param $aFactor In how many subsquare should we split this square. A value of 1 indicates that no action
*/ */
function IntSquare( $aRow, $aCol, $aFactor ) { function IntSquare( $aRow, $aCol, $aFactor ) {
if ( $aFactor <= 1 ) if ( $aFactor <= 1 )
return; return;
   
$step = pow( 2, $aFactor-1 ); $step = pow( 2, $aFactor-1 );
   
$v0 = $this->data[$aRow][$aCol]; $v0 = $this->data[$aRow][$aCol];
$v1 = $this->data[$aRow][$aCol + $step]; $v1 = $this->data[$aRow][$aCol + $step];
$v2 = $this->data[$aRow + $step][$aCol]; $v2 = $this->data[$aRow + $step][$aCol];
$v3 = $this->data[$aRow + $step][$aCol + $step]; $v3 = $this->data[$aRow + $step][$aCol + $step];
   
$this->data[$aRow][$aCol + $step / 2] = ( $v0 + $v1 ) / 2; $this->data[$aRow][$aCol + $step / 2] = ( $v0 + $v1 ) / 2;
$this->data[$aRow + $step / 2][$aCol] = ( $v0 + $v2 ) / 2; $this->data[$aRow + $step / 2][$aCol] = ( $v0 + $v2 ) / 2;
$this->data[$aRow + $step][$aCol + $step / 2] = ( $v2 + $v3 ) / 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] = ( $v1 + $v3 ) / 2;
$this->data[$aRow + $step / 2][$aCol + $step / 2] = ( $v0 + $v1 + $v2 + $v3 ) / 4; $this->data[$aRow + $step / 2][$aCol + $step / 2] = ( $v0 + $v1 + $v2 + $v3 ) / 4;
   
$this->IntSquare( $aRow, $aCol, $aFactor-1 ); $this->IntSquare( $aRow, $aCol, $aFactor-1 );
$this->IntSquare( $aRow, $aCol + $step / 2, $aFactor-1 ); $this->IntSquare( $aRow, $aCol + $step / 2, $aFactor-1 );
$this->IntSquare( $aRow + $step / 2, $aCol, $aFactor-1 ); $this->IntSquare( $aRow + $step / 2, $aCol, $aFactor-1 );
$this->IntSquare( $aRow + $step / 2, $aCol + $step / 2, $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 * 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 * 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. * 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 * Note: This will blow up the matrcide in memory size in the order of $aInNbr^2
* *
* @param $ &$aData The original data matricde * @param $ &$aData The original data matricde
* @param $aInNbr Interpolation factor * @param $aInNbr Interpolation factor
* @return the interpolated matrice * @return the interpolated matrice
*/ */
function Linear( &$aData, $aIntFactor ) { function Linear( &$aData, $aIntFactor ) {
$step = pow( 2, $aIntFactor-1 ); $step = pow( 2, $aIntFactor-1 );
   
$orig_cols = count( $aData[0] ); $orig_cols = count( $aData[0] );
$orig_rows = count( $aData ); $orig_rows = count( $aData );
// Number of new columns/rows // Number of new columns/rows
// N = (a-1) * 2^(f-1) + 1 // N = (a-1) * 2^(f-1) + 1
$p = pow( 2, $aIntFactor-1 ); $p = pow( 2, $aIntFactor-1 );
$new_cols = $p * ( $orig_cols - 1 ) + 1; $new_cols = $p * ( $orig_cols - 1 ) + 1;
$new_rows = $p * ( $orig_rows - 1 ) + 1; $new_rows = $p * ( $orig_rows - 1 ) + 1;
   
$this->data = array_fill( 0, $new_rows, array_fill( 0, $new_cols, 0 ) ); $this->data = array_fill( 0, $new_rows, array_fill( 0, $new_cols, 0 ) );
// Initialize the new matrix with the values that we know // Initialize the new matrix with the values that we know
for ( $i = 0; $i < $new_rows; $i++ ) { for ( $i = 0; $i < $new_rows; $i++ ) {
for ( $j = 0; $j < $new_cols; $j++ ) { for ( $j = 0; $j < $new_cols; $j++ ) {
$v = 0 ; $v = 0 ;
if ( ( $i % $step == 0 ) && ( $j % $step == 0 ) ) { if ( ( $i % $step == 0 ) && ( $j % $step == 0 ) ) {
$v = $aData[$i / $step][$j / $step]; $v = $aData[$i / $step][$j / $step];
} }
$this->data[$i][$j] = $v; $this->data[$i][$j] = $v;
} }
} }
   
for ( $i = 0; $i < $new_rows-1; $i += $step ) { for ( $i = 0; $i < $new_rows-1; $i += $step ) {
for ( $j = 0; $j < $new_cols-1; $j += $step ) { for ( $j = 0; $j < $new_cols-1; $j += $step ) {
$this->IntSquare( $i, $j, $aIntFactor ); $this->IntSquare( $i, $j, $aIntFactor );
} }
} }
   
return $this->data; return $this->data;
} }
} }
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_MGRAPH.PHP // File: JPGRAPH_MGRAPH.PHP
// Description: Class to handle multiple graphs in the same image // Description: Class to handle multiple graphs in the same image
// Created: 2006-01-15 // Created: 2006-01-15
// Ver: $Id: jpgraph_mgraph.php 1770 2009-08-17 06:10:22Z ljp $ // Ver: $Id: jpgraph_mgraph.php 1770 2009-08-17 06:10:22Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
//============================================================================= //=============================================================================
// CLASS MGraph // CLASS MGraph
// Description: Create a container image that can hold several graph // Description: Create a container image that can hold several graph
//============================================================================= //=============================================================================
class MGraph { class MGraph {
   
public $title = null, $subtitle = null, $subsubtitle = null; public $title = null, $subtitle = null, $subsubtitle = null;
   
protected $img=NULL; protected $img=NULL;
protected $iCnt=0,$iGraphs = array(); // image_handle, x, y, fx, fy, sizex, sizey protected $iCnt=0,$iGraphs = array(); // image_handle, x, y, fx, fy, sizex, sizey
protected $iFillColor='white', $iCurrentColor=0; protected $iFillColor='white', $iCurrentColor=0;
protected $lm=4,$rm=4,$tm=4,$bm=4; protected $lm=4,$rm=4,$tm=4,$bm=4;
protected $iDoFrame = FALSE, $iFrameColor = 'black', $iFrameWeight = 1; protected $iDoFrame = FALSE, $iFrameColor = 'black', $iFrameWeight = 1;
protected $iLineWeight = 1; protected $iLineWeight = 1;
protected $expired=false; protected $expired=false;
protected $cache=null,$cache_name = '',$inline=true; protected $cache=null,$cache_name = '',$inline=true;
protected $image_format='png',$image_quality=75; protected $image_format='png',$image_quality=75;
protected $iWidth=NULL,$iHeight=NULL; protected $iWidth=NULL,$iHeight=NULL;
protected $background_image='',$background_image_center=true, protected $background_image='',$background_image_center=true,
$backround_image_format='',$background_image_mix=100, $backround_image_format='',$background_image_mix=100,
$background_image_y=NULL, $background_image_x=NULL; $background_image_y=NULL, $background_image_x=NULL;
private $doshadow=false, $shadow_width=4, $shadow_color='gray@0.5'; private $doshadow=false, $shadow_width=4, $shadow_color='gray@0.5';
public $footer; public $footer;
   
   
// Create a new instane of the combined graph // Create a new instane of the combined graph
function __construct($aWidth=NULL,$aHeight=NULL,$aCachedName='',$aTimeOut=0,$aInline=true) { function __construct($aWidth=NULL,$aHeight=NULL,$aCachedName='',$aTimeOut=0,$aInline=true) {
$this->iWidth = $aWidth; $this->iWidth = $aWidth;
$this->iHeight = $aHeight; $this->iHeight = $aHeight;
   
// If the cached version exist just read it directly from the // If the cached version exist just read it directly from the
// cache, stream it back to browser and exit // cache, stream it back to browser and exit
if( $aCachedName!='' && READ_CACHE && $aInline ) { if( $aCachedName!='' && READ_CACHE && $aInline ) {
$this->cache = new ImgStreamCache(); $this->cache = new ImgStreamCache();
$this->cache->SetTimeOut($aTimeOut); $this->cache->SetTimeOut($aTimeOut);
$image = new Image(); $image = new Image();
if( $this->cache->GetAndStream($image,$aCachedName) ) { if( $this->cache->GetAndStream($image,$aCachedName) ) {
exit(); exit();
} }
} }
$this->inline = $aInline; $this->inline = $aInline;
$this->cache_name = $aCachedName; $this->cache_name = $aCachedName;
   
$this->title = new Text(); $this->title = new Text();
$this->title->ParagraphAlign('center'); $this->title->ParagraphAlign('center');
$this->title->SetFont(FF_FONT2,FS_BOLD); $this->title->SetFont(FF_FONT2,FS_BOLD);
$this->title->SetMargin(3); $this->title->SetMargin(3);
$this->title->SetAlign('center'); $this->title->SetAlign('center');
   
$this->subtitle = new Text(); $this->subtitle = new Text();
$this->subtitle->ParagraphAlign('center'); $this->subtitle->ParagraphAlign('center');
$this->subtitle->SetFont(FF_FONT1,FS_BOLD); $this->subtitle->SetFont(FF_FONT1,FS_BOLD);
$this->subtitle->SetMargin(3); $this->subtitle->SetMargin(3);
$this->subtitle->SetAlign('center'); $this->subtitle->SetAlign('center');
   
$this->subsubtitle = new Text(); $this->subsubtitle = new Text();
$this->subsubtitle->ParagraphAlign('center'); $this->subsubtitle->ParagraphAlign('center');
$this->subsubtitle->SetFont(FF_FONT1,FS_NORMAL); $this->subsubtitle->SetFont(FF_FONT1,FS_NORMAL);
$this->subsubtitle->SetMargin(3); $this->subsubtitle->SetMargin(3);
$this->subsubtitle->SetAlign('center'); $this->subsubtitle->SetAlign('center');
   
$this->footer = new Footer(); $this->footer = new Footer();
   
} }
   
// Specify background fill color for the combined graph // Specify background fill color for the combined graph
function SetFillColor($aColor) { function SetFillColor($aColor) {
$this->iFillColor = $aColor; $this->iFillColor = $aColor;
} }
   
// Add a frame around the combined graph // Add a frame around the combined graph
function SetFrame($aFlg,$aColor='black',$aWeight=1) { function SetFrame($aFlg,$aColor='black',$aWeight=1) {
$this->iDoFrame = $aFlg; $this->iDoFrame = $aFlg;
$this->iFrameColor = $aColor; $this->iFrameColor = $aColor;
$this->iFrameWeight = $aWeight; $this->iFrameWeight = $aWeight;
} }
   
// Specify a background image blend // Specify a background image blend
function SetBackgroundImageMix($aMix) { function SetBackgroundImageMix($aMix) {
$this->background_image_mix = $aMix ; $this->background_image_mix = $aMix ;
} }
   
// Specify a background image // Specify a background image
function SetBackgroundImage($aFileName,$aCenter_aX=NULL,$aY=NULL) { function SetBackgroundImage($aFileName,$aCenter_aX=NULL,$aY=NULL) {
// Second argument can be either a boolean value or // Second argument can be either a boolean value or
// a numeric // a numeric
$aCenter=TRUE; $aCenter=TRUE;
$aX=NULL; $aX=NULL;
   
if( is_numeric($aCenter_aX) ) { if( is_numeric($aCenter_aX) ) {
$aX=$aCenter_aX; $aX=$aCenter_aX;
} }
   
// Get extension to determine image type // Get extension to determine image type
$e = explode('.',$aFileName); $e = explode('.',$aFileName);
if( !$e ) { if( !$e ) {
JpGraphError::RaiseL(12002,$aFileName); 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'); //('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'); $valid_formats = array('png', 'jpg', 'gif');
$aImgFormat = strtolower($e[count($e)-1]); $aImgFormat = strtolower($e[count($e)-1]);
if ($aImgFormat == 'jpeg') { if ($aImgFormat == 'jpeg') {
$aImgFormat = 'jpg'; $aImgFormat = 'jpg';
} }
elseif (!in_array($aImgFormat, $valid_formats) ) { elseif (!in_array($aImgFormat, $valid_formats) ) {
JpGraphError::RaiseL(12003,$aImgFormat,$aFileName); JpGraphError::RaiseL(12003,$aImgFormat,$aFileName);
//('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName); //('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName);
} }
   
$this->background_image = $aFileName; $this->background_image = $aFileName;
$this->background_image_center=$aCenter; $this->background_image_center=$aCenter;
$this->background_image_format=$aImgFormat; $this->background_image_format=$aImgFormat;
$this->background_image_x = $aX; $this->background_image_x = $aX;
$this->background_image_y = $aY; $this->background_image_y = $aY;
} }
   
function _strokeBackgroundImage() { function _strokeBackgroundImage() {
if( $this->background_image == '' ) return; if( $this->background_image == '' ) return;
   
$bkgimg = Graph::LoadBkgImage('',$this->background_image); $bkgimg = Graph::LoadBkgImage('',$this->background_image);
   
// Background width & Heoght // Background width & Heoght
$bw = imagesx($bkgimg); $bw = imagesx($bkgimg);
$bh = imagesy($bkgimg); $bh = imagesy($bkgimg);
   
// Canvas width and height // Canvas width and height
$cw = imagesx($this->img); $cw = imagesx($this->img);
$ch = imagesy($this->img); $ch = imagesy($this->img);
   
if( $this->doshadow ) { if( $this->doshadow ) {
$cw -= $this->shadow_width; $cw -= $this->shadow_width;
$ch -= $this->shadow_width; $ch -= $this->shadow_width;
} }
   
if( $this->background_image_x === NULL || $this->background_image_y === NULL ) { if( $this->background_image_x === NULL || $this->background_image_y === NULL ) {
if( $this->background_image_center ) { if( $this->background_image_center ) {
// Center original image in the plot area // Center original image in the plot area
$x = round($cw/2-$bw/2); $y = round($ch/2-$bh/2); $x = round($cw/2-$bw/2); $y = round($ch/2-$bh/2);
} }
else { else {
// Just copy the image from left corner, no resizing // Just copy the image from left corner, no resizing
$x=0; $y=0; $x=0; $y=0;
} }
} }
else { else {
$x = $this->background_image_x; $x = $this->background_image_x;
$y = $this->background_image_y; $y = $this->background_image_y;
} }
imagecopymerge($this->img,$bkgimg,$x,$y,0,0,$bw,$bh,$this->background_image_mix); 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) { 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); $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) { 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); $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) { function _gdImgHandle($agdCanvas,$x,$y,$fx=0,$fy=0,$w=0,$h=0,$mix=100) {
if( $w == 0 ) { if( $w == 0 ) {
$w = @imagesx($agdCanvas); $w = @imagesx($agdCanvas);
} }
if( $w === NULL ) { if( $w === NULL ) {
JpGraphError::RaiseL(12007); JpGraphError::RaiseL(12007);
//('Argument to MGraph::Add() is not a valid GD image handle.'); //('Argument to MGraph::Add() is not a valid GD image handle.');
return; return;
} }
if( $h == 0 ) { if( $h == 0 ) {
$h = @imagesy($agdCanvas); $h = @imagesy($agdCanvas);
} }
$this->iGraphs[$this->iCnt++] = array($agdCanvas,$x,$y,$fx,$fy,$w,$h,$mix); $this->iGraphs[$this->iCnt++] = array($agdCanvas,$x,$y,$fx,$fy,$w,$h,$mix);
} }
   
function SetMargin($lm,$rm,$tm,$bm) { function SetMargin($lm,$rm,$tm,$bm) {
$this->lm = $lm; $this->lm = $lm;
$this->rm = $rm; $this->rm = $rm;
$this->tm = $tm; $this->tm = $tm;
$this->bm = $bm; $this->bm = $bm;
} }
   
function SetExpired($aFlg=true) { function SetExpired($aFlg=true) {
$this->expired = $aFlg; $this->expired = $aFlg;
} }
   
function SetImgFormat($aFormat,$aQuality=75) { function SetImgFormat($aFormat,$aQuality=75) {
$this->image_format = $aFormat; $this->image_format = $aFormat;
$this->image_quality = $aQuality; $this->image_quality = $aQuality;
} }
   
// Set the shadow around the whole image // Set the shadow around the whole image
function SetShadow($aShowShadow=true,$aShadowWidth=4,$aShadowColor='gray@0.3') { function SetShadow($aShowShadow=true,$aShadowWidth=4,$aShadowColor='gray@0.3') {
$this->doshadow = $aShowShadow; $this->doshadow = $aShowShadow;
$this->shadow_color = $aShadowColor; $this->shadow_color = $aShadowColor;
$this->shadow_width = $aShadowWidth; $this->shadow_width = $aShadowWidth;
$this->footer->iBottomMargin += $aShadowWidth; $this->footer->iBottomMargin += $aShadowWidth;
$this->footer->iRightMargin += $aShadowWidth; $this->footer->iRightMargin += $aShadowWidth;
} }
   
function StrokeTitle($image,$w,$h) { function StrokeTitle($image,$w,$h) {
// Stroke title // Stroke title
if( $this->title->t !== '' ) { if( $this->title->t !== '' ) {
   
$margin = 3; $margin = 3;
   
$y = $this->title->margin; $y = $this->title->margin;
if( $this->title->halign == 'center' ) { if( $this->title->halign == 'center' ) {
$this->title->Center(0,$w,$y); $this->title->Center(0,$w,$y);
} }
elseif( $this->title->halign == 'left' ) { elseif( $this->title->halign == 'left' ) {
$this->title->SetPos($this->title->margin+2,$y); $this->title->SetPos($this->title->margin+2,$y);
} }
elseif( $this->title->halign == 'right' ) { elseif( $this->title->halign == 'right' ) {
$indent = 0; $indent = 0;
if( $this->doshadow ) { if( $this->doshadow ) {
$indent = $this->shadow_width+2; $indent = $this->shadow_width+2;
} }
$this->title->SetPos($w-$this->title->margin-$indent,$y,'right'); $this->title->SetPos($w-$this->title->margin-$indent,$y,'right');
} }
$this->title->Stroke($image); $this->title->Stroke($image);
   
// ... and subtitle // ... and subtitle
$y += $this->title->GetTextHeight($image) + $margin + $this->subtitle->margin; $y += $this->title->GetTextHeight($image) + $margin + $this->subtitle->margin;
if( $this->subtitle->halign == 'center' ) { if( $this->subtitle->halign == 'center' ) {
$this->subtitle->Center(0,$w,$y); $this->subtitle->Center(0,$w,$y);
} }
elseif( $this->subtitle->halign == 'left' ) { elseif( $this->subtitle->halign == 'left' ) {
$this->subtitle->SetPos($this->subtitle->margin+2,$y); $this->subtitle->SetPos($this->subtitle->margin+2,$y);
} }
elseif( $this->subtitle->halign == 'right' ) { elseif( $this->subtitle->halign == 'right' ) {
$indent = 0; $indent = 0;
if( $this->doshadow ) { if( $this->doshadow ) {
$indent = $this->shadow_width+2; $indent = $this->shadow_width+2;
} }
$this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right'); $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right');
} }
$this->subtitle->Stroke($image); $this->subtitle->Stroke($image);
   
// ... and subsubtitle // ... and subsubtitle
$y += $this->subtitle->GetTextHeight($image) + $margin + $this->subsubtitle->margin; $y += $this->subtitle->GetTextHeight($image) + $margin + $this->subsubtitle->margin;
if( $this->subsubtitle->halign == 'center' ) { if( $this->subsubtitle->halign == 'center' ) {
$this->subsubtitle->Center(0,$w,$y); $this->subsubtitle->Center(0,$w,$y);
} }
elseif( $this->subsubtitle->halign == 'left' ) { elseif( $this->subsubtitle->halign == 'left' ) {
$this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y); $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y);
} }
elseif( $this->subsubtitle->halign == 'right' ) { elseif( $this->subsubtitle->halign == 'right' ) {
$indent = 0; $indent = 0;
if( $this->doshadow ) { if( $this->doshadow ) {
$indent = $this->shadow_width+2; $indent = $this->shadow_width+2;
} }
$this->subsubtitle->SetPos($w-$this->subsubtitle->margin-$indent,$y,'right'); $this->subsubtitle->SetPos($w-$this->subsubtitle->margin-$indent,$y,'right');
} }
$this->subsubtitle->Stroke($image); $this->subsubtitle->Stroke($image);
   
} }
} }
   
function Stroke($aFileName='') { function Stroke($aFileName='') {
// Find out the necessary size for the container image // Find out the necessary size for the container image
$w=0; $h=0; $w=0; $h=0;
for($i=0; $i < $this->iCnt; ++$i ) { for($i=0; $i < $this->iCnt; ++$i ) {
$maxw = $this->iGraphs[$i][1]+$this->iGraphs[$i][5]; $maxw = $this->iGraphs[$i][1]+$this->iGraphs[$i][5];
$maxh = $this->iGraphs[$i][2]+$this->iGraphs[$i][6]; $maxh = $this->iGraphs[$i][2]+$this->iGraphs[$i][6];
$w = max( $w, $maxw ); $w = max( $w, $maxw );
$h = max( $h, $maxh ); $h = max( $h, $maxh );
} }
$w += $this->lm+$this->rm; $w += $this->lm+$this->rm;
$h += $this->tm+$this->bm; $h += $this->tm+$this->bm;
   
// User specified width,height overrides // User specified width,height overrides
if( $this->iWidth !== NULL && $this->iWidth !== 0 ) $w = $this->iWidth; if( $this->iWidth !== NULL && $this->iWidth !== 0 ) $w = $this->iWidth;
if( $this->iHeight!== NULL && $this->iHeight !== 0) $h = $this->iHeight; if( $this->iHeight!== NULL && $this->iHeight !== 0) $h = $this->iHeight;
   
if( $this->doshadow ) { if( $this->doshadow ) {
$w += $this->shadow_width; $w += $this->shadow_width;
$h += $this->shadow_width; $h += $this->shadow_width;
} }
   
$image = new Image($w,$h); $image = new Image($w,$h);
$image->SetImgFormat( $this->image_format,$this->image_quality); $image->SetImgFormat( $this->image_format,$this->image_quality);
   
if( $this->doshadow ) { if( $this->doshadow ) {
$image->SetColor($this->iFrameColor); $image->SetColor($this->iFrameColor);
$image->ShadowRectangle(0,0,$w-1,$h-1,$this->iFillColor,$this->shadow_width,$this->shadow_color); $image->ShadowRectangle(0,0,$w-1,$h-1,$this->iFillColor,$this->shadow_width,$this->shadow_color);
$w -= $this->shadow_width; $w -= $this->shadow_width;
$h -= $this->shadow_width; $h -= $this->shadow_width;
} }
else { else {
$image->SetColor($this->iFillColor); $image->SetColor($this->iFillColor);
$image->FilledRectangle(0,0,$w-1,$h-1); $image->FilledRectangle(0,0,$w-1,$h-1);
} }
$image->SetExpired($this->expired); $image->SetExpired($this->expired);
   
$this->img = $image->img; $this->img = $image->img;
$this->_strokeBackgroundImage(); $this->_strokeBackgroundImage();
   
if( $this->iDoFrame && ! $this->doshadow ) { if( $this->iDoFrame && ! $this->doshadow ) {
$image->SetColor($this->iFrameColor); $image->SetColor($this->iFrameColor);
$image->SetLineWeight($this->iFrameWeight); $image->SetLineWeight($this->iFrameWeight);
$image->Rectangle(0,0,$w-1,$h-1); $image->Rectangle(0,0,$w-1,$h-1);
} }
   
// Copy all sub graphs to the container // Copy all sub graphs to the container
for($i=0; $i < $this->iCnt; ++$i ) { for($i=0; $i < $this->iCnt; ++$i ) {
$image->CopyMerge($this->iGraphs[$i][0], $image->CopyMerge($this->iGraphs[$i][0],
$this->iGraphs[$i][1]+$this->lm,$this->iGraphs[$i][2]+$this->tm, $this->iGraphs[$i][1]+$this->lm,$this->iGraphs[$i][2]+$this->tm,
$this->iGraphs[$i][3],$this->iGraphs[$i][4], $this->iGraphs[$i][3],$this->iGraphs[$i][4],
$this->iGraphs[$i][5],$this->iGraphs[$i][6], $this->iGraphs[$i][5],$this->iGraphs[$i][6],
-1,-1, /* Full from width and height */ -1,-1, /* Full from width and height */
$this->iGraphs[$i][7]); $this->iGraphs[$i][7]);
   
   
} }
   
$this->StrokeTitle($image,$w,$h); $this->StrokeTitle($image,$w,$h);
$this->footer->Stroke($image); $this->footer->Stroke($image);
   
// Output image // Output image
if( $aFileName == _IMG_HANDLER ) { if( $aFileName == _IMG_HANDLER ) {
return $image->img; return $image->img;
} }
else { else {
//Finally stream the generated picture //Finally stream the generated picture
$this->cache = new ImgStreamCache(); $this->cache = new ImgStreamCache();
$this->cache->PutAndStream($image,$this->cache_name,$this->inline,$aFileName); $this->cache->PutAndStream($image,$this->cache_name,$this->inline,$aFileName);
} }
} }
} }
   
// EOF // EOF
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_PIE.PHP // File: JPGRAPH_PIE.PHP
// Description: Pie plot extension for JpGraph // Description: Pie plot extension for JpGraph
// Created: 2001-02-14 // Created: 2001-02-14
// Ver: $Id: jpgraph_pie.php 1790 2009-09-03 18:16:18Z ljp $ // Ver: $Id: jpgraph_pie.php 1790 2009-09-03 18:16:18Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
   
// Defines for PiePlot::SetLabelType() // Defines for PiePlot::SetLabelType()
define("PIE_VALUE_ABS",1); define("PIE_VALUE_ABS",1);
define("PIE_VALUE_PER",0); define("PIE_VALUE_PER",0);
define("PIE_VALUE_PERCENTAGE",0); define("PIE_VALUE_PERCENTAGE",0);
define("PIE_VALUE_ADJPERCENTAGE",2); define("PIE_VALUE_ADJPERCENTAGE",2);
define("PIE_VALUE_ADJPER",2); define("PIE_VALUE_ADJPER",2);
   
//=================================================== //===================================================
// CLASS PiePlot // CLASS PiePlot
// Description: Draws a pie plot // Description: Draws a pie plot
//=================================================== //===================================================
class PiePlot { class PiePlot {
public $posx=0.5,$posy=0.5; public $posx=0.5,$posy=0.5;
protected $radius=0.3; protected $radius=0.3;
protected $explode_radius=array(),$explode_all=false,$explode_r=20; protected $explode_radius=array(),$explode_all=false,$explode_r=20;
protected $labels=null, $legends=null; protected $labels=null, $legends=null;
protected $csimtargets=null,$csimwintargets=null; // Array of targets for CSIM protected $csimtargets=null,$csimwintargets=null; // Array of targets for CSIM
protected $csimareas=''; // Generated CSIM text protected $csimareas=''; // Generated CSIM text
protected $csimalts=null; // ALT tags for corresponding target protected $csimalts=null; // ALT tags for corresponding target
protected $data=null; protected $data=null;
public $title; public $title;
protected $startangle=0; protected $startangle=0;
protected $weight=1, $color="black"; protected $weight=1, $color="black";
protected $legend_margin=6,$show_labels=true; protected $legend_margin=6,$show_labels=true;
protected $themearr = array( protected $themearr = array(
"earth" => array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430), "earth" => 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), "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), "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)); "sand" => array(27,168,34,170,19,50,65,72,131,209,46,393));
protected $theme="earth"; protected $theme="earth";
protected $setslicecolors=array(); protected $setslicecolors=array();
protected $labeltype=0; // Default to percentage protected $labeltype=0; // Default to percentage
protected $pie_border=true,$pie_interior_border=true; protected $pie_border=true,$pie_interior_border=true;
public $value; public $value;
protected $ishadowcolor='',$ishadowdrop=4; protected $ishadowcolor='',$ishadowdrop=4;
protected $ilabelposadj=1; protected $ilabelposadj=1;
protected $legendcsimtargets = array(),$legendcsimwintargets = array(); protected $legendcsimtargets = array(),$legendcsimwintargets = array();
protected $legendcsimalts = array(); protected $legendcsimalts = array();
protected $adjusted_data = array(); protected $adjusted_data = array();
public $guideline = null; public $guideline = null;
protected $guidelinemargin=10,$iShowGuideLineForSingle = false; protected $guidelinemargin=10,$iShowGuideLineForSingle = false;
protected $iGuideLineCurve = false,$iGuideVFactor=1.4,$iGuideLineRFactor=0.8; protected $iGuideLineCurve = false,$iGuideVFactor=1.4,$iGuideLineRFactor=0.8;
protected $la = array(); // Holds the exact angle for each label protected $la = array(); // Holds the exact angle for each label
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($data) { function __construct($data) {
$this->data = array_reverse($data); $this->data = array_reverse($data);
$this->title = new Text(""); $this->title = new Text("");
$this->title->SetFont(FF_FONT1,FS_BOLD); $this->title->SetFont(FF_FONT1,FS_BOLD);
$this->value = new DisplayValue(); $this->value = new DisplayValue();
$this->value->Show(); $this->value->Show();
$this->value->SetFormat('%.1f%%'); $this->value->SetFormat('%.1f%%');
$this->guideline = new LineProperty(); $this->guideline = new LineProperty();
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function SetCenter($x,$y=0.5) { function SetCenter($x,$y=0.5) {
$this->posx = $x; $this->posx = $x;
$this->posy = $y; $this->posy = $y;
} }
   
// Enable guideline and set drwaing policy // Enable guideline and set drwaing policy
function SetGuideLines($aFlg=true,$aCurved=true,$aAlways=false) { function SetGuideLines($aFlg=true,$aCurved=true,$aAlways=false) {
$this->guideline->Show($aFlg); $this->guideline->Show($aFlg);
$this->iShowGuideLineForSingle = $aAlways; $this->iShowGuideLineForSingle = $aAlways;
$this->iGuideLineCurve = $aCurved; $this->iGuideLineCurve = $aCurved;
} }
   
// Adjuste the distance between labels and labels and pie // Adjuste the distance between labels and labels and pie
function SetGuideLinesAdjust($aVFactor,$aRFactor=0.8) { function SetGuideLinesAdjust($aVFactor,$aRFactor=0.8) {
$this->iGuideVFactor=$aVFactor; $this->iGuideVFactor=$aVFactor;
$this->iGuideLineRFactor=$aRFactor; $this->iGuideLineRFactor=$aRFactor;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->color = $aColor; $this->color = $aColor;
} }
   
function SetSliceColors($aColors) { function SetSliceColors($aColors) {
$this->setslicecolors = $aColors; $this->setslicecolors = $aColors;
} }
   
function SetShadow($aColor='darkgray',$aDropWidth=4) { function SetShadow($aColor='darkgray',$aDropWidth=4) {
$this->ishadowcolor = $aColor; $this->ishadowcolor = $aColor;
$this->ishadowdrop = $aDropWidth; $this->ishadowdrop = $aDropWidth;
} }
   
function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') { function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
$this->csimtargets=array_reverse($aTargets); $this->csimtargets=array_reverse($aTargets);
if( is_array($aWinTargets) ) if( is_array($aWinTargets) )
$this->csimwintargets=array_reverse($aWinTargets); $this->csimwintargets=array_reverse($aWinTargets);
if( is_array($aAlts) ) if( is_array($aAlts) )
$this->csimalts=array_reverse($aAlts); $this->csimalts=array_reverse($aAlts);
} }
   
function GetCSIMareas() { function GetCSIMareas() {
return $this->csimareas; return $this->csimareas;
} }
   
function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
//Slice number, ellipse centre (x,y), height, width, start angle, end angle //Slice number, ellipse centre (x,y), height, width, start angle, end angle
while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI; while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI; while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
   
$sa = 2*M_PI - $sa; $sa = 2*M_PI - $sa;
$ea = 2*M_PI - $ea; $ea = 2*M_PI - $ea;
   
// Special case when we have only one slice since then both start and end // Special case when we have only one slice since then both start and end
// angle will be == 0 // angle will be == 0
if( abs($sa - $ea) < 0.0001 ) { if( abs($sa - $ea) < 0.0001 ) {
$sa=2*M_PI; $ea=0; $sa=2*M_PI; $ea=0;
} }
   
//add coordinates of the centre to the map //add coordinates of the centre to the map
$xc = floor($xc);$yc=floor($yc); $xc = floor($xc);$yc=floor($yc);
$coords = "$xc, $yc"; $coords = "$xc, $yc";
   
//add coordinates of the first point on the arc to the map //add coordinates of the first point on the arc to the map
$xp = floor(($radius*cos($ea))+$xc); $xp = floor(($radius*cos($ea))+$xc);
$yp = floor($yc-$radius*sin($ea)); $yp = floor($yc-$radius*sin($ea));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
   
//add coordinates every 0.2 radians //add coordinates every 0.2 radians
$a=$ea+0.2; $a=$ea+0.2;
   
// If we cross the 360-limit with a slice we need to handle // If we cross the 360-limit with a slice we need to handle
// the fact that end angle is smaller than start // the fact that end angle is smaller than start
if( $sa < $ea ) { if( $sa < $ea ) {
while ($a <= 2*M_PI) { while ($a <= 2*M_PI) {
$xp = floor($radius*cos($a)+$xc); $xp = floor($radius*cos($a)+$xc);
$yp = floor($yc-$radius*sin($a)); $yp = floor($yc-$radius*sin($a));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$a += 0.2; $a += 0.2;
} }
$a -= 2*M_PI; $a -= 2*M_PI;
} }
   
   
while ($a < $sa) { while ($a < $sa) {
$xp = floor($radius*cos($a)+$xc); $xp = floor($radius*cos($a)+$xc);
$yp = floor($yc-$radius*sin($a)); $yp = floor($yc-$radius*sin($a));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$a += 0.2; $a += 0.2;
} }
   
//Add the last point on the arc //Add the last point on the arc
$xp = floor($radius*cos($sa)+$xc); $xp = floor($radius*cos($sa)+$xc);
$yp = floor($yc-$radius*sin($sa)); $yp = floor($yc-$radius*sin($sa));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
if( !empty($this->csimtargets[$i]) ) { if( !empty($this->csimtargets[$i]) ) {
$this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\""; $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\"";
$tmp=""; $tmp="";
if( !empty($this->csimwintargets[$i]) ) { if( !empty($this->csimwintargets[$i]) ) {
$this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
} }
if( !empty($this->csimalts[$i]) ) { if( !empty($this->csimalts[$i]) ) {
$tmp=sprintf($this->csimalts[$i],$this->data[$i]); $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
} }
   
   
function SetTheme($aTheme) { function SetTheme($aTheme) {
if( in_array($aTheme,array_keys($this->themearr)) ) if( in_array($aTheme,array_keys($this->themearr)) )
$this->theme = $aTheme; $this->theme = $aTheme;
else else
JpGraphError::RaiseL(15001,$aTheme);//("PiePLot::SetTheme() Unknown theme: $aTheme"); JpGraphError::RaiseL(15001,$aTheme);//("PiePLot::SetTheme() Unknown theme: $aTheme");
} }
   
function ExplodeSlice($e,$radius=20) { function ExplodeSlice($e,$radius=20) {
if( ! is_integer($e) ) if( ! is_integer($e) )
JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer'); JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer');
$this->explode_radius[$e]=$radius; $this->explode_radius[$e]=$radius;
} }
   
function ExplodeAll($radius=20) { function ExplodeAll($radius=20) {
$this->explode_all=true; $this->explode_all=true;
$this->explode_r = $radius; $this->explode_r = $radius;
} }
   
function Explode($aExplodeArr) { function Explode($aExplodeArr) {
if( !is_array($aExplodeArr) ) { if( !is_array($aExplodeArr) ) {
JpGraphError::RaiseL(15003); JpGraphError::RaiseL(15003);
//("Argument to PiePlot::Explode() must be an array with integer distances."); //("Argument to PiePlot::Explode() must be an array with integer distances.");
} }
$this->explode_radius = $aExplodeArr; $this->explode_radius = $aExplodeArr;
} }
   
function SetStartAngle($aStart) { function SetStartAngle($aStart) {
if( $aStart < 0 || $aStart > 360 ) { if( $aStart < 0 || $aStart > 360 ) {
JpGraphError::RaiseL(15004);//('Slice start angle must be between 0 and 360 degrees.'); JpGraphError::RaiseL(15004);//('Slice start angle must be between 0 and 360 degrees.');
} }
if( $aStart == 0 ) { if( $aStart == 0 ) {
$this->startangle = 0; $this->startangle = 0;
} }
else { else {
$this->startangle = 360-$aStart; $this->startangle = 360-$aStart;
$this->startangle *= M_PI/180; $this->startangle *= M_PI/180;
} }
} }
   
// Size in percentage // Size in percentage
function SetSize($aSize) { function SetSize($aSize) {
if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) ) if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) )
$this->radius = $aSize; $this->radius = $aSize;
else else
JpGraphError::RaiseL(15006); 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]"); //("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 // Set label arrays
function SetLegends($aLegend) { function SetLegends($aLegend) {
$this->legends = $aLegend; $this->legends = $aLegend;
} }
   
// Set text labels for slices // Set text labels for slices
function SetLabels($aLabels,$aLblPosAdj="auto") { function SetLabels($aLabels,$aLblPosAdj="auto") {
$this->labels = array_reverse($aLabels); $this->labels = array_reverse($aLabels);
$this->ilabelposadj=$aLblPosAdj; $this->ilabelposadj=$aLblPosAdj;
} }
   
function SetLabelPos($aLblPosAdj) { function SetLabelPos($aLblPosAdj) {
$this->ilabelposadj=$aLblPosAdj; $this->ilabelposadj=$aLblPosAdj;
} }
   
// Should we display actual value or percentage? // Should we display actual value or percentage?
function SetLabelType($aType) { function SetLabelType($aType) {
if( $aType < 0 || $aType > 2 ) if( $aType < 0 || $aType > 2 )
JpGraphError::RaiseL(15008,$aType); JpGraphError::RaiseL(15008,$aType);
//("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t)."); //("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t).");
$this->labeltype = $aType; $this->labeltype = $aType;
} }
   
// Deprecated. // Deprecated.
function SetValueType($aType) { function SetValueType($aType) {
$this->SetLabelType($aType); $this->SetLabelType($aType);
} }
   
// Should the circle around a pie plot be displayed // Should the circle around a pie plot be displayed
function ShowBorder($exterior=true,$interior=true) { function ShowBorder($exterior=true,$interior=true) {
$this->pie_border = $exterior; $this->pie_border = $exterior;
$this->pie_interior_border = $interior; $this->pie_interior_border = $interior;
} }
   
// Setup the legends // Setup the legends
function Legend($graph) { function Legend($graph) {
$colors = array_keys($graph->img->rgb->rgb_table); $colors = array_keys($graph->img->rgb->rgb_table);
sort($colors); sort($colors);
$ta=$this->themearr[$this->theme]; $ta=$this->themearr[$this->theme];
$n = count($this->data); $n = count($this->data);
   
if( $this->setslicecolors==null ) { if( $this->setslicecolors==null ) {
$numcolors=count($ta); $numcolors=count($ta);
if( class_exists('PiePlot3D',false) && ($this instanceof PiePlot3D) ) { if( class_exists('PiePlot3D',false) && ($this instanceof PiePlot3D) ) {
$ta = array_reverse(array_slice($ta,0,$n)); $ta = array_reverse(array_slice($ta,0,$n));
} }
} }
else { else {
$this->setslicecolors = array_slice($this->setslicecolors,0,$n); $this->setslicecolors = array_slice($this->setslicecolors,0,$n);
$numcolors=count($this->setslicecolors); $numcolors=count($this->setslicecolors);
if( $graph->pieaa && !($this instanceof PiePlot3D) ) { if( $graph->pieaa && !($this instanceof PiePlot3D) ) {
$this->setslicecolors = array_reverse($this->setslicecolors); $this->setslicecolors = array_reverse($this->setslicecolors);
} }
} }
   
$sum=0; $sum=0;
for($i=0; $i < $n; ++$i) for($i=0; $i < $n; ++$i)
$sum += $this->data[$i]; $sum += $this->data[$i];
   
// Bail out with error if the sum is 0 // Bail out with error if the sum is 0
if( $sum==0 ) if( $sum==0 )
JpGraphError::RaiseL(15009);//("Illegal pie plot. Sum of all data is zero for Pie!"); 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 // Make sure we don't plot more values than data points
// (in case the user added more legends than data points) // (in case the user added more legends than data points)
$n = min(count($this->legends),count($this->data)); $n = min(count($this->legends),count($this->data));
if( $this->legends != "" ) { if( $this->legends != "" ) {
$this->legends = array_reverse(array_slice($this->legends,0,$n)); $this->legends = array_reverse(array_slice($this->legends,0,$n));
} }
for( $i=$n-1; $i >= 0; --$i ) { for( $i=$n-1; $i >= 0; --$i ) {
$l = $this->legends[$i]; $l = $this->legends[$i];
// Replace possible format with actual values // Replace possible format with actual values
if( count($this->csimalts) > $i ) { if( count($this->csimalts) > $i ) {
$fmt = $this->csimalts[$i]; $fmt = $this->csimalts[$i];
} }
else { else {
$fmt = "%d"; // Deafult Alt if no other has been specified $fmt = "%d"; // Deafult Alt if no other has been specified
} }
if( $this->labeltype==0 ) { if( $this->labeltype==0 ) {
$l = sprintf($l,100*$this->data[$i]/$sum); $l = sprintf($l,100*$this->data[$i]/$sum);
$alt = sprintf($fmt,$this->data[$i]); $alt = sprintf($fmt,$this->data[$i]);
   
} }
elseif( $this->labeltype == 1) { elseif( $this->labeltype == 1) {
$l = sprintf($l,$this->data[$i]); $l = sprintf($l,$this->data[$i]);
$alt = sprintf($fmt,$this->data[$i]); $alt = sprintf($fmt,$this->data[$i]);
   
} }
else { else {
$l = sprintf($l,$this->adjusted_data[$i]); $l = sprintf($l,$this->adjusted_data[$i]);
$alt = sprintf($fmt,$this->adjusted_data[$i]); $alt = sprintf($fmt,$this->adjusted_data[$i]);
} }
   
if( empty($this->csimwintargets[$i]) ) { if( empty($this->csimwintargets[$i]) ) {
$wintarg = ''; $wintarg = '';
} }
else { else {
$wintarg = $this->csimwintargets[$i]; $wintarg = $this->csimwintargets[$i];
} }
   
if( $this->setslicecolors==null ) { if( $this->setslicecolors==null ) {
$graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,$this->csimtargets[$i],$alt,$wintarg); $graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,$this->csimtargets[$i],$alt,$wintarg);
} }
else { else {
$graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,$this->csimtargets[$i],$alt,$wintarg); $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,$this->csimtargets[$i],$alt,$wintarg);
} }
} }
} }
   
// Adjust the rounded percetage value so that the sum of // Adjust the rounded percetage value so that the sum of
// of the pie slices are always 100% // of the pie slices are always 100%
// Using the Hare/Niemeyer method // Using the Hare/Niemeyer method
function AdjPercentage($aData,$aPrec=0) { function AdjPercentage($aData,$aPrec=0) {
$mul=100; $mul=100;
if( $aPrec > 0 && $aPrec < 3 ) { if( $aPrec > 0 && $aPrec < 3 ) {
if( $aPrec == 1 ) if( $aPrec == 1 )
$mul=1000; $mul=1000;
else else
$mul=10000; $mul=10000;
} }
   
$tmp = array(); $tmp = array();
$result = array(); $result = array();
$quote_sum=0; $quote_sum=0;
$n = count($aData) ; $n = count($aData) ;
for( $i=0, $sum=0; $i < $n; ++$i ) for( $i=0, $sum=0; $i < $n; ++$i )
$sum+=$aData[$i]; $sum+=$aData[$i];
foreach($aData as $index => $value) { foreach($aData as $index => $value) {
$tmp_percentage=$value/$sum*$mul; $tmp_percentage=$value/$sum*$mul;
$result[$index]=floor($tmp_percentage); $result[$index]=floor($tmp_percentage);
$tmp[$index]=$tmp_percentage-$result[$index]; $tmp[$index]=$tmp_percentage-$result[$index];
$quote_sum+=$result[$index]; $quote_sum+=$result[$index];
} }
if( $quote_sum == $mul) { if( $quote_sum == $mul) {
if( $mul > 100 ) { if( $mul > 100 ) {
$tmp = $mul / 100; $tmp = $mul / 100;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$result[$i] /= $tmp ; $result[$i] /= $tmp ;
} }
} }
return $result; return $result;
} }
arsort($tmp,SORT_NUMERIC); arsort($tmp,SORT_NUMERIC);
reset($tmp); reset($tmp);
for($i=0; $i < $mul-$quote_sum; $i++) for($i=0; $i < $mul-$quote_sum; $i++)
{ {
$result[key($tmp)]++; $result[key($tmp)]++;
next($tmp); next($tmp);
} }
if( $mul > 100 ) { if( $mul > 100 ) {
$tmp = $mul / 100; $tmp = $mul / 100;
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$result[$i] /= $tmp ; $result[$i] /= $tmp ;
} }
} }
return $result; return $result;
} }
   
   
function Stroke($img,$aaoption=0) { function Stroke($img,$aaoption=0) {
// aaoption is used to handle antialias // aaoption is used to handle antialias
// aaoption == 0 a normal pie // aaoption == 0 a normal pie
// aaoption == 1 just the body // aaoption == 1 just the body
// aaoption == 2 just the values // aaoption == 2 just the values
   
// Explode scaling. If anti alias we scale the image // Explode scaling. If anti alias we scale the image
// twice and we also need to scale the exploding distance // twice and we also need to scale the exploding distance
$expscale = $aaoption === 1 ? 2 : 1; $expscale = $aaoption === 1 ? 2 : 1;
   
if( $this->labeltype == 2 ) { if( $this->labeltype == 2 ) {
// Adjust the data so that it will add up to 100% // Adjust the data so that it will add up to 100%
$this->adjusted_data = $this->AdjPercentage($this->data); $this->adjusted_data = $this->AdjPercentage($this->data);
} }
   
$colors = array_keys($img->rgb->rgb_table); $colors = array_keys($img->rgb->rgb_table);
sort($colors); sort($colors);
$ta=$this->themearr[$this->theme]; $ta=$this->themearr[$this->theme];
$n = count($this->data); $n = count($this->data);
   
if( $this->setslicecolors==null ) { if( $this->setslicecolors==null ) {
$numcolors=count($ta); $numcolors=count($ta);
} }
else { else {
// We need to create an array of colors as long as the data // 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 // since we need to reverse it to get the colors in the right order
$numcolors=count($this->setslicecolors); $numcolors=count($this->setslicecolors);
$i = 2*$numcolors; $i = 2*$numcolors;
while( $n > $i ) { while( $n > $i ) {
$this->setslicecolors = array_merge($this->setslicecolors,$this->setslicecolors); $this->setslicecolors = array_merge($this->setslicecolors,$this->setslicecolors);
$i += $n; $i += $n;
} }
$tt = array_slice($this->setslicecolors,0,$n % $numcolors); $tt = array_slice($this->setslicecolors,0,$n % $numcolors);
$this->setslicecolors = array_merge($this->setslicecolors,$tt); $this->setslicecolors = array_merge($this->setslicecolors,$tt);
$this->setslicecolors = array_reverse($this->setslicecolors); $this->setslicecolors = array_reverse($this->setslicecolors);
} }
   
// Draw the slices // Draw the slices
$sum=0; $sum=0;
for($i=0; $i < $n; ++$i) for($i=0; $i < $n; ++$i)
$sum += $this->data[$i]; $sum += $this->data[$i];
   
// Bail out with error if the sum is 0 // Bail out with error if the sum is 0
if( $sum==0 ) { if( $sum==0 ) {
JpGraphError::RaiseL(15009);//("Sum of all data is 0 for Pie."); JpGraphError::RaiseL(15009);//("Sum of all data is 0 for Pie.");
} }
   
// Set up the pie-circle // Set up the pie-circle
if( $this->radius <= 1 ) { if( $this->radius <= 1 ) {
$radius = floor($this->radius*min($img->width,$img->height)); $radius = floor($this->radius*min($img->width,$img->height));
} }
else { else {
$radius = $aaoption === 1 ? $this->radius*2 : $this->radius; $radius = $aaoption === 1 ? $this->radius*2 : $this->radius;
} }
   
if( $this->posx <= 1 && $this->posx > 0 ) { if( $this->posx <= 1 && $this->posx > 0 ) {
$xc = round($this->posx*$img->width); $xc = round($this->posx*$img->width);
} }
else { else {
$xc = $this->posx ; $xc = $this->posx ;
} }
   
if( $this->posy <= 1 && $this->posy > 0 ) { if( $this->posy <= 1 && $this->posy > 0 ) {
$yc = round($this->posy*$img->height); $yc = round($this->posy*$img->height);
} }
else { else {
$yc = $this->posy ; $yc = $this->posy ;
} }
   
$n = count($this->data); $n = count($this->data);
   
if( $this->explode_all ) { if( $this->explode_all ) {
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$this->explode_radius[$i]=$this->explode_r; $this->explode_radius[$i]=$this->explode_r;
} }
} }
   
// If we have a shadow and not just drawing the labels // If we have a shadow and not just drawing the labels
if( $this->ishadowcolor != "" && $aaoption !== 2) { if( $this->ishadowcolor != "" && $aaoption !== 2) {
$accsum=0; $accsum=0;
$angle2 = $this->startangle; $angle2 = $this->startangle;
$img->SetColor($this->ishadowcolor); $img->SetColor($this->ishadowcolor);
for($i=0; $sum > 0 && $i < $n; ++$i) { for($i=0; $sum > 0 && $i < $n; ++$i) {
$j = $n-$i-1; $j = $n-$i-1;
$d = $this->data[$i]; $d = $this->data[$i];
$angle1 = $angle2; $angle1 = $angle2;
$accsum += $d; $accsum += $d;
$angle2 = $this->startangle+2*M_PI*$accsum/$sum; $angle2 = $this->startangle+2*M_PI*$accsum/$sum;
if( empty($this->explode_radius[$j]) ) { if( empty($this->explode_radius[$j]) ) {
$this->explode_radius[$j]=0; $this->explode_radius[$j]=0;
} }
   
if( $d < 0.00001 ) continue; if( $d < 0.00001 ) continue;
   
$la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
   
$xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale; $xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale;
$ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale; $ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale;
   
$xcm += $this->ishadowdrop*$expscale; $xcm += $this->ishadowdrop*$expscale;
$ycm += $this->ishadowdrop*$expscale; $ycm += $this->ishadowdrop*$expscale;
   
$_sa = round($angle1*180/M_PI); $_sa = round($angle1*180/M_PI);
$_ea = round($angle2*180/M_PI); $_ea = round($angle2*180/M_PI);
   
// The CakeSlice method draws a full circle in case of start angle = end angle // 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 // 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 // slice in the pie in case it is the wanted behaviour
if( $_ea-$_sa > 0.1 || $n==1 ) { if( $_ea-$_sa > 0.1 || $n==1 ) {
$img->CakeSlice($xcm,$ycm,$radius-1,$radius-1, $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,
$angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor); $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor);
} }
} }
} }
   
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// This is the main loop to draw each cake slice // This is the main loop to draw each cake slice
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
   
// Set up the accumulated sum, start angle for first slice and border color // Set up the accumulated sum, start angle for first slice and border color
$accsum=0; $accsum=0;
$angle2 = $this->startangle; $angle2 = $this->startangle;
$img->SetColor($this->color); $img->SetColor($this->color);
   
// Loop though all the slices if there is a pie to draw (sum>0) // Loop though all the slices if there is a pie to draw (sum>0)
// There are n slices in total // There are n slices in total
for($i=0; $sum>0 && $i < $n; ++$i) { for($i=0; $sum>0 && $i < $n; ++$i) {
   
// $j is the actual index used for the slice // $j is the actual index used for the slice
$j = $n-$i-1; $j = $n-$i-1;
   
// Make sure we havea valid distance to explode the slice // Make sure we havea valid distance to explode the slice
if( empty($this->explode_radius[$j]) ) { if( empty($this->explode_radius[$j]) ) {
$this->explode_radius[$j]=0; $this->explode_radius[$j]=0;
} }
   
// The actual numeric value for the slice // The actual numeric value for the slice
$d = $this->data[$i]; $d = $this->data[$i];
   
$angle1 = $angle2; $angle1 = $angle2;
   
// Accumlate the sum // Accumlate the sum
$accsum += $d; $accsum += $d;
   
// The new angle when we add the "size" of this slice // The new angle when we add the "size" of this slice
// angle1 is then the start and angle2 the end 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); $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 avoid some trouble by not allowing end angle to be 0, in that case
// we translate to 360 // we translate to 360
   
// la is used to hold the label angle, which is centered on the slice // la is used to hold the label angle, which is centered on the slice
if( $angle2 < 0.0001 && $angle1 > 0.0001 ) { if( $angle2 < 0.0001 && $angle1 > 0.0001 ) {
$this->la[$i] = 2*M_PI - (abs(2*M_PI-$angle1)/2.0+$angle1); $this->la[$i] = 2*M_PI - (abs(2*M_PI-$angle1)/2.0+$angle1);
} }
elseif( $angle1 > $angle2 ) { elseif( $angle1 > $angle2 ) {
// The case where the slice crosses the 3 a'clock line // The case where the slice crosses the 3 a'clock line
// Remember that the slices are counted clockwise and // Remember that the slices are counted clockwise and
// labels are counted counter clockwise so we need to revert with 2 PI // 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); $this->la[$i] = 2*M_PI-$this->NormAngle($angle1 + ((2*M_PI - $angle1)+$angle2)/2);
} }
else { else {
$this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); $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 // Too avoid rounding problems we skip the slice if it is too small
if( $d < 0.00001 ) continue; if( $d < 0.00001 ) continue;
   
// If the user has specified an array of colors for each slice then use // 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 // that a color otherwise use the theme array (ta) of colors
if( $this->setslicecolors==null ) { if( $this->setslicecolors==null ) {
$slicecolor=$colors[$ta[$i%$numcolors]]; $slicecolor=$colors[$ta[$i%$numcolors]];
} }
else { else {
$slicecolor=$this->setslicecolors[$i%$numcolors]; $slicecolor=$this->setslicecolors[$i%$numcolors];
} }
   
// $_sa = round($angle1*180/M_PI); // $_sa = round($angle1*180/M_PI);
// $_ea = round($angle2*180/M_PI); // $_ea = round($angle2*180/M_PI);
// $_la = round($this->la[$i]*180/M_PI); // $_la = round($this->la[$i]*180/M_PI);
// echo "Slice#$i: ang1=$_sa , ang2=$_ea, la=$_la, color=$slicecolor<br>"; // echo "Slice#$i: ang1=$_sa , ang2=$_ea, la=$_la, color=$slicecolor<br>";
   
   
// If we have enabled antialias then we don't draw any border so // If we have enabled antialias then we don't draw any border so
// make the bordedr color the same as the slice color // make the bordedr color the same as the slice color
if( $this->pie_interior_border && $aaoption===0 ) { if( $this->pie_interior_border && $aaoption===0 ) {
$img->SetColor($this->color); $img->SetColor($this->color);
} }
else { else {
$img->SetColor($slicecolor); $img->SetColor($slicecolor);
} }
$arccolor = $this->pie_border && $aaoption===0 ? $this->color : ""; $arccolor = $this->pie_border && $aaoption===0 ? $this->color : "";
   
// Calculate the x,y coordinates for the base of this slice taking // 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 // 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 // ray of extension and we have the mid angle handy as it is also the
// label angle // label angle
$xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale; $xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale;
$ycm = $yc - $this->explode_radius[$j]*sin($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 we are not just drawing the labels then draw this cake slice
if( $aaoption !== 2 ) { if( $aaoption !== 2 ) {
   
$_sa = round($angle1*180/M_PI); $_sa = round($angle1*180/M_PI);
$_ea = round($angle2*180/M_PI); $_ea = round($angle2*180/M_PI);
$_la = round($this->la[$i]*180/M_PI); $_la = round($this->la[$i]*180/M_PI);
//echo "[$i] sa=$_sa, ea=$_ea, la[$i]=$_la, (color=$slicecolor)<br>"; //echo "[$i] sa=$_sa, ea=$_ea, la[$i]=$_la, (color=$slicecolor)<br>";
   
// The CakeSlice method draws a full circle in case of start angle = end angle // 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 // for pie slices we want this in case the slice have a value larger than 99% of the
// total sum // total sum
if( abs($_ea-$_sa) > 0.1 || $d > 0 ) { if( abs($_ea-$_sa) > 0.1 || $d > 0 ) {
$img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,$_sa,$_ea,$slicecolor,$arccolor); $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 the CSIM is used then make sure we register a CSIM area for this slice as well
if( $this->csimtargets && $aaoption !== 1 ) { if( $this->csimtargets && $aaoption !== 1 ) {
$this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2); $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2);
} }
} }
   
// Format the titles for each slice // Format the titles for each slice
if( $aaoption !== 2 ) { if( $aaoption !== 2 ) {
for( $i=0; $i < $n; ++$i) { for( $i=0; $i < $n; ++$i) {
if( $this->labeltype==0 ) { if( $this->labeltype==0 ) {
if( $sum != 0 ) if( $sum != 0 )
$l = 100.0*$this->data[$i]/$sum; $l = 100.0*$this->data[$i]/$sum;
else else
$l = 0.0; $l = 0.0;
} }
elseif( $this->labeltype==1 ) { elseif( $this->labeltype==1 ) {
$l = $this->data[$i]*1.0; $l = $this->data[$i]*1.0;
} }
else { else {
$l = $this->adjusted_data[$i]; $l = $this->adjusted_data[$i];
} }
if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) if( isset($this->labels[$i]) && is_string($this->labels[$i]) )
$this->labels[$i]=sprintf($this->labels[$i],$l); $this->labels[$i]=sprintf($this->labels[$i],$l);
else else
$this->labels[$i]=$l; $this->labels[$i]=$l;
} }
} }
   
if( $this->value->show && $aaoption !== 1 ) { if( $this->value->show && $aaoption !== 1 ) {
$this->StrokeAllLabels($img,$xc,$yc,$radius); $this->StrokeAllLabels($img,$xc,$yc,$radius);
} }
   
// Adjust title position // Adjust title position
if( $aaoption !== 1 ) { if( $aaoption !== 1 ) {
$this->title->SetPos($xc, $this->title->SetPos($xc,
$yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin, $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin,
"center","bottom"); "center","bottom");
$this->title->Stroke($img); $this->title->Stroke($img);
} }
   
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
   
function NormAngle($a) { function NormAngle($a) {
while( $a < 0 ) $a += 2*M_PI; while( $a < 0 ) $a += 2*M_PI;
while( $a > 2*M_PI ) $a -= 2*M_PI; while( $a > 2*M_PI ) $a -= 2*M_PI;
return $a; return $a;
} }
   
function Quadrant($a) { function Quadrant($a) {
$a=$this->NormAngle($a); $a=$this->NormAngle($a);
if( $a > 0 && $a <= M_PI/2 ) if( $a > 0 && $a <= M_PI/2 )
return 0; return 0;
if( $a > M_PI/2 && $a <= M_PI ) if( $a > M_PI/2 && $a <= M_PI )
return 1; return 1;
if( $a > M_PI && $a <= 1.5*M_PI ) if( $a > M_PI && $a <= 1.5*M_PI )
return 2; return 2;
if( $a > 1.5*M_PI ) if( $a > 1.5*M_PI )
return 3; return 3;
} }
   
function StrokeGuideLabels($img,$xc,$yc,$radius) { function StrokeGuideLabels($img,$xc,$yc,$radius) {
$n = count($this->labels); $n = count($this->labels);
   
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// Step 1 of the algorithm is to construct a number of clusters // Step 1 of the algorithm is to construct a number of clusters
// a cluster is defined as all slices within the same quadrant (almost) // a cluster is defined as all slices within the same quadrant (almost)
// that has an angular distance less than the treshold // that has an angular distance less than the treshold
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
$tresh_hold=25 * M_PI/180; // 25 degrees difference to be in a cluster $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 $incluster=false; // flag if we are currently in a cluster or not
$clusters = array(); // array of clusters $clusters = array(); // array of clusters
$cidx=-1; // running cluster index $cidx=-1; // running cluster index
   
// Go through all the labels and construct a number of clusters // Go through all the labels and construct a number of clusters
for($i=0; $i < $n-1; ++$i) { for($i=0; $i < $n-1; ++$i) {
// Calc the angle distance between two consecutive slices // Calc the angle distance between two consecutive slices
$a1=$this->la[$i]; $a1=$this->la[$i];
$a2=$this->la[$i+1]; $a2=$this->la[$i+1];
$q1 = $this->Quadrant($a1); $q1 = $this->Quadrant($a1);
$q2 = $this->Quadrant($a2); $q2 = $this->Quadrant($a2);
$diff = abs($a1-$a2); $diff = abs($a1-$a2);
if( $diff < $tresh_hold ) { if( $diff < $tresh_hold ) {
if( $incluster ) { if( $incluster ) {
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
// Each cluster can only cover one quadrant // Each cluster can only cover one quadrant
// Do we cross a quadrant ( and must break the cluster) // Do we cross a quadrant ( and must break the cluster)
if( $q1 != $q2 ) { if( $q1 != $q2 ) {
// If we cross a quadrant boundary we normally start a // If we cross a quadrant boundary we normally start a
// new cluster. However we need to take the 12'a clock // new cluster. However we need to take the 12'a clock
// and 6'a clock positions into a special consideration. // and 6'a clock positions into a special consideration.
// Case 1: WE go from q=1 to q=2 if the last slice on // 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 // the cluster for q=1 is close to 12'a clock and the
// first slice in q=0 is small we extend the previous // first slice in q=0 is small we extend the previous
// cluster // cluster
if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) { if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) {
if( $i < $n-2 ) { if( $i < $n-2 ) {
$a3 = $this->la[$i+2]; $a3 = $this->la[$i+2];
// If there isn't a cluster coming up with the next-next slice // If there isn't a cluster coming up with the next-next slice
// we extend the previous cluster to cover this slice as well // we extend the previous cluster to cover this slice as well
if( abs($a3-$a2) >= $tresh_hold ) { if( abs($a3-$a2) >= $tresh_hold ) {
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
$i++; $i++;
} }
} }
} }
elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) { elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) {
if( $i < $n-2 ) { if( $i < $n-2 ) {
$a3 = $this->la[$i+2]; $a3 = $this->la[$i+2];
// If there isn't a cluster coming up with the next-next slice // If there isn't a cluster coming up with the next-next slice
// we extend the previous cluster to cover this slice as well // we extend the previous cluster to cover this slice as well
if( abs($a3-$a2) >= $tresh_hold ) { if( abs($a3-$a2) >= $tresh_hold ) {
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
$i++; $i++;
} }
} }
} }
   
if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) { if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) {
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
$i++; $i++;
} }
   
$incluster = false; $incluster = false;
} }
} }
elseif( $q1 == $q2) { elseif( $q1 == $q2) {
$incluster = true; $incluster = true;
// Now we have a special case for quadrant 0. If we previously // Now we have a special case for quadrant 0. If we previously
// have a cluster of one in quadrant 0 we just extend that // 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 // cluster. If we don't do this then we risk that the label
// for the cluster of one will cross the guide-line // for the cluster of one will cross the guide-line
if( $q1 == 0 && $cidx > -1 && if( $q1 == 0 && $cidx > -1 &&
$clusters[$cidx][1] == 1 && $clusters[$cidx][1] == 1 &&
$this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) { $this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) {
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
} }
else { else {
$cidx++; $cidx++;
$clusters[$cidx][0] = $i; $clusters[$cidx][0] = $i;
$clusters[$cidx][1] = 1; $clusters[$cidx][1] = 1;
} }
} }
else { else {
// Create a "cluster" of one since we are just crossing // Create a "cluster" of one since we are just crossing
// a quadrant // a quadrant
$cidx++; $cidx++;
$clusters[$cidx][0] = $i; $clusters[$cidx][0] = $i;
$clusters[$cidx][1] = 1; $clusters[$cidx][1] = 1;
} }
} }
else { else {
if( $incluster ) { if( $incluster ) {
// Add the last slice // Add the last slice
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
$incluster = false; $incluster = false;
} }
else { // Create a "cluster" of one else { // Create a "cluster" of one
$cidx++; $cidx++;
$clusters[$cidx][0] = $i; $clusters[$cidx][0] = $i;
$clusters[$cidx][1] = 1; $clusters[$cidx][1] = 1;
} }
} }
} }
// Handle the very last slice // Handle the very last slice
if( $incluster ) { if( $incluster ) {
$clusters[$cidx][1]++; $clusters[$cidx][1]++;
} }
else { // Create a "cluster" of one else { // Create a "cluster" of one
$cidx++; $cidx++;
$clusters[$cidx][0] = $i; $clusters[$cidx][0] = $i;
$clusters[$cidx][1] = 1; $clusters[$cidx][1] = 1;
} }
   
/* /*
if( true ) { if( true ) {
// Debug printout in labels // Debug printout in labels
for( $i=0; $i <= $cidx; ++$i ) { for( $i=0; $i <= $cidx; ++$i ) {
for( $j=0; $j < $clusters[$i][1]; ++$j ) { for( $j=0; $j < $clusters[$i][1]; ++$j ) {
$a = $this->la[$clusters[$i][0]+$j]; $a = $this->la[$clusters[$i][0]+$j];
$aa = round($a*180/M_PI); $aa = round($a*180/M_PI);
$q = $this->Quadrant($a); $q = $this->Quadrant($a);
$this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j"; $this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j";
} }
} }
} }
*/ */
   
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// Step 2 of the algorithm is use the clusters and draw the labels // Step 2 of the algorithm is use the clusters and draw the labels
// and guidelines // and guidelines
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
   
// We use the font height as the base factor for how far we need to // We use the font height as the base factor for how far we need to
// spread the labels in the Y-direction. // spread the labels in the Y-direction.
$this->value->ApplyFont($img); $this->value->ApplyFont($img);
$fh = $img->GetFontHeight(); $fh = $img->GetFontHeight();
$origvstep=$fh*$this->iGuideVFactor; $origvstep=$fh*$this->iGuideVFactor;
$this->value->SetMargin(0); $this->value->SetMargin(0);
   
// Number of clusters found // Number of clusters found
$nc = count($clusters); $nc = count($clusters);
   
// Walk through all the clusters // Walk through all the clusters
for($i=0; $i < $nc; ++$i) { for($i=0; $i < $nc; ++$i) {
   
// Start angle and number of slices in this cluster // Start angle and number of slices in this cluster
$csize = $clusters[$i][1]; $csize = $clusters[$i][1];
$a = $this->la[$clusters[$i][0]]; $a = $this->la[$clusters[$i][0]];
$q = $this->Quadrant($a); $q = $this->Quadrant($a);
   
// Now set up the start and end conditions to make sure that // 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 // 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" // 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. // we have different conditions depending on in which quadrant the slice lies within.
if( $q == 0 ) { if( $q == 0 ) {
$start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep; $start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep;
} }
elseif( $q == 1 ) { elseif( $q == 1 ) {
$start = 0; $idx = $start; $step = 1; $vstep = -$origvstep; $start = 0; $idx = $start; $step = 1; $vstep = -$origvstep;
} }
elseif( $q == 2 ) { elseif( $q == 2 ) {
$start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep; $start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep;
} }
elseif( $q == 3 ) { elseif( $q == 3 ) {
$start = 0; $idx = $start; $step = 1; $vstep = $origvstep; $start = 0; $idx = $start; $step = 1; $vstep = $origvstep;
} }
   
// Walk through all slices within this cluster // Walk through all slices within this cluster
for($j=0; $j < $csize; ++$j) { for($j=0; $j < $csize; ++$j) {
// Now adjust the position of the labels in each cluster starting // Now adjust the position of the labels in each cluster starting
// with the slice that is closest to the equator of the pie // with the slice that is closest to the equator of the pie
$a = $this->la[$clusters[$i][0]+$idx]; $a = $this->la[$clusters[$i][0]+$idx];
   
// Guide line start in the center of the arc of the slice // Guide line start in the center of the arc of the slice
$r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)];
$x = round($r*cos($a)+$xc); $x = round($r*cos($a)+$xc);
$y = round($yc-$r*sin($a)); $y = round($yc-$r*sin($a));
   
// The distance from the arc depends on chosen font and the "R-Factor" // The distance from the arc depends on chosen font and the "R-Factor"
$r += $fh*$this->iGuideLineRFactor; $r += $fh*$this->iGuideLineRFactor;
   
// Should the labels be placed curved along the pie or in straight columns // Should the labels be placed curved along the pie or in straight columns
// outside the pie? // outside the pie?
if( $this->iGuideLineCurve ) if( $this->iGuideLineCurve )
$xt=round($r*cos($a)+$xc); $xt=round($r*cos($a)+$xc);
   
// If this is the first slice in the cluster we need some first time // If this is the first slice in the cluster we need some first time
// proessing // proessing
if( $idx == $start ) { if( $idx == $start ) {
if( ! $this->iGuideLineCurve ) if( ! $this->iGuideLineCurve )
$xt=round($r*cos($a)+$xc); $xt=round($r*cos($a)+$xc);
$yt=round($yc-$r*sin($a)); $yt=round($yc-$r*sin($a));
   
// Some special consideration in case this cluster starts // Some special consideration in case this cluster starts
// in quadrant 1 or 3 very close to the "equator" (< 20 degrees) // in quadrant 1 or 3 very close to the "equator" (< 20 degrees)
// and the previous clusters last slice is within the tolerance. // and the previous clusters last slice is within the tolerance.
// In that case we add a font height to this labels Y-position // In that case we add a font height to this labels Y-position
// so it doesn't collide with // so it doesn't collide with
// the slice in the previous cluster // the slice in the previous cluster
$prevcluster = ($i + ($nc-1) ) % $nc; $prevcluster = ($i + ($nc-1) ) % $nc;
$previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1; $previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1;
if( $q == 1 && $a > 160*M_PI/180 ) { if( $q == 1 && $a > 160*M_PI/180 ) {
// Get the angle for the previous clusters last slice // Get the angle for the previous clusters last slice
$diff = abs($a-$this->la[$previdx]); $diff = abs($a-$this->la[$previdx]);
if( $diff < $tresh_hold ) { if( $diff < $tresh_hold ) {
$yt -= $fh; $yt -= $fh;
} }
} }
elseif( $q == 3 && $a > 340*M_PI/180 ) { elseif( $q == 3 && $a > 340*M_PI/180 ) {
// We need to subtract 360 to compare angle distance between // We need to subtract 360 to compare angle distance between
// q=0 and q=3 // q=0 and q=3
$diff = abs($a-$this->la[$previdx]-360*M_PI/180); $diff = abs($a-$this->la[$previdx]-360*M_PI/180);
if( $diff < $tresh_hold ) { if( $diff < $tresh_hold ) {
$yt += $fh; $yt += $fh;
} }
} }
   
} }
else { else {
// The step is at minimum $vstep but if the slices are relatively large // 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 // 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 // distance between the centers at the arc on the slice
$prev_a = $this->la[$clusters[$i][0]+($idx-$step)]; $prev_a = $this->la[$clusters[$i][0]+($idx-$step)];
$dy = abs($radius*(sin($a)-sin($prev_a))*1.2); $dy = abs($radius*(sin($a)-sin($prev_a))*1.2);
if( $vstep > 0 ) if( $vstep > 0 )
$yt += max($vstep,$dy); $yt += max($vstep,$dy);
else else
$yt += min($vstep,-$dy); $yt += min($vstep,-$dy);
} }
   
$label = $this->labels[$clusters[$i][0]+$idx]; $label = $this->labels[$clusters[$i][0]+$idx];
   
if( $csize == 1 ) { if( $csize == 1 ) {
// A "meta" cluster with only one slice // A "meta" cluster with only one slice
$r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)];
$rr = $r+$img->GetFontHeight()/2; $rr = $r+$img->GetFontHeight()/2;
$xt=round($rr*cos($a)+$xc); $xt=round($rr*cos($a)+$xc);
$yt=round($yc-$rr*sin($a)); $yt=round($yc-$rr*sin($a));
$this->StrokeLabel($label,$img,$xc,$yc,$a,$r); $this->StrokeLabel($label,$img,$xc,$yc,$a,$r);
if( $this->iShowGuideLineForSingle ) if( $this->iShowGuideLineForSingle )
$this->guideline->Stroke($img,$x,$y,$xt,$yt); $this->guideline->Stroke($img,$x,$y,$xt,$yt);
} }
else { else {
$this->guideline->Stroke($img,$x,$y,$xt,$yt); $this->guideline->Stroke($img,$x,$y,$xt,$yt);
if( $q==1 || $q==2 ) { if( $q==1 || $q==2 ) {
// Left side of Pie // Left side of Pie
$this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt); $this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt);
$lbladj = -$this->guidelinemargin-5; $lbladj = -$this->guidelinemargin-5;
$this->value->halign = "right"; $this->value->halign = "right";
$this->value->valign = "center"; $this->value->valign = "center";
} }
else { else {
// Right side of pie // Right side of pie
$this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt); $this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt);
$lbladj = $this->guidelinemargin+5; $lbladj = $this->guidelinemargin+5;
$this->value->halign = "left"; $this->value->halign = "left";
$this->value->valign = "center"; $this->value->valign = "center";
} }
$this->value->Stroke($img,$label,$xt+$lbladj,$yt); $this->value->Stroke($img,$label,$xt+$lbladj,$yt);
} }
   
// Udate idx to point to next slice in the cluster to process // Udate idx to point to next slice in the cluster to process
$idx += $step; $idx += $step;
} }
} }
} }
   
function StrokeAllLabels($img,$xc,$yc,$radius) { function StrokeAllLabels($img,$xc,$yc,$radius) {
// First normalize all angles for labels // First normalize all angles for labels
$n = count($this->la); $n = count($this->la);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$this->la[$i] = $this->NormAngle($this->la[$i]); $this->la[$i] = $this->NormAngle($this->la[$i]);
} }
if( $this->guideline->iShow ) { if( $this->guideline->iShow ) {
$this->StrokeGuideLabels($img,$xc,$yc,$radius); $this->StrokeGuideLabels($img,$xc,$yc,$radius);
} }
else { else {
$n = count($this->labels); $n = count($this->labels);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$this->StrokeLabel($this->labels[$i],$img,$xc,$yc, $this->StrokeLabel($this->labels[$i],$img,$xc,$yc,
$this->la[$i], $this->la[$i],
$radius + $this->explode_radius[$n-1-$i]); $radius + $this->explode_radius[$n-1-$i]);
} }
} }
} }
   
// Position the labels of each slice // Position the labels of each slice
function StrokeLabel($label,$img,$xc,$yc,$a,$r) { function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
   
// Default value // Default value
if( $this->ilabelposadj === 'auto' ) if( $this->ilabelposadj === 'auto' )
$this->ilabelposadj = 0.65; $this->ilabelposadj = 0.65;
   
// We position the values diferently depending on if they are inside // We position the values diferently depending on if they are inside
// or outside the pie // or outside the pie
if( $this->ilabelposadj < 1.0 ) { if( $this->ilabelposadj < 1.0 ) {
   
$this->value->SetAlign('center','center'); $this->value->SetAlign('center','center');
$this->value->margin = 0; $this->value->margin = 0;
   
$xt=round($this->ilabelposadj*$r*cos($a)+$xc); $xt=round($this->ilabelposadj*$r*cos($a)+$xc);
$yt=round($yc-$this->ilabelposadj*$r*sin($a)); $yt=round($yc-$this->ilabelposadj*$r*sin($a));
   
$this->value->Stroke($img,$label,$xt,$yt); $this->value->Stroke($img,$label,$xt,$yt);
} }
else { else {
   
$this->value->halign = "left"; $this->value->halign = "left";
$this->value->valign = "top"; $this->value->valign = "top";
$this->value->margin = 0; $this->value->margin = 0;
   
// Position the axis title. // Position the axis title.
// dx, dy is the offset from the top left corner of the bounding box that sorrounds the text // 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 // 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 // bit messy but this is really the only way of having a reasonable position of the
// axis titles. // axis titles.
$this->value->ApplyFont($img); $this->value->ApplyFont($img);
$h=$img->GetTextHeight($label); $h=$img->GetTextHeight($label);
// For numeric values the format of the display value // For numeric values the format of the display value
// must be taken into account // must be taken into account
if( is_numeric($label) ) { if( is_numeric($label) ) {
if( $label > 0 ) if( $label > 0 )
$w=$img->GetTextWidth(sprintf($this->value->format,$label)); $w=$img->GetTextWidth(sprintf($this->value->format,$label));
else else
$w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
} }
else else
$w=$img->GetTextWidth($label); $w=$img->GetTextWidth($label);
   
if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) { if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) {
$r *= $this->ilabelposadj; $r *= $this->ilabelposadj;
} }
   
$r += $img->GetFontHeight()/1.5; $r += $img->GetFontHeight()/1.5;
   
$xt=round($r*cos($a)+$xc); $xt=round($r*cos($a)+$xc);
$yt=round($yc-$r*sin($a)); $yt=round($yc-$r*sin($a));
   
// Normalize angle // Normalize angle
while( $a < 0 ) $a += 2*M_PI; while( $a < 0 ) $a += 2*M_PI;
while( $a > 2*M_PI ) $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>=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>=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>=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>=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>=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 ) $dy=(1-$a*2/M_PI);
if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; 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>=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; if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
   
$this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h); $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h);
} }
} }
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS PiePlotC // CLASS PiePlotC
// Description: Same as a normal pie plot but with a // Description: Same as a normal pie plot but with a
// filled circle in the center // filled circle in the center
//=================================================== //===================================================
class PiePlotC extends PiePlot { class PiePlotC extends PiePlot {
private $imidsize=0.5; // Fraction of total width private $imidsize=0.5; // Fraction of total width
private $imidcolor='white'; private $imidcolor='white';
public $midtitle=''; public $midtitle='';
private $middlecsimtarget='',$middlecsimwintarget='',$middlecsimalt=''; private $middlecsimtarget='',$middlecsimwintarget='',$middlecsimalt='';
   
function __construct($data,$aCenterTitle='') { function __construct($data,$aCenterTitle='') {
parent::__construct($data); parent::__construct($data);
$this->midtitle = new Text(); $this->midtitle = new Text();
$this->midtitle->ParagraphAlign('center'); $this->midtitle->ParagraphAlign('center');
} }
   
function SetMid($aTitle,$aColor='white',$aSize=0.5) { function SetMid($aTitle,$aColor='white',$aSize=0.5) {
$this->midtitle->Set($aTitle); $this->midtitle->Set($aTitle);
   
$this->imidsize = $aSize ; $this->imidsize = $aSize ;
$this->imidcolor = $aColor ; $this->imidcolor = $aColor ;
} }
   
function SetMidTitle($aTitle) { function SetMidTitle($aTitle) {
$this->midtitle->Set($aTitle); $this->midtitle->Set($aTitle);
} }
   
function SetMidSize($aSize) { function SetMidSize($aSize) {
$this->imidsize = $aSize ; $this->imidsize = $aSize ;
} }
   
function SetMidColor($aColor) { function SetMidColor($aColor) {
$this->imidcolor = $aColor ; $this->imidcolor = $aColor ;
} }
   
function SetMidCSIM($aTarget,$aAlt='',$aWinTarget='') { function SetMidCSIM($aTarget,$aAlt='',$aWinTarget='') {
$this->middlecsimtarget = $aTarget; $this->middlecsimtarget = $aTarget;
$this->middlecsimwintarget = $aWinTarget; $this->middlecsimwintarget = $aWinTarget;
$this->middlecsimalt = $aAlt; $this->middlecsimalt = $aAlt;
} }
   
function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
//Slice number, ellipse centre (x,y), radius, start angle, end angle //Slice number, ellipse centre (x,y), radius, start angle, end angle
while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI; while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI; while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
   
$sa = 2*M_PI - $sa; $sa = 2*M_PI - $sa;
$ea = 2*M_PI - $ea; $ea = 2*M_PI - $ea;
   
// Special case when we have only one slice since then both start and end // Special case when we have only one slice since then both start and end
// angle will be == 0 // angle will be == 0
if( abs($sa - $ea) < 0.0001 ) { if( abs($sa - $ea) < 0.0001 ) {
$sa=2*M_PI; $ea=0; $sa=2*M_PI; $ea=0;
} }
   
// Add inner circle first point // Add inner circle first point
$xp = floor(($this->imidsize*$radius*cos($ea))+$xc); $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
$yp = floor($yc-($this->imidsize*$radius*sin($ea))); $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
$coords = "$xp, $yp"; $coords = "$xp, $yp";
   
//add coordinates every 0.25 radians //add coordinates every 0.25 radians
$a=$ea+0.25; $a=$ea+0.25;
   
// If we cross the 360-limit with a slice we need to handle // If we cross the 360-limit with a slice we need to handle
// the fact that end angle is smaller than start // the fact that end angle is smaller than start
if( $sa < $ea ) { if( $sa < $ea ) {
while ($a <= 2*M_PI) { while ($a <= 2*M_PI) {
$xp = floor($radius*cos($a)+$xc); $xp = floor($radius*cos($a)+$xc);
$yp = floor($yc-$radius*sin($a)); $yp = floor($yc-$radius*sin($a));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$a += 0.25; $a += 0.25;
} }
$a -= 2*M_PI; $a -= 2*M_PI;
} }
   
while ($a < $sa) { while ($a < $sa) {
$xp = floor(($this->imidsize*$radius*cos($a)+$xc)); $xp = floor(($this->imidsize*$radius*cos($a)+$xc));
$yp = floor($yc-($this->imidsize*$radius*sin($a))); $yp = floor($yc-($this->imidsize*$radius*sin($a)));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$a += 0.25; $a += 0.25;
} }
   
// Make sure we end at the last point // Make sure we end at the last point
$xp = floor(($this->imidsize*$radius*cos($sa)+$xc)); $xp = floor(($this->imidsize*$radius*cos($sa)+$xc));
$yp = floor($yc-($this->imidsize*$radius*sin($sa))); $yp = floor($yc-($this->imidsize*$radius*sin($sa)));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
   
// Straight line to outer circle // Straight line to outer circle
$xp = floor($radius*cos($sa)+$xc); $xp = floor($radius*cos($sa)+$xc);
$yp = floor($yc-$radius*sin($sa)); $yp = floor($yc-$radius*sin($sa));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
   
//add coordinates every 0.25 radians //add coordinates every 0.25 radians
$a=$sa - 0.25; $a=$sa - 0.25;
while ($a > $ea) { while ($a > $ea) {
$xp = floor($radius*cos($a)+$xc); $xp = floor($radius*cos($a)+$xc);
$yp = floor($yc-$radius*sin($a)); $yp = floor($yc-$radius*sin($a));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$a -= 0.25; $a -= 0.25;
} }
   
//Add the last point on the arc //Add the last point on the arc
$xp = floor($radius*cos($ea)+$xc); $xp = floor($radius*cos($ea)+$xc);
$yp = floor($yc-$radius*sin($ea)); $yp = floor($yc-$radius*sin($ea));
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
   
// Close the arc // Close the arc
$xp = floor(($this->imidsize*$radius*cos($ea))+$xc); $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
$yp = floor($yc-($this->imidsize*$radius*sin($ea))); $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
$coords .= ", $xp, $yp"; $coords .= ", $xp, $yp";
   
if( !empty($this->csimtargets[$i]) ) { if( !empty($this->csimtargets[$i]) ) {
$this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"". $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".
$this->csimtargets[$i]."\""; $this->csimtargets[$i]."\"";
if( !empty($this->csimwintargets[$i]) ) { if( !empty($this->csimwintargets[$i]) ) {
$this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
} }
if( !empty($this->csimalts[$i]) ) { if( !empty($this->csimalts[$i]) ) {
$tmp=sprintf($this->csimalts[$i],$this->data[$i]); $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
} }
   
   
function Stroke($img,$aaoption=0) { function Stroke($img,$aaoption=0) {
   
// Stroke the pie but don't stroke values // Stroke the pie but don't stroke values
$tmp = $this->value->show; $tmp = $this->value->show;
$this->value->show = false; $this->value->show = false;
parent::Stroke($img,$aaoption); parent::Stroke($img,$aaoption);
$this->value->show = $tmp; $this->value->show = $tmp;
   
$xc = round($this->posx*$img->width); $xc = round($this->posx*$img->width);
$yc = round($this->posy*$img->height); $yc = round($this->posy*$img->height);
   
$radius = floor($this->radius * min($img->width,$img->height)) ; $radius = floor($this->radius * min($img->width,$img->height)) ;
   
   
if( $this->imidsize > 0 && $aaoption !== 2 ) { if( $this->imidsize > 0 && $aaoption !== 2 ) {
   
if( $this->ishadowcolor != "" ) { if( $this->ishadowcolor != "" ) {
$img->SetColor($this->ishadowcolor); $img->SetColor($this->ishadowcolor);
$img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop, $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop,
round($radius*$this->imidsize)); round($radius*$this->imidsize));
} }
   
$img->SetColor($this->imidcolor); $img->SetColor($this->imidcolor);
$img->FilledCircle($xc,$yc,round($radius*$this->imidsize)); $img->FilledCircle($xc,$yc,round($radius*$this->imidsize));
   
if( $this->pie_border && $aaoption === 0 ) { if( $this->pie_border && $aaoption === 0 ) {
$img->SetColor($this->color); $img->SetColor($this->color);
$img->Circle($xc,$yc,round($radius*$this->imidsize)); $img->Circle($xc,$yc,round($radius*$this->imidsize));
} }
   
if( !empty($this->middlecsimtarget) ) if( !empty($this->middlecsimtarget) )
$this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize)); $this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize));
   
} }
   
if( $this->value->show && $aaoption !== 1) { if( $this->value->show && $aaoption !== 1) {
$this->StrokeAllLabels($img,$xc,$yc,$radius); $this->StrokeAllLabels($img,$xc,$yc,$radius);
$this->midtitle->SetPos($xc,$yc,'center','center'); $this->midtitle->SetPos($xc,$yc,'center','center');
$this->midtitle->Stroke($img); $this->midtitle->Stroke($img);
} }
   
} }
   
function AddMiddleCSIM($xc,$yc,$r) { function AddMiddleCSIM($xc,$yc,$r) {
$xc=round($xc);$yc=round($yc);$r=round($r); $xc=round($xc);$yc=round($yc);$r=round($r);
$this->csimareas .= "<area shape=\"circle\" coords=\"$xc,$yc,$r\" href=\"". $this->csimareas .= "<area shape=\"circle\" coords=\"$xc,$yc,$r\" href=\"".
$this->middlecsimtarget."\""; $this->middlecsimtarget."\"";
if( !empty($this->middlecsimwintarget) ) { if( !empty($this->middlecsimwintarget) ) {
$this->csimareas .= " target=\"".$this->middlecsimwintarget."\""; $this->csimareas .= " target=\"".$this->middlecsimwintarget."\"";
} }
if( !empty($this->middlecsimalt) ) { if( !empty($this->middlecsimalt) ) {
$tmp = $this->middlecsimalt; $tmp = $this->middlecsimalt;
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
   
function StrokeLabel($label,$img,$xc,$yc,$a,$r) { function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
   
if( $this->ilabelposadj === 'auto' ) if( $this->ilabelposadj === 'auto' )
$this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize; $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
   
parent::StrokeLabel($label,$img,$xc,$yc,$a,$r); parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
   
} }
   
} }
   
   
//=================================================== //===================================================
// CLASS PieGraph // CLASS PieGraph
// Description: // Description:
//=================================================== //===================================================
class PieGraph extends Graph { class PieGraph extends Graph {
private $posx, $posy, $radius; private $posx, $posy, $radius;
private $legends=array(); private $legends=array();
public $plots=array(); public $plots=array();
public $pieaa = false ; public $pieaa = false ;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
parent::__construct($width,$height,$cachedName,$timeout,$inline); parent::__construct($width,$height,$cachedName,$timeout,$inline);
$this->posx=$width/2; $this->posx=$width/2;
$this->posy=$height/2; $this->posy=$height/2;
$this->SetColor(array(255,255,255)); $this->SetColor(array(255,255,255));
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function Add($aObj) { function Add($aObj) {
   
if( is_array($aObj) && count($aObj) > 0 ) if( is_array($aObj) && count($aObj) > 0 )
$cl = $aObj[0]; $cl = $aObj[0];
else else
$cl = $aObj; $cl = $aObj;
   
if( $cl instanceof Text ) if( $cl instanceof Text )
$this->AddText($aObj); $this->AddText($aObj);
elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) )
$this->AddIcon($aObj); $this->AddIcon($aObj);
else { else {
if( is_array($aObj) ) { if( is_array($aObj) ) {
$n = count($aObj); $n = count($aObj);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$this->plots[] = $aObj[$i]; $this->plots[] = $aObj[$i];
} }
} }
else { else {
$this->plots[] = $aObj; $this->plots[] = $aObj;
} }
} }
} }
   
function SetAntiAliasing($aFlg=true) { function SetAntiAliasing($aFlg=true) {
$this->pieaa = $aFlg; $this->pieaa = $aFlg;
} }
   
function SetColor($c) { function SetColor($c) {
$this->SetMarginColor($c); $this->SetMarginColor($c);
} }
   
   
function DisplayCSIMAreas() { function DisplayCSIMAreas() {
$csim=""; $csim="";
foreach($this->plots as $p ) { foreach($this->plots as $p ) {
$csim .= $p->GetCSIMareas(); $csim .= $p->GetCSIMareas();
} }
//$csim.= $this->legend->GetCSIMareas(); //$csim.= $this->legend->GetCSIMareas();
if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) { if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
$this->img->SetColor($this->csimcolor); $this->img->SetColor($this->csimcolor);
$n = count($coords[0]); $n = count($coords[0]);
for ($i=0; $i < $n; $i++) { for ($i=0; $i < $n; $i++) {
if ($coords[1][$i]=="poly") { if ($coords[1][$i]=="poly") {
preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts); 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]); $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
$m = count($pts[0]); $m = count($pts[0]);
for ($j=0; $j < $m; $j++) { for ($j=0; $j < $m; $j++) {
$this->img->LineTo($pts[1][$j],$pts[2][$j]); $this->img->LineTo($pts[1][$j],$pts[2][$j]);
} }
} else if ($coords[1][$i]=="rect") { } else if ($coords[1][$i]=="rect") {
$pts = preg_split('/,/', $coords[2][$i]); $pts = preg_split('/,/', $coords[2][$i]);
$this->img->SetStartPoint($pts[0],$pts[1]); $this->img->SetStartPoint($pts[0],$pts[1]);
$this->img->LineTo($pts[2],$pts[1]); $this->img->LineTo($pts[2],$pts[1]);
$this->img->LineTo($pts[2],$pts[3]); $this->img->LineTo($pts[2],$pts[3]);
$this->img->LineTo($pts[0],$pts[3]); $this->img->LineTo($pts[0],$pts[3]);
$this->img->LineTo($pts[0],$pts[1]); $this->img->LineTo($pts[0],$pts[1]);
   
} }
} }
} }
} }
   
// Method description // Method description
function Stroke($aStrokeFileName="") { function Stroke($aStrokeFileName="") {
// If the filename is the predefined value = '_csim_special_' // If the filename is the predefined value = '_csim_special_'
// we assume that the call to stroke only needs to do enough // we assume that the call to stroke only needs to do enough
// to correctly generate the CSIM maps. // to correctly generate the CSIM maps.
// We use this variable to skip things we don't strictly need // We use this variable to skip things we don't strictly need
// to do to generate the image map to improve performance // 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 // a best we can. Therefor you will see a lot of tests !$_csim in the
// code below. // code below.
$_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
   
// If we are called the second time (perhaps the user has called GetHTMLImageMap() // 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 // 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 // CSIM coordinats. Since we do not want the legends to be populated a second time
// we clear the legends // we clear the legends
$this->legend->Clear(); $this->legend->Clear();
   
// We need to know if we have stroked the plot in the // We need to know if we have stroked the plot in the
// GetCSIMareas. Otherwise the CSIM hasn't been generated // GetCSIMareas. Otherwise the CSIM hasn't been generated
// and in the case of GetCSIM called before stroke to generate // and in the case of GetCSIM called before stroke to generate
// CSIM without storing an image to disk GetCSIM must call Stroke. // CSIM without storing an image to disk GetCSIM must call Stroke.
$this->iHasStroked = true; $this->iHasStroked = true;
   
$n = count($this->plots); $n = count($this->plots);
   
if( $this->pieaa ) { if( $this->pieaa ) {
   
if( !$_csim ) { if( !$_csim ) {
if( $this->background_image != "" ) { if( $this->background_image != "" ) {
$this->StrokeFrameBackground(); $this->StrokeFrameBackground();
} }
else { else {
$this->StrokeFrame(); $this->StrokeFrame();
$this->StrokeBackgroundGrad(); $this->StrokeBackgroundGrad();
} }
} }
   
   
$w = $this->img->width; $w = $this->img->width;
$h = $this->img->height; $h = $this->img->height;
$oldimg = $this->img->img; $oldimg = $this->img->img;
   
$this->img->CreateImgCanvas(2*$w,2*$h); $this->img->CreateImgCanvas(2*$w,2*$h);
   
$this->img->SetColor( $this->margin_color ); $this->img->SetColor( $this->margin_color );
$this->img->FilledRectangle(0,0,2*$w-1,2*$h-1); $this->img->FilledRectangle(0,0,2*$w-1,2*$h-1);
   
// Make all icons *2 i size since we will be scaling down the // Make all icons *2 i size since we will be scaling down the
// imahe to do the anti aliasing // imahe to do the anti aliasing
$ni = count($this->iIcons); $ni = count($this->iIcons);
for($i=0; $i < $ni; ++$i) { for($i=0; $i < $ni; ++$i) {
$this->iIcons[$i]->iScale *= 2 ; $this->iIcons[$i]->iScale *= 2 ;
if( $this->iIcons[$i]->iX > 1 ) if( $this->iIcons[$i]->iX > 1 )
$this->iIcons[$i]->iX *= 2 ; $this->iIcons[$i]->iX *= 2 ;
if( $this->iIcons[$i]->iY > 1 ) if( $this->iIcons[$i]->iY > 1 )
$this->iIcons[$i]->iY *= 2 ; $this->iIcons[$i]->iY *= 2 ;
} }
   
$this->StrokeIcons(); $this->StrokeIcons();
   
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $this->plots[$i]->posx > 1 ) if( $this->plots[$i]->posx > 1 )
$this->plots[$i]->posx *= 2 ; $this->plots[$i]->posx *= 2 ;
if( $this->plots[$i]->posy > 1 ) if( $this->plots[$i]->posy > 1 )
$this->plots[$i]->posy *= 2 ; $this->plots[$i]->posy *= 2 ;
   
$this->plots[$i]->Stroke($this->img,1); $this->plots[$i]->Stroke($this->img,1);
   
if( $this->plots[$i]->posx > 1 ) if( $this->plots[$i]->posx > 1 )
$this->plots[$i]->posx /= 2 ; $this->plots[$i]->posx /= 2 ;
if( $this->plots[$i]->posy > 1 ) if( $this->plots[$i]->posy > 1 )
$this->plots[$i]->posy /= 2 ; $this->plots[$i]->posy /= 2 ;
} }
   
$indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ; $indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ;
$indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ; $indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ;
$this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent, $this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent,
$w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent)); $w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent));
   
$this->img->img = $oldimg ; $this->img->img = $oldimg ;
$this->img->width = $w ; $this->img->width = $w ;
$this->img->height = $h ; $this->img->height = $h ;
   
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$this->plots[$i]->Stroke($this->img,2); // Stroke labels $this->plots[$i]->Stroke($this->img,2); // Stroke labels
$this->plots[$i]->Legend($this); $this->plots[$i]->Legend($this);
} }
   
} }
else { else {
   
if( !$_csim ) { if( !$_csim ) {
if( $this->background_image != "" ) { if( $this->background_image != "" ) {
$this->StrokeFrameBackground(); $this->StrokeFrameBackground();
} }
else { else {
$this->StrokeFrame(); $this->StrokeFrame();
$this->StrokeBackgroundGrad(); $this->StrokeBackgroundGrad();
} }
} }
   
$this->StrokeIcons(); $this->StrokeIcons();
   
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$this->plots[$i]->Stroke($this->img); $this->plots[$i]->Stroke($this->img);
$this->plots[$i]->Legend($this); $this->plots[$i]->Legend($this);
} }
} }
   
$this->legend->Stroke($this->img); $this->legend->Stroke($this->img);
$this->footer->Stroke($this->img); $this->footer->Stroke($this->img);
$this->StrokeTitles(); $this->StrokeTitles();
   
if( !$_csim ) { if( !$_csim ) {
   
// Stroke texts // Stroke texts
if( $this->texts != null ) { if( $this->texts != null ) {
$n = count($this->texts); $n = count($this->texts);
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$this->texts[$i]->Stroke($this->img); $this->texts[$i]->Stroke($this->img);
} }
} }
   
if( _JPG_DEBUG ) { if( _JPG_DEBUG ) {
$this->DisplayCSIMAreas(); $this->DisplayCSIMAreas();
} }
   
// Should we do any final image transformation // Should we do any final image transformation
if( $this->iImgTrans ) { if( $this->iImgTrans ) {
if( !class_exists('ImgTrans',false) ) { if( !class_exists('ImgTrans',false) ) {
require_once('jpgraph_imgtrans.php'); require_once('jpgraph_imgtrans.php');
//JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.'); //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); $tform = new ImgTrans($this->img->img);
$this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
$this->iImgTransDirection,$this->iImgTransHighQ, $this->iImgTransDirection,$this->iImgTransHighQ,
$this->iImgTransMinSize,$this->iImgTransFillColor, $this->iImgTransMinSize,$this->iImgTransFillColor,
$this->iImgTransBorder); $this->iImgTransBorder);
} }
   
   
// If the filename is given as the special "__handle" // If the filename is given as the special "__handle"
// then the image handler is returned and the image is NOT // then the image handler is returned and the image is NOT
// streamed back // streamed back
if( $aStrokeFileName == _IMG_HANDLER ) { if( $aStrokeFileName == _IMG_HANDLER ) {
return $this->img->img; return $this->img->img;
} }
else { else {
// Finally stream the generated picture // Finally stream the generated picture
$this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
$aStrokeFileName); $aStrokeFileName);
} }
} }
} }
} // Class } // Class
   
/* EOF */ /* EOF */
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_PIE3D.PHP // File: JPGRAPH_PIE3D.PHP
// Description: 3D Pie plot extension for JpGraph // Description: 3D Pie plot extension for JpGraph
// Created: 2001-03-24 // Created: 2001-03-24
// Ver: $Id: jpgraph_pie3d.php 1329 2009-06-20 19:23:30Z ljp $ // Ver: $Id: jpgraph_pie3d.php 1329 2009-06-20 19:23:30Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
//=================================================== //===================================================
// CLASS PiePlot3D // CLASS PiePlot3D
// Description: Plots a 3D pie with a specified projection // Description: Plots a 3D pie with a specified projection
// angle between 20 and 70 degrees. // angle between 20 and 70 degrees.
//=================================================== //===================================================
class PiePlot3D extends PiePlot { class PiePlot3D extends PiePlot {
private $labelhintcolor="red",$showlabelhint=true; private $labelhintcolor="red",$showlabelhint=true;
private $angle=50; private $angle=50;
private $edgecolor="", $edgeweight=1; private $edgecolor="", $edgeweight=1;
private $iThickness=false; private $iThickness=false;
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($data) { function __construct($data) {
$this->radius = 0.5; $this->radius = 0.5;
$this->data = $data; $this->data = $data;
$this->title = new Text(""); $this->title = new Text("");
$this->title->SetFont(FF_FONT1,FS_BOLD); $this->title->SetFont(FF_FONT1,FS_BOLD);
$this->value = new DisplayValue(); $this->value = new DisplayValue();
$this->value->Show(); $this->value->Show();
$this->value->SetFormat('%.0f%%'); $this->value->SetFormat('%.0f%%');
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
// Set label arrays // Set label arrays
function SetLegends($aLegend) { function SetLegends($aLegend) {
$this->legends = array_reverse(array_slice($aLegend,0,count($this->data))); $this->legends = array_reverse(array_slice($aLegend,0,count($this->data)));
} }
   
function SetSliceColors($aColors) { function SetSliceColors($aColors) {
$this->setslicecolors = $aColors; $this->setslicecolors = $aColors;
} }
   
function Legend($aGraph) { function Legend($aGraph) {
parent::Legend($aGraph); parent::Legend($aGraph);
$aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol); $aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol);
} }
   
function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') { function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
$this->csimtargets = $aTargets; $this->csimtargets = $aTargets;
$this->csimwintargets = $aWinTargets; $this->csimwintargets = $aWinTargets;
$this->csimalts = $aAlts; $this->csimalts = $aAlts;
} }
   
// Should the slices be separated by a line? If color is specified as "" no line // Should the slices be separated by a line? If color is specified as "" no line
// will be used to separate pie slices. // will be used to separate pie slices.
function SetEdge($aColor='black',$aWeight=1) { function SetEdge($aColor='black',$aWeight=1) {
$this->edgecolor = $aColor; $this->edgecolor = $aColor;
$this->edgeweight = $aWeight; $this->edgeweight = $aWeight;
} }
   
// Specify projection angle for 3D in degrees // Specify projection angle for 3D in degrees
// Must be between 20 and 70 degrees // Must be between 20 and 70 degrees
function SetAngle($a) { function SetAngle($a) {
if( $a<5 || $a>90 ) { if( $a<5 || $a>90 ) {
JpGraphError::RaiseL(14002); JpGraphError::RaiseL(14002);
//("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees."); //("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.");
} }
else { else {
$this->angle = $a; $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 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; $sa *= M_PI/180;
$ea *= M_PI/180; $ea *= M_PI/180;
   
//add coordinates of the centre to the map //add coordinates of the centre to the map
$coords = "$xc, $yc"; $coords = "$xc, $yc";
   
//add coordinates of the first point on the arc to the map //add coordinates of the first point on the arc to the map
$xp = floor($width*cos($sa)/2+$xc); $xp = floor($width*cos($sa)/2+$xc);
$yp = floor($yc-$height*sin($sa)/2); $yp = floor($yc-$height*sin($sa)/2);
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
   
//If on the front half, add the thickness offset //If on the front half, add the thickness offset
if ($sa >= M_PI && $sa <= 2*M_PI*1.01) { if ($sa >= M_PI && $sa <= 2*M_PI*1.01) {
$yp = floor($yp+$thick); $yp = floor($yp+$thick);
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
} }
   
//add coordinates every 0.2 radians //add coordinates every 0.2 radians
$a=$sa+0.2; $a=$sa+0.2;
while ($a<$ea) { while ($a<$ea) {
$xp = floor($width*cos($a)/2+$xc); $xp = floor($width*cos($a)/2+$xc);
if ($a >= M_PI && $a <= 2*M_PI*1.01) { if ($a >= M_PI && $a <= 2*M_PI*1.01) {
$yp = floor($yc-($height*sin($a)/2)+$thick); $yp = floor($yc-($height*sin($a)/2)+$thick);
} else { } else {
$yp = floor($yc-$height*sin($a)/2); $yp = floor($yc-$height*sin($a)/2);
} }
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$a += 0.2; $a += 0.2;
} }
   
//Add the last point on the arc //Add the last point on the arc
$xp = floor($width*cos($ea)/2+$xc); $xp = floor($width*cos($ea)/2+$xc);
$yp = floor($yc-$height*sin($ea)/2); $yp = floor($yc-$height*sin($ea)/2);
   
   
if ($ea >= M_PI && $ea <= 2*M_PI*1.01) { if ($ea >= M_PI && $ea <= 2*M_PI*1.01) {
$coords.= ", $xp, ".floor($yp+$thick); $coords.= ", $xp, ".floor($yp+$thick);
} }
$coords.= ", $xp, $yp"; $coords.= ", $xp, $yp";
$alt=''; $alt='';
   
if( !empty($this->csimtargets[$i]) ) { if( !empty($this->csimtargets[$i]) ) {
$this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\""; $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\"";
   
if( !empty($this->csimwintargets[$i]) ) { if( !empty($this->csimwintargets[$i]) ) {
$this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
} }
if( !empty($this->csimalts[$i]) ) { if( !empty($this->csimalts[$i]) ) {
$tmp=sprintf($this->csimalts[$i],$this->data[$i]); $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
$this->csimareas .= "alt=\"$tmp\" title=\"$tmp\" "; $this->csimareas .= "alt=\"$tmp\" title=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
   
} }
   
function SetLabels($aLabels,$aLblPosAdj="auto") { function SetLabels($aLabels,$aLblPosAdj="auto") {
$this->labels = $aLabels; $this->labels = $aLabels;
$this->ilabelposadj=$aLblPosAdj; $this->ilabelposadj=$aLblPosAdj;
} }
   
   
// Distance from the pie to the labels // Distance from the pie to the labels
function SetLabelMargin($m) { function SetLabelMargin($m) {
$this->value->SetMargin($m); $this->value->SetMargin($m);
} }
   
// Show a thin line from the pie to the label for a specific slice // Show a thin line from the pie to the label for a specific slice
function ShowLabelHint($f=true) { function ShowLabelHint($f=true) {
$this->showlabelhint=$f; $this->showlabelhint=$f;
} }
   
// Set color of hint line to label for each slice // Set color of hint line to label for each slice
function SetLabelHintColor($c) { function SetLabelHintColor($c) {
$this->labelhintcolor=$c; $this->labelhintcolor=$c;
} }
   
function SetHeight($aHeight) { function SetHeight($aHeight) {
$this->iThickness = $aHeight; $this->iThickness = $aHeight;
} }
   
   
// Normalize Angle between 0-360 // Normalize Angle between 0-360
function NormAngle($a) { function NormAngle($a) {
// Normalize anle to 0 to 2M_PI // Normalize anle to 0 to 2M_PI
// //
if( $a > 0 ) { if( $a > 0 ) {
while($a > 360) $a -= 360; while($a > 360) $a -= 360;
} }
else { else {
while($a < 0) $a += 360; while($a < 0) $a += 360;
} }
if( $a < 0 ) if( $a < 0 )
$a = 360 + $a; $a = 360 + $a;
   
if( $a == 360 ) $a=0; if( $a == 360 ) $a=0;
return $a; return $a;
} }
   
   
   
// Draw one 3D pie slice at position ($xc,$yc) with height $z // 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) { 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 // Due to the way the 3D Pie algorithm works we are
// guaranteed that any slice we get into this method // guaranteed that any slice we get into this method
// belongs to either the left or right side of the // belongs to either the left or right side of the
// pie ellipse. Hence, no slice will cross 90 or 270 // pie ellipse. Hence, no slice will cross 90 or 270
// point. // point.
if( ($sa < 90 && $ea > 90) || ( ($sa > 90 && $sa < 270) && $ea > 270) ) { if( ($sa < 90 && $ea > 90) || ( ($sa > 90 && $sa < 270) && $ea > 270) ) {
JpGraphError::RaiseL(14003);//('Internal assertion failed. Pie3D::Pie3DSlice'); JpGraphError::RaiseL(14003);//('Internal assertion failed. Pie3D::Pie3DSlice');
exit(1); exit(1);
} }
   
$p[] = array(); $p[] = array();
   
// Setup pre-calculated values // Setup pre-calculated values
$rsa = $sa/180*M_PI; // to Rad $rsa = $sa/180*M_PI; // to Rad
$rea = $ea/180*M_PI; // to Rad $rea = $ea/180*M_PI; // to Rad
$sinsa = sin($rsa); $sinsa = sin($rsa);
$cossa = cos($rsa); $cossa = cos($rsa);
$sinea = sin($rea); $sinea = sin($rea);
$cosea = cos($rea); $cosea = cos($rea);
   
// p[] is the points for the overall slice and // p[] is the points for the overall slice and
// pt[] is the points for the top pie // pt[] is the points for the top pie
   
// Angular step when approximating the arc with a polygon train. // Angular step when approximating the arc with a polygon train.
$step = 0.05; $step = 0.05;
   
if( $sa >= 270 ) { if( $sa >= 270 ) {
if( $ea > 360 || ($ea > 0 && $ea <= 90) ) { if( $ea > 360 || ($ea > 0 && $ea <= 90) ) {
if( $ea > 0 && $ea <= 90 ) { if( $ea > 0 && $ea <= 90 ) {
// Adjust angle to simplify conditions in loops // Adjust angle to simplify conditions in loops
$rea += 2*M_PI; $rea += 2*M_PI;
} }
   
$p = array($xc,$yc,$xc,$yc+$z, $p = array($xc,$yc,$xc,$yc+$z,
$xc+$w*$cossa,$z+$yc-$h*$sinsa); $xc+$w*$cossa,$z+$yc-$h*$sinsa);
$pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
   
for( $a=$rsa; $a < 2*M_PI; $a += $step ) { for( $a=$rsa; $a < 2*M_PI; $a += $step ) {
$tca = cos($a); $tca = cos($a);
$tsa = sin($a); $tsa = sin($a);
$p[] = $xc+$w*$tca; $p[] = $xc+$w*$tca;
$p[] = $z+$yc-$h*$tsa; $p[] = $z+$yc-$h*$tsa;
$pt[] = $xc+$w*$tca; $pt[] = $xc+$w*$tca;
$pt[] = $yc-$h*$tsa; $pt[] = $yc-$h*$tsa;
} }
   
$pt[] = $xc+$w; $pt[] = $xc+$w;
$pt[] = $yc; $pt[] = $yc;
   
$p[] = $xc+$w; $p[] = $xc+$w;
$p[] = $z+$yc; $p[] = $z+$yc;
$p[] = $xc+$w; $p[] = $xc+$w;
$p[] = $yc; $p[] = $yc;
$p[] = $xc; $p[] = $xc;
$p[] = $yc; $p[] = $yc;
   
for( $a=2*M_PI+$step; $a < $rea; $a += $step ) { for( $a=2*M_PI+$step; $a < $rea; $a += $step ) {
$pt[] = $xc + $w*cos($a); $pt[] = $xc + $w*cos($a);
$pt[] = $yc - $h*sin($a); $pt[] = $yc - $h*sin($a);
} }
   
$pt[] = $xc+$w*$cosea; $pt[] = $xc+$w*$cosea;
$pt[] = $yc-$h*$sinea; $pt[] = $yc-$h*$sinea;
$pt[] = $xc; $pt[] = $xc;
$pt[] = $yc; $pt[] = $yc;
   
} }
else { else {
$p = array($xc,$yc,$xc,$yc+$z, $p = array($xc,$yc,$xc,$yc+$z,
$xc+$w*$cossa,$z+$yc-$h*$sinsa); $xc+$w*$cossa,$z+$yc-$h*$sinsa);
$pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
   
$rea = $rea == 0.0 ? 2*M_PI : $rea; $rea = $rea == 0.0 ? 2*M_PI : $rea;
for( $a=$rsa; $a < $rea; $a += $step ) { for( $a=$rsa; $a < $rea; $a += $step ) {
$tca = cos($a); $tca = cos($a);
$tsa = sin($a); $tsa = sin($a);
$p[] = $xc+$w*$tca; $p[] = $xc+$w*$tca;
$p[] = $z+$yc-$h*$tsa; $p[] = $z+$yc-$h*$tsa;
$pt[] = $xc+$w*$tca; $pt[] = $xc+$w*$tca;
$pt[] = $yc-$h*$tsa; $pt[] = $yc-$h*$tsa;
} }
   
$pt[] = $xc+$w*$cosea; $pt[] = $xc+$w*$cosea;
$pt[] = $yc-$h*$sinea; $pt[] = $yc-$h*$sinea;
$pt[] = $xc; $pt[] = $xc;
$pt[] = $yc; $pt[] = $yc;
   
$p[] = $xc+$w*$cosea; $p[] = $xc+$w*$cosea;
$p[] = $z+$yc-$h*$sinea; $p[] = $z+$yc-$h*$sinea;
$p[] = $xc+$w*$cosea; $p[] = $xc+$w*$cosea;
$p[] = $yc-$h*$sinea; $p[] = $yc-$h*$sinea;
$p[] = $xc; $p[] = $xc;
$p[] = $yc; $p[] = $yc;
} }
} }
elseif( $sa >= 180 ) { elseif( $sa >= 180 ) {
$p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea); $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea);
$pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
   
for( $a=$rea; $a>$rsa; $a -= $step ) { for( $a=$rea; $a>$rsa; $a -= $step ) {
$tca = cos($a); $tca = cos($a);
$tsa = sin($a); $tsa = sin($a);
$p[] = $xc+$w*$tca; $p[] = $xc+$w*$tca;
$p[] = $z+$yc-$h*$tsa; $p[] = $z+$yc-$h*$tsa;
$pt[] = $xc+$w*$tca; $pt[] = $xc+$w*$tca;
$pt[] = $yc-$h*$tsa; $pt[] = $yc-$h*$tsa;
} }
   
$pt[] = $xc+$w*$cossa; $pt[] = $xc+$w*$cossa;
$pt[] = $yc-$h*$sinsa; $pt[] = $yc-$h*$sinsa;
$pt[] = $xc; $pt[] = $xc;
$pt[] = $yc; $pt[] = $yc;
   
$p[] = $xc+$w*$cossa; $p[] = $xc+$w*$cossa;
$p[] = $z+$yc-$h*$sinsa; $p[] = $z+$yc-$h*$sinsa;
$p[] = $xc+$w*$cossa; $p[] = $xc+$w*$cossa;
$p[] = $yc-$h*$sinsa; $p[] = $yc-$h*$sinsa;
$p[] = $xc; $p[] = $xc;
$p[] = $yc; $p[] = $yc;
   
} }
elseif( $sa >= 90 ) { elseif( $sa >= 90 ) {
if( $ea > 180 ) { if( $ea > 180 ) {
$p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea); $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea);
$pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
   
for( $a=$rea; $a > M_PI; $a -= $step ) { for( $a=$rea; $a > M_PI; $a -= $step ) {
$tca = cos($a); $tca = cos($a);
$tsa = sin($a); $tsa = sin($a);
$p[] = $xc+$w*$tca; $p[] = $xc+$w*$tca;
$p[] = $z + $yc - $h*$tsa; $p[] = $z + $yc - $h*$tsa;
$pt[] = $xc+$w*$tca; $pt[] = $xc+$w*$tca;
$pt[] = $yc-$h*$tsa; $pt[] = $yc-$h*$tsa;
} }
   
$p[] = $xc-$w; $p[] = $xc-$w;
$p[] = $z+$yc; $p[] = $z+$yc;
$p[] = $xc-$w; $p[] = $xc-$w;
$p[] = $yc; $p[] = $yc;
$p[] = $xc; $p[] = $xc;
$p[] = $yc; $p[] = $yc;
   
$pt[] = $xc-$w; $pt[] = $xc-$w;
$pt[] = $z+$yc; $pt[] = $z+$yc;
$pt[] = $xc-$w; $pt[] = $xc-$w;
$pt[] = $yc; $pt[] = $yc;
   
for( $a=M_PI-$step; $a > $rsa; $a -= $step ) { for( $a=M_PI-$step; $a > $rsa; $a -= $step ) {
$pt[] = $xc + $w*cos($a); $pt[] = $xc + $w*cos($a);
$pt[] = $yc - $h*sin($a); $pt[] = $yc - $h*sin($a);
} }
   
$pt[] = $xc+$w*$cossa; $pt[] = $xc+$w*$cossa;
$pt[] = $yc-$h*$sinsa; $pt[] = $yc-$h*$sinsa;
$pt[] = $xc; $pt[] = $xc;
$pt[] = $yc; $pt[] = $yc;
   
} }
else { // $sa >= 90 && $ea <= 180 else { // $sa >= 90 && $ea <= 180
$p = array($xc,$yc,$xc,$yc+$z, $p = array($xc,$yc,$xc,$yc+$z,
$xc+$w*$cosea,$z+$yc-$h*$sinea, $xc+$w*$cosea,$z+$yc-$h*$sinea,
$xc+$w*$cosea,$yc-$h*$sinea, $xc+$w*$cosea,$yc-$h*$sinea,
$xc,$yc); $xc,$yc);
   
$pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea); $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
   
for( $a=$rea; $a>$rsa; $a -= $step ) { for( $a=$rea; $a>$rsa; $a -= $step ) {
$pt[] = $xc + $w*cos($a); $pt[] = $xc + $w*cos($a);
$pt[] = $yc - $h*sin($a); $pt[] = $yc - $h*sin($a);
} }
   
$pt[] = $xc+$w*$cossa; $pt[] = $xc+$w*$cossa;
$pt[] = $yc-$h*$sinsa; $pt[] = $yc-$h*$sinsa;
$pt[] = $xc; $pt[] = $xc;
$pt[] = $yc; $pt[] = $yc;
   
} }
} }
else { // sa > 0 && ea < 90 else { // sa > 0 && ea < 90
   
$p = array($xc,$yc,$xc,$yc+$z, $p = array($xc,$yc,$xc,$yc+$z,
$xc+$w*$cossa,$z+$yc-$h*$sinsa, $xc+$w*$cossa,$z+$yc-$h*$sinsa,
$xc+$w*$cossa,$yc-$h*$sinsa, $xc+$w*$cossa,$yc-$h*$sinsa,
$xc,$yc); $xc,$yc);
   
$pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa); $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
   
for( $a=$rsa; $a < $rea; $a += $step ) { for( $a=$rsa; $a < $rea; $a += $step ) {
$pt[] = $xc + $w*cos($a); $pt[] = $xc + $w*cos($a);
$pt[] = $yc - $h*sin($a); $pt[] = $yc - $h*sin($a);
} }
   
$pt[] = $xc+$w*$cosea; $pt[] = $xc+$w*$cosea;
$pt[] = $yc-$h*$sinea; $pt[] = $yc-$h*$sinea;
$pt[] = $xc; $pt[] = $xc;
$pt[] = $yc; $pt[] = $yc;
} }
$img->PushColor($fillcolor.":".$shadow); $img->PushColor($fillcolor.":".$shadow);
$img->FilledPolygon($p); $img->FilledPolygon($p);
$img->PopColor(); $img->PopColor();
   
$img->PushColor($fillcolor); $img->PushColor($fillcolor);
$img->FilledPolygon($pt); $img->FilledPolygon($pt);
$img->PopColor(); $img->PopColor();
} }
   
function SetStartAngle($aStart) { function SetStartAngle($aStart) {
if( $aStart < 0 || $aStart > 360 ) { if( $aStart < 0 || $aStart > 360 ) {
JpGraphError::RaiseL(14004);//('Slice start angle must be between 0 and 360 degrees.'); JpGraphError::RaiseL(14004);//('Slice start angle must be between 0 and 360 degrees.');
} }
$this->startangle = $aStart; $this->startangle = $aStart;
} }
   
// Draw a 3D Pie // Draw a 3D Pie
function Pie3D($aaoption,$img,$data,$colors,$xc,$yc,$d,$angle,$z, function Pie3D($aaoption,$img,$data,$colors,$xc,$yc,$d,$angle,$z,
$shadow=0.65,$startangle=0,$edgecolor="",$edgeweight=1) { $shadow=0.65,$startangle=0,$edgecolor="",$edgeweight=1) {
   
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// As usual the algorithm get more complicated than I originally // As usual the algorithm get more complicated than I originally
// envisioned. I believe that this is as simple as it is possible // 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 // 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 // thinking on how to do this to convince your self that all this
// is really needed for the general case. // is really needed for the general case.
// //
// The algorithm two draw 3D pies without "real 3D" is done in // The algorithm two draw 3D pies without "real 3D" is done in
// two steps. // two steps.
// First imagine the pie cut in half through a thought line between // 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 // 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 // the individual slices for each half by starting with the topmost
// pie slice and continue down to 6'a clock. // pie slice and continue down to 6'a clock.
// //
// In the algortithm this is done in three principal steps // In the algortithm this is done in three principal steps
// Step 1. Do the knife cut to ensure by splitting slices that extends // 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 // over the cut line. This is done by splitting the original slices into
// upto 3 subslices. // upto 3 subslices.
// Step 2. Find the top slice for each half // Step 2. Find the top slice for each half
// Step 3. Draw the slices from top to bottom // Step 3. Draw the slices from top to bottom
// //
// The thing that slightly complicates this scheme with all the // The thing that slightly complicates this scheme with all the
// angle comparisons below is that we can have an arbitrary start // angle comparisons below is that we can have an arbitrary start
// angle so we must take into account the different equivalence classes. // angle so we must take into account the different equivalence classes.
// For the same reason we must walk through the angle array in a // For the same reason we must walk through the angle array in a
// modulo fashion. // modulo fashion.
// //
// Limitations of algorithm: // Limitations of algorithm:
// * A small exploded slice which crosses the 270 degree point // * A small exploded slice which crosses the 270 degree point
// will get slightly nagged close to the center due to the fact that // 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 // we print the slices in Z-order and that the slice left part
// get printed first and might get slightly nagged by a larger // 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 on the right side just before the right part of the small
// slice. Not a major problem though. // slice. Not a major problem though.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
   
   
// Determine the height of the ellippse which gives an // Determine the height of the ellippse which gives an
// indication of the inclination angle // indication of the inclination angle
$h = ($angle/90.0)*$d; $h = ($angle/90.0)*$d;
$sum = 0; $sum = 0;
for($i=0; $i<count($data); ++$i ) { for($i=0; $i<count($data); ++$i ) {
$sum += $data[$i]; $sum += $data[$i];
} }
   
// Special optimization // Special optimization
if( $sum==0 ) return; if( $sum==0 ) return;
   
if( $this->labeltype == 2 ) { if( $this->labeltype == 2 ) {
$this->adjusted_data = $this->AdjPercentage($data); $this->adjusted_data = $this->AdjPercentage($data);
} }
   
// Setup the start // Setup the start
$accsum = 0; $accsum = 0;
$a = $startangle; $a = $startangle;
$a = $this->NormAngle($a); $a = $this->NormAngle($a);
   
// //
// Step 1 . Split all slices that crosses 90 or 270 // Step 1 . Split all slices that crosses 90 or 270
// //
$idx=0; $idx=0;
$adjexplode=array(); $adjexplode=array();
$numcolors = count($colors); $numcolors = count($colors);
for($i=0; $i<count($data); ++$i, ++$idx ) { for($i=0; $i<count($data); ++$i, ++$idx ) {
$da = $data[$i]/$sum * 360; $da = $data[$i]/$sum * 360;
   
if( empty($this->explode_radius[$i]) ) { if( empty($this->explode_radius[$i]) ) {
$this->explode_radius[$i]=0; $this->explode_radius[$i]=0;
} }
   
$expscale=1; $expscale=1;
if( $aaoption == 1 ) { if( $aaoption == 1 ) {
$expscale=2; $expscale=2;
} }
   
$la = $a + $da/2; $la = $a + $da/2;
$explode = array( $xc + $this->explode_radius[$i]*cos($la*M_PI/180)*$expscale, $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 ); $yc - $this->explode_radius[$i]*sin($la*M_PI/180) * ($h/$d) *$expscale );
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
$labeldata[$i] = array($la,$explode[0],$explode[1]); $labeldata[$i] = array($la,$explode[0],$explode[1]);
$originalangles[$i] = array($a,$a+$da); $originalangles[$i] = array($a,$a+$da);
   
$ne = $this->NormAngle($a+$da); $ne = $this->NormAngle($a+$da);
if( $da <= 180 ) { if( $da <= 180 ) {
// If the slice size is <= 90 it can at maximum cut across // If the slice size is <= 90 it can at maximum cut across
// one boundary (either 90 or 270) where it needs to be split // one boundary (either 90 or 270) where it needs to be split
$split=-1; // no split $split=-1; // no split
if( ($da<=90 && ($a <= 90 && $ne > 90)) || if( ($da<=90 && ($a <= 90 && $ne > 90)) ||
(($da <= 180 && $da >90) && (($a < 90 || $a >= 270) && $ne > 90)) ) { (($da <= 180 && $da >90) && (($a < 90 || $a >= 270) && $ne > 90)) ) {
$split = 90; $split = 90;
} }
elseif( ($da<=90 && ($a <= 270 && $ne > 270)) || elseif( ($da<=90 && ($a <= 270 && $ne > 270)) ||
(($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) { (($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) {
$split = 270; $split = 270;
} }
if( $split > 0 ) { // split in two if( $split > 0 ) { // split in two
$angles[$idx] = array($a,$split); $angles[$idx] = array($a,$split);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
$angles[++$idx] = array($split,$ne); $angles[++$idx] = array($split,$ne);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
} }
else { // no split else { // no split
$angles[$idx] = array($a,$ne); $angles[$idx] = array($a,$ne);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
} }
} }
else { else {
// da>180 // da>180
// Slice may, depending on position, cross one or two // Slice may, depending on position, cross one or two
// bonudaries // bonudaries
   
if( $a < 90 ) $split = 90; if( $a < 90 ) $split = 90;
elseif( $a <= 270 ) $split = 270; elseif( $a <= 270 ) $split = 270;
else $split = 90; else $split = 90;
   
$angles[$idx] = array($a,$split); $angles[$idx] = array($a,$split);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
//if( $a+$da > 360-$split ) { //if( $a+$da > 360-$split ) {
// For slices larger than 270 degrees we might cross // For slices larger than 270 degrees we might cross
// another boundary as well. This means that we must // another boundary as well. This means that we must
// split the slice further. The comparison gets a little // split the slice further. The comparison gets a little
// bit complicated since we must take into accound that // bit complicated since we must take into accound that
// a pie might have a startangle >0 and hence a slice might // a pie might have a startangle >0 and hence a slice might
// wrap around the 0 angle. // wrap around the 0 angle.
// Three cases: // Three cases:
// a) Slice starts before 90 and hence gets a split=90, but // a) Slice starts before 90 and hence gets a split=90, but
// we must also check if we need to split at 270 // we must also check if we need to split at 270
// b) Slice starts after 90 but before 270 and slices // b) Slice starts after 90 but before 270 and slices
// crosses 90 (after a wrap around of 0) // crosses 90 (after a wrap around of 0)
// c) If start is > 270 (hence the firstr split is at 90) // c) If start is > 270 (hence the firstr split is at 90)
// and the slice is so large that it goes all the way // and the slice is so large that it goes all the way
// around 270. // around 270.
if( ($a < 90 && ($a+$da > 270)) || ($a > 90 && $a<=270 && ($a+$da>360+90) ) || ($a > 270 && $this->NormAngle($a+$da)>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); $angles[++$idx] = array($split,360-$split);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
$angles[++$idx] = array(360-$split,$ne); $angles[++$idx] = array(360-$split,$ne);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
} }
else { else {
// Just a simple split to the previous decided // Just a simple split to the previous decided
// angle. // angle.
$angles[++$idx] = array($split,$ne); $angles[++$idx] = array($split,$ne);
$adjcolors[$idx] = $colors[$i % $numcolors]; $adjcolors[$idx] = $colors[$i % $numcolors];
$adjexplode[$idx] = $explode; $adjexplode[$idx] = $explode;
} }
} }
$a += $da; $a += $da;
$a = $this->NormAngle($a); $a = $this->NormAngle($a);
} }
   
// Total number of slices // Total number of slices
$n = count($angles); $n = count($angles);
   
for($i=0; $i<$n; ++$i) { for($i=0; $i<$n; ++$i) {
list($dbgs,$dbge) = $angles[$i]; list($dbgs,$dbge) = $angles[$i];
} }
   
// //
// Step 2. Find start index (first pie that starts in upper left quadrant) // Step 2. Find start index (first pie that starts in upper left quadrant)
// //
$minval = $angles[0][0]; $minval = $angles[0][0];
$min = 0; $min = 0;
for( $i=0; $i<$n; ++$i ) { for( $i=0; $i<$n; ++$i ) {
if( $angles[$i][0] < $minval ) { if( $angles[$i][0] < $minval ) {
$minval = $angles[$i][0]; $minval = $angles[$i][0];
$min = $i; $min = $i;
} }
} }
$j = $min; $j = $min;
$cnt = 0; $cnt = 0;
while( $angles[$j][1] <= 90 ) { while( $angles[$j][1] <= 90 ) {
$j++; $j++;
if( $j>=$n) { if( $j>=$n) {
$j=0; $j=0;
} }
if( $cnt > $n ) { if( $cnt > $n ) {
JpGraphError::RaiseL(14005); JpGraphError::RaiseL(14005);
//("Pie3D Internal error (#1). Trying to wrap twice when looking for start index"); //("Pie3D Internal error (#1). Trying to wrap twice when looking for start index");
} }
++$cnt; ++$cnt;
} }
$start = $j; $start = $j;
   
// //
// Step 3. Print slices in z-order // Step 3. Print slices in z-order
// //
$cnt = 0; $cnt = 0;
   
// First stroke all the slices between 90 and 270 (left half circle) // First stroke all the slices between 90 and 270 (left half circle)
// counterclockwise // counterclockwise
while( $angles[$j][0] < 270 && $aaoption !== 2 ) { while( $angles[$j][0] < 270 && $aaoption !== 2 ) {
   
list($x,$y) = $adjexplode[$j]; list($x,$y) = $adjexplode[$j];
   
$this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1],
$z,$adjcolors[$j],$shadow); $z,$adjcolors[$j],$shadow);
   
$last = array($x,$y,$j); $last = array($x,$y,$j);
   
$j++; $j++;
if( $j >= $n ) $j=0; if( $j >= $n ) $j=0;
if( $cnt > $n ) { if( $cnt > $n ) {
JpGraphError::RaiseL(14006); JpGraphError::RaiseL(14006);
//("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
} }
++$cnt; ++$cnt;
} }
$slice_left = $n-$cnt; $slice_left = $n-$cnt;
$j=$start-1; $j=$start-1;
if($j<0) $j=$n-1; if($j<0) $j=$n-1;
$cnt = 0; $cnt = 0;
   
// The stroke all slices from 90 to -90 (right half circle) // The stroke all slices from 90 to -90 (right half circle)
// clockwise // clockwise
while( $cnt < $slice_left && $aaoption !== 2 ) { while( $cnt < $slice_left && $aaoption !== 2 ) {
   
list($x,$y) = $adjexplode[$j]; list($x,$y) = $adjexplode[$j];
   
$this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1],
$z,$adjcolors[$j],$shadow); $z,$adjcolors[$j],$shadow);
$j--; $j--;
if( $cnt > $n ) { if( $cnt > $n ) {
JpGraphError::RaiseL(14006); JpGraphError::RaiseL(14006);
//("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); //("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; if($j<0) $j=$n-1;
$cnt++; $cnt++;
} }
   
// Now do a special thing. Stroke the last slice on the left // Now do a special thing. Stroke the last slice on the left
// halfcircle one more time. This is needed in the case where // halfcircle one more time. This is needed in the case where
// the slice close to 270 have been exploded. In that case the // 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 // part of the slice close to the center of the pie might be
// slightly nagged. // slightly nagged.
if( $aaoption !== 2 ) if( $aaoption !== 2 )
$this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0], $this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0],
$angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow); $angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow);
   
   
if( $aaoption !== 1 ) { if( $aaoption !== 1 ) {
// Now print possible labels and add csim // Now print possible labels and add csim
$this->value->ApplyFont($img); $this->value->ApplyFont($img);
$margin = $img->GetFontHeight()/2 + $this->value->margin ; $margin = $img->GetFontHeight()/2 + $this->value->margin ;
for($i=0; $i < count($data); ++$i ) { for($i=0; $i < count($data); ++$i ) {
$la = $labeldata[$i][0]; $la = $labeldata[$i][0];
$x = $labeldata[$i][1] + cos($la*M_PI/180)*($d+$margin)*$this->ilabelposadj; $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; $y = $labeldata[$i][2] - sin($la*M_PI/180)*($h+$margin)*$this->ilabelposadj;
if( $this->ilabelposadj >= 1.0 ) { if( $this->ilabelposadj >= 1.0 ) {
if( $la > 180 && $la < 360 ) $y += $z; if( $la > 180 && $la < 360 ) $y += $z;
} }
if( $this->labeltype == 0 ) { if( $this->labeltype == 0 ) {
if( $sum > 0 ) $l = 100*$data[$i]/$sum; if( $sum > 0 ) $l = 100*$data[$i]/$sum;
else $l = 0; else $l = 0;
} }
elseif( $this->labeltype == 1 ) { elseif( $this->labeltype == 1 ) {
$l = $data[$i]; $l = $data[$i];
} }
else { else {
$l = $this->adjusted_data[$i]; $l = $this->adjusted_data[$i];
} }
if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) { if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) {
$l=sprintf($this->labels[$i],$l); $l=sprintf($this->labels[$i],$l);
} }
   
$this->StrokeLabels($l,$img,$labeldata[$i][0]*M_PI/180,$x,$y,$z); $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, $this->Add3DSliceToCSIM($i,$labeldata[$i][1],$labeldata[$i][2],$h*2,$d*2,$z,
$originalangles[$i][0],$originalangles[$i][1]); $originalangles[$i][0],$originalangles[$i][1]);
} }
} }
   
// //
// Finally add potential lines in pie // Finally add potential lines in pie
// //
   
if( $edgecolor=="" || $aaoption !== 0 ) return; if( $edgecolor=="" || $aaoption !== 0 ) return;
   
$accsum = 0; $accsum = 0;
$a = $startangle; $a = $startangle;
$a = $this->NormAngle($a); $a = $this->NormAngle($a);
   
$a *= M_PI/180.0; $a *= M_PI/180.0;
   
$idx=0; $idx=0;
$img->PushColor($edgecolor); $img->PushColor($edgecolor);
$img->SetLineWeight($edgeweight); $img->SetLineWeight($edgeweight);
   
$fulledge = true; $fulledge = true;
for($i=0; $i < count($data) && $fulledge; ++$i ) { for($i=0; $i < count($data) && $fulledge; ++$i ) {
if( empty($this->explode_radius[$i]) ) { if( empty($this->explode_radius[$i]) ) {
$this->explode_radius[$i]=0; $this->explode_radius[$i]=0;
} }
if( $this->explode_radius[$i] > 0 ) { if( $this->explode_radius[$i] > 0 ) {
$fulledge = false; $fulledge = false;
} }
} }
   
for($i=0; $i < count($data); ++$i, ++$idx ) { for($i=0; $i < count($data); ++$i, ++$idx ) {
   
$da = $data[$i]/$sum * 2*M_PI; $da = $data[$i]/$sum * 2*M_PI;
$this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor, $this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor,
$this->explode_radius[$i],$fulledge); $this->explode_radius[$i],$fulledge);
$a += $da; $a += $da;
} }
$img->PopColor(); $img->PopColor();
} }
   
function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) { function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) {
$step = 0.02; $step = 0.02;
   
if( $exploderadius > 0 ) { if( $exploderadius > 0 ) {
$la = ($sa+$ea)/2; $la = ($sa+$ea)/2;
$xc += $exploderadius*cos($la); $xc += $exploderadius*cos($la);
$yc -= $exploderadius*sin($la) * ($h/$w) ; $yc -= $exploderadius*sin($la) * ($h/$w) ;
} }
   
$p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa)); $p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa));
   
for($a=$sa; $a < $ea; $a += $step ) { for($a=$sa; $a < $ea; $a += $step ) {
$p[] = $xc + $w*cos($a); $p[] = $xc + $w*cos($a);
$p[] = $yc - $h*sin($a); $p[] = $yc - $h*sin($a);
} }
   
$p[] = $xc+$w*cos($ea); $p[] = $xc+$w*cos($ea);
$p[] = $yc-$h*sin($ea); $p[] = $yc-$h*sin($ea);
$p[] = $xc; $p[] = $xc;
$p[] = $yc; $p[] = $yc;
   
$img->SetColor($edgecolor); $img->SetColor($edgecolor);
$img->Polygon($p); $img->Polygon($p);
   
// Unfortunately we can't really draw the full edge around the whole of // 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 // 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 // this algorithm is to simply. There are cases where the edges will
// "overwrite" other slices when they have been exploded. // "overwrite" other slices when they have been exploded.
// Doing the full, proper 3D hidden lines stiff is actually quite // Doing the full, proper 3D hidden lines stiff is actually quite
// tricky. So for exploded pies we only draw the top edge. Not perfect // tricky. So for exploded pies we only draw the top edge. Not perfect
// but the "real" solution is much more complicated. // but the "real" solution is much more complicated.
if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) { if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) {
   
if($sa < M_PI && $ea > M_PI) { if($sa < M_PI && $ea > M_PI) {
$sa = M_PI; $sa = M_PI;
} }
   
if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) ) { if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) ) {
$ea = 2*M_PI; $ea = 2*M_PI;
} }
   
if( $sa >= M_PI && $ea <= 2*M_PI ) { if( $sa >= M_PI && $ea <= 2*M_PI ) {
$p = array($xc + $w*cos($sa),$yc - $h*sin($sa), $p = array($xc + $w*cos($sa),$yc - $h*sin($sa),
$xc + $w*cos($sa),$z + $yc - $h*sin($sa)); $xc + $w*cos($sa),$z + $yc - $h*sin($sa));
   
for($a=$sa+$step; $a < $ea; $a += $step ) { for($a=$sa+$step; $a < $ea; $a += $step ) {
$p[] = $xc + $w*cos($a); $p[] = $xc + $w*cos($a);
$p[] = $z + $yc - $h*sin($a); $p[] = $z + $yc - $h*sin($a);
} }
$p[] = $xc + $w*cos($ea); $p[] = $xc + $w*cos($ea);
$p[] = $z + $yc - $h*sin($ea); $p[] = $z + $yc - $h*sin($ea);
$p[] = $xc + $w*cos($ea); $p[] = $xc + $w*cos($ea);
$p[] = $yc - $h*sin($ea); $p[] = $yc - $h*sin($ea);
$img->SetColor($edgecolor); $img->SetColor($edgecolor);
$img->Polygon($p); $img->Polygon($p);
} }
} }
} }
   
function Stroke($img,$aaoption=0) { function Stroke($img,$aaoption=0) {
$n = count($this->data); $n = count($this->data);
   
// If user hasn't set the colors use the theme array // If user hasn't set the colors use the theme array
if( $this->setslicecolors==null ) { if( $this->setslicecolors==null ) {
$colors = array_keys($img->rgb->rgb_table); $colors = array_keys($img->rgb->rgb_table);
sort($colors); sort($colors);
$idx_a=$this->themearr[$this->theme]; $idx_a=$this->themearr[$this->theme];
$ca = array(); $ca = array();
$m = count($idx_a); $m = count($idx_a);
for($i=0; $i < $m; ++$i) { for($i=0; $i < $m; ++$i) {
$ca[$i] = $colors[$idx_a[$i]]; $ca[$i] = $colors[$idx_a[$i]];
} }
$ca = array_reverse(array_slice($ca,0,$n)); $ca = array_reverse(array_slice($ca,0,$n));
} }
else { else {
$ca = $this->setslicecolors; $ca = $this->setslicecolors;
} }
   
   
if( $this->posx <= 1 && $this->posx > 0 ) { if( $this->posx <= 1 && $this->posx > 0 ) {
$xc = round($this->posx*$img->width); $xc = round($this->posx*$img->width);
} }
else { else {
$xc = $this->posx ; $xc = $this->posx ;
} }
   
if( $this->posy <= 1 && $this->posy > 0 ) { if( $this->posy <= 1 && $this->posy > 0 ) {
$yc = round($this->posy*$img->height); $yc = round($this->posy*$img->height);
} }
else { else {
$yc = $this->posy ; $yc = $this->posy ;
} }
   
if( $this->radius <= 1 ) { if( $this->radius <= 1 ) {
$width = floor($this->radius*min($img->width,$img->height)); $width = floor($this->radius*min($img->width,$img->height));
// Make sure that the pie doesn't overflow the image border // Make sure that the pie doesn't overflow the image border
// The 0.9 factor is simply an extra margin to leave some space // The 0.9 factor is simply an extra margin to leave some space
// between the pie an the border of the image. // between the pie an the border of the image.
$width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9)); $width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9));
} }
else { else {
$width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ; $width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ;
} }
   
// Add a sanity check for width // Add a sanity check for width
if( $width < 1 ) { if( $width < 1 ) {
JpGraphError::RaiseL(14007);//("Width for 3D Pie is 0. Specify a size > 0"); 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 // Establish a thickness. By default the thickness is a fifth of the
// pie slice width (=pie radius) but since the perspective depends // pie slice width (=pie radius) but since the perspective depends
// on the inclination angle we use some heuristics to make the edge // on the inclination angle we use some heuristics to make the edge
// slightly thicker the less the angle. // slightly thicker the less the angle.
   
// Has user specified an absolute thickness? In that case use // Has user specified an absolute thickness? In that case use
// that instead // that instead
   
if( $this->iThickness ) { if( $this->iThickness ) {
$thick = $this->iThickness; $thick = $this->iThickness;
$thick *= ($aaoption === 1 ? 2 : 1 ); $thick *= ($aaoption === 1 ? 2 : 1 );
} }
else { else {
$thick = $width/12; $thick = $width/12;
} }
$a = $this->angle; $a = $this->angle;
if( $a <= 30 ) $thick *= 1.6; if( $a <= 30 ) $thick *= 1.6;
elseif( $a <= 40 ) $thick *= 1.4; elseif( $a <= 40 ) $thick *= 1.4;
elseif( $a <= 50 ) $thick *= 1.2; elseif( $a <= 50 ) $thick *= 1.2;
elseif( $a <= 60 ) $thick *= 1.0; elseif( $a <= 60 ) $thick *= 1.0;
elseif( $a <= 70 ) $thick *= 0.8; elseif( $a <= 70 ) $thick *= 0.8;
elseif( $a <= 80 ) $thick *= 0.7; elseif( $a <= 80 ) $thick *= 0.7;
else $thick *= 0.6; else $thick *= 0.6;
   
$thick = floor($thick); $thick = floor($thick);
   
if( $this->explode_all ) { if( $this->explode_all ) {
for($i=0; $i < $n; ++$i) for($i=0; $i < $n; ++$i)
$this->explode_radius[$i]=$this->explode_r; $this->explode_radius[$i]=$this->explode_r;
} }
   
$this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle, $this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle,
$thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight); $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight);
   
// Adjust title position // Adjust title position
if( $aaoption != 1 ) { if( $aaoption != 1 ) {
$this->title->SetPos($xc,$yc-$this->title->GetFontHeight($img)-$width/2-$this->title->margin, "center","bottom"); $this->title->SetPos($xc,$yc-$this->title->GetFontHeight($img)-$width/2-$this->title->margin, "center","bottom");
$this->title->Stroke($img); $this->title->Stroke($img);
} }
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
   
// Position the labels of each slice // Position the labels of each slice
function StrokeLabels($label,$img,$a,$xp,$yp,$z) { function StrokeLabels($label,$img,$a,$xp,$yp,$z) {
$this->value->halign="left"; $this->value->halign="left";
$this->value->valign="top"; $this->value->valign="top";
   
// Position the axis title. // Position the axis title.
// dx, dy is the offset from the top left corner of the bounding box that sorrounds the text // 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 // 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 // bit messy but this is really the only way of having a reasonable position of the
// axis titles. // axis titles.
$this->value->ApplyFont($img); $this->value->ApplyFont($img);
$h=$img->GetTextHeight($label); $h=$img->GetTextHeight($label);
// For numeric values the format of the display value // For numeric values the format of the display value
// must be taken into account // must be taken into account
if( is_numeric($label) ) { if( is_numeric($label) ) {
if( $label >= 0 ) { if( $label >= 0 ) {
$w=$img->GetTextWidth(sprintf($this->value->format,$label)); $w=$img->GetTextWidth(sprintf($this->value->format,$label));
} }
else { else {
$w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
} }
} }
else { else {
$w=$img->GetTextWidth($label); $w=$img->GetTextWidth($label);
} }
while( $a > 2*M_PI ) { while( $a > 2*M_PI ) {
$a -= 2*M_PI; $a -= 2*M_PI;
} }
if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; 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>=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>=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>=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>=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 ) $dy=(1-$a*2/M_PI);
if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; 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>=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; if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
   
$x = round($xp-$dx*$w); $x = round($xp-$dx*$w);
$y = round($yp-$dy*$h); $y = round($yp-$dy*$h);
   
// Mark anchor point for debugging // Mark anchor point for debugging
/* /*
$img->SetColor('red'); $img->SetColor('red');
$img->Line($xp-10,$yp,$xp+10,$yp); $img->Line($xp-10,$yp,$xp+10,$yp);
$img->Line($xp,$yp-10,$xp,$yp+10); $img->Line($xp,$yp-10,$xp,$yp+10);
*/ */
   
$oldmargin = $this->value->margin; $oldmargin = $this->value->margin;
$this->value->margin=0; $this->value->margin=0;
$this->value->Stroke($img,$label,$x,$y); $this->value->Stroke($img,$label,$x,$y);
$this->value->margin=$oldmargin; $this->value->margin=$oldmargin;
   
} }
} // Class } // Class
   
/* EOF */ /* EOF */
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_PLOTBAND.PHP // File: JPGRAPH_PLOTBAND.PHP
// Description: PHP4 Graph Plotting library. Extension module. // Description: PHP4 Graph Plotting library. Extension module.
// Created: 2004-02-18 // Created: 2004-02-18
// Ver: $Id: jpgraph_plotband.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_plotband.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
// Constants for types of static bands in plot area // Constants for types of static bands in plot area
define("BAND_RDIAG",1); // Right diagonal lines define("BAND_RDIAG",1); // Right diagonal lines
define("BAND_LDIAG",2); // Left diagonal lines define("BAND_LDIAG",2); // Left diagonal lines
define("BAND_SOLID",3); // Solid one color define("BAND_SOLID",3); // Solid one color
define("BAND_VLINE",4); // Vertical lines define("BAND_VLINE",4); // Vertical lines
define("BAND_HLINE",5); // Horizontal lines define("BAND_HLINE",5); // Horizontal lines
define("BAND_3DPLANE",6); // "3D" Plane define("BAND_3DPLANE",6); // "3D" Plane
define("BAND_HVCROSS",7); // Vertical/Hor crosses define("BAND_HVCROSS",7); // Vertical/Hor crosses
define("BAND_DIAGCROSS",8); // Diagonal crosses define("BAND_DIAGCROSS",8); // Diagonal crosses
   
   
// Utility class to hold coordinates for a rectangle // Utility class to hold coordinates for a rectangle
class Rectangle { class Rectangle {
public $x,$y,$w,$h; public $x,$y,$w,$h;
public $xe, $ye; public $xe, $ye;
function __construct($aX,$aY,$aWidth,$aHeight) { function __construct($aX,$aY,$aWidth,$aHeight) {
$this->x=$aX; $this->x=$aX;
$this->y=$aY; $this->y=$aY;
$this->w=$aWidth; $this->w=$aWidth;
$this->h=$aHeight; $this->h=$aHeight;
$this->xe=$aX+$aWidth-1; $this->xe=$aX+$aWidth-1;
$this->ye=$aY+$aHeight-1; $this->ye=$aY+$aHeight-1;
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPattern // Class RectPattern
// Base class for pattern hierarchi that is used to display patterned // Base class for pattern hierarchi that is used to display patterned
// bands on the graph. Any subclass that doesn't override Stroke() // bands on the graph. Any subclass that doesn't override Stroke()
// must at least implement method DoPattern($aImg) which is responsible // must at least implement method DoPattern($aImg) which is responsible
// for drawing the pattern onto the graph. // for drawing the pattern onto the graph.
//===================================================================== //=====================================================================
class RectPattern { class RectPattern {
protected $color; protected $color;
protected $weight; protected $weight;
protected $rect=null; protected $rect=null;
protected $doframe=true; protected $doframe=true;
protected $linespacing; // Line spacing in pixels protected $linespacing; // Line spacing in pixels
protected $iBackgroundColor=-1; // Default is no background fill protected $iBackgroundColor=-1; // Default is no background fill
   
function __construct($aColor,$aWeight=1) { function __construct($aColor,$aWeight=1) {
$this->color = $aColor; $this->color = $aColor;
$this->weight = $aWeight; $this->weight = $aWeight;
} }
   
function SetBackground($aBackgroundColor) { function SetBackground($aBackgroundColor) {
$this->iBackgroundColor=$aBackgroundColor; $this->iBackgroundColor=$aBackgroundColor;
} }
   
function SetPos($aRect) { function SetPos($aRect) {
$this->rect = $aRect; $this->rect = $aRect;
} }
   
function ShowFrame($aShow=true) { function ShowFrame($aShow=true) {
$this->doframe=$aShow; $this->doframe=$aShow;
} }
   
function SetDensity($aDens) { function SetDensity($aDens) {
if( $aDens < 1 || $aDens > 100 ) if( $aDens < 1 || $aDens > 100 )
JpGraphError::RaiseL(16001,$aDens); JpGraphError::RaiseL(16001,$aDens);
//(" Desity for pattern must be between 1 and 100. (You tried $aDens)"); //(" Desity for pattern must be between 1 and 100. (You tried $aDens)");
// 1% corresponds to linespacing=50 // 1% corresponds to linespacing=50
// 100 % corresponds to linespacing 1 // 100 % corresponds to linespacing 1
$this->linespacing = floor(((100-$aDens)/100.0)*50)+1; $this->linespacing = floor(((100-$aDens)/100.0)*50)+1;
   
} }
   
function Stroke($aImg) { function Stroke($aImg) {
if( $this->rect == null ) if( $this->rect == null )
JpGraphError::RaiseL(16002); JpGraphError::RaiseL(16002);
//(" No positions specified for pattern."); //(" No positions specified for pattern.");
   
if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) { if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) {
$aImg->SetColor($this->iBackgroundColor); $aImg->SetColor($this->iBackgroundColor);
$aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
} }
   
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->SetLineWeight($this->weight); $aImg->SetLineWeight($this->weight);
   
// Virtual function implemented by subclass // Virtual function implemented by subclass
$this->DoPattern($aImg); $this->DoPattern($aImg);
   
// Frame around the pattern area // Frame around the pattern area
if( $this->doframe ) if( $this->doframe )
$aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
} }
   
} }
   
   
//===================================================================== //=====================================================================
// Class RectPatternSolid // Class RectPatternSolid
// Implements a solid band // Implements a solid band
//===================================================================== //=====================================================================
class RectPatternSolid extends RectPattern { class RectPatternSolid extends RectPattern {
   
function __construct($aColor="black",$aWeight=1) { function __construct($aColor="black",$aWeight=1) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->FilledRectangle($this->rect->x,$this->rect->y, $aImg->FilledRectangle($this->rect->x,$this->rect->y,
$this->rect->xe,$this->rect->ye); $this->rect->xe,$this->rect->ye);
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPatternHor // Class RectPatternHor
// Implements horizontal line pattern // Implements horizontal line pattern
//===================================================================== //=====================================================================
class RectPatternHor extends RectPattern { class RectPatternHor extends RectPattern {
   
function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) { function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
$this->linespacing = $aLineSpacing; $this->linespacing = $aLineSpacing;
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
$x0 = $this->rect->x; $x0 = $this->rect->x;
$x1 = $this->rect->xe; $x1 = $this->rect->xe;
$y = $this->rect->y; $y = $this->rect->y;
while( $y < $this->rect->ye ) { while( $y < $this->rect->ye ) {
$aImg->Line($x0,$y,$x1,$y); $aImg->Line($x0,$y,$x1,$y);
$y += $this->linespacing; $y += $this->linespacing;
} }
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPatternVert // Class RectPatternVert
// Implements vertical line pattern // Implements vertical line pattern
//===================================================================== //=====================================================================
class RectPatternVert extends RectPattern { class RectPatternVert extends RectPattern {
   
function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) { function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
$this->linespacing = $aLineSpacing; $this->linespacing = $aLineSpacing;
} }
   
//-------------------- //--------------------
// Private methods // Private methods
// //
function DoPattern($aImg) { function DoPattern($aImg) {
$x = $this->rect->x; $x = $this->rect->x;
$y0 = $this->rect->y; $y0 = $this->rect->y;
$y1 = $this->rect->ye; $y1 = $this->rect->ye;
while( $x < $this->rect->xe ) { while( $x < $this->rect->xe ) {
$aImg->Line($x,$y0,$x,$y1); $aImg->Line($x,$y0,$x,$y1);
$x += $this->linespacing; $x += $this->linespacing;
} }
} }
} }
   
   
//===================================================================== //=====================================================================
// Class RectPatternRDiag // Class RectPatternRDiag
// Implements right diagonal pattern // Implements right diagonal pattern
//===================================================================== //=====================================================================
class RectPatternRDiag extends RectPattern { class RectPatternRDiag extends RectPattern {
   
function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) { function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
$this->linespacing = $aLineSpacing; $this->linespacing = $aLineSpacing;
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
// -------------------- // --------------------
// | / / / / /| // | / / / / /|
// |/ / / / / | // |/ / / / / |
// | / / / / | // | / / / / |
// -------------------- // --------------------
$xe = $this->rect->xe; $xe = $this->rect->xe;
$ye = $this->rect->ye; $ye = $this->rect->ye;
$x0 = $this->rect->x + round($this->linespacing/2); $x0 = $this->rect->x + round($this->linespacing/2);
$y0 = $this->rect->y; $y0 = $this->rect->y;
$x1 = $this->rect->x; $x1 = $this->rect->x;
$y1 = $this->rect->y + round($this->linespacing/2); $y1 = $this->rect->y + round($this->linespacing/2);
   
while($x0<=$xe && $y1<=$ye) { while($x0<=$xe && $y1<=$ye) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$x0 += $this->linespacing; $x0 += $this->linespacing;
$y1 += $this->linespacing; $y1 += $this->linespacing;
} }
   
if( $xe-$x1 > $ye-$y0 ) { if( $xe-$x1 > $ye-$y0 ) {
// Width larger than height // Width larger than height
$x1 = $this->rect->x + ($y1-$ye); $x1 = $this->rect->x + ($y1-$ye);
$y1 = $ye; $y1 = $ye;
$y0 = $this->rect->y; $y0 = $this->rect->y;
while( $x0 <= $xe ) { while( $x0 <= $xe ) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$x0 += $this->linespacing; $x0 += $this->linespacing;
$x1 += $this->linespacing; $x1 += $this->linespacing;
} }
$y0=$this->rect->y + ($x0-$xe); $y0=$this->rect->y + ($x0-$xe);
$x0=$xe; $x0=$xe;
} }
else { else {
// Height larger than width // Height larger than width
$diff = $x0-$xe; $diff = $x0-$xe;
$y0 = $diff+$this->rect->y; $y0 = $diff+$this->rect->y;
$x0 = $xe; $x0 = $xe;
$x1 = $this->rect->x; $x1 = $this->rect->x;
while( $y1 <= $ye ) { while( $y1 <= $ye ) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$y1 += $this->linespacing; $y1 += $this->linespacing;
$y0 += $this->linespacing; $y0 += $this->linespacing;
} }
$diff = $y1-$ye; $diff = $y1-$ye;
$y1 = $ye; $y1 = $ye;
$x1 = $diff + $this->rect->x; $x1 = $diff + $this->rect->x;
} }
   
while( $y0 <= $ye ) { while( $y0 <= $ye ) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$y0 += $this->linespacing; $y0 += $this->linespacing;
$x1 += $this->linespacing; $x1 += $this->linespacing;
} }
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPatternLDiag // Class RectPatternLDiag
// Implements left diagonal pattern // Implements left diagonal pattern
//===================================================================== //=====================================================================
class RectPatternLDiag extends RectPattern { class RectPatternLDiag extends RectPattern {
   
function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) { function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) {
$this->linespacing = $aLineSpacing; $this->linespacing = $aLineSpacing;
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
// -------------------- // --------------------
// |\ \ \ \ \ | // |\ \ \ \ \ |
// | \ \ \ \ \| // | \ \ \ \ \|
// | \ \ \ \ | // | \ \ \ \ |
// |------------------| // |------------------|
$xe = $this->rect->xe; $xe = $this->rect->xe;
$ye = $this->rect->ye; $ye = $this->rect->ye;
$x0 = $this->rect->x + round($this->linespacing/2); $x0 = $this->rect->x + round($this->linespacing/2);
$y0 = $this->rect->ye; $y0 = $this->rect->ye;
$x1 = $this->rect->x; $x1 = $this->rect->x;
$y1 = $this->rect->ye - round($this->linespacing/2); $y1 = $this->rect->ye - round($this->linespacing/2);
   
while($x0<=$xe && $y1>=$this->rect->y) { while($x0<=$xe && $y1>=$this->rect->y) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$x0 += $this->linespacing; $x0 += $this->linespacing;
$y1 -= $this->linespacing; $y1 -= $this->linespacing;
} }
if( $xe-$x1 > $ye-$this->rect->y ) { if( $xe-$x1 > $ye-$this->rect->y ) {
// Width larger than height // Width larger than height
$x1 = $this->rect->x + ($this->rect->y-$y1); $x1 = $this->rect->x + ($this->rect->y-$y1);
$y0=$ye; $y1=$this->rect->y; $y0=$ye; $y1=$this->rect->y;
while( $x0 <= $xe ) { while( $x0 <= $xe ) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$x0 += $this->linespacing; $x0 += $this->linespacing;
$x1 += $this->linespacing; $x1 += $this->linespacing;
} }
$y0=$this->rect->ye - ($x0-$xe); $y0=$this->rect->ye - ($x0-$xe);
$x0=$xe; $x0=$xe;
} }
else { else {
// Height larger than width // Height larger than width
$diff = $x0-$xe; $diff = $x0-$xe;
$y0 = $ye-$diff; $y0 = $ye-$diff;
$x0 = $xe; $x0 = $xe;
while( $y1 >= $this->rect->y ) { while( $y1 >= $this->rect->y ) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$y0 -= $this->linespacing; $y0 -= $this->linespacing;
$y1 -= $this->linespacing; $y1 -= $this->linespacing;
} }
$diff = $this->rect->y - $y1; $diff = $this->rect->y - $y1;
$x1 = $this->rect->x + $diff; $x1 = $this->rect->x + $diff;
$y1 = $this->rect->y; $y1 = $this->rect->y;
} }
while( $y0 >= $this->rect->y ) { while( $y0 >= $this->rect->y ) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$y0 -= $this->linespacing; $y0 -= $this->linespacing;
$x1 += $this->linespacing; $x1 += $this->linespacing;
} }
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPattern3DPlane // Class RectPattern3DPlane
// Implements "3D" plane pattern // Implements "3D" plane pattern
//===================================================================== //=====================================================================
class RectPattern3DPlane extends RectPattern { class RectPattern3DPlane extends RectPattern {
private $alpha=50; // Parameter that specifies the distance private $alpha=50; // Parameter that specifies the distance
// to "simulated" horizon in pixel from the // to "simulated" horizon in pixel from the
// top of the band. Specifies how fast the lines // top of the band. Specifies how fast the lines
// converge. // converge.
   
function __construct($aColor="black",$aWeight=1) { function __construct($aColor="black",$aWeight=1) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
$this->SetDensity(10); // Slightly larger default $this->SetDensity(10); // Slightly larger default
} }
   
function SetHorizon($aHorizon) { function SetHorizon($aHorizon) {
$this->alpha=$aHorizon; $this->alpha=$aHorizon;
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
// "Fake" a nice 3D grid-effect. // "Fake" a nice 3D grid-effect.
$x0 = $this->rect->x + $this->rect->w/2; $x0 = $this->rect->x + $this->rect->w/2;
$y0 = $this->rect->y; $y0 = $this->rect->y;
$x1 = $x0; $x1 = $x0;
$y1 = $this->rect->ye; $y1 = $this->rect->ye;
$x0_right = $x0; $x0_right = $x0;
$x1_right = $x1; $x1_right = $x1;
   
// BTW "apa" means monkey in Swedish but is really a shortform for // 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 // "alpha+a" which was the labels I used on paper when I derived the
// geometric to get the 3D perspective right. // geometric to get the 3D perspective right.
// $apa is the height of the bounding rectangle plus the distance to the // $apa is the height of the bounding rectangle plus the distance to the
// artifical horizon (alpha) // artifical horizon (alpha)
$apa = $this->rect->h + $this->alpha; $apa = $this->rect->h + $this->alpha;
   
// Three cases and three loops // Three cases and three loops
// 1) The endpoint of the line ends on the bottom line // 1) The endpoint of the line ends on the bottom line
// 2) The endpoint ends on the side // 2) The endpoint ends on the side
// 3) Horizontal lines // 3) Horizontal lines
   
// Endpoint falls on bottom line // Endpoint falls on bottom line
$middle=$this->rect->x + $this->rect->w/2; $middle=$this->rect->x + $this->rect->w/2;
$dist=$this->linespacing; $dist=$this->linespacing;
$factor=$this->alpha /($apa); $factor=$this->alpha /($apa);
while($x1>$this->rect->x) { while($x1>$this->rect->x) {
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$aImg->Line($x0_right,$y0,$x1_right,$y1); $aImg->Line($x0_right,$y0,$x1_right,$y1);
$x1 = $middle - $dist; $x1 = $middle - $dist;
$x0 = $middle - $dist * $factor; $x0 = $middle - $dist * $factor;
$x1_right = $middle + $dist; $x1_right = $middle + $dist;
$x0_right = $middle + $dist * $factor; $x0_right = $middle + $dist * $factor;
$dist += $this->linespacing; $dist += $this->linespacing;
} }
   
// Endpoint falls on sides // Endpoint falls on sides
$dist -= $this->linespacing; $dist -= $this->linespacing;
$d=$this->rect->w/2; $d=$this->rect->w/2;
$c = $apa - $d*$apa/$dist; $c = $apa - $d*$apa/$dist;
while( $x0>$this->rect->x ) { while( $x0>$this->rect->x ) {
$aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c); $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c);
$aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c); $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c);
$dist += $this->linespacing; $dist += $this->linespacing;
$x0 = $middle - $dist * $factor; $x0 = $middle - $dist * $factor;
$x1 = $middle - $dist; $x1 = $middle - $dist;
$x0_right = $middle + $dist * $factor; $x0_right = $middle + $dist * $factor;
$c = $apa - $d*$apa/$dist; $c = $apa - $d*$apa/$dist;
} }
   
// Horizontal lines // Horizontal lines
// They need some serious consideration since they are a function // They need some serious consideration since they are a function
// of perspective depth (alpha) and density (linespacing) // of perspective depth (alpha) and density (linespacing)
$x0=$this->rect->x; $x0=$this->rect->x;
$x1=$this->rect->xe; $x1=$this->rect->xe;
$y=$this->rect->ye; $y=$this->rect->ye;
   
// The first line is drawn directly. Makes the loop below slightly // The first line is drawn directly. Makes the loop below slightly
// more readable. // more readable.
$aImg->Line($x0,$y,$x1,$y); $aImg->Line($x0,$y,$x1,$y);
$hls = $this->linespacing; $hls = $this->linespacing;
   
// A correction factor for vertical "brick" line spacing to account for // A correction factor for vertical "brick" line spacing to account for
// a) the difference in number of pixels hor vs vert // a) the difference in number of pixels hor vs vert
// b) visual apperance to make the first layer of "bricks" look more // b) visual apperance to make the first layer of "bricks" look more
// square. // square.
$vls = $this->linespacing*0.6; $vls = $this->linespacing*0.6;
   
$ds = $hls*($apa-$vls)/$apa; $ds = $hls*($apa-$vls)/$apa;
// Get the slope for the "perspective line" going from bottom right // Get the slope for the "perspective line" going from bottom right
// corner to top left corner of the "first" brick. // corner to top left corner of the "first" brick.
   
// Uncomment the following lines if you want to get a visual understanding // 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 // of what this helpline does. BTW this mimics the way you would get the
// perspective right when drawing on paper. // perspective right when drawing on paper.
/* /*
$x0 = $middle; $x0 = $middle;
$y0 = $this->rect->ye; $y0 = $this->rect->ye;
$len=floor(($this->rect->ye-$this->rect->y)/$vls); $len=floor(($this->rect->ye-$this->rect->y)/$vls);
$x1 = $middle+round($len*$ds); $x1 = $middle+round($len*$ds);
$y1 = $this->rect->ye-$len*$vls; $y1 = $this->rect->ye-$len*$vls;
$aImg->PushColor("red"); $aImg->PushColor("red");
$aImg->Line($x0,$y0,$x1,$y1); $aImg->Line($x0,$y0,$x1,$y1);
$aImg->PopColor(); $aImg->PopColor();
*/ */
   
$y -= $vls; $y -= $vls;
$k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds)); $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds));
$dist = $hls; $dist = $hls;
while( $y>$this->rect->y ) { while( $y>$this->rect->y ) {
$aImg->Line($this->rect->x,$y,$this->rect->xe,$y); $aImg->Line($this->rect->x,$y,$this->rect->xe,$y);
$adj = $k*$dist/(1+$dist*$k/$apa); $adj = $k*$dist/(1+$dist*$k/$apa);
if( $adj < 2 ) $adj=1; if( $adj < 2 ) $adj=1;
$y = $this->rect->ye - round($adj); $y = $this->rect->ye - round($adj);
$dist += $hls; $dist += $hls;
} }
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPatternCross // Class RectPatternCross
// Vert/Hor crosses // Vert/Hor crosses
//===================================================================== //=====================================================================
class RectPatternCross extends RectPattern { class RectPatternCross extends RectPattern {
private $vert=null; private $vert=null;
private $hor=null; private $hor=null;
function __construct($aColor="black",$aWeight=1) { function __construct($aColor="black",$aWeight=1) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
$this->vert = new RectPatternVert($aColor,$aWeight); $this->vert = new RectPatternVert($aColor,$aWeight);
$this->hor = new RectPatternHor($aColor,$aWeight); $this->hor = new RectPatternHor($aColor,$aWeight);
} }
   
function SetOrder($aDepth) { function SetOrder($aDepth) {
$this->vert->SetOrder($aDepth); $this->vert->SetOrder($aDepth);
$this->hor->SetOrder($aDepth); $this->hor->SetOrder($aDepth);
} }
   
function SetPos($aRect) { function SetPos($aRect) {
parent::SetPos($aRect); parent::SetPos($aRect);
$this->vert->SetPos($aRect); $this->vert->SetPos($aRect);
$this->hor->SetPos($aRect); $this->hor->SetPos($aRect);
} }
   
function SetDensity($aDens) { function SetDensity($aDens) {
$this->vert->SetDensity($aDens); $this->vert->SetDensity($aDens);
$this->hor->SetDensity($aDens); $this->hor->SetDensity($aDens);
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
$this->vert->DoPattern($aImg); $this->vert->DoPattern($aImg);
$this->hor->DoPattern($aImg); $this->hor->DoPattern($aImg);
} }
} }
   
//===================================================================== //=====================================================================
// Class RectPatternDiagCross // Class RectPatternDiagCross
// Vert/Hor crosses // Vert/Hor crosses
//===================================================================== //=====================================================================
   
class RectPatternDiagCross extends RectPattern { class RectPatternDiagCross extends RectPattern {
private $left=null; private $left=null;
private $right=null; private $right=null;
function __construct($aColor="black",$aWeight=1) { function __construct($aColor="black",$aWeight=1) {
parent::__construct($aColor,$aWeight); parent::__construct($aColor,$aWeight);
$this->right = new RectPatternRDiag($aColor,$aWeight); $this->right = new RectPatternRDiag($aColor,$aWeight);
$this->left = new RectPatternLDiag($aColor,$aWeight); $this->left = new RectPatternLDiag($aColor,$aWeight);
} }
   
function SetOrder($aDepth) { function SetOrder($aDepth) {
$this->left->SetOrder($aDepth); $this->left->SetOrder($aDepth);
$this->right->SetOrder($aDepth); $this->right->SetOrder($aDepth);
} }
   
function SetPos($aRect) { function SetPos($aRect) {
parent::SetPos($aRect); parent::SetPos($aRect);
$this->left->SetPos($aRect); $this->left->SetPos($aRect);
$this->right->SetPos($aRect); $this->right->SetPos($aRect);
} }
   
function SetDensity($aDens) { function SetDensity($aDens) {
$this->left->SetDensity($aDens); $this->left->SetDensity($aDens);
$this->right->SetDensity($aDens); $this->right->SetDensity($aDens);
} }
   
function DoPattern($aImg) { function DoPattern($aImg) {
$this->left->DoPattern($aImg); $this->left->DoPattern($aImg);
$this->right->DoPattern($aImg); $this->right->DoPattern($aImg);
} }
   
} }
   
//===================================================================== //=====================================================================
// Class RectPatternFactory // Class RectPatternFactory
// Factory class for rectangular pattern // Factory class for rectangular pattern
//===================================================================== //=====================================================================
class RectPatternFactory { class RectPatternFactory {
function __construct() { function __construct() {
// Empty // Empty
} }
function Create($aPattern,$aColor,$aWeight=1) { function Create($aPattern,$aColor,$aWeight=1) {
switch($aPattern) { switch($aPattern) {
case BAND_RDIAG: case BAND_RDIAG:
$obj = new RectPatternRDiag($aColor,$aWeight); $obj = new RectPatternRDiag($aColor,$aWeight);
break; break;
case BAND_LDIAG: case BAND_LDIAG:
$obj = new RectPatternLDiag($aColor,$aWeight); $obj = new RectPatternLDiag($aColor,$aWeight);
break; break;
case BAND_SOLID: case BAND_SOLID:
$obj = new RectPatternSolid($aColor,$aWeight); $obj = new RectPatternSolid($aColor,$aWeight);
break; break;
case BAND_VLINE: case BAND_VLINE:
$obj = new RectPatternVert($aColor,$aWeight); $obj = new RectPatternVert($aColor,$aWeight);
break; break;
case BAND_HLINE: case BAND_HLINE:
$obj = new RectPatternHor($aColor,$aWeight); $obj = new RectPatternHor($aColor,$aWeight);
break; break;
case BAND_3DPLANE: case BAND_3DPLANE:
$obj = new RectPattern3DPlane($aColor,$aWeight); $obj = new RectPattern3DPlane($aColor,$aWeight);
break; break;
case BAND_HVCROSS: case BAND_HVCROSS:
$obj = new RectPatternCross($aColor,$aWeight); $obj = new RectPatternCross($aColor,$aWeight);
break; break;
case BAND_DIAGCROSS: case BAND_DIAGCROSS:
$obj = new RectPatternDiagCross($aColor,$aWeight); $obj = new RectPatternDiagCross($aColor,$aWeight);
break; break;
default: default:
JpGraphError::RaiseL(16003,$aPattern); JpGraphError::RaiseL(16003,$aPattern);
//(" Unknown pattern specification ($aPattern)"); //(" Unknown pattern specification ($aPattern)");
} }
return $obj; return $obj;
} }
} }
   
   
//===================================================================== //=====================================================================
// Class PlotBand // Class PlotBand
// Factory class which is used by the client. // Factory class which is used by the client.
// It is responsible for factoring the corresponding pattern // It is responsible for factoring the corresponding pattern
// concrete class. // concrete class.
//===================================================================== //=====================================================================
class PlotBand { class PlotBand {
public $depth; // Determine if band should be over or under the plots public $depth; // Determine if band should be over or under the plots
private $prect=null; private $prect=null;
private $dir, $min, $max; private $dir, $min, $max;
   
function __construct($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) { function __construct($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) {
$f = new RectPatternFactory(); $f = new RectPatternFactory();
$this->prect = $f->Create($aPattern,$aColor,$aWeight); $this->prect = $f->Create($aPattern,$aColor,$aWeight);
if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) ) if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) )
JpGraphError::RaiseL(16004); JpGraphError::RaiseL(16004);
//('Min value for plotband is larger than specified max value. Please correct.'); //('Min value for plotband is larger than specified max value. Please correct.');
$this->dir = $aDir; $this->dir = $aDir;
$this->min = $aMin; $this->min = $aMin;
$this->max = $aMax; $this->max = $aMax;
$this->depth=$aDepth; $this->depth=$aDepth;
} }
   
// Set position. aRect contains absolute image coordinates // Set position. aRect contains absolute image coordinates
function SetPos($aRect) { function SetPos($aRect) {
assert( $this->prect != null ) ; assert( $this->prect != null ) ;
$this->prect->SetPos($aRect); $this->prect->SetPos($aRect);
} }
   
function ShowFrame($aFlag=true) { function ShowFrame($aFlag=true) {
$this->prect->ShowFrame($aFlag); $this->prect->ShowFrame($aFlag);
} }
   
// Set z-order. In front of pplot or in the back // Set z-order. In front of pplot or in the back
function SetOrder($aDepth) { function SetOrder($aDepth) {
$this->depth=$aDepth; $this->depth=$aDepth;
} }
   
function SetDensity($aDens) { function SetDensity($aDens) {
$this->prect->SetDensity($aDens); $this->prect->SetDensity($aDens);
} }
   
function GetDir() { function GetDir() {
return $this->dir; return $this->dir;
} }
   
function GetMin() { function GetMin() {
return $this->min; return $this->min;
} }
   
function GetMax() { function GetMax() {
return $this->max; return $this->max;
} }
   
function PreStrokeAdjust($aGraph) { function PreStrokeAdjust($aGraph) {
// Nothing to do // Nothing to do
} }
   
// Display band // Display band
function Stroke($aImg,$aXScale,$aYScale) { function Stroke($aImg,$aXScale,$aYScale) {
assert( $this->prect != null ) ; assert( $this->prect != null ) ;
if( $this->dir == HORIZONTAL ) { if( $this->dir == HORIZONTAL ) {
if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal(); if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal();
if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal(); if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal();
   
// Only draw the bar if it actually appears in the range // Only draw the bar if it actually appears in the range
if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) { if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) {
// Trucate to limit of axis // Trucate to limit of axis
$this->min = max($this->min, $aYScale->GetMinVal()); $this->min = max($this->min, $aYScale->GetMinVal());
$this->max = min($this->max, $aYScale->GetMaxVal()); $this->max = min($this->max, $aYScale->GetMaxVal());
   
$x=$aXScale->scale_abs[0]; $x=$aXScale->scale_abs[0];
$y=$aYScale->Translate($this->max); $y=$aYScale->Translate($this->max);
$width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1; $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1;
$height=abs($y-$aYScale->Translate($this->min))+1; $height=abs($y-$aYScale->Translate($this->min))+1;
$this->prect->SetPos(new Rectangle($x,$y,$width,$height)); $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
$this->prect->Stroke($aImg); $this->prect->Stroke($aImg);
} }
} }
else { // VERTICAL else { // VERTICAL
if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal(); if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal();
if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal(); if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal();
   
// Only draw the bar if it actually appears in the range // Only draw the bar if it actually appears in the range
if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) { if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) {
// Trucate to limit of axis // Trucate to limit of axis
$this->min = max($this->min, $aXScale->GetMinVal()); $this->min = max($this->min, $aXScale->GetMinVal());
$this->max = min($this->max, $aXScale->GetMaxVal()); $this->max = min($this->max, $aXScale->GetMaxVal());
   
$y=$aYScale->scale_abs[1]; $y=$aYScale->scale_abs[1];
$x=$aXScale->Translate($this->min); $x=$aXScale->Translate($this->min);
$height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]); $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]);
$width=abs($x-$aXScale->Translate($this->max)); $width=abs($x-$aXScale->Translate($this->max));
$this->prect->SetPos(new Rectangle($x,$y,$width,$height)); $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
$this->prect->Stroke($aImg); $this->prect->Stroke($aImg);
} }
} }
} }
} }
   
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_PLOTLINE.PHP // File: JPGRAPH_PLOTLINE.PHP
// Description: PlotLine extension for JpGraph // Description: PlotLine extension for JpGraph
// Created: 2009-03-24 // Created: 2009-03-24
// Ver: $Id: jpgraph_plotline.php 1881 2009-10-01 10:28:12Z ljp $ // Ver: $Id: jpgraph_plotline.php 1881 2009-10-01 10:28:12Z ljp $
// //
// CLASS PlotLine // CLASS PlotLine
// Data container class to hold properties for a static // Data container class to hold properties for a static
// line that is drawn directly in the plot area. // line that is drawn directly in the plot area.
// Useful to add static borders inside a plot to show for example set-values // Useful to add static borders inside a plot to show for example set-values
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
class PlotLine { class PlotLine {
public $scaleposition, $direction=-1; public $scaleposition, $direction=-1;
protected $weight=1; protected $weight=1;
protected $color = 'black'; protected $color = 'black';
private $legend='',$hidelegend=false, $legendcsimtarget='', $legendcsimalt='',$legendcsimwintarget=''; private $legend='',$hidelegend=false, $legendcsimtarget='', $legendcsimalt='',$legendcsimwintarget='';
private $iLineStyle='solid'; private $iLineStyle='solid';
public $numpoints=0; // Needed since the framework expects this property public $numpoints=0; // Needed since the framework expects this property
   
function __construct($aDir=HORIZONTAL,$aPos=0,$aColor='black',$aWeight=1) { function __construct($aDir=HORIZONTAL,$aPos=0,$aColor='black',$aWeight=1) {
$this->direction = $aDir; $this->direction = $aDir;
$this->color=$aColor; $this->color=$aColor;
$this->weight=$aWeight; $this->weight=$aWeight;
$this->scaleposition=$aPos; $this->scaleposition=$aPos;
} }
   
function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') { function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') {
$this->legend = $aLegend; $this->legend = $aLegend;
$this->legendcsimtarget = $aCSIM; $this->legendcsimtarget = $aCSIM;
$this->legendcsimwintarget = $aCSIMWinTarget; $this->legendcsimwintarget = $aCSIMWinTarget;
$this->legendcsimalt = $aCSIMAlt; $this->legendcsimalt = $aCSIMAlt;
} }
   
function HideLegend($f=true) { function HideLegend($f=true) {
$this->hidelegend = $f; $this->hidelegend = $f;
} }
   
function SetPosition($aScalePosition) { function SetPosition($aScalePosition) {
$this->scaleposition=$aScalePosition; $this->scaleposition=$aScalePosition;
} }
   
function SetDirection($aDir) { function SetDirection($aDir) {
$this->direction = $aDir; $this->direction = $aDir;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->color=$aColor; $this->color=$aColor;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->weight=$aWeight; $this->weight=$aWeight;
} }
   
function SetLineStyle($aStyle) { function SetLineStyle($aStyle) {
$this->iLineStyle = $aStyle; $this->iLineStyle = $aStyle;
} }
   
//--------------- //---------------
// PRIVATE METHODS // PRIVATE METHODS
   
function DoLegend($graph) { function DoLegend($graph) {
if( !$this->hidelegend ) $this->Legend($graph); if( !$this->hidelegend ) $this->Legend($graph);
} }
   
// Framework function the chance for each plot class to set a legend // Framework function the chance for each plot class to set a legend
function Legend($aGraph) { function Legend($aGraph) {
if( $this->legend != '' ) { if( $this->legend != '' ) {
$dummyPlotMark = new PlotMark(); $dummyPlotMark = new PlotMark();
$lineStyle = 1; $lineStyle = 1;
$aGraph->legend->Add($this->legend,$this->color,$dummyPlotMark,$lineStyle, $aGraph->legend->Add($this->legend,$this->color,$dummyPlotMark,$lineStyle,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
} }
   
function PreStrokeAdjust($aGraph) { function PreStrokeAdjust($aGraph) {
// Nothing to do // Nothing to do
} }
   
// Called by framework to allow the object to draw // Called by framework to allow the object to draw
// optional information in the margin area // optional information in the margin area
function StrokeMargin($aImg) { function StrokeMargin($aImg) {
// Nothing to do // Nothing to do
} }
   
// Framework function to allow the object to adjust the scale // Framework function to allow the object to adjust the scale
function PrescaleSetup($aGraph) { function PrescaleSetup($aGraph) {
// Nothing to do // Nothing to do
} }
   
function Min() { function Min() {
return array(null,null); return array(null,null);
} }
   
function Max() { function Max() {
return array(null,null); return array(null,null);
} }
   
function _Stroke($aImg,$aMinX,$aMinY,$aMaxX,$aMaxY,$aXPos,$aYPos) { function _Stroke($aImg,$aMinX,$aMinY,$aMaxX,$aMaxY,$aXPos,$aYPos) {
$aImg->SetColor($this->color); $aImg->SetColor($this->color);
$aImg->SetLineWeight($this->weight); $aImg->SetLineWeight($this->weight);
$oldStyle = $aImg->SetLineStyle($this->iLineStyle); $oldStyle = $aImg->SetLineStyle($this->iLineStyle);
if( $this->direction == VERTICAL ) { if( $this->direction == VERTICAL ) {
$ymin_abs = $aMinY; $ymin_abs = $aMinY;
$ymax_abs = $aMaxY; $ymax_abs = $aMaxY;
$xpos_abs = $aXPos; $xpos_abs = $aXPos;
$aImg->StyleLine($xpos_abs, $ymin_abs, $xpos_abs, $ymax_abs); $aImg->StyleLine($xpos_abs, $ymin_abs, $xpos_abs, $ymax_abs);
} }
elseif( $this->direction == HORIZONTAL ) { elseif( $this->direction == HORIZONTAL ) {
$xmin_abs = $aMinX; $xmin_abs = $aMinX;
$xmax_abs = $aMaxX; $xmax_abs = $aMaxX;
$ypos_abs = $aYPos; $ypos_abs = $aYPos;
$aImg->StyleLine($xmin_abs, $ypos_abs, $xmax_abs, $ypos_abs); $aImg->StyleLine($xmin_abs, $ypos_abs, $xmax_abs, $ypos_abs);
} }
else { else {
JpGraphError::RaiseL(25125);//(" Illegal direction for static line"); JpGraphError::RaiseL(25125);//(" Illegal direction for static line");
} }
$aImg->SetLineStyle($oldStyle); $aImg->SetLineStyle($oldStyle);
} }
   
function Stroke($aImg,$aXScale,$aYScale) { function Stroke($aImg,$aXScale,$aYScale) {
$this->_Stroke($aImg, $this->_Stroke($aImg,
$aImg->left_margin, $aImg->left_margin,
$aYScale->Translate($aYScale->GetMinVal()), $aYScale->Translate($aYScale->GetMinVal()),
$aImg->width-$aImg->right_margin, $aImg->width-$aImg->right_margin,
$aYScale->Translate($aYScale->GetMaxVal()), $aYScale->Translate($aYScale->GetMaxVal()),
$aXScale->Translate($this->scaleposition), $aXScale->Translate($this->scaleposition),
$aYScale->Translate($this->scaleposition) $aYScale->Translate($this->scaleposition)
); );
} }
} }
   
   
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_PLOTMARK.PHP // File: JPGRAPH_PLOTMARK.PHP
// Description: Class file. Handles plotmarks // Description: Class file. Handles plotmarks
// Created: 2003-03-21 // Created: 2003-03-21
// Ver: $Id: jpgraph_plotmark.inc.php 1106 2009-02-22 20:16:35Z ljp $ // Ver: $Id: jpgraph_plotmark.inc.php 1106 2009-02-22 20:16:35Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
//=================================================== //===================================================
// CLASS PlotMark // CLASS PlotMark
// Description: Handles the plot marks in graphs // Description: Handles the plot marks in graphs
//=================================================== //===================================================
   
class PlotMark { class PlotMark {
public $title, $show=true; public $title, $show=true;
public $type,$weight=1; public $type,$weight=1;
public $iFormatCallback="", $iFormatCallback2=""; public $iFormatCallback="", $iFormatCallback2="";
public $fill_color="blue"; public $fill_color="blue";
public $color="black", $width=4; public $color="black", $width=4;
private $yvalue,$xvalue='',$csimtarget,$csimwintarget='',$csimalt,$csimareas; private $yvalue,$xvalue='',$csimtarget,$csimwintarget='',$csimalt,$csimareas;
private $markimg='',$iScale=1.0; private $markimg='',$iScale=1.0;
private $oldfilename='',$iFileName=''; private $oldfilename='',$iFileName='';
private $imgdata_balls = null; private $imgdata_balls = null;
private $imgdata_diamonds = null; private $imgdata_diamonds = null;
private $imgdata_squares = null; private $imgdata_squares = null;
private $imgdata_bevels = null; private $imgdata_bevels = null;
private $imgdata_stars = null; private $imgdata_stars = null;
private $imgdata_pushpins = null; private $imgdata_pushpins = null;
   
//-------------- //--------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct() { function __construct() {
$this->title = new Text(); $this->title = new Text();
$this->title->Hide(); $this->title->Hide();
$this->csimareas = ''; $this->csimareas = '';
$this->type=-1; $this->type=-1;
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function SetType($aType,$aFileName='',$aScale=1.0) { function SetType($aType,$aFileName='',$aScale=1.0) {
$this->type = $aType; $this->type = $aType;
if( $aType == MARK_IMG && $aFileName=='' ) { if( $aType == MARK_IMG && $aFileName=='' ) {
JpGraphError::RaiseL(23003);//('A filename must be specified if you set the mark type to MARK_IMG.'); JpGraphError::RaiseL(23003);//('A filename must be specified if you set the mark type to MARK_IMG.');
} }
$this->iFileName = $aFileName; $this->iFileName = $aFileName;
$this->iScale = $aScale; $this->iScale = $aScale;
} }
   
function SetCallback($aFunc) { function SetCallback($aFunc) {
$this->iFormatCallback = $aFunc; $this->iFormatCallback = $aFunc;
} }
   
function SetCallbackYX($aFunc) { function SetCallbackYX($aFunc) {
$this->iFormatCallback2 = $aFunc; $this->iFormatCallback2 = $aFunc;
} }
   
function GetType() { function GetType() {
return $this->type; return $this->type;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->color=$aColor; $this->color=$aColor;
} }
   
function SetFillColor($aFillColor) { function SetFillColor($aFillColor) {
$this->fill_color = $aFillColor; $this->fill_color = $aFillColor;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->weight = $aWeight; $this->weight = $aWeight;
} }
   
// Synonym for SetWidth() // Synonym for SetWidth()
function SetSize($aWidth) { function SetSize($aWidth) {
$this->width=$aWidth; $this->width=$aWidth;
} }
   
function SetWidth($aWidth) { function SetWidth($aWidth) {
$this->width=$aWidth; $this->width=$aWidth;
} }
   
function SetDefaultWidth() { function SetDefaultWidth() {
switch( $this->type ) { switch( $this->type ) {
case MARK_CIRCLE: case MARK_CIRCLE:
case MARK_FILLEDCIRCLE: case MARK_FILLEDCIRCLE:
$this->width=4; $this->width=4;
break; break;
default: default:
$this->width=7; $this->width=7;
} }
} }
   
function GetWidth() { function GetWidth() {
return $this->width; return $this->width;
} }
   
function Hide($aHide=true) { function Hide($aHide=true) {
$this->show = !$aHide; $this->show = !$aHide;
} }
   
function Show($aShow=true) { function Show($aShow=true) {
$this->show = $aShow; $this->show = $aShow;
} }
   
function SetCSIMAltVal($aY,$aX='') { function SetCSIMAltVal($aY,$aX='') {
$this->yvalue=$aY; $this->yvalue=$aY;
$this->xvalue=$aX; $this->xvalue=$aX;
} }
   
function SetCSIMTarget($aTarget,$aWinTarget='') { function SetCSIMTarget($aTarget,$aWinTarget='') {
$this->csimtarget=$aTarget; $this->csimtarget=$aTarget;
$this->csimwintarget=$aWinTarget; $this->csimwintarget=$aWinTarget;
} }
   
function SetCSIMAlt($aAlt) { function SetCSIMAlt($aAlt) {
$this->csimalt=$aAlt; $this->csimalt=$aAlt;
} }
   
function GetCSIMAreas(){ function GetCSIMAreas(){
return $this->csimareas; return $this->csimareas;
} }
   
function AddCSIMPoly($aPts) { function AddCSIMPoly($aPts) {
$coords = round($aPts[0]).", ".round($aPts[1]); $coords = round($aPts[0]).", ".round($aPts[1]);
$n = count($aPts)/2; $n = count($aPts)/2;
for( $i=1; $i < $n; ++$i){ for( $i=1; $i < $n; ++$i){
$coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]); $coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]);
} }
$this->csimareas=""; $this->csimareas="";
if( !empty($this->csimtarget) ) { if( !empty($this->csimtarget) ) {
$this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->csimtarget)."\""; $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->csimtarget)."\"";
   
if( !empty($this->csimwintarget) ) { if( !empty($this->csimwintarget) ) {
$this->csimareas .= " target=\"".$this->csimwintarget."\" "; $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
} }
   
if( !empty($this->csimalt) ) { if( !empty($this->csimalt) ) {
$tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\""; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\"";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
} }
   
function AddCSIMCircle($x,$y,$r) { function AddCSIMCircle($x,$y,$r) {
$x = round($x); $y=round($y); $r=round($r); $x = round($x); $y=round($y); $r=round($r);
$this->csimareas=""; $this->csimareas="";
if( !empty($this->csimtarget) ) { if( !empty($this->csimtarget) ) {
$this->csimareas .= "<area shape=\"circle\" coords=\"$x,$y,$r\" href=\"".htmlentities($this->csimtarget)."\""; $this->csimareas .= "<area shape=\"circle\" coords=\"$x,$y,$r\" href=\"".htmlentities($this->csimtarget)."\"";
   
if( !empty($this->csimwintarget) ) { if( !empty($this->csimwintarget) ) {
$this->csimareas .= " target=\"".$this->csimwintarget."\" "; $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
} }
   
if( !empty($this->csimalt) ) { if( !empty($this->csimalt) ) {
$tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
} }
function Stroke($img,$x,$y) { function Stroke($img,$x,$y) {
if( !$this->show ) return; if( !$this->show ) return;
   
if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) { if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) {
   
if( $this->iFormatCallback != '' ) { if( $this->iFormatCallback != '' ) {
$f = $this->iFormatCallback; $f = $this->iFormatCallback;
list($width,$color,$fcolor) = call_user_func($f,$this->yvalue); list($width,$color,$fcolor) = call_user_func($f,$this->yvalue);
$filename = $this->iFileName; $filename = $this->iFileName;
$imgscale = $this->iScale; $imgscale = $this->iScale;
} }
else { else {
$f = $this->iFormatCallback2; $f = $this->iFormatCallback2;
list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue); list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue);
if( $filename=="" ) $filename = $this->iFileName; if( $filename=="" ) $filename = $this->iFileName;
if( $imgscale=="" ) $imgscale = $this->iScale; if( $imgscale=="" ) $imgscale = $this->iScale;
} }
   
if( $width=="" ) $width = $this->width; if( $width=="" ) $width = $this->width;
if( $color=="" ) $color = $this->color; if( $color=="" ) $color = $this->color;
if( $fcolor=="" ) $fcolor = $this->fill_color; if( $fcolor=="" ) $fcolor = $this->fill_color;
   
} }
else { else {
$fcolor = $this->fill_color; $fcolor = $this->fill_color;
$color = $this->color; $color = $this->color;
$width = $this->width; $width = $this->width;
$filename = $this->iFileName; $filename = $this->iFileName;
$imgscale = $this->iScale; $imgscale = $this->iScale;
} }
   
if( $this->type == MARK_IMG || if( $this->type == MARK_IMG ||
($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) || ($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) ||
$this->type >= MARK_IMG_PUSHPIN ) { $this->type >= MARK_IMG_PUSHPIN ) {
   
// Note: For the builtin images we use the "filename" parameter // Note: For the builtin images we use the "filename" parameter
// to denote the color // to denote the color
$anchor_x = 0.5; $anchor_x = 0.5;
$anchor_y = 0.5; $anchor_y = 0.5;
switch( $this->type ) { switch( $this->type ) {
case MARK_FLAG1: case MARK_FLAG1:
case MARK_FLAG2: case MARK_FLAG2:
case MARK_FLAG3: case MARK_FLAG3:
case MARK_FLAG4: case MARK_FLAG4:
$this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename); $this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename);
break; break;
   
case MARK_IMG : case MARK_IMG :
// Load an image and use that as a marker // Load an image and use that as a marker
// Small optimization, if we have already read an image don't // Small optimization, if we have already read an image don't
// waste time reading it again. // waste time reading it again.
if( $this->markimg == '' || !($this->oldfilename === $filename) ) { if( $this->markimg == '' || !($this->oldfilename === $filename) ) {
$this->markimg = Graph::LoadBkgImage('',$filename); $this->markimg = Graph::LoadBkgImage('',$filename);
$this->oldfilename = $filename ; $this->oldfilename = $filename ;
} }
break; break;
   
case MARK_IMG_PUSHPIN: case MARK_IMG_PUSHPIN:
case MARK_IMG_SPUSHPIN: case MARK_IMG_SPUSHPIN:
case MARK_IMG_LPUSHPIN: case MARK_IMG_LPUSHPIN:
if( $this->imgdata_pushpins == null ) { if( $this->imgdata_pushpins == null ) {
require_once 'imgdata_pushpins.inc.php'; require_once 'imgdata_pushpins.inc.php';
$this->imgdata_pushpins = new ImgData_PushPins(); $this->imgdata_pushpins = new ImgData_PushPins();
} }
$this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename); $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename);
list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor(); list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor();
break; break;
   
case MARK_IMG_SQUARE: case MARK_IMG_SQUARE:
if( $this->imgdata_squares == null ) { if( $this->imgdata_squares == null ) {
require_once 'imgdata_squares.inc.php'; require_once 'imgdata_squares.inc.php';
$this->imgdata_squares = new ImgData_Squares(); $this->imgdata_squares = new ImgData_Squares();
} }
$this->markimg = $this->imgdata_squares->GetImg($this->type,$filename); $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename);
list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor(); list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor();
break; break;
   
case MARK_IMG_STAR: case MARK_IMG_STAR:
if( $this->imgdata_stars == null ) { if( $this->imgdata_stars == null ) {
require_once 'imgdata_stars.inc.php'; require_once 'imgdata_stars.inc.php';
$this->imgdata_stars = new ImgData_Stars(); $this->imgdata_stars = new ImgData_Stars();
} }
$this->markimg = $this->imgdata_stars->GetImg($this->type,$filename); $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename);
list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor(); list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor();
break; break;
   
case MARK_IMG_BEVEL: case MARK_IMG_BEVEL:
if( $this->imgdata_bevels == null ) { if( $this->imgdata_bevels == null ) {
require_once 'imgdata_bevels.inc.php'; require_once 'imgdata_bevels.inc.php';
$this->imgdata_bevels = new ImgData_Bevels(); $this->imgdata_bevels = new ImgData_Bevels();
} }
$this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename); $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename);
list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor(); list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor();
break; break;
   
case MARK_IMG_DIAMOND: case MARK_IMG_DIAMOND:
if( $this->imgdata_diamonds == null ) { if( $this->imgdata_diamonds == null ) {
require_once 'imgdata_diamonds.inc.php'; require_once 'imgdata_diamonds.inc.php';
$this->imgdata_diamonds = new ImgData_Diamonds(); $this->imgdata_diamonds = new ImgData_Diamonds();
} }
$this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename); $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename);
list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor(); list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor();
break; break;
   
case MARK_IMG_BALL: case MARK_IMG_BALL:
case MARK_IMG_SBALL: case MARK_IMG_SBALL:
case MARK_IMG_MBALL: case MARK_IMG_MBALL:
case MARK_IMG_LBALL: case MARK_IMG_LBALL:
if( $this->imgdata_balls == null ) { if( $this->imgdata_balls == null ) {
require_once 'imgdata_balls.inc.php'; require_once 'imgdata_balls.inc.php';
$this->imgdata_balls = new ImgData_Balls(); $this->imgdata_balls = new ImgData_Balls();
} }
$this->markimg = $this->imgdata_balls->GetImg($this->type,$filename); $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename);
list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor(); list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor();
break; break;
} }
   
$w = $img->GetWidth($this->markimg); $w = $img->GetWidth($this->markimg);
$h = $img->GetHeight($this->markimg); $h = $img->GetHeight($this->markimg);
$dw = round($imgscale * $w ); $dw = round($imgscale * $w );
$dh = round($imgscale * $h ); $dh = round($imgscale * $h );
   
// Do potential rotation // Do potential rotation
list($x,$y) = $img->Rotate($x,$y); list($x,$y) = $img->Rotate($x,$y);
   
$dx = round($x-$dw*$anchor_x); $dx = round($x-$dw*$anchor_x);
$dy = round($y-$dh*$anchor_y); $dy = round($y-$dh*$anchor_y);
$this->width = max($dx,$dy); $this->width = max($dx,$dy);
$img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h); $img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h);
if( !empty($this->csimtarget) ) { if( !empty($this->csimtarget) ) {
$this->csimareas = "<area shape=\"rect\" coords=\"". $this->csimareas = "<area shape=\"rect\" coords=\"".
$dx.','.$dy.','.round($dx+$dw).','.round($dy+$dh).'" '. $dx.','.$dy.','.round($dx+$dw).','.round($dy+$dh).'" '.
"href=\"".htmlentities($this->csimtarget)."\""; "href=\"".htmlentities($this->csimtarget)."\"";
   
if( !empty($this->csimwintarget) ) { if( !empty($this->csimwintarget) ) {
$this->csimareas .= " target=\"".$this->csimwintarget."\" "; $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
} }
   
if( !empty($this->csimalt) ) { if( !empty($this->csimalt) ) {
$tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue); $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
$this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" "; $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
} }
$this->csimareas .= " />\n"; $this->csimareas .= " />\n";
} }
// Stroke title // Stroke title
$this->title->Align("center","top"); $this->title->Align("center","top");
$this->title->Stroke($img,$x,$y+round($dh/2)); $this->title->Stroke($img,$x,$y+round($dh/2));
return; return;
} }
   
$weight = $this->weight; $weight = $this->weight;
$dx=round($width/2,0); $dx=round($width/2,0);
$dy=round($width/2,0); $dy=round($width/2,0);
$pts=0; $pts=0;
   
switch( $this->type ) { switch( $this->type ) {
case MARK_SQUARE: 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; $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; $pts=5;
break; break;
case MARK_UTRIANGLE: case MARK_UTRIANGLE:
++$dx;++$dy; ++$dx;++$dy;
$c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
$c[]=$x;$c[]=$y-0.87*$dy; $c[]=$x;$c[]=$y-0.87*$dy;
$c[]=$x+$dx;$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 $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
$pts=4; $pts=4;
break; break;
case MARK_DTRIANGLE: case MARK_DTRIANGLE:
++$dx;++$dy; ++$dx;++$dy;
$c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx $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+$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 $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
$pts=4; $pts=4;
break; break;
case MARK_DIAMOND: case MARK_DIAMOND:
$c[]=$x;$c[]=$y+$dy; $c[]=$x;$c[]=$y+$dy;
$c[]=$x-$dx;$c[]=$y; $c[]=$x-$dx;$c[]=$y;
$c[]=$x;$c[]=$y-$dy; $c[]=$x;$c[]=$y-$dy;
$c[]=$x+$dx;$c[]=$y; $c[]=$x+$dx;$c[]=$y;
$c[]=$x;$c[]=$y+$dy; $c[]=$x;$c[]=$y+$dy;
$pts=5; $pts=5;
break; break;
case MARK_LEFTTRIANGLE: case MARK_LEFTTRIANGLE:
$c[]=$x;$c[]=$y; $c[]=$x;$c[]=$y;
$c[]=$x;$c[]=$y+2*$dy; $c[]=$x;$c[]=$y+2*$dy;
$c[]=$x+$dx*2;$c[]=$y; $c[]=$x+$dx*2;$c[]=$y;
$c[]=$x;$c[]=$y; $c[]=$x;$c[]=$y;
$pts=4; $pts=4;
break; break;
case MARK_RIGHTTRIANGLE: case MARK_RIGHTTRIANGLE:
$c[]=$x-$dx*2;$c[]=$y; $c[]=$x-$dx*2;$c[]=$y;
$c[]=$x;$c[]=$y+2*$dy; $c[]=$x;$c[]=$y+2*$dy;
$c[]=$x;$c[]=$y; $c[]=$x;$c[]=$y;
$c[]=$x-$dx*2;$c[]=$y; $c[]=$x-$dx*2;$c[]=$y;
$pts=4; $pts=4;
break; break;
case MARK_FLASH: case MARK_FLASH:
$dy *= 2; $dy *= 2;
$c[]=$x+$dx/2; $c[]=$y-$dy; $c[]=$x+$dx/2; $c[]=$y-$dy;
$c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$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/2; $c[]=$y+$dy*1.3-$dy;
$c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy; $c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy;
$img->SetLineWeight($weight); $img->SetLineWeight($weight);
$img->SetColor($color); $img->SetColor($color);
$img->Polygon($c); $img->Polygon($c);
$img->SetLineWeight(1); $img->SetLineWeight(1);
$this->AddCSIMPoly($c); $this->AddCSIMPoly($c);
break; break;
} }
   
if( $pts>0 ) { if( $pts>0 ) {
$this->AddCSIMPoly($c); $this->AddCSIMPoly($c);
$img->SetLineWeight($weight); $img->SetLineWeight($weight);
$img->SetColor($fcolor); $img->SetColor($fcolor);
$img->FilledPolygon($c); $img->FilledPolygon($c);
$img->SetColor($color); $img->SetColor($color);
$img->Polygon($c); $img->Polygon($c);
$img->SetLineWeight(1); $img->SetLineWeight(1);
} }
elseif( $this->type==MARK_CIRCLE ) { elseif( $this->type==MARK_CIRCLE ) {
$img->SetColor($color); $img->SetColor($color);
$img->Circle($x,$y,$width); $img->Circle($x,$y,$width);
$this->AddCSIMCircle($x,$y,$width); $this->AddCSIMCircle($x,$y,$width);
} }
elseif( $this->type==MARK_FILLEDCIRCLE ) { elseif( $this->type==MARK_FILLEDCIRCLE ) {
$img->SetColor($fcolor); $img->SetColor($fcolor);
$img->FilledCircle($x,$y,$width); $img->FilledCircle($x,$y,$width);
$img->SetColor($color); $img->SetColor($color);
$img->Circle($x,$y,$width); $img->Circle($x,$y,$width);
$this->AddCSIMCircle($x,$y,$width); $this->AddCSIMCircle($x,$y,$width);
} }
elseif( $this->type==MARK_CROSS ) { elseif( $this->type==MARK_CROSS ) {
// Oversize by a pixel to match the X // Oversize by a pixel to match the X
$img->SetColor($color); $img->SetColor($color);
$img->SetLineWeight($weight); $img->SetLineWeight($weight);
$img->Line($x,$y+$dy+1,$x,$y-$dy-1); $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
$img->Line($x-$dx-1,$y,$x+$dx+1,$y); $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
$this->AddCSIMCircle($x,$y,$dx); $this->AddCSIMCircle($x,$y,$dx);
} }
elseif( $this->type==MARK_X ) { elseif( $this->type==MARK_X ) {
$img->SetColor($color); $img->SetColor($color);
$img->SetLineWeight($weight); $img->SetLineWeight($weight);
$img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy); $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
$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); $this->AddCSIMCircle($x,$y,$dx+$dy);
} }
elseif( $this->type==MARK_STAR ) { elseif( $this->type==MARK_STAR ) {
$img->SetColor($color); $img->SetColor($color);
$img->SetLineWeight($weight); $img->SetLineWeight($weight);
$img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy); $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
$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 // Oversize by a pixel to match the X
$img->Line($x,$y+$dy+1,$x,$y-$dy-1); $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
$img->Line($x-$dx-1,$y,$x+$dx+1,$y); $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
$this->AddCSIMCircle($x,$y,$dx+$dy); $this->AddCSIMCircle($x,$y,$dx+$dy);
} }
   
// Stroke title // Stroke title
$this->title->Align("center","center"); $this->title->Align("center","center");
$this->title->Stroke($img,$x,$y); $this->title->Stroke($img,$x,$y);
} }
} // Class } // Class
   
   
   
//======================================================================== //========================================================================
// CLASS ImgData // CLASS ImgData
// Description: Base class for all image data classes that contains the // Description: Base class for all image data classes that contains the
// real image data. // real image data.
//======================================================================== //========================================================================
class ImgData { class ImgData {
protected $name = ''; // Each subclass gives a name protected $name = ''; // Each subclass gives a name
protected $an = array(); // Data array names protected $an = array(); // Data array names
protected $colors = array(); // Available colors protected $colors = array(); // Available colors
protected $index = array(); // Index for colors protected $index = array(); // Index for colors
protected $maxidx = 0 ; // Max color index protected $maxidx = 0 ; // Max color index
protected $anchor_x=0.5, $anchor_y=0.5 ; // Where is the center of the image protected $anchor_x=0.5, $anchor_y=0.5 ; // Where is the center of the image
function __construct() { function __construct() {
// Empty // Empty
} }
// Create a GD image from the data and return a GD handle // Create a GD image from the data and return a GD handle
function GetImg($aMark,$aIdx) { function GetImg($aMark,$aIdx) {
$n = $this->an[$aMark]; $n = $this->an[$aMark];
if( is_string($aIdx) ) { if( is_string($aIdx) ) {
if( !in_array($aIdx,$this->colors) ) { if( !in_array($aIdx,$this->colors) ) {
JpGraphError::RaiseL(23001,$this->name,$aIdx);//('This marker "'.($this->name).'" does not exist in color: '.$aIdx); JpGraphError::RaiseL(23001,$this->name,$aIdx);//('This marker "'.($this->name).'" does not exist in color: '.$aIdx);
} }
$idx = $this->index[$aIdx]; $idx = $this->index[$aIdx];
} }
elseif( !is_integer($aIdx) || elseif( !is_integer($aIdx) ||
(is_integer($aIdx) && $aIdx > $this->maxidx ) ) { (is_integer($aIdx) && $aIdx > $this->maxidx ) ) {
JpGraphError::RaiseL(23002,$this->name);//('Mark color index too large for marker "'.($this->name).'"'); JpGraphError::RaiseL(23002,$this->name);//('Mark color index too large for marker "'.($this->name).'"');
} }
else else
$idx = $aIdx ; $idx = $aIdx ;
return Image::CreateFromString(base64_decode($this->{$n}[$idx][1])); return Image::CreateFromString(base64_decode($this->{$n}[$idx][1]));
} }
function GetAnchor() { function GetAnchor() {
return array($this->anchor_x,$this->anchor_y); return array($this->anchor_x,$this->anchor_y);
} }
} }
   
   
// Keep a global flag cache to reduce memory usage // Keep a global flag cache to reduce memory usage
$_gFlagCache=array( $_gFlagCache=array(
1 => null, 1 => null,
2 => null, 2 => null,
3 => null, 3 => null,
4 => null, 4 => null,
); );
// Only supposed to b called as statics // Only supposed to b called as statics
class FlagCache { class FlagCache {
static function GetFlagImgByName($aSize,$aName) { static function GetFlagImgByName($aSize,$aName) {
global $_gFlagCache; global $_gFlagCache;
require_once('jpgraph_flags.php'); require_once('jpgraph_flags.php');
if( $_gFlagCache[$aSize] === null ) { if( $_gFlagCache[$aSize] === null ) {
$_gFlagCache[$aSize] = new FlagImages($aSize); $_gFlagCache[$aSize] = new FlagImages($aSize);
} }
$f = $_gFlagCache[$aSize]; $f = $_gFlagCache[$aSize];
$idx = $f->GetIdxByName($aName,$aFullName); $idx = $f->GetIdxByName($aName,$aFullName);
return $f->GetImgByIdx($idx); return $f->GetImgByIdx($idx);
} }
} }
   
?> ?>
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_POLAR.PHP // File: JPGRAPH_POLAR.PHP
// Description: Polar plot extension for JpGraph // Description: Polar plot extension for JpGraph
// Created: 2003-02-02 // Created: 2003-02-02
// Ver: $Id: jpgraph_polar.php 1796 2009-09-07 09:37:19Z ljp $ // Ver: $Id: jpgraph_polar.php 1796 2009-09-07 09:37:19Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
require_once ('jpgraph_plotmark.inc.php'); require_once ('jpgraph_plotmark.inc.php');
require_once "jpgraph_log.php"; require_once "jpgraph_log.php";
   
   
define('POLAR_360',1); define('POLAR_360',1);
define('POLAR_180',2); define('POLAR_180',2);
   
// //
// Note. Don't attempt to make sense of this code. // Note. Don't attempt to make sense of this code.
// In order not to have to be able to inherit the scaling code // In order not to have to be able to inherit the scaling code
// from the main graph package we have had to make some "tricks" since // from the main graph package we have had to make some "tricks" since
// the original scaling and axis was not designed to do what is // the original scaling and axis was not designed to do what is
// required here. // required here.
// There were two option. 1: Re-implement everything and get a clean design // There were two option. 1: Re-implement everything and get a clean design
// and 2: do some "small" trickery and be able to inherit most of // and 2: do some "small" trickery and be able to inherit most of
// the functionlity from the main graph package. // the functionlity from the main graph package.
// We choose 2: here in order to save some time. // We choose 2: here in order to save some time.
// //
   
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// class PolarPlot // class PolarPlot
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
class PolarPlot { class PolarPlot {
public $line_style='solid',$mark; public $line_style='solid',$mark;
public $legendcsimtarget=''; public $legendcsimtarget='';
public $legendcsimalt=''; public $legendcsimalt='';
public $legend=""; public $legend="";
public $csimtargets=array(); // Array of targets for CSIM public $csimtargets=array(); // Array of targets for CSIM
public $csimareas=""; // Resultant CSIM area tags public $csimareas=""; // Resultant CSIM area tags
public $csimalts=null; // ALT:s for corresponding target public $csimalts=null; // ALT:s for corresponding target
public $scale=null; public $scale=null;
private $numpoints=0; private $numpoints=0;
private $iColor='navy',$iFillColor=''; private $iColor='navy',$iFillColor='';
private $iLineWeight=1; private $iLineWeight=1;
private $coord=null; private $coord=null;
   
function __construct($aData) { function __construct($aData) {
$n = count($aData); $n = count($aData);
if( $n & 1 ) { if( $n & 1 ) {
JpGraphError::RaiseL(17001); JpGraphError::RaiseL(17001);
//('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).'); //('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).');
} }
$this->numpoints = $n/2; $this->numpoints = $n/2;
$this->coord = $aData; $this->coord = $aData;
$this->mark = new PlotMark(); $this->mark = new PlotMark();
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->iLineWeight = $aWeight; $this->iLineWeight = $aWeight;
} }
   
function SetColor($aColor){ function SetColor($aColor){
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function SetFillColor($aColor){ function SetFillColor($aColor){
$this->iFillColor = $aColor; $this->iFillColor = $aColor;
} }
   
function Max() { function Max() {
$m = $this->coord[1]; $m = $this->coord[1];
$i=1; $i=1;
while( $i < $this->numpoints ) { while( $i < $this->numpoints ) {
$m = max($m,$this->coord[2*$i+1]); $m = max($m,$this->coord[2*$i+1]);
++$i; ++$i;
} }
return $m; return $m;
} }
// Set href targets for CSIM // Set href targets for CSIM
function SetCSIMTargets($aTargets,$aAlts=null) { function SetCSIMTargets($aTargets,$aAlts=null) {
$this->csimtargets=$aTargets; $this->csimtargets=$aTargets;
$this->csimalts=$aAlts; $this->csimalts=$aAlts;
} }
   
// Get all created areas // Get all created areas
function GetCSIMareas() { function GetCSIMareas() {
return $this->csimareas; return $this->csimareas;
} }
   
function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") { function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") {
$this->legend = $aLegend; $this->legend = $aLegend;
$this->legendcsimtarget = $aCSIM; $this->legendcsimtarget = $aCSIM;
$this->legendcsimalt = $aCSIMAlt; $this->legendcsimalt = $aCSIMAlt;
} }
   
// Private methods // Private methods
   
function Legend($aGraph) { function Legend($aGraph) {
$color = $this->iColor ; $color = $this->iColor ;
if( $this->legend != "" ) { if( $this->legend != "" ) {
if( $this->iFillColor!='' ) { if( $this->iFillColor!='' ) {
$color = $this->iFillColor; $color = $this->iFillColor;
$aGraph->legend->Add($this->legend,$color,$this->mark,0, $aGraph->legend->Add($this->legend,$color,$this->mark,0,
$this->legendcsimtarget,$this->legendcsimalt); $this->legendcsimtarget,$this->legendcsimalt);
} }
else { else {
$aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style, $aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style,
$this->legendcsimtarget,$this->legendcsimalt); $this->legendcsimtarget,$this->legendcsimalt);
} }
} }
} }
   
function Stroke($img,$scale) { function Stroke($img,$scale) {
   
$i=0; $i=0;
$p=array(); $p=array();
$this->csimareas=''; $this->csimareas='';
while($i < $this->numpoints) { while($i < $this->numpoints) {
list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]); list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]);
$p[2*$i] = $x1; $p[2*$i] = $x1;
$p[2*$i+1] = $y1; $p[2*$i+1] = $y1;
   
if( isset($this->csimtargets[$i]) ) { if( isset($this->csimtargets[$i]) ) {
$this->mark->SetCSIMTarget($this->csimtargets[$i]); $this->mark->SetCSIMTarget($this->csimtargets[$i]);
$this->mark->SetCSIMAlt($this->csimalts[$i]); $this->mark->SetCSIMAlt($this->csimalts[$i]);
$this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]); $this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]);
$this->mark->Stroke($img,$x1,$y1); $this->mark->Stroke($img,$x1,$y1);
$this->csimareas .= $this->mark->GetCSIMAreas(); $this->csimareas .= $this->mark->GetCSIMAreas();
} }
else { else {
$this->mark->Stroke($img,$x1,$y1); $this->mark->Stroke($img,$x1,$y1);
} }
   
++$i; ++$i;
} }
   
if( $this->iFillColor != '' ) { if( $this->iFillColor != '' ) {
$img->SetColor($this->iFillColor); $img->SetColor($this->iFillColor);
$img->FilledPolygon($p); $img->FilledPolygon($p);
} }
$img->SetLineWeight($this->iLineWeight); $img->SetLineWeight($this->iLineWeight);
$img->SetColor($this->iColor); $img->SetColor($this->iColor);
$img->Polygon($p,$this->iFillColor!=''); $img->Polygon($p,$this->iFillColor!='');
} }
} }
   
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// class PolarAxis // class PolarAxis
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
class PolarAxis extends Axis { class PolarAxis extends Axis {
private $angle_step=15,$angle_color='lightgray',$angle_label_color='black'; 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_fontfam=FF_FONT1,$angle_fontstyle=FS_NORMAL,$angle_fontsize=10;
private $angle_fontcolor = 'navy'; private $angle_fontcolor = 'navy';
private $gridminor_color='lightgray',$gridmajor_color='lightgray'; private $gridminor_color='lightgray',$gridmajor_color='lightgray';
private $show_minor_grid = false, $show_major_grid = true ; private $show_minor_grid = false, $show_major_grid = true ;
private $show_angle_mark=true, $show_angle_grid=true, $show_angle_label=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 $angle_tick_len=3, $angle_tick_len2=3, $angle_tick_color='black';
private $show_angle_tick=true; private $show_angle_tick=true;
private $radius_tick_color='black'; private $radius_tick_color='black';
   
function __construct($img,$aScale) { function __construct($img,$aScale) {
parent::__construct($img,$aScale); parent::__construct($img,$aScale);
} }
   
function ShowAngleDegreeMark($aFlg=true) { function ShowAngleDegreeMark($aFlg=true) {
$this->show_angle_mark = $aFlg; $this->show_angle_mark = $aFlg;
} }
   
function SetAngleStep($aStep) { function SetAngleStep($aStep) {
$this->angle_step=$aStep; $this->angle_step=$aStep;
} }
   
function HideTicks($aFlg=true,$aAngleFlg=true) { function HideTicks($aFlg=true,$aAngleFlg=true) {
parent::HideTicks($aFlg,$aFlg); parent::HideTicks($aFlg,$aFlg);
$this->show_angle_tick = !$aAngleFlg; $this->show_angle_tick = !$aAngleFlg;
} }
   
function ShowAngleLabel($aFlg=true) { function ShowAngleLabel($aFlg=true) {
$this->show_angle_label = $aFlg; $this->show_angle_label = $aFlg;
} }
   
function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) { function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) {
$this->show_minor_grid = $aMinor; $this->show_minor_grid = $aMinor;
$this->show_major_grid = $aMajor; $this->show_major_grid = $aMajor;
$this->show_angle_grid = $aAngle ; $this->show_angle_grid = $aAngle ;
} }
   
function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) { function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) {
$this->angle_fontfam = $aFontFam; $this->angle_fontfam = $aFontFam;
$this->angle_fontstyle = $aFontStyle; $this->angle_fontstyle = $aFontStyle;
$this->angle_fontsize = $aFontSize; $this->angle_fontsize = $aFontSize;
} }
   
function SetColor($aColor,$aRadColor='',$aAngleColor='') { function SetColor($aColor,$aRadColor='',$aAngleColor='') {
if( $aAngleColor == '' ) if( $aAngleColor == '' )
$aAngleColor=$aColor; $aAngleColor=$aColor;
parent::SetColor($aColor,$aRadColor); parent::SetColor($aColor,$aRadColor);
$this->angle_fontcolor = $aAngleColor; $this->angle_fontcolor = $aAngleColor;
} }
   
function SetGridColor($aMajorColor,$aMinorColor='',$aAngleColor='') { function SetGridColor($aMajorColor,$aMinorColor='',$aAngleColor='') {
if( $aMinorColor == '' ) if( $aMinorColor == '' )
$aMinorColor = $aMajorColor; $aMinorColor = $aMajorColor;
if( $aAngleColor == '' ) if( $aAngleColor == '' )
$aAngleColor = $aMajorColor; $aAngleColor = $aMajorColor;
   
$this->gridminor_color = $aMinorColor; $this->gridminor_color = $aMinorColor;
$this->gridmajor_color = $aMajorColor; $this->gridmajor_color = $aMajorColor;
$this->angle_color = $aAngleColor; $this->angle_color = $aAngleColor;
} }
   
function SetTickColors($aRadColor,$aAngleColor='') { function SetTickColors($aRadColor,$aAngleColor='') {
$this->radius_tick_color = $aRadColor; $this->radius_tick_color = $aRadColor;
$this->angle_tick_color = $aAngleColor; $this->angle_tick_color = $aAngleColor;
} }
   
// Private methods // Private methods
function StrokeGrid($pos) { function StrokeGrid($pos) {
$x = round($this->img->left_margin + $this->img->plotwidth/2); $x = round($this->img->left_margin + $this->img->plotwidth/2);
$this->scale->ticks->Stroke($this->img,$this->scale,$pos); $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
   
// Stroke the minor arcs // Stroke the minor arcs
$pmin = array(); $pmin = array();
$p = $this->scale->ticks->ticks_pos; $p = $this->scale->ticks->ticks_pos;
$n = count($p); $n = count($p);
$i = 0; $i = 0;
$this->img->SetColor($this->gridminor_color); $this->img->SetColor($this->gridminor_color);
while( $i < $n ) { while( $i < $n ) {
$r = $p[$i]-$x+1; $r = $p[$i]-$x+1;
$pmin[]=$r; $pmin[]=$r;
if( $this->show_minor_grid ) { if( $this->show_minor_grid ) {
$this->img->Circle($x,$pos,$r); $this->img->Circle($x,$pos,$r);
} }
$i++; $i++;
} }
   
$limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ; $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
while( $r < $limit ) { while( $r < $limit ) {
$off = $r; $off = $r;
$i=1; $i=1;
$r = $off + round($p[$i]-$x+1); $r = $off + round($p[$i]-$x+1);
while( $r < $limit && $i < $n ) { while( $r < $limit && $i < $n ) {
$r = $off+$p[$i]-$x; $r = $off+$p[$i]-$x;
$pmin[]=$r; $pmin[]=$r;
if( $this->show_minor_grid ) { if( $this->show_minor_grid ) {
$this->img->Circle($x,$pos,$r); $this->img->Circle($x,$pos,$r);
} }
$i++; $i++;
} }
} }
   
// Stroke the major arcs // Stroke the major arcs
if( $this->show_major_grid ) { if( $this->show_major_grid ) {
// First determine how many minor step on // First determine how many minor step on
// every major step. We have recorded the minor radius // every major step. We have recorded the minor radius
// in pmin and use these values. This is done in order // in pmin and use these values. This is done in order
// to avoid rounding errors if we were to recalculate the // to avoid rounding errors if we were to recalculate the
// different major radius. // different major radius.
$pmaj = $this->scale->ticks->maj_ticks_pos; $pmaj = $this->scale->ticks->maj_ticks_pos;
$p = $this->scale->ticks->ticks_pos; $p = $this->scale->ticks->ticks_pos;
if( $this->scale->name == 'lin' ) { if( $this->scale->name == 'lin' ) {
$step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0])); $step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0]));
} }
else { else {
$step=9; $step=9;
} }
$n = round(count($pmin)/$step); $n = round(count($pmin)/$step);
$i = 0; $i = 0;
$this->img->SetColor($this->gridmajor_color); $this->img->SetColor($this->gridmajor_color);
$limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ; $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
$off = $r; $off = $r;
$i=0; $i=0;
$r = $pmin[$i*$step]; $r = $pmin[$i*$step];
while( $r < $limit && $i < $n ) { while( $r < $limit && $i < $n ) {
$r = $pmin[$i*$step]; $r = $pmin[$i*$step];
$this->img->Circle($x,$pos,$r); $this->img->Circle($x,$pos,$r);
$i++; $i++;
} }
} }
   
// Draw angles // Draw angles
if( $this->show_angle_grid ) { if( $this->show_angle_grid ) {
$this->img->SetColor($this->angle_color); $this->img->SetColor($this->angle_color);
$d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ; $d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ;
$a = 0; $a = 0;
$p = $this->scale->ticks->ticks_pos; $p = $this->scale->ticks->ticks_pos;
$start_radius = $p[1]-$x; $start_radius = $p[1]-$x;
while( $a < 360 ) { while( $a < 360 ) {
if( $a == 90 || $a == 270 ) { if( $a == 90 || $a == 270 ) {
// Make sure there are no rounding problem with // Make sure there are no rounding problem with
// exactly vertical lines // exactly vertical lines
$this->img->Line($x+$start_radius*cos($a/180*M_PI)+1, $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
$pos-$start_radius*sin($a/180*M_PI), $pos-$start_radius*sin($a/180*M_PI),
$x+$start_radius*cos($a/180*M_PI)+1, $x+$start_radius*cos($a/180*M_PI)+1,
$pos-$d*sin($a/180*M_PI)); $pos-$d*sin($a/180*M_PI));
   
} }
else { else {
$this->img->Line($x+$start_radius*cos($a/180*M_PI)+1, $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
$pos-$start_radius*sin($a/180*M_PI), $pos-$start_radius*sin($a/180*M_PI),
$x+$d*cos($a/180*M_PI), $x+$d*cos($a/180*M_PI),
$pos-$d*sin($a/180*M_PI)); $pos-$d*sin($a/180*M_PI));
} }
$a += $this->angle_step; $a += $this->angle_step;
} }
} }
} }
   
function StrokeAngleLabels($pos,$type) { function StrokeAngleLabels($pos,$type) {
   
if( !$this->show_angle_label ) if( !$this->show_angle_label )
return; return;
   
$x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1; $x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1;
   
$d = max($this->img->plotwidth,$this->img->plotheight)*1.42; $d = max($this->img->plotwidth,$this->img->plotheight)*1.42;
$a = $this->angle_step; $a = $this->angle_step;
$t = new Text(); $t = new Text();
$t->SetColor($this->angle_fontcolor); $t->SetColor($this->angle_fontcolor);
$t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize); $t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize);
$xright = $this->img->width - $this->img->right_margin; $xright = $this->img->width - $this->img->right_margin;
$ytop = $this->img->top_margin; $ytop = $this->img->top_margin;
$xleft = $this->img->left_margin; $xleft = $this->img->left_margin;
$ybottom = $this->img->height - $this->img->bottom_margin; $ybottom = $this->img->height - $this->img->bottom_margin;
$ha = 'left'; $ha = 'left';
$va = 'center'; $va = 'center';
$w = $this->img->plotwidth/2; $w = $this->img->plotwidth/2;
$h = $this->img->plotheight/2; $h = $this->img->plotheight/2;
$xt = $x0; $yt = $pos; $xt = $x0; $yt = $pos;
$margin=5; $margin=5;
   
$tl = $this->angle_tick_len ; // Outer len $tl = $this->angle_tick_len ; // Outer len
$tl2 = $this->angle_tick_len2 ; // Interior len $tl2 = $this->angle_tick_len2 ; // Interior len
   
$this->img->SetColor($this->angle_tick_color); $this->img->SetColor($this->angle_tick_color);
$rot90 = $this->img->a == 90 ; $rot90 = $this->img->a == 90 ;
   
if( $type == POLAR_360 ) { if( $type == POLAR_360 ) {
   
// Corner angles of the four corners // Corner angles of the four corners
$ca1 = atan($h/$w)/M_PI*180; $ca1 = atan($h/$w)/M_PI*180;
$ca2 = 180-$ca1; $ca2 = 180-$ca1;
$ca3 = $ca1+180; $ca3 = $ca1+180;
$ca4 = 360-$ca1; $ca4 = 360-$ca1;
$end = 360; $end = 360;
   
while( $a < $end ) { while( $a < $end ) {
$ca = cos($a/180*M_PI); $ca = cos($a/180*M_PI);
$sa = sin($a/180*M_PI); $sa = sin($a/180*M_PI);
$x = $d*$ca; $x = $d*$ca;
$y = $d*$sa; $y = $d*$sa;
$xt=1000;$yt=1000; $xt=1000;$yt=1000;
if( $a <= $ca1 || $a >= $ca4 ) { if( $a <= $ca1 || $a >= $ca4 ) {
$yt = $pos - $w * $y/$x; $yt = $pos - $w * $y/$x;
$xt = $xright + $margin; $xt = $xright + $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'center'; $ha = 'center';
$va = 'top'; $va = 'top';
} }
else { else {
$ha = 'left'; $ha = 'left';
$va = 'center'; $va = 'center';
} }
$x1=$xright-$tl2; $x2=$xright+$tl; $x1=$xright-$tl2; $x2=$xright+$tl;
$y1=$y2=$yt; $y1=$y2=$yt;
} }
elseif( $a > $ca1 && $a < $ca2 ) { elseif( $a > $ca1 && $a < $ca2 ) {
$xt = $x0 + $h * $x/$y; $xt = $x0 + $h * $x/$y;
$yt = $ytop - $margin; $yt = $ytop - $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'left'; $ha = 'left';
$va = 'center'; $va = 'center';
} }
else { else {
$ha = 'center'; $ha = 'center';
$va = 'bottom'; $va = 'bottom';
} }
$y1=$ytop+$tl2;$y2=$ytop-$tl; $y1=$ytop+$tl2;$y2=$ytop-$tl;
$x1=$x2=$xt; $x1=$x2=$xt;
} }
elseif( $a >= $ca2 && $a <= $ca3 ) { elseif( $a >= $ca2 && $a <= $ca3 ) {
$yt = $pos + $w * $y/$x; $yt = $pos + $w * $y/$x;
$xt = $xleft - $margin; $xt = $xleft - $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'center'; $ha = 'center';
$va = 'bottom'; $va = 'bottom';
} }
else { else {
$ha = 'right'; $ha = 'right';
$va = 'center'; $va = 'center';
} }
$x1=$xleft+$tl2;$x2=$xleft-$tl; $x1=$xleft+$tl2;$x2=$xleft-$tl;
$y1=$y2=$yt; $y1=$y2=$yt;
} }
else { else {
$xt = $x0 - $h * $x/$y; $xt = $x0 - $h * $x/$y;
$yt = $ybottom + $margin; $yt = $ybottom + $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'right'; $ha = 'right';
$va = 'center'; $va = 'center';
} }
else { else {
$ha = 'center'; $ha = 'center';
$va = 'top'; $va = 'top';
} }
$y1=$ybottom-$tl2;$y2=$ybottom+$tl; $y1=$ybottom-$tl2;$y2=$ybottom+$tl;
$x1=$x2=$xt; $x1=$x2=$xt;
} }
if( $a != 0 && $a != 180 ) { if( $a != 0 && $a != 180 ) {
$t->Align($ha,$va); $t->Align($ha,$va);
if( $this->scale->clockwise ) { if( $this->scale->clockwise ) {
$t->Set(360-$a); $t->Set(360-$a);
} }
else { else {
$t->Set($a); $t->Set($a);
} }
if( $this->show_angle_mark && $t->font_family > 4 ) { if( $this->show_angle_mark && $t->font_family > 4 ) {
$a .= SymChar::Get('degree'); $a .= SymChar::Get('degree');
} }
$t->Stroke($this->img,$xt,$yt); $t->Stroke($this->img,$xt,$yt);
if( $this->show_angle_tick ) { if( $this->show_angle_tick ) {
$this->img->Line($x1,$y1,$x2,$y2); $this->img->Line($x1,$y1,$x2,$y2);
} }
} }
$a += $this->angle_step; $a += $this->angle_step;
} }
} }
else { else {
// POLAR_HALF // POLAR_HALF
$ca1 = atan($h/$w*2)/M_PI*180; $ca1 = atan($h/$w*2)/M_PI*180;
$ca2 = 180-$ca1; $ca2 = 180-$ca1;
$end = 180; $end = 180;
while( $a < $end ) { while( $a < $end ) {
$ca = cos($a/180*M_PI); $ca = cos($a/180*M_PI);
$sa = sin($a/180*M_PI); $sa = sin($a/180*M_PI);
$x = $d*$ca; $x = $d*$ca;
$y = $d*$sa; $y = $d*$sa;
if( $a <= $ca1 ) { if( $a <= $ca1 ) {
$yt = $pos - $w * $y/$x; $yt = $pos - $w * $y/$x;
$xt = $xright + $margin; $xt = $xright + $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'center'; $ha = 'center';
$va = 'top'; $va = 'top';
} }
else { else {
$ha = 'left'; $ha = 'left';
$va = 'center'; $va = 'center';
} }
$x1=$xright-$tl2; $x2=$xright+$tl; $x1=$xright-$tl2; $x2=$xright+$tl;
$y1=$y2=$yt; $y1=$y2=$yt;
} }
elseif( $a > $ca1 && $a < $ca2 ) { elseif( $a > $ca1 && $a < $ca2 ) {
$xt = $x0 + 2*$h * $x/$y; $xt = $x0 + 2*$h * $x/$y;
$yt = $ytop - $margin; $yt = $ytop - $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'left'; $ha = 'left';
$va = 'center'; $va = 'center';
} }
else { else {
$ha = 'center'; $ha = 'center';
$va = 'bottom'; $va = 'bottom';
} }
$y1=$ytop+$tl2;$y2=$ytop-$tl; $y1=$ytop+$tl2;$y2=$ytop-$tl;
$x1=$x2=$xt; $x1=$x2=$xt;
} }
elseif( $a >= $ca2 ) { elseif( $a >= $ca2 ) {
$yt = $pos + $w * $y/$x; $yt = $pos + $w * $y/$x;
$xt = $xleft - $margin; $xt = $xleft - $margin;
if( $rot90 ) { if( $rot90 ) {
$ha = 'center'; $ha = 'center';
$va = 'bottom'; $va = 'bottom';
} }
else { else {
$ha = 'right'; $ha = 'right';
$va = 'center'; $va = 'center';
} }
$x1=$xleft+$tl2;$x2=$xleft-$tl; $x1=$xleft+$tl2;$x2=$xleft-$tl;
$y1=$y2=$yt; $y1=$y2=$yt;
} }
$t->Align($ha,$va); $t->Align($ha,$va);
if( $this->show_angle_mark && $t->font_family > 4 ) { if( $this->show_angle_mark && $t->font_family > 4 ) {
$a .= SymChar::Get('degree'); $a .= SymChar::Get('degree');
} }
$t->Set($a); $t->Set($a);
$t->Stroke($this->img,$xt,$yt); $t->Stroke($this->img,$xt,$yt);
if( $this->show_angle_tick ) { if( $this->show_angle_tick ) {
$this->img->Line($x1,$y1,$x2,$y2); $this->img->Line($x1,$y1,$x2,$y2);
} }
$a += $this->angle_step; $a += $this->angle_step;
} }
} }
} }
   
function Stroke($pos,$dummy=true) { function Stroke($pos,$dummy=true) {
   
$this->img->SetLineWeight($this->weight); $this->img->SetLineWeight($this->weight);
$this->img->SetColor($this->color); $this->img->SetColor($this->color);
$this->img->SetFont($this->font_family,$this->font_style,$this->font_size); $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
if( !$this->hide_line ) { if( !$this->hide_line ) {
$this->img->FilledRectangle($this->img->left_margin,$pos, $this->img->FilledRectangle($this->img->left_margin,$pos,
$this->img->width-$this->img->right_margin, $this->img->width-$this->img->right_margin,
$pos+$this->weight-1); $pos+$this->weight-1);
} }
$y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin; $y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin;
if( $this->title_adjust=="high" ) { if( $this->title_adjust=="high" ) {
$this->title->SetPos($this->img->width-$this->img->right_margin,$y,"right","top"); $this->title->SetPos($this->img->width-$this->img->right_margin,$y,"right","top");
} }
elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" ) { 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, $this->title->SetPos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin,
$y,"center","top"); $y,"center","top");
} }
elseif($this->title_adjust=="low") { elseif($this->title_adjust=="low") {
$this->title->SetPos($this->img->left_margin,$y,"left","top"); $this->title->SetPos($this->img->left_margin,$y,"left","top");
} }
else { else {
JpGraphError::RaiseL(17002,$this->title_adjust); JpGraphError::RaiseL(17002,$this->title_adjust);
//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')'); //('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')');
} }
   
   
if (!$this->hide_labels) { if (!$this->hide_labels) {
$this->StrokeLabels($pos,false); $this->StrokeLabels($pos,false);
} }
$this->img->SetColor($this->radius_tick_color); $this->img->SetColor($this->radius_tick_color);
$this->scale->ticks->Stroke($this->img,$this->scale,$pos); $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
   
// //
// Mirror the positions for the left side of the scale // Mirror the positions for the left side of the scale
// //
$mid = 2*($this->img->left_margin+$this->img->plotwidth/2); $mid = 2*($this->img->left_margin+$this->img->plotwidth/2);
$n = count($this->scale->ticks->ticks_pos); $n = count($this->scale->ticks->ticks_pos);
$i=0; $i=0;
while( $i < $n ) { while( $i < $n ) {
$this->scale->ticks->ticks_pos[$i] = $this->scale->ticks->ticks_pos[$i] =
$mid-$this->scale->ticks->ticks_pos[$i] ; $mid-$this->scale->ticks->ticks_pos[$i] ;
++$i; ++$i;
} }
   
$n = count($this->scale->ticks->maj_ticks_pos); $n = count($this->scale->ticks->maj_ticks_pos);
$i=0; $i=0;
while( $i < $n ) { while( $i < $n ) {
$this->scale->ticks->maj_ticks_pos[$i] = $this->scale->ticks->maj_ticks_pos[$i] =
$mid-$this->scale->ticks->maj_ticks_pos[$i] ; $mid-$this->scale->ticks->maj_ticks_pos[$i] ;
++$i; ++$i;
} }
   
$n = count($this->scale->ticks->maj_ticklabels_pos); $n = count($this->scale->ticks->maj_ticklabels_pos);
$i=1; $i=1;
while( $i < $n ) { while( $i < $n ) {
$this->scale->ticks->maj_ticklabels_pos[$i] = $this->scale->ticks->maj_ticklabels_pos[$i] =
$mid-$this->scale->ticks->maj_ticklabels_pos[$i] ; $mid-$this->scale->ticks->maj_ticklabels_pos[$i] ;
++$i; ++$i;
} }
   
// Draw the left side of the scale // Draw the left side of the scale
$n = count($this->scale->ticks->ticks_pos); $n = count($this->scale->ticks->ticks_pos);
$yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize(); $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize();
   
   
// Minor ticks // Minor ticks
if( ! $this->scale->ticks->supress_minor_tickmarks ) { if( ! $this->scale->ticks->supress_minor_tickmarks ) {
$i=1; $i=1;
while( $i < $n/2 ) { while( $i < $n/2 ) {
$x = round($this->scale->ticks->ticks_pos[$i]) ; $x = round($this->scale->ticks->ticks_pos[$i]) ;
$this->img->Line($x,$pos,$x,$yu); $this->img->Line($x,$pos,$x,$yu);
++$i; ++$i;
} }
} }
   
$n = count($this->scale->ticks->maj_ticks_pos); $n = count($this->scale->ticks->maj_ticks_pos);
$yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize(); $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize();
   
   
// Major ticks // Major ticks
if( ! $this->scale->ticks->supress_tickmarks ) { if( ! $this->scale->ticks->supress_tickmarks ) {
$i=1; $i=1;
while( $i < $n/2 ) { while( $i < $n/2 ) {
$x = round($this->scale->ticks->maj_ticks_pos[$i]) ; $x = round($this->scale->ticks->maj_ticks_pos[$i]) ;
$this->img->Line($x,$pos,$x,$yu); $this->img->Line($x,$pos,$x,$yu);
++$i; ++$i;
} }
} }
if (!$this->hide_labels) { if (!$this->hide_labels) {
$this->StrokeLabels($pos,false); $this->StrokeLabels($pos,false);
} }
$this->title->Stroke($this->img); $this->title->Stroke($this->img);
} }
} }
   
class PolarScale extends LinearScale { class PolarScale extends LinearScale {
private $graph; private $graph;
public $clockwise=false; public $clockwise=false;
   
function __construct($aMax,$graph,$aClockwise) { function __construct($aMax,$graph,$aClockwise) {
parent::__construct(0,$aMax,'x'); parent::__construct(0,$aMax,'x');
$this->graph = $graph; $this->graph = $graph;
$this->clockwise = $aClockwise; $this->clockwise = $aClockwise;
} }
   
function SetClockwise($aFlg) { function SetClockwise($aFlg) {
$this->clockwise = $aFlg; $this->clockwise = $aFlg;
} }
   
function _Translate($v) { function _Translate($v) {
return parent::Translate($v); return parent::Translate($v);
} }
   
function PTranslate($aAngle,$aRad) { function PTranslate($aAngle,$aRad) {
   
$m = $this->scale[1]; $m = $this->scale[1];
$w = $this->graph->img->plotwidth/2; $w = $this->graph->img->plotwidth/2;
$aRad = $aRad/$m*$w; $aRad = $aRad/$m*$w;
   
$a = $aAngle/180 * M_PI; $a = $aAngle/180 * M_PI;
if( $this->clockwise ) { if( $this->clockwise ) {
$a = 2*M_PI-$a; $a = 2*M_PI-$a;
} }
   
$x = cos($a) * $aRad; $x = cos($a) * $aRad;
$y = sin($a) * $aRad; $y = sin($a) * $aRad;
   
$x += $this->_Translate(0); $x += $this->_Translate(0);
   
if( $this->graph->iType == POLAR_360 ) { if( $this->graph->iType == POLAR_360 ) {
$y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y; $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
} }
else { else {
$y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y; $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
} }
return array($x,$y); return array($x,$y);
} }
} }
   
class PolarLogScale extends LogScale { class PolarLogScale extends LogScale {
private $graph; private $graph;
public $clockwise=false; public $clockwise=false;
   
function __construct($aMax,$graph,$aClockwise=false) { function __construct($aMax,$graph,$aClockwise=false) {
parent::__construct(0,$aMax,'x'); parent::__construct(0,$aMax,'x');
$this->graph = $graph; $this->graph = $graph;
$this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE); $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE);
$this->clockwise = $aClockwise; $this->clockwise = $aClockwise;
   
} }
   
function SetClockwise($aFlg) { function SetClockwise($aFlg) {
$this->clockwise = $aFlg; $this->clockwise = $aFlg;
} }
   
function PTranslate($aAngle,$aRad) { function PTranslate($aAngle,$aRad) {
   
if( $aRad == 0 ) if( $aRad == 0 )
$aRad = 1; $aRad = 1;
$aRad = log10($aRad); $aRad = log10($aRad);
$m = $this->scale[1]; $m = $this->scale[1];
$w = $this->graph->img->plotwidth/2; $w = $this->graph->img->plotwidth/2;
$aRad = $aRad/$m*$w; $aRad = $aRad/$m*$w;
   
$a = $aAngle/180 * M_PI; $a = $aAngle/180 * M_PI;
if( $this->clockwise ) { if( $this->clockwise ) {
$a = 2*M_PI-$a; $a = 2*M_PI-$a;
} }
   
$x = cos( $a ) * $aRad; $x = cos( $a ) * $aRad;
$y = sin( $a ) * $aRad; $y = sin( $a ) * $aRad;
   
$x += $w+$this->graph->img->left_margin;//$this->_Translate(0); $x += $w+$this->graph->img->left_margin;//$this->_Translate(0);
if( $this->graph->iType == POLAR_360 ) { if( $this->graph->iType == POLAR_360 ) {
$y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y; $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
} }
else { else {
$y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y; $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
} }
return array($x,$y); return array($x,$y);
} }
} }
   
class PolarGraph extends Graph { class PolarGraph extends Graph {
public $scale; public $scale;
public $axis; public $axis;
public $iType=POLAR_360; public $iType=POLAR_360;
private $iClockwise=false; private $iClockwise=false;
   
function __construct($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) { function __construct($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) {
parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ; parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ;
$this->SetDensity(TICKD_DENSE); $this->SetDensity(TICKD_DENSE);
$this->SetBox(); $this->SetBox();
$this->SetMarginColor('white'); $this->SetMarginColor('white');
} }
   
function SetDensity($aDense) { function SetDensity($aDense) {
$this->SetTickDensity(TICKD_NORMAL,$aDense); $this->SetTickDensity(TICKD_NORMAL,$aDense);
} }
   
function SetClockwise($aFlg) { function SetClockwise($aFlg) {
$this->scale->SetClockwise($aFlg); $this->scale->SetClockwise($aFlg);
} }
   
function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) { function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
$adj = ($this->img->height - $this->img->width)/2; $adj = ($this->img->height - $this->img->width)/2;
$this->SetAngle(90); $this->SetAngle(90);
$lm2 = -$adj + ($lm-$rm+$tm+$bm)/2; $lm2 = -$adj + ($lm-$rm+$tm+$bm)/2;
$rm2 = -$adj + (-$lm+$rm+$tm+$bm)/2; $rm2 = -$adj + (-$lm+$rm+$tm+$bm)/2;
$tm2 = $adj + ($tm-$bm+$lm+$rm)/2; $tm2 = $adj + ($tm-$bm+$lm+$rm)/2;
$bm2 = $adj + (-$tm+$bm+$lm+$rm)/2; $bm2 = $adj + (-$tm+$bm+$lm+$rm)/2;
$this->SetMargin($lm2, $rm2, $tm2, $bm2); $this->SetMargin($lm2, $rm2, $tm2, $bm2);
$this->axis->SetLabelAlign('right','center'); $this->axis->SetLabelAlign('right','center');
} }
   
function SetScale($aScale,$rmax=0,$dummy1=1,$dummy2=1,$dummy3=1) { function SetScale($aScale,$rmax=0,$dummy1=1,$dummy2=1,$dummy3=1) {
if( $aScale == 'lin' ) { if( $aScale == 'lin' ) {
$this->scale = new PolarScale($rmax,$this,$this->iClockwise); $this->scale = new PolarScale($rmax,$this,$this->iClockwise);
} }
elseif( $aScale == 'log' ) { elseif( $aScale == 'log' ) {
$this->scale = new PolarLogScale($rmax,$this,$this->iClockwise); $this->scale = new PolarLogScale($rmax,$this,$this->iClockwise);
} }
else { else {
JpGraphError::RaiseL(17004);//('Unknown scale type for polar graph. Must be "lin" or "log"'); JpGraphError::RaiseL(17004);//('Unknown scale type for polar graph. Must be "lin" or "log"');
} }
   
$this->axis = new PolarAxis($this->img,$this->scale); $this->axis = new PolarAxis($this->img,$this->scale);
$this->SetMargin(40,40,50,40); $this->SetMargin(40,40,50,40);
} }
   
function SetType($aType) { function SetType($aType) {
$this->iType = $aType; $this->iType = $aType;
} }
   
function SetPlotSize($w,$h) { function SetPlotSize($w,$h) {
$this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2, $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2,
($this->img->height-$h)/2,($this->img->height-$h)/2); ($this->img->height-$h)/2,($this->img->height-$h)/2);
} }
   
// Private methods // Private methods
function GetPlotsMax() { function GetPlotsMax() {
$n = count($this->plots); $n = count($this->plots);
$m = $this->plots[0]->Max(); $m = $this->plots[0]->Max();
$i=1; $i=1;
while($i < $n) { while($i < $n) {
$m = max($this->plots[$i]->Max(),$m); $m = max($this->plots[$i]->Max(),$m);
++$i; ++$i;
} }
return $m; return $m;
} }
   
function Stroke($aStrokeFileName="") { function Stroke($aStrokeFileName="") {
   
// Start by adjusting the margin so that potential titles will fit. // Start by adjusting the margin so that potential titles will fit.
$this->AdjustMarginsForTitles(); $this->AdjustMarginsForTitles();
   
// If the filename is the predefined value = '_csim_special_' // If the filename is the predefined value = '_csim_special_'
// we assume that the call to stroke only needs to do enough // we assume that the call to stroke only needs to do enough
// to correctly generate the CSIM maps. // to correctly generate the CSIM maps.
// We use this variable to skip things we don't strictly need // We use this variable to skip things we don't strictly need
// to do to generate the image map to improve performance // 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 // a best we can. Therefor you will see a lot of tests !$_csim in the
// code below. // code below.
$_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
   
// We need to know if we have stroked the plot in the // We need to know if we have stroked the plot in the
// GetCSIMareas. Otherwise the CSIM hasn't been generated // GetCSIMareas. Otherwise the CSIM hasn't been generated
// and in the case of GetCSIM called before stroke to generate // and in the case of GetCSIM called before stroke to generate
// CSIM without storing an image to disk GetCSIM must call Stroke. // CSIM without storing an image to disk GetCSIM must call Stroke.
$this->iHasStroked = true; $this->iHasStroked = true;
   
//Check if we should autoscale axis //Check if we should autoscale axis
if( !$this->scale->IsSpecified() && count($this->plots)>0 ) { if( !$this->scale->IsSpecified() && count($this->plots)>0 ) {
$max = $this->GetPlotsMax(); $max = $this->GetPlotsMax();
$t1 = $this->img->plotwidth; $t1 = $this->img->plotwidth;
$this->img->plotwidth /= 2; $this->img->plotwidth /= 2;
$t2 = $this->img->left_margin; $t2 = $this->img->left_margin;
$this->img->left_margin += $this->img->plotwidth+1; $this->img->left_margin += $this->img->plotwidth+1;
$this->scale->AutoScale($this->img,0,$max, $this->scale->AutoScale($this->img,0,$max,
$this->img->plotwidth/$this->xtick_factor/2); $this->img->plotwidth/$this->xtick_factor/2);
$this->img->plotwidth = $t1; $this->img->plotwidth = $t1;
$this->img->left_margin = $t2; $this->img->left_margin = $t2;
} }
else { else {
// The tick calculation will use the user suplied min/max values to determine // 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 // the ticks. If auto_ticks is false the exact user specifed min and max
// values will be used for the scale. // values will be used for the scale.
// If auto_ticks is true then the scale might be slightly adjusted // 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. // so that the min and max values falls on an even major step.
//$min = 0; //$min = 0;
$max = $this->scale->scale[1]; $max = $this->scale->scale[1];
$t1 = $this->img->plotwidth; $t1 = $this->img->plotwidth;
$this->img->plotwidth /= 2; $this->img->plotwidth /= 2;
$t2 = $this->img->left_margin; $t2 = $this->img->left_margin;
$this->img->left_margin += $this->img->plotwidth+1; $this->img->left_margin += $this->img->plotwidth+1;
$this->scale->AutoScale($this->img,0,$max, $this->scale->AutoScale($this->img,0,$max,
$this->img->plotwidth/$this->xtick_factor/2); $this->img->plotwidth/$this->xtick_factor/2);
$this->img->plotwidth = $t1; $this->img->plotwidth = $t1;
$this->img->left_margin = $t2; $this->img->left_margin = $t2;
} }
   
if( $this->iType == POLAR_180 ) { if( $this->iType == POLAR_180 ) {
$pos = $this->img->height - $this->img->bottom_margin; $pos = $this->img->height - $this->img->bottom_margin;
} }
else { else {
$pos = $this->img->plotheight/2 + $this->img->top_margin; $pos = $this->img->plotheight/2 + $this->img->top_margin;
} }
   
if( !$_csim ) { if( !$_csim ) {
$this->StrokePlotArea(); $this->StrokePlotArea();
} }
   
$this->iDoClipping = true; $this->iDoClipping = true;
   
if( $this->iDoClipping ) { if( $this->iDoClipping ) {
$oldimage = $this->img->CloneCanvasH(); $oldimage = $this->img->CloneCanvasH();
} }
   
if( !$_csim ) { if( !$_csim ) {
$this->axis->StrokeGrid($pos); $this->axis->StrokeGrid($pos);
} }
   
// Stroke all plots for Y1 axis // Stroke all plots for Y1 axis
for($i=0; $i < count($this->plots); ++$i) { for($i=0; $i < count($this->plots); ++$i) {
$this->plots[$i]->Stroke($this->img,$this->scale); $this->plots[$i]->Stroke($this->img,$this->scale);
} }
   
   
if( $this->iDoClipping ) { if( $this->iDoClipping ) {
// Clipping only supports graphs at 0 and 90 degrees // Clipping only supports graphs at 0 and 90 degrees
if( $this->img->a == 0 ) { if( $this->img->a == 0 ) {
$this->img->CopyCanvasH($oldimage,$this->img->img, $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->left_margin,$this->img->top_margin, $this->img->left_margin,$this->img->top_margin,
$this->img->plotwidth+1,$this->img->plotheight+1); $this->img->plotwidth+1,$this->img->plotheight+1);
} }
elseif( $this->img->a == 90 ) { elseif( $this->img->a == 90 ) {
$adj1 = round(($this->img->height - $this->img->width)/2); $adj1 = round(($this->img->height - $this->img->width)/2);
$adj2 = round(($this->img->width - $this->img->height)/2); $adj2 = round(($this->img->width - $this->img->height)/2);
$lm = $this->img->left_margin; $lm = $this->img->left_margin;
$rm = $this->img->right_margin; $rm = $this->img->right_margin;
$tm = $this->img->top_margin; $tm = $this->img->top_margin;
$bm = $this->img->bottom_margin; $bm = $this->img->bottom_margin;
$this->img->CopyCanvasH($oldimage,$this->img->img, $this->img->CopyCanvasH($oldimage,$this->img->img,
$adj2 + round(($lm-$rm+$tm+$bm)/2), $adj2 + round(($lm-$rm+$tm+$bm)/2),
$adj1 + round(($tm-$bm+$lm+$rm)/2), $adj1 + round(($tm-$bm+$lm+$rm)/2),
$adj2 + round(($lm-$rm+$tm+$bm)/2), $adj2 + round(($lm-$rm+$tm+$bm)/2),
$adj1 + round(($tm-$bm+$lm+$rm)/2), $adj1 + round(($tm-$bm+$lm+$rm)/2),
$this->img->plotheight+1, $this->img->plotheight+1,
$this->img->plotwidth+1); $this->img->plotwidth+1);
} }
$this->img->Destroy(); $this->img->Destroy();
$this->img->SetCanvasH($oldimage); $this->img->SetCanvasH($oldimage);
} }
   
if( !$_csim ) { if( !$_csim ) {
$this->axis->Stroke($pos); $this->axis->Stroke($pos);
$this->axis->StrokeAngleLabels($pos,$this->iType); $this->axis->StrokeAngleLabels($pos,$this->iType);
} }
   
if( !$_csim ) { if( !$_csim ) {
$this->StrokePlotBox(); $this->StrokePlotBox();
$this->footer->Stroke($this->img); $this->footer->Stroke($this->img);
   
// The titles and legends never gets rotated so make sure // The titles and legends never gets rotated so make sure
// that the angle is 0 before stroking them // that the angle is 0 before stroking them
$aa = $this->img->SetAngle(0); $aa = $this->img->SetAngle(0);
$this->StrokeTitles(); $this->StrokeTitles();
} }
   
for($i=0; $i < count($this->plots) ; ++$i ) { for($i=0; $i < count($this->plots) ; ++$i ) {
$this->plots[$i]->Legend($this); $this->plots[$i]->Legend($this);
} }
   
$this->legend->Stroke($this->img); $this->legend->Stroke($this->img);
   
if( !$_csim ) { if( !$_csim ) {
   
$this->StrokeTexts(); $this->StrokeTexts();
$this->img->SetAngle($aa); $this->img->SetAngle($aa);
   
// Draw an outline around the image map // Draw an outline around the image map
if(_JPG_DEBUG) if(_JPG_DEBUG)
$this->DisplayClientSideaImageMapAreas(); $this->DisplayClientSideaImageMapAreas();
   
// If the filename is given as the special "__handle" // If the filename is given as the special "__handle"
// then the image handler is returned and the image is NOT // then the image handler is returned and the image is NOT
// streamed back // streamed back
if( $aStrokeFileName == _IMG_HANDLER ) { if( $aStrokeFileName == _IMG_HANDLER ) {
return $this->img->img; return $this->img->img;
} }
else { else {
// Finally stream the generated picture // Finally stream the generated picture
$this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
} }
} }
} }
} }
   
   
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_RADAR.PHP // File: JPGRAPH_RADAR.PHP
// Description: Radar plot extension for JpGraph // Description: Radar plot extension for JpGraph
// Created: 2001-02-04 // Created: 2001-02-04
// Ver: $Id: jpgraph_radar.php 1783 2009-08-25 11:41:01Z ljp $ // Ver: $Id: jpgraph_radar.php 1783 2009-08-25 11:41:01Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
require_once('jpgraph_plotmark.inc.php'); require_once('jpgraph_plotmark.inc.php');
   
//=================================================== //===================================================
// CLASS RadarLogTicks // CLASS RadarLogTicks
// Description: Logarithmic ticks // Description: Logarithmic ticks
//=================================================== //===================================================
class RadarLogTicks extends Ticks { class RadarLogTicks extends Ticks {
   
function __construct() { function __construct() {
// Empty // Empty
} }
   
function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) { function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
$start = $aScale->GetMinVal(); $start = $aScale->GetMinVal();
$limit = $aScale->GetMaxVal(); $limit = $aScale->GetMaxVal();
$nextMajor = 10*$start; $nextMajor = 10*$start;
$step = $nextMajor / 10.0; $step = $nextMajor / 10.0;
$count=1; $count=1;
   
$ticklen_maj=5; $ticklen_maj=5;
$dx_maj=round(sin($aAxisAngle)*$ticklen_maj); $dx_maj=round(sin($aAxisAngle)*$ticklen_maj);
$dy_maj=round(cos($aAxisAngle)*$ticklen_maj); $dy_maj=round(cos($aAxisAngle)*$ticklen_maj);
$ticklen_min=3; $ticklen_min=3;
$dx_min=round(sin($aAxisAngle)*$ticklen_min); $dx_min=round(sin($aAxisAngle)*$ticklen_min);
$dy_min=round(cos($aAxisAngle)*$ticklen_min); $dy_min=round(cos($aAxisAngle)*$ticklen_min);
   
$aMajPos=array(); $aMajPos=array();
$aMajLabel=array(); $aMajLabel=array();
   
if( $this->supress_first ) { if( $this->supress_first ) {
$aMajLabel[] = ''; $aMajLabel[] = '';
} }
else { else {
$aMajLabel[]=$start; $aMajLabel[]=$start;
} }
   
$yr=$aScale->RelTranslate($start); $yr=$aScale->RelTranslate($start);
$xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
$yt=$aPos-round($yr*sin($aAxisAngle)); $yt=$aPos-round($yr*sin($aAxisAngle));
$aMajPos[]=$xt+2*$dx_maj; $aMajPos[]=$xt+2*$dx_maj;
$aMajPos[]=$yt-$aImg->GetFontheight()/2; $aMajPos[]=$yt-$aImg->GetFontheight()/2;
$grid[]=$xt; $grid[]=$xt;
$grid[]=$yt; $grid[]=$yt;
   
$aImg->SetLineWeight($this->weight); $aImg->SetLineWeight($this->weight);
   
for($y=$start; $y<=$limit; $y+=$step,++$count ) { for($y=$start; $y<=$limit; $y+=$step,++$count ) {
$yr=$aScale->RelTranslate($y); $yr=$aScale->RelTranslate($y);
$xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
$yt=$aPos-round($yr*sin($aAxisAngle)); $yt=$aPos-round($yr*sin($aAxisAngle));
if( $count % 10 == 0 ) { if( $count % 10 == 0 ) {
$grid[]=$xt; $grid[]=$xt;
$grid[]=$yt; $grid[]=$yt;
$aMajPos[]=$xt+2*$dx_maj; $aMajPos[]=$xt+2*$dx_maj;
$aMajPos[]=$yt-$aImg->GetFontheight()/2; $aMajPos[]=$yt-$aImg->GetFontheight()/2;
if( !$this->supress_tickmarks ) { if( !$this->supress_tickmarks ) {
if( $this->majcolor != '' ) { if( $this->majcolor != '' ) {
$aImg->PushColor($this->majcolor); $aImg->PushColor($this->majcolor);
} }
$aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj); $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj);
if( $this->majcolor != '' ) { if( $this->majcolor != '' ) {
$aImg->PopColor(); $aImg->PopColor();
} }
} }
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f=$this->label_formfunc; $f=$this->label_formfunc;
$l = call_user_func($f,$nextMajor); $l = call_user_func($f,$nextMajor);
} }
else { else {
$l = $nextMajor; $l = $nextMajor;
} }
   
$aMajLabel[]=$l; $aMajLabel[]=$l;
$nextMajor *= 10; $nextMajor *= 10;
$step *= 10; $step *= 10;
$count=1; $count=1;
} }
else { else {
if( !$this->supress_minor_tickmarks ) { if( !$this->supress_minor_tickmarks ) {
if( $this->mincolor != '' ) { if( $this->mincolor != '' ) {
$aImg->PushColor($this->mincolor); $aImg->PushColor($this->mincolor);
} }
$aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min); $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min);
if( $this->mincolor != '' ) { if( $this->mincolor != '' ) {
$aImg->PopColor(); $aImg->PopColor();
} }
} }
} }
} }
} }
} }
   
//=================================================== //===================================================
// CLASS RadarLinear // CLASS RadarLinear
// Description: Linear ticks // Description: Linear ticks
//=================================================== //===================================================
class RadarLinearTicks extends Ticks { class RadarLinearTicks extends Ticks {
   
private $minor_step=1, $major_step=2; private $minor_step=1, $major_step=2;
private $xlabel_offset=0,$xtick_offset=0; private $xlabel_offset=0,$xtick_offset=0;
   
function __construct() { function __construct() {
// Empty // Empty
} }
   
// Return major step size in world coordinates // Return major step size in world coordinates
function GetMajor() { function GetMajor() {
return $this->major_step; return $this->major_step;
} }
   
// Return minor step size in world coordinates // Return minor step size in world coordinates
function GetMinor() { function GetMinor() {
return $this->minor_step; return $this->minor_step;
} }
   
// Set Minor and Major ticks (in world coordinates) // Set Minor and Major ticks (in world coordinates)
function Set($aMajStep,$aMinStep=false) { function Set($aMajStep,$aMinStep=false) {
if( $aMinStep==false ) { if( $aMinStep==false ) {
$aMinStep=$aMajStep; $aMinStep=$aMajStep;
} }
   
if( $aMajStep <= 0 || $aMinStep <= 0 ) { if( $aMajStep <= 0 || $aMinStep <= 0 ) {
JpGraphError::RaiseL(25064); 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."); //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->major_step=$aMajStep;
$this->minor_step=$aMinStep; $this->minor_step=$aMinStep;
$this->is_set = true; $this->is_set = true;
} }
   
function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) { function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
// Prepare to draw linear ticks // Prepare to draw linear ticks
$maj_step_abs = abs($aScale->scale_factor*$this->major_step); $maj_step_abs = abs($aScale->scale_factor*$this->major_step);
$min_step_abs = abs($aScale->scale_factor*$this->minor_step); $min_step_abs = abs($aScale->scale_factor*$this->minor_step);
$nbrmaj = round($aScale->world_abs_size/$maj_step_abs); $nbrmaj = round($aScale->world_abs_size/$maj_step_abs);
$nbrmin = round($aScale->world_abs_size/$min_step_abs); $nbrmin = round($aScale->world_abs_size/$min_step_abs);
$skip = round($nbrmin/$nbrmaj); // Don't draw minor on top of major $skip = round($nbrmin/$nbrmaj); // Don't draw minor on top of major
   
// Draw major ticks // Draw major ticks
$ticklen2=$this->major_abs_size; $ticklen2=$this->major_abs_size;
$dx=round(sin($aAxisAngle)*$ticklen2); $dx=round(sin($aAxisAngle)*$ticklen2);
$dy=round(cos($aAxisAngle)*$ticklen2); $dy=round(cos($aAxisAngle)*$ticklen2);
$label=$aScale->scale[0]+$this->major_step; $label=$aScale->scale[0]+$this->major_step;
   
$aImg->SetLineWeight($this->weight); $aImg->SetLineWeight($this->weight);
   
$aMajPos = array(); $aMajPos = array();
$aMajLabel = array(); $aMajLabel = array();
   
for($i=1; $i<=$nbrmaj; ++$i) { for($i=1; $i<=$nbrmaj; ++$i) {
$xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
$yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle)); $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle));
   
if( $this->label_formfunc != '' ) { if( $this->label_formfunc != '' ) {
$f=$this->label_formfunc; $f=$this->label_formfunc;
$l = call_user_func($f,$label); $l = call_user_func($f,$label);
} }
else { else {
$l = $label; $l = $label;
} }
   
$aMajLabel[]=$l; $aMajLabel[]=$l;
$label += $this->major_step; $label += $this->major_step;
$grid[]=$xt; $grid[]=$xt;
$grid[]=$yt; $grid[]=$yt;
$aMajPos[($i-1)*2]=$xt+2*$dx; $aMajPos[($i-1)*2]=$xt+2*$dx;
$aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2; $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2;
if( !$this->supress_tickmarks ) { if( !$this->supress_tickmarks ) {
if( $this->majcolor != '' ) { if( $this->majcolor != '' ) {
$aImg->PushColor($this->majcolor); $aImg->PushColor($this->majcolor);
} }
$aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
if( $this->majcolor != '' ) { if( $this->majcolor != '' ) {
$aImg->PopColor(); $aImg->PopColor();
} }
} }
} }
   
// Draw minor ticks // Draw minor ticks
$ticklen2=$this->minor_abs_size; $ticklen2=$this->minor_abs_size;
$dx=round(sin($aAxisAngle)*$ticklen2); $dx=round(sin($aAxisAngle)*$ticklen2);
$dy=round(cos($aAxisAngle)*$ticklen2); $dy=round(cos($aAxisAngle)*$ticklen2);
if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
if( $this->mincolor != '' ) { if( $this->mincolor != '' ) {
$aImg->PushColor($this->mincolor); $aImg->PushColor($this->mincolor);
} }
for($i=1; $i<=$nbrmin; ++$i) { for($i=1; $i<=$nbrmin; ++$i) {
if( ($i % $skip) == 0 ) { if( ($i % $skip) == 0 ) {
continue; continue;
} }
$xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
$yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle)); $yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle));
$aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
} }
if( $this->mincolor != '' ) { if( $this->mincolor != '' ) {
$aImg->PopColor(); $aImg->PopColor();
} }
} }
} }
} }
   
   
//=================================================== //===================================================
// CLASS RadarAxis // CLASS RadarAxis
// Description: Implements axis for the radar graph // Description: Implements axis for the radar graph
//=================================================== //===================================================
class RadarAxis extends AxisPrototype { class RadarAxis extends AxisPrototype {
public $title=null; public $title=null;
private $title_color='navy'; private $title_color='navy';
private $len=0; private $len=0;
   
function __construct($img,$aScale,$color=array(0,0,0)) { function __construct($img,$aScale,$color=array(0,0,0)) {
parent::__construct($img,$aScale,$color); parent::__construct($img,$aScale,$color);
$this->len = $img->plotheight; $this->len = $img->plotheight;
$this->title = new Text(); $this->title = new Text();
$this->title->SetFont(FF_FONT1,FS_BOLD); $this->title->SetFont(FF_FONT1,FS_BOLD);
$this->color = array(0,0,0); $this->color = array(0,0,0);
} }
   
// Stroke the axis // Stroke the axis
// $pos = Vertical position of axis // $pos = Vertical position of axis
// $aAxisAngle = Axis angle // $aAxisAngle = Axis angle
// $grid = Returns an array with positions used to draw the grid // $grid = Returns an array with positions used to draw the grid
// $lf = Label flag, TRUE if the axis should have labels // $lf = Label flag, TRUE if the axis should have labels
function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) { function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) {
$this->img->SetColor($this->color); $this->img->SetColor($this->color);
   
// Determine end points for the axis // Determine end points for the axis
$x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]); $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]);
$y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle)); $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle));
   
// Draw axis // Draw axis
$this->img->SetColor($this->color); $this->img->SetColor($this->color);
$this->img->SetLineWeight($this->weight); $this->img->SetLineWeight($this->weight);
if( !$this->hide ) { if( !$this->hide ) {
$this->img->Line($this->scale->scale_abs[0],$pos,$x,$y); $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y);
} }
   
$this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel); $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel);
$ncolor=0; $ncolor=0;
if( isset($this->ticks_label_colors) ) { if( isset($this->ticks_label_colors) ) {
$ncolor=count($this->ticks_label_colors); $ncolor=count($this->ticks_label_colors);
} }
   
// Draw labels // Draw labels
if( $lf && !$this->hide ) { if( $lf && !$this->hide ) {
$this->img->SetFont($this->font_family,$this->font_style,$this->font_size); $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
$this->img->SetTextAlign('left','top'); $this->img->SetTextAlign('left','top');
$this->img->SetColor($this->label_color); $this->img->SetColor($this->label_color);
   
// majpos contains (x,y) coordinates for labels // majpos contains (x,y) coordinates for labels
if( ! $this->hide_labels ) { if( ! $this->hide_labels ) {
$n = floor(count($majpos)/2); $n = floor(count($majpos)/2);
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
// Set specific label color if specified // Set specific label color if specified
if( $ncolor > 0 ) { if( $ncolor > 0 ) {
$this->img->SetColor($this->ticks_label_colors[$i % $ncolor]); $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
} }
   
if( $this->ticks_label != null && isset($this->ticks_label[$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]); $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]);
} }
else { else {
$this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]); $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]);
} }
} }
} }
} }
$this->_StrokeAxisTitle($pos,$aAxisAngle,$title); $this->_StrokeAxisTitle($pos,$aAxisAngle,$title);
} }
   
function _StrokeAxisTitle($pos,$aAxisAngle,$title) { function _StrokeAxisTitle($pos,$aAxisAngle,$title) {
$this->title->Set($title); $this->title->Set($title);
$marg=6+$this->title->margin; $marg=6+$this->title->margin;
$xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]); $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)); $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle));
   
// Position the axis title. // Position the axis title.
// dx, dy is the offset from the top left corner of the bounding box that sorrounds the text // 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 // 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 // bit messy but this is really the only way of having a reasonable position of the
// axis titles. // axis titles.
if( $this->title->iWordwrap > 0 ) { if( $this->title->iWordwrap > 0 ) {
$title = wordwrap($title,$this->title->iWordwrap,"\n"); $title = wordwrap($title,$this->title->iWordwrap,"\n");
} }
   
$h=$this->img->GetTextHeight($title)*1.2; $h=$this->img->GetTextHeight($title)*1.2;
$w=$this->img->GetTextWidth($title)*1.2; $w=$this->img->GetTextWidth($title)*1.2;
   
while( $aAxisAngle > 2*M_PI ) while( $aAxisAngle > 2*M_PI )
$aAxisAngle -= 2*M_PI; $aAxisAngle -= 2*M_PI;
   
// Around 3 a'clock // 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 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 // Around 12 a'clock
if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI; if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI;
   
// Around 9 a'clock // Around 9 a'clock
if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1; if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1;
   
// Around 6 a'clock // 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>=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>=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/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 > M_PI/12) $dy=(1-$aAxisAngle*2/M_PI);
if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1; 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>=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( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0;
   
if( !$this->hide ) { if( !$this->hide ) {
$this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title); $this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title);
} }
} }
   
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS RadarGrid // CLASS RadarGrid
// Description: Draws grid for the radar graph // Description: Draws grid for the radar graph
//=================================================== //===================================================
class RadarGrid { //extends Grid { class RadarGrid { //extends Grid {
private $type='solid'; private $type='solid';
private $grid_color='#DDDDDD'; private $grid_color='#DDDDDD';
private $show=false, $weight=1; private $show=false, $weight=1;
   
function __construct() { function __construct() {
// Empty // Empty
} }
   
function SetColor($aMajColor) { function SetColor($aMajColor) {
$this->grid_color = $aMajColor; $this->grid_color = $aMajColor;
} }
   
function SetWeight($aWeight) { function SetWeight($aWeight) {
$this->weight=$aWeight; $this->weight=$aWeight;
} }
   
// Specify if grid should be dashed, dotted or solid // Specify if grid should be dashed, dotted or solid
function SetLineStyle($aType) { function SetLineStyle($aType) {
$this->type = $aType; $this->type = $aType;
} }
   
// Decide if both major and minor grid should be displayed // Decide if both major and minor grid should be displayed
function Show($aShowMajor=true) { function Show($aShowMajor=true) {
$this->show=$aShowMajor; $this->show=$aShowMajor;
} }
   
function Stroke($img,$grid) { function Stroke($img,$grid) {
if( !$this->show ) { if( !$this->show ) {
return; return;
} }
   
$nbrticks = count($grid[0])/2; $nbrticks = count($grid[0])/2;
$nbrpnts = count($grid); $nbrpnts = count($grid);
$img->SetColor($this->grid_color); $img->SetColor($this->grid_color);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
   
for($i=0; $i<$nbrticks; ++$i) { for($i=0; $i<$nbrticks; ++$i) {
for($j=0; $j<$nbrpnts; ++$j) { for($j=0; $j<$nbrpnts; ++$j) {
$pnts[$j*2]=$grid[$j][$i*2]; $pnts[$j*2]=$grid[$j][$i*2];
$pnts[$j*2+1]=$grid[$j][$i*2+1]; $pnts[$j*2+1]=$grid[$j][$i*2+1];
} }
for($k=0; $k<$nbrpnts; ++$k ){ for($k=0; $k<$nbrpnts; ++$k ){
$l=($k+1)%$nbrpnts; $l=($k+1)%$nbrpnts;
if( $this->type == 'solid' ) if( $this->type == 'solid' )
$img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]); $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]);
elseif( $this->type == 'dotted' ) elseif( $this->type == 'dotted' )
$img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6); $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6);
elseif( $this->type == 'dashed' ) elseif( $this->type == 'dashed' )
$img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4); $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4);
elseif( $this->type == 'longdashed' ) elseif( $this->type == 'longdashed' )
$img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6); $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6);
} }
$pnts=array(); $pnts=array();
} }
} }
} // Class } // Class
   
   
//=================================================== //===================================================
// CLASS RadarPlot // CLASS RadarPlot
// Description: Plot a radarplot // Description: Plot a radarplot
//=================================================== //===================================================
class RadarPlot { class RadarPlot {
public $mark=null; public $mark=null;
public $legend=''; public $legend='';
public $legendcsimtarget=''; public $legendcsimtarget='';
public $legendcsimalt=''; public $legendcsimalt='';
public $csimtargets=array(); // Array of targets for CSIM public $csimtargets=array(); // Array of targets for CSIM
public $csimareas=""; // Resultant CSIM area tags public $csimareas=""; // Resultant CSIM area tags
public $csimalts=null; // ALT:s for corresponding target public $csimalts=null; // ALT:s for corresponding target
private $data=array(); private $data=array();
private $fill=false, $fill_color=array(200,170,180); private $fill=false, $fill_color=array(200,170,180);
private $color=array(0,0,0); private $color=array(0,0,0);
private $weight=1; private $weight=1;
private $linestyle='solid'; private $linestyle='solid';
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($data) { function __construct($data) {
$this->data = $data; $this->data = $data;
$this->mark = new PlotMark(); $this->mark = new PlotMark();
} }
   
function Min() { function Min() {
return Min($this->data); return Min($this->data);
} }
   
function Max() { function Max() {
return Max($this->data); return Max($this->data);
} }
   
function SetLegend($legend) { function SetLegend($legend) {
$this->legend=$legend; $this->legend=$legend;
} }
   
function SetLineStyle($aStyle) { function SetLineStyle($aStyle) {
$this->linestyle=$aStyle; $this->linestyle=$aStyle;
} }
   
function SetLineWeight($w) { function SetLineWeight($w) {
$this->weight=$w; $this->weight=$w;
} }
   
function SetFillColor($aColor) { function SetFillColor($aColor) {
$this->fill_color = $aColor; $this->fill_color = $aColor;
$this->fill = true; $this->fill = true;
} }
   
function SetFill($f=true) { function SetFill($f=true) {
$this->fill = $f; $this->fill = $f;
} }
   
function SetColor($aColor,$aFillColor=false) { function SetColor($aColor,$aFillColor=false) {
$this->color = $aColor; $this->color = $aColor;
if( $aFillColor ) { if( $aFillColor ) {
$this->SetFillColor($aFillColor); $this->SetFillColor($aFillColor);
$this->fill = true; $this->fill = true;
} }
} }
   
// Set href targets for CSIM // Set href targets for CSIM
function SetCSIMTargets($aTargets,$aAlts=null) { function SetCSIMTargets($aTargets,$aAlts=null) {
$this->csimtargets=$aTargets; $this->csimtargets=$aTargets;
$this->csimalts=$aAlts; $this->csimalts=$aAlts;
} }
   
// Get all created areas // Get all created areas
function GetCSIMareas() { function GetCSIMareas() {
return $this->csimareas; return $this->csimareas;
} }
   
function Stroke($img, $pos, $scale, $startangle) { function Stroke($img, $pos, $scale, $startangle) {
$nbrpnts = count($this->data); $nbrpnts = count($this->data);
$astep=2*M_PI/$nbrpnts; $astep=2*M_PI/$nbrpnts;
$a=$startangle; $a=$startangle;
   
for($i=0; $i<$nbrpnts; ++$i) { for($i=0; $i<$nbrpnts; ++$i) {
   
// Rotate each non null point to the correct axis-angle // Rotate each non null point to the correct axis-angle
$cs=$scale->RelTranslate($this->data[$i]); $cs=$scale->RelTranslate($this->data[$i]);
$x=round($cs*cos($a)+$scale->scale_abs[0]); $x=round($cs*cos($a)+$scale->scale_abs[0]);
$y=round($pos-$cs*sin($a)); $y=round($pos-$cs*sin($a));
   
$pnts[$i*2]=$x; $pnts[$i*2]=$x;
$pnts[$i*2+1]=$y; $pnts[$i*2+1]=$y;
   
// If the next point is null then we draw this polygon segment // If the next point is null then we draw this polygon segment
// to the center, skip the next and draw the next segment from // 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 // 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 // value and continues from that point. Some additoinal logic is necessary
// to handle the boundary conditions // to handle the boundary conditions
if( $i < $nbrpnts-1 ) { if( $i < $nbrpnts-1 ) {
if( is_null($this->data[$i+1]) ) { if( is_null($this->data[$i+1]) ) {
$cs = 0; $cs = 0;
$x=round($cs*cos($a)+$scale->scale_abs[0]); $x=round($cs*cos($a)+$scale->scale_abs[0]);
$y=round($pos-$cs*sin($a)); $y=round($pos-$cs*sin($a));
$pnts[$i*2]=$x; $pnts[$i*2]=$x;
$pnts[$i*2+1]=$y; $pnts[$i*2+1]=$y;
$a += $astep; $a += $astep;
} }
} }
   
$a += $astep; $a += $astep;
} }
   
if( $this->fill ) { if( $this->fill ) {
$img->SetColor($this->fill_color); $img->SetColor($this->fill_color);
$img->FilledPolygon($pnts); $img->FilledPolygon($pnts);
} }
   
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$img->SetColor($this->color); $img->SetColor($this->color);
$img->SetLineStyle($this->linestyle); $img->SetLineStyle($this->linestyle);
$pnts[] = $pnts[0]; $pnts[] = $pnts[0];
$pnts[] = $pnts[1]; $pnts[] = $pnts[1];
$img->Polygon($pnts); $img->Polygon($pnts);
$img->SetLineStyle('solid'); // Reset line style to default $img->SetLineStyle('solid'); // Reset line style to default
   
// Add plotmarks on top // Add plotmarks on top
if( $this->mark->show ) { if( $this->mark->show ) {
for($i=0; $i < $nbrpnts; ++$i) { for($i=0; $i < $nbrpnts; ++$i) {
if( isset($this->csimtargets[$i]) ) { if( isset($this->csimtargets[$i]) ) {
$this->mark->SetCSIMTarget($this->csimtargets[$i]); $this->mark->SetCSIMTarget($this->csimtargets[$i]);
$this->mark->SetCSIMAlt($this->csimalts[$i]); $this->mark->SetCSIMAlt($this->csimalts[$i]);
$this->mark->SetCSIMAltVal($pnts[$i*2], $pnts[$i*2+1]); $this->mark->SetCSIMAltVal($pnts[$i*2], $pnts[$i*2+1]);
$this->mark->Stroke($img, $pnts[$i*2], $pnts[$i*2+1]); $this->mark->Stroke($img, $pnts[$i*2], $pnts[$i*2+1]);
$this->csimareas .= $this->mark->GetCSIMAreas(); $this->csimareas .= $this->mark->GetCSIMAreas();
} }
else { else {
$this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]); $this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]);
} }
} }
} }
   
} }
   
function GetCount() { function GetCount() {
return count($this->data); return count($this->data);
} }
   
function Legend($graph) { function Legend($graph) {
if( $this->legend == '' ) { if( $this->legend == '' ) {
return; return;
} }
if( $this->fill ) { if( $this->fill ) {
$graph->legend->Add($this->legend,$this->fill_color,$this->mark); $graph->legend->Add($this->legend,$this->fill_color,$this->mark);
} else { } else {
$graph->legend->Add($this->legend,$this->color,$this->mark); $graph->legend->Add($this->legend,$this->color,$this->mark);
} }
} }
   
} // Class } // Class
   
//=================================================== //===================================================
// CLASS RadarGraph // CLASS RadarGraph
// Description: Main container for a radar graph // Description: Main container for a radar graph
//=================================================== //===================================================
class RadarGraph extends Graph { class RadarGraph extends Graph {
public $grid,$axis=null; public $grid,$axis=null;
private $posx,$posy; private $posx,$posy;
private $len; private $len;
private $axis_title=null; private $axis_title=null;
   
function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
parent::__construct($width,$height,$cachedName,$timeout,$inline); parent::__construct($width,$height,$cachedName,$timeout,$inline);
$this->posx = $width/2; $this->posx = $width/2;
$this->posy = $height/2; $this->posy = $height/2;
$this->len = min($width,$height)*0.35; $this->len = min($width,$height)*0.35;
$this->SetColor(array(255,255,255)); $this->SetColor(array(255,255,255));
$this->SetTickDensity(TICKD_NORMAL); $this->SetTickDensity(TICKD_NORMAL);
$this->SetScale('lin'); $this->SetScale('lin');
$this->SetGridDepth(DEPTH_FRONT); $this->SetGridDepth(DEPTH_FRONT);
} }
   
function HideTickMarks($aFlag=true) { function HideTickMarks($aFlag=true) {
$this->axis->scale->ticks->SupressTickMarks($aFlag); $this->axis->scale->ticks->SupressTickMarks($aFlag);
} }
   
function ShowMinorTickmarks($aFlag=true) { function ShowMinorTickmarks($aFlag=true) {
$this->yscale->ticks->SupressMinorTickMarks(!$aFlag); $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
} }
   
function SetScale($axtype,$ymin=1,$ymax=1,$dummy1=null,$dumy2=null) { function SetScale($axtype,$ymin=1,$ymax=1,$dummy1=null,$dumy2=null) {
if( $axtype != 'lin' && $axtype != 'log' ) { if( $axtype != 'lin' && $axtype != 'log' ) {
JpGraphError::RaiseL(18003,$axtype); JpGraphError::RaiseL(18003,$axtype);
//("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\""); //("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\"");
} }
if( $axtype == 'lin' ) { if( $axtype == 'lin' ) {
$this->yscale = new LinearScale($ymin,$ymax); $this->yscale = new LinearScale($ymin,$ymax);
$this->yscale->ticks = new RadarLinearTicks(); $this->yscale->ticks = new RadarLinearTicks();
$this->yscale->ticks->SupressMinorTickMarks(); $this->yscale->ticks->SupressMinorTickMarks();
} }
elseif( $axtype == 'log' ) { elseif( $axtype == 'log' ) {
$this->yscale = new LogScale($ymin,$ymax); $this->yscale = new LogScale($ymin,$ymax);
$this->yscale->ticks = new RadarLogTicks(); $this->yscale->ticks = new RadarLogTicks();
} }
   
$this->axis = new RadarAxis($this->img,$this->yscale); $this->axis = new RadarAxis($this->img,$this->yscale);
$this->grid = new RadarGrid(); $this->grid = new RadarGrid();
} }
   
function SetSize($aSize) { function SetSize($aSize) {
if( $aSize < 0.1 || $aSize>1 ) { if( $aSize < 0.1 || $aSize>1 ) {
JpGraphError::RaiseL(18004,$aSize); JpGraphError::RaiseL(18004,$aSize);
//("Radar Plot size must be between 0.1 and 1. (Your value=$s)"); //("Radar Plot size must be between 0.1 and 1. (Your value=$s)");
} }
$this->len=min($this->img->width,$this->img->height)*$aSize/2; $this->len=min($this->img->width,$this->img->height)*$aSize/2;
} }
   
function SetPlotSize($aSize) { function SetPlotSize($aSize) {
$this->SetSize($aSize); $this->SetSize($aSize);
} }
   
function SetTickDensity($densy=TICKD_NORMAL,$dummy1=null) { function SetTickDensity($densy=TICKD_NORMAL,$dummy1=null) {
$this->ytick_factor=25; $this->ytick_factor=25;
switch( $densy ) { switch( $densy ) {
case TICKD_DENSE: case TICKD_DENSE:
$this->ytick_factor=12; $this->ytick_factor=12;
break; break;
case TICKD_NORMAL: case TICKD_NORMAL:
$this->ytick_factor=25; $this->ytick_factor=25;
break; break;
case TICKD_SPARSE: case TICKD_SPARSE:
$this->ytick_factor=40; $this->ytick_factor=40;
break; break;
case TICKD_VERYSPARSE: case TICKD_VERYSPARSE:
$this->ytick_factor=70; $this->ytick_factor=70;
break; break;
default: default:
JpGraphError::RaiseL(18005,$densy); JpGraphError::RaiseL(18005,$densy);
//("RadarPlot Unsupported Tick density: $densy"); //("RadarPlot Unsupported Tick density: $densy");
} }
} }
   
function SetPos($px,$py=0.5) { function SetPos($px,$py=0.5) {
$this->SetCenter($px,$py); $this->SetCenter($px,$py);
} }
   
function SetCenter($px,$py=0.5) { function SetCenter($px,$py=0.5) {
if( $px >= 0 && $px <= 1 ) { if( $px >= 0 && $px <= 1 ) {
$this->posx = $this->img->width*$px; $this->posx = $this->img->width*$px;
} }
else { else {
$this->posx = $px; $this->posx = $px;
} }
if( $py >= 0 && $py <= 1 ) { if( $py >= 0 && $py <= 1 ) {
$this->posy = $this->img->height*$py; $this->posy = $this->img->height*$py;
} }
else { else {
$this->posy = $py; $this->posy = $py;
} }
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->SetMarginColor($aColor); $this->SetMarginColor($aColor);
} }
   
function SetTitles($aTitleArray) { function SetTitles($aTitleArray) {
$this->axis_title = $aTitleArray; $this->axis_title = $aTitleArray;
} }
   
function Add($aPlot) { function Add($aPlot) {
if( $aPlot == null ) { if( $aPlot == null ) {
JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph."); JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
} }
if( is_array($aPlot) && count($aPlot) > 0 ) { if( is_array($aPlot) && count($aPlot) > 0 ) {
$cl = $aPlot[0]; $cl = $aPlot[0];
} }
else { else {
$cl = $aPlot; $cl = $aPlot;
} }
   
if( $cl instanceof Text ) $this->AddText($aPlot); if( $cl instanceof Text ) $this->AddText($aPlot);
elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot); elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
else { else {
$this->plots[] = $aPlot; $this->plots[] = $aPlot;
} }
} }
   
function GetPlotsYMinMax($aPlots) { function GetPlotsYMinMax($aPlots) {
$min=$aPlots[0]->Min(); $min=$aPlots[0]->Min();
$max=$aPlots[0]->Max(); $max=$aPlots[0]->Max();
foreach( $this->plots as $p ) { foreach( $this->plots as $p ) {
$max=max($max,$p->Max()); $max=max($max,$p->Max());
$min=min($min,$p->Min()); $min=min($min,$p->Min());
} }
if( $min < 0 ) { if( $min < 0 ) {
JpGraphError::RaiseL(18006,$min); JpGraphError::RaiseL(18006,$min);
//("Minimum data $min (Radar plots should only be used when all data points > 0)"); //("Minimum data $min (Radar plots should only be used when all data points > 0)");
} }
return array($min,$max); return array($min,$max);
} }
   
function StrokeIcons() { function StrokeIcons() {
if( $this->iIcons != null ) { if( $this->iIcons != null ) {
$n = count($this->iIcons); $n = count($this->iIcons);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->iIcons[$i]->Stroke($this->img); $this->iIcons[$i]->Stroke($this->img);
} }
} }
} }
   
function StrokeTexts() { function StrokeTexts() {
if( $this->texts != null ) { if( $this->texts != null ) {
$n = count($this->texts); $n = count($this->texts);
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$this->texts[$i]->Stroke($this->img); $this->texts[$i]->Stroke($this->img);
} }
} }
} }
   
// Stroke the Radar graph // Stroke the Radar graph
function Stroke($aStrokeFileName='') { function Stroke($aStrokeFileName='') {
   
// If the filename is the predefined value = '_csim_special_' // If the filename is the predefined value = '_csim_special_'
// we assume that the call to stroke only needs to do enough // we assume that the call to stroke only needs to do enough
// to correctly generate the CSIM maps. // to correctly generate the CSIM maps.
// We use this variable to skip things we don't strictly need // We use this variable to skip things we don't strictly need
// to do to generate the image map to improve performance // 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 // a best we can. Therefor you will see a lot of tests !$_csim in the
// code below. // code below.
$_csim = ( $aStrokeFileName === _CSIM_SPECIALFILE ); $_csim = ( $aStrokeFileName === _CSIM_SPECIALFILE );
   
// We need to know if we have stroked the plot in the // We need to know if we have stroked the plot in the
// GetCSIMareas. Otherwise the CSIM hasn't been generated // GetCSIMareas. Otherwise the CSIM hasn't been generated
// and in the case of GetCSIM called before stroke to generate // and in the case of GetCSIM called before stroke to generate
// CSIM without storing an image to disk GetCSIM must call Stroke. // CSIM without storing an image to disk GetCSIM must call Stroke.
$this->iHasStroked = true; $this->iHasStroked = true;
   
$n = count($this->plots); $n = count($this->plots);
// Set Y-scale // Set Y-scale
   
if( !$this->yscale->IsSpecified() && count($this->plots) > 0 ) { if( !$this->yscale->IsSpecified() && count($this->plots) > 0 ) {
list($min,$max) = $this->GetPlotsYMinMax($this->plots); list($min,$max) = $this->GetPlotsYMinMax($this->plots);
$this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor); $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor);
} }
elseif( $this->yscale->IsSpecified() && elseif( $this->yscale->IsSpecified() &&
( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) { ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) {
   
// The tick calculation will use the user suplied min/max values to determine // 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 // the ticks. If auto_ticks is false the exact user specifed min and max
// values will be used for the scale. // values will be used for the scale.
// If auto_ticks is true then the scale might be slightly adjusted // 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. // so that the min and max values falls on an even major step.
$min = $this->yscale->scale[0]; $min = $this->yscale->scale[0];
$max = $this->yscale->scale[1]; $max = $this->yscale->scale[1];
$this->yscale->AutoScale($this->img,$min,$max, $this->yscale->AutoScale($this->img,$min,$max,
$this->len/$this->ytick_factor, $this->len/$this->ytick_factor,
$this->yscale->auto_ticks); $this->yscale->auto_ticks);
} }
   
// Set start position end length of scale (in absolute pixels) // Set start position end length of scale (in absolute pixels)
$this->yscale->SetConstants($this->posx,$this->len); $this->yscale->SetConstants($this->posx,$this->len);
   
// We need as many axis as there are data points // We need as many axis as there are data points
$nbrpnts=$this->plots[0]->GetCount(); $nbrpnts=$this->plots[0]->GetCount();
   
// If we have no titles just number the axis 1,2,3,... // If we have no titles just number the axis 1,2,3,...
if( $this->axis_title==null ) { if( $this->axis_title==null ) {
for($i=0; $i < $nbrpnts; ++$i ) { for($i=0; $i < $nbrpnts; ++$i ) {
$this->axis_title[$i] = $i+1; $this->axis_title[$i] = $i+1;
} }
} }
elseif( count($this->axis_title) < $nbrpnts) { elseif( count($this->axis_title) < $nbrpnts) {
JpGraphError::RaiseL(18007); JpGraphError::RaiseL(18007);
// ("Number of titles does not match number of points in plot."); // ("Number of titles does not match number of points in plot.");
} }
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
if( $nbrpnts != $this->plots[$i]->GetCount() ) { if( $nbrpnts != $this->plots[$i]->GetCount() ) {
JpGraphError::RaiseL(18008); JpGraphError::RaiseL(18008);
//("Each radar plot must have the same number of data points."); //("Each radar plot must have the same number of data points.");
} }
} }
   
if( !$_csim ) { if( !$_csim ) {
if( $this->background_image != '' ) { if( $this->background_image != '' ) {
$this->StrokeFrameBackground(); $this->StrokeFrameBackground();
} }
else { else {
$this->StrokeFrame(); $this->StrokeFrame();
$this->StrokeBackgroundGrad(); $this->StrokeBackgroundGrad();
} }
} }
$astep=2*M_PI/$nbrpnts; $astep=2*M_PI/$nbrpnts;
   
if( !$_csim ) { if( !$_csim ) {
if( $this->iIconDepth == DEPTH_BACK ) { if( $this->iIconDepth == DEPTH_BACK ) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
   
   
// Prepare legends // Prepare legends
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
$this->plots[$i]->Legend($this); $this->plots[$i]->Legend($this);
} }
$this->legend->Stroke($this->img); $this->legend->Stroke($this->img);
$this->footer->Stroke($this->img); $this->footer->Stroke($this->img);
} }
   
if( !$_csim ) { if( !$_csim ) {
if( $this->grid_depth == DEPTH_BACK ) { if( $this->grid_depth == DEPTH_BACK ) {
// Draw axis and grid // Draw axis and grid
for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) { 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->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
} }
$this->grid->Stroke($this->img,$grid); $this->grid->Stroke($this->img,$grid);
} }
if( $this->iIconDepth == DEPTH_BACK ) { if( $this->iIconDepth == DEPTH_BACK ) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
   
} }
   
// Plot points // Plot points
$a=M_PI/2; $a=M_PI/2;
for($i=0; $i < $n; ++$i ) { for($i=0; $i < $n; ++$i ) {
$this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a); $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a);
} }
   
if( !$_csim ) { if( !$_csim ) {
if( $this->grid_depth != DEPTH_BACK ) { if( $this->grid_depth != DEPTH_BACK ) {
// Draw axis and grid // Draw axis and grid
for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) { 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->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
} }
$this->grid->Stroke($this->img,$grid); $this->grid->Stroke($this->img,$grid);
} }
   
$this->StrokeTitles(); $this->StrokeTitles();
$this->StrokeTexts(); $this->StrokeTexts();
if( $this->iIconDepth == DEPTH_FRONT ) { if( $this->iIconDepth == DEPTH_FRONT ) {
$this->StrokeIcons(); $this->StrokeIcons();
} }
} }
   
// Should we do any final image transformation // Should we do any final image transformation
if( $this->iImgTrans && !$_csim ) { if( $this->iImgTrans && !$_csim ) {
if( !class_exists('ImgTrans',false) ) { if( !class_exists('ImgTrans',false) ) {
require_once('jpgraph_imgtrans.php'); require_once('jpgraph_imgtrans.php');
} }
   
$tform = new ImgTrans($this->img->img); $tform = new ImgTrans($this->img->img);
$this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
$this->iImgTransDirection,$this->iImgTransHighQ, $this->iImgTransDirection,$this->iImgTransHighQ,
$this->iImgTransMinSize,$this->iImgTransFillColor, $this->iImgTransMinSize,$this->iImgTransFillColor,
$this->iImgTransBorder); $this->iImgTransBorder);
} }
   
if( !$_csim ) { if( !$_csim ) {
// If the filename is given as the special "__handle" // If the filename is given as the special "__handle"
// then the image handler is returned and the image is NOT // then the image handler is returned and the image is NOT
// streamed back // streamed back
if( $aStrokeFileName == _IMG_HANDLER ) { if( $aStrokeFileName == _IMG_HANDLER ) {
return $this->img->img; return $this->img->img;
} }
else { else {
// Finally stream the generated picture // Finally stream the generated picture
$this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
} }
} }
} }
} // Class } // Class
   
/* EOF */ /* EOF */
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_REGSTAT.PHP // File: JPGRAPH_REGSTAT.PHP
// Description: Regression and statistical analysis helper classes // Description: Regression and statistical analysis helper classes
// Created: 2002-12-01 // Created: 2002-12-01
// Ver: $Id: jpgraph_regstat.php 1131 2009-03-11 20:08:24Z ljp $ // Ver: $Id: jpgraph_regstat.php 1131 2009-03-11 20:08:24Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// CLASS Spline // CLASS Spline
// Create a new data array from an existing data array but with more points. // Create a new data array from an existing data array but with more points.
// The new points are interpolated using a cubic spline algorithm // The new points are interpolated using a cubic spline algorithm
//------------------------------------------------------------------------ //------------------------------------------------------------------------
class Spline { class Spline {
// 3:rd degree polynom approximation // 3:rd degree polynom approximation
   
private $xdata,$ydata; // Data vectors private $xdata,$ydata; // Data vectors
private $y2; // 2:nd derivate of ydata private $y2; // 2:nd derivate of ydata
private $n=0; private $n=0;
   
function __construct($xdata,$ydata) { function __construct($xdata,$ydata) {
$this->y2 = array(); $this->y2 = array();
$this->xdata = $xdata; $this->xdata = $xdata;
$this->ydata = $ydata; $this->ydata = $ydata;
   
$n = count($ydata); $n = count($ydata);
$this->n = $n; $this->n = $n;
if( $this->n !== count($xdata) ) { if( $this->n !== count($xdata) ) {
JpGraphError::RaiseL(19001); JpGraphError::RaiseL(19001);
//('Spline: Number of X and Y coordinates must be the same'); //('Spline: Number of X and Y coordinates must be the same');
} }
   
// Natural spline 2:derivate == 0 at endpoints // Natural spline 2:derivate == 0 at endpoints
$this->y2[0] = 0.0; $this->y2[0] = 0.0;
$this->y2[$n-1] = 0.0; $this->y2[$n-1] = 0.0;
$delta[0] = 0.0; $delta[0] = 0.0;
   
// Calculate 2:nd derivate // Calculate 2:nd derivate
for($i=1; $i < $n-1; ++$i) { for($i=1; $i < $n-1; ++$i) {
$d = ($xdata[$i+1]-$xdata[$i-1]); $d = ($xdata[$i+1]-$xdata[$i-1]);
if( $d == 0 ) { if( $d == 0 ) {
JpGraphError::RaiseL(19002); 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.'); //('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; $s = ($xdata[$i]-$xdata[$i-1])/$d;
$p = $s*$this->y2[$i-1]+2.0; $p = $s*$this->y2[$i-1]+2.0;
$this->y2[$i] = ($s-1.0)/$p; $this->y2[$i] = ($s-1.0)/$p;
$delta[$i] = ($ydata[$i+1]-$ydata[$i])/($xdata[$i+1]-$xdata[$i]) - $delta[$i] = ($ydata[$i+1]-$ydata[$i])/($xdata[$i+1]-$xdata[$i]) -
($ydata[$i]-$ydata[$i-1])/($xdata[$i]-$xdata[$i-1]); ($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; $delta[$i] = (6.0*$delta[$i]/($xdata[$i+1]-$xdata[$i-1])-$s*$delta[$i-1])/$p;
} }
   
// Backward substitution // Backward substitution
for( $j=$n-2; $j >= 0; --$j ) { for( $j=$n-2; $j >= 0; --$j ) {
$this->y2[$j] = $this->y2[$j]*$this->y2[$j+1] + $delta[$j]; $this->y2[$j] = $this->y2[$j]*$this->y2[$j+1] + $delta[$j];
} }
} }
   
// Return the two new data vectors // Return the two new data vectors
function Get($num=50) { function Get($num=50) {
$n = $this->n ; $n = $this->n ;
$step = ($this->xdata[$n-1]-$this->xdata[0]) / ($num-1); $step = ($this->xdata[$n-1]-$this->xdata[0]) / ($num-1);
$xnew=array(); $xnew=array();
$ynew=array(); $ynew=array();
$xnew[0] = $this->xdata[0]; $xnew[0] = $this->xdata[0];
$ynew[0] = $this->ydata[0]; $ynew[0] = $this->ydata[0];
for( $j=1; $j < $num; ++$j ) { for( $j=1; $j < $num; ++$j ) {
$xnew[$j] = $xnew[0]+$j*$step; $xnew[$j] = $xnew[0]+$j*$step;
$ynew[$j] = $this->Interpolate($xnew[$j]); $ynew[$j] = $this->Interpolate($xnew[$j]);
} }
return array($xnew,$ynew); return array($xnew,$ynew);
} }
   
// Return a single interpolated Y-value from an x value // Return a single interpolated Y-value from an x value
function Interpolate($xpoint) { function Interpolate($xpoint) {
   
$max = $this->n-1; $max = $this->n-1;
$min = 0; $min = 0;
   
// Binary search to find interval // Binary search to find interval
while( $max-$min > 1 ) { while( $max-$min > 1 ) {
$k = ($max+$min) / 2; $k = ($max+$min) / 2;
if( $this->xdata[$k] > $xpoint ) if( $this->xdata[$k] > $xpoint )
$max=$k; $max=$k;
else else
$min=$k; $min=$k;
} }
   
// Each interval is interpolated by a 3:degree polynom function // Each interval is interpolated by a 3:degree polynom function
$h = $this->xdata[$max]-$this->xdata[$min]; $h = $this->xdata[$max]-$this->xdata[$min];
   
if( $h == 0 ) { if( $h == 0 ) {
JpGraphError::RaiseL(19002); 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.'); //('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; $a = ($this->xdata[$max]-$xpoint)/$h;
$b = ($xpoint-$this->xdata[$min])/$h; $b = ($xpoint-$this->xdata[$min])/$h;
return $a*$this->ydata[$min]+$b*$this->ydata[$max]+ 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; (($a*$a*$a-$a)*$this->y2[$min]+($b*$b*$b-$b)*$this->y2[$max])*($h*$h)/6.0;
} }
} }
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// CLASS Bezier // CLASS Bezier
// Create a new data array from a number of control points // Create a new data array from a number of control points
//------------------------------------------------------------------------ //------------------------------------------------------------------------
class Bezier { class Bezier {
/** /**
* @author Thomas Despoix, openXtrem company * @author Thomas Despoix, openXtrem company
* @license released under QPL * @license released under QPL
* @abstract Bezier interoplated point generation, * @abstract Bezier interoplated point generation,
* computed from control points data sets, based on Paul Bourke algorithm : * computed from control points data sets, based on Paul Bourke algorithm :
* http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html * http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html
*/ */
private $datax = array(); private $datax = array();
private $datay = array(); private $datay = array();
private $n=0; private $n=0;
   
function __construct($datax, $datay, $attraction_factor = 1) { function __construct($datax, $datay, $attraction_factor = 1) {
// Adding control point multiple time will raise their attraction power over the curve // Adding control point multiple time will raise their attraction power over the curve
$this->n = count($datax); $this->n = count($datax);
if( $this->n !== count($datay) ) { if( $this->n !== count($datay) ) {
JpGraphError::RaiseL(19003); JpGraphError::RaiseL(19003);
//('Bezier: Number of X and Y coordinates must be the same'); //('Bezier: Number of X and Y coordinates must be the same');
} }
$idx=0; $idx=0;
foreach($datax as $datumx) { foreach($datax as $datumx) {
for ($i = 0; $i < $attraction_factor; $i++) { for ($i = 0; $i < $attraction_factor; $i++) {
$this->datax[$idx++] = $datumx; $this->datax[$idx++] = $datumx;
} }
} }
$idx=0; $idx=0;
foreach($datay as $datumy) { foreach($datay as $datumy) {
for ($i = 0; $i < $attraction_factor; $i++) { for ($i = 0; $i < $attraction_factor; $i++) {
$this->datay[$idx++] = $datumy; $this->datay[$idx++] = $datumy;
} }
} }
$this->n *= $attraction_factor; $this->n *= $attraction_factor;
} }
   
/** /**
* Return a set of data points that specifies the bezier curve with $steps points * Return a set of data points that specifies the bezier curve with $steps points
* @param $steps Number of new points to return * @param $steps Number of new points to return
* @return array($datax, $datay) * @return array($datax, $datay)
*/ */
function Get($steps) { function Get($steps) {
$datax = array(); $datax = array();
$datay = array(); $datay = array();
for ($i = 0; $i < $steps; $i++) { for ($i = 0; $i < $steps; $i++) {
list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps); list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps);
$datax[$i] = $datumx; $datax[$i] = $datumx;
$datay[$i] = $datumy; $datay[$i] = $datumy;
} }
$datax[] = end($this->datax); $datax[] = end($this->datax);
$datay[] = end($this->datay); $datay[] = end($this->datay);
return array($datax, $datay); return array($datax, $datay);
} }
   
/** /**
* Return one point on the bezier curve. $mu is the position on the curve where $mu is in the * 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 * 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 * point depends on all the existing points
* *
* @param $mu Position on the bezier curve * @param $mu Position on the bezier curve
* @return array($x, $y) * @return array($x, $y)
*/ */
function GetPoint($mu) { function GetPoint($mu) {
$n = $this->n - 1; $n = $this->n - 1;
$k = 0; $k = 0;
$kn = 0; $kn = 0;
$nn = 0; $nn = 0;
$nkn = 0; $nkn = 0;
$blend = 0.0; $blend = 0.0;
$newx = 0.0; $newx = 0.0;
$newy = 0.0; $newy = 0.0;
   
$muk = 1.0; $muk = 1.0;
$munk = (double) pow(1-$mu,(double) $n); $munk = (double) pow(1-$mu,(double) $n);
   
for ($k = 0; $k <= $n; $k++) { for ($k = 0; $k <= $n; $k++) {
$nn = $n; $nn = $n;
$kn = $k; $kn = $k;
$nkn = $n - $k; $nkn = $n - $k;
$blend = $muk * $munk; $blend = $muk * $munk;
$muk *= $mu; $muk *= $mu;
$munk /= (1-$mu); $munk /= (1-$mu);
while ($nn >= 1) { while ($nn >= 1) {
$blend *= $nn; $blend *= $nn;
$nn--; $nn--;
if ($kn > 1) { if ($kn > 1) {
$blend /= (double) $kn; $blend /= (double) $kn;
$kn--; $kn--;
} }
if ($nkn > 1) { if ($nkn > 1) {
$blend /= (double) $nkn; $blend /= (double) $nkn;
$nkn--; $nkn--;
} }
} }
$newx += $this->datax[$k] * $blend; $newx += $this->datax[$k] * $blend;
$newy += $this->datay[$k] * $blend; $newy += $this->datay[$k] * $blend;
} }
   
return array($newx, $newy); return array($newx, $newy);
} }
} }
   
// EOF // EOF
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_RGB.INC.PHP // File: JPGRAPH_RGB.INC.PHP
// Description: Class to handle RGb color space specification and // Description: Class to handle RGb color space specification and
// named colors // named colors
// Created: 2001-01-08 (Refactored to separate file 2008-08-01) // Created: 2001-01-08 (Refactored to separate file 2008-08-01)
// Ver: $Id: jpgraph_rgb.inc.php 1893 2009-10-02 23:15:25Z ljp $ // Ver: $Id: jpgraph_rgb.inc.php 1893 2009-10-02 23:15:25Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
/*=================================================== /*===================================================
// CLASS RGB // CLASS RGB
// Description: Color definitions as RGB triples // Description: Color definitions as RGB triples
//=================================================== //===================================================
*/ */
   
class RGB { class RGB {
public $rgb_table; public $rgb_table;
public $img; public $img;
   
function __construct($aImg=null) { function __construct($aImg=null) {
$this->img = $aImg; $this->img = $aImg;
   
// Conversion array between color names and RGB // Conversion array between color names and RGB
$this->rgb_table = array( $this->rgb_table = array(
'aqua'=> array(0,255,255), 'aqua'=> array(0,255,255),
'lime'=> array(0,255,0), 'lime'=> array(0,255,0),
'teal'=> array(0,128,128), 'teal'=> array(0,128,128),
'whitesmoke'=>array(245,245,245), 'whitesmoke'=>array(245,245,245),
'gainsboro'=>array(220,220,220), 'gainsboro'=>array(220,220,220),
'oldlace'=>array(253,245,230), 'oldlace'=>array(253,245,230),
'linen'=>array(250,240,230), 'linen'=>array(250,240,230),
'antiquewhite'=>array(250,235,215), 'antiquewhite'=>array(250,235,215),
'papayawhip'=>array(255,239,213), 'papayawhip'=>array(255,239,213),
'blanchedalmond'=>array(255,235,205), 'blanchedalmond'=>array(255,235,205),
'bisque'=>array(255,228,196), 'bisque'=>array(255,228,196),
'peachpuff'=>array(255,218,185), 'peachpuff'=>array(255,218,185),
'navajowhite'=>array(255,222,173), 'navajowhite'=>array(255,222,173),
'moccasin'=>array(255,228,181), 'moccasin'=>array(255,228,181),
'cornsilk'=>array(255,248,220), 'cornsilk'=>array(255,248,220),
'ivory'=>array(255,255,240), 'ivory'=>array(255,255,240),
'lemonchiffon'=>array(255,250,205), 'lemonchiffon'=>array(255,250,205),
'seashell'=>array(255,245,238), 'seashell'=>array(255,245,238),
'mintcream'=>array(245,255,250), 'mintcream'=>array(245,255,250),
'azure'=>array(240,255,255), 'azure'=>array(240,255,255),
'aliceblue'=>array(240,248,255), 'aliceblue'=>array(240,248,255),
'lavender'=>array(230,230,250), 'lavender'=>array(230,230,250),
'lavenderblush'=>array(255,240,245), 'lavenderblush'=>array(255,240,245),
'mistyrose'=>array(255,228,225), 'mistyrose'=>array(255,228,225),
'white'=>array(255,255,255), 'white'=>array(255,255,255),
'black'=>array(0,0,0), 'black'=>array(0,0,0),
'darkslategray'=>array(47,79,79), 'darkslategray'=>array(47,79,79),
'dimgray'=>array(105,105,105), 'dimgray'=>array(105,105,105),
'slategray'=>array(112,128,144), 'slategray'=>array(112,128,144),
'lightslategray'=>array(119,136,153), 'lightslategray'=>array(119,136,153),
'gray'=>array(190,190,190), 'gray'=>array(190,190,190),
'lightgray'=>array(211,211,211), 'lightgray'=>array(211,211,211),
'midnightblue'=>array(25,25,112), 'midnightblue'=>array(25,25,112),
'navy'=>array(0,0,128), 'navy'=>array(0,0,128),
'indigo'=>array(75,0,130), 'indigo'=>array(75,0,130),
'electricindigo'=>array(102,0,255), 'electricindigo'=>array(102,0,255),
'deepindigo'=>array(138,43,226), 'deepindigo'=>array(138,43,226),
'pigmentindigo'=>array(75,0,130), 'pigmentindigo'=>array(75,0,130),
'indigodye'=>array(0,65,106), 'indigodye'=>array(0,65,106),
'cornflowerblue'=>array(100,149,237), 'cornflowerblue'=>array(100,149,237),
'darkslateblue'=>array(72,61,139), 'darkslateblue'=>array(72,61,139),
'slateblue'=>array(106,90,205), 'slateblue'=>array(106,90,205),
'mediumslateblue'=>array(123,104,238), 'mediumslateblue'=>array(123,104,238),
'lightslateblue'=>array(132,112,255), 'lightslateblue'=>array(132,112,255),
'mediumblue'=>array(0,0,205), 'mediumblue'=>array(0,0,205),
'royalblue'=>array(65,105,225), 'royalblue'=>array(65,105,225),
'blue'=>array(0,0,255), 'blue'=>array(0,0,255),
'dodgerblue'=>array(30,144,255), 'dodgerblue'=>array(30,144,255),
'deepskyblue'=>array(0,191,255), 'deepskyblue'=>array(0,191,255),
'skyblue'=>array(135,206,235), 'skyblue'=>array(135,206,235),
'lightskyblue'=>array(135,206,250), 'lightskyblue'=>array(135,206,250),
'steelblue'=>array(70,130,180), 'steelblue'=>array(70,130,180),
'lightred'=>array(211,167,168), 'lightred'=>array(211,167,168),
'lightsteelblue'=>array(176,196,222), 'lightsteelblue'=>array(176,196,222),
'lightblue'=>array(173,216,230), 'lightblue'=>array(173,216,230),
'powderblue'=>array(176,224,230), 'powderblue'=>array(176,224,230),
'paleturquoise'=>array(175,238,238), 'paleturquoise'=>array(175,238,238),
'darkturquoise'=>array(0,206,209), 'darkturquoise'=>array(0,206,209),
'mediumturquoise'=>array(72,209,204), 'mediumturquoise'=>array(72,209,204),
'turquoise'=>array(64,224,208), 'turquoise'=>array(64,224,208),
'cyan'=>array(0,255,255), 'cyan'=>array(0,255,255),
'lightcyan'=>array(224,255,255), 'lightcyan'=>array(224,255,255),
'cadetblue'=>array(95,158,160), 'cadetblue'=>array(95,158,160),
'mediumaquamarine'=>array(102,205,170), 'mediumaquamarine'=>array(102,205,170),
'aquamarine'=>array(127,255,212), 'aquamarine'=>array(127,255,212),
'darkgreen'=>array(0,100,0), 'darkgreen'=>array(0,100,0),
'darkolivegreen'=>array(85,107,47), 'darkolivegreen'=>array(85,107,47),
'darkseagreen'=>array(143,188,143), 'darkseagreen'=>array(143,188,143),
'seagreen'=>array(46,139,87), 'seagreen'=>array(46,139,87),
'mediumseagreen'=>array(60,179,113), 'mediumseagreen'=>array(60,179,113),
'lightseagreen'=>array(32,178,170), 'lightseagreen'=>array(32,178,170),
'palegreen'=>array(152,251,152), 'palegreen'=>array(152,251,152),
'springgreen'=>array(0,255,127), 'springgreen'=>array(0,255,127),
'lawngreen'=>array(124,252,0), 'lawngreen'=>array(124,252,0),
'green'=>array(0,255,0), 'green'=>array(0,255,0),
'chartreuse'=>array(127,255,0), 'chartreuse'=>array(127,255,0),
'mediumspringgreen'=>array(0,250,154), 'mediumspringgreen'=>array(0,250,154),
'greenyellow'=>array(173,255,47), 'greenyellow'=>array(173,255,47),
'limegreen'=>array(50,205,50), 'limegreen'=>array(50,205,50),
'yellowgreen'=>array(154,205,50), 'yellowgreen'=>array(154,205,50),
'forestgreen'=>array(34,139,34), 'forestgreen'=>array(34,139,34),
'olivedrab'=>array(107,142,35), 'olivedrab'=>array(107,142,35),
'darkkhaki'=>array(189,183,107), 'darkkhaki'=>array(189,183,107),
'khaki'=>array(240,230,140), 'khaki'=>array(240,230,140),
'palegoldenrod'=>array(238,232,170), 'palegoldenrod'=>array(238,232,170),
'lightgoldenrodyellow'=>array(250,250,210), 'lightgoldenrodyellow'=>array(250,250,210),
'lightyellow'=>array(255,255,200), 'lightyellow'=>array(255,255,200),
'yellow'=>array(255,255,0), 'yellow'=>array(255,255,0),
'gold'=>array(255,215,0), 'gold'=>array(255,215,0),
'lightgoldenrod'=>array(238,221,130), 'lightgoldenrod'=>array(238,221,130),
'goldenrod'=>array(218,165,32), 'goldenrod'=>array(218,165,32),
'darkgoldenrod'=>array(184,134,11), 'darkgoldenrod'=>array(184,134,11),
'rosybrown'=>array(188,143,143), 'rosybrown'=>array(188,143,143),
'indianred'=>array(205,92,92), 'indianred'=>array(205,92,92),
'saddlebrown'=>array(139,69,19), 'saddlebrown'=>array(139,69,19),
'sienna'=>array(160,82,45), 'sienna'=>array(160,82,45),
'peru'=>array(205,133,63), 'peru'=>array(205,133,63),
'burlywood'=>array(222,184,135), 'burlywood'=>array(222,184,135),
'beige'=>array(245,245,220), 'beige'=>array(245,245,220),
'wheat'=>array(245,222,179), 'wheat'=>array(245,222,179),
'sandybrown'=>array(244,164,96), 'sandybrown'=>array(244,164,96),
'tan'=>array(210,180,140), 'tan'=>array(210,180,140),
'chocolate'=>array(210,105,30), 'chocolate'=>array(210,105,30),
'firebrick'=>array(178,34,34), 'firebrick'=>array(178,34,34),
'brown'=>array(165,42,42), 'brown'=>array(165,42,42),
'darksalmon'=>array(233,150,122), 'darksalmon'=>array(233,150,122),
'salmon'=>array(250,128,114), 'salmon'=>array(250,128,114),
'lightsalmon'=>array(255,160,122), 'lightsalmon'=>array(255,160,122),
'orange'=>array(255,165,0), 'orange'=>array(255,165,0),
'darkorange'=>array(255,140,0), 'darkorange'=>array(255,140,0),
'coral'=>array(255,127,80), 'coral'=>array(255,127,80),
'lightcoral'=>array(240,128,128), 'lightcoral'=>array(240,128,128),
'tomato'=>array(255,99,71), 'tomato'=>array(255,99,71),
'orangered'=>array(255,69,0), 'orangered'=>array(255,69,0),
'red'=>array(255,0,0), 'red'=>array(255,0,0),
'hotpink'=>array(255,105,180), 'hotpink'=>array(255,105,180),
'deeppink'=>array(255,20,147), 'deeppink'=>array(255,20,147),
'pink'=>array(255,192,203), 'pink'=>array(255,192,203),
'lightpink'=>array(255,182,193), 'lightpink'=>array(255,182,193),
'palevioletred'=>array(219,112,147), 'palevioletred'=>array(219,112,147),
'maroon'=>array(176,48,96), 'maroon'=>array(176,48,96),
'mediumvioletred'=>array(199,21,133), 'mediumvioletred'=>array(199,21,133),
'violetred'=>array(208,32,144), 'violetred'=>array(208,32,144),
'magenta'=>array(255,0,255), 'magenta'=>array(255,0,255),
'violet'=>array(238,130,238), 'violet'=>array(238,130,238),
'plum'=>array(221,160,221), 'plum'=>array(221,160,221),
'orchid'=>array(218,112,214), 'orchid'=>array(218,112,214),
'mediumorchid'=>array(186,85,211), 'mediumorchid'=>array(186,85,211),
'darkorchid'=>array(153,50,204), 'darkorchid'=>array(153,50,204),
'darkviolet'=>array(148,0,211), 'darkviolet'=>array(148,0,211),
'blueviolet'=>array(138,43,226), 'blueviolet'=>array(138,43,226),
'purple'=>array(160,32,240), 'purple'=>array(160,32,240),
'mediumpurple'=>array(147,112,219), 'mediumpurple'=>array(147,112,219),
'thistle'=>array(216,191,216), 'thistle'=>array(216,191,216),
'snow1'=>array(255,250,250), 'snow1'=>array(255,250,250),
'snow2'=>array(238,233,233), 'snow2'=>array(238,233,233),
'snow3'=>array(205,201,201), 'snow3'=>array(205,201,201),
'snow4'=>array(139,137,137), 'snow4'=>array(139,137,137),
'seashell1'=>array(255,245,238), 'seashell1'=>array(255,245,238),
'seashell2'=>array(238,229,222), 'seashell2'=>array(238,229,222),
'seashell3'=>array(205,197,191), 'seashell3'=>array(205,197,191),
'seashell4'=>array(139,134,130), 'seashell4'=>array(139,134,130),
'AntiqueWhite1'=>array(255,239,219), 'AntiqueWhite1'=>array(255,239,219),
'AntiqueWhite2'=>array(238,223,204), 'AntiqueWhite2'=>array(238,223,204),
'AntiqueWhite3'=>array(205,192,176), 'AntiqueWhite3'=>array(205,192,176),
'AntiqueWhite4'=>array(139,131,120), 'AntiqueWhite4'=>array(139,131,120),
'bisque1'=>array(255,228,196), 'bisque1'=>array(255,228,196),
'bisque2'=>array(238,213,183), 'bisque2'=>array(238,213,183),
'bisque3'=>array(205,183,158), 'bisque3'=>array(205,183,158),
'bisque4'=>array(139,125,107), 'bisque4'=>array(139,125,107),
'peachPuff1'=>array(255,218,185), 'peachPuff1'=>array(255,218,185),
'peachpuff2'=>array(238,203,173), 'peachpuff2'=>array(238,203,173),
'peachpuff3'=>array(205,175,149), 'peachpuff3'=>array(205,175,149),
'peachpuff4'=>array(139,119,101), 'peachpuff4'=>array(139,119,101),
'navajowhite1'=>array(255,222,173), 'navajowhite1'=>array(255,222,173),
'navajowhite2'=>array(238,207,161), 'navajowhite2'=>array(238,207,161),
'navajowhite3'=>array(205,179,139), 'navajowhite3'=>array(205,179,139),
'navajowhite4'=>array(139,121,94), 'navajowhite4'=>array(139,121,94),
'lemonchiffon1'=>array(255,250,205), 'lemonchiffon1'=>array(255,250,205),
'lemonchiffon2'=>array(238,233,191), 'lemonchiffon2'=>array(238,233,191),
'lemonchiffon3'=>array(205,201,165), 'lemonchiffon3'=>array(205,201,165),
'lemonchiffon4'=>array(139,137,112), 'lemonchiffon4'=>array(139,137,112),
'ivory1'=>array(255,255,240), 'ivory1'=>array(255,255,240),
'ivory2'=>array(238,238,224), 'ivory2'=>array(238,238,224),
'ivory3'=>array(205,205,193), 'ivory3'=>array(205,205,193),
'ivory4'=>array(139,139,131), 'ivory4'=>array(139,139,131),
'honeydew'=>array(193,205,193), 'honeydew'=>array(193,205,193),
'lavenderblush1'=>array(255,240,245), 'lavenderblush1'=>array(255,240,245),
'lavenderblush2'=>array(238,224,229), 'lavenderblush2'=>array(238,224,229),
'lavenderblush3'=>array(205,193,197), 'lavenderblush3'=>array(205,193,197),
'lavenderblush4'=>array(139,131,134), 'lavenderblush4'=>array(139,131,134),
'mistyrose1'=>array(255,228,225), 'mistyrose1'=>array(255,228,225),
'mistyrose2'=>array(238,213,210), 'mistyrose2'=>array(238,213,210),
'mistyrose3'=>array(205,183,181), 'mistyrose3'=>array(205,183,181),
'mistyrose4'=>array(139,125,123), 'mistyrose4'=>array(139,125,123),
'azure1'=>array(240,255,255), 'azure1'=>array(240,255,255),
'azure2'=>array(224,238,238), 'azure2'=>array(224,238,238),
'azure3'=>array(193,205,205), 'azure3'=>array(193,205,205),
'azure4'=>array(131,139,139), 'azure4'=>array(131,139,139),
'slateblue1'=>array(131,111,255), 'slateblue1'=>array(131,111,255),
'slateblue2'=>array(122,103,238), 'slateblue2'=>array(122,103,238),
'slateblue3'=>array(105,89,205), 'slateblue3'=>array(105,89,205),
'slateblue4'=>array(71,60,139), 'slateblue4'=>array(71,60,139),
'royalblue1'=>array(72,118,255), 'royalblue1'=>array(72,118,255),
'royalblue2'=>array(67,110,238), 'royalblue2'=>array(67,110,238),
'royalblue3'=>array(58,95,205), 'royalblue3'=>array(58,95,205),
'royalblue4'=>array(39,64,139), 'royalblue4'=>array(39,64,139),
'dodgerblue1'=>array(30,144,255), 'dodgerblue1'=>array(30,144,255),
'dodgerblue2'=>array(28,134,238), 'dodgerblue2'=>array(28,134,238),
'dodgerblue3'=>array(24,116,205), 'dodgerblue3'=>array(24,116,205),
'dodgerblue4'=>array(16,78,139), 'dodgerblue4'=>array(16,78,139),
'steelblue1'=>array(99,184,255), 'steelblue1'=>array(99,184,255),
'steelblue2'=>array(92,172,238), 'steelblue2'=>array(92,172,238),
'steelblue3'=>array(79,148,205), 'steelblue3'=>array(79,148,205),
'steelblue4'=>array(54,100,139), 'steelblue4'=>array(54,100,139),
'deepskyblue1'=>array(0,191,255), 'deepskyblue1'=>array(0,191,255),
'deepskyblue2'=>array(0,178,238), 'deepskyblue2'=>array(0,178,238),
'deepskyblue3'=>array(0,154,205), 'deepskyblue3'=>array(0,154,205),
'deepskyblue4'=>array(0,104,139), 'deepskyblue4'=>array(0,104,139),
'skyblue1'=>array(135,206,255), 'skyblue1'=>array(135,206,255),
'skyblue2'=>array(126,192,238), 'skyblue2'=>array(126,192,238),
'skyblue3'=>array(108,166,205), 'skyblue3'=>array(108,166,205),
'skyblue4'=>array(74,112,139), 'skyblue4'=>array(74,112,139),
'lightskyblue1'=>array(176,226,255), 'lightskyblue1'=>array(176,226,255),
'lightskyblue2'=>array(164,211,238), 'lightskyblue2'=>array(164,211,238),
'lightskyblue3'=>array(141,182,205), 'lightskyblue3'=>array(141,182,205),
'lightskyblue4'=>array(96,123,139), 'lightskyblue4'=>array(96,123,139),
'slategray1'=>array(198,226,255), 'slategray1'=>array(198,226,255),
'slategray2'=>array(185,211,238), 'slategray2'=>array(185,211,238),
'slategray3'=>array(159,182,205), 'slategray3'=>array(159,182,205),
'slategray4'=>array(108,123,139), 'slategray4'=>array(108,123,139),
'lightsteelblue1'=>array(202,225,255), 'lightsteelblue1'=>array(202,225,255),
'lightsteelblue2'=>array(188,210,238), 'lightsteelblue2'=>array(188,210,238),
'lightsteelblue3'=>array(162,181,205), 'lightsteelblue3'=>array(162,181,205),
'lightsteelblue4'=>array(110,123,139), 'lightsteelblue4'=>array(110,123,139),
'lightblue1'=>array(191,239,255), 'lightblue1'=>array(191,239,255),
'lightblue2'=>array(178,223,238), 'lightblue2'=>array(178,223,238),
'lightblue3'=>array(154,192,205), 'lightblue3'=>array(154,192,205),
'lightblue4'=>array(104,131,139), 'lightblue4'=>array(104,131,139),
'lightcyan1'=>array(224,255,255), 'lightcyan1'=>array(224,255,255),
'lightcyan2'=>array(209,238,238), 'lightcyan2'=>array(209,238,238),
'lightcyan3'=>array(180,205,205), 'lightcyan3'=>array(180,205,205),
'lightcyan4'=>array(122,139,139), 'lightcyan4'=>array(122,139,139),
'paleturquoise1'=>array(187,255,255), 'paleturquoise1'=>array(187,255,255),
'paleturquoise2'=>array(174,238,238), 'paleturquoise2'=>array(174,238,238),
'paleturquoise3'=>array(150,205,205), 'paleturquoise3'=>array(150,205,205),
'paleturquoise4'=>array(102,139,139), 'paleturquoise4'=>array(102,139,139),
'cadetblue1'=>array(152,245,255), 'cadetblue1'=>array(152,245,255),
'cadetblue2'=>array(142,229,238), 'cadetblue2'=>array(142,229,238),
'cadetblue3'=>array(122,197,205), 'cadetblue3'=>array(122,197,205),
'cadetblue4'=>array(83,134,139), 'cadetblue4'=>array(83,134,139),
'turquoise1'=>array(0,245,255), 'turquoise1'=>array(0,245,255),
'turquoise2'=>array(0,229,238), 'turquoise2'=>array(0,229,238),
'turquoise3'=>array(0,197,205), 'turquoise3'=>array(0,197,205),
'turquoise4'=>array(0,134,139), 'turquoise4'=>array(0,134,139),
'cyan1'=>array(0,255,255), 'cyan1'=>array(0,255,255),
'cyan2'=>array(0,238,238), 'cyan2'=>array(0,238,238),
'cyan3'=>array(0,205,205), 'cyan3'=>array(0,205,205),
'cyan4'=>array(0,139,139), 'cyan4'=>array(0,139,139),
'darkslategray1'=>array(151,255,255), 'darkslategray1'=>array(151,255,255),
'darkslategray2'=>array(141,238,238), 'darkslategray2'=>array(141,238,238),
'darkslategray3'=>array(121,205,205), 'darkslategray3'=>array(121,205,205),
'darkslategray4'=>array(82,139,139), 'darkslategray4'=>array(82,139,139),
'aquamarine1'=>array(127,255,212), 'aquamarine1'=>array(127,255,212),
'aquamarine2'=>array(118,238,198), 'aquamarine2'=>array(118,238,198),
'aquamarine3'=>array(102,205,170), 'aquamarine3'=>array(102,205,170),
'aquamarine4'=>array(69,139,116), 'aquamarine4'=>array(69,139,116),
'darkseagreen1'=>array(193,255,193), 'darkseagreen1'=>array(193,255,193),
'darkseagreen2'=>array(180,238,180), 'darkseagreen2'=>array(180,238,180),
'darkseagreen3'=>array(155,205,155), 'darkseagreen3'=>array(155,205,155),
'darkseagreen4'=>array(105,139,105), 'darkseagreen4'=>array(105,139,105),
'seagreen1'=>array(84,255,159), 'seagreen1'=>array(84,255,159),
'seagreen2'=>array(78,238,148), 'seagreen2'=>array(78,238,148),
'seagreen3'=>array(67,205,128), 'seagreen3'=>array(67,205,128),
'seagreen4'=>array(46,139,87), 'seagreen4'=>array(46,139,87),
'palegreen1'=>array(154,255,154), 'palegreen1'=>array(154,255,154),
'palegreen2'=>array(144,238,144), 'palegreen2'=>array(144,238,144),
'palegreen3'=>array(124,205,124), 'palegreen3'=>array(124,205,124),
'palegreen4'=>array(84,139,84), 'palegreen4'=>array(84,139,84),
'springgreen1'=>array(0,255,127), 'springgreen1'=>array(0,255,127),
'springgreen2'=>array(0,238,118), 'springgreen2'=>array(0,238,118),
'springgreen3'=>array(0,205,102), 'springgreen3'=>array(0,205,102),
'springgreen4'=>array(0,139,69), 'springgreen4'=>array(0,139,69),
'chartreuse1'=>array(127,255,0), 'chartreuse1'=>array(127,255,0),
'chartreuse2'=>array(118,238,0), 'chartreuse2'=>array(118,238,0),
'chartreuse3'=>array(102,205,0), 'chartreuse3'=>array(102,205,0),
'chartreuse4'=>array(69,139,0), 'chartreuse4'=>array(69,139,0),
'olivedrab1'=>array(192,255,62), 'olivedrab1'=>array(192,255,62),
'olivedrab2'=>array(179,238,58), 'olivedrab2'=>array(179,238,58),
'olivedrab3'=>array(154,205,50), 'olivedrab3'=>array(154,205,50),
'olivedrab4'=>array(105,139,34), 'olivedrab4'=>array(105,139,34),
'darkolivegreen1'=>array(202,255,112), 'darkolivegreen1'=>array(202,255,112),
'darkolivegreen2'=>array(188,238,104), 'darkolivegreen2'=>array(188,238,104),
'darkolivegreen3'=>array(162,205,90), 'darkolivegreen3'=>array(162,205,90),
'darkolivegreen4'=>array(110,139,61), 'darkolivegreen4'=>array(110,139,61),
'khaki1'=>array(255,246,143), 'khaki1'=>array(255,246,143),
'khaki2'=>array(238,230,133), 'khaki2'=>array(238,230,133),
'khaki3'=>array(205,198,115), 'khaki3'=>array(205,198,115),
'khaki4'=>array(139,134,78), 'khaki4'=>array(139,134,78),
'lightgoldenrod1'=>array(255,236,139), 'lightgoldenrod1'=>array(255,236,139),
'lightgoldenrod2'=>array(238,220,130), 'lightgoldenrod2'=>array(238,220,130),
'lightgoldenrod3'=>array(205,190,112), 'lightgoldenrod3'=>array(205,190,112),
'lightgoldenrod4'=>array(139,129,76), 'lightgoldenrod4'=>array(139,129,76),
'yellow1'=>array(255,255,0), 'yellow1'=>array(255,255,0),
'yellow2'=>array(238,238,0), 'yellow2'=>array(238,238,0),
'yellow3'=>array(205,205,0), 'yellow3'=>array(205,205,0),
'yellow4'=>array(139,139,0), 'yellow4'=>array(139,139,0),
'gold1'=>array(255,215,0), 'gold1'=>array(255,215,0),
'gold2'=>array(238,201,0), 'gold2'=>array(238,201,0),
'gold3'=>array(205,173,0), 'gold3'=>array(205,173,0),
'gold4'=>array(139,117,0), 'gold4'=>array(139,117,0),
'goldenrod1'=>array(255,193,37), 'goldenrod1'=>array(255,193,37),
'goldenrod2'=>array(238,180,34), 'goldenrod2'=>array(238,180,34),
'goldenrod3'=>array(205,155,29), 'goldenrod3'=>array(205,155,29),
'goldenrod4'=>array(139,105,20), 'goldenrod4'=>array(139,105,20),
'darkgoldenrod1'=>array(255,185,15), 'darkgoldenrod1'=>array(255,185,15),
'darkgoldenrod2'=>array(238,173,14), 'darkgoldenrod2'=>array(238,173,14),
'darkgoldenrod3'=>array(205,149,12), 'darkgoldenrod3'=>array(205,149,12),
'darkgoldenrod4'=>array(139,101,8), 'darkgoldenrod4'=>array(139,101,8),
'rosybrown1'=>array(255,193,193), 'rosybrown1'=>array(255,193,193),
'rosybrown2'=>array(238,180,180), 'rosybrown2'=>array(238,180,180),
'rosybrown3'=>array(205,155,155), 'rosybrown3'=>array(205,155,155),
'rosybrown4'=>array(139,105,105), 'rosybrown4'=>array(139,105,105),
'indianred1'=>array(255,106,106), 'indianred1'=>array(255,106,106),
'indianred2'=>array(238,99,99), 'indianred2'=>array(238,99,99),
'indianred3'=>array(205,85,85), 'indianred3'=>array(205,85,85),
'indianred4'=>array(139,58,58), 'indianred4'=>array(139,58,58),
'sienna1'=>array(255,130,71), 'sienna1'=>array(255,130,71),
'sienna2'=>array(238,121,66), 'sienna2'=>array(238,121,66),
'sienna3'=>array(205,104,57), 'sienna3'=>array(205,104,57),
'sienna4'=>array(139,71,38), 'sienna4'=>array(139,71,38),
'burlywood1'=>array(255,211,155), 'burlywood1'=>array(255,211,155),
'burlywood2'=>array(238,197,145), 'burlywood2'=>array(238,197,145),
'burlywood3'=>array(205,170,125), 'burlywood3'=>array(205,170,125),
'burlywood4'=>array(139,115,85), 'burlywood4'=>array(139,115,85),
'wheat1'=>array(255,231,186), 'wheat1'=>array(255,231,186),
'wheat2'=>array(238,216,174), 'wheat2'=>array(238,216,174),
'wheat3'=>array(205,186,150), 'wheat3'=>array(205,186,150),
'wheat4'=>array(139,126,102), 'wheat4'=>array(139,126,102),
'tan1'=>array(255,165,79), 'tan1'=>array(255,165,79),
'tan2'=>array(238,154,73), 'tan2'=>array(238,154,73),
'tan3'=>array(205,133,63), 'tan3'=>array(205,133,63),
'tan4'=>array(139,90,43), 'tan4'=>array(139,90,43),
'chocolate1'=>array(255,127,36), 'chocolate1'=>array(255,127,36),
'chocolate2'=>array(238,118,33), 'chocolate2'=>array(238,118,33),
'chocolate3'=>array(205,102,29), 'chocolate3'=>array(205,102,29),
'chocolate4'=>array(139,69,19), 'chocolate4'=>array(139,69,19),
'firebrick1'=>array(255,48,48), 'firebrick1'=>array(255,48,48),
'firebrick2'=>array(238,44,44), 'firebrick2'=>array(238,44,44),
'firebrick3'=>array(205,38,38), 'firebrick3'=>array(205,38,38),
'firebrick4'=>array(139,26,26), 'firebrick4'=>array(139,26,26),
'brown1'=>array(255,64,64), 'brown1'=>array(255,64,64),
'brown2'=>array(238,59,59), 'brown2'=>array(238,59,59),
'brown3'=>array(205,51,51), 'brown3'=>array(205,51,51),
'brown4'=>array(139,35,35), 'brown4'=>array(139,35,35),
'salmon1'=>array(255,140,105), 'salmon1'=>array(255,140,105),
'salmon2'=>array(238,130,98), 'salmon2'=>array(238,130,98),
'salmon3'=>array(205,112,84), 'salmon3'=>array(205,112,84),
'salmon4'=>array(139,76,57), 'salmon4'=>array(139,76,57),
'lightsalmon1'=>array(255,160,122), 'lightsalmon1'=>array(255,160,122),
'lightsalmon2'=>array(238,149,114), 'lightsalmon2'=>array(238,149,114),
'lightsalmon3'=>array(205,129,98), 'lightsalmon3'=>array(205,129,98),
'lightsalmon4'=>array(139,87,66), 'lightsalmon4'=>array(139,87,66),
'orange1'=>array(255,165,0), 'orange1'=>array(255,165,0),
'orange2'=>array(238,154,0), 'orange2'=>array(238,154,0),
'orange3'=>array(205,133,0), 'orange3'=>array(205,133,0),
'orange4'=>array(139,90,0), 'orange4'=>array(139,90,0),
'darkorange1'=>array(255,127,0), 'darkorange1'=>array(255,127,0),
'darkorange2'=>array(238,118,0), 'darkorange2'=>array(238,118,0),
'darkorange3'=>array(205,102,0), 'darkorange3'=>array(205,102,0),
'darkorange4'=>array(139,69,0), 'darkorange4'=>array(139,69,0),
'coral1'=>array(255,114,86), 'coral1'=>array(255,114,86),
'coral2'=>array(238,106,80), 'coral2'=>array(238,106,80),
'coral3'=>array(205,91,69), 'coral3'=>array(205,91,69),
'coral4'=>array(139,62,47), 'coral4'=>array(139,62,47),
'tomato1'=>array(255,99,71), 'tomato1'=>array(255,99,71),
'tomato2'=>array(238,92,66), 'tomato2'=>array(238,92,66),
'tomato3'=>array(205,79,57), 'tomato3'=>array(205,79,57),
'tomato4'=>array(139,54,38), 'tomato4'=>array(139,54,38),
'orangered1'=>array(255,69,0), 'orangered1'=>array(255,69,0),
'orangered2'=>array(238,64,0), 'orangered2'=>array(238,64,0),
'orangered3'=>array(205,55,0), 'orangered3'=>array(205,55,0),
'orangered4'=>array(139,37,0), 'orangered4'=>array(139,37,0),
'deeppink1'=>array(255,20,147), 'deeppink1'=>array(255,20,147),
'deeppink2'=>array(238,18,137), 'deeppink2'=>array(238,18,137),
'deeppink3'=>array(205,16,118), 'deeppink3'=>array(205,16,118),
'deeppink4'=>array(139,10,80), 'deeppink4'=>array(139,10,80),
'hotpink1'=>array(255,110,180), 'hotpink1'=>array(255,110,180),
'hotpink2'=>array(238,106,167), 'hotpink2'=>array(238,106,167),
'hotpink3'=>array(205,96,144), 'hotpink3'=>array(205,96,144),
'hotpink4'=>array(139,58,98), 'hotpink4'=>array(139,58,98),
'pink1'=>array(255,181,197), 'pink1'=>array(255,181,197),
'pink2'=>array(238,169,184), 'pink2'=>array(238,169,184),
'pink3'=>array(205,145,158), 'pink3'=>array(205,145,158),
'pink4'=>array(139,99,108), 'pink4'=>array(139,99,108),
'lightpink1'=>array(255,174,185), 'lightpink1'=>array(255,174,185),
'lightpink2'=>array(238,162,173), 'lightpink2'=>array(238,162,173),
'lightpink3'=>array(205,140,149), 'lightpink3'=>array(205,140,149),
'lightpink4'=>array(139,95,101), 'lightpink4'=>array(139,95,101),
'palevioletred1'=>array(255,130,171), 'palevioletred1'=>array(255,130,171),
'palevioletred2'=>array(238,121,159), 'palevioletred2'=>array(238,121,159),
'palevioletred3'=>array(205,104,137), 'palevioletred3'=>array(205,104,137),
'palevioletred4'=>array(139,71,93), 'palevioletred4'=>array(139,71,93),
'maroon1'=>array(255,52,179), 'maroon1'=>array(255,52,179),
'maroon2'=>array(238,48,167), 'maroon2'=>array(238,48,167),
'maroon3'=>array(205,41,144), 'maroon3'=>array(205,41,144),
'maroon4'=>array(139,28,98), 'maroon4'=>array(139,28,98),
'violetred1'=>array(255,62,150), 'violetred1'=>array(255,62,150),
'violetred2'=>array(238,58,140), 'violetred2'=>array(238,58,140),
'violetred3'=>array(205,50,120), 'violetred3'=>array(205,50,120),
'violetred4'=>array(139,34,82), 'violetred4'=>array(139,34,82),
'magenta1'=>array(255,0,255), 'magenta1'=>array(255,0,255),
'magenta2'=>array(238,0,238), 'magenta2'=>array(238,0,238),
'magenta3'=>array(205,0,205), 'magenta3'=>array(205,0,205),
'magenta4'=>array(139,0,139), 'magenta4'=>array(139,0,139),
'mediumred'=>array(140,34,34), 'mediumred'=>array(140,34,34),
'orchid1'=>array(255,131,250), 'orchid1'=>array(255,131,250),
'orchid2'=>array(238,122,233), 'orchid2'=>array(238,122,233),
'orchid3'=>array(205,105,201), 'orchid3'=>array(205,105,201),
'orchid4'=>array(139,71,137), 'orchid4'=>array(139,71,137),
'plum1'=>array(255,187,255), 'plum1'=>array(255,187,255),
'plum2'=>array(238,174,238), 'plum2'=>array(238,174,238),
'plum3'=>array(205,150,205), 'plum3'=>array(205,150,205),
'plum4'=>array(139,102,139), 'plum4'=>array(139,102,139),
'mediumorchid1'=>array(224,102,255), 'mediumorchid1'=>array(224,102,255),
'mediumorchid2'=>array(209,95,238), 'mediumorchid2'=>array(209,95,238),
'mediumorchid3'=>array(180,82,205), 'mediumorchid3'=>array(180,82,205),
'mediumorchid4'=>array(122,55,139), 'mediumorchid4'=>array(122,55,139),
'darkorchid1'=>array(191,62,255), 'darkorchid1'=>array(191,62,255),
'darkorchid2'=>array(178,58,238), 'darkorchid2'=>array(178,58,238),
'darkorchid3'=>array(154,50,205), 'darkorchid3'=>array(154,50,205),
'darkorchid4'=>array(104,34,139), 'darkorchid4'=>array(104,34,139),
'purple1'=>array(155,48,255), 'purple1'=>array(155,48,255),
'purple2'=>array(145,44,238), 'purple2'=>array(145,44,238),
'purple3'=>array(125,38,205), 'purple3'=>array(125,38,205),
'purple4'=>array(85,26,139), 'purple4'=>array(85,26,139),
'mediumpurple1'=>array(171,130,255), 'mediumpurple1'=>array(171,130,255),
'mediumpurple2'=>array(159,121,238), 'mediumpurple2'=>array(159,121,238),
'mediumpurple3'=>array(137,104,205), 'mediumpurple3'=>array(137,104,205),
'mediumpurple4'=>array(93,71,139), 'mediumpurple4'=>array(93,71,139),
'thistle1'=>array(255,225,255), 'thistle1'=>array(255,225,255),
'thistle2'=>array(238,210,238), 'thistle2'=>array(238,210,238),
'thistle3'=>array(205,181,205), 'thistle3'=>array(205,181,205),
'thistle4'=>array(139,123,139), 'thistle4'=>array(139,123,139),
'gray1'=>array(10,10,10), 'gray1'=>array(10,10,10),
'gray2'=>array(40,40,30), 'gray2'=>array(40,40,30),
'gray3'=>array(70,70,70), 'gray3'=>array(70,70,70),
'gray4'=>array(100,100,100), 'gray4'=>array(100,100,100),
'gray5'=>array(130,130,130), 'gray5'=>array(130,130,130),
'gray6'=>array(160,160,160), 'gray6'=>array(160,160,160),
'gray7'=>array(190,190,190), 'gray7'=>array(190,190,190),
'gray8'=>array(210,210,210), 'gray8'=>array(210,210,210),
'gray9'=>array(240,240,240), 'gray9'=>array(240,240,240),
'darkgray'=>array(100,100,100), 'darkgray'=>array(100,100,100),
'darkblue'=>array(0,0,139), 'darkblue'=>array(0,0,139),
'darkcyan'=>array(0,139,139), 'darkcyan'=>array(0,139,139),
'darkmagenta'=>array(139,0,139), 'darkmagenta'=>array(139,0,139),
'darkred'=>array(139,0,0), 'darkred'=>array(139,0,0),
'silver'=>array(192, 192, 192), 'silver'=>array(192, 192, 192),
'eggplant'=>array(144,176,168), 'eggplant'=>array(144,176,168),
'lightgreen'=>array(144,238,144)); 'lightgreen'=>array(144,238,144));
} }
   
   
//---------------- //----------------
// PUBLIC METHODS // PUBLIC METHODS
// Colors can be specified as either // Colors can be specified as either
// 1. #xxxxxx HTML style // 1. #xxxxxx HTML style
// 2. "colorname" as a named color // 2. "colorname" as a named color
// 3. array(r,g,b) RGB triple // 3. array(r,g,b) RGB triple
// This function translates this to a native RGB format and returns an // This function translates this to a native RGB format and returns an
// RGB triple. // RGB triple.
   
function Color($aColor) { function Color($aColor) {
if (is_string($aColor)) { if (is_string($aColor)) {
$matches = array(); $matches = array();
// this regex will parse a color string and fill the $matches array as such: // this regex will parse a color string and fill the $matches array as such:
// 0: the full match if any // 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...) // 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 # // 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 # // 5: all alpha-numeric characters at the beginning of the string if string does not start with #
// 6: alpha value prefixed by @ if supplied // 6: alpha value prefixed by @ if supplied
// 7: alpha value with @ stripped // 7: alpha value with @ stripped
// 8: adjust value prefixed with : if supplied // 8: adjust value prefixed with : if supplied
// 9: adjust value with : stripped // 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\.,]+))?/'; $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)) { if(!preg_match($regex, $aColor, $matches)) {
JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor"); JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor");
} }
if(empty($matches[5])) { if(empty($matches[5])) {
$r = strlen($matches[2]) == 1 ? $matches[2].$matches[2] : $matches[2]; $r = strlen($matches[2]) == 1 ? $matches[2].$matches[2] : $matches[2];
$g = strlen($matches[3]) == 1 ? $matches[3].$matches[3] : $matches[3]; $g = strlen($matches[3]) == 1 ? $matches[3].$matches[3] : $matches[3];
$b = strlen($matches[4]) == 1 ? $matches[4].$matches[4] : $matches[4]; $b = strlen($matches[4]) == 1 ? $matches[4].$matches[4] : $matches[4];
$r = hexdec($r); $r = hexdec($r);
$g = hexdec($g); $g = hexdec($g);
$b = hexdec($b); $b = hexdec($b);
}else { }else {
if(!isset($this->rgb_table[$matches[5]]) ) { if(!isset($this->rgb_table[$matches[5]]) ) {
JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor"); JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor");
} }
$r = $this->rgb_table[$matches[5]][0]; $r = $this->rgb_table[$matches[5]][0];
$g = $this->rgb_table[$matches[5]][1]; $g = $this->rgb_table[$matches[5]][1];
$b = $this->rgb_table[$matches[5]][2]; $b = $this->rgb_table[$matches[5]][2];
} }
$alpha = isset($matches[7]) ? str_replace(',','.',$matches[7]) : 0; $alpha = isset($matches[7]) ? str_replace(',','.',$matches[7]) : 0;
$adj = isset($matches[9]) ? str_replace(',','.',$matches[9]) : 1.0; $adj = isset($matches[9]) ? str_replace(',','.',$matches[9]) : 1.0;
   
if( $adj < 0 ) { if( $adj < 0 ) {
JpGraphError::RaiseL(25077);//('Adjustment factor for color must be > 0'); JpGraphError::RaiseL(25077);//('Adjustment factor for color must be > 0');
} }
   
// Scale adj so that an adj=2 always // Scale adj so that an adj=2 always
// makes the color 100% white (i.e. 255,255,255. // makes the color 100% white (i.e. 255,255,255.
// and adj=1 neutral and adj=0 black. // and adj=1 neutral and adj=0 black.
if( $adj == 1) { if( $adj == 1) {
return array($r,$g,$b,$alpha); return array($r,$g,$b,$alpha);
} }
elseif( $adj > 1 ) { elseif( $adj > 1 ) {
$m = ($adj-1.0)*(255-min(255,min($r,min($g,$b)))); $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); return array(min(255,$r+$m), min(255,$g+$m), min(255,$b+$m),$alpha);
} }
elseif( $adj < 1 ) { elseif( $adj < 1 ) {
$m = ($adj-1.0)*max(255,max($r,max($g,$b))); $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); return array(max(0,$r+$m), max(0,$g+$m), max(0,$b+$m),$alpha);
} }
} elseif( is_array($aColor) ) { } elseif( is_array($aColor) ) {
if(!isset($aColor[3])) $aColor[3] = 0; if(!isset($aColor[3])) $aColor[3] = 0;
return $aColor; return $aColor;
} }
else { else {
JpGraphError::RaiseL(25079,$aColor,count($aColor));//(" Unknown color specification: $aColor , size=".count($aColor)); JpGraphError::RaiseL(25079,$aColor,count($aColor));//(" Unknown color specification: $aColor , size=".count($aColor));
} }
} }
   
// Compare two colors // Compare two colors
// return true if equal // return true if equal
function Equal($aCol1,$aCol2) { function Equal($aCol1,$aCol2) {
$c1 = $this->Color($aCol1); $c1 = $this->Color($aCol1);
$c2 = $this->Color($aCol2); $c2 = $this->Color($aCol2);
return $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] ; return $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] ;
} }
   
// Allocate a new color in the current image // Allocate a new color in the current image
// Return new color index, -1 if no more colors could be allocated // Return new color index, -1 if no more colors could be allocated
function Allocate($aColor,$aAlpha=0.0) { function Allocate($aColor,$aAlpha=0.0) {
list ($r, $g, $b, $a) = $this->color($aColor); list ($r, $g, $b, $a) = $this->color($aColor);
// If alpha is specified in the color string then this // If alpha is specified in the color string then this
// takes precedence over the second argument // takes precedence over the second argument
if( $a > 0 ) { if( $a > 0 ) {
$aAlpha = $a; $aAlpha = $a;
} }
if( $aAlpha < 0 || $aAlpha > 1 ) { if( $aAlpha < 0 || $aAlpha > 1 ) {
JpGraphError::RaiseL(25080);//('Alpha parameter for color must be between 0.0 and 1.0'); 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)); return imagecolorresolvealpha($this->img, $r, $g, $b, round($aAlpha * 127));
} }
   
// Try to convert an array with three valid numbers to the corresponding hex array // 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 // 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. // 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 // 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) // a single color (specifeid as an RGB triple)
static function tryHexConversion($aColor) { static function tryHexConversion($aColor) {
if( is_array( $aColor ) ) { if( is_array( $aColor ) ) {
if( count( $aColor ) == 3 ) { if( count( $aColor ) == 3 ) {
if( is_numeric($aColor[0]) && is_numeric($aColor[1]) && is_numeric($aColor[2]) ) { if( is_numeric($aColor[0]) && is_numeric($aColor[1]) && is_numeric($aColor[2]) ) {
if( ($aColor[0] >= 0 && $aColor[0] <= 255) && if( ($aColor[0] >= 0 && $aColor[0] <= 255) &&
($aColor[1] >= 0 && $aColor[1] <= 255) && ($aColor[1] >= 0 && $aColor[1] <= 255) &&
($aColor[2] >= 0 && $aColor[2] <= 255) ) { ($aColor[2] >= 0 && $aColor[2] <= 255) ) {
return sprintf('#%02x%02x%02x',$aColor[0],$aColor[1],$aColor[2]); return sprintf('#%02x%02x%02x',$aColor[0],$aColor[1],$aColor[2]);
} }
} }
} }
} }
return $aColor; return $aColor;
} }
   
// Return a RGB tripple corresponding to a position in the normal light spectrum // 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 // 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 // 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. // of the constituting colors in the visible color spectra.
// The $aDynamicRange specified how much of the dynamic range we shold use // 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 // 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. // colors. In the extreme of 0.0 then all colors will be black.
static function GetSpectrum($aVal,$aDynamicRange=1.0) { static function GetSpectrum($aVal,$aDynamicRange=1.0) {
if( $aVal < 0 || $aVal > 1.0001 ) { if( $aVal < 0 || $aVal > 1.0001 ) {
return array(0,0,0); // Invalid case - just return black return array(0,0,0); // Invalid case - just return black
} }
   
$sat = round(255*$aDynamicRange); $sat = round(255*$aDynamicRange);
$a = 0.25; $a = 0.25;
if( $aVal <= 0.25 ) { if( $aVal <= 0.25 ) {
return array(0, round($sat*$aVal/$a), $sat); return array(0, round($sat*$aVal/$a), $sat);
} }
elseif( $aVal <= 0.5 ) { elseif( $aVal <= 0.5 ) {
return array(0, $sat, round($sat-$sat*($aVal-0.25)/$a)); return array(0, $sat, round($sat-$sat*($aVal-0.25)/$a));
} }
elseif( $aVal <= 0.75 ) { elseif( $aVal <= 0.75 ) {
return array(round($sat*($aVal-0.5)/$a), $sat, 0); return array(round($sat*($aVal-0.5)/$a), $sat, 0);
} }
else { else {
return array($sat, round($sat-$sat*($aVal-0.75)/$a), 0); return array($sat, round($sat-$sat*($aVal-0.75)/$a), 0);
} }
} }
   
} // Class } // Class
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_SCATTER.PHP // File: JPGRAPH_SCATTER.PHP
// Description: Scatter (and impuls) plot extension for JpGraph // Description: Scatter (and impuls) plot extension for JpGraph
// Created: 2001-02-11 // Created: 2001-02-11
// Ver: $Id: jpgraph_scatter.php 1397 2009-06-27 21:34:14Z ljp $ // Ver: $Id: jpgraph_scatter.php 1397 2009-06-27 21:34:14Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
require_once ('jpgraph_plotmark.inc.php'); require_once ('jpgraph_plotmark.inc.php');
   
//=================================================== //===================================================
// CLASS FieldArrow // CLASS FieldArrow
// Description: Draw an arrow at (x,y) with angle a // Description: Draw an arrow at (x,y) with angle a
//=================================================== //===================================================
class FieldArrow { class FieldArrow {
public $iColor='black'; public $iColor='black';
public $iSize=10; // Length in pixels for arrow public $iSize=10; // Length in pixels for arrow
public $iArrowSize = 2; public $iArrowSize = 2;
private $isizespec = array( private $isizespec = array(
array(2,1),array(3,2),array(4,3),array(6,4),array(7,4),array(8,5),array(10,6),array(12,7),array(16,8),array(20,10) array(2,1),array(3,2),array(4,3),array(6,4),array(7,4),array(8,5),array(10,6),array(12,7),array(16,8),array(20,10)
); );
function __construct() { function __construct() {
// Empty // Empty
} }
   
function SetSize($aSize,$aArrowSize=2) { function SetSize($aSize,$aArrowSize=2) {
$this->iSize = $aSize; $this->iSize = $aSize;
$this->iArrowSize = $aArrowSize; $this->iArrowSize = $aArrowSize;
} }
   
function SetColor($aColor) { function SetColor($aColor) {
$this->iColor = $aColor; $this->iColor = $aColor;
} }
   
function Stroke($aImg,$x,$y,$a) { function Stroke($aImg,$x,$y,$a) {
// First rotate the center coordinates // First rotate the center coordinates
list($x,$y) = $aImg->Rotate($x,$y); list($x,$y) = $aImg->Rotate($x,$y);
   
$old_origin = $aImg->SetCenter($x,$y); $old_origin = $aImg->SetCenter($x,$y);
$old_a = $aImg->a; $old_a = $aImg->a;
$aImg->SetAngle(-$a+$old_a); $aImg->SetAngle(-$a+$old_a);
   
$dx = round($this->iSize/2); $dx = round($this->iSize/2);
$c = array($x-$dx,$y,$x+$dx,$y); $c = array($x-$dx,$y,$x+$dx,$y);
$x += $dx; $x += $dx;
   
list($dx,$dy) = $this->isizespec[$this->iArrowSize]; list($dx,$dy) = $this->isizespec[$this->iArrowSize];
$ca = array($x,$y,$x-$dx,$y-$dy,$x-$dx,$y+$dy,$x,$y); $ca = array($x,$y,$x-$dx,$y-$dy,$x-$dx,$y+$dy,$x,$y);
   
$aImg->SetColor($this->iColor); $aImg->SetColor($this->iColor);
$aImg->Polygon($c); $aImg->Polygon($c);
$aImg->FilledPolygon($ca); $aImg->FilledPolygon($ca);
   
$aImg->SetCenter($old_origin[0],$old_origin[1]); $aImg->SetCenter($old_origin[0],$old_origin[1]);
$aImg->SetAngle($old_a); $aImg->SetAngle($old_a);
} }
} }
   
//=================================================== //===================================================
// CLASS FieldPlot // CLASS FieldPlot
// Description: Render a field plot // Description: Render a field plot
//=================================================== //===================================================
class FieldPlot extends Plot { class FieldPlot extends Plot {
public $arrow = ''; public $arrow = '';
private $iAngles = array(); private $iAngles = array();
private $iCallback = ''; private $iCallback = '';
   
function __construct($datay,$datax,$angles) { function __construct($datay,$datax,$angles) {
if( (count($datax) != count($datay)) ) if( (count($datax) != count($datay)) )
JpGraphError::RaiseL(20001);//("Fieldplots must have equal number of X and Y points."); JpGraphError::RaiseL(20001);//("Fieldplots must have equal number of X and Y points.");
if( (count($datax) != count($angles)) ) if( (count($datax) != count($angles)) )
JpGraphError::RaiseL(20002);//("Fieldplots must have an angle specified for each X and Y points."); JpGraphError::RaiseL(20002);//("Fieldplots must have an angle specified for each X and Y points.");
   
$this->iAngles = $angles; $this->iAngles = $angles;
   
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
$this->value->SetAlign('center','center'); $this->value->SetAlign('center','center');
$this->value->SetMargin(15); $this->value->SetMargin(15);
   
$this->arrow = new FieldArrow(); $this->arrow = new FieldArrow();
} }
   
function SetCallback($aFunc) { function SetCallback($aFunc) {
$this->iCallback = $aFunc; $this->iCallback = $aFunc;
} }
   
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
   
// Remeber base color and size // Remeber base color and size
$bc = $this->arrow->iColor; $bc = $this->arrow->iColor;
$bs = $this->arrow->iSize; $bs = $this->arrow->iSize;
$bas = $this->arrow->iArrowSize; $bas = $this->arrow->iArrowSize;
   
for( $i=0; $i<$this->numpoints; ++$i ) { for( $i=0; $i<$this->numpoints; ++$i ) {
// Skip null values // Skip null values
if( $this->coords[0][$i]==="" ) if( $this->coords[0][$i]==="" )
continue; continue;
   
$f = $this->iCallback; $f = $this->iCallback;
if( $f != "" ) { if( $f != "" ) {
list($cc,$cs,$cas) = call_user_func($f,$this->coords[1][$i],$this->coords[0][$i],$this->iAngles[$i]); 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 // Fall back on global data if the callback isn't set
if( $cc == "" ) $cc = $bc; if( $cc == "" ) $cc = $bc;
if( $cs == "" ) $cs = $bs; if( $cs == "" ) $cs = $bs;
if( $cas == "" ) $cas = $bas; if( $cas == "" ) $cas = $bas;
$this->arrow->SetColor($cc); $this->arrow->SetColor($cc);
$this->arrow->SetSize($cs,$cas); $this->arrow->SetSize($cs,$cas);
} }
   
$xt = $xscale->Translate($this->coords[1][$i]); $xt = $xscale->Translate($this->coords[1][$i]);
$yt = $yscale->Translate($this->coords[0][$i]); $yt = $yscale->Translate($this->coords[0][$i]);
   
$this->arrow->Stroke($img,$xt,$yt,$this->iAngles[$i]); $this->arrow->Stroke($img,$xt,$yt,$this->iAngles[$i]);
$this->value->Stroke($img,$this->coords[0][$i],$xt,$yt); $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt);
} }
} }
   
// Framework function // Framework function
function Legend($aGraph) { function Legend($aGraph) {
if( $this->legend != "" ) { if( $this->legend != "" ) {
$aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0, $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
} }
} }
   
//=================================================== //===================================================
// CLASS ScatterPlot // CLASS ScatterPlot
// Description: Render X and Y plots // Description: Render X and Y plots
//=================================================== //===================================================
class ScatterPlot extends Plot { class ScatterPlot extends Plot {
public $mark,$link; public $mark,$link;
private $impuls = false; private $impuls = false;
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
if( (count($datax) != count($datay)) && is_array($datax)) { if( (count($datax) != count($datay)) && is_array($datax)) {
JpGraphError::RaiseL(20003);//("Scatterplot must have equal number of X and Y points."); JpGraphError::RaiseL(20003);//("Scatterplot must have equal number of X and Y points.");
} }
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
$this->mark = new PlotMark(); $this->mark = new PlotMark();
$this->mark->SetType(MARK_SQUARE); $this->mark->SetType(MARK_SQUARE);
$this->mark->SetColor($this->color); $this->mark->SetColor($this->color);
$this->value->SetAlign('center','center'); $this->value->SetAlign('center','center');
$this->value->SetMargin(0); $this->value->SetMargin(0);
$this->link = new LineProperty(1,'black','solid'); $this->link = new LineProperty(1,'black','solid');
$this->link->iShow = false; $this->link->iShow = false;
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
function SetImpuls($f=true) { function SetImpuls($f=true) {
$this->impuls = $f; $this->impuls = $f;
} }
   
function SetStem($f=true) { function SetStem($f=true) {
$this->impuls = $f; $this->impuls = $f;
} }
   
// Combine the scatter plot points with a line // Combine the scatter plot points with a line
function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1,$aStyle='solid') { function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1,$aStyle='solid') {
$this->link->iShow = $aFlag; $this->link->iShow = $aFlag;
$this->link->iColor = $aColor; $this->link->iColor = $aColor;
$this->link->iWeight = $aWeight; $this->link->iWeight = $aWeight;
$this->link->iStyle = $aStyle; $this->link->iStyle = $aStyle;
} }
   
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
   
$ymin=$yscale->scale_abs[0]; $ymin=$yscale->scale_abs[0];
if( $yscale->scale[0] < 0 ) if( $yscale->scale[0] < 0 )
$yzero=$yscale->Translate(0); $yzero=$yscale->Translate(0);
else else
$yzero=$yscale->scale_abs[0]; $yzero=$yscale->scale_abs[0];
   
$this->csimareas = ''; $this->csimareas = '';
for( $i=0; $i<$this->numpoints; ++$i ) { for( $i=0; $i<$this->numpoints; ++$i ) {
   
// Skip null values // Skip null values
if( $this->coords[0][$i]==='' || $this->coords[0][$i]==='-' || $this->coords[0][$i]==='x') if( $this->coords[0][$i]==='' || $this->coords[0][$i]==='-' || $this->coords[0][$i]==='x')
continue; continue;
   
if( isset($this->coords[1]) ) if( isset($this->coords[1]) )
$xt = $xscale->Translate($this->coords[1][$i]); $xt = $xscale->Translate($this->coords[1][$i]);
else else
$xt = $xscale->Translate($i); $xt = $xscale->Translate($i);
$yt = $yscale->Translate($this->coords[0][$i]); $yt = $yscale->Translate($this->coords[0][$i]);
   
   
if( $this->link->iShow && isset($yt_old) ) { if( $this->link->iShow && isset($yt_old) ) {
$img->SetColor($this->link->iColor); $img->SetColor($this->link->iColor);
$img->SetLineWeight($this->link->iWeight); $img->SetLineWeight($this->link->iWeight);
$old = $img->SetLineStyle($this->link->iStyle); $old = $img->SetLineStyle($this->link->iStyle);
$img->StyleLine($xt_old,$yt_old,$xt,$yt); $img->StyleLine($xt_old,$yt_old,$xt,$yt);
$img->SetLineStyle($old); $img->SetLineStyle($old);
} }
   
if( $this->impuls ) { if( $this->impuls ) {
$img->SetColor($this->color); $img->SetColor($this->color);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
$img->Line($xt,$yzero,$xt,$yt); $img->Line($xt,$yzero,$xt,$yt);
} }
   
if( !empty($this->csimtargets[$i]) ) { if( !empty($this->csimtargets[$i]) ) {
if( !empty($this->csimwintargets[$i]) ) { if( !empty($this->csimwintargets[$i]) ) {
$this->mark->SetCSIMTarget($this->csimtargets[$i],$this->csimwintargets[$i]); $this->mark->SetCSIMTarget($this->csimtargets[$i],$this->csimwintargets[$i]);
} }
else { else {
$this->mark->SetCSIMTarget($this->csimtargets[$i]); $this->mark->SetCSIMTarget($this->csimtargets[$i]);
} }
$this->mark->SetCSIMAlt($this->csimalts[$i]); $this->mark->SetCSIMAlt($this->csimalts[$i]);
} }
   
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
$this->mark->SetCSIMAltVal($this->coords[0][$i],$this->coords[1][$i]); $this->mark->SetCSIMAltVal($this->coords[0][$i],$this->coords[1][$i]);
} }
else { else {
$this->mark->SetCSIMAltVal($this->coords[0][$i],$i); $this->mark->SetCSIMAltVal($this->coords[0][$i],$i);
} }
   
$this->mark->Stroke($img,$xt,$yt); $this->mark->Stroke($img,$xt,$yt);
   
$this->csimareas .= $this->mark->GetCSIMAreas(); $this->csimareas .= $this->mark->GetCSIMAreas();
$this->value->Stroke($img,$this->coords[0][$i],$xt,$yt); $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt);
   
$xt_old = $xt; $xt_old = $xt;
$yt_old = $yt; $yt_old = $yt;
} }
} }
   
// Framework function // Framework function
function Legend($aGraph) { function Legend($aGraph) {
if( $this->legend != "" ) { if( $this->legend != "" ) {
$aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0, $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0,
$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
} }
} }
} // Class } // Class
/* EOF */ /* EOF */
?> ?>
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_STOCK.PHP // File: JPGRAPH_STOCK.PHP
// Description: Stock plot extension for JpGraph // Description: Stock plot extension for JpGraph
// Created: 2003-01-27 // Created: 2003-01-27
// Ver: $Id: jpgraph_stock.php 1364 2009-06-24 07:07:44Z ljp $ // Ver: $Id: jpgraph_stock.php 1364 2009-06-24 07:07:44Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
//=================================================== //===================================================
// CLASS StockPlot // CLASS StockPlot
//=================================================== //===================================================
class StockPlot extends Plot { class StockPlot extends Plot {
protected $iTupleSize = 4; protected $iTupleSize = 4;
private $iWidth=9; private $iWidth=9;
private $iEndLines=1; private $iEndLines=1;
private $iStockColor1='white',$iStockColor2='darkred',$iStockColor3='darkred'; private $iStockColor1='white',$iStockColor2='darkred',$iStockColor3='darkred';
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
if( count($datay) % $this->iTupleSize ) { if( count($datay) % $this->iTupleSize ) {
JpGraphError::RaiseL(21001,$this->iTupleSize); JpGraphError::RaiseL(21001,$this->iTupleSize);
//('Data values for Stock charts must contain an even multiple of '.$this->iTupleSize.' data points.'); //('Data values for Stock charts must contain an even multiple of '.$this->iTupleSize.' data points.');
} }
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
$this->numpoints /= $this->iTupleSize; $this->numpoints /= $this->iTupleSize;
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
   
function SetColor($aColor,$aColor1='white',$aColor2='darkred',$aColor3='darkred') { function SetColor($aColor,$aColor1='white',$aColor2='darkred',$aColor3='darkred') {
$this->color = $aColor; $this->color = $aColor;
$this->iStockColor1 = $aColor1; $this->iStockColor1 = $aColor1;
$this->iStockColor2 = $aColor2; $this->iStockColor2 = $aColor2;
$this->iStockColor3 = $aColor3; $this->iStockColor3 = $aColor3;
} }
   
function SetWidth($aWidth) { function SetWidth($aWidth) {
// Make sure it's odd // Make sure it's odd
$this->iWidth = 2*floor($aWidth/2)+1; $this->iWidth = 2*floor($aWidth/2)+1;
} }
   
function HideEndLines($aHide=true) { function HideEndLines($aHide=true) {
$this->iEndLines = !$aHide; $this->iEndLines = !$aHide;
} }
   
// Gets called before any axis are stroked // Gets called before any axis are stroked
function PreStrokeAdjust($graph) { function PreStrokeAdjust($graph) {
if( $this->center ) { if( $this->center ) {
$a=0.5; $b=0.5; $a=0.5; $b=0.5;
$this->numpoints++; $this->numpoints++;
} else { } else {
$a=0; $b=0; $a=0; $b=0;
} }
$graph->xaxis->scale->ticks->SetXLabelOffset($a); $graph->xaxis->scale->ticks->SetXLabelOffset($a);
$graph->SetTextScaleOff($b); $graph->SetTextScaleOff($b);
} }
   
// Method description // Method description
function Stroke($img,$xscale,$yscale) { function Stroke($img,$xscale,$yscale) {
$n=$this->numpoints; $n=$this->numpoints;
if( $this->center ) $n--; if( $this->center ) $n--;
if( isset($this->coords[1]) ) { if( isset($this->coords[1]) ) {
if( count($this->coords[1])!=$n ) { if( count($this->coords[1])!=$n ) {
JpGraphError::RaiseL(2003,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"); // ("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
} }
else { else {
$exist_x = true; $exist_x = true;
} }
} }
else { else {
$exist_x = false; $exist_x = false;
} }
   
if( $exist_x ) { if( $exist_x ) {
$xs=$this->coords[1][0]; $xs=$this->coords[1][0];
} }
else { else {
$xs=0; $xs=0;
} }
   
$ts = $this->iTupleSize; $ts = $this->iTupleSize;
$this->csimareas = ''; $this->csimareas = '';
for( $i=0; $i<$n; ++$i) { for( $i=0; $i<$n; ++$i) {
   
//If value is NULL, then don't draw a bar at all //If value is NULL, then don't draw a bar at all
if ($this->coords[0][$i*$ts] === null) continue; if ($this->coords[0][$i*$ts] === null) continue;
   
if( $exist_x ) { if( $exist_x ) {
$x=$this->coords[1][$i]; $x=$this->coords[1][$i];
if ($x === null) continue; if ($x === null) continue;
} }
else { else {
$x=$i; $x=$i;
} }
$xt = $xscale->Translate($x); $xt = $xscale->Translate($x);
   
$neg = $this->coords[0][$i*$ts] > $this->coords[0][$i*$ts+1] ; $neg = $this->coords[0][$i*$ts] > $this->coords[0][$i*$ts+1] ;
$yopen = $yscale->Translate($this->coords[0][$i*$ts]); $yopen = $yscale->Translate($this->coords[0][$i*$ts]);
$yclose = $yscale->Translate($this->coords[0][$i*$ts+1]); $yclose = $yscale->Translate($this->coords[0][$i*$ts+1]);
$ymin = $yscale->Translate($this->coords[0][$i*$ts+2]); $ymin = $yscale->Translate($this->coords[0][$i*$ts+2]);
$ymax = $yscale->Translate($this->coords[0][$i*$ts+3]); $ymax = $yscale->Translate($this->coords[0][$i*$ts+3]);
   
$dx = floor($this->iWidth/2); $dx = floor($this->iWidth/2);
$xl = $xt - $dx; $xl = $xt - $dx;
$xr = $xt + $dx; $xr = $xt + $dx;
   
if( $neg ) { if( $neg ) {
$img->SetColor($this->iStockColor3); $img->SetColor($this->iStockColor3);
} }
else { else {
$img->SetColor($this->iStockColor1); $img->SetColor($this->iStockColor1);
} }
$img->FilledRectangle($xl,$yopen,$xr,$yclose); $img->FilledRectangle($xl,$yopen,$xr,$yclose);
$img->SetLineWeight($this->weight); $img->SetLineWeight($this->weight);
if( $neg ) { if( $neg ) {
$img->SetColor($this->iStockColor2); $img->SetColor($this->iStockColor2);
} }
else { else {
$img->SetColor($this->color); $img->SetColor($this->color);
} }
   
$img->Rectangle($xl,$yopen,$xr,$yclose); $img->Rectangle($xl,$yopen,$xr,$yclose);
   
if( $yopen < $yclose ) { if( $yopen < $yclose ) {
$ytop = $yopen ; $ytop = $yopen ;
$ybottom = $yclose ; $ybottom = $yclose ;
} }
else { else {
$ytop = $yclose ; $ytop = $yclose ;
$ybottom = $yopen ; $ybottom = $yopen ;
} }
$img->SetColor($this->color); $img->SetColor($this->color);
$img->Line($xt,$ytop,$xt,$ymax); $img->Line($xt,$ytop,$xt,$ymax);
$img->Line($xt,$ybottom,$xt,$ymin); $img->Line($xt,$ybottom,$xt,$ymin);
   
if( $this->iEndLines ) { if( $this->iEndLines ) {
$img->Line($xl,$ymax,$xr,$ymax); $img->Line($xl,$ymax,$xr,$ymax);
$img->Line($xl,$ymin,$xr,$ymin); $img->Line($xl,$ymin,$xr,$ymin);
} }
   
// A chance for subclasses to add things to the bar // A chance for subclasses to add things to the bar
// for data point i // for data point i
$this->ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg); $this->ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg);
   
// Setup image maps // Setup image maps
if( !empty($this->csimtargets[$i]) ) { if( !empty($this->csimtargets[$i]) ) {
$this->csimareas.= '<area shape="rect" coords="'. $this->csimareas.= '<area shape="rect" coords="'.
round($xl).','.round($ytop).','. round($xl).','.round($ytop).','.
round($xr).','.round($ybottom).'" '; round($xr).','.round($ybottom).'" ';
$this->csimareas .= ' href="'.$this->csimtargets[$i].'"'; $this->csimareas .= ' href="'.$this->csimtargets[$i].'"';
if( !empty($this->csimalts[$i]) ) { if( !empty($this->csimalts[$i]) ) {
$sval=$this->csimalts[$i]; $sval=$this->csimalts[$i];
$this->csimareas .= " title=\"$sval\" alt=\"$sval\" "; $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
} }
$this->csimareas.= " />\n"; $this->csimareas.= " />\n";
} }
} }
return true; return true;
} }
   
// A hook for subclasses to modify the plot // A hook for subclasses to modify the plot
function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {} function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {}
   
} // Class } // Class
   
//=================================================== //===================================================
// CLASS BoxPlot // CLASS BoxPlot
//=================================================== //===================================================
class BoxPlot extends StockPlot { class BoxPlot extends StockPlot {
private $iPColor='black',$iNColor='white'; private $iPColor='black',$iNColor='white';
   
function __construct($datay,$datax=false) { function __construct($datay,$datax=false) {
$this->iTupleSize=5; $this->iTupleSize=5;
parent::__construct($datay,$datax); parent::__construct($datay,$datax);
} }
   
function SetMedianColor($aPos,$aNeg) { function SetMedianColor($aPos,$aNeg) {
$this->iPColor = $aPos; $this->iPColor = $aPos;
$this->iNColor = $aNeg; $this->iNColor = $aNeg;
} }
   
function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) { function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {
if( $neg ) if( $neg )
$img->SetColor($this->iNColor); $img->SetColor($this->iNColor);
else else
$img->SetColor($this->iPColor); $img->SetColor($this->iPColor);
   
$y = $yscale->Translate($this->coords[0][$i*5+4]); $y = $yscale->Translate($this->coords[0][$i*5+4]);
$img->Line($xl,$y,$xr,$y); $img->Line($xl,$y,$xr,$y);
} }
} }
   
/* EOF */ /* EOF */
?> ?>
<?php <?php
//======================================================================= //=======================================================================
// File: JPGRAPH_TEXT.INC.PHP // File: JPGRAPH_TEXT.INC.PHP
// Description: Class to handle text as object in the graph. // Description: Class to handle text as object in the graph.
// The low level text layout engine is handled by the GD class // The low level text layout engine is handled by the GD class
// Created: 2001-01-08 (Refactored to separate file 2008-08-01) // Created: 2001-01-08 (Refactored to separate file 2008-08-01)
// Ver: $Id: jpgraph_text.inc.php 1844 2009-09-26 17:05:31Z ljp $ // Ver: $Id: jpgraph_text.inc.php 1844 2009-09-26 17:05:31Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
   
//=================================================== //===================================================
// CLASS Text // CLASS Text
// Description: Arbitrary text object that can be added to the graph // Description: Arbitrary text object that can be added to the graph
//=================================================== //===================================================
class Text { class Text {
public $t,$margin=0; public $t,$margin=0;
public $x=0,$y=0,$halign="left",$valign="top",$color=array(0,0,0); public $x=0,$y=0,$halign="left",$valign="top",$color=array(0,0,0);
public $hide=false, $dir=0; public $hide=false, $dir=0;
public $iScalePosY=null,$iScalePosX=null; public $iScalePosY=null,$iScalePosX=null;
public $iWordwrap=0; public $iWordwrap=0;
public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12; public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12;
protected $boxed=false; // Should the text be boxed protected $boxed=false; // Should the text be boxed
protected $paragraph_align="left"; protected $paragraph_align="left";
protected $icornerradius=0,$ishadowwidth=3; protected $icornerradius=0,$ishadowwidth=3;
protected $fcolor='white',$bcolor='black',$shadow=false; protected $fcolor='white',$bcolor='black',$shadow=false;
protected $iCSIMarea='',$iCSIMalt='',$iCSIMtarget='',$iCSIMWinTarget=''; protected $iCSIMarea='',$iCSIMalt='',$iCSIMtarget='',$iCSIMWinTarget='';
private $iBoxType = 1; // Which variant of filled box around text we want private $iBoxType = 1; // Which variant of filled box around text we want
   
//--------------- //---------------
// CONSTRUCTOR // CONSTRUCTOR
   
// Create new text at absolute pixel coordinates // Create new text at absolute pixel coordinates
function __construct($aTxt="",$aXAbsPos=0,$aYAbsPos=0) { function __construct($aTxt="",$aXAbsPos=0,$aYAbsPos=0) {
if( ! is_string($aTxt) ) { if( ! is_string($aTxt) ) {
JpGraphError::RaiseL(25050);//('First argument to Text::Text() must be s atring.'); JpGraphError::RaiseL(25050);//('First argument to Text::Text() must be s atring.');
} }
$this->t = $aTxt; $this->t = $aTxt;
$this->x = round($aXAbsPos); $this->x = round($aXAbsPos);
$this->y = round($aYAbsPos); $this->y = round($aYAbsPos);
$this->margin = 0; $this->margin = 0;
} }
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
// Set the string in the text object // Set the string in the text object
function Set($aTxt) { function Set($aTxt) {
$this->t = $aTxt; $this->t = $aTxt;
} }
   
// Alias for Pos() // Alias for Pos()
function SetPos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") { function SetPos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") {
//$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign); //$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign);
$this->x = $aXAbsPos; $this->x = $aXAbsPos;
$this->y = $aYAbsPos; $this->y = $aYAbsPos;
$this->halign = $aHAlign; $this->halign = $aHAlign;
$this->valign = $aVAlign; $this->valign = $aVAlign;
} }
   
function SetScalePos($aX,$aY) { function SetScalePos($aX,$aY) {
$this->iScalePosX = $aX; $this->iScalePosX = $aX;
$this->iScalePosY = $aY; $this->iScalePosY = $aY;
} }
   
// Specify alignment for the text // Specify alignment for the text
function Align($aHAlign,$aVAlign="top",$aParagraphAlign="") { function Align($aHAlign,$aVAlign="top",$aParagraphAlign="") {
$this->halign = $aHAlign; $this->halign = $aHAlign;
$this->valign = $aVAlign; $this->valign = $aVAlign;
if( $aParagraphAlign != "" ) if( $aParagraphAlign != "" )
$this->paragraph_align = $aParagraphAlign; $this->paragraph_align = $aParagraphAlign;
} }
   
// Alias // Alias
function SetAlign($aHAlign,$aVAlign="top",$aParagraphAlign="") { function SetAlign($aHAlign,$aVAlign="top",$aParagraphAlign="") {
$this->Align($aHAlign,$aVAlign,$aParagraphAlign); $this->Align($aHAlign,$aVAlign,$aParagraphAlign);
} }
   
// Specifies the alignment for a multi line text // Specifies the alignment for a multi line text
function ParagraphAlign($aAlign) { function ParagraphAlign($aAlign) {
$this->paragraph_align = $aAlign; $this->paragraph_align = $aAlign;
} }
   
// Specifies the alignment for a multi line text // Specifies the alignment for a multi line text
function SetParagraphAlign($aAlign) { function SetParagraphAlign($aAlign) {
$this->paragraph_align = $aAlign; $this->paragraph_align = $aAlign;
} }
   
function SetShadow($aShadowColor='gray',$aShadowWidth=3) { function SetShadow($aShadowColor='gray',$aShadowWidth=3) {
$this->ishadowwidth=$aShadowWidth; $this->ishadowwidth=$aShadowWidth;
$this->shadow=$aShadowColor; $this->shadow=$aShadowColor;
$this->boxed=true; $this->boxed=true;
} }
   
function SetWordWrap($aCol) { function SetWordWrap($aCol) {
$this->iWordwrap = $aCol ; $this->iWordwrap = $aCol ;
} }
   
// Specify that the text should be boxed. fcolor=frame color, bcolor=border color, // Specify that the text should be boxed. fcolor=frame color, bcolor=border color,
// $shadow=drop shadow should be added around the text. // $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) { function SetBox($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) {
if( $aFrameColor === false ) { if( $aFrameColor === false ) {
$this->boxed=false; $this->boxed=false;
} }
else { else {
$this->boxed=true; $this->boxed=true;
} }
$this->fcolor=$aFrameColor; $this->fcolor=$aFrameColor;
$this->bcolor=$aBorderColor; $this->bcolor=$aBorderColor;
// For backwards compatibility when shadow was just true or false // For backwards compatibility when shadow was just true or false
if( $aShadowColor === true ) { if( $aShadowColor === true ) {
$aShadowColor = 'gray'; $aShadowColor = 'gray';
} }
$this->shadow=$aShadowColor; $this->shadow=$aShadowColor;
$this->icornerradius=$aCornerRadius; $this->icornerradius=$aCornerRadius;
$this->ishadowwidth=$aShadowWidth; $this->ishadowwidth=$aShadowWidth;
} }
   
function SetBox2($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) { function SetBox2($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) {
$this->iBoxType=2; $this->iBoxType=2;
$this->SetBox($aFrameColor,$aBorderColor,$aShadowColor,$aCornerRadius,$aShadowWidth); $this->SetBox($aFrameColor,$aBorderColor,$aShadowColor,$aCornerRadius,$aShadowWidth);
} }
   
// Hide the text // Hide the text
function Hide($aHide=true) { function Hide($aHide=true) {
$this->hide=$aHide; $this->hide=$aHide;
} }
   
// This looks ugly since it's not a very orthogonal design // This looks ugly since it's not a very orthogonal design
// but I added this "inverse" of Hide() to harmonize // but I added this "inverse" of Hide() to harmonize
// with some classes which I designed more recently (especially) // with some classes which I designed more recently (especially)
// jpgraph_gantt // jpgraph_gantt
function Show($aShow=true) { function Show($aShow=true) {
$this->hide=!$aShow; $this->hide=!$aShow;
} }
   
// Specify font // Specify font
function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) { function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
$this->font_family=$aFamily; $this->font_family=$aFamily;
$this->font_style=$aStyle; $this->font_style=$aStyle;
$this->font_size=$aSize; $this->font_size=$aSize;
} }
   
// Center the text between $left and $right coordinates // Center the text between $left and $right coordinates
function Center($aLeft,$aRight,$aYAbsPos=false) { function Center($aLeft,$aRight,$aYAbsPos=false) {
$this->x = $aLeft + ($aRight-$aLeft )/2; $this->x = $aLeft + ($aRight-$aLeft )/2;
$this->halign = "center"; $this->halign = "center";
if( is_numeric($aYAbsPos) ) if( is_numeric($aYAbsPos) )
$this->y = $aYAbsPos; $this->y = $aYAbsPos;
} }
   
// Set text color // Set text color
function SetColor($aColor) { function SetColor($aColor) {
$this->color = $aColor; $this->color = $aColor;
} }
   
function SetAngle($aAngle) { function SetAngle($aAngle) {
$this->SetOrientation($aAngle); $this->SetOrientation($aAngle);
} }
   
// Orientation of text. Note only TTF fonts can have an arbitrary angle // Orientation of text. Note only TTF fonts can have an arbitrary angle
function SetOrientation($aDirection=0) { function SetOrientation($aDirection=0) {
if( is_numeric($aDirection) ) if( is_numeric($aDirection) )
$this->dir=$aDirection; $this->dir=$aDirection;
elseif( $aDirection=="h" ) elseif( $aDirection=="h" )
$this->dir = 0; $this->dir = 0;
elseif( $aDirection=="v" ) elseif( $aDirection=="v" )
$this->dir = 90; $this->dir = 90;
else else
JpGraphError::RaiseL(25051);//(" Invalid direction specified for text."); JpGraphError::RaiseL(25051);//(" Invalid direction specified for text.");
} }
   
// Total width of text // Total width of text
function GetWidth($aImg) { function GetWidth($aImg) {
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$w = $aImg->GetTextWidth($this->t,$this->dir); $w = $aImg->GetTextWidth($this->t,$this->dir);
return $w; return $w;
} }
   
// Hight of font // Hight of font
function GetFontHeight($aImg) { function GetFontHeight($aImg) {
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$h = $aImg->GetFontHeight(); $h = $aImg->GetFontHeight();
return $h; return $h;
   
} }
   
function GetTextHeight($aImg) { function GetTextHeight($aImg) {
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$h = $aImg->GetTextHeight($this->t,$this->dir); $h = $aImg->GetTextHeight($this->t,$this->dir);
return $h; return $h;
} }
   
function GetHeight($aImg) { function GetHeight($aImg) {
// Synonym for GetTextHeight() // Synonym for GetTextHeight()
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$h = $aImg->GetTextHeight($this->t,$this->dir); $h = $aImg->GetTextHeight($this->t,$this->dir);
return $h; return $h;
} }
   
// Set the margin which will be interpretated differently depending // Set the margin which will be interpretated differently depending
// on the context. // on the context.
function SetMargin($aMarg) { function SetMargin($aMarg) {
$this->margin = $aMarg; $this->margin = $aMarg;
} }
   
function StrokeWithScale($aImg,$axscale,$ayscale) { function StrokeWithScale($aImg,$axscale,$ayscale) {
if( $this->iScalePosX === null || $this->iScalePosY === null ) { if( $this->iScalePosX === null || $this->iScalePosY === null ) {
$this->Stroke($aImg); $this->Stroke($aImg);
} }
else { else {
$this->Stroke($aImg, $this->Stroke($aImg,
round($axscale->Translate($this->iScalePosX)), round($axscale->Translate($this->iScalePosX)),
round($ayscale->Translate($this->iScalePosY))); round($ayscale->Translate($this->iScalePosY)));
} }
} }
   
function SetCSIMTarget($aURITarget,$aAlt='',$aWinTarget='') { function SetCSIMTarget($aURITarget,$aAlt='',$aWinTarget='') {
$this->iCSIMtarget = $aURITarget; $this->iCSIMtarget = $aURITarget;
$this->iCSIMalt = $aAlt; $this->iCSIMalt = $aAlt;
$this->iCSIMWinTarget = $aWinTarget; $this->iCSIMWinTarget = $aWinTarget;
} }
   
function GetCSIMareas() { function GetCSIMareas() {
if( $this->iCSIMtarget !== '' ) { if( $this->iCSIMtarget !== '' ) {
return $this->iCSIMarea; return $this->iCSIMarea;
} }
else { else {
return ''; return '';
} }
} }
   
// Display text in image // Display text in image
function Stroke($aImg,$x=null,$y=null) { function Stroke($aImg,$x=null,$y=null) {
   
if( $x !== null ) $this->x = round($x); if( $x !== null ) $this->x = round($x);
if( $y !== null ) $this->y = round($y); if( $y !== null ) $this->y = round($y);
   
// Insert newlines // Insert newlines
if( $this->iWordwrap > 0 ) { if( $this->iWordwrap > 0 ) {
$this->t = wordwrap($this->t,$this->iWordwrap,"\n"); $this->t = wordwrap($this->t,$this->iWordwrap,"\n");
} }
   
// If position been given as a fraction of the image size // If position been given as a fraction of the image size
// calculate the absolute position // calculate the absolute position
if( $this->x < 1 && $this->x > 0 ) $this->x *= $aImg->width; if( $this->x < 1 && $this->x > 0 ) $this->x *= $aImg->width;
if( $this->y < 1 && $this->y > 0 ) $this->y *= $aImg->height; if( $this->y < 1 && $this->y > 0 ) $this->y *= $aImg->height;
   
$aImg->PushColor($this->color); $aImg->PushColor($this->color);
$aImg->SetFont($this->font_family,$this->font_style,$this->font_size); $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
$aImg->SetTextAlign($this->halign,$this->valign); $aImg->SetTextAlign($this->halign,$this->valign);
   
if( $this->boxed ) { if( $this->boxed ) {
if( $this->fcolor=="nofill" ) { if( $this->fcolor=="nofill" ) {
$this->fcolor=false; $this->fcolor=false;
} }
   
$oldweight=$aImg->SetLineWeight(1); $oldweight=$aImg->SetLineWeight(1);
   
if( $this->iBoxType == 2 && $this->font_family > FF_FONT2+2 ) { if( $this->iBoxType == 2 && $this->font_family > FF_FONT2+2 ) {
   
$bbox = $aImg->StrokeBoxedText2($this->x, $this->y, $bbox = $aImg->StrokeBoxedText2($this->x, $this->y,
$this->t, $this->dir, $this->t, $this->dir,
$this->fcolor, $this->fcolor,
$this->bcolor, $this->bcolor,
$this->shadow, $this->shadow,
$this->paragraph_align, $this->paragraph_align,
2,4, 2,4,
$this->icornerradius, $this->icornerradius,
$this->ishadowwidth); $this->ishadowwidth);
} }
else { else {
$bbox = $aImg->StrokeBoxedText($this->x,$this->y,$this->t, $bbox = $aImg->StrokeBoxedText($this->x,$this->y,$this->t,
$this->dir,$this->fcolor,$this->bcolor,$this->shadow, $this->dir,$this->fcolor,$this->bcolor,$this->shadow,
$this->paragraph_align,3,3,$this->icornerradius, $this->paragraph_align,3,3,$this->icornerradius,
$this->ishadowwidth); $this->ishadowwidth);
} }
   
$aImg->SetLineWeight($oldweight); $aImg->SetLineWeight($oldweight);
} }
else { else {
$debug=false; $debug=false;
$bbox = $aImg->StrokeText($this->x,$this->y,$this->t,$this->dir,$this->paragraph_align,$debug); $bbox = $aImg->StrokeText($this->x,$this->y,$this->t,$this->dir,$this->paragraph_align,$debug);
} }
   
// Create CSIM targets // Create CSIM targets
$coords = $bbox[0].','.$bbox[1].','.$bbox[2].','.$bbox[3].','.$bbox[4].','.$bbox[5].','.$bbox[6].','.$bbox[7]; $coords = $bbox[0].','.$bbox[1].','.$bbox[2].','.$bbox[3].','.$bbox[4].','.$bbox[5].','.$bbox[6].','.$bbox[7];
$this->iCSIMarea = "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->iCSIMtarget)."\" "; $this->iCSIMarea = "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->iCSIMtarget)."\" ";
if( trim($this->iCSIMalt) != '' ) { if( trim($this->iCSIMalt) != '' ) {
$this->iCSIMarea .= " alt=\"".$this->iCSIMalt."\" "; $this->iCSIMarea .= " alt=\"".$this->iCSIMalt."\" ";
$this->iCSIMarea .= " title=\"".$this->iCSIMalt."\" "; $this->iCSIMarea .= " title=\"".$this->iCSIMalt."\" ";
} }
if( trim($this->iCSIMWinTarget) != '' ) { if( trim($this->iCSIMWinTarget) != '' ) {
$this->iCSIMarea .= " target=\"".$this->iCSIMWinTarget."\" "; $this->iCSIMarea .= " target=\"".$this->iCSIMWinTarget."\" ";
} }
$this->iCSIMarea .= " />\n"; $this->iCSIMarea .= " />\n";
   
$aImg->PopColor($this->color); $aImg->PopColor($this->color);
} }
} // Class } // Class
   
   
?> ?>
   
<?php <?php
//======================================================================= //=======================================================================
// File: jpgraph_ttf.inc.php // File: jpgraph_ttf.inc.php
// Description: Handling of TTF fonts // Description: Handling of TTF fonts
// Created: 2006-11-19 // Created: 2006-11-19
// Ver: $Id: jpgraph_ttf.inc.php 1858 2009-09-28 14:39:51Z ljp $ // Ver: $Id: jpgraph_ttf.inc.php 1858 2009-09-28 14:39:51Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
   
// TTF Font families // TTF Font families
define("FF_COURIER",10); define("FF_COURIER",10);
define("FF_VERDANA",11); define("FF_VERDANA",11);
define("FF_TIMES",12); define("FF_TIMES",12);
define("FF_COMIC",14); define("FF_COMIC",14);
define("FF_ARIAL",15); define("FF_ARIAL",15);
define("FF_GEORGIA",16); define("FF_GEORGIA",16);
define("FF_TREBUCHE",17); define("FF_TREBUCHE",17);
   
// Gnome Vera font // Gnome Vera font
// Available from http://www.gnome.org/fonts/ // Available from http://www.gnome.org/fonts/
define("FF_VERA",18); define("FF_VERA",18);
define("FF_VERAMONO",19); define("FF_VERAMONO",19);
define("FF_VERASERIF",20); define("FF_VERASERIF",20);
   
// Chinese font // Chinese font
define("FF_SIMSUN",30); define("FF_SIMSUN",30);
define("FF_CHINESE",31); define("FF_CHINESE",31);
define("FF_BIG5",32); define("FF_BIG5",32);
   
// Japanese font // Japanese font
define("FF_MINCHO",40); define("FF_MINCHO",40);
define("FF_PMINCHO",41); define("FF_PMINCHO",41);
define("FF_GOTHIC",42); define("FF_GOTHIC",42);
define("FF_PGOTHIC",43); define("FF_PGOTHIC",43);
   
// Hebrew fonts // Hebrew fonts
define("FF_DAVID",44); define("FF_DAVID",44);
define("FF_MIRIAM",45); define("FF_MIRIAM",45);
define("FF_AHRON",46); define("FF_AHRON",46);
   
// Dejavu-fonts http://sourceforge.net/projects/dejavu // Dejavu-fonts http://sourceforge.net/projects/dejavu
define("FF_DV_SANSSERIF",47); define("FF_DV_SANSSERIF",47);
define("FF_DV_SERIF",48); define("FF_DV_SERIF",48);
define("FF_DV_SANSSERIFMONO",49); define("FF_DV_SANSSERIFMONO",49);
define("FF_DV_SERIFCOND",50); define("FF_DV_SERIFCOND",50);
define("FF_DV_SANSSERIFCOND",51); define("FF_DV_SANSSERIFCOND",51);
   
// Extra fonts // Extra fonts
// Download fonts from // Download fonts from
// http://www.webfontlist.com // http://www.webfontlist.com
// http://www.webpagepublicity.com/free-fonts.html // http://www.webpagepublicity.com/free-fonts.html
// http://www.fontonic.com/fonts.asp?width=d&offset=120 // http://www.fontonic.com/fonts.asp?width=d&offset=120
// http://www.fontspace.com/category/famous // http://www.fontspace.com/category/famous
   
// define("FF_SPEEDO",71); // This font is also known as Bauer (Used for development gauge fascia) // define("FF_SPEEDO",71); // This font is also known as Bauer (Used for development gauge fascia)
define("FF_DIGITAL",72); // Digital readout font define("FF_DIGITAL",72); // Digital readout font
define("FF_COMPUTER",73); // The classic computer font define("FF_COMPUTER",73); // The classic computer font
define("FF_CALCULATOR",74); // Triad font define("FF_CALCULATOR",74); // Triad font
   
define("FF_USERFONT",90); define("FF_USERFONT",90);
define("FF_USERFONT1",90); define("FF_USERFONT1",90);
define("FF_USERFONT2",91); define("FF_USERFONT2",91);
define("FF_USERFONT3",92); define("FF_USERFONT3",92);
   
// Limits for fonts // Limits for fonts
define("_FIRST_FONT",10); define("_FIRST_FONT",10);
define("_LAST_FONT",99); define("_LAST_FONT",99);
   
// TTF Font styles // TTF Font styles
define("FS_NORMAL",9001); define("FS_NORMAL",9001);
define("FS_BOLD",9002); define("FS_BOLD",9002);
define("FS_ITALIC",9003); define("FS_ITALIC",9003);
define("FS_BOLDIT",9004); define("FS_BOLDIT",9004);
define("FS_BOLDITALIC",9004); define("FS_BOLDITALIC",9004);
   
//Definitions for internal font //Definitions for internal font
define("FF_FONT0",1); define("FF_FONT0",1);
define("FF_FONT1",2); define("FF_FONT1",2);
define("FF_FONT2",4); define("FF_FONT2",4);
   
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Defines for font setup // Defines for font setup
//------------------------------------------------------------------------ //------------------------------------------------------------------------
   
// Actual name of the TTF file used together with FF_CHINESE aka FF_BIG5 // Actual name of the TTF file used together with FF_CHINESE aka FF_BIG5
// This is the TTF file being used when the font family is specified as // This is the TTF file being used when the font family is specified as
// either FF_CHINESE or FF_BIG5 // either FF_CHINESE or FF_BIG5
define('CHINESE_TTF_FONT','bkai00mp.ttf'); define('CHINESE_TTF_FONT','bkai00mp.ttf');
   
// Special unicode greek language support // Special unicode greek language support
define("LANGUAGE_GREEK",false); define("LANGUAGE_GREEK",false);
   
// If you are setting this config to true the conversion of greek characters // If you are setting this config to true the conversion of greek characters
// will assume that the input text is windows 1251 // will assume that the input text is windows 1251
define("GREEK_FROM_WINDOWS",false); define("GREEK_FROM_WINDOWS",false);
   
// Special unicode cyrillic language support // Special unicode cyrillic language support
define("LANGUAGE_CYRILLIC",false); define("LANGUAGE_CYRILLIC",false);
   
// If you are setting this config to true the conversion // If you are setting this config to true the conversion
// will assume that the input text is windows 1251, if // will assume that the input text is windows 1251, if
// false it will assume koi8-r // false it will assume koi8-r
define("CYRILLIC_FROM_WINDOWS",false); define("CYRILLIC_FROM_WINDOWS",false);
   
// The following constant is used to auto-detect // The following constant is used to auto-detect
// whether cyrillic conversion is really necessary // whether cyrillic conversion is really necessary
// if enabled. Just replace 'windows-1251' with a variable // if enabled. Just replace 'windows-1251' with a variable
// containing the input character encoding string // containing the input character encoding string
// of your application calling jpgraph. // of your application calling jpgraph.
// A typical such string would be 'UTF-8' or 'utf-8'. // A typical such string would be 'UTF-8' or 'utf-8'.
// The comparison is case-insensitive. // The comparison is case-insensitive.
// If this charset is not a 'koi8-r' or 'windows-1251' // If this charset is not a 'koi8-r' or 'windows-1251'
// derivate then no conversion is done. // derivate then no conversion is done.
// //
// This constant can be very important in multi-user // This constant can be very important in multi-user
// multi-language environments where a cyrillic conversion // multi-language environments where a cyrillic conversion
// could be needed for some cyrillic people // could be needed for some cyrillic people
// and resulting in just erraneous conversions // and resulting in just erraneous conversions
// for not-cyrillic language based people. // for not-cyrillic language based people.
// //
// Example: In the free project management // Example: In the free project management
// software dotproject.net $locale_char_set is dynamically // software dotproject.net $locale_char_set is dynamically
// set by the language environment the user has chosen. // set by the language environment the user has chosen.
// //
// Usage: define('LANGUAGE_CHARSET', $locale_char_set); // Usage: define('LANGUAGE_CHARSET', $locale_char_set);
// //
// where $locale_char_set is a GLOBAL (string) variable // where $locale_char_set is a GLOBAL (string) variable
// from the application including JpGraph. // from the application including JpGraph.
// //
define('LANGUAGE_CHARSET', null); define('LANGUAGE_CHARSET', null);
   
// Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC // Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC
// Standard fonts from Infomation-technology Promotion Agency (IPA) // Standard fonts from Infomation-technology Promotion Agency (IPA)
// See http://mix-mplus-ipa.sourceforge.jp/ // See http://mix-mplus-ipa.sourceforge.jp/
define('MINCHO_TTF_FONT','ipam.ttf'); define('MINCHO_TTF_FONT','ipam.ttf');
define('PMINCHO_TTF_FONT','ipamp.ttf'); define('PMINCHO_TTF_FONT','ipamp.ttf');
define('GOTHIC_TTF_FONT','ipag.ttf'); define('GOTHIC_TTF_FONT','ipag.ttf');
define('PGOTHIC_TTF_FONT','ipagp.ttf'); define('PGOTHIC_TTF_FONT','ipagp.ttf');
   
// Assume that Japanese text have been entered in EUC-JP encoding. // Assume that Japanese text have been entered in EUC-JP encoding.
// If this define is true then conversion from EUC-JP to UTF8 is done // If this define is true then conversion from EUC-JP to UTF8 is done
// automatically in the library using the mbstring module in PHP. // automatically in the library using the mbstring module in PHP.
define('ASSUME_EUCJP_ENCODING',false); define('ASSUME_EUCJP_ENCODING',false);
   
   
//================================================================= //=================================================================
// CLASS LanguageConv // CLASS LanguageConv
// Description: // Description:
// Converts various character encoding into proper // Converts various character encoding into proper
// UTF-8 depending on how the library have been configured and // UTF-8 depending on how the library have been configured and
// what font family is being used // what font family is being used
//================================================================= //=================================================================
class LanguageConv { class LanguageConv {
private $g2312 = null ; private $g2312 = null ;
   
function Convert($aTxt,$aFF) { function Convert($aTxt,$aFF) {
if( LANGUAGE_GREEK ) { if( LANGUAGE_GREEK ) {
if( GREEK_FROM_WINDOWS ) { if( GREEK_FROM_WINDOWS ) {
$unistring = LanguageConv::gr_win2uni($aTxt); $unistring = LanguageConv::gr_win2uni($aTxt);
} else { } else {
$unistring = LanguageConv::gr_iso2uni($aTxt); $unistring = LanguageConv::gr_iso2uni($aTxt);
} }
return $unistring; return $unistring;
} elseif( LANGUAGE_CYRILLIC ) { } elseif( LANGUAGE_CYRILLIC ) {
if( CYRILLIC_FROM_WINDOWS && (!defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'windows-1251')) ) { if( CYRILLIC_FROM_WINDOWS && (!defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'windows-1251')) ) {
$aTxt = convert_cyr_string($aTxt, "w", "k"); $aTxt = convert_cyr_string($aTxt, "w", "k");
} }
if( !defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'koi8-r') || stristr(LANGUAGE_CHARSET, 'windows-1251')) { if( !defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'koi8-r') || stristr(LANGUAGE_CHARSET, 'windows-1251')) {
$isostring = convert_cyr_string($aTxt, "k", "i"); $isostring = convert_cyr_string($aTxt, "k", "i");
$unistring = LanguageConv::iso2uni($isostring); $unistring = LanguageConv::iso2uni($isostring);
} }
else { else {
$unistring = $aTxt; $unistring = $aTxt;
} }
return $unistring; return $unistring;
} }
elseif( $aFF === FF_SIMSUN ) { elseif( $aFF === FF_SIMSUN ) {
// Do Chinese conversion // Do Chinese conversion
if( $this->g2312 == null ) { if( $this->g2312 == null ) {
include_once 'jpgraph_gb2312.php' ; include_once 'jpgraph_gb2312.php' ;
$this->g2312 = new GB2312toUTF8(); $this->g2312 = new GB2312toUTF8();
} }
return $this->g2312->gb2utf8($aTxt); return $this->g2312->gb2utf8($aTxt);
} }
elseif( $aFF === FF_BIG5 ) { elseif( $aFF === FF_BIG5 ) {
if( !function_exists('iconv') ) { if( !function_exists('iconv') ) {
JpGraphError::RaiseL(25006); 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).'); //('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); return iconv('BIG5','UTF-8',$aTxt);
} }
elseif( ASSUME_EUCJP_ENCODING && elseif( ASSUME_EUCJP_ENCODING &&
($aFF == FF_MINCHO || $aFF == FF_GOTHIC || $aFF == FF_PMINCHO || $aFF == FF_PGOTHIC) ) { ($aFF == FF_MINCHO || $aFF == FF_GOTHIC || $aFF == FF_PMINCHO || $aFF == FF_PGOTHIC) ) {
if( !function_exists('mb_convert_encoding') ) { if( !function_exists('mb_convert_encoding') ) {
JpGraphError::RaiseL(25127); JpGraphError::RaiseL(25127);
} }
return mb_convert_encoding($aTxt, 'UTF-8','EUC-JP'); return mb_convert_encoding($aTxt, 'UTF-8','EUC-JP');
} }
elseif( $aFF == FF_DAVID || $aFF == FF_MIRIAM || $aFF == FF_AHRON ) { elseif( $aFF == FF_DAVID || $aFF == FF_MIRIAM || $aFF == FF_AHRON ) {
return LanguageConv::heb_iso2uni($aTxt); return LanguageConv::heb_iso2uni($aTxt);
} }
else else
return $aTxt; return $aTxt;
} }
   
// Translate iso encoding to unicode // Translate iso encoding to unicode
public static function iso2uni ($isoline){ public static function iso2uni ($isoline){
$uniline=''; $uniline='';
for ($i=0; $i < strlen($isoline); $i++){ for ($i=0; $i < strlen($isoline); $i++){
$thischar=substr($isoline,$i,1); $thischar=substr($isoline,$i,1);
$charcode=ord($thischar); $charcode=ord($thischar);
$uniline.=($charcode>175) ? "&#" . (1040+($charcode-176)). ";" : $thischar; $uniline.=($charcode>175) ? "&#" . (1040+($charcode-176)). ";" : $thischar;
} }
return $uniline; return $uniline;
} }
   
// Translate greek iso encoding to unicode // Translate greek iso encoding to unicode
public static function gr_iso2uni ($isoline) { public static function gr_iso2uni ($isoline) {
$uniline=''; $uniline='';
for ($i=0; $i < strlen($isoline); $i++) { for ($i=0; $i < strlen($isoline); $i++) {
$thischar=substr($isoline,$i,1); $thischar=substr($isoline,$i,1);
$charcode=ord($thischar); $charcode=ord($thischar);
$uniline.=($charcode>179 && $charcode!=183 && $charcode!=187 && $charcode!=189) ? "&#" . (900+($charcode-180)). ";" : $thischar; $uniline.=($charcode>179 && $charcode!=183 && $charcode!=187 && $charcode!=189) ? "&#" . (900+($charcode-180)). ";" : $thischar;
} }
return $uniline; return $uniline;
} }
   
// Translate greek win encoding to unicode // Translate greek win encoding to unicode
public static function gr_win2uni ($winline) { public static function gr_win2uni ($winline) {
$uniline=''; $uniline='';
for ($i=0; $i < strlen($winline); $i++) { for ($i=0; $i < strlen($winline); $i++) {
$thischar=substr($winline,$i,1); $thischar=substr($winline,$i,1);
$charcode=ord($thischar); $charcode=ord($thischar);
if ($charcode==161 || $charcode==162) { if ($charcode==161 || $charcode==162) {
$uniline.="&#" . (740+$charcode). ";"; $uniline.="&#" . (740+$charcode). ";";
} }
else { else {
$uniline.=(($charcode>183 && $charcode!=187 && $charcode!=189) || $charcode==180) ? "&#" . (900+($charcode-180)). ";" : $thischar; $uniline.=(($charcode>183 && $charcode!=187 && $charcode!=189) || $charcode==180) ? "&#" . (900+($charcode-180)). ";" : $thischar;
} }
} }
return $uniline; return $uniline;
} }
   
public static function heb_iso2uni($isoline) { public static function heb_iso2uni($isoline) {
$isoline = hebrev($isoline); $isoline = hebrev($isoline);
$o = ''; $o = '';
   
$n = strlen($isoline); $n = strlen($isoline);
for($i=0; $i < $n; $i++) { for($i=0; $i < $n; $i++) {
$c=ord( substr($isoline,$i,1) ); $c=ord( substr($isoline,$i,1) );
$o .= ($c > 223) && ($c < 251) ? '&#'.(1264+$c).';' : chr($c); $o .= ($c > 223) && ($c < 251) ? '&#'.(1264+$c).';' : chr($c);
} }
return utf8_encode($o); return utf8_encode($o);
} }
} }
   
//============================================================= //=============================================================
// CLASS TTF // CLASS TTF
// Description: Handle TTF font names and mapping and loading of // Description: Handle TTF font names and mapping and loading of
// font files // font files
//============================================================= //=============================================================
class TTF { class TTF {
private $font_files,$style_names; private $font_files,$style_names;
   
function __construct() { function __construct() {
   
// String names for font styles to be used in error messages // String names for font styles to be used in error messages
$this->style_names=array( $this->style_names=array(
FS_NORMAL =>'normal', FS_NORMAL =>'normal',
FS_BOLD =>'bold', FS_BOLD =>'bold',
FS_ITALIC =>'italic', FS_ITALIC =>'italic',
FS_BOLDITALIC =>'bolditalic'); FS_BOLDITALIC =>'bolditalic');
   
// File names for available fonts // File names for available fonts
$this->font_files=array( $this->font_files=array(
FF_COURIER => array(FS_NORMAL =>'cour.ttf', FF_COURIER => array(FS_NORMAL =>'cour.ttf',
FS_BOLD =>'courbd.ttf', FS_BOLD =>'courbd.ttf',
FS_ITALIC =>'couri.ttf', FS_ITALIC =>'couri.ttf',
FS_BOLDITALIC =>'courbi.ttf' ), FS_BOLDITALIC =>'courbi.ttf' ),
FF_GEORGIA => array(FS_NORMAL =>'georgia.ttf', FF_GEORGIA => array(FS_NORMAL =>'georgia.ttf',
FS_BOLD =>'georgiab.ttf', FS_BOLD =>'georgiab.ttf',
FS_ITALIC =>'georgiai.ttf', FS_ITALIC =>'georgiai.ttf',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
FF_TREBUCHE =>array(FS_NORMAL =>'trebuc.ttf', FF_TREBUCHE =>array(FS_NORMAL =>'trebuc.ttf',
FS_BOLD =>'trebucbd.ttf', FS_BOLD =>'trebucbd.ttf',
FS_ITALIC =>'trebucit.ttf', FS_ITALIC =>'trebucit.ttf',
FS_BOLDITALIC =>'trebucbi.ttf' ), FS_BOLDITALIC =>'trebucbi.ttf' ),
FF_VERDANA => array(FS_NORMAL =>'verdana.ttf', FF_VERDANA => array(FS_NORMAL =>'verdana.ttf',
FS_BOLD =>'verdanab.ttf', FS_BOLD =>'verdanab.ttf',
FS_ITALIC =>'verdanai.ttf', FS_ITALIC =>'verdanai.ttf',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
FF_TIMES => array(FS_NORMAL =>'times.ttf', FF_TIMES => array(FS_NORMAL =>'times.ttf',
FS_BOLD =>'timesbd.ttf', FS_BOLD =>'timesbd.ttf',
FS_ITALIC =>'timesi.ttf', FS_ITALIC =>'timesi.ttf',
FS_BOLDITALIC =>'timesbi.ttf' ), FS_BOLDITALIC =>'timesbi.ttf' ),
FF_COMIC => array(FS_NORMAL =>'comic.ttf', FF_COMIC => array(FS_NORMAL =>'comic.ttf',
FS_BOLD =>'comicbd.ttf', FS_BOLD =>'comicbd.ttf',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
FF_ARIAL => array(FS_NORMAL =>'arial.ttf', FF_ARIAL => array(FS_NORMAL =>'arial.ttf',
FS_BOLD =>'arialbd.ttf', FS_BOLD =>'arialbd.ttf',
FS_ITALIC =>'ariali.ttf', FS_ITALIC =>'ariali.ttf',
FS_BOLDITALIC =>'arialbi.ttf' ) , FS_BOLDITALIC =>'arialbi.ttf' ) ,
FF_VERA => array(FS_NORMAL =>'Vera.ttf', FF_VERA => array(FS_NORMAL =>'Vera.ttf',
FS_BOLD =>'VeraBd.ttf', FS_BOLD =>'VeraBd.ttf',
FS_ITALIC =>'VeraIt.ttf', FS_ITALIC =>'VeraIt.ttf',
FS_BOLDITALIC =>'VeraBI.ttf' ), FS_BOLDITALIC =>'VeraBI.ttf' ),
FF_VERAMONO => array(FS_NORMAL =>'VeraMono.ttf', FF_VERAMONO => array(FS_NORMAL =>'VeraMono.ttf',
FS_BOLD =>'VeraMoBd.ttf', FS_BOLD =>'VeraMoBd.ttf',
FS_ITALIC =>'VeraMoIt.ttf', FS_ITALIC =>'VeraMoIt.ttf',
FS_BOLDITALIC =>'VeraMoBI.ttf' ), FS_BOLDITALIC =>'VeraMoBI.ttf' ),
FF_VERASERIF=> array(FS_NORMAL =>'VeraSe.ttf', FF_VERASERIF=> array(FS_NORMAL =>'VeraSe.ttf',
FS_BOLD =>'VeraSeBd.ttf', FS_BOLD =>'VeraSeBd.ttf',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ) , FS_BOLDITALIC =>'' ) ,
   
/* Chinese fonts */ /* Chinese fonts */
FF_SIMSUN => array( FF_SIMSUN => array(
FS_NORMAL =>'simsun.ttc', FS_NORMAL =>'simsun.ttc',
FS_BOLD =>'simhei.ttf', FS_BOLD =>'simhei.ttf',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
FF_CHINESE => array( FF_CHINESE => array(
FS_NORMAL =>CHINESE_TTF_FONT, FS_NORMAL =>CHINESE_TTF_FONT,
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
FF_BIG5 => array( FF_BIG5 => array(
FS_NORMAL =>CHINESE_TTF_FONT, FS_NORMAL =>CHINESE_TTF_FONT,
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
/* Japanese fonts */ /* Japanese fonts */
FF_MINCHO => array( FF_MINCHO => array(
FS_NORMAL =>MINCHO_TTF_FONT, FS_NORMAL =>MINCHO_TTF_FONT,
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_PMINCHO => array( FF_PMINCHO => array(
FS_NORMAL =>PMINCHO_TTF_FONT, FS_NORMAL =>PMINCHO_TTF_FONT,
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_GOTHIC => array( FF_GOTHIC => array(
FS_NORMAL =>GOTHIC_TTF_FONT, FS_NORMAL =>GOTHIC_TTF_FONT,
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_PGOTHIC => array( FF_PGOTHIC => array(
FS_NORMAL =>PGOTHIC_TTF_FONT, FS_NORMAL =>PGOTHIC_TTF_FONT,
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
/* Hebrew fonts */ /* Hebrew fonts */
FF_DAVID => array( FF_DAVID => array(
FS_NORMAL =>'DAVIDNEW.TTF', FS_NORMAL =>'DAVIDNEW.TTF',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_MIRIAM => array( FF_MIRIAM => array(
FS_NORMAL =>'MRIAMY.TTF', FS_NORMAL =>'MRIAMY.TTF',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_AHRON => array( FF_AHRON => array(
FS_NORMAL =>'ahronbd.ttf', FS_NORMAL =>'ahronbd.ttf',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
/* Misc fonts */ /* Misc fonts */
FF_DIGITAL => array( FF_DIGITAL => array(
FS_NORMAL =>'DIGIRU__.TTF', FS_NORMAL =>'DIGIRU__.TTF',
FS_BOLD =>'Digirtu_.ttf', FS_BOLD =>'Digirtu_.ttf',
FS_ITALIC =>'Digir___.ttf', FS_ITALIC =>'Digir___.ttf',
FS_BOLDITALIC =>'DIGIRT__.TTF' ), FS_BOLDITALIC =>'DIGIRT__.TTF' ),
   
/* This is an experimental font for the speedometer development /* This is an experimental font for the speedometer development
FF_SPEEDO => array( FF_SPEEDO => array(
FS_NORMAL =>'Speedo.ttf', FS_NORMAL =>'Speedo.ttf',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
*/ */
   
FF_COMPUTER => array( FF_COMPUTER => array(
FS_NORMAL =>'COMPUTER.TTF', FS_NORMAL =>'COMPUTER.TTF',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_CALCULATOR => array( FF_CALCULATOR => array(
FS_NORMAL =>'Triad_xs.ttf', FS_NORMAL =>'Triad_xs.ttf',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
/* Dejavu fonts */ /* Dejavu fonts */
FF_DV_SANSSERIF => array( FF_DV_SANSSERIF => array(
FS_NORMAL =>array('DejaVuSans.ttf'), FS_NORMAL =>array('DejaVuSans.ttf'),
FS_BOLD =>array('DejaVuSans-Bold.ttf','DejaVuSansBold.ttf'), FS_BOLD =>array('DejaVuSans-Bold.ttf','DejaVuSansBold.ttf'),
FS_ITALIC =>array('DejaVuSans-Oblique.ttf','DejaVuSansOblique.ttf'), FS_ITALIC =>array('DejaVuSans-Oblique.ttf','DejaVuSansOblique.ttf'),
FS_BOLDITALIC =>array('DejaVuSans-BoldOblique.ttf','DejaVuSansBoldOblique.ttf') ), FS_BOLDITALIC =>array('DejaVuSans-BoldOblique.ttf','DejaVuSansBoldOblique.ttf') ),
   
FF_DV_SANSSERIFMONO => array( FF_DV_SANSSERIFMONO => array(
FS_NORMAL =>array('DejaVuSansMono.ttf','DejaVuMonoSans.ttf'), FS_NORMAL =>array('DejaVuSansMono.ttf','DejaVuMonoSans.ttf'),
FS_BOLD =>array('DejaVuSansMono-Bold.ttf','DejaVuMonoSansBold.ttf'), FS_BOLD =>array('DejaVuSansMono-Bold.ttf','DejaVuMonoSansBold.ttf'),
FS_ITALIC =>array('DejaVuSansMono-Oblique.ttf','DejaVuMonoSansOblique.ttf'), FS_ITALIC =>array('DejaVuSansMono-Oblique.ttf','DejaVuMonoSansOblique.ttf'),
FS_BOLDITALIC =>array('DejaVuSansMono-BoldOblique.ttf','DejaVuMonoSansBoldOblique.ttf') ), FS_BOLDITALIC =>array('DejaVuSansMono-BoldOblique.ttf','DejaVuMonoSansBoldOblique.ttf') ),
   
FF_DV_SANSSERIFCOND => array( FF_DV_SANSSERIFCOND => array(
FS_NORMAL =>array('DejaVuSansCondensed.ttf','DejaVuCondensedSans.ttf'), FS_NORMAL =>array('DejaVuSansCondensed.ttf','DejaVuCondensedSans.ttf'),
FS_BOLD =>array('DejaVuSansCondensed-Bold.ttf','DejaVuCondensedSansBold.ttf'), FS_BOLD =>array('DejaVuSansCondensed-Bold.ttf','DejaVuCondensedSansBold.ttf'),
FS_ITALIC =>array('DejaVuSansCondensed-Oblique.ttf','DejaVuCondensedSansOblique.ttf'), FS_ITALIC =>array('DejaVuSansCondensed-Oblique.ttf','DejaVuCondensedSansOblique.ttf'),
FS_BOLDITALIC =>array('DejaVuSansCondensed-BoldOblique.ttf','DejaVuCondensedSansBoldOblique.ttf') ), FS_BOLDITALIC =>array('DejaVuSansCondensed-BoldOblique.ttf','DejaVuCondensedSansBoldOblique.ttf') ),
   
FF_DV_SERIF => array( FF_DV_SERIF => array(
FS_NORMAL =>array('DejaVuSerif.ttf'), FS_NORMAL =>array('DejaVuSerif.ttf'),
FS_BOLD =>array('DejaVuSerif-Bold.ttf','DejaVuSerifBold.ttf'), FS_BOLD =>array('DejaVuSerif-Bold.ttf','DejaVuSerifBold.ttf'),
FS_ITALIC =>array('DejaVuSerif-Italic.ttf','DejaVuSerifItalic.ttf'), FS_ITALIC =>array('DejaVuSerif-Italic.ttf','DejaVuSerifItalic.ttf'),
FS_BOLDITALIC =>array('DejaVuSerif-BoldItalic.ttf','DejaVuSerifBoldItalic.ttf') ), FS_BOLDITALIC =>array('DejaVuSerif-BoldItalic.ttf','DejaVuSerifBoldItalic.ttf') ),
   
FF_DV_SERIFCOND => array( FF_DV_SERIFCOND => array(
FS_NORMAL =>array('DejaVuSerifCondensed.ttf','DejaVuCondensedSerif.ttf'), FS_NORMAL =>array('DejaVuSerifCondensed.ttf','DejaVuCondensedSerif.ttf'),
FS_BOLD =>array('DejaVuSerifCondensed-Bold.ttf','DejaVuCondensedSerifBold.ttf'), FS_BOLD =>array('DejaVuSerifCondensed-Bold.ttf','DejaVuCondensedSerifBold.ttf'),
FS_ITALIC =>array('DejaVuSerifCondensed-Italic.ttf','DejaVuCondensedSerifItalic.ttf'), FS_ITALIC =>array('DejaVuSerifCondensed-Italic.ttf','DejaVuCondensedSerifItalic.ttf'),
FS_BOLDITALIC =>array('DejaVuSerifCondensed-BoldItalic.ttf','DejaVuCondensedSerifBoldItalic.ttf') ), FS_BOLDITALIC =>array('DejaVuSerifCondensed-BoldItalic.ttf','DejaVuCondensedSerifBoldItalic.ttf') ),
   
   
/* Placeholders for defined fonts */ /* Placeholders for defined fonts */
FF_USERFONT1 => array( FF_USERFONT1 => array(
FS_NORMAL =>'', FS_NORMAL =>'',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_USERFONT2 => array( FF_USERFONT2 => array(
FS_NORMAL =>'', FS_NORMAL =>'',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
FF_USERFONT3 => array( FF_USERFONT3 => array(
FS_NORMAL =>'', FS_NORMAL =>'',
FS_BOLD =>'', FS_BOLD =>'',
FS_ITALIC =>'', FS_ITALIC =>'',
FS_BOLDITALIC =>'' ), FS_BOLDITALIC =>'' ),
   
); );
} }
   
//--------------- //---------------
// PUBLIC METHODS // PUBLIC METHODS
// Create the TTF file from the font specification // Create the TTF file from the font specification
function File($family,$style=FS_NORMAL) { function File($family,$style=FS_NORMAL) {
$fam = @$this->font_files[$family]; $fam = @$this->font_files[$family];
if( !$fam ) { 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/"); 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]; $ff = @$fam[$style];
   
if( is_array($ff) ) { if( is_array($ff) ) {
// There are several optional file names. They are tried in order // There are several optional file names. They are tried in order
// and the first one found is used // and the first one found is used
$n = count($ff); $n = count($ff);
} else { } else {
$n = 1; $n = 1;
$ff = array($ff); $ff = array($ff);
} }
$i = 0; $i = 0;
do { do {
$f = $ff[$i]; $f = $ff[$i];
// All font families are guaranteed to have the normal style // All font families are guaranteed to have the normal style
   
if( $f==='' ) 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].'.'); 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 ) { if( !$f ) {
JpGraphError::RaiseL(25048,$fam);//("Unknown font style specification [$fam]."); JpGraphError::RaiseL(25048,$fam);//("Unknown font style specification [$fam].");
} }
   
if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) { if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) {
$f = MBTTF_DIR.$f; $f = MBTTF_DIR.$f;
} else { } else {
$f = TTF_DIR.$f; $f = TTF_DIR.$f;
} }
++$i; ++$i;
} while( $i < $n && (file_exists($f) === false || is_readable($f) === false) ); } while( $i < $n && (file_exists($f) === false || is_readable($f) === false) );
   
if( !file_exists($f) ) { if( !file_exists($f) ) {
JpGraphError::RaiseL(25049,$f);//("Font file \"$f\" is not readable or does not exist."); JpGraphError::RaiseL(25049,$f);//("Font file \"$f\" is not readable or does not exist.");
} }
return $f; return $f;
} }
   
function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->font_files[FF_USERFONT] = $this->font_files[FF_USERFONT] =
array(FS_NORMAL => $aNormal, array(FS_NORMAL => $aNormal,
FS_BOLD => $aBold, FS_BOLD => $aBold,
FS_ITALIC => $aItalic, FS_ITALIC => $aItalic,
FS_BOLDITALIC => $aBoldIt ) ; FS_BOLDITALIC => $aBoldIt ) ;
} }
   
function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->font_files[FF_USERFONT1] = $this->font_files[FF_USERFONT1] =
array(FS_NORMAL => $aNormal, array(FS_NORMAL => $aNormal,
FS_BOLD => $aBold, FS_BOLD => $aBold,
FS_ITALIC => $aItalic, FS_ITALIC => $aItalic,
FS_BOLDITALIC => $aBoldIt ) ; FS_BOLDITALIC => $aBoldIt ) ;
} }
   
function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->font_files[FF_USERFONT2] = $this->font_files[FF_USERFONT2] =
array(FS_NORMAL => $aNormal, array(FS_NORMAL => $aNormal,
FS_BOLD => $aBold, FS_BOLD => $aBold,
FS_ITALIC => $aItalic, FS_ITALIC => $aItalic,
FS_BOLDITALIC => $aBoldIt ) ; FS_BOLDITALIC => $aBoldIt ) ;
} }
   
function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') { function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
$this->font_files[FF_USERFONT3] = $this->font_files[FF_USERFONT3] =
array(FS_NORMAL => $aNormal, array(FS_NORMAL => $aNormal,
FS_BOLD => $aBold, FS_BOLD => $aBold,
FS_ITALIC => $aItalic, FS_ITALIC => $aItalic,
FS_BOLDITALIC => $aBoldIt ) ; FS_BOLDITALIC => $aBoldIt ) ;
} }
   
} // Class } // Class
   
   
//============================================================================= //=============================================================================
// CLASS SymChar // CLASS SymChar
// Description: Code values for some commonly used characters that // Description: Code values for some commonly used characters that
// normally isn't available directly on the keyboard, for example // normally isn't available directly on the keyboard, for example
// mathematical and greek symbols. // mathematical and greek symbols.
//============================================================================= //=============================================================================
class SymChar { class SymChar {
static function Get($aSymb,$aCapital=FALSE) { static function Get($aSymb,$aCapital=FALSE) {
$iSymbols = array( $iSymbols = array(
/* Greek */ /* Greek */
array('alpha','03B1','0391'), array('alpha','03B1','0391'),
array('beta','03B2','0392'), array('beta','03B2','0392'),
array('gamma','03B3','0393'), array('gamma','03B3','0393'),
array('delta','03B4','0394'), array('delta','03B4','0394'),
array('epsilon','03B5','0395'), array('epsilon','03B5','0395'),
array('zeta','03B6','0396'), array('zeta','03B6','0396'),
array('ny','03B7','0397'), array('ny','03B7','0397'),
array('eta','03B8','0398'), array('eta','03B8','0398'),
array('theta','03B8','0398'), array('theta','03B8','0398'),
array('iota','03B9','0399'), array('iota','03B9','0399'),
array('kappa','03BA','039A'), array('kappa','03BA','039A'),
array('lambda','03BB','039B'), array('lambda','03BB','039B'),
array('mu','03BC','039C'), array('mu','03BC','039C'),
array('nu','03BD','039D'), array('nu','03BD','039D'),
array('xi','03BE','039E'), array('xi','03BE','039E'),
array('omicron','03BF','039F'), array('omicron','03BF','039F'),
array('pi','03C0','03A0'), array('pi','03C0','03A0'),
array('rho','03C1','03A1'), array('rho','03C1','03A1'),
array('sigma','03C3','03A3'), array('sigma','03C3','03A3'),
array('tau','03C4','03A4'), array('tau','03C4','03A4'),
array('upsilon','03C5','03A5'), array('upsilon','03C5','03A5'),
array('phi','03C6','03A6'), array('phi','03C6','03A6'),
array('chi','03C7','03A7'), array('chi','03C7','03A7'),
array('psi','03C8','03A8'), array('psi','03C8','03A8'),
array('omega','03C9','03A9'), array('omega','03C9','03A9'),
/* Money */ /* Money */
array('euro','20AC'), array('euro','20AC'),
array('yen','00A5'), array('yen','00A5'),
array('pound','20A4'), array('pound','20A4'),
/* Math */ /* Math */
array('approx','2248'), array('approx','2248'),
array('neq','2260'), array('neq','2260'),
array('not','2310'), array('not','2310'),
array('def','2261'), array('def','2261'),
array('inf','221E'), array('inf','221E'),
array('sqrt','221A'), array('sqrt','221A'),
array('int','222B'), array('int','222B'),
/* Misc */ /* Misc */
array('copy','00A9'), array('copy','00A9'),
array('para','00A7'), array('para','00A7'),
array('tm','2122'), /* Trademark symbol */ array('tm','2122'), /* Trademark symbol */
array('rtm','00AE'), /* Registered trademark */ array('rtm','00AE'), /* Registered trademark */
array('degree','00b0'), array('degree','00b0'),
array('lte','2264'), /* Less than or equal */ array('lte','2264'), /* Less than or equal */
array('gte','2265'), /* Greater than or equal */ array('gte','2265'), /* Greater than or equal */
   
); );
   
$n = count($iSymbols); $n = count($iSymbols);
$i=0; $i=0;
$found = false; $found = false;
$aSymb = strtolower($aSymb); $aSymb = strtolower($aSymb);
while( $i < $n && !$found ) { while( $i < $n && !$found ) {
$found = $aSymb === $iSymbols[$i++][0]; $found = $aSymb === $iSymbols[$i++][0];
} }
if( $found ) { if( $found ) {
$ca = $iSymbols[--$i]; $ca = $iSymbols[--$i];
if( $aCapital && count($ca)==3 ) if( $aCapital && count($ca)==3 )
$s = $ca[2]; $s = $ca[2];
else else
$s = $ca[1]; $s = $ca[1];
return sprintf('&#%04d;',hexdec($s)); return sprintf('&#%04d;',hexdec($s));
} }
else else
return ''; return '';
} }
} }
   
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: JPGRAPH_UTILS.INC // File: JPGRAPH_UTILS.INC
// Description: Collection of non-essential "nice to have" utilities // Description: Collection of non-essential "nice to have" utilities
// Created: 2005-11-20 // Created: 2005-11-20
// Ver: $Id: jpgraph_utils.inc.php 1777 2009-08-23 17:34:36Z ljp $ // Ver: $Id: jpgraph_utils.inc.php 1777 2009-08-23 17:34:36Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
//=================================================== //===================================================
// CLASS FuncGenerator // CLASS FuncGenerator
// Description: Utility class to help generate data for function plots. // Description: Utility class to help generate data for function plots.
// The class supports both parametric and regular functions. // The class supports both parametric and regular functions.
//=================================================== //===================================================
class FuncGenerator { class FuncGenerator {
private $iFunc='',$iXFunc='',$iMin,$iMax,$iStepSize; private $iFunc='',$iXFunc='',$iMin,$iMax,$iStepSize;
   
function __construct($aFunc,$aXFunc='') { function __construct($aFunc,$aXFunc='') {
$this->iFunc = $aFunc; $this->iFunc = $aFunc;
$this->iXFunc = $aXFunc; $this->iXFunc = $aXFunc;
} }
   
function E($aXMin,$aXMax,$aSteps=50) { function E($aXMin,$aXMax,$aSteps=50) {
$this->iMin = $aXMin; $this->iMin = $aXMin;
$this->iMax = $aXMax; $this->iMax = $aXMax;
$this->iStepSize = ($aXMax-$aXMin)/$aSteps; $this->iStepSize = ($aXMax-$aXMin)/$aSteps;
   
if( $this->iXFunc != '' ) if( $this->iXFunc != '' )
$t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}'; $t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}';
elseif( $this->iFunc != '' ) elseif( $this->iFunc != '' )
$t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;'; $t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;';
else else
JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. '); JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. ');
   
@eval($t); @eval($t);
   
// If there is an error in the function specifcation this is the only // If there is an error in the function specifcation this is the only
// way we can discover that. // way we can discover that.
if( empty($xa) || empty($ya) ) if( empty($xa) || empty($ya) )
JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification '); JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification ');
   
return array($xa,$ya); return array($xa,$ya);
} }
} }
   
   
//============================================================================= //=============================================================================
// CLASS DateScaleUtils // CLASS DateScaleUtils
// Description: Help to create a manual date scale // Description: Help to create a manual date scale
//============================================================================= //=============================================================================
define('DSUTILS_MONTH',1); // Major and minor ticks on a monthly basis 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_MONTH1',1); // Major and minor ticks on a monthly basis
define('DSUTILS_MONTH2',2); // Major ticks on a bi-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_MONTH3',3); // Major icks on a tri-monthly basis
define('DSUTILS_MONTH6',4); // Major on a six-monthly basis define('DSUTILS_MONTH6',4); // Major on a six-monthly basis
define('DSUTILS_WEEK1',5); // Major ticks on a weekly basis define('DSUTILS_WEEK1',5); // Major ticks on a weekly basis
define('DSUTILS_WEEK2',6); // Major ticks on a bi-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_WEEK4',7); // Major ticks on a quod-weekly basis
define('DSUTILS_DAY1',8); // Major ticks on a daily basis define('DSUTILS_DAY1',8); // Major ticks on a daily basis
define('DSUTILS_DAY2',9); // Major ticks on a bi-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_DAY4',10); // Major ticks on a qoud-daily basis
define('DSUTILS_YEAR1',11); // Major ticks on a yearly basis define('DSUTILS_YEAR1',11); // Major ticks on a yearly basis
define('DSUTILS_YEAR2',12); // Major ticks on a bi-yearly basis define('DSUTILS_YEAR2',12); // Major ticks on a bi-yearly basis
define('DSUTILS_YEAR5',13); // Major ticks on a five-yearly basis define('DSUTILS_YEAR5',13); // Major ticks on a five-yearly basis
   
   
class DateScaleUtils { class DateScaleUtils {
public static $iMin=0, $iMax=0; public static $iMin=0, $iMax=0;
   
private static $starthour,$startmonth, $startday, $startyear; private static $starthour,$startmonth, $startday, $startyear;
private static $endmonth, $endyear, $endday; private static $endmonth, $endyear, $endday;
private static $tickPositions=array(),$minTickPositions=array(); private static $tickPositions=array(),$minTickPositions=array();
private static $iUseWeeks = true; private static $iUseWeeks = true;
   
static function UseWeekFormat($aFlg) { static function UseWeekFormat($aFlg) {
self::$iUseWeeks = $aFlg; self::$iUseWeeks = $aFlg;
} }
   
static function doYearly($aType,$aMinor=false) { static function doYearly($aType,$aMinor=false) {
$i=0; $j=0; $i=0; $j=0;
$m = self::$startmonth; $m = self::$startmonth;
$y = self::$startyear; $y = self::$startyear;
   
if( self::$startday == 1 ) { if( self::$startday == 1 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
} }
++$m; ++$m;
   
   
switch( $aType ) { switch( $aType ) {
case DSUTILS_YEAR1: case DSUTILS_YEAR1:
for($y=self::$startyear; $y <= self::$endyear; ++$y ) { for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
if( $aMinor ) { if( $aMinor ) {
while( $m <= 12 ) { while( $m <= 12 ) {
if( !($y == self::$endyear && $m > self::$endmonth) ) { if( !($y == self::$endyear && $m > self::$endmonth) ) {
self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
} }
++$m; ++$m;
} }
$m=1; $m=1;
} }
self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
} }
break; break;
case DSUTILS_YEAR2: case DSUTILS_YEAR2:
$y=self::$startyear; $y=self::$startyear;
while( $y <= self::$endyear ) { while( $y <= self::$endyear ) {
self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
for($k=0; $k < 1; ++$k ) { for($k=0; $k < 1; ++$k ) {
++$y; ++$y;
if( $aMinor ) { if( $aMinor ) {
self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y); self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
} }
} }
++$y; ++$y;
} }
break; break;
case DSUTILS_YEAR5: case DSUTILS_YEAR5:
$y=self::$startyear; $y=self::$startyear;
while( $y <= self::$endyear ) { while( $y <= self::$endyear ) {
self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
for($k=0; $k < 4; ++$k ) { for($k=0; $k < 4; ++$k ) {
++$y; ++$y;
if( $aMinor ) { if( $aMinor ) {
self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y); self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
} }
} }
++$y; ++$y;
} }
break; break;
} }
} }
   
static function doDaily($aType,$aMinor=false) { static function doDaily($aType,$aMinor=false) {
$m = self::$startmonth; $m = self::$startmonth;
$y = self::$startyear; $y = self::$startyear;
$d = self::$startday; $d = self::$startday;
$h = self::$starthour; $h = self::$starthour;
$i=0;$j=0; $i=0;$j=0;
   
if( $h == 0 ) { if( $h == 0 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
} }
$t = mktime(0,0,0,$m,$d,$y); $t = mktime(0,0,0,$m,$d,$y);
   
switch($aType) { switch($aType) {
case DSUTILS_DAY1: case DSUTILS_DAY1:
while( $t <= self::$iMax ) { while( $t <= self::$iMax ) {
$t = strtotime('+1 day',$t); $t = strtotime('+1 day',$t);
self::$tickPositions[$i++] = $t; self::$tickPositions[$i++] = $t;
if( $aMinor ) { if( $aMinor ) {
self::$minTickPositions[$j++] = strtotime('+12 hours',$t); self::$minTickPositions[$j++] = strtotime('+12 hours',$t);
} }
} }
break; break;
case DSUTILS_DAY2: case DSUTILS_DAY2:
while( $t <= self::$iMax ) { while( $t <= self::$iMax ) {
$t = strtotime('+1 day',$t); $t = strtotime('+1 day',$t);
if( $aMinor ) { if( $aMinor ) {
self::$minTickPositions[$j++] = $t; self::$minTickPositions[$j++] = $t;
} }
$t = strtotime('+1 day',$t); $t = strtotime('+1 day',$t);
self::$tickPositions[$i++] = $t; self::$tickPositions[$i++] = $t;
} }
break; break;
case DSUTILS_DAY4: case DSUTILS_DAY4:
while( $t <= self::$iMax ) { while( $t <= self::$iMax ) {
for($k=0; $k < 3; ++$k ) { for($k=0; $k < 3; ++$k ) {
$t = strtotime('+1 day',$t); $t = strtotime('+1 day',$t);
if( $aMinor ) { if( $aMinor ) {
self::$minTickPositions[$j++] = $t; self::$minTickPositions[$j++] = $t;
} }
} }
$t = strtotime('+1 day',$t); $t = strtotime('+1 day',$t);
self::$tickPositions[$i++] = $t; self::$tickPositions[$i++] = $t;
} }
break; break;
} }
} }
   
static function doWeekly($aType,$aMinor=false) { static function doWeekly($aType,$aMinor=false) {
$hpd = 3600*24; $hpd = 3600*24;
$hpw = 3600*24*7; $hpw = 3600*24*7;
// Find out week number of min date // Find out week number of min date
$thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7); $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; $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7;
$daynumber = date('w',self::$iMin); $daynumber = date('w',self::$iMin);
if( $daynumber == 0 ) $daynumber = 7; if( $daynumber == 0 ) $daynumber = 7;
$m = self::$startmonth; $m = self::$startmonth;
$y = self::$startyear; $y = self::$startyear;
$d = self::$startday; $d = self::$startday;
$i=0;$j=0; $i=0;$j=0;
// The assumption is that the weeks start on Monday. If the first day // 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 // is later in the week then the first week tick has to be on the following
// week. // week.
if( $daynumber == 1 ) { if( $daynumber == 1 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
$t = mktime(0,0,0,$m,$d,$y) + $hpw; $t = mktime(0,0,0,$m,$d,$y) + $hpw;
} }
else { else {
$t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber); $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber);
} }
   
switch($aType) { switch($aType) {
case DSUTILS_WEEK1: case DSUTILS_WEEK1:
$cnt=0; $cnt=0;
break; break;
case DSUTILS_WEEK2: case DSUTILS_WEEK2:
$cnt=1; $cnt=1;
break; break;
case DSUTILS_WEEK4: case DSUTILS_WEEK4:
$cnt=3; $cnt=3;
break; break;
} }
while( $t <= self::$iMax ) { while( $t <= self::$iMax ) {
self::$tickPositions[$i++] = $t; self::$tickPositions[$i++] = $t;
for($k=0; $k < $cnt; ++$k ) { for($k=0; $k < $cnt; ++$k ) {
$t += $hpw; $t += $hpw;
if( $aMinor ) { if( $aMinor ) {
self::$minTickPositions[$j++] = $t; self::$minTickPositions[$j++] = $t;
} }
} }
$t += $hpw; $t += $hpw;
} }
} }
   
static function doMonthly($aType,$aMinor=false) { static function doMonthly($aType,$aMinor=false) {
$monthcount=0; $monthcount=0;
$m = self::$startmonth; $m = self::$startmonth;
$y = self::$startyear; $y = self::$startyear;
$i=0; $j=0; $i=0; $j=0;
   
// Skip the first month label if it is before the startdate // Skip the first month label if it is before the startdate
if( self::$startday == 1 ) { if( self::$startday == 1 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
$monthcount=1; $monthcount=1;
} }
if( $aType == 1 ) { if( $aType == 1 ) {
if( self::$startday < 15 ) { if( self::$startday < 15 ) {
self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
} }
} }
++$m; ++$m;
   
// Loop through all the years included in the scale // Loop through all the years included in the scale
for($y=self::$startyear; $y <= self::$endyear; ++$y ) { for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
// Loop through all the months. There are three cases to consider: // Loop through all the months. There are three cases to consider:
// 1. We are in the first year and must start with the startmonth // 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 // 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 // 3. A year in between where we run through all the 12 months
$stopmonth = $y == self::$endyear ? self::$endmonth : 12; $stopmonth = $y == self::$endyear ? self::$endmonth : 12;
while( $m <= $stopmonth ) { while( $m <= $stopmonth ) {
switch( $aType ) { switch( $aType ) {
case DSUTILS_MONTH1: case DSUTILS_MONTH1:
// Set minor tick at the middle of the month // Set minor tick at the middle of the month
if( $aMinor ) { if( $aMinor ) {
if( $m <= $stopmonth ) { if( $m <= $stopmonth ) {
if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) ) if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) )
self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
} }
} }
// Major at month // Major at month
// Get timestamp of first hour of first day in each month // Get timestamp of first hour of first day in each month
self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
   
break; break;
case DSUTILS_MONTH2: case DSUTILS_MONTH2:
if( $aMinor ) { if( $aMinor ) {
// Set minor tick at start of each month // Set minor tick at start of each month
self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
} }
   
// Major at every second month // Major at every second month
// Get timestamp of first hour of first day in each month // Get timestamp of first hour of first day in each month
if( $monthcount % 2 == 0 ) { if( $monthcount % 2 == 0 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
} }
break; break;
case DSUTILS_MONTH3: case DSUTILS_MONTH3:
if( $aMinor ) { if( $aMinor ) {
// Set minor tick at start of each month // Set minor tick at start of each month
self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
} }
// Major at every third month // Major at every third month
// Get timestamp of first hour of first day in each month // Get timestamp of first hour of first day in each month
if( $monthcount % 3 == 0 ) { if( $monthcount % 3 == 0 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
} }
break; break;
case DSUTILS_MONTH6: case DSUTILS_MONTH6:
if( $aMinor ) { if( $aMinor ) {
// Set minor tick at start of each month // Set minor tick at start of each month
self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
} }
// Major at every third month // Major at every third month
// Get timestamp of first hour of first day in each month // Get timestamp of first hour of first day in each month
if( $monthcount % 6 == 0 ) { if( $monthcount % 6 == 0 ) {
self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y); self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
} }
break; break;
} }
++$m; ++$m;
++$monthcount; ++$monthcount;
} }
$m=1; $m=1;
} }
   
// For the case where all dates are within the same month // 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 // we want to make sure we have at least two ticks on the scale
// since the scale want work properly otherwise // since the scale want work properly otherwise
if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) { if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) {
self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear); self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear);
} }
   
return array(self::$tickPositions,self::$minTickPositions); return array(self::$tickPositions,self::$minTickPositions);
} }
   
static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) { static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) {
$n = count($aData); $n = count($aData);
return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints); return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
} }
   
static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) { static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) {
$diff = $aMax - $aMin; $diff = $aMax - $aMin;
$spd = 3600*24; $spd = 3600*24;
$spw = $spd*7; $spw = $spd*7;
$spm = $spd*30; $spm = $spd*30;
$spy = $spd*352; $spy = $spd*352;
   
if( self::$iUseWeeks ) if( self::$iUseWeeks )
$w = 'W'; $w = 'W';
else else
$w = 'd M'; $w = 'd M';
   
// Decision table for suitable scales // Decision table for suitable scales
// First value: Main decision point // First value: Main decision point
// Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,.. // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,..
$tt = array( $tt = array(
array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')), 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($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($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'))); 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); $ntt = count($tt);
$nd = floor($diff/$spd); $nd = floor($diff/$spd);
for($i=0; $i < $ntt; ++$i ) { for($i=0; $i < $ntt; ++$i ) {
if( $diff <= $tt[$i][0] || $i==$ntt-1) { if( $diff <= $tt[$i][0] || $i==$ntt-1) {
$t = $tt[$i][1]; $t = $tt[$i][1];
$n = count($t)/3; $n = count($t)/3;
for( $j=0; $j < $n; ++$j ) { for( $j=0; $j < $n; ++$j ) {
if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) { if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) {
$type = $t[3*$j+1]; $type = $t[3*$j+1];
$fs = $t[3*$j+2]; $fs = $t[3*$j+2];
list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor); list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor);
return array($fs,$tickPositions,$minTickPositions,$type); return array($fs,$tickPositions,$minTickPositions,$type);
} }
} }
} }
} }
} }
   
static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) { static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) {
self::$starthour = date('G',$aMin); self::$starthour = date('G',$aMin);
self::$startmonth = date('n',$aMin); self::$startmonth = date('n',$aMin);
self::$startday = date('j',$aMin); self::$startday = date('j',$aMin);
self::$startyear = date('Y',$aMin); self::$startyear = date('Y',$aMin);
self::$endmonth = date('n',$aMax); self::$endmonth = date('n',$aMax);
self::$endyear = date('Y',$aMax); self::$endyear = date('Y',$aMax);
self::$endday = date('j',$aMax); self::$endday = date('j',$aMax);
self::$iMin = $aMin; self::$iMin = $aMin;
self::$iMax = $aMax; self::$iMax = $aMax;
   
if( $aType <= DSUTILS_MONTH6 ) { if( $aType <= DSUTILS_MONTH6 ) {
self::doMonthly($aType,$aMinor); self::doMonthly($aType,$aMinor);
} }
elseif( $aType <= DSUTILS_WEEK4 ) { elseif( $aType <= DSUTILS_WEEK4 ) {
self::doWeekly($aType,$aMinor); self::doWeekly($aType,$aMinor);
} }
elseif( $aType <= DSUTILS_DAY4 ) { elseif( $aType <= DSUTILS_DAY4 ) {
self::doDaily($aType,$aMinor); self::doDaily($aType,$aMinor);
} }
elseif( $aType <= DSUTILS_YEAR5 ) { elseif( $aType <= DSUTILS_YEAR5 ) {
self::doYearly($aType,$aMinor); self::doYearly($aType,$aMinor);
} }
else { else {
JpGraphError::RaiseL(24003); JpGraphError::RaiseL(24003);
} }
// put a label at the very left data pos // put a label at the very left data pos
if( $aEndPoints ) { if( $aEndPoints ) {
$tickPositions[$i++] = $aData[0]; $tickPositions[$i++] = $aData[0];
} }
   
// put a label at the very right data pos // put a label at the very right data pos
if( $aEndPoints ) { if( $aEndPoints ) {
$tickPositions[$i] = $aData[$n-1]; $tickPositions[$i] = $aData[$n-1];
} }
   
return array(self::$tickPositions,self::$minTickPositions); return array(self::$tickPositions,self::$minTickPositions);
} }
} }
   
//============================================================================= //=============================================================================
// Class ReadFileData // Class ReadFileData
//============================================================================= //=============================================================================
Class ReadFileData { Class ReadFileData {
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Desciption: // Desciption:
// Read numeric data from a file. // Read numeric data from a file.
// Each value should be separated by either a new line or by a specified // Each value should be separated by either a new line or by a specified
// separator character (default is ','). // separator character (default is ',').
// Before returning the data each value is converted to a proper float // 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 // value. The routine is robust in the sense that non numeric data in the
// file will be discarded. // file will be discarded.
// //
// Returns: // Returns:
// The number of data values read on success, FALSE on failure // The number of data values read on success, FALSE on failure
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) { static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) {
$rh = @fopen($aFile,'r'); $rh = @fopen($aFile,'r');
if( $rh === false ) { if( $rh === false ) {
return false; return false;
} }
$tmp = array(); $tmp = array();
$lineofdata = fgetcsv($rh, 1000, ','); $lineofdata = fgetcsv($rh, 1000, ',');
while ( $lineofdata !== FALSE) { while ( $lineofdata !== FALSE) {
$tmp = array_merge($tmp,$lineofdata); $tmp = array_merge($tmp,$lineofdata);
$lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar); $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar);
} }
fclose($rh); fclose($rh);
   
// Now make sure that all data is numeric. By default // Now make sure that all data is numeric. By default
// all data is read as strings // all data is read as strings
$n = count($tmp); $n = count($tmp);
$aData = array(); $aData = array();
$cnt=0; $cnt=0;
for($i=0; $i < $n; ++$i) { for($i=0; $i < $n; ++$i) {
if( $tmp[$i] !== "" ) { if( $tmp[$i] !== "" ) {
$aData[$cnt++] = floatval($tmp[$i]); $aData[$cnt++] = floatval($tmp[$i]);
} }
} }
return $cnt; return $cnt;
} }
   
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Desciption: // Desciption:
// Read numeric data from a file. // Read numeric data from a file.
// Each value should be separated by either a new line or by a specified // Each value should be separated by either a new line or by a specified
// separator character (default is ','). // separator character (default is ',').
// Before returning the data each value is converted to a proper float // 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 // value. The routine is robust in the sense that non numeric data in the
// file will be discarded. // file will be discarded.
// //
// Options: // Options:
// 'separator' => ',', // 'separator' => ',',
// 'enclosure' => '"', // 'enclosure' => '"',
// 'readlength' => 1024, // 'readlength' => 1024,
// 'ignore_first' => false, // 'ignore_first' => false,
// 'first_as_key' => false // 'first_as_key' => false
// 'escape' => '\', # PHP >= 5.3 only // 'escape' => '\', # PHP >= 5.3 only
// //
// Returns: // Returns:
// The number of lines read on success, FALSE on failure // The number of lines read on success, FALSE on failure
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static function FromCSV2($aFile, &$aData, $aOptions = array()) { static function FromCSV2($aFile, &$aData, $aOptions = array()) {
$aDefaults = array( $aDefaults = array(
'separator' => ',', 'separator' => ',',
'enclosure' => chr(34), 'enclosure' => chr(34),
'escape' => chr(92), 'escape' => chr(92),
'readlength' => 1024, 'readlength' => 1024,
'ignore_first' => false, 'ignore_first' => false,
'first_as_key' => false 'first_as_key' => false
); );
   
$aOptions = array_merge( $aOptions = array_merge(
$aDefaults, is_array($aOptions) ? $aOptions : array()); $aDefaults, is_array($aOptions) ? $aOptions : array());
   
if( $aOptions['first_as_key'] ) { if( $aOptions['first_as_key'] ) {
$aOptions['ignore_first'] = true; $aOptions['ignore_first'] = true;
} }
   
$rh = @fopen($aFile, 'r'); $rh = @fopen($aFile, 'r');
   
if( $rh === false ) { if( $rh === false ) {
return false; return false;
} }
   
$aData = array(); $aData = array();
$aLine = fgetcsv($rh, $aLine = fgetcsv($rh,
$aOptions['readlength'], $aOptions['readlength'],
$aOptions['separator'], $aOptions['separator'],
$aOptions['enclosure'] $aOptions['enclosure']
/*, $aOptions['escape'] # PHP >= 5.3 only */ /*, $aOptions['escape'] # PHP >= 5.3 only */
); );
   
// Use numeric array keys for the columns by default // Use numeric array keys for the columns by default
// If specified use first lines values as assoc keys instead // If specified use first lines values as assoc keys instead
$keys = array_keys($aLine); $keys = array_keys($aLine);
if( $aOptions['first_as_key'] ) { if( $aOptions['first_as_key'] ) {
$keys = array_values($aLine); $keys = array_values($aLine);
} }
   
$num_lines = 0; $num_lines = 0;
$num_cols = count($aLine); $num_cols = count($aLine);
   
while ($aLine !== false) { while ($aLine !== false) {
if( is_array($aLine) && count($aLine) != $num_cols ) { if( is_array($aLine) && count($aLine) != $num_cols ) {
JpGraphError::RaiseL(24004); JpGraphError::RaiseL(24004);
// 'ReadCSV2: Column count mismatch in %s line %d' // 'ReadCSV2: Column count mismatch in %s line %d'
} }
   
// fgetcsv returns NULL for empty lines // fgetcsv returns NULL for empty lines
if( !is_null($aLine) ) { if( !is_null($aLine) ) {
$num_lines++; $num_lines++;
   
if( !($aOptions['ignore_first'] && $num_lines == 1) && is_numeric($aLine[0]) ) { if( !($aOptions['ignore_first'] && $num_lines == 1) && is_numeric($aLine[0]) ) {
for( $i = 0; $i < $num_cols; $i++ ) { for( $i = 0; $i < $num_cols; $i++ ) {
$aData[ $keys[$i] ][] = floatval($aLine[$i]); $aData[ $keys[$i] ][] = floatval($aLine[$i]);
} }
} }
} }
   
$aLine = fgetcsv($rh, $aLine = fgetcsv($rh,
$aOptions['readlength'], $aOptions['readlength'],
$aOptions['separator'], $aOptions['separator'],
$aOptions['enclosure'] $aOptions['enclosure']
/*, $aOptions['escape'] # PHP >= 5.3 only*/ /*, $aOptions['escape'] # PHP >= 5.3 only*/
); );
} }
   
fclose($rh); fclose($rh);
   
if( $aOptions['ignore_first'] ) { if( $aOptions['ignore_first'] ) {
$num_lines--; $num_lines--;
} }
   
return $num_lines; return $num_lines;
} }
   
// Read data from two columns in a plain text file // Read data from two columns in a plain text file
static function From2Col($aFile, $aCol1, $aCol2, $aSepChar=' ') { static function From2Col($aFile, $aCol1, $aCol2, $aSepChar=' ') {
$lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
if( $lines === false ) { if( $lines === false ) {
return false; return false;
} }
$s = '/[\s]+/'; $s = '/[\s]+/';
if( $aSepChar == ',' ) { if( $aSepChar == ',' ) {
$s = '/[\s]*,[\s]*/'; $s = '/[\s]*,[\s]*/';
} }
elseif( $aSepChar == ';' ) { elseif( $aSepChar == ';' ) {
$s = '/[\s]*;[\s]*/'; $s = '/[\s]*;[\s]*/';
} }
foreach( $lines as $line => $datarow ) { foreach( $lines as $line => $datarow ) {
$split = preg_split($s,$datarow); $split = preg_split($s,$datarow);
$aCol1[] = floatval(trim($split[0])); $aCol1[] = floatval(trim($split[0]));
$aCol2[] = floatval(trim($split[1])); $aCol2[] = floatval(trim($split[1]));
} }
   
return count($lines); return count($lines);
} }
   
// Read data from one columns in a plain text file // Read data from one columns in a plain text file
static function From1Col($aFile, $aCol1) { static function From1Col($aFile, $aCol1) {
$lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
if( $lines === false ) { if( $lines === false ) {
return false; return false;
} }
foreach( $lines as $line => $datarow ) { foreach( $lines as $line => $datarow ) {
$aCol1[] = floatval(trim($datarow)); $aCol1[] = floatval(trim($datarow));
} }
   
return count($lines); return count($lines);
} }
   
static function FromMatrix($aFile,$aSepChar=' ') { static function FromMatrix($aFile,$aSepChar=' ') {
$lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
if( $lines === false ) { if( $lines === false ) {
return false; return false;
} }
$mat = array(); $mat = array();
$reg = '/'.$aSepChar.'/'; $reg = '/'.$aSepChar.'/';
foreach( $lines as $line => $datarow ) { foreach( $lines as $line => $datarow ) {
$row = preg_split($reg,trim($datarow)); $row = preg_split($reg,trim($datarow));
foreach ($row as $key => $cell ) { foreach ($row as $key => $cell ) {
$row[$key] = floatval(trim($cell)); $row[$key] = floatval(trim($cell));
} }
$mat[] = $row; $mat[] = $row;
} }
return $mat; return $mat;
} }
   
   
} }
   
define('__LR_EPSILON', 1.0e-8); define('__LR_EPSILON', 1.0e-8);
//============================================================================= //=============================================================================
// Class LinearRegression // Class LinearRegression
//============================================================================= //=============================================================================
class LinearRegression { class LinearRegression {
private $ix=array(),$iy=array(); private $ix=array(),$iy=array();
private $ib=0, $ia=0; private $ib=0, $ia=0;
private $icalculated=false; private $icalculated=false;
public $iDet=0, $iCorr=0, $iStdErr=0; public $iDet=0, $iCorr=0, $iStdErr=0;
   
public function __construct($aDataX,$aDataY) { public function __construct($aDataX,$aDataY) {
if( count($aDataX) !== count($aDataY) ) { if( count($aDataX) !== count($aDataY) ) {
JpGraph::Raise('LinearRegression: X and Y data array must be of equal length.'); JpGraph::Raise('LinearRegression: X and Y data array must be of equal length.');
} }
$this->ix = $aDataX; $this->ix = $aDataX;
$this->iy = $aDataY; $this->iy = $aDataY;
} }
   
public function Calc() { public function Calc() {
   
$this->icalculated = true; $this->icalculated = true;
   
$n = count($this->ix); $n = count($this->ix);
$sx2 = 0 ; $sx2 = 0 ;
$sy2 = 0 ; $sy2 = 0 ;
$sxy = 0 ; $sxy = 0 ;
$sx = 0 ; $sx = 0 ;
$sy = 0 ; $sy = 0 ;
   
for( $i=0; $i < $n; ++$i ) { for( $i=0; $i < $n; ++$i ) {
$sx2 += $this->ix[$i] * $this->ix[$i]; $sx2 += $this->ix[$i] * $this->ix[$i];
$sy2 += $this->iy[$i] * $this->iy[$i]; $sy2 += $this->iy[$i] * $this->iy[$i];
$sxy += $this->ix[$i] * $this->iy[$i]; $sxy += $this->ix[$i] * $this->iy[$i];
$sx += $this->ix[$i]; $sx += $this->ix[$i];
$sy += $this->iy[$i]; $sy += $this->iy[$i];
} }
   
if( $n*$sx2 - $sx*$sx > __LR_EPSILON ) { if( $n*$sx2 - $sx*$sx > __LR_EPSILON ) {
$this->ib = ($n*$sxy - $sx*$sy) / ( $n*$sx2 - $sx*$sx ); $this->ib = ($n*$sxy - $sx*$sy) / ( $n*$sx2 - $sx*$sx );
$this->ia = ( $sy - $this->ib*$sx ) / $n; $this->ia = ( $sy - $this->ib*$sx ) / $n;
   
$sx = $this->ib * ( $sxy - $sx*$sy/$n ); $sx = $this->ib * ( $sxy - $sx*$sy/$n );
$sy2 = $sy2 - $sy*$sy/$n; $sy2 = $sy2 - $sy*$sy/$n;
$sy = $sy2 - $sx; $sy = $sy2 - $sx;
   
$this->iDet = $sx / $sy2; $this->iDet = $sx / $sy2;
$this->iCorr = sqrt($this->iDet); $this->iCorr = sqrt($this->iDet);
if( $n > 2 ) { if( $n > 2 ) {
$this->iStdErr = sqrt( $sy / ($n-2) ); $this->iStdErr = sqrt( $sy / ($n-2) );
} }
else { else {
$this->iStdErr = NAN ; $this->iStdErr = NAN ;
} }
} }
else { else {
$this->ib = 0; $this->ib = 0;
$this->ia = 0; $this->ia = 0;
} }
   
} }
   
public function GetAB() { public function GetAB() {
if( $this->icalculated == false ) if( $this->icalculated == false )
$this->Calc(); $this->Calc();
return array($this->ia, $this->ib); return array($this->ia, $this->ib);
} }
   
public function GetStat() { public function GetStat() {
if( $this->icalculated == false ) if( $this->icalculated == false )
$this->Calc(); $this->Calc();
return array($this->iStdErr, $this->iCorr, $this->iDet); return array($this->iStdErr, $this->iCorr, $this->iDet);
} }
   
public function GetY($aMinX, $aMaxX, $aStep=1) { public function GetY($aMinX, $aMaxX, $aStep=1) {
if( $this->icalculated == false ) if( $this->icalculated == false )
$this->Calc(); $this->Calc();
   
$yy = array(); $yy = array();
$i = 0; $i = 0;
for( $x=$aMinX; $x <= $aMaxX; $x += $aStep ) { for( $x=$aMinX; $x <= $aMaxX; $x += $aStep ) {
$xx[$i ] = $x; $xx[$i ] = $x;
$yy[$i++] = $this->ia + $this->ib * $x; $yy[$i++] = $this->ia + $this->ib * $x;
} }
   
return array($xx,$yy); return array($xx,$yy);
} }
   
} }
   
?> ?>
<?php <?php
/*======================================================================= /*=======================================================================
// File: DE.INC.PHP // File: DE.INC.PHP
// Description: German language file for error messages // Description: German language file for error messages
// Created: 2006-03-06 // Created: 2006-03-06
// Author: Timo Leopold (timo@leopold-hh.de) // Author: Timo Leopold (timo@leopold-hh.de)
// Johan Persson (ljp@localhost.nil) // Johan Persson (ljp@localhost.nil)
// Ver: $Id: de.inc.php 1886 2009-10-01 23:30:16Z ljp $ // Ver: $Id: de.inc.php 1886 2009-10-01 23:30:16Z ljp $
// //
// Copyright (c) // Copyright (c)
//======================================================================== //========================================================================
*/ */
   
// Notiz: Das Format fuer jede Fehlermeldung ist array(<Fehlermeldung>,<Anzahl der Argumente>) // Notiz: Das Format fuer jede Fehlermeldung ist array(<Fehlermeldung>,<Anzahl der Argumente>)
$_jpg_messages = array( $_jpg_messages = array(
   
/* /*
** Headers wurden bereits gesendet - Fehler. Dies wird als HTML formatiert, weil es direkt als text zurueckgesendet wird ** Headers wurden bereits gesendet - Fehler. Dies wird als HTML formatiert, weil es direkt als text zurueckgesendet wird
*/ */
10 => array('<table border="1"><tr><td style="color:darkred;font-size:1.2em;"><b>JpGraph Fehler:</b> 10 => array('<table border="1"><tr><td style="color:darkred;font-size:1.2em;"><b>JpGraph Fehler:</b>
HTTP header wurden bereits gesendet.<br>Fehler in der Datei <b>%s</b> in der Zeile <b>%d</b>.</td></tr><tr><td><b>Erklärung:</b><br>HTTP header wurden bereits zum Browser gesendet, wobei die Daten als Text gekennzeichnet wurden, bevor die Bibliothek die Chance hatte, seinen Bild-HTTP-Header zum Browser zu schicken. Dies verhindert, dass die Bibliothek Bilddaten zum Browser schicken kann (weil sie vom Browser als Text interpretiert würden und daher nur Mist dargestellt würde).<p>Wahrscheinlich steht Text im Skript bevor <i>Graph::Stroke()</i> aufgerufen wird. Wenn dieser Text zum Browser gesendet wird, nimmt dieser an, dass die gesamten Daten aus Text bestehen. Such nach irgendwelchem Text, auch nach Leerzeichen und Zeilenumbrüchen, die eventuell bereits zum Browser gesendet wurden. <p>Zum Beispiel ist ein oft auftretender Fehler, eine Leerzeile am Anfang der Datei oder vor <i>Graph::Stroke()</i> zu lassen."<b>&lt;?php</b>".</td></tr></table>',2), HTTP header wurden bereits gesendet.<br>Fehler in der Datei <b>%s</b> in der Zeile <b>%d</b>.</td></tr><tr><td><b>Erklärung:</b><br>HTTP header wurden bereits zum Browser gesendet, wobei die Daten als Text gekennzeichnet wurden, bevor die Bibliothek die Chance hatte, seinen Bild-HTTP-Header zum Browser zu schicken. Dies verhindert, dass die Bibliothek Bilddaten zum Browser schicken kann (weil sie vom Browser als Text interpretiert würden und daher nur Mist dargestellt würde).<p>Wahrscheinlich steht Text im Skript bevor <i>Graph::Stroke()</i> aufgerufen wird. Wenn dieser Text zum Browser gesendet wird, nimmt dieser an, dass die gesamten Daten aus Text bestehen. Such nach irgendwelchem Text, auch nach Leerzeichen und Zeilenumbrüchen, die eventuell bereits zum Browser gesendet wurden. <p>Zum Beispiel ist ein oft auftretender Fehler, eine Leerzeile am Anfang der Datei oder vor <i>Graph::Stroke()</i> zu lassen."<b>&lt;?php</b>".</td></tr></table>',2),
   
/* /*
** Setup Fehler ** 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), 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), 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), 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 ** jpgraph_bar
*/ */
   
2001 => array('Die Anzahl der Farben ist nicht gleich der Anzahl der Vorlagen in BarPlot::SetPattern().',0), 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), 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), 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), 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), 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), 2006 => array('Unbekannte Position für die Werte der Balken: %s.',1),
2007 => array('Kann GroupBarPlot nicht aus einem leeren Vektor erzeugen.',0), 2007 => array('Kann GroupBarPlot nicht aus einem leeren Vektor erzeugen.',0),
2008 => array('GroupBarPlot Element nbr %d wurde nicht definiert oder ist leer.',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), 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), 2010 => array('Kann AccBarPlot nicht aus einem leeren Vektor erzeugen.',0),
2011 => array('AccBarPlot-Element nbr %d wurde nicht definiert oder ist leer.',1), 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), 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), 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), 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), 2015 => array('Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-coordinates',0),
   
   
/* /*
** jpgraph_date ** jpgraph_date
*/ */
   
3001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0), 3001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0),
   
/* /*
** jpgraph_error ** jpgraph_error
*/ */
   
4002 => array('Fehler bei den Eingabedaten von LineErrorPlot. Die Anzahl der Datenpunkte mus ein Mehrfaches von drei sein!',0), 4002 => array('Fehler bei den Eingabedaten von LineErrorPlot. Die Anzahl der Datenpunkte mus ein Mehrfaches von drei sein!',0),
   
/* /*
** jpgraph_flags ** jpgraph_flags
*/ */
   
5001 => array('Unbekannte Flaggen-Größe (%d).',1), 5001 => array('Unbekannte Flaggen-Größe (%d).',1),
5002 => array('Der Flaggen-Index %s existiert nicht.',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), 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), 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 ** jpgraph_gantt
*/ */
   
6001 => array('Interner Fehler. Die Höhe für ActivityTitles ist < 0.',0), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 6012 => array('Unbekannter Typ bei der Gantt-Objekt-Title-Definition.',0),
6015 => array('Ungültige vertikale Position %d',1), 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), 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), 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), 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), 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), 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), 6021 => array('Unbekanntes Format für die Woche.',0),
6022 => array('Die Gantt-Skala wurde nicht eingegeben.',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), 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), 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), 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), 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), 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), 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), 6030 => array('Unbekannte Pfeilrichtung für eine Verbindung.',0),
6031 => array('Unbekannter Pfeiltyp 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), 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), 6033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0),
   
/* /*
** jpgraph_gradient ** jpgraph_gradient
*/ */
   
7001 => array('Unbekannter Gradiententyp (=%d).',1), 7001 => array('Unbekannter Gradiententyp (=%d).',1),
   
/* /*
** jpgraph_iconplot ** jpgraph_iconplot
*/ */
   
8001 => array('Der Mix-Wert für das Icon muss zwischen 0 und 100 sein.',0), 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), 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), 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), 8004 => array('Wenn Du Landesflaggen benutzen willst, musst Du die Datei "jpgraph_flags.php" hinzufügen (per include).',0),
   
/* /*
** jpgraph_imgtrans ** 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), 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 ** jpgraph_lineplot
*/ */
   
10001 => array('Die Methode LinePlot::SetFilled() sollte nicht mehr benutzt werden. Benutze lieber SetFillColor()',0), 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), 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), 10003 => array('Each plot in an accumulated lineplot must have the same number of data points.',0),
/* /*
** jpgraph_log ** jpgraph_log
*/ */
   
11001 => array('Deine Daten enthalten nicht-numerische Werte.',0), 11001 => array('Deine Daten enthalten nicht-numerische Werte.',0),
11002 => array('Negative Werte können nicht für logarithmische Achsen verwendet werden.',0), 11002 => array('Negative Werte können nicht für logarithmische Achsen verwendet werden.',0),
11003 => array('Deine Daten enthalten nicht-numerische Werte.',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), 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), 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 ** 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 12012 => array('Es konnte kein Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
   
/* /*
** jpgraph_pie3d ** jpgraph_pie3d
*/ */
   
14001 => array('Pie3D::ShowBorder(). Missbilligte Funktion. Benutze Pie3D::SetEdge(), um die Ecken der Tortenstücke zu kontrollieren.',0), 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), 14002 => array('PiePlot3D::SetAngle() 3D-Torten-Projektionswinkel muss zwischen 5 und 85 Grad sein.',0),
14003 => array('Interne Festlegung schlug fehl. Pie3D::Pie3DSlice',0), 14003 => array('Interne Festlegung schlug fehl. Pie3D::Pie3DSlice',0),
14004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',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,), 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), 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), 14007 => array('Die Breite für das 3D-Tortendiagramm ist 0. Gib eine Breite > 0 an.',0),
   
/* /*
** jpgraph_pie ** jpgraph_pie
*/ */
   
15001 => array('PiePLot::SetTheme() Unbekannter Stil: %s',1), 15001 => array('PiePLot::SetTheme() Unbekannter Stil: %s',1),
15002 => array('Argument für PiePlot::ExplodeSlice() muss ein Integer-Wert sein',0), 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), 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), 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), 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), 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), 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), 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), 15009 => array('Ungültiges Tortendiagramm. Die Summe aller Daten ist Null.',0),
15010 => array('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), 15011 => array('Um Bildtransformationen benutzen zu können, muss die Datei jpgraph_imgtrans.php eingefügt werden (per include).',0),
   
/* /*
** jpgraph_plotband ** jpgraph_plotband
*/ */
   
16001 => array('Die Dichte für das Pattern muss zwischen 1 und 100 sein. (Du hast %f eingegeben)',1), 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), 16002 => array('Es wurde keine Position für das Pattern angegeben.',0),
16003 => array('Unbekannte Pattern-Definition (%d)',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), 16004 => array('Der Mindeswert für das PlotBand ist größer als der Maximalwert. Bitte korrigiere dies!',0),
   
   
/* /*
** jpgraph_polar ** jpgraph_polar
*/ */
   
17001 => array('PolarPlots müssen eine gerade Anzahl von Datenpunkten haben. Jeder Datenpunkt ist ein Tupel (Winkel, Radius).',0), 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), 17002 => array('Unbekannte Ausrichtung für X-Achsen-Titel. (%s)',1),
//17003 => array('Set90AndMargin() wird für PolarGraph nicht unterstützt.',0), //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), 17004 => array('Unbekannter Achsentyp für PolarGraph. Er muss entweder \'lin\' oder \'log\' sein.',0),
   
/* /*
** jpgraph_radar ** jpgraph_radar
*/ */
   
18001 => array('ClientSideImageMaps werden für RadarPlots nicht unterstützt.',0), 18001 => array('ClientSideImageMaps werden für RadarPlots nicht unterstützt.',0),
18002 => array('RadarGraph::SupressTickMarks() sollte nicht mehr verwendet werden. Benutze stattdessen HideTickMarks().',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), 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), 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), 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), 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), 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), 18008 => array('Jeder RadarPlot muss die gleiche Anzahl von Datenpunkten haben.',0),
   
/* /*
** jpgraph_regstat ** jpgraph_regstat
*/ */
   
19001 => array('Spline: Anzahl der X- und Y-Koordinaten muss gleich sein.',0), 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), 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), 19003 => array('Bezier: Anzahl der X- und Y-Koordinaten muss gleich sein.',0),
   
/* /*
** jpgraph_scatter ** jpgraph_scatter
*/ */
   
20001 => array('Fieldplots müssen die gleiche Anzahl von X und Y Datenpunkten haben.',0), 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), 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), 20003 => array('Scatterplots müssen die gleiche Anzahl von X- und Y-Datenpunkten haben.',0),
   
/* /*
** jpgraph_stock ** jpgraph_stock
*/ */
   
21001 => array('Die Anzahl der Datenwerte für Stock-Charts müssen ein Mehrfaches von %d Datenpunkten sein.',1), 21001 => array('Die Anzahl der Datenwerte für Stock-Charts müssen ein Mehrfaches von %d Datenpunkten sein.',1),
   
/* /*
** jpgraph_plotmark ** jpgraph_plotmark
*/ */
   
23001 => array('Der Marker "%s" existiert nicht in der Farbe: %d',2), 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), 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), 23003 => array('Ein Dateiname muss angegeben werden, wenn Du den Marker-Typ auf MARK_IMG setzt.',0),
   
/* /*
** jpgraph_utils ** jpgraph_utils
*/ */
   
24001 => array('FuncGenerator : Keine Funktion definiert. ',0), 24001 => array('FuncGenerator : Keine Funktion definiert. ',0),
24002 => array('FuncGenerator : Syntax-Fehler in der Funktionsdefinition ',0), 24002 => array('FuncGenerator : Syntax-Fehler in der Funktionsdefinition ',0),
24003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',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), 24004 => array('ReadCSV2: Die anzahl der spalten fehler in %s reihe %d',2),
/* /*
** jpgraph ** 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), 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), 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), 25003 => array('Genereller PHP Fehler : Bei %s:%d : %s',3),
25004 => array('Genereller PHP Fehler : %s ',1), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25021 => array('Unbekannte Achsendefinition für die Y-Achse. (%s)',1),
25022 => array('Unbekannte Achsendefinition für die X-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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25032 => array('Es existieren keine Plots für die Y-Achse nbr:%d',1),
25033 => array('',0), 25033 => array('',0),
25034 => array('Undefinierte X-Achse kann nicht gezeichnet werden. Es wurden keine Plots definiert.',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), 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), 25036 => array('Unbekannter Achsentyp AxisStyle() : %s',1),
25037 => array('Das Bildformat Deines Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',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), 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), 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), 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), 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), 25042 => array('Unbekanntes Hintergrundbild-Layout',0),
25043 => array('Unbekannter Titelhintergrund-Stil.',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), 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), 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), 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), 25047 => array('Stil %s ist nicht verfügbar für Schriftfamilie %s',2),
25048 => array('Unbekannte Schriftstildefinition [%s].',1), 25048 => array('Unbekannte Schriftstildefinition [%s].',1),
25049 => array('Schriftdatei "%s" ist nicht lesbar oder existiert nicht.',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), 25050 => array('Erstes Argument für Text::Text() muss ein String sein.',0),
25051 => array('Ungültige Richtung angegeben für Text.',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), 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), 25053 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte horizontale Ausrichtung für Text.',0),
25054 => array('Interner Fehler: Unbekannte Grid-Achse %s',1), 25054 => array('Interner Fehler: Unbekannte Grid-Achse %s',1),
25055 => array('Axis::SetTickDirection() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetTickSide().',0), 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), 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), 25057 => array('SetTextTicks() sollte nicht mehr verwendet werden. Benutze stattdessen SetTextTickInterval().',0),
25058 => array('TextLabelIntevall >= 1 muss angegeben werden.',0), 25058 => array('TextLabelIntevall >= 1 muss angegeben werden.',0),
25059 => array('SetLabelPos() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetLabelSide().',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), 25060 => array('Unbekannte Ausrichtung angegeben für X-Achsentitel (%s).',1),
25061 => array('Unbekannte Ausrichtung angegeben für Y-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), 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), 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), 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), 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), 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), 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), 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), 25069 => array('Grace muss größer sein als 0',0),
   
25070 => array('Deine Daten enthalten nicht-numerische Werte.',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), 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), 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), 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), 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), 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), 25077 => array('Einstellfaktor für die Farbe muss größer sein als 0',0),
25078 => array('Unbekannte Farbe: %s',1), 25078 => array('Unbekannte Farbe: %s',1),
25079 => array('Unbekannte Farbdefinition: %s, Größe=%d',2), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25094 => array('Die Textrichtung muss in einem Winkel zwischen 0 und 90 engegeben werden.',0),
25095 => array('Unbekannte Schriftfamilien-Definition. ',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), 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), 25097 => array('Eine Farbe wurde als leerer String im Aufruf von PushColor() angegegeben.',0),
25098 => array('Negativer Farbindex. Unpassender Aufruf von PopColor().',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), 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), 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), 25101 => array('Ungültiges numerisches Argument für SetLineStyle(): (%d)',1),
25102 => array('Ungültiges String-Argument für SetLineStyle(): %s',1), 25102 => array('Ungültiges String-Argument für SetLineStyle(): %s',1),
25103 => array('Ungültiges Argument für SetLineStyle %s',1), 25103 => array('Ungültiges Argument für SetLineStyle %s',1),
25104 => array('Unbekannter Linientyp: %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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0),
   
/* /*
** jpgraph_led ** 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), 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 ** Pro-version strings
**--------------------------------------------------------------------------------------------- **---------------------------------------------------------------------------------------------
*/ */
   
/* /*
** jpgraph_table ** jpgraph_table
*/ */
   
27001 => array('GTextTable: Ungültiges Argument für Set(). Das Array-Argument muss 2-- dimensional sein.',0), 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), 27002 => array('GTextTable: Ungültiges Argument für Set()',0),
27003 => array('GTextTable: Falsche Anzahl von Argumenten für GTextTable::SetColor()',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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 27015 => array('GTextTable: Der Zellenbildbedingungstyp muss entweder TIMG_WIDTH oder TIMG_HEIGHT sein.',0),
   
/* /*
** jpgraph_windrose ** jpgraph_windrose
*/ */
   
22001 => array('Die Gesamtsumme der prozentualen Anteile aller Windrosenarme darf 100%% nicht überschreiten!\n(Aktuell max: %d)',1), 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), 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), 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), 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), 22006 => array('Es wurde ein ungültiger Windrosentyp angegeben.',0),
22007 => array('Es wurden zu wenig Werte für die Bereichslegende 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), 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), 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), 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), 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), 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), 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), 22014 => array('Der Index für eine Kompassrichtung muss zwischen 0 und 15 sein.',0),
22015 => array('Du hast einen unbekannten Windrosenplottyp angegeben.',0), 22015 => array('Du hast einen unbekannten Windrosenplottyp angegeben.',0),
22016 => array('Der Windrosenarmindex muss ein numerischer oder ein Richtungswert sein.',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), 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), 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), 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), 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), 22021 => array('It is only possible to add Text, IconPlot or WindrosePlot to a Windrose Graph',0),
   
/* /*
** jpgraph_odometer ** jpgraph_odometer
*/ */
   
13001 => array('Unbekannter Nadeltypstil (%d).',1), 13001 => array('Unbekannter Nadeltypstil (%d).',1),
13002 => array('Ein Wert für das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3), 13002 => array('Ein Wert für das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3),
   
/* /*
** jpgraph_barcode ** jpgraph_barcode
*/ */
   
1001 => array('Unbekannte Kodier-Specifikation: %s',1), 1001 => array('Unbekannte Kodier-Specifikation: %s',1),
1002 => array('datenvalidierung schlug fehl. [%s] kann nicht mittels der Kodierung "%s" kodiert werden',2), 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), 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), 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), 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), 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), 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), 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), 1009 => array('Kodieren mittels CODE 93 wird noch nicht unterstützt.',0),
1010 => array('Kodieren mittels POSTNET 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), 1011 => array('Nicht untrstütztes Barcode-Backend für den Typ %s',1),
   
/* /*
** PDF417 ** 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 26010 => array('PDF417: Interner Fehler: Keine Eingabedaten beim Dekodieren.',0),
26011 => array('PDF417: Kodierfehler. Numerisches Kodieren bei nicht-numerischen Daten nicht möglich.',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), 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), 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), 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), 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), 26016 => array('PDF417: Interner Fehler: Nichtregistrierter Statusübertragungsmodus beim Dekodieren.',0),
   
   
/* /*
** jpgraph_contour ** jpgraph_contour
*/ */
   
28001 => array('Dritten parameter fur Contour muss ein vector der fargen sind.',0), 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), 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), 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), 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), 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), 28006 => array('ContourPlot Interner Fehler: isobarVCrossing: Spalten index ist zu hoch (%d)',1),
28007 => array('ContourPlot. Interpolation faktor ist zu hoch (>5)',0), 28007 => array('ContourPlot. Interpolation faktor ist zu hoch (>5)',0),
   
   
/* /*
* jpgraph_matrix and colormap * jpgraph_matrix and colormap
*/ */
29201 => array('Min range value must be less or equal to max range value for colormaps',0), 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), 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), 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), 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), 29205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1),
29206 => array('Invalid object added to MatrixGraph',0), 29206 => array('Invalid object added to MatrixGraph',0),
29207 => array('Empty input data specified for MatrixPlot',0), 29207 => array('Empty input data specified for MatrixPlot',0),
29208 => array('Unknown side specifiction for matrix labels "%s"',1), 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), 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), 29210 => array('CSIM Target for matrix labels does not match the number of labels (csim=%d, labels=%d)',2),
   
); );
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: EN.INC.PHP // File: EN.INC.PHP
// Description: English language file for error messages // Description: English language file for error messages
// Created: 2006-01-25 // Created: 2006-01-25
// Ver: $Id: en.inc.php 1886 2009-10-01 23:30:16Z ljp $ // Ver: $Id: en.inc.php 1886 2009-10-01 23:30:16Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
// Note: Format of each error message is array(<error message>,<number of arguments>) // Note: Format of each error message is array(<error message>,<number of arguments>)
$_jpg_messages = array( $_jpg_messages = array(
   
/* /*
** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text ** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text
*/ */
10 => array('<table border="1"><tr><td style="color:darkred; font-size:1.2em;"><b>JpGraph Error:</b> 10 => array('<table border="1"><tr><td style="color:darkred; font-size:1.2em;"><b>JpGraph Error:</b>
HTTP headers have already been sent.<br>Caused by output from file <b>%s</b> at line <b>%d</b>.</td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it\'s image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening "<b>&lt;?php</b>".</td></tr></table>',2), HTTP headers have already been sent.<br>Caused by output from file <b>%s</b> at line <b>%d</b>.</td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it\'s image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening "<b>&lt;?php</b>".</td></tr></table>',2),
   
/* /*
** Setup errors ** Setup errors
*/ */
11 => array('No path specified for CACHE_DIR. Please specify CACHE_DIR manually in jpg-config.inc',0), 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), 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), 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 ** jpgraph_bar
*/ */
   
2001 => array('Number of colors is not the same as the number of patterns in BarPlot::SetPattern()',0), 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), 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), 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), 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), 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), 2006 => array('Unknown position for values on bars : %s',1),
2007 => array('Cannot create GroupBarPlot from empty plot array.',0), 2007 => array('Cannot create GroupBarPlot from empty plot array.',0),
2008 => array('Group bar plot element nbr %d is undefined or empty.',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), 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), 2010 => array('Cannot create AccBarPlot from empty plot array.',0),
2011 => array('Acc bar plot element nbr %d is undefined or empty.',1), 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), 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), 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), 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), 2015 => array('Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-coordinates',0),
   
   
/* /*
** jpgraph_date ** jpgraph_date
*/ */
   
3001 => array('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both',0), 3001 => array('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both',0),
   
/* /*
** jpgraph_error ** jpgraph_error
*/ */
   
4002 => array('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3',0), 4002 => array('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3',0),
   
/* /*
** jpgraph_flags ** jpgraph_flags
*/ */
   
5001 => array('Unknown flag size (%d).',1), 5001 => array('Unknown flag size (%d).',1),
5002 => array('Flag index %s does not exist.',1), 5002 => array('Flag index %s does not exist.',1),
5003 => array('Invalid ordinal number (%d) specified for flag index.',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), 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 ** jpgraph_gantt
*/ */
   
6001 => array('Internal error. Height for ActivityTitles is < 0',0), 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), 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), 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), 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), 6005 => array('SetScale() is not meaningful with Gantt charts.',0),
6006 => array('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]',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), 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), 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), 6009 => array('Unknown constrain type specified from row=%d to row=%d',2),
6010 => array('Illegal icon index for Gantt builtin icon [%d]',1), 6010 => array('Illegal icon index for Gantt builtin icon [%d]',1),
6011 => array('Argument to IconImage must be string or integer',0), 6011 => array('Argument to IconImage must be string or integer',0),
6012 => array('Unknown type in Gantt object title specification',0), 6012 => array('Unknown type in Gantt object title specification',0),
6015 => array('Illegal vertical position %d',1), 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), 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), 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), 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), 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), 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), 6021 => array('Unknown formatting style for week.',0),
6022 => array('Gantt scale has not been specified.',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), 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), 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), 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), 6027 => array('Progress value must in range [0, 1]',0),
6028 => array('Specified height (%d) for gantt bar is out of range.',1), 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), 6029 => array('Offset for vertical line must be in range [0,1]',0),
6030 => array('Unknown arrow direction for link.',0), 6030 => array('Unknown arrow direction for link.',0),
6031 => array('Unknown arrow type for link.',0), 6031 => array('Unknown arrow type for link.',0),
6032 => array('Internal error: Unknown path type (=%d) specified for link.',1), 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), 6033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0),
   
/* /*
** jpgraph_gradient ** jpgraph_gradient
*/ */
   
7001 => array('Unknown gradient style (=%d).',1), 7001 => array('Unknown gradient style (=%d).',1),
   
/* /*
** jpgraph_iconplot ** jpgraph_iconplot
*/ */
   
8001 => array('Mix value for icon must be between 0 and 100.',0), 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), 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), 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), 8004 => array('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.',0),
   
/* /*
** jpgraph_imgtrans ** 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), 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 ** jpgraph_lineplot
*/ */
   
10001 => array('LinePlot::SetFilled() is deprecated. Use SetFillColor()',0), 10001 => array('LinePlot::SetFilled() is deprecated. Use SetFillColor()',0),
10002 => array('Plot too complicated for fast line Stroke. Use standard Stroke()',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), 10003 => array('Each plot in an accumulated lineplot must have the same number of data points.',0),
   
/* /*
** jpgraph_log ** jpgraph_log
*/ */
   
11001 => array('Your data contains non-numeric values.',0), 11001 => array('Your data contains non-numeric values.',0),
11002 => array('Negative data values can not be used in a log scale.',0), 11002 => array('Negative data values can not be used in a log scale.',0),
11003 => array('Your data contains non-numeric values.',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), 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), 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 ** 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 12012 => array('Can\'t create image. Check that you really have GD2 library installed.',0),
   
/* /*
** jpgraph_pie3d ** jpgraph_pie3d
*/ */
   
14001 => array('Pie3D::ShowBorder() . Deprecated function. Use Pie3D::SetEdge() to control the edges around slices.',0), 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), 14002 => array('PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.',0),
14003 => array('Internal assertion failed. Pie3D::Pie3DSlice',0), 14003 => array('Internal assertion failed. Pie3D::Pie3DSlice',0),
14004 => array('Slice start angle must be between 0 and 360 degrees.',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,), 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), 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), 14007 => array('Width for 3D Pie is 0. Specify a size > 0',0),
   
/* /*
** jpgraph_pie ** jpgraph_pie
*/ */
   
15001 => array('PiePLot::SetTheme() Unknown theme: %s',1), 15001 => array('PiePLot::SetTheme() Unknown theme: %s',1),
15002 => array('Argument to PiePlot::ExplodeSlice() must be an integer',0), 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), 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), 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), 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), 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), 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), 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), 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), 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), 15011 => array('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.',0),
   
/* /*
** jpgraph_plotband ** jpgraph_plotband
*/ */
   
16001 => array('Density for pattern must be between 1 and 100. (You tried %f)',1), 16001 => array('Density for pattern must be between 1 and 100. (You tried %f)',1),
16002 => array('No positions specified for pattern.',0), 16002 => array('No positions specified for pattern.',0),
16003 => array('Unknown pattern specification (%d)',0), 16003 => array('Unknown pattern specification (%d)',0),
16004 => array('Min value for plotband is larger than specified max value. Please correct.',0), 16004 => array('Min value for plotband is larger than specified max value. Please correct.',0),
   
   
/* /*
** jpgraph_polar ** jpgraph_polar
*/ */
   
17001 => array('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).',0), 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), 17002 => array('Unknown alignment specified for X-axis title. (%s)',1),
//17003 => array('Set90AndMargin() is not supported for polar graphs.',0), //17003 => array('Set90AndMargin() is not supported for polar graphs.',0),
17004 => array('Unknown scale type for polar graph. Must be "lin" or "log"',0), 17004 => array('Unknown scale type for polar graph. Must be "lin" or "log"',0),
   
/* /*
** jpgraph_radar ** jpgraph_radar
*/ */
   
18001 => array('Client side image maps not supported for RadarPlots.',0), 18001 => array('Client side image maps not supported for RadarPlots.',0),
18002 => array('RadarGraph::SupressTickMarks() is deprecated. Use HideTickMarks() instead.',0), 18002 => array('RadarGraph::SupressTickMarks() is deprecated. Use HideTickMarks() instead.',0),
18003 => array('Illegal scale for radarplot (%s). Must be \'lin\' or \'log\'',1), 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), 18004 => array('Radar Plot size must be between 0.1 and 1. (Your value=%f)',1),
18005 => array('RadarPlot Unsupported Tick density: %d',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), 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), 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), 18008 => array('Each radar plot must have the same number of data points.',0),
   
/* /*
** jpgraph_regstat ** jpgraph_regstat
*/ */
   
19001 => array('Spline: Number of X and Y coordinates must be the same',0), 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), 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), 19003 => array('Bezier: Number of X and Y coordinates must be the same',0),
   
/* /*
** jpgraph_scatter ** jpgraph_scatter
*/ */
   
20001 => array('Fieldplots must have equal number of X and Y points.',0), 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), 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), 20003 => array('Scatterplot must have equal number of X and Y points.',0),
   
/* /*
** jpgraph_stock ** jpgraph_stock
*/ */
   
21001 => array('Data values for Stock charts must contain an even multiple of %d data points.',1), 21001 => array('Data values for Stock charts must contain an even multiple of %d data points.',1),
   
/* /*
** jpgraph_plotmark ** jpgraph_plotmark
*/ */
   
23001 => array('This marker "%s" does not exist in color with index: %d',2), 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), 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), 23003 => array('A filename must be specified if you set the mark type to MARK_IMG.',0),
   
/* /*
** jpgraph_utils ** jpgraph_utils
*/ */
   
24001 => array('FuncGenerator : No function specified. ',0), 24001 => array('FuncGenerator : No function specified. ',0),
24002 => array('FuncGenerator : Syntax error in function specification ',0), 24002 => array('FuncGenerator : Syntax error in function specification ',0),
24003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0), 24003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0),
24004 => array('ReadCSV2: Column count mismatch in %s line %d',2), 24004 => array('ReadCSV2: Column count mismatch in %s line %d',2),
/* /*
** jpgraph ** 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), 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), 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), 25003 => array('General PHP error : At %s:%d : %s',3),
25004 => array('General PHP error : %s ',1), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25021 => array('Unknown scale specification for Y-scale. (%s)',1),
25022 => array('Unknown scale specification for X-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), 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), 25024 => array('Unsupported Y axis type: "%s" Must be one of (lin,log,int)',1),
25025 => array('Unsupported Tick density: %d',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), 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), 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), 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), 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), 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), 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), 25032 => array('No plots for Y-axis nbr:%d',1),
25033 => array('',0), 25033 => array('',0),
25034 => array('Can\'t draw unspecified X-scale. No plots specified.',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), 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), 25036 => array('Unknown AxisStyle() : %s',1),
25037 => array('The image format of your background image (%s) is not supported in your system configuration. ',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), 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), 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), 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), 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), 25042 => array('Unknown background image layout',0),
25043 => array('Unknown title background style.',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), 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), 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), 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), 25047 => array('Style %s is not available for font family %s',2),
25048 => array('Unknown font style specification [%s].',1), 25048 => array('Unknown font style specification [%s].',1),
25049 => array('Font file "%s" is not readable or does not exist.',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), 25050 => array('First argument to Text::Text() must be a string.',0),
25051 => array('Invalid direction specified for text.',0), 25051 => array('Invalid direction specified for text.',0),
25052 => array('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment 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), 25053 => array('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text',0),
25054 => array('Internal error: Unknown grid axis %s',1), 25054 => array('Internal error: Unknown grid axis %s',1),
25055 => array('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead',0), 25055 => array('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead',0),
25056 => array('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.',0), 25056 => array('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.',0),
25057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0), 25057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0),
25058 => array('Text label interval must be specified >= 1.',0), 25058 => array('Text label interval must be specified >= 1.',0),
25059 => array('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.',0), 25059 => array('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.',0),
   
25060 => array('Unknown alignment specified for X-axis title. (%s)',1), 25060 => array('Unknown alignment specified for X-axis title. (%s)',1),
25061 => array('Unknown alignment specified for Y-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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25075 => array('Can\'t automatically determine ticks since min==max.',0),
25077 => array('Adjustment factor for color must be > 0',0), 25077 => array('Adjustment factor for color must be > 0',0),
25078 => array('Unknown color: %s',1), 25078 => array('Unknown color: %s',1),
25079 => array('Unknown color specification: %s, size=%d',2), 25079 => array('Unknown color specification: %s, size=%d',2),
   
25080 => array('Alpha parameter for color must be between 0.0 and 1.0',0), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25094 => array('Direction for text most be given as an angle between 0 and 90.',0),
25095 => array('Unknown font font family specification. ',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), 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), 25097 => array('Color specified as empty string in PushColor().',0),
25098 => array('Negative Color stack index. Unmatched call to PopColor()',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), 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), 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), 25101 => array('Illegal numeric argument to SetLineStyle(): (%d)',1),
25102 => array('Illegal string argument to SetLineStyle(): %s',1), 25102 => array('Illegal string argument to SetLineStyle(): %s',1),
25103 => array('Illegal argument to SetLineStyle %s',1), 25103 => array('Illegal argument to SetLineStyle %s',1),
25104 => array('Unknown line style: %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), 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), 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), 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), 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), 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), 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), 25111 => array('Can\'t delete cached image %s. Permission problem?',1),
25112 => array('Cached imagefile (%s) has file date in the future.',1), 25112 => array('Cached imagefile (%s) has file date in the future.',1),
25113 => array('Can\'t delete cached image "%s". Permission problem?',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), 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), 25115 => array('Can\'t set permission for cached image "%s". Permission problem?',1),
25116 => array('Cant open file from cache "%s"',1), 25116 => array('Cant open file from cache "%s"',1),
25117 => array('Can\'t open cached image "%s" for reading.',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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 25131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0),
   
/* /*
** jpgraph_led ** 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), 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 ** Pro-version strings
**--------------------------------------------------------------------------------------------- **---------------------------------------------------------------------------------------------
*/ */
   
/* /*
** jpgraph_table ** jpgraph_table
*/ */
   
27001 => array('GTextTable: Invalid argument to Set(). Array argument must be 2 dimensional',0), 27001 => array('GTextTable: Invalid argument to Set(). Array argument must be 2 dimensional',0),
27002 => array('GTextTable: Invalid argument to Set()',0), 27002 => array('GTextTable: Invalid argument to Set()',0),
27003 => array('GTextTable: Wrong number of arguments to GTextTable::SetColor()',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), 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), 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), 27006 => array('GTextTable: Column argument = %d is outside specified table size.',1),
27007 => array('GTextTable: Row 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), 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), 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), 27010 => array('GTextTable: No alignment specified in call to SetAlign()',0),
27011 => array('GTextTable: Unknown alignment specified in SetAlign(). Horizontal=%s, Vertical=%s',2), 27011 => array('GTextTable: Unknown alignment specified in SetAlign(). Horizontal=%s, Vertical=%s',2),
27012 => array('GTextTable: Internal error. Invalid alignment specified =%s',1), 27012 => array('GTextTable: Internal error. Invalid alignment specified =%s',1),
27013 => array('GTextTable: Argument to FormatNumber() must be a string.',0), 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), 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), 27015 => array('GTextTable: Cell image constrain type must be TIMG_WIDTH or TIMG_HEIGHT',0),
   
/* /*
** jpgraph_windrose ** jpgraph_windrose
*/ */
   
22001 => array('Total percentage for all windrose legs in a windrose plot can not exceed 100%% !\n(Current max is: %d)',1), 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), 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), 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), 22005 => array('Line style for radial lines must be on of ("solid","dotted","dashed","longdashed") ',0),
22006 => array('Illegal windrose type specified.',0), 22006 => array('Illegal windrose type specified.',0),
22007 => array('To few values for the range legend.',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), 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), 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), 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), 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), 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), 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), 22014 => array('Index for compass direction must be between 0 and 15.',0),
22015 => array('You have specified an undefined Windrose plot type.',0), 22015 => array('You have specified an undefined Windrose plot type.',0),
22016 => array('Windrose leg index must be numeric or direction label.',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), 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), 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), 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), 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), 22021 => array('It is only possible to add Text, IconPlot or WindrosePlot to a Windrose Graph',0),
/* /*
** jpgraph_odometer ** jpgraph_odometer
*/ */
   
13001 => array('Unknown needle style (%d).',1), 13001 => array('Unknown needle style (%d).',1),
13002 => array('Value for odometer (%f) is outside specified scale [%f,%f]',3), 13002 => array('Value for odometer (%f) is outside specified scale [%f,%f]',3),
   
/* /*
** jpgraph_barcode ** jpgraph_barcode
*/ */
   
1001 => array('Unknown encoder specification: %s',1), 1001 => array('Unknown encoder specification: %s',1),
1002 => array('Data validation failed. Can\'t encode [%s] using encoding "%s"',2), 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), 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), 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), 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), 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), 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), 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), 1009 => array('Encoding using CODE 93 is not yet supported.',0),
1010 => array('Encoding using POSTNET 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), 1011 => array('Non supported barcode backend for type %s',1),
   
/* /*
** PDF417 ** 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), 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), 26001 => array('PDF417: Number of Columns must be >= 1 and <= 30',0),
26002 => array('PDF417: Error level must be between 0 and 8',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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 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), 26013 => array('PDF417: Internal error. Checksum error. Coefficient tables corrupted.',0),
26014 => array('PDF417: Internal error. No data to calculate codewords on.',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), 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), 26016 => array('PDF417: Internal error: Unrecognized state transition mode in decode.',0),
   
/* /*
** jpgraph_contour ** jpgraph_contour
*/ */
   
28001 => array('Third argument to Contour must be an array of colors.',0), 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), 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), 28003 => array('ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)',1),
28004 => array('ContourPlot Internal Error: isobarHCrossing: Row 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), 28005 => array('ContourPlot Internal Error: isobarVCrossing: Row index too large (%d)',1),
28006 => array('ContourPlot Internal Error: isobarVCrossing: Col 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), 28007 => array('ContourPlot interpolation factor is too large (>5)',0),
   
/* /*
* jpgraph_matrix and colormap * jpgraph_matrix and colormap
*/ */
29201 => array('Min range value must be less or equal to max range value for colormaps',0), 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), 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), 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), 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), 29205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1),
29206 => array('Invalid object added to MatrixGraph',0), 29206 => array('Invalid object added to MatrixGraph',0),
29207 => array('Empty input data specified for MatrixPlot',0), 29207 => array('Empty input data specified for MatrixPlot',0),
29208 => array('Unknown side specifiction for matrix labels "%s"',1), 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), 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), 29210 => array('CSIM Target for matrix labels does not match the number of labels (csim=%d, labels=%d)',2),
   
); );
   
?> ?>
   
<?php <?php
/*======================================================================= /*=======================================================================
// File: PROD.INC.PHP // File: PROD.INC.PHP
// Description: Special localization file with the same error messages // Description: Special localization file with the same error messages
// for all errors. // for all errors.
// Created: 2006-02-18 // Created: 2006-02-18
// Ver: $Id: prod.inc.php 1886 2009-10-01 23:30:16Z ljp $ // Ver: $Id: prod.inc.php 1886 2009-10-01 23:30:16Z ljp $
// //
// Copyright (c) Aditus Consulting. All rights reserved. // Copyright (c) Aditus Consulting. All rights reserved.
//======================================================================== //========================================================================
*/ */
   
// The single error message for all errors // The single error message for all errors
DEFINE('DEFAULT_ERROR_MESSAGE','We are sorry but the system could not generate the requested image. Please contact site support to resolve this problem. Problem no: #'); DEFINE('DEFAULT_ERROR_MESSAGE','We are sorry but the system could not generate the requested image. Please contact site support to resolve this problem. Problem no: #');
   
// Note: Format of each error message is array(<error message>,<number of arguments>) // Note: Format of each error message is array(<error message>,<number of arguments>)
$_jpg_messages = array( $_jpg_messages = array(
   
/* /*
** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text ** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text
*/ */
10 => array('<table border=1><tr><td><font color=darkred size=4><b>JpGraph Error:</b> 10 => array('<table border=1><tr><td><font color=darkred size=4><b>JpGraph Error:</b>
HTTP headers have already been sent.<br>Caused by output from file <b>%s</b> at line <b>%d</b>.</font></td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it\'s image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening "<b>&lt;?php</b>".</td></tr></table>',2), HTTP headers have already been sent.<br>Caused by output from file <b>%s</b> at line <b>%d</b>.</font></td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it\'s image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening "<b>&lt;?php</b>".</td></tr></table>',2),
   
   
11 => array(DEFAULT_ERROR_MESSAGE.'11',0), 11 => array(DEFAULT_ERROR_MESSAGE.'11',0),
12 => array(DEFAULT_ERROR_MESSAGE.'12',0), 12 => array(DEFAULT_ERROR_MESSAGE.'12',0),
13 => array(DEFAULT_ERROR_MESSAGE.'13',0), 13 => array(DEFAULT_ERROR_MESSAGE.'13',0),
2001 => array(DEFAULT_ERROR_MESSAGE.'2001',0), 2001 => array(DEFAULT_ERROR_MESSAGE.'2001',0),
2002 => array(DEFAULT_ERROR_MESSAGE.'2002',0), 2002 => array(DEFAULT_ERROR_MESSAGE.'2002',0),
2003 => array(DEFAULT_ERROR_MESSAGE.'2003',0), 2003 => array(DEFAULT_ERROR_MESSAGE.'2003',0),
2004 => array(DEFAULT_ERROR_MESSAGE.'2004',0), 2004 => array(DEFAULT_ERROR_MESSAGE.'2004',0),
2005 => array(DEFAULT_ERROR_MESSAGE.'2005',0), 2005 => array(DEFAULT_ERROR_MESSAGE.'2005',0),
2006 => array(DEFAULT_ERROR_MESSAGE.'2006',0), 2006 => array(DEFAULT_ERROR_MESSAGE.'2006',0),
2007 => array(DEFAULT_ERROR_MESSAGE.'2007',0), 2007 => array(DEFAULT_ERROR_MESSAGE.'2007',0),
2008 => array(DEFAULT_ERROR_MESSAGE.'2008',0), 2008 => array(DEFAULT_ERROR_MESSAGE.'2008',0),
2009 => array(DEFAULT_ERROR_MESSAGE.'2009',0), 2009 => array(DEFAULT_ERROR_MESSAGE.'2009',0),
2010 => array(DEFAULT_ERROR_MESSAGE.'2010',0), 2010 => array(DEFAULT_ERROR_MESSAGE.'2010',0),
2011 => array(DEFAULT_ERROR_MESSAGE.'2011',0), 2011 => array(DEFAULT_ERROR_MESSAGE.'2011',0),
2012 => array(DEFAULT_ERROR_MESSAGE.'2012',0), 2012 => array(DEFAULT_ERROR_MESSAGE.'2012',0),
2013 => array(DEFAULT_ERROR_MESSAGE.'2013',0), 2013 => array(DEFAULT_ERROR_MESSAGE.'2013',0),
2014 => array(DEFAULT_ERROR_MESSAGE.'2014',0), 2014 => array(DEFAULT_ERROR_MESSAGE.'2014',0),
3001 => array(DEFAULT_ERROR_MESSAGE.'3001',0), 3001 => array(DEFAULT_ERROR_MESSAGE.'3001',0),
4002 => array(DEFAULT_ERROR_MESSAGE.'4002',0), 4002 => array(DEFAULT_ERROR_MESSAGE.'4002',0),
5001 => array(DEFAULT_ERROR_MESSAGE.'5001',0), 5001 => array(DEFAULT_ERROR_MESSAGE.'5001',0),
5002 => array(DEFAULT_ERROR_MESSAGE.'5002',0), 5002 => array(DEFAULT_ERROR_MESSAGE.'5002',0),
5003 => array(DEFAULT_ERROR_MESSAGE.'5003',0), 5003 => array(DEFAULT_ERROR_MESSAGE.'5003',0),
5004 => array(DEFAULT_ERROR_MESSAGE.'5004',0), 5004 => array(DEFAULT_ERROR_MESSAGE.'5004',0),
6001 => array(DEFAULT_ERROR_MESSAGE.'6001',0), 6001 => array(DEFAULT_ERROR_MESSAGE.'6001',0),
6002 => array(DEFAULT_ERROR_MESSAGE.'6002',0), 6002 => array(DEFAULT_ERROR_MESSAGE.'6002',0),
6003 => array(DEFAULT_ERROR_MESSAGE.'6003',0), 6003 => array(DEFAULT_ERROR_MESSAGE.'6003',0),
6004 => array(DEFAULT_ERROR_MESSAGE.'6004',0), 6004 => array(DEFAULT_ERROR_MESSAGE.'6004',0),
6005 => array(DEFAULT_ERROR_MESSAGE.'6005',0), 6005 => array(DEFAULT_ERROR_MESSAGE.'6005',0),
6006 => array(DEFAULT_ERROR_MESSAGE.'6006',0), 6006 => array(DEFAULT_ERROR_MESSAGE.'6006',0),
6007 => array(DEFAULT_ERROR_MESSAGE.'6007',0), 6007 => array(DEFAULT_ERROR_MESSAGE.'6007',0),
6008 => array(DEFAULT_ERROR_MESSAGE.'6008',0), 6008 => array(DEFAULT_ERROR_MESSAGE.'6008',0),
6009 => array(DEFAULT_ERROR_MESSAGE.'6009',0), 6009 => array(DEFAULT_ERROR_MESSAGE.'6009',0),
6010 => array(DEFAULT_ERROR_MESSAGE.'6010',0), 6010 => array(DEFAULT_ERROR_MESSAGE.'6010',0),
6011 => array(DEFAULT_ERROR_MESSAGE.'6011',0), 6011 => array(DEFAULT_ERROR_MESSAGE.'6011',0),
6012 => array(DEFAULT_ERROR_MESSAGE.'6012',0), 6012 => array(DEFAULT_ERROR_MESSAGE.'6012',0),
6015 => array(DEFAULT_ERROR_MESSAGE.'6015',0), 6015 => array(DEFAULT_ERROR_MESSAGE.'6015',0),
6016 => array(DEFAULT_ERROR_MESSAGE.'6016',0), 6016 => array(DEFAULT_ERROR_MESSAGE.'6016',0),
6017 => array(DEFAULT_ERROR_MESSAGE.'6017',0), 6017 => array(DEFAULT_ERROR_MESSAGE.'6017',0),
6018 => array(DEFAULT_ERROR_MESSAGE.'6018',0), 6018 => array(DEFAULT_ERROR_MESSAGE.'6018',0),
6019 => array(DEFAULT_ERROR_MESSAGE.'6019',0), 6019 => array(DEFAULT_ERROR_MESSAGE.'6019',0),
6020 => array(DEFAULT_ERROR_MESSAGE.'6020',0), 6020 => array(DEFAULT_ERROR_MESSAGE.'6020',0),
6021 => array(DEFAULT_ERROR_MESSAGE.'6021',0), 6021 => array(DEFAULT_ERROR_MESSAGE.'6021',0),
6022 => array(DEFAULT_ERROR_MESSAGE.'6022',0), 6022 => array(DEFAULT_ERROR_MESSAGE.'6022',0),
6023 => array(DEFAULT_ERROR_MESSAGE.'6023',0), 6023 => array(DEFAULT_ERROR_MESSAGE.'6023',0),
6024 => array(DEFAULT_ERROR_MESSAGE.'6024',0), 6024 => array(DEFAULT_ERROR_MESSAGE.'6024',0),
6025 => array(DEFAULT_ERROR_MESSAGE.'6025',0), 6025 => array(DEFAULT_ERROR_MESSAGE.'6025',0),
6027 => array(DEFAULT_ERROR_MESSAGE.'6027',0), 6027 => array(DEFAULT_ERROR_MESSAGE.'6027',0),
6028 => array(DEFAULT_ERROR_MESSAGE.'6028',0), 6028 => array(DEFAULT_ERROR_MESSAGE.'6028',0),
6029 => array(DEFAULT_ERROR_MESSAGE.'6029',0), 6029 => array(DEFAULT_ERROR_MESSAGE.'6029',0),
6030 => array(DEFAULT_ERROR_MESSAGE.'6030',0), 6030 => array(DEFAULT_ERROR_MESSAGE.'6030',0),
6031 => array(DEFAULT_ERROR_MESSAGE.'6031',0), 6031 => array(DEFAULT_ERROR_MESSAGE.'6031',0),
6032 => array(DEFAULT_ERROR_MESSAGE.'6032',0), 6032 => array(DEFAULT_ERROR_MESSAGE.'6032',0),
6033 => array(DEFAULT_ERROR_MESSAGE.'6033',0), 6033 => array(DEFAULT_ERROR_MESSAGE.'6033',0),
7001 => array(DEFAULT_ERROR_MESSAGE.'7001',0), 7001 => array(DEFAULT_ERROR_MESSAGE.'7001',0),
8001 => array(DEFAULT_ERROR_MESSAGE.'8001',0), 8001 => array(DEFAULT_ERROR_MESSAGE.'8001',0),
8002 => array(DEFAULT_ERROR_MESSAGE.'8002',0), 8002 => array(DEFAULT_ERROR_MESSAGE.'8002',0),
8003 => array(DEFAULT_ERROR_MESSAGE.'8003',0), 8003 => array(DEFAULT_ERROR_MESSAGE.'8003',0),
8004 => array(DEFAULT_ERROR_MESSAGE.'8004',0), 8004 => array(DEFAULT_ERROR_MESSAGE.'8004',0),
9001 => array(DEFAULT_ERROR_MESSAGE.'9001',0), 9001 => array(DEFAULT_ERROR_MESSAGE.'9001',0),
10001 => array(DEFAULT_ERROR_MESSAGE.'10001',0), 10001 => array(DEFAULT_ERROR_MESSAGE.'10001',0),
10002 => array(DEFAULT_ERROR_MESSAGE.'10002',0), 10002 => array(DEFAULT_ERROR_MESSAGE.'10002',0),
10003 => array(DEFAULT_ERROR_MESSAGE.'10003',0), 10003 => array(DEFAULT_ERROR_MESSAGE.'10003',0),
11001 => array(DEFAULT_ERROR_MESSAGE.'11001',0), 11001 => array(DEFAULT_ERROR_MESSAGE.'11001',0),
11002 => array(DEFAULT_ERROR_MESSAGE.'11002',0), 11002 => array(DEFAULT_ERROR_MESSAGE.'11002',0),
11003 => array(DEFAULT_ERROR_MESSAGE.'11003',0), 11003 => array(DEFAULT_ERROR_MESSAGE.'11003',0),
11004 => array(DEFAULT_ERROR_MESSAGE.'11004',0), 11004 => array(DEFAULT_ERROR_MESSAGE.'11004',0),
11005 => array(DEFAULT_ERROR_MESSAGE.'11005',0), 11005 => array(DEFAULT_ERROR_MESSAGE.'11005',0),
12001 => array(DEFAULT_ERROR_MESSAGE.'12001',0), 12001 => array(DEFAULT_ERROR_MESSAGE.'12001',0),
12002 => array(DEFAULT_ERROR_MESSAGE.'12002',0), 12002 => array(DEFAULT_ERROR_MESSAGE.'12002',0),
12003 => array(DEFAULT_ERROR_MESSAGE.'12003',0), 12003 => array(DEFAULT_ERROR_MESSAGE.'12003',0),
12004 => array(DEFAULT_ERROR_MESSAGE.'12004',0), 12004 => array(DEFAULT_ERROR_MESSAGE.'12004',0),
12005 => array(DEFAULT_ERROR_MESSAGE.'12005',0), 12005 => array(DEFAULT_ERROR_MESSAGE.'12005',0),
12006 => array(DEFAULT_ERROR_MESSAGE.'12006',0), 12006 => array(DEFAULT_ERROR_MESSAGE.'12006',0),
12007 => array(DEFAULT_ERROR_MESSAGE.'12007',0), 12007 => array(DEFAULT_ERROR_MESSAGE.'12007',0),
12008 => array(DEFAULT_ERROR_MESSAGE.'12008',0), 12008 => array(DEFAULT_ERROR_MESSAGE.'12008',0),
12009 => array(DEFAULT_ERROR_MESSAGE.'12009',0), 12009 => array(DEFAULT_ERROR_MESSAGE.'12009',0),
12010 => array(DEFAULT_ERROR_MESSAGE.'12010',0), 12010 => array(DEFAULT_ERROR_MESSAGE.'12010',0),
12011 => array(DEFAULT_ERROR_MESSAGE.'12011',0), 12011 => array(DEFAULT_ERROR_MESSAGE.'12011',0),
12012 => array(DEFAULT_ERROR_MESSAGE.'12012',0), 12012 => array(DEFAULT_ERROR_MESSAGE.'12012',0),
14001 => array(DEFAULT_ERROR_MESSAGE.'14001',0), 14001 => array(DEFAULT_ERROR_MESSAGE.'14001',0),
14002 => array(DEFAULT_ERROR_MESSAGE.'14002',0), 14002 => array(DEFAULT_ERROR_MESSAGE.'14002',0),
14003 => array(DEFAULT_ERROR_MESSAGE.'14003',0), 14003 => array(DEFAULT_ERROR_MESSAGE.'14003',0),
14004 => array(DEFAULT_ERROR_MESSAGE.'14004',0), 14004 => array(DEFAULT_ERROR_MESSAGE.'14004',0),
14005 => array(DEFAULT_ERROR_MESSAGE.'14005',0), 14005 => array(DEFAULT_ERROR_MESSAGE.'14005',0),
14006 => array(DEFAULT_ERROR_MESSAGE.'14006',0), 14006 => array(DEFAULT_ERROR_MESSAGE.'14006',0),
14007 => array(DEFAULT_ERROR_MESSAGE.'14007',0), 14007 => array(DEFAULT_ERROR_MESSAGE.'14007',0),
15001 => array(DEFAULT_ERROR_MESSAGE.'15001',0), 15001 => array(DEFAULT_ERROR_MESSAGE.'15001',0),
15002 => array(DEFAULT_ERROR_MESSAGE.'15002',0), 15002 => array(DEFAULT_ERROR_MESSAGE.'15002',0),
15003 => array(DEFAULT_ERROR_MESSAGE.'15003',0), 15003 => array(DEFAULT_ERROR_MESSAGE.'15003',0),
15004 => array(DEFAULT_ERROR_MESSAGE.'15004',0), 15004 => array(DEFAULT_ERROR_MESSAGE.'15004',0),
15005 => array(DEFAULT_ERROR_MESSAGE.'15005',0), 15005 => array(DEFAULT_ERROR_MESSAGE.'15005',0),
15006 => array(DEFAULT_ERROR_MESSAGE.'15006',0), 15006 => array(DEFAULT_ERROR_MESSAGE.'15006',0),
15007 => array(DEFAULT_ERROR_MESSAGE.'15007',0), 15007 => array(DEFAULT_ERROR_MESSAGE.'15007',0),
15008 => array(DEFAULT_ERROR_MESSAGE.'15008',0), 15008 => array(DEFAULT_ERROR_MESSAGE.'15008',0),
15009 => array(DEFAULT_ERROR_MESSAGE.'15009',0), 15009 => array(DEFAULT_ERROR_MESSAGE.'15009',0),
15010 => array(DEFAULT_ERROR_MESSAGE.'15010',0), 15010 => array(DEFAULT_ERROR_MESSAGE.'15010',0),
15011 => array(DEFAULT_ERROR_MESSAGE.'15011',0), 15011 => array(DEFAULT_ERROR_MESSAGE.'15011',0),
16001 => array(DEFAULT_ERROR_MESSAGE.'16001',0), 16001 => array(DEFAULT_ERROR_MESSAGE.'16001',0),
16002 => array(DEFAULT_ERROR_MESSAGE.'16002',0), 16002 => array(DEFAULT_ERROR_MESSAGE.'16002',0),
16003 => array(DEFAULT_ERROR_MESSAGE.'16003',0), 16003 => array(DEFAULT_ERROR_MESSAGE.'16003',0),
16004 => array(DEFAULT_ERROR_MESSAGE.'16004',0), 16004 => array(DEFAULT_ERROR_MESSAGE.'16004',0),
17001 => array(DEFAULT_ERROR_MESSAGE.'17001',0), 17001 => array(DEFAULT_ERROR_MESSAGE.'17001',0),
17002 => array(DEFAULT_ERROR_MESSAGE.'17002',0), 17002 => array(DEFAULT_ERROR_MESSAGE.'17002',0),
17004 => array(DEFAULT_ERROR_MESSAGE.'17004',0), 17004 => array(DEFAULT_ERROR_MESSAGE.'17004',0),
18001 => array(DEFAULT_ERROR_MESSAGE.'18001',0), 18001 => array(DEFAULT_ERROR_MESSAGE.'18001',0),
18002 => array(DEFAULT_ERROR_MESSAGE.'18002',0), 18002 => array(DEFAULT_ERROR_MESSAGE.'18002',0),
18003 => array(DEFAULT_ERROR_MESSAGE.'18003',0), 18003 => array(DEFAULT_ERROR_MESSAGE.'18003',0),
18004 => array(DEFAULT_ERROR_MESSAGE.'18004',0), 18004 => array(DEFAULT_ERROR_MESSAGE.'18004',0),
18005 => array(DEFAULT_ERROR_MESSAGE.'18005',0), 18005 => array(DEFAULT_ERROR_MESSAGE.'18005',0),
18006 => array(DEFAULT_ERROR_MESSAGE.'18006',0), 18006 => array(DEFAULT_ERROR_MESSAGE.'18006',0),
18007 => array(DEFAULT_ERROR_MESSAGE.'18007',0), 18007 => array(DEFAULT_ERROR_MESSAGE.'18007',0),
18008 => array(DEFAULT_ERROR_MESSAGE.'18008',0), 18008 => array(DEFAULT_ERROR_MESSAGE.'18008',0),
19001 => array(DEFAULT_ERROR_MESSAGE.'19001',0), 19001 => array(DEFAULT_ERROR_MESSAGE.'19001',0),
19002 => array(DEFAULT_ERROR_MESSAGE.'19002',0), 19002 => array(DEFAULT_ERROR_MESSAGE.'19002',0),
19003 => array(DEFAULT_ERROR_MESSAGE.'19003',0), 19003 => array(DEFAULT_ERROR_MESSAGE.'19003',0),
20001 => array(DEFAULT_ERROR_MESSAGE.'20001',0), 20001 => array(DEFAULT_ERROR_MESSAGE.'20001',0),
20002 => array(DEFAULT_ERROR_MESSAGE.'20002',0), 20002 => array(DEFAULT_ERROR_MESSAGE.'20002',0),
20003 => array(DEFAULT_ERROR_MESSAGE.'20003',0), 20003 => array(DEFAULT_ERROR_MESSAGE.'20003',0),
21001 => array(DEFAULT_ERROR_MESSAGE.'21001',0), 21001 => array(DEFAULT_ERROR_MESSAGE.'21001',0),
23001 => array(DEFAULT_ERROR_MESSAGE.'23001',0), 23001 => array(DEFAULT_ERROR_MESSAGE.'23001',0),
23002 => array(DEFAULT_ERROR_MESSAGE.'23002',0), 23002 => array(DEFAULT_ERROR_MESSAGE.'23002',0),
23003 => array(DEFAULT_ERROR_MESSAGE.'23003',0), 23003 => array(DEFAULT_ERROR_MESSAGE.'23003',0),
24001 => array(DEFAULT_ERROR_MESSAGE.'24001',0), 24001 => array(DEFAULT_ERROR_MESSAGE.'24001',0),
24002 => array(DEFAULT_ERROR_MESSAGE.'24002',0), 24002 => array(DEFAULT_ERROR_MESSAGE.'24002',0),
24003 => array(DEFAULT_ERROR_MESSAGE.'24003',0), 24003 => array(DEFAULT_ERROR_MESSAGE.'24003',0),
24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0), 24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0),
25001 => array(DEFAULT_ERROR_MESSAGE.'25001',0), 25001 => array(DEFAULT_ERROR_MESSAGE.'25001',0),
25002 => array(DEFAULT_ERROR_MESSAGE.'25002',0), 25002 => array(DEFAULT_ERROR_MESSAGE.'25002',0),
25003 => array(DEFAULT_ERROR_MESSAGE.'25003',0), 25003 => array(DEFAULT_ERROR_MESSAGE.'25003',0),
25004 => array(DEFAULT_ERROR_MESSAGE.'25004',0), 25004 => array(DEFAULT_ERROR_MESSAGE.'25004',0),
25005 => array(DEFAULT_ERROR_MESSAGE.'25005',0), 25005 => array(DEFAULT_ERROR_MESSAGE.'25005',0),
25006 => array(DEFAULT_ERROR_MESSAGE.'25006',0), 25006 => array(DEFAULT_ERROR_MESSAGE.'25006',0),
25007 => array(DEFAULT_ERROR_MESSAGE.'25007',0), 25007 => array(DEFAULT_ERROR_MESSAGE.'25007',0),
25008 => array(DEFAULT_ERROR_MESSAGE.'25008',0), 25008 => array(DEFAULT_ERROR_MESSAGE.'25008',0),
25009 => array(DEFAULT_ERROR_MESSAGE.'25009',0), 25009 => array(DEFAULT_ERROR_MESSAGE.'25009',0),
25010 => array(DEFAULT_ERROR_MESSAGE.'25010',0), 25010 => array(DEFAULT_ERROR_MESSAGE.'25010',0),
25011 => array(DEFAULT_ERROR_MESSAGE.'25011',0), 25011 => array(DEFAULT_ERROR_MESSAGE.'25011',0),
25012 => array(DEFAULT_ERROR_MESSAGE.'25012',0), 25012 => array(DEFAULT_ERROR_MESSAGE.'25012',0),
25013 => array(DEFAULT_ERROR_MESSAGE.'25013',0), 25013 => array(DEFAULT_ERROR_MESSAGE.'25013',0),
25014 => array(DEFAULT_ERROR_MESSAGE.'25014',0), 25014 => array(DEFAULT_ERROR_MESSAGE.'25014',0),
25015 => array(DEFAULT_ERROR_MESSAGE.'25015',0), 25015 => array(DEFAULT_ERROR_MESSAGE.'25015',0),
25016 => array(DEFAULT_ERROR_MESSAGE.'25016',0), 25016 => array(DEFAULT_ERROR_MESSAGE.'25016',0),
25017 => array(DEFAULT_ERROR_MESSAGE.'25017',0), 25017 => array(DEFAULT_ERROR_MESSAGE.'25017',0),
25018 => array(DEFAULT_ERROR_MESSAGE.'25018',0), 25018 => array(DEFAULT_ERROR_MESSAGE.'25018',0),
25019 => array(DEFAULT_ERROR_MESSAGE.'25019',0), 25019 => array(DEFAULT_ERROR_MESSAGE.'25019',0),
25020 => array(DEFAULT_ERROR_MESSAGE.'25020',0), 25020 => array(DEFAULT_ERROR_MESSAGE.'25020',0),
25021 => array(DEFAULT_ERROR_MESSAGE.'25021',0), 25021 => array(DEFAULT_ERROR_MESSAGE.'25021',0),
25022 => array(DEFAULT_ERROR_MESSAGE.'25022',0), 25022 => array(DEFAULT_ERROR_MESSAGE.'25022',0),
25023 => array(DEFAULT_ERROR_MESSAGE.'25023',0), 25023 => array(DEFAULT_ERROR_MESSAGE.'25023',0),
25024 => array(DEFAULT_ERROR_MESSAGE.'25024',0), 25024 => array(DEFAULT_ERROR_MESSAGE.'25024',0),
25025 => array(DEFAULT_ERROR_MESSAGE.'25025',0), 25025 => array(DEFAULT_ERROR_MESSAGE.'25025',0),
25026 => array(DEFAULT_ERROR_MESSAGE.'25026',0), 25026 => array(DEFAULT_ERROR_MESSAGE.'25026',0),
25027 => array(DEFAULT_ERROR_MESSAGE.'25027',0), 25027 => array(DEFAULT_ERROR_MESSAGE.'25027',0),
25028 => array(DEFAULT_ERROR_MESSAGE.'25028',0), 25028 => array(DEFAULT_ERROR_MESSAGE.'25028',0),
25029 => array(DEFAULT_ERROR_MESSAGE.'25029',0), 25029 => array(DEFAULT_ERROR_MESSAGE.'25029',0),
25030 => array(DEFAULT_ERROR_MESSAGE.'25030',0), 25030 => array(DEFAULT_ERROR_MESSAGE.'25030',0),
25031 => array(DEFAULT_ERROR_MESSAGE.'25031',0), 25031 => array(DEFAULT_ERROR_MESSAGE.'25031',0),
25032 => array(DEFAULT_ERROR_MESSAGE.'25032',0), 25032 => array(DEFAULT_ERROR_MESSAGE.'25032',0),
25033 => array(DEFAULT_ERROR_MESSAGE.'25033',0), 25033 => array(DEFAULT_ERROR_MESSAGE.'25033',0),
25034 => array(DEFAULT_ERROR_MESSAGE.'25034',0), 25034 => array(DEFAULT_ERROR_MESSAGE.'25034',0),
25035 => array(DEFAULT_ERROR_MESSAGE.'25035',0), 25035 => array(DEFAULT_ERROR_MESSAGE.'25035',0),
25036 => array(DEFAULT_ERROR_MESSAGE.'25036',0), 25036 => array(DEFAULT_ERROR_MESSAGE.'25036',0),
25037 => array(DEFAULT_ERROR_MESSAGE.'25037',0), 25037 => array(DEFAULT_ERROR_MESSAGE.'25037',0),
25038 => array(DEFAULT_ERROR_MESSAGE.'25038',0), 25038 => array(DEFAULT_ERROR_MESSAGE.'25038',0),
25039 => array(DEFAULT_ERROR_MESSAGE.'25039',0), 25039 => array(DEFAULT_ERROR_MESSAGE.'25039',0),
25040 => array(DEFAULT_ERROR_MESSAGE.'25040',0), 25040 => array(DEFAULT_ERROR_MESSAGE.'25040',0),
25041 => array(DEFAULT_ERROR_MESSAGE.'25041',0), 25041 => array(DEFAULT_ERROR_MESSAGE.'25041',0),
25042 => array(DEFAULT_ERROR_MESSAGE.'25042',0), 25042 => array(DEFAULT_ERROR_MESSAGE.'25042',0),
25043 => array(DEFAULT_ERROR_MESSAGE.'25043',0), 25043 => array(DEFAULT_ERROR_MESSAGE.'25043',0),
25044 => array(DEFAULT_ERROR_MESSAGE.'25044',0), 25044 => array(DEFAULT_ERROR_MESSAGE.'25044',0),
25045 => array(DEFAULT_ERROR_MESSAGE.'25045',0), 25045 => array(DEFAULT_ERROR_MESSAGE.'25045',0),
25046 => array(DEFAULT_ERROR_MESSAGE.'25046',0), 25046 => array(DEFAULT_ERROR_MESSAGE.'25046',0),
25047 => array(DEFAULT_ERROR_MESSAGE.'25047',0), 25047 => array(DEFAULT_ERROR_MESSAGE.'25047',0),
25048 => array(DEFAULT_ERROR_MESSAGE.'25048',0), 25048 => array(DEFAULT_ERROR_MESSAGE.'25048',0),
25049 => array(DEFAULT_ERROR_MESSAGE.'25049',0), 25049 => array(DEFAULT_ERROR_MESSAGE.'25049',0),
25050 => array(DEFAULT_ERROR_MESSAGE.'25050',0), 25050 => array(DEFAULT_ERROR_MESSAGE.'25050',0),
25051 => array(DEFAULT_ERROR_MESSAGE.'25051',0), 25051 => array(DEFAULT_ERROR_MESSAGE.'25051',0),
25052 => array(DEFAULT_ERROR_MESSAGE.'25052',0), 25052 => array(DEFAULT_ERROR_MESSAGE.'25052',0),
25053 => array(DEFAULT_ERROR_MESSAGE.'25053',0), 25053 => array(DEFAULT_ERROR_MESSAGE.'25053',0),
25054 => array(DEFAULT_ERROR_MESSAGE.'25054',0), 25054 => array(DEFAULT_ERROR_MESSAGE.'25054',0),
25055 => array(DEFAULT_ERROR_MESSAGE.'25055',0), 25055 => array(DEFAULT_ERROR_MESSAGE.'25055',0),
25056 => array(DEFAULT_ERROR_MESSAGE.'25056',0), 25056 => array(DEFAULT_ERROR_MESSAGE.'25056',0),
25057 => array(DEFAULT_ERROR_MESSAGE.'25057',0), 25057 => array(DEFAULT_ERROR_MESSAGE.'25057',0),
25058 => array(DEFAULT_ERROR_MESSAGE.'25058',0), 25058 => array(DEFAULT_ERROR_MESSAGE.'25058',0),
25059 => array(DEFAULT_ERROR_MESSAGE.'25059',0), 25059 => array(DEFAULT_ERROR_MESSAGE.'25059',0),
25060 => array(DEFAULT_ERROR_MESSAGE.'25060',0), 25060 => array(DEFAULT_ERROR_MESSAGE.'25060',0),
25061 => array(DEFAULT_ERROR_MESSAGE.'25061',0), 25061 => array(DEFAULT_ERROR_MESSAGE.'25061',0),
25062 => array(DEFAULT_ERROR_MESSAGE.'25062',0), 25062 => array(DEFAULT_ERROR_MESSAGE.'25062',0),
25063 => array(DEFAULT_ERROR_MESSAGE.'25063',0), 25063 => array(DEFAULT_ERROR_MESSAGE.'25063',0),
25064 => array(DEFAULT_ERROR_MESSAGE.'25064',0), 25064 => array(DEFAULT_ERROR_MESSAGE.'25064',0),
25065 => array(DEFAULT_ERROR_MESSAGE.'25065',0), 25065 => array(DEFAULT_ERROR_MESSAGE.'25065',0),
25066 => array(DEFAULT_ERROR_MESSAGE.'25066',0), 25066 => array(DEFAULT_ERROR_MESSAGE.'25066',0),
25067 => array(DEFAULT_ERROR_MESSAGE.'25067',0), 25067 => array(DEFAULT_ERROR_MESSAGE.'25067',0),
25068 => array(DEFAULT_ERROR_MESSAGE.'25068',0), 25068 => array(DEFAULT_ERROR_MESSAGE.'25068',0),
25069 => array(DEFAULT_ERROR_MESSAGE.'25069',0), 25069 => array(DEFAULT_ERROR_MESSAGE.'25069',0),
25070 => array(DEFAULT_ERROR_MESSAGE.'25070',0), 25070 => array(DEFAULT_ERROR_MESSAGE.'25070',0),
25071 => array(DEFAULT_ERROR_MESSAGE.'25071',0), 25071 => array(DEFAULT_ERROR_MESSAGE.'25071',0),
25072 => array(DEFAULT_ERROR_MESSAGE.'25072',0), 25072 => array(DEFAULT_ERROR_MESSAGE.'25072',0),
25073 => array(DEFAULT_ERROR_MESSAGE.'25073',0), 25073 => array(DEFAULT_ERROR_MESSAGE.'25073',0),
25074 => array(DEFAULT_ERROR_MESSAGE.'25074',0), 25074 => array(DEFAULT_ERROR_MESSAGE.'25074',0),
25075 => array(DEFAULT_ERROR_MESSAGE.'25075',0), 25075 => array(DEFAULT_ERROR_MESSAGE.'25075',0),
25077 => array(DEFAULT_ERROR_MESSAGE.'25077',0), 25077 => array(DEFAULT_ERROR_MESSAGE.'25077',0),
25078 => array(DEFAULT_ERROR_MESSAGE.'25078',0), 25078 => array(DEFAULT_ERROR_MESSAGE.'25078',0),
25079 => array(DEFAULT_ERROR_MESSAGE.'25079',0), 25079 => array(DEFAULT_ERROR_MESSAGE.'25079',0),
25080 => array(DEFAULT_ERROR_MESSAGE.'25080',0), 25080 => array(DEFAULT_ERROR_MESSAGE.'25080',0),
25081 => array(DEFAULT_ERROR_MESSAGE.'25081',0), 25081 => array(DEFAULT_ERROR_MESSAGE.'25081',0),
25082 => array(DEFAULT_ERROR_MESSAGE.'25082',0), 25082 => array(DEFAULT_ERROR_MESSAGE.'25082',0),
25083 => array(DEFAULT_ERROR_MESSAGE.'25083',0), 25083 => array(DEFAULT_ERROR_MESSAGE.'25083',0),
25084 => array(DEFAULT_ERROR_MESSAGE.'25084',0), 25084 => array(DEFAULT_ERROR_MESSAGE.'25084',0),
25085 => array(DEFAULT_ERROR_MESSAGE.'25085',0), 25085 => array(DEFAULT_ERROR_MESSAGE.'25085',0),
25086 => array(DEFAULT_ERROR_MESSAGE.'25086',0), 25086 => array(DEFAULT_ERROR_MESSAGE.'25086',0),
25087 => array(DEFAULT_ERROR_MESSAGE.'25087',0), 25087 => array(DEFAULT_ERROR_MESSAGE.'25087',0),
25088 => array(DEFAULT_ERROR_MESSAGE.'25088',0), 25088 => array(DEFAULT_ERROR_MESSAGE.'25088',0),
25089 => array(DEFAULT_ERROR_MESSAGE.'25089',0), 25089 => array(DEFAULT_ERROR_MESSAGE.'25089',0),
25090 => array(DEFAULT_ERROR_MESSAGE.'25090',0), 25090 => array(DEFAULT_ERROR_MESSAGE.'25090',0),
25091 => array(DEFAULT_ERROR_MESSAGE.'25091',0), 25091 => array(DEFAULT_ERROR_MESSAGE.'25091',0),
25092 => array(DEFAULT_ERROR_MESSAGE.'25092',0), 25092 => array(DEFAULT_ERROR_MESSAGE.'25092',0),
25093 => array(DEFAULT_ERROR_MESSAGE.'25093',0), 25093 => array(DEFAULT_ERROR_MESSAGE.'25093',0),
25094 => array(DEFAULT_ERROR_MESSAGE.'25094',0), 25094 => array(DEFAULT_ERROR_MESSAGE.'25094',0),
25095 => array(DEFAULT_ERROR_MESSAGE.'25095',0), 25095 => array(DEFAULT_ERROR_MESSAGE.'25095',0),
25096 => array(DEFAULT_ERROR_MESSAGE.'25096',0), 25096 => array(DEFAULT_ERROR_MESSAGE.'25096',0),
25097 => array(DEFAULT_ERROR_MESSAGE.'25097',0), 25097 => array(DEFAULT_ERROR_MESSAGE.'25097',0),
25098 => array(DEFAULT_ERROR_MESSAGE.'25098',0), 25098 => array(DEFAULT_ERROR_MESSAGE.'25098',0),
25099 => array(DEFAULT_ERROR_MESSAGE.'25099',0), 25099 => array(DEFAULT_ERROR_MESSAGE.'25099',0),
25100 => array(DEFAULT_ERROR_MESSAGE.'25100',0), 25100 => array(DEFAULT_ERROR_MESSAGE.'25100',0),
25101 => array(DEFAULT_ERROR_MESSAGE.'25101',0), 25101 => array(DEFAULT_ERROR_MESSAGE.'25101',0),
25102 => array(DEFAULT_ERROR_MESSAGE.'25102',0), 25102 => array(DEFAULT_ERROR_MESSAGE.'25102',0),
25103 => array(DEFAULT_ERROR_MESSAGE.'25103',0), 25103 => array(DEFAULT_ERROR_MESSAGE.'25103',0),
25104 => array(DEFAULT_ERROR_MESSAGE.'25104',0), 25104 => array(DEFAULT_ERROR_MESSAGE.'25104',0),
25105 => array(DEFAULT_ERROR_MESSAGE.'25105',0), 25105 => array(DEFAULT_ERROR_MESSAGE.'25105',0),
25106 => array(DEFAULT_ERROR_MESSAGE.'25106',0), 25106 => array(DEFAULT_ERROR_MESSAGE.'25106',0),
25107 => array(DEFAULT_ERROR_MESSAGE.'25107',0), 25107 => array(DEFAULT_ERROR_MESSAGE.'25107',0),
25108 => array(DEFAULT_ERROR_MESSAGE.'25108',0), 25108 => array(DEFAULT_ERROR_MESSAGE.'25108',0),
25109 => array(DEFAULT_ERROR_MESSAGE.'25109',0), 25109 => array(DEFAULT_ERROR_MESSAGE.'25109',0),
25110 => array(DEFAULT_ERROR_MESSAGE.'25110',0), 25110 => array(DEFAULT_ERROR_MESSAGE.'25110',0),
25111 => array(DEFAULT_ERROR_MESSAGE.'25111',0), 25111 => array(DEFAULT_ERROR_MESSAGE.'25111',0),
25112 => array(DEFAULT_ERROR_MESSAGE.'25112',0), 25112 => array(DEFAULT_ERROR_MESSAGE.'25112',0),
25113 => array(DEFAULT_ERROR_MESSAGE.'25113',0), 25113 => array(DEFAULT_ERROR_MESSAGE.'25113',0),
25114 => array(DEFAULT_ERROR_MESSAGE.'25114',0), 25114 => array(DEFAULT_ERROR_MESSAGE.'25114',0),
25115 => array(DEFAULT_ERROR_MESSAGE.'25115',0), 25115 => array(DEFAULT_ERROR_MESSAGE.'25115',0),
25116 => array(DEFAULT_ERROR_MESSAGE.'25116',0), 25116 => array(DEFAULT_ERROR_MESSAGE.'25116',0),
25117 => array(DEFAULT_ERROR_MESSAGE.'25117',0), 25117 => array(DEFAULT_ERROR_MESSAGE.'25117',0),
25118 => array(DEFAULT_ERROR_MESSAGE.'25118',0), 25118 => array(DEFAULT_ERROR_MESSAGE.'25118',0),
25119 => array(DEFAULT_ERROR_MESSAGE.'25119',0), 25119 => array(DEFAULT_ERROR_MESSAGE.'25119',0),
25120 => array(DEFAULT_ERROR_MESSAGE.'25120',0), 25120 => array(DEFAULT_ERROR_MESSAGE.'25120',0),
25121 => array(DEFAULT_ERROR_MESSAGE.'25121',0), 25121 => array(DEFAULT_ERROR_MESSAGE.'25121',0),
25122 => array(DEFAULT_ERROR_MESSAGE.'25122',0), 25122 => array(DEFAULT_ERROR_MESSAGE.'25122',0),
25123 => array(DEFAULT_ERROR_MESSAGE.'25123',0), 25123 => array(DEFAULT_ERROR_MESSAGE.'25123',0),
25124 => array(DEFAULT_ERROR_MESSAGE.'25124',0), 25124 => array(DEFAULT_ERROR_MESSAGE.'25124',0),
25125 => array(DEFAULT_ERROR_MESSAGE.'25125',0), 25125 => array(DEFAULT_ERROR_MESSAGE.'25125',0),
25126 => array(DEFAULT_ERROR_MESSAGE.'25126',0), 25126 => array(DEFAULT_ERROR_MESSAGE.'25126',0),
25127 => array(DEFAULT_ERROR_MESSAGE.'25127',0), 25127 => array(DEFAULT_ERROR_MESSAGE.'25127',0),
25128 => array(DEFAULT_ERROR_MESSAGE.'25128',0), 25128 => array(DEFAULT_ERROR_MESSAGE.'25128',0),
25129 => array(DEFAULT_ERROR_MESSAGE.'25129',0), 25129 => array(DEFAULT_ERROR_MESSAGE.'25129',0),
25130 => array(DEFAULT_ERROR_MESSAGE.'25130',0), 25130 => array(DEFAULT_ERROR_MESSAGE.'25130',0),
25131 => array(DEFAULT_ERROR_MESSAGE.'25131',0), 25131 => array(DEFAULT_ERROR_MESSAGE.'25131',0),
25500 => array(DEFAULT_ERROR_MESSAGE.'25500',0), 25500 => array(DEFAULT_ERROR_MESSAGE.'25500',0),
24003 => array(DEFAULT_ERROR_MESSAGE.'24003',0), 24003 => array(DEFAULT_ERROR_MESSAGE.'24003',0),
24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0), 24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0),
24005 => array(DEFAULT_ERROR_MESSAGE.'24005',0), 24005 => array(DEFAULT_ERROR_MESSAGE.'24005',0),
24006 => array(DEFAULT_ERROR_MESSAGE.'24006',0), 24006 => array(DEFAULT_ERROR_MESSAGE.'24006',0),
24007 => array(DEFAULT_ERROR_MESSAGE.'24007',0), 24007 => array(DEFAULT_ERROR_MESSAGE.'24007',0),
24008 => array(DEFAULT_ERROR_MESSAGE.'24008',0), 24008 => array(DEFAULT_ERROR_MESSAGE.'24008',0),
24009 => array(DEFAULT_ERROR_MESSAGE.'24009',0), 24009 => array(DEFAULT_ERROR_MESSAGE.'24009',0),
24010 => array(DEFAULT_ERROR_MESSAGE.'24010',0), 24010 => array(DEFAULT_ERROR_MESSAGE.'24010',0),
24011 => array(DEFAULT_ERROR_MESSAGE.'24011',0), 24011 => array(DEFAULT_ERROR_MESSAGE.'24011',0),
24012 => array(DEFAULT_ERROR_MESSAGE.'24012',0), 24012 => array(DEFAULT_ERROR_MESSAGE.'24012',0),
24013 => array(DEFAULT_ERROR_MESSAGE.'24013',0), 24013 => array(DEFAULT_ERROR_MESSAGE.'24013',0),
24014 => array(DEFAULT_ERROR_MESSAGE.'24014',0), 24014 => array(DEFAULT_ERROR_MESSAGE.'24014',0),
24015 => array(DEFAULT_ERROR_MESSAGE.'24015',0), 24015 => array(DEFAULT_ERROR_MESSAGE.'24015',0),
22001 => array(DEFAULT_ERROR_MESSAGE.'22001',0), 22001 => array(DEFAULT_ERROR_MESSAGE.'22001',0),
22002 => array(DEFAULT_ERROR_MESSAGE.'22002',0), 22002 => array(DEFAULT_ERROR_MESSAGE.'22002',0),
22004 => array(DEFAULT_ERROR_MESSAGE.'22004',0), 22004 => array(DEFAULT_ERROR_MESSAGE.'22004',0),
22005 => array(DEFAULT_ERROR_MESSAGE.'22005',0), 22005 => array(DEFAULT_ERROR_MESSAGE.'22005',0),
22006 => array(DEFAULT_ERROR_MESSAGE.'22006',0), 22006 => array(DEFAULT_ERROR_MESSAGE.'22006',0),
22007 => array(DEFAULT_ERROR_MESSAGE.'22007',0), 22007 => array(DEFAULT_ERROR_MESSAGE.'22007',0),
22008 => array(DEFAULT_ERROR_MESSAGE.'22008',0), 22008 => array(DEFAULT_ERROR_MESSAGE.'22008',0),
22009 => array(DEFAULT_ERROR_MESSAGE.'22009',0), 22009 => array(DEFAULT_ERROR_MESSAGE.'22009',0),
22010 => array(DEFAULT_ERROR_MESSAGE.'22010',0), 22010 => array(DEFAULT_ERROR_MESSAGE.'22010',0),
22011 => array(DEFAULT_ERROR_MESSAGE.'22011',0), 22011 => array(DEFAULT_ERROR_MESSAGE.'22011',0),
22012 => array(DEFAULT_ERROR_MESSAGE.'22012',0), 22012 => array(DEFAULT_ERROR_MESSAGE.'22012',0),
22013 => array(DEFAULT_ERROR_MESSAGE.'22013',0), 22013 => array(DEFAULT_ERROR_MESSAGE.'22013',0),
22014 => array(DEFAULT_ERROR_MESSAGE.'22014',0), 22014 => array(DEFAULT_ERROR_MESSAGE.'22014',0),
22015 => array(DEFAULT_ERROR_MESSAGE.'22015',0), 22015 => array(DEFAULT_ERROR_MESSAGE.'22015',0),
22016 => array(DEFAULT_ERROR_MESSAGE.'22016',0), 22016 => array(DEFAULT_ERROR_MESSAGE.'22016',0),
22017 => array(DEFAULT_ERROR_MESSAGE.'22017',0), 22017 => array(DEFAULT_ERROR_MESSAGE.'22017',0),
22018 => array(DEFAULT_ERROR_MESSAGE.'22018',0), 22018 => array(DEFAULT_ERROR_MESSAGE.'22018',0),
22019 => array(DEFAULT_ERROR_MESSAGE.'22019',0), 22019 => array(DEFAULT_ERROR_MESSAGE.'22019',0),
22020 => array(DEFAULT_ERROR_MESSAGE.'22020',0), 22020 => array(DEFAULT_ERROR_MESSAGE.'22020',0),
13001 => array(DEFAULT_ERROR_MESSAGE.'13001',0), 13001 => array(DEFAULT_ERROR_MESSAGE.'13001',0),
13002 => array(DEFAULT_ERROR_MESSAGE.'13002',0), 13002 => array(DEFAULT_ERROR_MESSAGE.'13002',0),
1001 => array(DEFAULT_ERROR_MESSAGE.'1001',0), 1001 => array(DEFAULT_ERROR_MESSAGE.'1001',0),
1002 => array(DEFAULT_ERROR_MESSAGE.'1002',0), 1002 => array(DEFAULT_ERROR_MESSAGE.'1002',0),
1003 => array(DEFAULT_ERROR_MESSAGE.'1003',0), 1003 => array(DEFAULT_ERROR_MESSAGE.'1003',0),
1004 => array(DEFAULT_ERROR_MESSAGE.'1004',0), 1004 => array(DEFAULT_ERROR_MESSAGE.'1004',0),
1005 => array(DEFAULT_ERROR_MESSAGE.'1005',0), 1005 => array(DEFAULT_ERROR_MESSAGE.'1005',0),
1006 => array(DEFAULT_ERROR_MESSAGE.'1006',0), 1006 => array(DEFAULT_ERROR_MESSAGE.'1006',0),
1007 => array(DEFAULT_ERROR_MESSAGE.'1007',0), 1007 => array(DEFAULT_ERROR_MESSAGE.'1007',0),
1008 => array(DEFAULT_ERROR_MESSAGE.'1008',0), 1008 => array(DEFAULT_ERROR_MESSAGE.'1008',0),
1009 => array(DEFAULT_ERROR_MESSAGE.'1009',0), 1009 => array(DEFAULT_ERROR_MESSAGE.'1009',0),
1010 => array(DEFAULT_ERROR_MESSAGE.'1010',0), 1010 => array(DEFAULT_ERROR_MESSAGE.'1010',0),
1011 => array(DEFAULT_ERROR_MESSAGE.'1011',0), 1011 => array(DEFAULT_ERROR_MESSAGE.'1011',0),
26000 => array(DEFAULT_ERROR_MESSAGE.'26000',0), 26000 => array(DEFAULT_ERROR_MESSAGE.'26000',0),
26001 => array(DEFAULT_ERROR_MESSAGE.'26001',0), 26001 => array(DEFAULT_ERROR_MESSAGE.'26001',0),
26002 => array(DEFAULT_ERROR_MESSAGE.'26002',0), 26002 => array(DEFAULT_ERROR_MESSAGE.'26002',0),
26003 => array(DEFAULT_ERROR_MESSAGE.'26003',0), 26003 => array(DEFAULT_ERROR_MESSAGE.'26003',0),
26004 => array(DEFAULT_ERROR_MESSAGE.'26004',0), 26004 => array(DEFAULT_ERROR_MESSAGE.'26004',0),
26005 => array(DEFAULT_ERROR_MESSAGE.'26005',0), 26005 => array(DEFAULT_ERROR_MESSAGE.'26005',0),
26006 => array(DEFAULT_ERROR_MESSAGE.'26006',0), 26006 => array(DEFAULT_ERROR_MESSAGE.'26006',0),
26007 => array(DEFAULT_ERROR_MESSAGE.'26007',0), 26007 => array(DEFAULT_ERROR_MESSAGE.'26007',0),
26008 => array(DEFAULT_ERROR_MESSAGE.'26008',0), 26008 => array(DEFAULT_ERROR_MESSAGE.'26008',0),
26009 => array(DEFAULT_ERROR_MESSAGE.'26009',0), 26009 => array(DEFAULT_ERROR_MESSAGE.'26009',0),
26010 => array(DEFAULT_ERROR_MESSAGE.'26010',0), 26010 => array(DEFAULT_ERROR_MESSAGE.'26010',0),
26011 => array(DEFAULT_ERROR_MESSAGE.'26011',0), 26011 => array(DEFAULT_ERROR_MESSAGE.'26011',0),
26012 => array(DEFAULT_ERROR_MESSAGE.'26012',0), 26012 => array(DEFAULT_ERROR_MESSAGE.'26012',0),
26013 => array(DEFAULT_ERROR_MESSAGE.'26013',0), 26013 => array(DEFAULT_ERROR_MESSAGE.'26013',0),
26014 => array(DEFAULT_ERROR_MESSAGE.'26014',0), 26014 => array(DEFAULT_ERROR_MESSAGE.'26014',0),
26015 => array(DEFAULT_ERROR_MESSAGE.'26015',0), 26015 => array(DEFAULT_ERROR_MESSAGE.'26015',0),
26016 => array(DEFAULT_ERROR_MESSAGE.'26016',0), 26016 => array(DEFAULT_ERROR_MESSAGE.'26016',0),
   
27001 => array(DEFAULT_ERROR_MESSAGE.'27001',0), 27001 => array(DEFAULT_ERROR_MESSAGE.'27001',0),
27002 => array(DEFAULT_ERROR_MESSAGE.'27002',0), 27002 => array(DEFAULT_ERROR_MESSAGE.'27002',0),
27003 => array(DEFAULT_ERROR_MESSAGE.'27003',0), 27003 => array(DEFAULT_ERROR_MESSAGE.'27003',0),
27004 => array(DEFAULT_ERROR_MESSAGE.'27004',0), 27004 => array(DEFAULT_ERROR_MESSAGE.'27004',0),
27005 => array(DEFAULT_ERROR_MESSAGE.'27005',0), 27005 => array(DEFAULT_ERROR_MESSAGE.'27005',0),
27006 => array(DEFAULT_ERROR_MESSAGE.'27006',0), 27006 => array(DEFAULT_ERROR_MESSAGE.'27006',0),
27007 => array(DEFAULT_ERROR_MESSAGE.'27007',0), 27007 => array(DEFAULT_ERROR_MESSAGE.'27007',0),
27008 => array(DEFAULT_ERROR_MESSAGE.'27008',0), 27008 => array(DEFAULT_ERROR_MESSAGE.'27008',0),
27009 => array(DEFAULT_ERROR_MESSAGE.'27009',0), 27009 => array(DEFAULT_ERROR_MESSAGE.'27009',0),
27010 => array(DEFAULT_ERROR_MESSAGE.'27010',0), 27010 => array(DEFAULT_ERROR_MESSAGE.'27010',0),
27011 => array(DEFAULT_ERROR_MESSAGE.'27011',0), 27011 => array(DEFAULT_ERROR_MESSAGE.'27011',0),
27012 => array(DEFAULT_ERROR_MESSAGE.'27012',0), 27012 => array(DEFAULT_ERROR_MESSAGE.'27012',0),
27013 => array(DEFAULT_ERROR_MESSAGE.'27013',0), 27013 => array(DEFAULT_ERROR_MESSAGE.'27013',0),
27014 => array(DEFAULT_ERROR_MESSAGE.'27014',0), 27014 => array(DEFAULT_ERROR_MESSAGE.'27014',0),
27015 => array(DEFAULT_ERROR_MESSAGE.'27015',0), 27015 => array(DEFAULT_ERROR_MESSAGE.'27015',0),
   
28001 => array(DEFAULT_ERROR_MESSAGE.'28001',0), 28001 => array(DEFAULT_ERROR_MESSAGE.'28001',0),
28002 => array(DEFAULT_ERROR_MESSAGE.'28002',0), 28002 => array(DEFAULT_ERROR_MESSAGE.'28002',0),
28003 => array(DEFAULT_ERROR_MESSAGE.'28003',0), 28003 => array(DEFAULT_ERROR_MESSAGE.'28003',0),
28004 => array(DEFAULT_ERROR_MESSAGE.'28004',0), 28004 => array(DEFAULT_ERROR_MESSAGE.'28004',0),
28005 => array(DEFAULT_ERROR_MESSAGE.'28005',0), 28005 => array(DEFAULT_ERROR_MESSAGE.'28005',0),
28006 => array(DEFAULT_ERROR_MESSAGE.'28006',0), 28006 => array(DEFAULT_ERROR_MESSAGE.'28006',0),
28007 => array(DEFAULT_ERROR_MESSAGE.'28007',0), 28007 => array(DEFAULT_ERROR_MESSAGE.'28007',0),
   
29201 => array(DEFAULT_ERROR_MESSAGE.'28001',0), 29201 => array(DEFAULT_ERROR_MESSAGE.'28001',0),
29202 => array(DEFAULT_ERROR_MESSAGE.'28002',0), 29202 => array(DEFAULT_ERROR_MESSAGE.'28002',0),
29203 => array(DEFAULT_ERROR_MESSAGE.'28003',0), 29203 => array(DEFAULT_ERROR_MESSAGE.'28003',0),
29204 => array(DEFAULT_ERROR_MESSAGE.'28004',0), 29204 => array(DEFAULT_ERROR_MESSAGE.'28004',0),
29205 => array(DEFAULT_ERROR_MESSAGE.'28005',0), 29205 => array(DEFAULT_ERROR_MESSAGE.'28005',0),
29206 => array(DEFAULT_ERROR_MESSAGE.'28006',0), 29206 => array(DEFAULT_ERROR_MESSAGE.'28006',0),
29207 => array(DEFAULT_ERROR_MESSAGE.'28007',0), 29207 => array(DEFAULT_ERROR_MESSAGE.'28007',0),
29208 => array(DEFAULT_ERROR_MESSAGE.'28008',0), 29208 => array(DEFAULT_ERROR_MESSAGE.'28008',0),
29209 => array(DEFAULT_ERROR_MESSAGE.'28009',0), 29209 => array(DEFAULT_ERROR_MESSAGE.'28009',0),
29210 => array(DEFAULT_ERROR_MESSAGE.'28010',0), 29210 => array(DEFAULT_ERROR_MESSAGE.'28010',0),
   
); );
   
?> ?>
   
<? <?
   
/* /*
@wordCloud @wordCloud
Author: Derek Harvey Author: Derek Harvey
Website: www.lotsofcode.com Website: www.lotsofcode.com
   
@Description @Description
PHP Tag Cloud Class, a nice and simple way to create a php tag cloud, a database and non-database solution. PHP Tag Cloud Class, a nice and simple way to create a php tag cloud, a database and non-database solution.
*/ */
   
class wordCloud class wordCloud
{ {
var $wordsArray = array(); var $wordsArray = array();
var $refsArray = array(); var $refsArray = array();
   
/* /*
* PHP 5 Constructor * PHP 5 Constructor
* *
* @param array $words * @param array $words
* @return void * @return void
*/ */
   
function __construct($words = false) function __construct($words = false)
{ {
if ($words !== false && is_array($words)) if ($words !== false && is_array($words))
{ {
foreach ($words as $key => $value) foreach ($words as $key => $value)
{ {
$this->addWord($value); $this->addWord($value);
} }
} }
} }
   
/* /*
* PHP 4 Constructor * PHP 4 Constructor
* *
* @param array $words * @param array $words
* @return void * @return void
*/ */
   
function wordCloud($words = false) function wordCloud($words = false)
{ {
$this->__construct($words); $this->__construct($words);
} }
   
/* /*
* Assign word to array * Assign word to array
* *
* @param string $word * @param string $word
* @return string * @return string
*/ */
   
function addWord($word, $value = 1, $ref = 0) function addWord($word, $value = 1, $ref = 0)
{ {
if (array_key_exists($word, $this->wordsArray)) if (array_key_exists($word, $this->wordsArray))
$this->wordsArray[$word] += $value; $this->wordsArray[$word] += $value;
else else
$this->wordsArray[$word] = $value; $this->wordsArray[$word] = $value;
$this->refsArray[$word] = $ref; $this->refsArray[$word] = $ref;
   
return $this->wordsArray[$word]; return $this->wordsArray[$word];
} }
   
/* /*
* Shuffle associated names in array * Shuffle associated names in array
*/ */
   
function shuffleCloud() function shuffleCloud()
{ {
$keys = array_keys($this->wordsArray); $keys = array_keys($this->wordsArray);
   
shuffle($keys); shuffle($keys);
   
if (count($keys) && is_array($keys)) if (count($keys) && is_array($keys))
{ {
$tmpArray = $this->wordsArray; $tmpArray = $this->wordsArray;
$this->wordsArray = array(); $this->wordsArray = array();
foreach ($keys as $key => $value) foreach ($keys as $key => $value)
$this->wordsArray[$value] = $tmpArray[$value]; $this->wordsArray[$value] = $tmpArray[$value];
} }
} }
   
/* /*
* Calculate size of words array * Calculate size of words array
*/ */
   
function getCloudSize() function getCloudSize()
{ {
return array_sum($this->wordsArray); return array_sum($this->wordsArray);
} }
   
/* /*
* Get the class range using a percentage * Get the class range using a percentage
* *
* @returns int $class * @returns int $class
*/ */
   
function getClassFromPercent($percent) function getClassFromPercent($percent)
{ {
if ($percent >= 99) if ($percent >= 99)
$class = 1; $class = 1;
else if ($percent >= 70) else if ($percent >= 70)
$class = 2; $class = 2;
else if ($percent >= 60) else if ($percent >= 60)
$class = 3; $class = 3;
else if ($percent >= 50) else if ($percent >= 50)
$class = 4; $class = 4;
else if ($percent >= 40) else if ($percent >= 40)
$class = 5; $class = 5;
else if ($percent >= 30) else if ($percent >= 30)
$class = 6; $class = 6;
else if ($percent >= 20) else if ($percent >= 20)
$class = 7; $class = 7;
else if ($percent >= 10) else if ($percent >= 10)
$class = 8; $class = 8;
else if ($percent >= 5) else if ($percent >= 5)
$class = 9; $class = 9;
else else
$class = 0; $class = 0;
   
return $class; return $class;
} }
   
/* /*
* Create the HTML code for each word and apply font size. * Create the HTML code for each word and apply font size.
* *
* @returns string $spans * @returns string $spans
*/ */
   
function showCloud($returnType = "html") function showCloud($returnType = "html")
{ {
$this->shuffleCloud(); $this->shuffleCloud();
$this->max = max($this->wordsArray); $this->max = max($this->wordsArray);
   
if (is_array($this->wordsArray)) if (is_array($this->wordsArray))
{ {
$return = ($returnType == "html" ? "" : ($returnType == "array" ? array() : "")); $return = ($returnType == "html" ? "" : ($returnType == "array" ? array() : ""));
foreach ($this->wordsArray as $word => $popularity) foreach ($this->wordsArray as $word => $popularity)
{ {
$sizeRange = $this->getClassFromPercent(($popularity / $this->max) * 100); $sizeRange = $this->getClassFromPercent(($popularity / $this->max) * 100);
if ($returnType == "array") if ($returnType == "array")
{ {
$return[$word]['word'] = $word; $return[$word]['word'] = $word;
$return[$word]['ref'] = $this->refsArray[$word]; $return[$word]['ref'] = $this->refsArray[$word];
$return[$word]['sizeRange'] = $sizeRange; $return[$word]['sizeRange'] = $sizeRange;
if ($currentColour) if ($currentColour)
$return[$word]['randomColour'] = $currentColour; $return[$word]['randomColour'] = $currentColour;
} }
else if ($returnType == "html") else if ($returnType == "html")
{ {
$return .= "<span class='word size{$sizeRange}'> {$word} </span>"; $return .= "<span class='word size{$sizeRange}'> {$word} </span>";
} }
} }
return $return; return $return;
} }
} }
} }
?> ?>
   
file:a/search.php -> file:b/search.php
<?php <?php
/* /*
search ABNs search ABNs
search agency name search agency name
search categories search categories
search supplier names search supplier names
--search supplier postcodes/suburbs/cities-- --search supplier postcodes/suburbs/cities--
search CN number search CN number
search description full text search description full text
*/ */
include('./lib/common.inc.php'); include('./lib/common.inc.php');
if ($_REQUEST['searchID']) { if ($_REQUEST['searchID']) {
$searchIDParts = explode("-",$_REQUEST['searchID']); $searchIDParts = explode("-",$_REQUEST['searchID']);
$type = array_shift($searchIDParts); $type = array_shift($searchIDParts);
$host = $_SERVER['HTTP_HOST']; $host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\'); $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
if ($type == "agency") { if ($type == "agency") {
header("Location: http://$host$uri/displayAgency.php?agency=".implode("-",$searchIDParts)); header("Location: http://$host$uri/displayAgency.php?agency=".implode("-",$searchIDParts));
} }
if ($type == "supplier") { if ($type == "supplier") {
header("Location: http://$host$uri/displaySupplier.php?supplier=".implode("-",$searchIDParts)); header("Location: http://$host$uri/displaySupplier.php?supplier=".implode("-",$searchIDParts));
} }
exit; exit;
} else { } else {
include_header("Search Results"); include_header("Search Results");
print_r($_REQUEST); print_r($_REQUEST);
include_footer(); include_footer();
} }
?> ?>
   
<?php <?php
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
$input = strtolower($_GET['input']); $input = strtolower($_GET['input']);
$len = strlen($input); $len = strlen($input);
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 0; $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 0;
$aResults = array(); $aResults = array();
$count = 0; $count = 0;
if ($len) { if ($len) {
$query = "SELECT supplierName, supplierABN, supplierName, count(*) as count $query = "SELECT supplierName, supplierABN, supplierName, count(*) as count
FROM `contractnotice` FROM `contractnotice`
WHERE supplierName LIKE '$input%' WHERE supplierName LIKE '$input%'
GROUP BY supplierName GROUP BY supplierName
ORDER BY count DESC ORDER BY count DESC
LIMIT 4; LIMIT 4;
"; ";
$result = mysql_query($query); $result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$count++; $count++;
$aResults[] = array( $aResults[] = array(
"id" => "supplier-".$row['supplierABN'].'-'.$row['supplierName'], "id" => "supplier-".$row['supplierABN'].'-'.$row['supplierName'],
"value" => htmlspecialchars($row['supplierName']) , "value" => htmlspecialchars($row['supplierName']) ,
"info" => htmlspecialchars("Supplier - ". $row['count']." records") "info" => htmlspecialchars("Supplier - ". $row['count']." records")
); );
} }
$query = "SELECT agencyName, count(*) as count $query = "SELECT agencyName, count(*) as count
FROM `contractnotice` FROM `contractnotice`
WHERE agencyName LIKE '$input%' WHERE agencyName LIKE '$input%'
GROUP BY agencyName GROUP BY agencyName
ORDER BY count DESC ORDER BY count DESC
LIMIT 4;"; LIMIT 4;";
$result = mysql_query($query); $result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) { while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$count++; $count++;
$aResults[] = array( $aResults[] = array(
"id" => "agency-".$row['agencyName'], "id" => "agency-".$row['agencyName'],
"value" => htmlspecialchars($row['agencyName']) , "value" => htmlspecialchars($row['agencyName']) ,
"info" => htmlspecialchars("Government Agency - ". $row['count']." records") "info" => htmlspecialchars("Government Agency - ". $row['count']." records")
); );
} }
} }
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Pragma: no-cache"); // HTTP/1.0 header("Pragma: no-cache"); // HTTP/1.0
if (isset($_REQUEST['json'])) { if (isset($_REQUEST['json'])) {
header("Content-Type: application/json"); header("Content-Type: application/json");
echo "{\"results\": ["; echo "{\"results\": [";
$arr = array(); $arr = array();
for ($i = 0;$i < count($aResults);$i++) { for ($i = 0;$i < count($aResults);$i++) {
$arr[] = "{\"id\": \"" . $aResults[$i]['id'] . "\", \"value\": \"" . $aResults[$i]['value'] . "\", \"info\": \"\"}"; $arr[] = "{\"id\": \"" . $aResults[$i]['id'] . "\", \"value\": \"" . $aResults[$i]['value'] . "\", \"info\": \"\"}";
} }
echo implode(", ", $arr); echo implode(", ", $arr);
echo "]}"; echo "]}";
} else { } else {
header("Content-Type: text/xml"); header("Content-Type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?><results>"; echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?><results>";
for ($i = 0;$i < count($aResults);$i++) { for ($i = 0;$i < count($aResults);$i++) {
echo "<rs id=\"" . $aResults[$i]['id'] . "\" info=\"" . $aResults[$i]['info'] . "\">" . $aResults[$i]['value'] . "</rs>"; echo "<rs id=\"" . $aResults[$i]['id'] . "\" info=\"" . $aResults[$i]['info'] . "\">" . $aResults[$i]['value'] . "</rs>";
} }
echo "</results>"; echo "</results>";
} }
?> ?>
file:a/todo.txt -> file:b/todo.txt
can we merge accountablity-avoiding contract notices (ie sequential/similar agencyInternalID/description to same vendor, same publish date) can we merge accountablity-avoiding contract notices (ie sequential/similar agencyInternalID/description to same vendor, same publish date)
can we merge ABN splitting companies like PWC/Dell Finance? can we merge ABN splitting companies like PWC/Dell Finance?
can we add google news? lobbyist officers? can we add google news? lobbyist officers?
   
  compile database of file lists
   
  compile database of employees