1<?php 2 3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5/** 6 * Image_Graph - PEAR PHP OO Graph Rendering Utility. 7 * 8 * PHP version 5 9 * 10 * LICENSE: This library is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License as published by 12 * the Free Software Foundation; either version 2.1 of the License, or (at your 13 * option) any later version. This library is distributed in the hope that it 14 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 16 * General Public License for more details. You should have received a copy of 17 * the GNU Lesser General Public License along with this library; if not, write 18 * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19 * 02111-1307 USA 20 * 21 * @category Images 22 * @package Image_Graph 23 * @subpackage Plot 24 * @author Jesper Veggerby <pear.nosey@veggerby.dk> 25 * @author Stefan Neufeind <pear.neufeind@speedpartner.de> 26 * @copyright 2003-2009 The PHP Group 27 * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 28 * @version SVN: $Id: Plot.php 291755 2009-12-06 02:25:02Z neufeind $ 29 * @link http://pear.php.net/package/Image_Graph 30 */ 31 32/** 33 * Include file Image/Graph/Plotarea/Element.php 34 */ 35require_once 'Image/Graph/Plotarea/Element.php'; 36 37/** 38 * Framework for a chart 39 * 40 * @category Images 41 * @package Image_Graph 42 * @subpackage Plot 43 * @author Jesper Veggerby <pear.nosey@veggerby.dk> 44 * @author Stefan Neufeind <pear.neufeind@speedpartner.de> 45 * @copyright 2003-2009 The PHP Groupn 46 * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 47 * @version Release: 0.8.0 48 * @link http://pear.php.net/package/Image_Graph 49 * @abstract 50 */ 51class Image_Graph_Plot extends Image_Graph_Plotarea_Element 52{ 53 54 /** 55 * The dataset to plot 56 * @var Dataset 57 * @access private 58 */ 59 var $_dataset; 60 61 /** 62 * The marker to plot the data set as 63 * @var Marker 64 * @access private 65 */ 66 var $_marker = null; 67 68 /** 69 * The dataselector to use for data marking 70 * @var DataSelector 71 * @access private 72 */ 73 var $_dataSelector = null; 74 75 /** 76 * The Y axis to associate the plot with 77 * @var int 78 * @access private 79 */ 80 var $_axisY = IMAGE_GRAPH_AXIS_Y; 81 82 /** 83 * The type of the plot if multiple datasets are used 84 * @var string 85 * @access private 86 */ 87 var $_multiType = 'normal'; 88 89 /** 90 * The title of the plot, used for legending in case of simple plots 91 * @var string 92 * @access private 93 */ 94 var $_title = 'plot'; 95 96 /** 97 * PlotType [Constructor] 98 * 99 * Valid values for multiType are: 100 * 101 * 'normal' Plot is normal, multiple datasets are displayes next to one 102 * another 103 * 104 * 'stacked' Datasets are stacked on top of each other 105 * 106 * 'stacked100pct' Datasets are stacked and displayed as percentages of the 107 * total sum 108 * 109 * I no title is specified a default is used, which is basically the plot 110 * type (fx. for a 'Image_Graph_Plot_Smoothed_Area' default title is 111 * 'Smoothed Area') 112 * 113 * @param Image_Graph_Dataset &$dataset The data set (value containter) to 114 * plot or an array of datasets 115 * @param string $multiType The type of the plot 116 * @param string $title The title of the plot (used for legends, 117 * {@link Image_Graph_Legend}) 118 */ 119 function Image_Graph_Plot(& $dataset, $multiType = 'normal', $title = '') 120 { 121 if (!is_a($dataset, 'Image_Graph_Dataset')) { 122 if (is_array($dataset)) { 123 $keys = array_keys($dataset); 124 foreach ($keys as $key) { 125 if (!is_a($dataset[$key], 'Image_Graph_Dataset')) { 126 $this->_error('Invalid dataset passed to ' . get_class($this)); 127 } 128 } 129 unset($keys); 130 } else { 131 $this->_error('Invalid dataset passed to ' . get_class($this)); 132 } 133 } 134 135 parent::__construct(); 136 if ($dataset) { 137 if (is_array($dataset)) { 138 $this->_dataset =& $dataset; 139 } else { 140 $this->_dataset = array(&$dataset); 141 } 142 } 143 if ($title) { 144 $this->_title = $title; 145 } else { 146 $this->_title = str_replace('_', ' ', substr(get_class($this), 17)); 147 } 148 149 $multiType = strtolower($multiType); 150 if (($multiType == 'normal') 151 || ($multiType == 'stacked') 152 || ($multiType == 'stacked100pct') 153 ) { 154 $this->_multiType = $multiType; 155 } else { 156 $this->_error( 157 'Invalid multitype: ' . $multiType . 158 ' expected (normal|stacked|stacked100pct)' 159 ); 160 $this->_multiType = 'normal'; 161 } 162 } 163 164 /** 165 * Sets the title of the plot, used for legend 166 * 167 * @param string $title The title of the plot 168 * 169 * @return void 170 */ 171 function setTitle($title) 172 { 173 $this->_title = $title; 174 } 175 176 /** 177 * Parses the URL mapping data in the point and adds it to the parameter array used by 178 * Image_Canvas 179 * 180 * @param array $point The data point (from the dataset) 181 * @param array $canvasData The The for the canvas method 182 * 183 * @return array The union of the canvas data points and the appropriate points for the dataset 184 * @access private 185 */ 186 function _mergeData($point, $canvasData) 187 { 188 if (isset($point['data'])) { 189 if (isset($point['data']['url'])) { 190 $canvasData['url'] = $point['data']['url']; 191 } 192 if (isset($point['data']['target'])) { 193 $canvasData['target'] = $point['data']['target']; 194 } 195 if (isset($point['data']['alt'])) { 196 $canvasData['alt'] = $point['data']['alt']; 197 } 198 if (isset($point['data']['htmltags'])) { 199 $canvasData['htmltags'] = $point['data']['htmltags']; 200 } 201 } 202 203 return $canvasData; 204 } 205 206 /** 207 * Sets the Y axis to plot the data 208 * 209 * @param int $axisY The Y axis (either IMAGE_GRAPH_AXIS_Y / 'y' or 210 * IMAGE_GRAPH_AXIS_Y_SECONDARY / 'ysec' (defaults to IMAGE_GRAPH_AXIS_Y)) 211 * 212 * @return void 213 * @access private 214 */ 215 function _setAxisY($axisY) 216 { 217 if ($axisY == 'y') { 218 $this->_axisY = IMAGE_GRAPH_AXIS_Y; 219 } elseif ($axisY == 'ysec') { 220 $this->_axisY = IMAGE_GRAPH_AXIS_Y_SECONDARY; 221 } else { 222 $this->_axisY = $axisY; 223 } 224 } 225 226 /** 227 * Sets the marker to 'display' data points on the graph 228 * 229 * @param Marker &$marker The marker 230 * 231 * @return Marker 232 */ 233 function &setMarker(& $marker) 234 { 235 $this->add($marker); 236 $this->_marker =& $marker; 237 return $marker; 238 } 239 240 /** 241 * Sets the dataselector to specify which data should be displayed on the 242 * plot as markers and which are not 243 * 244 * @param DataSelector &$dataSelector The dataselector 245 * 246 * @return void 247 */ 248 function setDataSelector(& $dataSelector) 249 { 250 $this->_dataSelector =& $dataSelector; 251 } 252 253 /** 254 * Calculate marker point data 255 * 256 * @param array $point The point to calculate data for 257 * @param array $nextPoint The next point 258 * @param array $prevPoint The previous point 259 * @param array &$totals The pre-calculated totals, if needed 260 * 261 * @return array An array containing marker point data 262 * @access private 263 */ 264 function _getMarkerData($point, $nextPoint, $prevPoint, & $totals) 265 { 266 if (is_array($this->_dataset)) { 267 if ($this->_multiType == 'stacked') { 268 if (!isset($totals['SUM_Y'])) { 269 $totals['SUM_Y'] = array(); 270 } 271 $x = $point['X']; 272 if (!isset($totals['SUM_Y'][$x])) { 273 $totals['SUM_Y'][$x] = 0; 274 } 275 } elseif ($this->_multiType == 'stacked100pct') { 276 $x = $point['X']; 277 if ($totals['TOTAL_Y'][$x] != 0) { 278 if (!isset($totals['SUM_Y'])) { 279 $totals['SUM_Y'] = array(); 280 } 281 if (!isset($totals['SUM_Y'][$x])) { 282 $totals['SUM_Y'][$x] = 0; 283 } 284 } 285 } 286 287 if (isset($totals['ALL_SUM_Y'])) { 288 $point['SUM_Y'] = $totals['ALL_SUM_Y']; 289 } 290 291 if (!$prevPoint) { 292 $point['AX'] = -5; 293 $point['AY'] = 5; 294 $point['PPX'] = 0; 295 $point['PPY'] = 0; 296 $point['NPX'] = $nextPoint['X']; 297 $point['NPY'] = $nextPoint['Y']; 298 } elseif (!$nextPoint) { 299 $point['AX'] = 5; 300 $point['AY'] = 5; 301 $point['PPX'] = $prevPoint['X']; 302 $point['PPY'] = $prevPoint['Y']; 303 $point['NPX'] = 0; 304 $point['NPY'] = 0; 305 } else { 306 $point['AX'] = $this->_pointY($prevPoint) - $this->_pointY($nextPoint); 307 $point['AY'] = $this->_pointX($nextPoint) - $this->_pointX($prevPoint); 308 $point['PPX'] = $prevPoint['X']; 309 $point['PPY'] = $prevPoint['Y']; 310 $point['NPX'] = $nextPoint['X']; 311 $point['NPY'] = $nextPoint['Y']; 312 } 313 314 $point['APX'] = $point['X']; 315 $point['APY'] = $point['Y']; 316 317 if ((isset($totals['MINIMUM_X'])) && ($totals['MINIMUM_X'] != 0)) { 318 $point['PCT_MIN_X'] = 100 * $point['X'] / $totals['MINIMUM_X']; 319 } 320 if ((isset($totals['MAXIMUM_X'])) && ($totals['MAXIMUM_X'] != 0)) { 321 $point['PCT_MAX_X'] = 100 * $point['X'] / $totals['MAXIMUM_X']; 322 } 323 324 if ((isset($totals['MINIMUM_Y'])) && ($totals['MINIMUM_Y'] != 0)) { 325 $point['PCT_MIN_Y'] = 100 * $point['Y'] / $totals['MINIMUM_Y']; 326 } 327 if ((isset($totals['MAXIMUM_Y'])) && ($totals['MAXIMUM_Y'] != 0)) { 328 $point['PCT_MAX_Y'] = 100 * $point['Y'] / $totals['MAXIMUM_Y']; 329 } 330 331 $point['LENGTH'] = sqrt(($point['AX'] * $point['AX']) + ($point['AY'] * $point['AY'])); 332 333 if ((isset($point['LENGTH'])) && ($point['LENGTH'] != 0)) { 334 $point['ANGLE'] = asin($point['AY'] / $point['LENGTH']); 335 } 336 337 if ((isset($point['AX'])) && ($point['AX'] > 0)) { 338 $point['ANGLE'] = pi() - $point['ANGLE']; 339 } 340 341 if ($this->_parent->_horizontal) { 342 $point['MARKER_Y1'] = $this->_pointY($point) - 343 (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); 344 345 $point['MARKER_Y2'] = $this->_pointY($point) + 346 (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); 347 348 $point['COLUMN_WIDTH'] = abs(($point['MARKER_Y2'] - $point['MARKER_Y1']) / count($this->_dataset)); 349 350 $point['MARKER_Y'] = $point['MARKER_Y1'] + 351 ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * 352 $point['COLUMN_WIDTH']; 353 354 $point['MARKER_X'] = $this->_pointX($point); 355 356 if ($this->_multiType == 'stacked') { 357 $point['MARKER_Y'] = ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; 358 359 $P1 = array('Y' => $totals['SUM_Y'][$x]); 360 $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); 361 362 $point['MARKER_X'] = ($this->_pointX($P1) + $this->_pointX($P2)) / 2; 363 } elseif ($this->_multiType == 'stacked100pct') { 364 $x = $point['X']; 365 if ($totals['TOTAL_Y'][$x] != 0) { 366 $point['MARKER_Y'] = ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; 367 368 $P1 = array( 369 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] 370 ); 371 372 $P2 = array( 373 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] 374 ); 375 376 $point['MARKER_X'] = ($this->_pointX($P1) + $this->_pointX($P2)) / 2; 377 } else { 378 $point = false; 379 } 380 } 381 } else { 382 $point['MARKER_X1'] = $this->_pointX($point) - (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); 383 384 $point['MARKER_X2'] = $this->_pointX($point) + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); 385 386 $point['COLUMN_WIDTH'] = abs(($point['MARKER_X2'] - $point['MARKER_X1']) / count($this->_dataset)); 387 388 $point['MARKER_X'] = $point['MARKER_X1'] + ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * $point['COLUMN_WIDTH']; 389 390 $point['MARKER_Y'] = $this->_pointY($point); 391 392 if ($this->_multiType == 'stacked') { 393 $point['MARKER_X'] = ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; 394 395 $P1 = array('Y' => $totals['SUM_Y'][$x]); 396 $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); 397 398 $point['MARKER_Y'] = ($this->_pointY($P1) + $this->_pointY($P2)) / 2; 399 } elseif ($this->_multiType == 'stacked100pct') { 400 $x = $point['X']; 401 if ($totals['TOTAL_Y'][$x] != 0) { 402 $point['MARKER_X'] = ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; 403 404 $P1 = array( 405 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] 406 ); 407 408 $P2 = array( 409 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] 410 ); 411 412 $point['MARKER_Y'] = ($this->_pointY($P1) + $this->_pointY($P2)) / 2; 413 } else { 414 $point = false; 415 } 416 } 417 } 418 return $point; 419 } 420 } 421 422 /** 423 * Draws markers on the canvas 424 * 425 * @return void 426 * @access private 427 */ 428 function _drawMarker() 429 { 430 if (($this->_marker) && (is_array($this->_dataset))) { 431 $this->_canvas->startGroup(get_class($this) . '_marker'); 432 433 $totals = $this->_getTotals(); 434 $totals['WIDTH'] = $this->width() / ($this->_maximumX() + 2) / 2; 435 436 $number = 0; 437 $keys = array_keys($this->_dataset); 438 foreach ($keys as $key) { 439 $dataset =& $this->_dataset[$key]; 440 $totals['MINIMUM_X'] = $dataset->minimumX(); 441 $totals['MAXIMUM_X'] = $dataset->maximumX(); 442 $totals['MINIMUM_Y'] = $dataset->minimumY(); 443 $totals['MAXIMUM_Y'] = $dataset->maximumY(); 444 $totals['NUMBER'] = $number ++; 445 $dataset->_reset(); 446 while ($point = $dataset->_next()) { 447 $prevPoint = $dataset->_nearby(-2); 448 $nextPoint = $dataset->_nearby(); 449 450 $x = $point['X']; 451 $y = $point['Y']; 452 if (((!is_object($this->_dataSelector)) 453 || ($this->_dataSelector->_select($point))) && ($point['Y'] !== null) 454 ) { 455 456 $point = $this->_getMarkerData( 457 $point, 458 $nextPoint, 459 $prevPoint, 460 $totals 461 ); 462 463 if (is_array($point)) { 464 $this->_marker->_drawMarker( 465 $point['MARKER_X'], 466 $point['MARKER_Y'], 467 $point 468 ); 469 } 470 } 471 if (!isset($totals['SUM_Y'])) { 472 $totals['SUM_Y'] = array(); 473 } 474 if (isset($totals['SUM_Y'][$x])) { 475 $totals['SUM_Y'][$x] += $y; 476 } else { 477 $totals['SUM_Y'][$x] = $y; 478 } 479 } 480 } 481 unset($keys); 482 $this->_canvas->endGroup(); 483 } 484 } 485 486 /** 487 * Get the minimum X value from the dataset 488 * 489 * @return double The minimum X value 490 * @access private 491 */ 492 function _minimumX() 493 { 494 if (!is_array($this->_dataset)) { 495 return 0; 496 } 497 498 $min = false; 499 if (is_array($this->_dataset)) { 500 $keys = array_keys($this->_dataset); 501 foreach ($keys as $key) { 502 if ($min === false) { 503 $min = $this->_dataset[$key]->minimumX(); 504 } else { 505 $min = min($min, $this->_dataset[$key]->minimumX()); 506 } 507 } 508 unset($keys); 509 } 510 return $min; 511 } 512 513 /** 514 * Get the maximum X value from the dataset 515 * 516 * @return double The maximum X value 517 * @access private 518 */ 519 function _maximumX() 520 { 521 if (!is_array($this->_dataset)) { 522 return 0; 523 } 524 525 $max = 0; 526 if (is_array($this->_dataset)) { 527 $keys = array_keys($this->_dataset); 528 foreach ($keys as $key) { 529 $max = max($max, $this->_dataset[$key]->maximumX()); 530 } 531 unset($keys); 532 } 533 return $max; 534 } 535 536 /** 537 * Get the minimum Y value from the dataset 538 * 539 * @return double The minimum Y value 540 * @access private 541 */ 542 function _minimumY() 543 { 544 if (!is_array($this->_dataset)) { 545 return 0; 546 } 547 548 $min = false; 549 if (is_array($this->_dataset)) { 550 $keys = array_keys($this->_dataset); 551 foreach ($keys as $key) { 552 if ($this->_multiType == 'normal') { 553 if ($min === false) { 554 $min = $this->_dataset[$key]->minimumY(); 555 } else { 556 $min = min($min, $this->_dataset[$key]->minimumY()); 557 } 558 } else { 559 if ($min === false) { 560 $min = 0; 561 } 562 $dataset =& $this->_dataset[$key]; 563 $dataset->_reset(); 564 while ($point = $dataset->_next()) { 565 if ($point['Y'] < 0) { 566 $x = $point['X']; 567 if ((!isset($total)) || (!isset($total[$x]))) { 568 $total[$x] = $point['Y']; 569 } else { 570 $total[$x] += $point['Y']; 571 } 572 if (isset($min)) { 573 $min = min($min, $total[$x]); 574 } else { 575 $min = $total[$x]; 576 } 577 } 578 } 579 } 580 } 581 unset($keys); 582 } 583 return $min; 584 } 585 586 /** 587 * Get the maximum Y value from the dataset 588 * 589 * @return double The maximum Y value 590 * @access private 591 */ 592 function _maximumY() 593 { 594 if ($this->_multiType == 'stacked100pct') { 595 return 100; 596 } 597 598 $maxY = 0; 599 if (is_array($this->_dataset)) { 600 $keys = array_keys($this->_dataset); 601 foreach ($keys as $key) { 602 $dataset =& $this->_dataset[$key]; 603 604 if ($this->_multiType == 'normal') { 605 if (isset($maxY)) { 606 $maxY = max($maxY, $dataset->maximumY()); 607 } else { 608 $maxY = $dataset->maximumY(); 609 } 610 } else { 611 $dataset->_reset(); 612 while ($point = $dataset->_next()) { 613 if ($point['Y'] > 0) { 614 $x = $point['X']; 615 if ((!isset($total)) || (!isset($total[$x]))) { 616 $total[$x] = $point['Y']; 617 } else { 618 $total[$x] += $point['Y']; 619 } 620 if (isset($maxY)) { 621 $maxY = max($maxY, $total[$x]); 622 } else { 623 $maxY = $total[$x]; 624 } 625 } 626 } 627 } 628 } 629 unset($keys); 630 } 631 return $maxY; 632 } 633 634 /** 635 * Get the X pixel position represented by a value 636 * 637 * @param double $point The value to get the pixel-point for 638 * 639 * @return double The pixel position along the axis 640 * @access private 641 */ 642 function _pointX($point) 643 { 644 $point['AXIS_Y'] = $this->_axisY; 645 return parent::_pointX($point); 646 } 647 648 /** 649 * Get the Y pixel position represented by a value 650 * 651 * @param double $point the value to get the pixel-point for 652 * 653 * @return double The pixel position along the axis 654 * @access private 655 */ 656 function _pointY($point) 657 { 658 $point['AXIS_Y'] = $this->_axisY; 659 return parent::_pointY($point); 660 } 661 662 /** 663 * Update coordinates 664 * 665 * @return void 666 * @access private 667 */ 668 function _updateCoords() 669 { 670 $this->_setCoords($this->_parent->_plotLeft, $this->_parent->_plotTop, $this->_parent->_plotRight, $this->_parent->_plotBottom); 671 parent::_updateCoords(); 672 } 673 674 /** 675 * Get the dataset 676 * 677 * @return Image_Graph_Dataset The dataset(s) 678 */ 679 function &dataset() 680 { 681 return $this->_dataset; 682 } 683 684 /** 685 * Calulate totals 686 * 687 * @return array An associated array with the totals 688 * @access private 689 */ 690 function _getTotals() 691 { 692 $total = array( 693 'MINIMUM_X' => $this->_minimumX(), 694 'MAXIMUM_X' => $this->_maximumX(), 695 'MINIMUM_Y' => $this->_minimumY(), 696 'MAXIMUM_Y' => $this->_maximumY() 697 ); 698 $total['ALL_SUM_Y'] = 0; 699 700 $keys = array_keys($this->_dataset); 701 foreach ($keys as $key) { 702 $dataset =& $this->_dataset[$key]; 703 704 $dataset->_reset(); 705 while ($point = $dataset->_next()) { 706 $x = $point['X']; 707 708 if (is_numeric($point['Y'])) { 709 $total['ALL_SUM_Y'] += $point['Y']; 710 if (isset($total['TOTAL_Y'][$x])) { 711 $total['TOTAL_Y'][$x] += $point['Y']; 712 } else { 713 $total['TOTAL_Y'][$x] = $point['Y']; 714 } 715 } 716 717 if (is_numeric($point['X'])) { 718 if (isset($total['TOTAL_X'][$x])) { 719 $total['TOTAL_X'][$x] += $point['X']; 720 } else { 721 $total['TOTAL_X'][$x] = $point['X']; 722 } 723 } 724 } 725 } 726 unset($keys); 727 return $total; 728 } 729 730 /** 731 * Perform the actual drawing on the legend. 732 * 733 * @param int $x0 The top-left x-coordinate 734 * @param int $y0 The top-left y-coordinate 735 * @param int $x1 The bottom-right x-coordinate 736 * @param int $y1 The bottom-right y-coordinate 737 * 738 * @return void 739 * @access private 740 */ 741 function _drawLegendSample($x0, $y0, $x1, $y1) 742 { 743 $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); 744 } 745 746 /** 747 * Draw a sample for use with legend 748 * 749 * @param array &$param The parameters for the legend 750 * 751 * @return void 752 * @access private 753 */ 754 function _legendSample(&$param) 755 { 756 if (!is_array($this->_dataset)) { 757 return false; 758 } 759 760 if (is_a($this->_fillStyle, 'Image_Graph_Fill')) { 761 $this->_fillStyle->_reset(); 762 } 763 764 $count = 0; 765 $keys = array_keys($this->_dataset); 766 foreach ($keys as $key) { 767 $dataset =& $this->_dataset[$key]; 768 $count++; 769 770 $caption = ($dataset->_name ? $dataset->_name : $this->_title); 771 772 $this->_canvas->setFont($param['font']); 773 $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); 774 $param['maxwidth'] = max($param['maxwidth'], $width); 775 $x2 = $param['x'] + $width; 776 $y2 = $param['y'] + $param['height'] + 5; 777 778 if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { 779 $param['y'] = $param['top']; 780 $param['x'] = $x2; 781 $y2 = $param['y'] + $param['height']; 782 } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { 783 $param['x'] = $param['left']; 784 $param['y'] = $y2; 785 $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); 786 } 787 788 $x = $x0 = $param['x']; 789 $y = $param['y']; 790 $y0 = $param['y']; 791 $x1 = $param['x'] + $param['width']; 792 $y1 = $param['y'] + $param['height']; 793 794 if (!isset($param['simulate'])) { 795 $this->_getFillStyle($key); 796 $this->_getLineStyle(); 797 $this->_drawLegendSample($x0, $y0, $x1, $y1); 798 799 if (($this->_marker) && ($dataset) && ($param['show_marker'])) { 800 $dataset->_reset(); 801 $point = $dataset->_next(); 802 $prevPoint = $dataset->_nearby(-2); 803 $nextPoint = $dataset->_nearby(); 804 805 $tmp = array(); 806 $point = $this->_getMarkerData($point, $nextPoint, $prevPoint, $tmp); 807 if (is_array($point)) { 808 $point['MARKER_X'] = $x+$param['width']/2; 809 $point['MARKER_Y'] = $y; 810 unset ($point['AVERAGE_Y']); 811 $this->_marker->_drawMarker($point['MARKER_X'], $point['MARKER_Y'], $point); 812 } 813 } 814 $this->write($x + $param['width'] + 10, $y + $param['height'] / 2, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); 815 } 816 817 if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { 818 $param['y'] = $y2; 819 } else { 820 $param['x'] = $x2; 821 } 822 } 823 unset($keys); 824 } 825 826} 827 828?> 829