/mcmis/reportico/jpgraph/src/jpgraph.php
PHP | 1809 lines | 1355 code | 223 blank | 231 comment | 309 complexity | 5430694b2658b28ecafb3b59a8d68398 MD5 | raw file
Possible License(s): LGPL-2.1
- <?php
- //=======================================================================
- // File: JPGRAPH.PHP
- // Description: PHP Graph Plotting library. Base module.
- // Created: 2001-01-08
- // Ver: $Id: jpgraph.php,v 1.1.1.1 2010-10-26 21:13:51 peter Exp $
- //
- // Copyright (c) Aditus Consulting. All rights reserved.
- //========================================================================
- require_once('jpg-config.inc.php');
- require_once('jpgraph_gradient.php');
- require_once('jpgraph_errhandler.inc.php');
- require_once('jpgraph_ttf.inc.php');
- require_once('jpgraph_rgb.inc.php');
- require_once('jpgraph_text.inc.php');
- require_once('jpgraph_legend.inc.php');
- require_once('gd_image.inc.php');
- // Version info
- define('JPG_VERSION','3.0.7');
- // Minimum required PHP version
- define('MIN_PHPVERSION','5.1.0');
- // Special file name to indicate that we only want to calc
- // the image map in the call to Graph::Stroke() used
- // internally from the GetHTMLCSIM() method.
- define('_CSIM_SPECIALFILE','_csim_special_');
- // HTTP GET argument that is used with image map
- // to indicate to the script to just generate the image
- // and not the full CSIM HTML page.
- define('_CSIM_DISPLAY','_jpg_csimd');
- // Special filename for Graph::Stroke(). If this filename is given
- // then the image will NOT be streamed to browser of file. Instead the
- // Stroke call will return the handler for the created GD image.
- define('_IMG_HANDLER','__handle');
- // 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.
- define('_IMG_AUTO','auto');
- // Tick density
- define("TICKD_DENSE",1);
- define("TICKD_NORMAL",2);
- define("TICKD_SPARSE",3);
- define("TICKD_VERYSPARSE",4);
- // Side for ticks and labels.
- define("SIDE_LEFT",-1);
- define("SIDE_RIGHT",1);
- define("SIDE_DOWN",-1);
- define("SIDE_BOTTOM",-1);
- define("SIDE_UP",1);
- define("SIDE_TOP",1);
- // Legend type stacked vertical or horizontal
- define("LEGEND_VERT",0);
- define("LEGEND_HOR",1);
- // Mark types for plot marks
- define("MARK_SQUARE",1);
- define("MARK_UTRIANGLE",2);
- define("MARK_DTRIANGLE",3);
- define("MARK_DIAMOND",4);
- define("MARK_CIRCLE",5);
- define("MARK_FILLEDCIRCLE",6);
- define("MARK_CROSS",7);
- define("MARK_STAR",8);
- define("MARK_X",9);
- define("MARK_LEFTTRIANGLE",10);
- define("MARK_RIGHTTRIANGLE",11);
- define("MARK_FLASH",12);
- define("MARK_IMG",13);
- define("MARK_FLAG1",14);
- define("MARK_FLAG2",15);
- define("MARK_FLAG3",16);
- define("MARK_FLAG4",17);
- // Builtin images
- define("MARK_IMG_PUSHPIN",50);
- define("MARK_IMG_SPUSHPIN",50);
- define("MARK_IMG_LPUSHPIN",51);
- define("MARK_IMG_DIAMOND",52);
- define("MARK_IMG_SQUARE",53);
- define("MARK_IMG_STAR",54);
- define("MARK_IMG_BALL",55);
- define("MARK_IMG_SBALL",55);
- define("MARK_IMG_MBALL",56);
- define("MARK_IMG_LBALL",57);
- define("MARK_IMG_BEVEL",58);
- // Inline defines
- define("INLINE_YES",1);
- define("INLINE_NO",0);
- // Format for background images
- define("BGIMG_FILLPLOT",1);
- define("BGIMG_FILLFRAME",2);
- define("BGIMG_COPY",3);
- define("BGIMG_CENTER",4);
- define("BGIMG_FREE",5);
- // Depth of objects
- define("DEPTH_BACK",0);
- define("DEPTH_FRONT",1);
- // Direction
- define("VERTICAL",1);
- define("HORIZONTAL",0);
- // Axis styles for scientific style axis
- define('AXSTYLE_SIMPLE',1);
- define('AXSTYLE_BOXIN',2);
- define('AXSTYLE_BOXOUT',3);
- define('AXSTYLE_YBOXIN',4);
- define('AXSTYLE_YBOXOUT',5);
- // Style for title backgrounds
- define('TITLEBKG_STYLE1',1);
- define('TITLEBKG_STYLE2',2);
- define('TITLEBKG_STYLE3',3);
- define('TITLEBKG_FRAME_NONE',0);
- define('TITLEBKG_FRAME_FULL',1);
- define('TITLEBKG_FRAME_BOTTOM',2);
- define('TITLEBKG_FRAME_BEVEL',3);
- define('TITLEBKG_FILLSTYLE_HSTRIPED',1);
- define('TITLEBKG_FILLSTYLE_VSTRIPED',2);
- define('TITLEBKG_FILLSTYLE_SOLID',3);
- // Styles for axis labels background
- define('LABELBKG_NONE',0);
- define('LABELBKG_XAXIS',1);
- define('LABELBKG_YAXIS',2);
- define('LABELBKG_XAXISFULL',3);
- define('LABELBKG_YAXISFULL',4);
- define('LABELBKG_XYFULL',5);
- define('LABELBKG_XY',6);
- // Style for background gradient fills
- define('BGRAD_FRAME',1);
- define('BGRAD_MARGIN',2);
- define('BGRAD_PLOT',3);
- // Width of tab titles
- define('TABTITLE_WIDTHFIT',0);
- define('TABTITLE_WIDTHFULL',-1);
- // Defines for 3D skew directions
- define('SKEW3D_UP',0);
- define('SKEW3D_DOWN',1);
- define('SKEW3D_LEFT',2);
- define('SKEW3D_RIGHT',3);
- // For internal use only
- define("_JPG_DEBUG",false);
- define("_FORCE_IMGTOFILE",false);
- define("_FORCE_IMGDIR",'/tmp/jpgimg/');
- //
- // Automatic settings of path for cache and font directory
- // if they have not been previously specified
- //
- if(USE_CACHE) {
- if (!defined('CACHE_DIR')) {
- if ( strstr( PHP_OS, 'WIN') ) {
- if( empty($_SERVER['TEMP']) ) {
- $t = new ErrMsgText();
- $msg = $t->Get(11,$file,$lineno);
- die($msg);
- }
- else {
- define('CACHE_DIR', $_SERVER['TEMP'] . '/');
- }
- } else {
- define('CACHE_DIR','/tmp/jpgraph_cache/');
- }
- }
- }
- elseif( !defined('CACHE_DIR') ) {
- define('CACHE_DIR', '');
- }
- //
- // Setup path for western/latin TTF fonts
- //
- if (!defined('TTF_DIR')) {
- if (strstr( PHP_OS, 'WIN') ) {
- $sroot = getenv('SystemRoot');
- if( empty($sroot) ) {
- $t = new ErrMsgText();
- $msg = $t->Get(12,$file,$lineno);
- die($msg);
- }
- else {
- define('TTF_DIR', $sroot.'/fonts/');
- }
- } else {
- define('TTF_DIR','/usr/share/fonts/truetype/');
- }
- }
- //
- // Setup path for MultiByte TTF fonts (japanese, chinese etc.)
- //
- if (!defined('MBTTF_DIR')) {
- if (strstr( PHP_OS, 'WIN') ) {
- $sroot = getenv('SystemRoot');
- if( empty($sroot) ) {
- $t = new ErrMsgText();
- $msg = $t->Get(12,$file,$lineno);
- die($msg);
- }
- else {
- define('MBTTF_DIR', $sroot.'/fonts/');
- }
- } else {
- define('MBTTF_DIR','/usr/share/fonts/truetype/');
- }
- }
- //
- // Check minimum PHP version
- //
- function CheckPHPVersion($aMinVersion) {
- list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION);
- list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion);
- if ($majorC != $majorR) return false;
- if ($majorC < $majorR) return false;
- // same major - check minor
- if ($minorC > $minorR) return true;
- if ($minorC < $minorR) return false;
- // and same minor
- if ($editC >= $editR) return true;
- return true;
- }
- //
- // Make sure PHP version is high enough
- //
- if( !CheckPHPVersion(MIN_PHPVERSION) ) {
- JpGraphError::RaiseL(13,PHP_VERSION,MIN_PHPVERSION);
- die();
- }
- //
- // Make GD sanity check
- //
- if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) {
- JpGraphError::RaiseL(25001);
- //("This PHP installation is not configured with the GD library. Please recompile PHP with GD support to run JpGraph. (Neither function imagetypes() nor imagecreatefromstring() does exist)");
- }
- //
- // Setup PHP error handler
- //
- function _phpErrorHandler($errno,$errmsg,$filename, $linenum, $vars) {
- // Respect current error level
- if( $errno & error_reporting() ) {
- JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
- }
- }
- if( INSTALL_PHP_ERR_HANDLER ) {
- set_error_handler("_phpErrorHandler");
- }
- //
- // Check if there were any warnings, perhaps some wrong includes by the user. In this
- // case we raise it immediately since otherwise the image will not show and makes
- // debugging difficult. This is controlled by the user setting CATCH_PHPERRMSG
- //
- if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
- JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']);
- }
- // Useful mathematical function
- function sign($a) {return $a >= 0 ? 1 : -1;}
- //
- // Utility function to generate an image name based on the filename we
- // are running from and assuming we use auto detection of graphic format
- // (top level), i.e it is safe to call this function
- // from a script that uses JpGraph
- //
- function GenImgName() {
- // Determine what format we should use when we save the images
- $supported = imagetypes();
- if( $supported & IMG_PNG ) $img_format="png";
- elseif( $supported & IMG_GIF ) $img_format="gif";
- elseif( $supported & IMG_JPG ) $img_format="jpeg";
- elseif( $supported & IMG_WBMP ) $img_format="wbmp";
- elseif( $supported & IMG_XPM ) $img_format="xpm";
- if( !isset($_SERVER['PHP_SELF']) ) {
- JpGraphError::RaiseL(25005);
- //(" Can't access PHP_SELF, PHP global variable. You can't run PHP from command line if you want to use the 'auto' naming of cache or image files.");
- }
- $fname = basename($_SERVER['PHP_SELF']);
- if( !empty($_SERVER['QUERY_STRING']) ) {
- $q = @$_SERVER['QUERY_STRING'];
- $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
- }
- else {
- $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
- }
- return $fname;
- }
- //===================================================
- // CLASS JpgTimer
- // Description: General timing utility class to handle
- // time measurement of generating graphs. Multiple
- // timers can be started.
- //===================================================
- class JpgTimer {
- private $start, $idx;
- function __construct() {
- $this->idx=0;
- }
- // Push a new timer start on stack
- function Push() {
- list($ms,$s)=explode(" ",microtime());
- $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;
- }
- // Pop the latest timer start and return the diff with the
- // current time
- function Pop() {
- assert($this->idx>0);
- list($ms,$s)=explode(" ",microtime());
- $etime=floor($ms*1000) + (1000*$s);
- $this->idx--;
- return $etime-$this->start[$this->idx];
- }
- } // Class
- //===================================================
- // CLASS DateLocale
- // Description: Hold localized text used in dates
- //===================================================
- class DateLocale {
- public $iLocale = 'C'; // environmental locale be used by default
- private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null;
- function __construct() {
- settype($this->iDayAbb, 'array');
- settype($this->iShortDay, 'array');
- settype($this->iShortMonth, 'array');
- settype($this->iMonthName, 'array');
- $this->Set('C');
- }
- function Set($aLocale) {
- if ( in_array($aLocale, array_keys($this->iDayAbb)) ){
- $this->iLocale = $aLocale;
- return TRUE; // already cached nothing else to do!
- }
- $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME
- if (is_array($aLocale)) {
- foreach ($aLocale as $loc) {
- $res = @setlocale(LC_TIME, $loc);
- if ( $res ) {
- $aLocale = $loc;
- break;
- }
- }
- }
- else {
- $res = @setlocale(LC_TIME, $aLocale);
- }
- if ( ! $res ) {
- JpGraphError::RaiseL(25007,$aLocale);
- //("You are trying to use the locale ($aLocale) which your PHP installation does not support. Hint: Use '' to indicate the default locale for this geographic region.");
- return FALSE;
- }
- $this->iLocale = $aLocale;
- for( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ) {
- $day = strftime('%a', strtotime("$ofs day"));
- $day[0] = strtoupper($day[0]);
- $this->iDayAbb[$aLocale][]= $day[0];
- $this->iShortDay[$aLocale][]= $day;
- }
- for($i=1; $i<=12; ++$i) {
- list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01")));
- $this->iShortMonth[$aLocale][] = ucfirst($short);
- $this->iMonthName [$aLocale][] = ucfirst($full);
- }
- setlocale(LC_TIME, $pLocale);
- return TRUE;
- }
- function GetDayAbb() {
- return $this->iDayAbb[$this->iLocale];
- }
- function GetShortDay() {
- return $this->iShortDay[$this->iLocale];
- }
- function GetShortMonth() {
- return $this->iShortMonth[$this->iLocale];
- }
- function GetShortMonthName($aNbr) {
- return $this->iShortMonth[$this->iLocale][$aNbr];
- }
- function GetLongMonthName($aNbr) {
- return $this->iMonthName[$this->iLocale][$aNbr];
- }
- function GetMonth() {
- return $this->iMonthName[$this->iLocale];
- }
- }
- // Global object handlers
- $gDateLocale = new DateLocale();
- $gJpgDateLocale = new DateLocale();
- //=======================================================
- // CLASS Footer
- // Description: Encapsulates the footer line in the Graph
- //=======================================================
- class Footer {
- public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ;
- public $left,$center,$right;
- private $iTimer=null, $itimerpoststring='';
- function __construct() {
- $this->left = new Text();
- $this->left->ParagraphAlign('left');
- $this->center = new Text();
- $this->center->ParagraphAlign('center');
- $this->right = new Text();
- $this->right->ParagraphAlign('right');
- }
- function SetTimer($aTimer,$aTimerPostString='') {
- $this->iTimer = $aTimer;
- $this->itimerpoststring = $aTimerPostString;
- }
- function SetMargin($aLeft=3,$aRight=3,$aBottom=3) {
- $this->iLeftMargin = $aLeft;
- $this->iRightMargin = $aRight;
- $this->iBottomMargin = $aBottom;
- }
- function Stroke($aImg) {
- $y = $aImg->height - $this->iBottomMargin;
- $x = $this->iLeftMargin;
- $this->left->Align('left','bottom');
- $this->left->Stroke($aImg,$x,$y);
- $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2;
- $this->center->Align('center','bottom');
- $this->center->Stroke($aImg,$x,$y);
- $x = $aImg->width - $this->iRightMargin;
- $this->right->Align('right','bottom');
- if( $this->iTimer != null ) {
- $this->right->Set( $this->right->t . sprintf('%.3f',$this->iTimer->Pop()/1000.0) . $this->itimerpoststring );
- }
- $this->right->Stroke($aImg,$x,$y);
- }
- }
- //===================================================
- // CLASS Graph
- // Description: Main class to handle graphs
- //===================================================
- class Graph {
- public $cache=null; // Cache object (singleton)
- public $img=null; // Img object (singleton)
- public $plots=array(); // Array of all plot object in the graph (for Y 1 axis)
- public $y2plots=array(); // Array of all plot object in the graph (for Y 2 axis)
- public $ynplots=array();
- public $xscale=null; // X Scale object (could be instance of LinearScale or LogScale
- public $yscale=null,$y2scale=null, $ynscale=array();
- public $iIcons = array(); // Array of Icons to add to
- public $cache_name; // File name to be used for the current graph in the cache directory
- public $xgrid=null; // X Grid object (linear or logarithmic)
- public $ygrid=null,$y2grid=null; //dito for Y
- public $doframe=true,$frame_color='black', $frame_weight=1; // Frame around graph
- public $boxed=false, $box_color='black', $box_weight=1; // Box around plot area
- public $doshadow=false,$shadow_width=4,$shadow_color='gray@0.5'; // Shadow for graph
- public $xaxis=null; // X-axis (instane of Axis class)
- public $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class)
- public $margin_color=array(230,230,230); // Margin color of graph
- public $plotarea_color=array(255,255,255); // Plot area color
- public $title,$subtitle,$subsubtitle; // Title and subtitle(s) text object
- public $axtype="linlin"; // Type of axis
- public $xtick_factor,$ytick_factor; // Factor to determine the maximum number of ticks depending on the plot width
- public $texts=null, $y2texts=null; // Text object to ge shown in the graph
- public $lines=null, $y2lines=null;
- public $bands=null, $y2bands=null;
- public $text_scale_off=0, $text_scale_abscenteroff=-1; // Text scale in fractions and for centering bars
- public $background_image='',$background_image_type=-1,$background_image_format="png";
- public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0;
- public $background_image_xpos=0,$background_image_ypos=0;
- public $image_bright=0, $image_contr=0, $image_sat=0;
- public $inline;
- public $showcsim=0,$csimcolor="red";//debug stuff, draw the csim boundaris on the image if <>0
- public $grid_depth=DEPTH_BACK; // Draw grid under all plots as default
- public $iAxisStyle = AXSTYLE_SIMPLE;
- public $iCSIMdisplay=false,$iHasStroked = false;
- public $footer;
- public $csimcachename = '', $csimcachetimeout = 0, $iCSIMImgAlt='';
- public $iDoClipping = false;
- public $y2orderback=true;
- public $tabtitle;
- public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN;
- public $bkg_gradfrom='navy', $bkg_gradto='silver';
- public $plot_gradtype=-1,$plot_gradstyle=BGRAD_MARGIN;
- public $plot_gradfrom='silver', $plot_gradto='navy';
- public $titlebackground = false;
- public $titlebackground_color = 'lightblue',
- $titlebackground_style = 1,
- $titlebackground_framecolor = 'blue',
- $titlebackground_framestyle = 2,
- $titlebackground_frameweight = 1,
- $titlebackground_bevelheight = 3 ;
- public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID;
- public $titlebkg_scolor1='black',$titlebkg_scolor2='white';
- public $framebevel = false, $framebeveldepth = 2 ;
- public $framebevelborder = false, $framebevelbordercolor='black';
- public $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4';
- public $background_image_mix=100;
- public $background_cflag = '';
- public $background_cflag_type = BGIMG_FILLPLOT;
- public $background_cflag_mix = 100;
- public $iImgTrans=false,
- $iImgTransHorizon = 100,$iImgTransSkewDist=150,
- $iImgTransDirection = 1, $iImgTransMinSize = true,
- $iImgTransFillColor='white',$iImgTransHighQ=false,
- $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
- public $legend;
- protected $iYAxisDeltaPos=50;
- protected $iIconDepth=DEPTH_BACK;
- protected $iAxisLblBgType = 0,
- $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
- $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
- protected $iTables=NULL;
- // aWIdth Width in pixels of image
- // aHeight Height in pixels of image
- // aCachedName Name for image file in cache directory
- // aTimeOut Timeout in minutes for image in cache
- // aInline If true the image is streamed back in the call to Stroke()
- // If false the image is just created in the cache
- function __construct($aWidth=300,$aHeight=200,$aCachedName='',$aTimeout=0,$aInline=true) {
- if( !is_numeric($aWidth) || !is_numeric($aHeight) ) {
- JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric');
- }
- // Automatically generate the image file name based on the name of the script that
- // generates the graph
- if( $aCachedName == 'auto' ) {
- $aCachedName=GenImgName();
- }
- // Should the image be streamed back to the browser or only to the cache?
- $this->inline=$aInline;
- $this->img = new RotImage($aWidth,$aHeight);
- $this->cache = new ImgStreamCache();
- // Window doesn't like '?' in the file name so replace it with an '_'
- $aCachedName = str_replace("?","_",$aCachedName);
- $this->SetupCache($aCachedName, $aTimeout);
- $this->title = new Text();
- $this->title->ParagraphAlign('center');
- $this->title->SetFont(FF_FONT2,FS_BOLD);
- $this->title->SetMargin(5);
- $this->title->SetAlign('center');
- $this->subtitle = new Text();
- $this->subtitle->ParagraphAlign('center');
- $this->subtitle->SetMargin(3);
- $this->subtitle->SetAlign('center');
- $this->subsubtitle = new Text();
- $this->subsubtitle->ParagraphAlign('center');
- $this->subsubtitle->SetMargin(3);
- $this->subsubtitle->SetAlign('center');
- $this->legend = new Legend();
- $this->footer = new Footer();
- // If the cached version exist just read it directly from the
- // cache, stream it back to browser and exit
- if( $aCachedName!='' && READ_CACHE && $aInline ) {
- if( $this->cache->GetAndStream($this->img,$aCachedName) ) {
- exit();
- }
- }
- $this->SetTickDensity(); // Normal density
- $this->tabtitle = new GraphTabTitle();
- }
- function SetupCache($aFilename,$aTimeout=60) {
- $this->cache_name = $aFilename;
- $this->cache->SetTimeOut($aTimeout);
- }
- // Enable final image perspective transformation
- function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) {
- $this->iImgTrans = true;
- $this->iImgTransHorizon = $aHorizon;
- $this->iImgTransSkewDist= $aSkewDist;
- $this->iImgTransDirection = $aDir;
- $this->iImgTransMinSize = $aMinSize;
- $this->iImgTransFillColor=$aFillColor;
- $this->iImgTransHighQ=$aQuality;
- $this->iImgTransBorder=$aBorder;
- $this->iImgTransHorizonPos=$aHorizonPos;
- }
- function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
- $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
- }
- function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
- $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
- }
- function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
- $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
- }
- function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
- $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
- }
- // Set Image format and optional quality
- function SetImgFormat($aFormat,$aQuality=75) {
- $this->img->SetImgFormat($aFormat,$aQuality);
- }
- // Should the grid be in front or back of the plot?
- function SetGridDepth($aDepth) {
- $this->grid_depth=$aDepth;
- }
- function SetIconDepth($aDepth) {
- $this->iIconDepth=$aDepth;
- }
- // Specify graph angle 0-360 degrees.
- function SetAngle($aAngle) {
- $this->img->SetAngle($aAngle);
- }
- function SetAlphaBlending($aFlg=true) {
- $this->img->SetAlphaBlending($aFlg);
- }
- // Shortcut to image margin
- function SetMargin($lm,$rm,$tm,$bm) {
- $this->img->SetMargin($lm,$rm,$tm,$bm);
- }
- function SetY2OrderBack($aBack=true) {
- $this->y2orderback = $aBack;
- }
- // Rotate the graph 90 degrees and set the margin
- // when we have done a 90 degree rotation
- function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
- $lm = $lm ==0 ? floor(0.2 * $this->img->width) : $lm ;
- $rm = $rm ==0 ? floor(0.1 * $this->img->width) : $rm ;
- $tm = $tm ==0 ? floor(0.2 * $this->img->height) : $tm ;
- $bm = $bm ==0 ? floor(0.1 * $this->img->height) : $bm ;
- $adj = ($this->img->height - $this->img->width)/2;
- $this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj);
- $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
- $this->SetAngle(90);
- if( empty($this->yaxis) || empty($this->xaxis) ) {
- JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()');
- }
- $this->xaxis->SetLabelAlign('right','center');
- $this->yaxis->SetLabelAlign('center','bottom');
- }
- function SetClipping($aFlg=true) {
- $this->iDoClipping = $aFlg ;
- }
- // Add a plot object to the graph
- function Add($aPlot) {
- if( $aPlot == null ) {
- JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
- }
- if( is_array($aPlot) && count($aPlot) > 0 ) {
- $cl = $aPlot[0];
- }
- else {
- $cl = $aPlot;
- }
- if( $cl instanceof Text ) $this->AddText($aPlot);
- elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) $this->AddLine($aPlot);
- elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) $this->AddBand($aPlot);
- elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
- elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) ) $this->AddTable($aPlot);
- else {
- if( is_array($aPlot) ) {
- $this->plots = array_merge($this->plots,$aPlot);
- }
- else {
- $this->plots[] = $aPlot;
- }
- }
- }
- function AddTable($aTable) {
- if( is_array($aTable) ) {
- for($i=0; $i < count($aTable); ++$i ) {
- $this->iTables[]=$aTable[$i];
- }
- }
- else {
- $this->iTables[] = $aTable ;
- }
- }
- function AddIcon($aIcon) {
- if( is_array($aIcon) ) {
- for($i=0; $i < count($aIcon); ++$i ) {
- $this->iIcons[]=$aIcon[$i];
- }
- }
- else {
- $this->iIcons[] = $aIcon ;
- }
- }
- // Add plot to second Y-scale
- function AddY2($aPlot) {
- if( $aPlot == null ) {
- JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph.");
- }
- if( is_array($aPlot) && count($aPlot) > 0 ) {
- $cl = $aPlot[0];
- }
- else {
- $cl = $aPlot;
- }
- if( $cl instanceof Text ) {
- $this->AddText($aPlot,true);
- }
- elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) {
- $this->AddLine($aPlot,true);
- }
- elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) {
- $this->AddBand($aPlot,true);
- }
- else {
- $this->y2plots[] = $aPlot;
- }
- }
- // Add plot to the extra Y-axises
- function AddY($aN,$aPlot) {
- if( $aPlot == null ) {
- JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph.");
- }
- if( is_array($aPlot) && count($aPlot) > 0 ) {
- $cl = $aPlot[0];
- }
- else {
- $cl = $aPlot;
- }
- if( ($cl instanceof Text) ||
- (class_exists('PlotLine',false) && ($cl instanceof PlotLine)) ||
- (class_exists('PlotBand',false) && ($cl instanceof PlotBand)) ) {
- JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis');
- }
- else {
- $this->ynplots[$aN][] = $aPlot;
- }
- }
- // Add text object to the graph
- function AddText($aTxt,$aToY2=false) {
- if( $aTxt == null ) {
- JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph.");
- }
- if( $aToY2 ) {
- if( is_array($aTxt) ) {
- for($i=0; $i < count($aTxt); ++$i ) {
- $this->y2texts[]=$aTxt[$i];
- }
- }
- else {
- $this->y2texts[] = $aTxt;
- }
- }
- else {
- if( is_array($aTxt) ) {
- for($i=0; $i < count($aTxt); ++$i ) {
- $this->texts[]=$aTxt[$i];
- }
- }
- else {
- $this->texts[] = $aTxt;
- }
- }
- }
- // Add a line object (class PlotLine) to the graph
- function AddLine($aLine,$aToY2=false) {
- if( $aLine == null ) {
- JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph.");
- }
- if( $aToY2 ) {
- if( is_array($aLine) ) {
- for($i=0; $i < count($aLine); ++$i ) {
- //$this->y2lines[]=$aLine[$i];
- $this->y2plots[]=$aLine[$i];
- }
- }
- else {
- //$this->y2lines[] = $aLine;
- $this->y2plots[]=$aLine;
- }
- }
- else {
- if( is_array($aLine) ) {
- for($i=0; $i<count($aLine); ++$i ) {
- //$this->lines[]=$aLine[$i];
- $this->plots[]=$aLine[$i];
- }
- }
- else {
- //$this->lines[] = $aLine;
- $this->plots[] = $aLine;
- }
- }
- }
- // Add vertical or horizontal band
- function AddBand($aBand,$aToY2=false) {
- if( $aBand == null ) {
- JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph.");
- }
- if( $aToY2 ) {
- if( is_array($aBand) ) {
- for($i=0; $i < count($aBand); ++$i ) {
- $this->y2bands[] = $aBand[$i];
- }
- }
- else {
- $this->y2bands[] = $aBand;
- }
- }
- else {
- if( is_array($aBand) ) {
- for($i=0; $i < count($aBand); ++$i ) {
- $this->bands[] = $aBand[$i];
- }
- }
- else {
- $this->bands[] = $aBand;
- }
- }
- }
- function SetPlotGradient($aFrom='navy',$aTo='silver',$aGradType=2) {
- $this->plot_gradtype=$aGradType;
- $this->plot_gradfrom = $aFrom;
- $this->plot_gradto = $aTo;
- }
- function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) {
- $this->bkg_gradtype=$aGradType;
- $this->bkg_gradstyle=$aStyle;
- $this->bkg_gradfrom = $aFrom;
- $this->bkg_gradto = $aTo;
- }
- // Set a country flag in the background
- function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
- $this->background_cflag = $aName;
- $this->background_cflag_type = $aBgType;
- $this->background_cflag_mix = $aMix;
- }
- // Alias for the above method
- function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
- $this->background_cflag = $aName;
- $this->background_cflag_type = $aBgType;
- $this->background_cflag_mix = $aMix;
- }
- // Specify a background image
- function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat='auto') {
- // Get extension to determine image type
- if( $aImgFormat == 'auto' ) {
- $e = explode('.',$aFileName);
- if( !$e ) {
- JpGraphError::RaiseL(25018,$aFileName);//('Incorrect file name for Graph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
- }
- $valid_formats = array('png', 'jpg', 'gif');
- $aImgFormat = strtolower($e[count($e)-1]);
- if ($aImgFormat == 'jpeg') {
- $aImgFormat = 'jpg';
- }
- elseif (!in_array($aImgFormat, $valid_formats) ) {
- JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName);
- }
- }
- $this->background_image = $aFileName;
- $this->background_image_type=$aBgType;
- $this->background_image_format=$aImgFormat;
- }
- function SetBackgroundImageMix($aMix) {
- $this->background_image_mix = $aMix ;
- }
- // Adjust background image position
- function SetBackgroundImagePos($aXpos,$aYpos) {
- $this->background_image_xpos = $aXpos ;
- $this->background_image_ypos = $aYpos ;
- }
- // Specify axis style (boxed or single)
- function SetAxisStyle($aStyle) {
- $this->iAxisStyle = $aStyle ;
- }
- // Set a frame around the plot area
- function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) {
- $this->boxed = $aDrawPlotFrame;
- $this->box_weight = $aPlotFrameWeight;
- $this->box_color = $aPlotFrameColor;
- }
- // Specify color for the plotarea (not the margins)
- function SetColor($aColor) {
- $this->plotarea_color=$aColor;
- }
- // Specify color for the margins (all areas outside the plotarea)
- function SetMarginColor($aColor) {
- $this->margin_color=$aColor;
- }
- // Set a frame around the entire image
- function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) {
- $this->doframe = $aDrawImgFrame;
- $this->frame_color = $aImgFrameColor;
- $this->frame_weight = $aImgFrameWeight;
- }
- function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) {
- $this->framebevel = $aFlg ;
- $this->framebeveldepth = $aDepth ;
- $this->framebevelborder = $aBorder ;
- $this->framebevelbordercolor = $aBorderColor ;
- $this->framebevelcolor1 = $aColor1 ;
- $this->framebevelcolor2 = $aColor2 ;
- $this->doshadow = false ;
- }
- // Set the shadow around the whole image
- function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor='darkgray') {
- $this->doshadow = $aShowShadow;
- $this->shadow_color = $aShadowColor;
- $this->shadow_width = $aShadowWidth;
- $this->footer->iBottomMargin += $aShadowWidth;
- $this->footer->iRightMargin += $aShadowWidth;
- }
- // Specify x,y scale. Note that if you manually specify the scale
- // you must also specify the tick distance with a call to Ticks::Set()
- function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
- $this->axtype = $aAxisType;
- if( $aYMax < $aYMin || $aXMax < $aXMin ) {
- JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.');
- }
- $yt=substr($aAxisType,-3,3);
- if( $yt == 'lin' ) {
- $this->yscale = new LinearScale($aYMin,$aYMax);
- }
- elseif( $yt == 'int' ) {
- $this->yscale = new LinearScale($aYMin,$aYMax);
- $this->yscale->SetIntScale();
- }
- elseif( $yt == 'log' ) {
- $this->yscale = new LogScale($aYMin,$aYMax);
- }
- else {
- JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)");
- }
- $xt=substr($aAxisType,0,3);
- if( $xt == 'lin' || $xt == 'tex' ) {
- $this->xscale = new LinearScale($aXMin,$aXMax,'x');
- $this->xscale->textscale = ($xt == 'tex');
- }
- elseif( $xt == 'int' ) {
- $this->xscale = new LinearScale($aXMin,$aXMax,'x');
- $this->xscale->SetIntScale();
- }
- elseif( $xt == 'dat' ) {
- $this->xscale = new DateScale($aXMin,$aXMax,'x');
- }
- elseif( $xt == 'log' ) {
- $this->xscale = new LogScale($aXMin,$aXMax,'x');
- }
- else {
- JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)");
- }
- $this->xaxis = new Axis($this->img,$this->xscale);
- $this->yaxis = new Axis($this->img,$this->yscale);
- $this->xgrid = new Grid($this->xaxis);
- $this->ygrid = new Grid($this->yaxis);
- $this->ygrid->Show();
- }
- // Specify secondary Y scale
- function SetY2Scale($aAxisType='lin',$aY2Min=1,$aY2Max=1) {
- if( $aAxisType == 'lin' ) {
- $this->y2scale = new LinearScale($aY2Min,$aY2Max);
- }
- elseif( $aAxisType == 'int' ) {
- $this->y2scale = new LinearScale($aY2Min,$aY2Max);
- $this->y2scale->SetIntScale();
- }
- elseif( $aAxisType == 'log' ) {
- $this->y2scale = new LogScale($aY2Min,$aY2Max);
- }
- else {
- JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)");
- }
- $this->y2axis = new Axis($this->img,$this->y2scale);
- $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT);
- $this->y2axis->SetLabelSide(SIDE_RIGHT);
- $this->y2axis->SetPos('max');
- $this->y2axis->SetTitleSide(SIDE_RIGHT);
- // Deafult position is the max x-value
- $this->y2grid = new Grid($this->y2axis);
- }
- // Set the delta position (in pixels) between the multiple Y-axis
- function SetYDeltaDist($aDist) {
- $this->iYAxisDeltaPos = $aDist;
- }
- // Specify secondary Y scale
- function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) {
- if( $aAxisType == 'lin' ) {
- $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
- }
- elseif( $aAxisType == 'int' ) {
- $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
- $this->ynscale[$aN]->SetIntScale();
- }
- elseif( $aAxisType == 'log' ) {
- $this->ynscale[$aN] = new LogScale($aYMin,$aYMax);
- }
- else {
- JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)");
- }
- $this->ynaxis[$aN] = new Axis($this->img,$this->ynscale[$aN]);
- $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT);
- $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT);
- }
- // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse'
- // The dividing factor have been determined heuristically according to my aesthetic
- // sense (or lack off) y.m.m.v !
- function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) {
- $this->xtick_factor=30;
- $this->ytick_factor=25;
- switch( $aYDensity ) {
- case TICKD_DENSE:
- $this->ytick_factor=12;
- break;
- case TICKD_NORMAL:
- $this->ytick_factor=25;
- break;
- case TICKD_SPARSE:
- $this->ytick_factor=40;
- break;
- case TICKD_VERYSPARSE:
- $this->ytick_factor=100;
- break;
- default:
- JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy");
- }
- switch( $aXDensity ) {
- case TICKD_DENSE:
- $this->xtick_factor=15;
- break;
- case TICKD_NORMAL:
- $this->xtick_factor=30;
- break;
- case TICKD_SPARSE:
- $this->xtick_factor=45;
- break;
- case TICKD_VERYSPARSE:
- $this->xtick_factor=60;
- break;
- default:
- JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx");
- }
- }
- // Get a string of all image map areas
- function GetCSIMareas() {
- if( !$this->iHasStroked ) {
- $this->Stroke(_CSIM_SPECIALFILE);
- }
- $csim = $this->title->GetCSIMAreas();
- $csim .= $this->subtitle->GetCSIMAreas();
- $csim .= $this->subsubtitle->GetCSIMAreas();
- $csim .= $this->legend->GetCSIMAreas();
- if( $this->y2axis != NULL ) {
- $csim .= $this->y2axis->title->GetCSIMAreas();
- }
- if( $this->texts != null ) {
- $n = count($this->texts);
- for($i=0; $i < $n; ++$i ) {
- $csim .= $this->texts[$i]->GetCSIMAreas();
- }
- }
- if( $this->y2texts != null && $this->y2scale != null ) {
- $n = count($this->y2texts);
- for($i=0; $i < $n; ++$i ) {
- $csim .= $this->y2texts[$i]->GetCSIMAreas();
- }
- }
- if( $this->yaxis != null && $this->xaxis != null ) {
- $csim .= $this->yaxis->title->GetCSIMAreas();
- $csim .= $this->xaxis->title->GetCSIMAreas();
- }
- $n = count($this->plots);
- for( $i=0; $i < $n; ++$i ) {
- $csim .= $this->plots[$i]->GetCSIMareas();
- }
- $n = count($this->y2plots);
- for( $i=0; $i < $n; ++$i ) {
- $csim .= $this->y2plots[$i]->GetCSIMareas();
- }
- $n = count($this->ynaxis);
- for( $i=0; $i < $n; ++$i ) {
- $m = count($this->ynplots[$i]);
- for($j=0; $j < $m; ++$j ) {
- $csim .= $this->ynplots[$i][$j]->GetCSIMareas();
- }
- }
- $n = count($this->iTables);
- for( $i=0; $i < $n; ++$i ) {
- $csim .= $this->iTables[$i]->GetCSIMareas();
- }
- return $csim;
- }
- // Get a complete <MAP>..</MAP> tag for the final image map
- function GetHTMLImageMap($aMapName) {
- $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
- $im .= $this->GetCSIMareas();
- $im .= "</map>";
- return $im;
- }
- function CheckCSIMCache($aCacheName,$aTimeOut=60) {
- global $_SERVER;
- if( $aCacheName=='auto' ) {
- $aCacheName=basename($_SERVER['PHP_SELF']);
- }
- $urlarg = $this->GetURLArguments();
- $this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg;
- $this->csimcachetimeout = $aTimeOut;
- // First determine if we need to check for a cached version
- // This differs from the standard cache in the sense that the
- // image and CSIM map HTML file is written relative to the directory
- // the script executes in and not the specified cache directory.
- // The reason for this is that the cache directory is not necessarily
- // accessible from the HTTP server.
- if( $this->csimcachename != '' ) {
- $dir = dirname($this->csimcachename);
- $base = basename($this->csimcachename);
- $base = strtok($base,'.');
- $suffix = strtok('.');
- $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
- $baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format;
- $timedout=false;
- // Does it exist at all ?
- if( file_exists($basecsim) && file_exists($baseimg) ) {
- // Check that it hasn't timed out
- $diff=time()-filemtime($basecsim);
- if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) {
- $timedout=true;
- @unlink($basecsim);
- @unlink($baseimg);
- }
- else {
- if ($fh = @fopen($basecsim, "r")) {
- fpassthru($fh);
- return true;
- }
- else {
- JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading.");
- }
- }
- }
- }
- return false;
- }
- // Build the argument string to be used with the csim images
- static function GetURLArguments($aAddRecursiveBlocker=false) {
- if( $aAddRecursiveBlocker ) {
- // This is a JPGRAPH internal defined that prevents
- // us from recursively coming here again
- $urlarg = _CSIM_DISPLAY.'=1';
- }
- // Now reconstruct any user URL argument
- reset($_GET);
- while( list($key,$value) = each($_GET) ) {
- if( is_array($value) ) {
- foreach ( $value as $k => $v ) {
- $urlarg .= '&'.$key.'%5B'.$k.'%5D='.urlencode($v);
- }
- }
- else {
- $urlarg .= '&'.$key.'='.urlencode($value);
- }
- }
- // It's not ideal to convert POST argument to GET arguments
- // but there is little else we can do. One idea for the
- // future might be recreate the POST header in case.
- reset($_POST);
- while( list($key,$value) = each($_POST) ) {
- if( is_array($value) ) {
- foreach ( $value as $k => $v ) {
- $urlarg .= '&'.$key.'%5B'.$k.'%5D='.urlencode($v);
- }
- }
- else {
- $urlarg .= '&'.$key.'='.urlencode($value);
- }
- }
- return $urlarg;
- }
- function SetCSIMImgAlt($aAlt) {
- $this->iCSIMImgAlt = $aAlt;
- }
- function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) {
- if( $aCSIMName=='' ) {
- // create a random map name
- srand ((double) microtime() * 1000000);
- $r = rand(0,100000);
- $aCSIMName='__mapname'.$r.'__';
- }
- if( $aScriptName=='auto' ) {
- $aScriptName=basename($_SERVER['PHP_SELF']);
- }
- $urlarg = $this->GetURLArguments(true);
- if( empty($_GET[_CSIM_DISPLAY]) ) {
- // First determine if we need to check for a cached version
- // This differs from the standard cache in the sense that the
- // image and CSIM map HTML file is written relative to the directory
- // the script executes in and not the specified cache directory.
- // The reason for this is that the cache directory is not necessarily
- // accessible from the HTTP server.
- if( $this->csimcachename != '' ) {
- $dir = dirname($this->csimcachename);
- $base = basename($this->csimcachename);
- $base = strtok($base,'.');
- $suffix = strtok('.');
- $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
- $baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format;
- // Check that apache can write to directory specified
- if( file_exists($dir) && !is_writeable($dir) ) {
- JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.');
- }
- // Make sure directory exists
- $this->cache->MakeDirs($dir);
- // Write the image file
- $this->Stroke(CSIMCACHE_DIR.$baseimg);
- // Construct wrapper HTML and write to file and send it back to browser
- // In the src URL we must replace the '?' with its encoding to prevent the arguments
- // to be converted to real arguments.
- $tmp = str_replace('?','%3f',$baseimg);
- $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n".
- '<img src="'.CSIMCACHE_HTTP_DIR.$tmp.'" ismap="ismap" usemap="#'.$aCSIMName.' width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
- if($fh = @fopen($basecsim,'w') ) {
- fwrite($fh,$htmlwrap);
- fclose($fh);
- echo $htmlwrap;
- }
- else {
- JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions.");
- }
- }
- else {
- if( $aScriptName=='' ) {
- JpGraphError::RaiseL(25030);//('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().');
- }
- echo $this->GetHTMLImageMap($aCSIMName) . $this->GetCSIMImgHTML($aCSIMName, $aScriptName, $aBorder);
- }
- }
- else {
- $this->Stroke();
- }
- }
- function StrokeCSIMImage() {
- if( @$_GET[_CSIM_DISPLAY] == 1 ) {
- $this->Stroke();
- }
- }
- function GetCSIMImgHTML($aCSIMName, $aScriptName='auto', $aBorder=0 ) {
- if( $aScriptName=='auto' ) {
- $aScriptName=basename($_SERVER['PHP_SELF']);
- }
- $urlarg = $this->GetURLArguments(true);
- return "<img src=\"".$aScriptName.'?'.$urlarg."\" ismap=\"ismap\" usemap=\"#".$aCSIMName.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
- }
- function GetTextsYMinMax($aY2=false) {
- if( $aY2 ) {
- $txts = $this->y2texts;
- }
- else {
- $txts = $this->texts;
- }
- $n = count($txts);
- $min=null;
- $max=null;
- for( $i=0; $i < $n; ++$i ) {
- if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) {
- if( $min === null ) {
- $min = $max = $txts[$i]->iScalePosY ;
- }
- else {
- $min = min($min,$txts[$i]->iScalePosY);
- $max = max($max,$txts[$i]->iScalePosY);
- }
- }
- }
- if( $min !== null ) {
- return array($min,$max);
- }
- else {
- return null;
- }
- }
- function GetTextsXMinMax($aY2=false) {
- if( $aY2 ) {
- $txts = $this->y2texts;
- }
- else {
- $txts = $this->texts;
- }
- $n = count($txts);
- $min=null;
- $max=null;
- for( $i=0; $i < $n; ++$i ) {
- if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) {
- if( $min === null ) {
- $min = $max = $txts[$i]->iScalePosX ;
- }
- else {
- $min = min($min,$txts[$i]->iScalePosX);
- $max = max($max,$txts[$i]->iScalePosX);
- }
- }
- }
- if( $min !== null ) {
- return array($min,$max);
- }
- else {
- return null;
- }
- }
- function GetXMinMax() {
- list($min,$ymin) = $this->plots[0]->Min();
- list($max,$ymax) = $this->plots[0]->Max();
- $i=0;
- // Some plots, e.g. PlotLine should not affect the scale
- // and will return (null,null). We should ignore those
- // values.
- while( ($min===null || $max === null) && ($i < count($this->plots)-1) ) {
- ++$i;
- list($min,$ymin) = $this->plots[$i]->Min();
- list($max,$ymax) = $this->plots[$i]->Max();
- }
- foreach( $this->plots as $p ) {
- list($xmin,$ymin) = $p->Min();
- list($xmax,$ymax) = $p->Max();
- if( $xmin !== null && $xmax !== null ) {
- $min = Min($xmin,$min);
- $max = Max($xmax,$max);
- }
- }
- if( $this->y2axis != null ) {
- foreach( $this->y2plots as $p ) {
- list($xmin,$ymin) = $p->Min();
- list($xmax,$ymax) = $p->Max();
- $min = Min($xmin,$min);
- $max = Max($xmax,$max);
- }
- }
- $n = count($this->ynaxis);
- for( $i=0; $i < $n; ++$i ) {
- if( $this->ynaxis[$i] != null) {
- foreach( $this->ynplots[$i] as $p ) {
- list($xmin,$ymin) = $p->Min();
- list($xmax,$ymax) = $p->Max();
- $min = Min($xmin,$min);
- $max = Max($xmax,$max);
- }
- }
- }
- return array($min,$max);
- }
- function AdjustMarginsForTitles() {
- $totrequired = ($this->title->t != '' ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 : 0 ) +
- ($this->subtitle->t != '' ? $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 : 0 ) +
- ($this->subsubtitle->t != '' ? $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 : 0 ) ;
- $btotrequired = 0;
- if($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels ) {
- // Minimum bottom margin
- if( $this->xaxis->title->t != '' ) {
- if( $this->img->a == 90 ) {
- $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 7 ;
- }
- else {
- $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 7 ;
- }
- }
- else {
- $btotrequired = 0;
- }
- if( $this->img->a == 90 ) {
- $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style,
- $this->yaxis->font_size);
- $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle);
- }
- else {
- $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style,
- $this->xaxis->font_size);
- $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle);
- }
- $btotrequired += $lh + 6;
- }
- if( $this->img->a == 90 ) {
- // DO Nothing. It gets too messy to do this properly for 90 deg...
- }
- else{
- if( $this->img->top_margin < $totrequired ) {
- $this->SetMargin($this->img->left_margin,$this->img->right_margin,
- $totrequired,$this->img->bottom_margin);
- }
- if( $this->img->bottom_margin < $btotrequired ) {
- $this->SetMargin($this->img->left_margin,$this->img->right_margin,
- $this->img->top_margin,$btotrequired);
- }
- }
- }
- function StrokeStore($aStrokeFileName) {
- // Get the handler to prevent the library from sending the
- // image to the browser
- $ih = $this->Stroke(_IMG_HANDLER);
- // Stroke it to a file
- $this->img->Stream($aStrokeFileName);
- // Send it back to browser
- $this->img->Headers();
- $this->img->Stream();
- }
- function doAutoscaleXAxis() {
- //Check if we should autoscale x-axis
- if( !$this->xscale->IsSpecified() ) {
- if( substr($this->axtype,0,4) == "text" ) {
- $max=0;
- $n = count($this->plots);
- for($i=0; $i < $n; ++$i ) {
- $p = $this->plots[$i];
- // We need some unfortunate sub class knowledge here in order
- // to increase number of data points in case it is a line plot
- // which has the barcenter set. If not it could mean that the
- // last point of the data is outside the scale since the barcenter
- // settings means that we will shift the entire plot half a tick step
- // to the right in oder to align with the center of the bars.
- if( class_exists('BarPlot',false) ) {
- $cl = strtolower(get_class($p));
- if( (class_exists('BarPlot',false) && ($p instanceof BarPlot)) || empty($p->barcenter) ) {
- $max=max($max,$p->numpoints-1);
- }
- else {
- $max=max($max,$p->numpoints);
- }
- }
- else {
- if( empty($p->barcenter) ) {
- $max=max($max,$p->numpoints-1);
- }
- else {
- $max=max($max,$p->numpoints);
- }
- }
- }
- $min=0;
- if( $this->y2axis != null ) {
- foreach( $this->y2plots as $p ) {
- $max=max($max,$p->numpoints-1);
- }
- }
- $n = count($this->ynaxis);
- for( $i=0; $i < $n; ++$i ) {
- if( $this->ynaxis[$i] != null) {
- foreach( $this->ynplots[$i] as $p ) {
- $max=max($max,$p->numpoints-1);
- }
- }
- }
- $this->xscale->Update($this->img,$min,$max);
- $this->xscale->ticks->Set($this->xaxis->tick_step,1);
- $this->xscale->ticks->SupressMinorTickMarks();
- }
- else {
- list($min,$max) = $this->GetXMinMax();
- $lres = $this->GetLinesXMinMax($this->lines);
- if( $lres ) {
- list($linmin,$linmax) = $lres ;
- $min = min($min,$linmin);
- $max = max($max,$linmax);
- }
- $lres = $this->GetLinesXMinMax($this->y2lines);
- if( $lres ) {
- list($linmin,$linmax) = $lres ;
- $min = min($min,$linmin);
- $max = max($max,$linmax);
- }
- $tres = $this->GetTextsXMinMax();
- if( $tres ) {
- list($tmin,$tmax) = $tres ;
- $min = min($min,$tmin);
- $max = max($max,$tmax);
- }
- $tres = $this->GetTextsXMinMax(true);
- if( $tres ) {
- list($tmin,$tmax) = $tres ;
- $min = min($min,$tmin);
- $max = max($max,$tmax);
- }
- $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor));
- }
- //Adjust position of y-axis and y2-axis to minimum/maximum of x-scale
- if( !is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos) ) {
- $this->yaxis->SetPos($this->xscale->GetMinVal());
- }
- }
- elseif( $this->xscale->IsSpecified() &&
- ( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) {
- // The tick calculation will use the user suplied min/max values to determine
- // the ticks. If auto_ticks is false the exact user specifed min and max
- // values will be used for the scale.
- // If auto_ticks is true then the scale might be slightly adjusted
- // so that the min and max values falls on an even major step.
- $min = $this->xscale->scale[0];
- $max = $this->xscale->scale[1];
- $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor),false);
- // Now make sure we show enough precision to accurate display the
- // labels. If this is not done then the user might end up with
- // a scale that might actually start with, say 13.5, butdue to rounding
- // the scale label will ony show 14.
- if( abs(floor($min)-$min) > 0 ) {
- // If the user has set a format then we bail out
- if( $this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '' ) {
- $this->xscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
- }
- }
- }
- // Position the optional Y2 and Yn axis to the rightmost position of the x-axis
- if( $this->y2axis != null ) {
- if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) {
- $this->y2axis->SetPos($this->xscale->GetMaxVal());
- }
- $this->y2axis->SetTitleSide(SIDE_RIGHT);
- }
- $n = count($this->ynaxis);
- $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0;
- for( $i=0; $i < $n; ++$i ) {
- if( $this->ynaxis[$i] != null ) {
- if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) {
- $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal());
- $this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj);
- }
- $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT);
- }
- }
- }
- function doAutoScaleYnAxis() {
- if( $this->y2scale != null) {
- if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) {
- list($min,$max) = $this->GetPlotsYMinMax($this->y2plots);
- $lres = $this->GetLinesYMinMax($this->y2lines);
- if( is_array($lres) ) {
- list($linmin,$linmax) = $lres ;
- $min = min($min,$linmin);
- $max = max($max,$linmax);
- }
- $tres = $this->GetTextsYMinMax(true);
- if( is_array($tres) ) {
- list($tmin,$tmax) = $tres ;
- $min = min($min,$tmin);
- $max = max($max,$tmax);
- }
- $this->y2scale->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor);
- }
- elseif( $this->y2scale->IsSpecified() && ( $this->y2scale->auto_ticks || !$this->y2scale->ticks->IsSpecified()) ) {
- // The tick calculation will use the user suplied min/max values to determine
- // the ticks. If auto_ticks is false the exact user specifed min and max
- // values will be used for the scale.
- // If auto_ticks is true then the scale might be slightly adjusted
- // so that the min and max values falls on an even major step.
- $min = $this->y2scale->scale[0];
- $max = $this->y2scale->scale[1];
- $this->y2scale->AutoScale($this->img,$min,$max,
- $this->img->plotheight/$this->ytick_factor,
- $this->y2scale->auto_ticks);
- // Now make sure we show enough precision to accurate display the
- // labels. If this is not done then the user might end up with
- // a scale that might actually start with, say 13.5, butdue to rounding
- // the scale label will ony show 14.
- if( abs(floor($min)-$min) > 0 ) {
- // If the user has set a format then we bail out
- if( $this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '' ) {
- $this->y2scale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
- }
- }
- }
- }
- //
- // Autoscale the extra Y-axises
- //
- $n = count($this->ynaxis);
- for( $i=0; $i < $n; ++$i ) {
- if( $this->ynscale[$i] != null) {
- if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) {
- list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]);
- $this->ynscale[$i]->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor);
- }
- elseif( $this->ynscale[$i]->IsSpecified() && ( $this->ynscale[$i]->auto_ticks || !$this->ynscale[$i]->ticks->IsSpecified()) ) {
- // The tick calculation will use the user suplied min/max values to determine
- // the ticks. If auto_ticks is false the exact user specifed min and max
- // values will be used for the scale.
- // If auto_ticks is true then the scale might be slightly adjusted
- // so that the min and max values falls on an even major step.
- $min = $this->ynscale[$i]->scale[0];
- $max = $this->ynscale[$i]->scale[1];
- $this->ynscale[$i]->AutoScale($this->img,$min,$max,
- $this->img->plotheight/$this->ytick_factor,
- $this->ynscale[$i]->auto_ticks);
- // Now make sure we show enough precision to accurate display the
- // labels. If this is not done then the user might end up with
- // a scale that might actually start with, say 13.5, butdue to rounding
- // the scale label will ony show 14.
- if( abs(floor($min)-$min) > 0 ) {
- // If the user has set a format then we bail out
- if( $this->ynscale[$i]->ticks->label_formatstr == '' && $this->ynscale[$i]->ticks->label_dateformatstr == '' ) {
- $this->ynscale[$i]->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
- }
- }
- }
- }
- }
- }
- function doAutoScaleYAxis() {
- //Check if we should autoscale y-axis
- if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) {
- list($min,$max) = $this->GetPlotsYMinMax($this->plots);
- $lres = $this->GetLinesYMinMax($this->lines);
- if( is_array($lres) ) {
- list($linmin,$linmax) = $lres ;
- $min = min($min,$linmin);
- $max = max($max,$linmax);
- }
- $tres = $this->GetTextsYMinMax();
- if( is_array($tres) ) {
- list($tmin,$tmax) = $tres ;
- $min = min($min,$tmin);
- $max = max($max,$tmax);
- }
- $this->yscale->AutoScale($this->img,$min,