PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/protected/Common/3rdParty/jpgraph/src/jpgraph.php

http://pradoportal.googlecode.com/
PHP | 5401 lines | 4060 code | 647 blank | 694 comment | 1008 complexity | e11c1a5aa6a07af326f5de49cd802d21 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. //=======================================================================
  3. // File: JPGRAPH.PHP
  4. // Description: PHP Graph Plotting library. Base module.
  5. // Created: 2001-01-08
  6. // Ver: $Id: jpgraph.php 1924 2010-01-11 14:03:26Z ljp $
  7. //
  8. // Copyright (c) Aditus Consulting. All rights reserved.
  9. //========================================================================
  10. require_once('jpg-config.inc.php');
  11. require_once('jpgraph_gradient.php');
  12. require_once('jpgraph_errhandler.inc.php');
  13. require_once('jpgraph_ttf.inc.php');
  14. require_once('jpgraph_rgb.inc.php');
  15. require_once('jpgraph_text.inc.php');
  16. require_once('jpgraph_legend.inc.php');
  17. require_once('gd_image.inc.php');
  18. // Version info
  19. define('JPG_VERSION','3.0.7');
  20. // Minimum required PHP version
  21. define('MIN_PHPVERSION','5.1.0');
  22. // Special file name to indicate that we only want to calc
  23. // the image map in the call to Graph::Stroke() used
  24. // internally from the GetHTMLCSIM() method.
  25. define('_CSIM_SPECIALFILE','_csim_special_');
  26. // HTTP GET argument that is used with image map
  27. // to indicate to the script to just generate the image
  28. // and not the full CSIM HTML page.
  29. define('_CSIM_DISPLAY','_jpg_csimd');
  30. // Special filename for Graph::Stroke(). If this filename is given
  31. // then the image will NOT be streamed to browser of file. Instead the
  32. // Stroke call will return the handler for the created GD image.
  33. define('_IMG_HANDLER','__handle');
  34. // Special filename for Graph::Stroke(). If this filename is given
  35. // the image will be stroked to a file with a name based on the script name.
  36. define('_IMG_AUTO','auto');
  37. // Tick density
  38. define("TICKD_DENSE",1);
  39. define("TICKD_NORMAL",2);
  40. define("TICKD_SPARSE",3);
  41. define("TICKD_VERYSPARSE",4);
  42. // Side for ticks and labels.
  43. define("SIDE_LEFT",-1);
  44. define("SIDE_RIGHT",1);
  45. define("SIDE_DOWN",-1);
  46. define("SIDE_BOTTOM",-1);
  47. define("SIDE_UP",1);
  48. define("SIDE_TOP",1);
  49. // Legend type stacked vertical or horizontal
  50. define("LEGEND_VERT",0);
  51. define("LEGEND_HOR",1);
  52. // Mark types for plot marks
  53. define("MARK_SQUARE",1);
  54. define("MARK_UTRIANGLE",2);
  55. define("MARK_DTRIANGLE",3);
  56. define("MARK_DIAMOND",4);
  57. define("MARK_CIRCLE",5);
  58. define("MARK_FILLEDCIRCLE",6);
  59. define("MARK_CROSS",7);
  60. define("MARK_STAR",8);
  61. define("MARK_X",9);
  62. define("MARK_LEFTTRIANGLE",10);
  63. define("MARK_RIGHTTRIANGLE",11);
  64. define("MARK_FLASH",12);
  65. define("MARK_IMG",13);
  66. define("MARK_FLAG1",14);
  67. define("MARK_FLAG2",15);
  68. define("MARK_FLAG3",16);
  69. define("MARK_FLAG4",17);
  70. // Builtin images
  71. define("MARK_IMG_PUSHPIN",50);
  72. define("MARK_IMG_SPUSHPIN",50);
  73. define("MARK_IMG_LPUSHPIN",51);
  74. define("MARK_IMG_DIAMOND",52);
  75. define("MARK_IMG_SQUARE",53);
  76. define("MARK_IMG_STAR",54);
  77. define("MARK_IMG_BALL",55);
  78. define("MARK_IMG_SBALL",55);
  79. define("MARK_IMG_MBALL",56);
  80. define("MARK_IMG_LBALL",57);
  81. define("MARK_IMG_BEVEL",58);
  82. // Inline defines
  83. define("INLINE_YES",1);
  84. define("INLINE_NO",0);
  85. // Format for background images
  86. define("BGIMG_FILLPLOT",1);
  87. define("BGIMG_FILLFRAME",2);
  88. define("BGIMG_COPY",3);
  89. define("BGIMG_CENTER",4);
  90. define("BGIMG_FREE",5);
  91. // Depth of objects
  92. define("DEPTH_BACK",0);
  93. define("DEPTH_FRONT",1);
  94. // Direction
  95. define("VERTICAL",1);
  96. define("HORIZONTAL",0);
  97. // Axis styles for scientific style axis
  98. define('AXSTYLE_SIMPLE',1);
  99. define('AXSTYLE_BOXIN',2);
  100. define('AXSTYLE_BOXOUT',3);
  101. define('AXSTYLE_YBOXIN',4);
  102. define('AXSTYLE_YBOXOUT',5);
  103. // Style for title backgrounds
  104. define('TITLEBKG_STYLE1',1);
  105. define('TITLEBKG_STYLE2',2);
  106. define('TITLEBKG_STYLE3',3);
  107. define('TITLEBKG_FRAME_NONE',0);
  108. define('TITLEBKG_FRAME_FULL',1);
  109. define('TITLEBKG_FRAME_BOTTOM',2);
  110. define('TITLEBKG_FRAME_BEVEL',3);
  111. define('TITLEBKG_FILLSTYLE_HSTRIPED',1);
  112. define('TITLEBKG_FILLSTYLE_VSTRIPED',2);
  113. define('TITLEBKG_FILLSTYLE_SOLID',3);
  114. // Styles for axis labels background
  115. define('LABELBKG_NONE',0);
  116. define('LABELBKG_XAXIS',1);
  117. define('LABELBKG_YAXIS',2);
  118. define('LABELBKG_XAXISFULL',3);
  119. define('LABELBKG_YAXISFULL',4);
  120. define('LABELBKG_XYFULL',5);
  121. define('LABELBKG_XY',6);
  122. // Style for background gradient fills
  123. define('BGRAD_FRAME',1);
  124. define('BGRAD_MARGIN',2);
  125. define('BGRAD_PLOT',3);
  126. // Width of tab titles
  127. define('TABTITLE_WIDTHFIT',0);
  128. define('TABTITLE_WIDTHFULL',-1);
  129. // Defines for 3D skew directions
  130. define('SKEW3D_UP',0);
  131. define('SKEW3D_DOWN',1);
  132. define('SKEW3D_LEFT',2);
  133. define('SKEW3D_RIGHT',3);
  134. // For internal use only
  135. define("_JPG_DEBUG",false);
  136. define("_FORCE_IMGTOFILE",false);
  137. define("_FORCE_IMGDIR",'/tmp/jpgimg/');
  138. //
  139. // Automatic settings of path for cache and font directory
  140. // if they have not been previously specified
  141. //
  142. if(USE_CACHE) {
  143. if (!defined('CACHE_DIR')) {
  144. if ( strstr( PHP_OS, 'WIN') ) {
  145. if( empty($_SERVER['TEMP']) ) {
  146. $t = new ErrMsgText();
  147. $msg = $t->Get(11,$file,$lineno);
  148. die($msg);
  149. }
  150. else {
  151. define('CACHE_DIR', $_SERVER['TEMP'] . '/');
  152. }
  153. } else {
  154. define('CACHE_DIR','/tmp/jpgraph_cache/');
  155. }
  156. }
  157. }
  158. elseif( !defined('CACHE_DIR') ) {
  159. define('CACHE_DIR', '');
  160. }
  161. //
  162. // Setup path for western/latin TTF fonts
  163. //
  164. if (!defined('TTF_DIR')) {
  165. if (strstr( PHP_OS, 'WIN') ) {
  166. $sroot = getenv('SystemRoot');
  167. if( empty($sroot) ) {
  168. $t = new ErrMsgText();
  169. $msg = $t->Get(12,$file,$lineno);
  170. die($msg);
  171. }
  172. else {
  173. define('TTF_DIR', $sroot.'/fonts/');
  174. }
  175. } else {
  176. define('TTF_DIR','/usr/share/fonts/truetype/');
  177. }
  178. }
  179. //
  180. // Setup path for MultiByte TTF fonts (japanese, chinese etc.)
  181. //
  182. if (!defined('MBTTF_DIR')) {
  183. if (strstr( PHP_OS, 'WIN') ) {
  184. $sroot = getenv('SystemRoot');
  185. if( empty($sroot) ) {
  186. $t = new ErrMsgText();
  187. $msg = $t->Get(12,$file,$lineno);
  188. die($msg);
  189. }
  190. else {
  191. define('MBTTF_DIR', $sroot.'/fonts/');
  192. }
  193. } else {
  194. define('MBTTF_DIR','/usr/share/fonts/truetype/');
  195. }
  196. }
  197. //
  198. // Check minimum PHP version
  199. //
  200. function CheckPHPVersion($aMinVersion) {
  201. list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION);
  202. list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion);
  203. if ($majorC != $majorR) return false;
  204. if ($majorC < $majorR) return false;
  205. // same major - check minor
  206. if ($minorC > $minorR) return true;
  207. if ($minorC < $minorR) return false;
  208. // and same minor
  209. if ($editC >= $editR) return true;
  210. return true;
  211. }
  212. //
  213. // Make sure PHP version is high enough
  214. //
  215. if( !CheckPHPVersion(MIN_PHPVERSION) ) {
  216. JpGraphError::RaiseL(13,PHP_VERSION,MIN_PHPVERSION);
  217. die();
  218. }
  219. //
  220. // Make GD sanity check
  221. //
  222. if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) {
  223. JpGraphError::RaiseL(25001);
  224. //("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)");
  225. }
  226. //
  227. // Setup PHP error handler
  228. //
  229. function _phpErrorHandler($errno,$errmsg,$filename, $linenum, $vars) {
  230. // Respect current error level
  231. if( $errno & error_reporting() ) {
  232. JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
  233. }
  234. }
  235. if( INSTALL_PHP_ERR_HANDLER ) {
  236. set_error_handler("_phpErrorHandler");
  237. }
  238. //
  239. // Check if there were any warnings, perhaps some wrong includes by the user. In this
  240. // case we raise it immediately since otherwise the image will not show and makes
  241. // debugging difficult. This is controlled by the user setting CATCH_PHPERRMSG
  242. //
  243. if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
  244. JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']);
  245. }
  246. // Useful mathematical function
  247. function sign($a) {return $a >= 0 ? 1 : -1;}
  248. //
  249. // Utility function to generate an image name based on the filename we
  250. // are running from and assuming we use auto detection of graphic format
  251. // (top level), i.e it is safe to call this function
  252. // from a script that uses JpGraph
  253. //
  254. function GenImgName() {
  255. // Determine what format we should use when we save the images
  256. $supported = imagetypes();
  257. if( $supported & IMG_PNG ) $img_format="png";
  258. elseif( $supported & IMG_GIF ) $img_format="gif";
  259. elseif( $supported & IMG_JPG ) $img_format="jpeg";
  260. elseif( $supported & IMG_WBMP ) $img_format="wbmp";
  261. elseif( $supported & IMG_XPM ) $img_format="xpm";
  262. if( !isset($_SERVER['PHP_SELF']) ) {
  263. JpGraphError::RaiseL(25005);
  264. //(" 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.");
  265. }
  266. $fname = basename($_SERVER['PHP_SELF']);
  267. if( !empty($_SERVER['QUERY_STRING']) ) {
  268. $q = @$_SERVER['QUERY_STRING'];
  269. $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
  270. }
  271. else {
  272. $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
  273. }
  274. return $fname;
  275. }
  276. //===================================================
  277. // CLASS JpgTimer
  278. // Description: General timing utility class to handle
  279. // time measurement of generating graphs. Multiple
  280. // timers can be started.
  281. //===================================================
  282. class JpgTimer {
  283. private $start, $idx;
  284. function __construct() {
  285. $this->idx=0;
  286. }
  287. // Push a new timer start on stack
  288. function Push() {
  289. list($ms,$s)=explode(" ",microtime());
  290. $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;
  291. }
  292. // Pop the latest timer start and return the diff with the
  293. // current time
  294. function Pop() {
  295. assert($this->idx>0);
  296. list($ms,$s)=explode(" ",microtime());
  297. $etime=floor($ms*1000) + (1000*$s);
  298. $this->idx--;
  299. return $etime-$this->start[$this->idx];
  300. }
  301. } // Class
  302. //===================================================
  303. // CLASS DateLocale
  304. // Description: Hold localized text used in dates
  305. //===================================================
  306. class DateLocale {
  307. public $iLocale = 'C'; // environmental locale be used by default
  308. private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null;
  309. function __construct() {
  310. settype($this->iDayAbb, 'array');
  311. settype($this->iShortDay, 'array');
  312. settype($this->iShortMonth, 'array');
  313. settype($this->iMonthName, 'array');
  314. $this->Set('C');
  315. }
  316. function Set($aLocale) {
  317. if ( in_array($aLocale, array_keys($this->iDayAbb)) ){
  318. $this->iLocale = $aLocale;
  319. return TRUE; // already cached nothing else to do!
  320. }
  321. $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME
  322. if (is_array($aLocale)) {
  323. foreach ($aLocale as $loc) {
  324. $res = @setlocale(LC_TIME, $loc);
  325. if ( $res ) {
  326. $aLocale = $loc;
  327. break;
  328. }
  329. }
  330. }
  331. else {
  332. $res = @setlocale(LC_TIME, $aLocale);
  333. }
  334. if ( ! $res ) {
  335. JpGraphError::RaiseL(25007,$aLocale);
  336. //("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.");
  337. return FALSE;
  338. }
  339. $this->iLocale = $aLocale;
  340. for( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ) {
  341. $day = strftime('%a', strtotime("$ofs day"));
  342. $day[0] = strtoupper($day[0]);
  343. $this->iDayAbb[$aLocale][]= $day[0];
  344. $this->iShortDay[$aLocale][]= $day;
  345. }
  346. for($i=1; $i<=12; ++$i) {
  347. list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01")));
  348. $this->iShortMonth[$aLocale][] = ucfirst($short);
  349. $this->iMonthName [$aLocale][] = ucfirst($full);
  350. }
  351. setlocale(LC_TIME, $pLocale);
  352. return TRUE;
  353. }
  354. function GetDayAbb() {
  355. return $this->iDayAbb[$this->iLocale];
  356. }
  357. function GetShortDay() {
  358. return $this->iShortDay[$this->iLocale];
  359. }
  360. function GetShortMonth() {
  361. return $this->iShortMonth[$this->iLocale];
  362. }
  363. function GetShortMonthName($aNbr) {
  364. return $this->iShortMonth[$this->iLocale][$aNbr];
  365. }
  366. function GetLongMonthName($aNbr) {
  367. return $this->iMonthName[$this->iLocale][$aNbr];
  368. }
  369. function GetMonth() {
  370. return $this->iMonthName[$this->iLocale];
  371. }
  372. }
  373. // Global object handlers
  374. $gDateLocale = new DateLocale();
  375. $gJpgDateLocale = new DateLocale();
  376. //=======================================================
  377. // CLASS Footer
  378. // Description: Encapsulates the footer line in the Graph
  379. //=======================================================
  380. class Footer {
  381. public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ;
  382. public $left,$center,$right;
  383. private $iTimer=null, $itimerpoststring='';
  384. function __construct() {
  385. $this->left = new Text();
  386. $this->left->ParagraphAlign('left');
  387. $this->center = new Text();
  388. $this->center->ParagraphAlign('center');
  389. $this->right = new Text();
  390. $this->right->ParagraphAlign('right');
  391. }
  392. function SetTimer($aTimer,$aTimerPostString='') {
  393. $this->iTimer = $aTimer;
  394. $this->itimerpoststring = $aTimerPostString;
  395. }
  396. function SetMargin($aLeft=3,$aRight=3,$aBottom=3) {
  397. $this->iLeftMargin = $aLeft;
  398. $this->iRightMargin = $aRight;
  399. $this->iBottomMargin = $aBottom;
  400. }
  401. function Stroke($aImg) {
  402. $y = $aImg->height - $this->iBottomMargin;
  403. $x = $this->iLeftMargin;
  404. $this->left->Align('left','bottom');
  405. $this->left->Stroke($aImg,$x,$y);
  406. $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2;
  407. $this->center->Align('center','bottom');
  408. $this->center->Stroke($aImg,$x,$y);
  409. $x = $aImg->width - $this->iRightMargin;
  410. $this->right->Align('right','bottom');
  411. if( $this->iTimer != null ) {
  412. $this->right->Set( $this->right->t . sprintf('%.3f',$this->iTimer->Pop()/1000.0) . $this->itimerpoststring );
  413. }
  414. $this->right->Stroke($aImg,$x,$y);
  415. }
  416. }
  417. //===================================================
  418. // CLASS Graph
  419. // Description: Main class to handle graphs
  420. //===================================================
  421. class Graph {
  422. public $cache=null; // Cache object (singleton)
  423. public $img=null; // Img object (singleton)
  424. public $plots=array(); // Array of all plot object in the graph (for Y 1 axis)
  425. public $y2plots=array(); // Array of all plot object in the graph (for Y 2 axis)
  426. public $ynplots=array();
  427. public $xscale=null; // X Scale object (could be instance of LinearScale or LogScale
  428. public $yscale=null,$y2scale=null, $ynscale=array();
  429. public $iIcons = array(); // Array of Icons to add to
  430. public $cache_name; // File name to be used for the current graph in the cache directory
  431. public $xgrid=null; // X Grid object (linear or logarithmic)
  432. public $ygrid=null,$y2grid=null; //dito for Y
  433. public $doframe=true,$frame_color='black', $frame_weight=1; // Frame around graph
  434. public $boxed=false, $box_color='black', $box_weight=1; // Box around plot area
  435. public $doshadow=false,$shadow_width=4,$shadow_color='gray@0.5'; // Shadow for graph
  436. public $xaxis=null; // X-axis (instane of Axis class)
  437. public $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class)
  438. public $margin_color=array(230,230,230); // Margin color of graph
  439. public $plotarea_color=array(255,255,255); // Plot area color
  440. public $title,$subtitle,$subsubtitle; // Title and subtitle(s) text object
  441. public $axtype="linlin"; // Type of axis
  442. public $xtick_factor,$ytick_factor; // Factor to determine the maximum number of ticks depending on the plot width
  443. public $texts=null, $y2texts=null; // Text object to ge shown in the graph
  444. public $lines=null, $y2lines=null;
  445. public $bands=null, $y2bands=null;
  446. public $text_scale_off=0, $text_scale_abscenteroff=-1; // Text scale in fractions and for centering bars
  447. public $background_image='',$background_image_type=-1,$background_image_format="png";
  448. public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0;
  449. public $background_image_xpos=0,$background_image_ypos=0;
  450. public $image_bright=0, $image_contr=0, $image_sat=0;
  451. public $inline;
  452. public $showcsim=0,$csimcolor="red";//debug stuff, draw the csim boundaris on the image if <>0
  453. public $grid_depth=DEPTH_BACK; // Draw grid under all plots as default
  454. public $iAxisStyle = AXSTYLE_SIMPLE;
  455. public $iCSIMdisplay=false,$iHasStroked = false;
  456. public $footer;
  457. public $csimcachename = '', $csimcachetimeout = 0, $iCSIMImgAlt='';
  458. public $iDoClipping = false;
  459. public $y2orderback=true;
  460. public $tabtitle;
  461. public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN;
  462. public $bkg_gradfrom='navy', $bkg_gradto='silver';
  463. public $plot_gradtype=-1,$plot_gradstyle=BGRAD_MARGIN;
  464. public $plot_gradfrom='silver', $plot_gradto='navy';
  465. public $titlebackground = false;
  466. public $titlebackground_color = 'lightblue',
  467. $titlebackground_style = 1,
  468. $titlebackground_framecolor = 'blue',
  469. $titlebackground_framestyle = 2,
  470. $titlebackground_frameweight = 1,
  471. $titlebackground_bevelheight = 3 ;
  472. public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID;
  473. public $titlebkg_scolor1='black',$titlebkg_scolor2='white';
  474. public $framebevel = false, $framebeveldepth = 2 ;
  475. public $framebevelborder = false, $framebevelbordercolor='black';
  476. public $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4';
  477. public $background_image_mix=100;
  478. public $background_cflag = '';
  479. public $background_cflag_type = BGIMG_FILLPLOT;
  480. public $background_cflag_mix = 100;
  481. public $iImgTrans=false,
  482. $iImgTransHorizon = 100,$iImgTransSkewDist=150,
  483. $iImgTransDirection = 1, $iImgTransMinSize = true,
  484. $iImgTransFillColor='white',$iImgTransHighQ=false,
  485. $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
  486. public $legend;
  487. protected $iYAxisDeltaPos=50;
  488. protected $iIconDepth=DEPTH_BACK;
  489. protected $iAxisLblBgType = 0,
  490. $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
  491. $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
  492. protected $iTables=NULL;
  493. // aWIdth Width in pixels of image
  494. // aHeight Height in pixels of image
  495. // aCachedName Name for image file in cache directory
  496. // aTimeOut Timeout in minutes for image in cache
  497. // aInline If true the image is streamed back in the call to Stroke()
  498. // If false the image is just created in the cache
  499. function __construct($aWidth=300,$aHeight=200,$aCachedName='',$aTimeout=0,$aInline=true) {
  500. if( !is_numeric($aWidth) || !is_numeric($aHeight) ) {
  501. JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric');
  502. }
  503. // Automatically generate the image file name based on the name of the script that
  504. // generates the graph
  505. if( $aCachedName == 'auto' ) {
  506. $aCachedName=GenImgName();
  507. }
  508. // Should the image be streamed back to the browser or only to the cache?
  509. $this->inline=$aInline;
  510. $this->img = new RotImage($aWidth,$aHeight);
  511. $this->cache = new ImgStreamCache();
  512. // Window doesn't like '?' in the file name so replace it with an '_'
  513. $aCachedName = str_replace("?","_",$aCachedName);
  514. $this->SetupCache($aCachedName, $aTimeout);
  515. $this->title = new Text();
  516. $this->title->ParagraphAlign('center');
  517. $this->title->SetFont(FF_FONT2,FS_BOLD);
  518. $this->title->SetMargin(5);
  519. $this->title->SetAlign('center');
  520. $this->subtitle = new Text();
  521. $this->subtitle->ParagraphAlign('center');
  522. $this->subtitle->SetMargin(3);
  523. $this->subtitle->SetAlign('center');
  524. $this->subsubtitle = new Text();
  525. $this->subsubtitle->ParagraphAlign('center');
  526. $this->subsubtitle->SetMargin(3);
  527. $this->subsubtitle->SetAlign('center');
  528. $this->legend = new Legend();
  529. $this->footer = new Footer();
  530. // If the cached version exist just read it directly from the
  531. // cache, stream it back to browser and exit
  532. if( $aCachedName!='' && READ_CACHE && $aInline ) {
  533. if( $this->cache->GetAndStream($this->img,$aCachedName) ) {
  534. exit();
  535. }
  536. }
  537. $this->SetTickDensity(); // Normal density
  538. $this->tabtitle = new GraphTabTitle();
  539. }
  540. function SetupCache($aFilename,$aTimeout=60) {
  541. $this->cache_name = $aFilename;
  542. $this->cache->SetTimeOut($aTimeout);
  543. }
  544. // Enable final image perspective transformation
  545. function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) {
  546. $this->iImgTrans = true;
  547. $this->iImgTransHorizon = $aHorizon;
  548. $this->iImgTransSkewDist= $aSkewDist;
  549. $this->iImgTransDirection = $aDir;
  550. $this->iImgTransMinSize = $aMinSize;
  551. $this->iImgTransFillColor=$aFillColor;
  552. $this->iImgTransHighQ=$aQuality;
  553. $this->iImgTransBorder=$aBorder;
  554. $this->iImgTransHorizonPos=$aHorizonPos;
  555. }
  556. function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
  557. $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
  558. }
  559. function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
  560. $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
  561. }
  562. function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
  563. $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
  564. }
  565. function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
  566. $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
  567. }
  568. // Set Image format and optional quality
  569. function SetImgFormat($aFormat,$aQuality=75) {
  570. $this->img->SetImgFormat($aFormat,$aQuality);
  571. }
  572. // Should the grid be in front or back of the plot?
  573. function SetGridDepth($aDepth) {
  574. $this->grid_depth=$aDepth;
  575. }
  576. function SetIconDepth($aDepth) {
  577. $this->iIconDepth=$aDepth;
  578. }
  579. // Specify graph angle 0-360 degrees.
  580. function SetAngle($aAngle) {
  581. $this->img->SetAngle($aAngle);
  582. }
  583. function SetAlphaBlending($aFlg=true) {
  584. $this->img->SetAlphaBlending($aFlg);
  585. }
  586. // Shortcut to image margin
  587. function SetMargin($lm,$rm,$tm,$bm) {
  588. $this->img->SetMargin($lm,$rm,$tm,$bm);
  589. }
  590. function SetY2OrderBack($aBack=true) {
  591. $this->y2orderback = $aBack;
  592. }
  593. // Rotate the graph 90 degrees and set the margin
  594. // when we have done a 90 degree rotation
  595. function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
  596. $lm = $lm ==0 ? floor(0.2 * $this->img->width) : $lm ;
  597. $rm = $rm ==0 ? floor(0.1 * $this->img->width) : $rm ;
  598. $tm = $tm ==0 ? floor(0.2 * $this->img->height) : $tm ;
  599. $bm = $bm ==0 ? floor(0.1 * $this->img->height) : $bm ;
  600. $adj = ($this->img->height - $this->img->width)/2;
  601. $this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj);
  602. $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
  603. $this->SetAngle(90);
  604. if( empty($this->yaxis) || empty($this->xaxis) ) {
  605. JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()');
  606. }
  607. $this->xaxis->SetLabelAlign('right','center');
  608. $this->yaxis->SetLabelAlign('center','bottom');
  609. }
  610. function SetClipping($aFlg=true) {
  611. $this->iDoClipping = $aFlg ;
  612. }
  613. // Add a plot object to the graph
  614. function Add($aPlot) {
  615. if( $aPlot == null ) {
  616. JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
  617. }
  618. if( is_array($aPlot) && count($aPlot) > 0 ) {
  619. $cl = $aPlot[0];
  620. }
  621. else {
  622. $cl = $aPlot;
  623. }
  624. if( $cl instanceof Text ) $this->AddText($aPlot);
  625. elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) $this->AddLine($aPlot);
  626. elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) $this->AddBand($aPlot);
  627. elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
  628. elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) ) $this->AddTable($aPlot);
  629. else {
  630. if( is_array($aPlot) ) {
  631. $this->plots = array_merge($this->plots,$aPlot);
  632. }
  633. else {
  634. $this->plots[] = $aPlot;
  635. }
  636. }
  637. }
  638. function AddTable($aTable) {
  639. if( is_array($aTable) ) {
  640. for($i=0; $i < count($aTable); ++$i ) {
  641. $this->iTables[]=$aTable[$i];
  642. }
  643. }
  644. else {
  645. $this->iTables[] = $aTable ;
  646. }
  647. }
  648. function AddIcon($aIcon) {
  649. if( is_array($aIcon) ) {
  650. for($i=0; $i < count($aIcon); ++$i ) {
  651. $this->iIcons[]=$aIcon[$i];
  652. }
  653. }
  654. else {
  655. $this->iIcons[] = $aIcon ;
  656. }
  657. }
  658. // Add plot to second Y-scale
  659. function AddY2($aPlot) {
  660. if( $aPlot == null ) {
  661. JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph.");
  662. }
  663. if( is_array($aPlot) && count($aPlot) > 0 ) {
  664. $cl = $aPlot[0];
  665. }
  666. else {
  667. $cl = $aPlot;
  668. }
  669. if( $cl instanceof Text ) {
  670. $this->AddText($aPlot,true);
  671. }
  672. elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) {
  673. $this->AddLine($aPlot,true);
  674. }
  675. elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) {
  676. $this->AddBand($aPlot,true);
  677. }
  678. else {
  679. $this->y2plots[] = $aPlot;
  680. }
  681. }
  682. // Add plot to the extra Y-axises
  683. function AddY($aN,$aPlot) {
  684. if( $aPlot == null ) {
  685. JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph.");
  686. }
  687. if( is_array($aPlot) && count($aPlot) > 0 ) {
  688. $cl = $aPlot[0];
  689. }
  690. else {
  691. $cl = $aPlot;
  692. }
  693. if( ($cl instanceof Text) ||
  694. (class_exists('PlotLine',false) && ($cl instanceof PlotLine)) ||
  695. (class_exists('PlotBand',false) && ($cl instanceof PlotBand)) ) {
  696. JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis');
  697. }
  698. else {
  699. $this->ynplots[$aN][] = $aPlot;
  700. }
  701. }
  702. // Add text object to the graph
  703. function AddText($aTxt,$aToY2=false) {
  704. if( $aTxt == null ) {
  705. JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph.");
  706. }
  707. if( $aToY2 ) {
  708. if( is_array($aTxt) ) {
  709. for($i=0; $i < count($aTxt); ++$i ) {
  710. $this->y2texts[]=$aTxt[$i];
  711. }
  712. }
  713. else {
  714. $this->y2texts[] = $aTxt;
  715. }
  716. }
  717. else {
  718. if( is_array($aTxt) ) {
  719. for($i=0; $i < count($aTxt); ++$i ) {
  720. $this->texts[]=$aTxt[$i];
  721. }
  722. }
  723. else {
  724. $this->texts[] = $aTxt;
  725. }
  726. }
  727. }
  728. // Add a line object (class PlotLine) to the graph
  729. function AddLine($aLine,$aToY2=false) {
  730. if( $aLine == null ) {
  731. JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph.");
  732. }
  733. if( $aToY2 ) {
  734. if( is_array($aLine) ) {
  735. for($i=0; $i < count($aLine); ++$i ) {
  736. //$this->y2lines[]=$aLine[$i];
  737. $this->y2plots[]=$aLine[$i];
  738. }
  739. }
  740. else {
  741. //$this->y2lines[] = $aLine;
  742. $this->y2plots[]=$aLine;
  743. }
  744. }
  745. else {
  746. if( is_array($aLine) ) {
  747. for($i=0; $i<count($aLine); ++$i ) {
  748. //$this->lines[]=$aLine[$i];
  749. $this->plots[]=$aLine[$i];
  750. }
  751. }
  752. else {
  753. //$this->lines[] = $aLine;
  754. $this->plots[] = $aLine;
  755. }
  756. }
  757. }
  758. // Add vertical or horizontal band
  759. function AddBand($aBand,$aToY2=false) {
  760. if( $aBand == null ) {
  761. JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph.");
  762. }
  763. if( $aToY2 ) {
  764. if( is_array($aBand) ) {
  765. for($i=0; $i < count($aBand); ++$i ) {
  766. $this->y2bands[] = $aBand[$i];
  767. }
  768. }
  769. else {
  770. $this->y2bands[] = $aBand;
  771. }
  772. }
  773. else {
  774. if( is_array($aBand) ) {
  775. for($i=0; $i < count($aBand); ++$i ) {
  776. $this->bands[] = $aBand[$i];
  777. }
  778. }
  779. else {
  780. $this->bands[] = $aBand;
  781. }
  782. }
  783. }
  784. function SetPlotGradient($aFrom='navy',$aTo='silver',$aGradType=2) {
  785. $this->plot_gradtype=$aGradType;
  786. $this->plot_gradfrom = $aFrom;
  787. $this->plot_gradto = $aTo;
  788. }
  789. function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) {
  790. $this->bkg_gradtype=$aGradType;
  791. $this->bkg_gradstyle=$aStyle;
  792. $this->bkg_gradfrom = $aFrom;
  793. $this->bkg_gradto = $aTo;
  794. }
  795. // Set a country flag in the background
  796. function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
  797. $this->background_cflag = $aName;
  798. $this->background_cflag_type = $aBgType;
  799. $this->background_cflag_mix = $aMix;
  800. }
  801. // Alias for the above method
  802. function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
  803. $this->background_cflag = $aName;
  804. $this->background_cflag_type = $aBgType;
  805. $this->background_cflag_mix = $aMix;
  806. }
  807. // Specify a background image
  808. function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat='auto') {
  809. // Get extension to determine image type
  810. if( $aImgFormat == 'auto' ) {
  811. $e = explode('.',$aFileName);
  812. if( !$e ) {
  813. 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');
  814. }
  815. $valid_formats = array('png', 'jpg', 'gif');
  816. $aImgFormat = strtolower($e[count($e)-1]);
  817. if ($aImgFormat == 'jpeg') {
  818. $aImgFormat = 'jpg';
  819. }
  820. elseif (!in_array($aImgFormat, $valid_formats) ) {
  821. JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName);
  822. }
  823. }
  824. $this->background_image = $aFileName;
  825. $this->background_image_type=$aBgType;
  826. $this->background_image_format=$aImgFormat;
  827. }
  828. function SetBackgroundImageMix($aMix) {
  829. $this->background_image_mix = $aMix ;
  830. }
  831. // Adjust background image position
  832. function SetBackgroundImagePos($aXpos,$aYpos) {
  833. $this->background_image_xpos = $aXpos ;
  834. $this->background_image_ypos = $aYpos ;
  835. }
  836. // Specify axis style (boxed or single)
  837. function SetAxisStyle($aStyle) {
  838. $this->iAxisStyle = $aStyle ;
  839. }
  840. // Set a frame around the plot area
  841. function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) {
  842. $this->boxed = $aDrawPlotFrame;
  843. $this->box_weight = $aPlotFrameWeight;
  844. $this->box_color = $aPlotFrameColor;
  845. }
  846. // Specify color for the plotarea (not the margins)
  847. function SetColor($aColor) {
  848. $this->plotarea_color=$aColor;
  849. }
  850. // Specify color for the margins (all areas outside the plotarea)
  851. function SetMarginColor($aColor) {
  852. $this->margin_color=$aColor;
  853. }
  854. // Set a frame around the entire image
  855. function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) {
  856. $this->doframe = $aDrawImgFrame;
  857. $this->frame_color = $aImgFrameColor;
  858. $this->frame_weight = $aImgFrameWeight;
  859. }
  860. function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) {
  861. $this->framebevel = $aFlg ;
  862. $this->framebeveldepth = $aDepth ;
  863. $this->framebevelborder = $aBorder ;
  864. $this->framebevelbordercolor = $aBorderColor ;
  865. $this->framebevelcolor1 = $aColor1 ;
  866. $this->framebevelcolor2 = $aColor2 ;
  867. $this->doshadow = false ;
  868. }
  869. // Set the shadow around the whole image
  870. function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor='darkgray') {
  871. $this->doshadow = $aShowShadow;
  872. $this->shadow_color = $aShadowColor;
  873. $this->shadow_width = $aShadowWidth;
  874. $this->footer->iBottomMargin += $aShadowWidth;
  875. $this->footer->iRightMargin += $aShadowWidth;
  876. }
  877. // Specify x,y scale. Note that if you manually specify the scale
  878. // you must also specify the tick distance with a call to Ticks::Set()
  879. function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
  880. $this->axtype = $aAxisType;
  881. if( $aYMax < $aYMin || $aXMax < $aXMin ) {
  882. JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.');
  883. }
  884. $yt=substr($aAxisType,-3,3);
  885. if( $yt == 'lin' ) {
  886. $this->yscale = new LinearScale($aYMin,$aYMax);
  887. }
  888. elseif( $yt == 'int' ) {
  889. $this->yscale = new LinearScale($aYMin,$aYMax);
  890. $this->yscale->SetIntScale();
  891. }
  892. elseif( $yt == 'log' ) {
  893. $this->yscale = new LogScale($aYMin,$aYMax);
  894. }
  895. else {
  896. JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)");
  897. }
  898. $xt=substr($aAxisType,0,3);
  899. if( $xt == 'lin' || $xt == 'tex' ) {
  900. $this->xscale = new LinearScale($aXMin,$aXMax,'x');
  901. $this->xscale->textscale = ($xt == 'tex');
  902. }
  903. elseif( $xt == 'int' ) {
  904. $this->xscale = new LinearScale($aXMin,$aXMax,'x');
  905. $this->xscale->SetIntScale();
  906. }
  907. elseif( $xt == 'dat' ) {
  908. $this->xscale = new DateScale($aXMin,$aXMax,'x');
  909. }
  910. elseif( $xt == 'log' ) {
  911. $this->xscale = new LogScale($aXMin,$aXMax,'x');
  912. }
  913. else {
  914. JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)");
  915. }
  916. $this->xaxis = new Axis($this->img,$this->xscale);
  917. $this->yaxis = new Axis($this->img,$this->yscale);
  918. $this->xgrid = new Grid($this->xaxis);
  919. $this->ygrid = new Grid($this->yaxis);
  920. $this->ygrid->Show();
  921. }
  922. // Specify secondary Y scale
  923. function SetY2Scale($aAxisType='lin',$aY2Min=1,$aY2Max=1) {
  924. if( $aAxisType == 'lin' ) {
  925. $this->y2scale = new LinearScale($aY2Min,$aY2Max);
  926. }
  927. elseif( $aAxisType == 'int' ) {
  928. $this->y2scale = new LinearScale($aY2Min,$aY2Max);
  929. $this->y2scale->SetIntScale();
  930. }
  931. elseif( $aAxisType == 'log' ) {
  932. $this->y2scale = new LogScale($aY2Min,$aY2Max);
  933. }
  934. else {
  935. JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)");
  936. }
  937. $this->y2axis = new Axis($this->img,$this->y2scale);
  938. $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT);
  939. $this->y2axis->SetLabelSide(SIDE_RIGHT);
  940. $this->y2axis->SetPos('max');
  941. $this->y2axis->SetTitleSide(SIDE_RIGHT);
  942. // Deafult position is the max x-value
  943. $this->y2grid = new Grid($this->y2axis);
  944. }
  945. // Set the delta position (in pixels) between the multiple Y-axis
  946. function SetYDeltaDist($aDist) {
  947. $this->iYAxisDeltaPos = $aDist;
  948. }
  949. // Specify secondary Y scale
  950. function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) {
  951. if( $aAxisType == 'lin' ) {
  952. $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
  953. }
  954. elseif( $aAxisType == 'int' ) {
  955. $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
  956. $this->ynscale[$aN]->SetIntScale();
  957. }
  958. elseif( $aAxisType == 'log' ) {
  959. $this->ynscale[$aN] = new LogScale($aYMin,$aYMax);
  960. }
  961. else {
  962. JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)");
  963. }
  964. $this->ynaxis[$aN] = new Axis($this->img,$this->ynscale[$aN]);
  965. $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT);
  966. $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT);
  967. }
  968. // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse'
  969. // The dividing factor have been determined heuristically according to my aesthetic
  970. // sense (or lack off) y.m.m.v !
  971. function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) {
  972. $this->xtick_factor=30;
  973. $this->ytick_factor=25;
  974. switch( $aYDensity ) {
  975. case TICKD_DENSE:
  976. $this->ytick_factor=12;
  977. break;
  978. case TICKD_NORMAL:
  979. $this->ytick_factor=25;
  980. break;
  981. case TICKD_SPARSE:
  982. $this->ytick_factor=40;
  983. break;
  984. case TICKD_VERYSPARSE:
  985. $this->ytick_factor=100;
  986. break;
  987. default:
  988. JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy");
  989. }
  990. switch( $aXDensity ) {
  991. case TICKD_DENSE:
  992. $this->xtick_factor=15;
  993. break;
  994. case TICKD_NORMAL:
  995. $this->xtick_factor=30;
  996. break;
  997. case TICKD_SPARSE:
  998. $this->xtick_factor=45;
  999. break;
  1000. case TICKD_VERYSPARSE:
  1001. $this->xtick_factor=60;
  1002. break;
  1003. default:
  1004. JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx");
  1005. }
  1006. }
  1007. // Get a string of all image map areas
  1008. function GetCSIMareas() {
  1009. if( !$this->iHasStroked ) {
  1010. $this->Stroke(_CSIM_SPECIALFILE);
  1011. }
  1012. $csim = $this->title->GetCSIMAreas();
  1013. $csim .= $this->subtitle->GetCSIMAreas();
  1014. $csim .= $this->subsubtitle->GetCSIMAreas();
  1015. $csim .= $this->legend->GetCSIMAreas();
  1016. if( $this->y2axis != NULL ) {
  1017. $csim .= $this->y2axis->title->GetCSIMAreas();
  1018. }
  1019. if( $this->texts != null ) {
  1020. $n = count($this->texts);
  1021. for($i=0; $i < $n; ++$i ) {
  1022. $csim .= $this->texts[$i]->GetCSIMAreas();
  1023. }
  1024. }
  1025. if( $this->y2texts != null && $this->y2scale != null ) {
  1026. $n = count($this->y2texts);
  1027. for($i=0; $i < $n; ++$i ) {
  1028. $csim .= $this->y2texts[$i]->GetCSIMAreas();
  1029. }
  1030. }
  1031. if( $this->yaxis != null && $this->xaxis != null ) {
  1032. $csim .= $this->yaxis->title->GetCSIMAreas();
  1033. $csim .= $this->xaxis->title->GetCSIMAreas();
  1034. }
  1035. $n = count($this->plots);
  1036. for( $i=0; $i < $n; ++$i ) {
  1037. $csim .= $this->plots[$i]->GetCSIMareas();
  1038. }
  1039. $n = count($this->y2plots);
  1040. for( $i=0; $i < $n; ++$i ) {
  1041. $csim .= $this->y2plots[$i]->GetCSIMareas();
  1042. }
  1043. $n = count($this->ynaxis);
  1044. for( $i=0; $i < $n; ++$i ) {
  1045. $m = count($this->ynplots[$i]);
  1046. for($j=0; $j < $m; ++$j ) {
  1047. $csim .= $this->ynplots[$i][$j]->GetCSIMareas();
  1048. }
  1049. }
  1050. $n = count($this->iTables);
  1051. for( $i=0; $i < $n; ++$i ) {
  1052. $csim .= $this->iTables[$i]->GetCSIMareas();
  1053. }
  1054. return $csim;
  1055. }
  1056. // Get a complete <MAP>..</MAP> tag for the final image map
  1057. function GetHTMLImageMap($aMapName) {
  1058. $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
  1059. $im .= $this->GetCSIMareas();
  1060. $im .= "</map>";
  1061. return $im;
  1062. }
  1063. function CheckCSIMCache($aCacheName,$aTimeOut=60) {
  1064. global $_SERVER;
  1065. if( $aCacheName=='auto' ) {
  1066. $aCacheName=basename($_SERVER['PHP_SELF']);
  1067. }
  1068. $urlarg = $this->GetURLArguments();
  1069. $this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg;
  1070. $this->csimcachetimeout = $aTimeOut;
  1071. // First determine if we need to check for a cached version
  1072. // This differs from the standard cache in the sense that the
  1073. // image and CSIM map HTML file is written relative to the directory
  1074. // the script executes in and not the specified cache directory.
  1075. // The reason for this is that the cache directory is not necessarily
  1076. // accessible from the HTTP server.
  1077. if( $this->csimcachename != '' ) {
  1078. $dir = dirname($this->csimcachename);
  1079. $base = basename($this->csimcachename);
  1080. $base = strtok($base,'.');
  1081. $suffix = strtok('.');
  1082. $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
  1083. $baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format;
  1084. $timedout=false;
  1085. // Does it exist at all ?
  1086. if( file_exists($basecsim) && file_exists($baseimg) ) {
  1087. // Check that it hasn't timed out
  1088. $diff=time()-filemtime($basecsim);
  1089. if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) {
  1090. $timedout=true;
  1091. @unlink($basecsim);
  1092. @unlink($baseimg);
  1093. }
  1094. else {
  1095. if ($fh = @fopen($basecsim, "r")) {
  1096. fpassthru($fh);
  1097. return true;
  1098. }
  1099. else {
  1100. JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading.");
  1101. }
  1102. }
  1103. }
  1104. }
  1105. return false;
  1106. }
  1107. // Build the argument string to be used with the csim images
  1108. static function GetURLArguments($aAddRecursiveBlocker=false) {
  1109. if( $aAddRecursiveBlocker ) {
  1110. // This is a JPGRAPH internal defined that prevents
  1111. // us from recursively coming here again
  1112. $urlarg = _CSIM_DISPLAY.'=1';
  1113. }
  1114. // Now reconstruct any user URL argument
  1115. reset($_GET);
  1116. while( list($key,$value) = each($_GET) ) {
  1117. if( is_array($value) ) {
  1118. foreach ( $value as $k => $v ) {
  1119. $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
  1120. }
  1121. }
  1122. else {
  1123. $urlarg .= '&amp;'.$key.'='.urlencode($value);
  1124. }
  1125. }
  1126. // It's not ideal to convert POST argument to GET arguments
  1127. // but there is little else we can do. One idea for the
  1128. // future might be recreate the POST header in case.
  1129. reset($_POST);
  1130. while( list($key,$value) = each($_POST) ) {
  1131. if( is_array($value) ) {
  1132. foreach ( $value as $k => $v ) {
  1133. $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
  1134. }
  1135. }
  1136. else {
  1137. $urlarg .= '&amp;'.$key.'='.urlencode($value);
  1138. }
  1139. }
  1140. return $urlarg;
  1141. }
  1142. function SetCSIMImgAlt($aAlt) {
  1143. $this->iCSIMImgAlt = $aAlt;
  1144. }
  1145. function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) {
  1146. if( $aCSIMName=='' ) {
  1147. // create a random map name
  1148. srand ((double) microtime() * 1000000);
  1149. $r = rand(0,100000);
  1150. $aCSIMName='__mapname'.$r.'__';
  1151. }
  1152. if( $aScriptName=='auto' ) {
  1153. $aScriptName=basename($_SERVER['PHP_SELF']);
  1154. }
  1155. $urlarg = $this->GetURLArguments(true);
  1156. if( empty($_GET[_CSIM_DISPLAY]) ) {
  1157. // First determine if we need to check for a cached version
  1158. // This differs from the standard cache in the sense that the
  1159. // image and CSIM map HTML file is written relative to the directory
  1160. // the script executes in and not the specified cache directory.
  1161. // The reason for this is that the cache directory is not necessarily
  1162. // accessible from the HTTP server.
  1163. if( $this->csimcachename != '' ) {
  1164. $dir = dirname($this->csimcachename);
  1165. $base = basename($this->csimcachename);
  1166. $base = strtok($base,'.');
  1167. $suffix = strtok('.');
  1168. $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
  1169. $baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format;
  1170. // Check that apache can write to directory specified
  1171. if( file_exists($dir) && !is_writeable($dir) ) {
  1172. JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.');
  1173. }
  1174. // Make sure directory exists
  1175. $this->cache->MakeDirs($dir);
  1176. // Write the image file
  1177. $this->Stroke(CSIMCACHE_DIR.$baseimg);
  1178. // Construct wrapper HTML and write to file and send it back to browser
  1179. // In the src URL we must replace the '?' with its encoding to prevent the arguments
  1180. // to be converted to real arguments.
  1181. $tmp = str_replace('?','%3f',$baseimg);
  1182. $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n".
  1183. '<img src="'.CSIMCACHE_HTTP_DIR.$tmp.'" ismap="ismap" usemap="#'.$aCSIMName.' width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
  1184. if($fh = @fopen($basecsim,'w') ) {
  1185. fwrite($fh,$htmlwrap);
  1186. fclose($fh);
  1187. echo $htmlwrap;
  1188. }
  1189. else {
  1190. JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions.");
  1191. }
  1192. }
  1193. else {
  1194. if( $aScriptName=='' ) {
  1195. 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().');
  1196. }
  1197. echo $this->GetHTMLImageMap($aCSIMName) . $this->GetCSIMImgHTML($aCSIMName, $aScriptName, $aBorder);
  1198. }
  1199. }
  1200. else {
  1201. $this->Stroke();
  1202. }
  1203. }
  1204. function StrokeCSIMImage() {
  1205. if( @$_GET[_CSIM_DISPLAY] == 1 ) {
  1206. $this->Stroke();
  1207. }
  1208. }
  1209. function GetCSIMImgHTML($aCSIMName, $aScriptName='auto', $aBorder=0 ) {
  1210. if( $aScriptName=='auto' ) {
  1211. $aScriptName=basename($_SERVER['PHP_SELF']);
  1212. }
  1213. $urlarg = $this->GetURLArguments(true);
  1214. return "<img src=\"".$aScriptName.'?'.$urlarg."\" ismap=\"ismap\" usemap=\"#".$aCSIMName.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
  1215. }
  1216. function GetTextsYMinMax($aY2=false) {
  1217. if( $aY2 ) {
  1218. $txts = $this->y2texts;
  1219. }
  1220. else {
  1221. $txts = $this->texts;
  1222. }
  1223. $n = count($txts);
  1224. $min=null;
  1225. $max=null;
  1226. for( $i=0; $i < $n; ++$i ) {
  1227. if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) {
  1228. if( $min === null ) {
  1229. $min = $max = $txts[$i]->iScalePosY ;
  1230. }
  1231. else {
  1232. $min = min($min,$txts[$i]->iScalePosY);
  1233. $max = max($max,$txts[$i]->iScalePosY);
  1234. }
  1235. }
  1236. }
  1237. if( $min !== null ) {
  1238. return array($min,$max);
  1239. }
  1240. else {
  1241. return null;
  1242. }
  1243. }
  1244. function GetTextsXMinMax($aY2=false) {
  1245. if( $aY2 ) {
  1246. $txts = $this->y2texts;
  1247. }
  1248. else {
  1249. $txts = $this->texts;
  1250. }
  1251. $n = count($txts);
  1252. $min=null;
  1253. $max=null;
  1254. for( $i=0; $i < $n; ++$i ) {
  1255. if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) {
  1256. if( $min === null ) {
  1257. $min = $max = $txts[$i]->iScalePosX ;
  1258. }
  1259. else {
  1260. $min = min($min,$txts[$i]->iScalePosX);
  1261. $max = max($max,$txts[$i]->iScalePosX);
  1262. }
  1263. }

Large files files are truncated, but you can click here to view the full file