| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * File containing the ezcGraphFlashDriver class 4 * 5 * @package Graph 6 * @version 1.5 7 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. 8 * @license http://ez.no/licenses/new_bsd New BSD License 9 */ 10 /** 11 * Driver to create Flash4 (SWF) files as graph output. The options of this 12 * class are defined in The options of this class are defined in the option 13 * class {@link ezcGraphFlashDriverOptions} extending the basic 14 * {@link ezcGraphDriverOptions}. 15 * 16 * <code> 17 * $graph = new ezcGraphPieChart(); 18 * $graph->title = 'Access statistics'; 19 * $graph->legend = false; 20 * 21 * $graph->driver = new ezcGraphFlashDriver(); 22 * $graph->options->font = 'tutorial_font.fdb'; 23 * 24 * $graph->driver->options->compression = 7; 25 * 26 * $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array( 27 * 'Mozilla' => 19113, 28 * 'Explorer' => 10917, 29 * 'Opera' => 1464, 30 * 'Safari' => 652, 31 * 'Konqueror' => 474, 32 * ) ); 33 * 34 * $graph->render( 400, 200, 'tutorial_driver_flash.swf' ); 35 * </code> 36 * 37 * 38 * @version 1.5 39 * @package Graph 40 * @mainclass 41 */ 42 class ezcGraphFlashDriver extends ezcGraphDriver 43 { 44 /** 45 * Flash movie 46 * 47 * @var SWFMovie 48 */ 49 protected $movie; 50 51 /** 52 * Unique element id 53 * 54 * @var int 55 */ 56 protected $id = 1; 57 58 /** 59 * Array with strings to draw later 60 * 61 * @var array 62 */ 63 protected $strings = array(); 64 65 /** 66 * Constructor 67 * 68 * @param array $options Default option array 69 * @return void 70 * @ignore 71 */ 72 public function __construct( array $options = array() ) 73 { 74 ezcBase::checkDependency( 'Graph', ezcBase::DEP_PHP_EXTENSION, 'ming' ); 75 $this->options = new ezcGraphFlashDriverOptions( $options ); 76 } 77 78 /** 79 * Returns unique movie object as a parent canvas for all swf objects. 80 * 81 * @return SWFMovie 82 */ 83 public function getDocument() 84 { 85 if ( $this->movie === null ) 86 { 87 ming_setscale( 1.0 ); 88 $this->movie = new SWFMovie(); 89 $this->movie->setDimension( $this->modifyCoordinate( $this->options->width ), $this->modifyCoordinate( $this->options->height ) ); 90 $this->movie->setRate( 1 ); 91 $this->movie->setBackground( 255, 255, 255 ); 92 } 93 94 return $this->movie; 95 } 96 97 /** 98 * Set the fill and line properties for a SWWFShape according to the 99 * given parameters. 100 * 101 * @param SWFShape $shape 102 * @param ezcGraphColor $color 103 * @param mixed $thickness 104 * @param mixed $filled 105 * @return void 106 */ 107 protected function setShapeColor( SWFShape $shape, ezcGraphColor $color, $thickness, $filled ) 108 { 109 if ( $filled ) 110 { 111 switch ( true ) 112 { 113 case ( $color instanceof ezcGraphLinearGradient ): 114 $gradient = new SWFGradient(); 115 $gradient->addEntry( 116 0, 117 $color->startColor->red, 118 $color->startColor->green, 119 $color->startColor->blue, 120 255 - $color->startColor->alpha 121 ); 122 $gradient->addEntry( 123 1, 124 $color->endColor->red, 125 $color->endColor->green, 126 $color->endColor->blue, 127 255 - $color->endColor->alpha 128 ); 129 130 $fill = $shape->addFill( $gradient, SWFFILL_LINEAR_GRADIENT ); 131 132 // Calculate desired length of gradient 133 $length = sqrt( 134 pow( $color->endPoint->x - $color->startPoint->x, 2 ) + 135 pow( $color->endPoint->y - $color->startPoint->y, 2 ) 136 ); 137 138 $fill->scaleTo( $this->modifyCoordinate( $length ) / 32768 , $this->modifyCoordinate( $length ) / 32768 ); 139 $fill->rotateTo( 140 rad2deg( asin( 141 ( $color->endPoint->x - $color->startPoint->x ) / $length 142 ) + 180 ) 143 ); 144 $fill->moveTo( 145 $this->modifyCoordinate( 146 ( $color->startPoint->x + $color->endPoint->x ) / 2 147 ), 148 $this->modifyCoordinate( 149 ( $color->startPoint->y + $color->endPoint->y ) / 2 150 ) 151 ); 152 153 $shape->setLeftFill( $fill ); 154 break; 155 case ( $color instanceof ezcGraphRadialGradient ): 156 $gradient = new SWFGradient(); 157 $gradient->addEntry( 158 0, 159 $color->startColor->red, 160 $color->startColor->green, 161 $color->startColor->blue, 162 255 - $color->startColor->alpha 163 ); 164 $gradient->addEntry( 165 1, 166 $color->endColor->red, 167 $color->endColor->green, 168 $color->endColor->blue, 169 255 - $color->endColor->alpha 170 ); 171 172 $fill = $shape->addFill( $gradient, SWFFILL_RADIAL_GRADIENT ); 173 174 $fill->scaleTo( $this->modifyCoordinate( $color->width ) / 32768, $this->modifyCoordinate( $color->height ) / 32768 ); 175 $fill->moveTo( $this->modifyCoordinate( $color->center->x ), $this->modifyCoordinate( $color->center->y ) ); 176 177 $shape->setLeftFill( $fill ); 178 break; 179 default: 180 $fill = $shape->addFill( $color->red, $color->green, $color->blue, 255 - $color->alpha ); 181 $shape->setLeftFill( $fill ); 182 break; 183 } 184 } 185 else 186 { 187 $shape->setLine( $this->modifyCoordinate( $thickness ), $color->red, $color->green, $color->blue, 255 - $color->alpha ); 188 } 189 } 190 191 /** 192 * Modifies a coordinate value, as flash usally uses twips instead of 193 * pixels for a higher solution, as it only accepts integer values. 194 * 195 * @param float $pointValue 196 * @return float 197 */ 198 protected function modifyCoordinate( $pointValue ) 199 { 200 return $pointValue * 10; 201 } 202 203 /** 204 * Demodifies a coordinate value, as flash usally uses twips instead of 205 * pixels for a higher solution, as it only accepts integer values. 206 * 207 * @param float $pointValue 208 * @return float 209 */ 210 protected function deModifyCoordinate( $pointValue ) 211 { 212 return $pointValue / 10; 213 } 214 215 /** 216 * Draws a single polygon. 217 * 218 * @param array $points Point array 219 * @param ezcGraphColor $color Polygon color 220 * @param mixed $filled Filled 221 * @param float $thickness Line thickness 222 * @return void 223 */ 224 public function drawPolygon( array $points, ezcGraphColor $color, $filled = true, $thickness = 1. ) 225 { 226 $movie = $this->getDocument(); 227 228 if ( !$filled ) 229 { 230 // The middle of the border is on the outline of a polygon in ming, 231 // fix that: 232 try 233 { 234 $points = $this->reducePolygonSize( $points, $thickness / 2 ); 235 } 236 catch ( ezcGraphReducementFailedException $e ) 237 { 238 return false; 239 } 240 } 241 242 $shape = new SWFShape(); 243 244 $this->setShapeColor( $shape, $color, $thickness, $filled ); 245 246 $lastPoint = end( $points ); 247 $shape->movePenTo( $this->modifyCoordinate( $lastPoint->x ), $this->modifyCoordinate( $lastPoint->y ) ); 248 249 foreach ( $points as $point ) 250 { 251 $shape->drawLineTo( $this->modifyCoordinate( $point->x ), $this->modifyCoordinate( $point->y ) ); 252 } 253 254 $object = $movie->add( $shape ); 255 $object->setName( $id = 'ezcGraphPolygon_' . $this->id++ ); 256 257 return $id; 258 } 259 260 /** 261 * Draws a line 262 * 263 * @param ezcGraphCoordinate $start Start point 264 * @param ezcGraphCoordinate $end End point 265 * @param ezcGraphColor $color Line color 266 * @param float $thickness Line thickness 267 * @return void 268 */ 269 public function drawLine( ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphColor $color, $thickness = 1. ) 270 { 271 $movie = $this->getDocument(); 272 273 $shape = new SWFShape(); 274 275 $this->setShapeColor( $shape, $color, $thickness, false ); 276 277 $shape->movePenTo( $this->modifyCoordinate( $start->x ), $this->modifyCoordinate( $start->y ) ); 278 $shape->drawLineTo( $this->modifyCoordinate( $end->x ), $this->modifyCoordinate( $end->y ) ); 279 280 $object = $movie->add( $shape ); 281 $object->setName( $id = 'ezcGraphLine_' . $this->id++ ); 282 283 return $id; 284 } 285 286 /** 287 * Returns boundings of text depending on the available font extension 288 * 289 * @param float $size Textsize 290 * @param ezcGraphFontOptions $font Font 291 * @param string $text Text 292 * @return ezcGraphBoundings Boundings of text 293 */ 294 protected function getTextBoundings( $size, ezcGraphFontOptions $font, $text ) 295 { 296 $t = new SWFText(); 297 $t->setFont( new SWFFont( $font->path ) ); 298 $t->setHeight( $size ); 299 300 $boundings = new ezcGraphBoundings( 0, 0, $t->getWidth( $text ), $size ); 301 302 return $boundings; 303 } 304 305 /** 306 * Writes text in a box of desired size 307 * 308 * @param string $string Text 309 * @param ezcGraphCoordinate $position Top left position 310 * @param float $width Width of text box 311 * @param float $height Height of text box 312 * @param int $align Alignement of text 313 * @param ezcGraphRotation $rotation 314 * @return void 315 */ 316 public function drawTextBox( $string, ezcGraphCoordinate $position, $width, $height, $align, ezcGraphRotation $rotation = null ) 317 { 318 $padding = $this->options->font->padding + ( $this->options->font->border !== false ? $this->options->font->borderWidth : 0 ); 319 320 $width = $this->modifyCoordinate( $width - $padding * 2 ); 321 $height = $this->modifyCoordinate( $height - $padding * 2 ); 322 $position = new ezcGraphCoordinate( 323 $this->modifyCoordinate( $position->x + $padding ), 324 $this->modifyCoordinate( $position->y + $padding ) 325 ); 326 327 // Try to get a font size for the text to fit into the box 328 $maxSize = $this->modifyCoordinate( min( $height, $this->options->font->maxFontSize ) ); 329 $minSize = $this->modifyCoordinate( $this->options->font->minFontSize ); 330 $result = false; 331 for ( $size = $maxSize; $size >= $minSize; ) 332 { 333 $result = $this->testFitStringInTextBox( $string, $position, $width, $height, $size ); 334 if ( is_array( $result ) ) 335 { 336 break; 337 } 338 $size = $this->deModifyCoordinate( $size ); 339 $size = $this->modifyCoordinate( floor( ( $newsize = $size * ( $result ) ) >= $size ? $size - 1 : $newsize ) ); 340 } 341 342 if ( !is_array( $result ) ) 343 { 344 if ( ( $height >= $this->options->font->minFontSize ) && 345 ( $this->options->autoShortenString ) ) 346 { 347 $result = $this->tryFitShortenedString( $string, $position, $width, $height, $size = $this->modifyCoordinate( $this->options->font->minFontSize ) ); 348 } 349 else 350 { 351 throw new ezcGraphFontRenderingException( $string, $this->options->font->minFontSize, $width, $height ); 352 } 353 } 354 355 356 $this->options->font->minimalUsedFont = $this->deModifyCoordinate( $size ); 357 358 $this->strings[] = array( 359 'text' => $result, 360 'id' => $id = 'ezcGraphTextBox_' . $this->id++, 361 'position' => $position, 362 'width' => $width, 363 'height' => $height, 364 'align' => $align, 365 'font' => $this->options->font, 366 'rotation' => $rotation, 367 ); 368 369 return $id; 370 } 371 372 /** 373 * Render text depending of font type and available font extensions 374 * 375 * @param string $id 376 * @param string $text 377 * @param string $chars 378 * @param int $type 379 * @param string $path 380 * @param ezcGraphColor $color 381 * @param ezcGraphCoordinate $position 382 * @param float $size 383 * @param float $rotation 384 * @return void 385 */ 386 protected function renderText( $id, $text, $chars, $type, $path, ezcGraphColor $color, ezcGraphCoordinate $position, $size, $rotation = null ) 387 { 388 $movie = $this->getDocument(); 389 390 $tb = new SWFTextField( SWFTEXTFIELD_NOEDIT ); 391 $tb->setFont( new SWFFont( $path ) ); 392 $tb->setHeight( $size ); 393 $tb->setColor( $color->red, $color->green, $color->blue, 255 - $color->alpha ); 394 $tb->addString( $text ); 395 $tb->addChars( $chars ); 396 397 $object = $movie->add( $tb ); 398 $object->rotate( 399 ( $rotation !== null ? -$rotation->getRotation() : 0 ) 400 ); 401 $object->moveTo( 402 $position->x + 403 ( $rotation === null ? 0 : $this->modifyCoordinate( $rotation->get( 0, 2 ) ) ), 404 $position->y - 405 $size * ( 1 + $this->options->lineSpacing ) + 406 ( $rotation === null ? 0 : $this->modifyCoordinate( $rotation->get( 1, 2 ) ) ) 407 ); 408 $object->setName( $id ); 409 } 410 411 /** 412 * Draw all collected texts 413 * 414 * The texts are collected and their maximum possible font size is 415 * calculated. This function finally draws the texts on the image, this 416 * delayed drawing has two reasons: 417 * 418 * 1) This way the text strings are always on top of the image, what 419 * results in better readable texts 420 * 2) The maximum possible font size can be calculated for a set of texts 421 * with the same font configuration. Strings belonging to one chart 422 * element normally have the same font configuration, so that all texts 423 * belonging to one element will have the same font size. 424 * 425 * @access protected 426 * @return void 427 */ 428 protected function drawAllTexts() 429 { 430 // Iterate over all strings to collect used chars per font 431 $chars = array(); 432 foreach ( $this->strings as $text ) 433 { 434 $completeString = ''; 435 foreach ( $text['text'] as $line ) 436 { 437 $completeString .= implode( ' ', $line ); 438 } 439 440 // Collect chars for each font 441 if ( !isset( $chars[$text['font']->path] ) ) 442 { 443 $chars[$text['font']->path] = $completeString; 444 } 445 else 446 { 447 $chars[$text['font']->path] .= $completeString; 448 } 449 } 450 451 foreach ( $this->strings as $text ) 452 { 453 $size = $this->modifyCoordinate( $text['font']->minimalUsedFont ); 454 455 $completeHeight = count( $text['text'] ) * $size + ( count( $text['text'] ) - 1 ) * $this->options->lineSpacing; 456 457 // Calculate y offset for vertical alignement 458 switch ( true ) 459 { 460 case ( $text['align'] & ezcGraph::BOTTOM ): 461 $yOffset = $text['height'] - $completeHeight; 462 break; 463 case ( $text['align'] & ezcGraph::MIDDLE ): 464 $yOffset = ( $text['height'] - $completeHeight ) / 2; 465 break; 466 case ( $text['align'] & ezcGraph::TOP ): 467 default: 468 $yOffset = 0; 469 break; 470 } 471 472 $padding = $text['font']->padding + $text['font']->borderWidth / 2; 473 if ( $this->options->font->minimizeBorder === true ) 474 { 475 // Calculate maximum width of text rows 476 $width = false; 477 foreach ( $text['text'] as $line ) 478 { 479 $string = implode( ' ', $line ); 480 $boundings = $this->getTextBoundings( $size, $text['font'], $string ); 481 if ( ( $width === false) || ( $boundings->width > $width ) ) 482 { 483 $width = $boundings->width; 484 } 485 } 486 487 switch ( true ) 488 { 489 case ( $text['align'] & ezcGraph::LEFT ): 490 $xOffset = 0; 491 break; 492 case ( $text['align'] & ezcGraph::CENTER ): 493 $xOffset = ( $text['width'] - $width ) / 2; 494 break; 495 case ( $text['align'] & ezcGraph::RIGHT ): 496 $xOffset = $text['width'] - $width; 497 break; 498 } 499 500 $borderPolygonArray = array( 501 new ezcGraphCoordinate( 502 $this->deModifyCoordinate( $text['position']->x - $padding + $xOffset ), 503 $this->deModifyCoordinate( $text['position']->y - $padding + $yOffset ) 504 ), 505 new ezcGraphCoordinate( 506 $this->deModifyCoordinate( $text['position']->x + $padding * 2 + $xOffset + $width ), 507 $this->deModifyCoordinate( $text['position']->y - $padding + $yOffset ) 508 ), 509 new ezcGraphCoordinate( 510 $this->deModifyCoordinate( $text['position']->x + $padding * 2 + $xOffset + $width ), 511 $this->deModifyCoordinate( $text['position']->y + $padding * 2 + $yOffset + $completeHeight ) 512 ), 513 new ezcGraphCoordinate( 514 $this->deModifyCoordinate( $text['position']->x - $padding + $xOffset ), 515 $this->deModifyCoordinate( $text['position']->y + $padding * 2 + $yOffset + $completeHeight ) 516 ), 517 ); 518 } 519 else 520 { 521 $borderPolygonArray = array( 522 new ezcGraphCoordinate( 523 $this->deModifyCoordinate( $text['position']->x - $padding ), 524 $this->deModifyCoordinate( $text['position']->y - $padding ) 525 ), 526 new ezcGraphCoordinate( 527 $this->deModifyCoordinate( $text['position']->x + $padding * 2 + $text['width'] ), 528 $this->deModifyCoordinate( $text['position']->y - $padding ) 529 ), 530 new ezcGraphCoordinate( 531 $this->deModifyCoordinate( $text['position']->x + $padding * 2 + $text['width'] ), 532 $this->deModifyCoordinate( $text['position']->y + $padding * 2 + $text['height'] ) 533 ), 534 new ezcGraphCoordinate( 535 $this->deModifyCoordinate( $text['position']->x - $padding ), 536 $this->deModifyCoordinate( $text['position']->y + $padding * 2 + $text['height'] ) 537 ), 538 ); 539 } 540 541 if ( $text['rotation'] !== null ) 542 { 543 foreach ( $borderPolygonArray as $nr => $point ) 544 { 545 $borderPolygonArray[$nr] = $text['rotation']->transformCoordinate( $point ); 546 } 547 } 548 549 if ( $text['font']->background !== false ) 550 { 551 $this->drawPolygon( 552 $borderPolygonArray, 553 $text['font']->background, 554 true 555 ); 556 } 557 558 if ( $text['font']->border !== false ) 559 { 560 $this->drawPolygon( 561 $borderPolygonArray, 562 $text['font']->border, 563 false, 564 $text['font']->borderWidth 565 ); 566 } 567 568 // Render text with evaluated font size 569 $completeString = ''; 570 foreach ( $text['text'] as $line ) 571 { 572 $string = implode( ' ', $line ); 573 $completeString .= $string; 574 $boundings = $this->getTextBoundings( $size, $text['font'], $string ); 575 $text['position']->y += $size; 576 577 switch ( true ) 578 { 579 case ( $text['align'] & ezcGraph::LEFT ): 580 $position = new ezcGraphCoordinate( 581 $text['position']->x, 582 $text['position']->y + $yOffset 583 ); 584 break; 585 case ( $text['align'] & ezcGraph::RIGHT ): 586 $position = new ezcGraphCoordinate( 587 $text['position']->x + ( $text['width'] - $boundings->width ), 588 $text['position']->y + $yOffset 589 ); 590 break; 591 case ( $text['align'] & ezcGraph::CENTER ): 592 $position = new ezcGraphCoordinate( 593 $text['position']->x + ( ( $text['width'] - $boundings->width ) / 2 ), 594 $text['position']->y + $yOffset 595 ); 596 break; 597 } 598 599 // Optionally draw text shadow 600 if ( $text['font']->textShadow === true ) 601 { 602 $this->renderText( 603 $text['id'], 604 $string, 605 $chars[$text['font']->path], 606 $text['font']->type, 607 $text['font']->path, 608 $text['font']->textShadowColor, 609 new ezcGraphCoordinate( 610 $position->x + $this->modifyCoordinate( $text['font']->textShadowOffset ), 611 $position->y + $this->modifyCoordinate( $text['font']->textShadowOffset ) 612 ), 613 $size, 614 $text['rotation'] 615 ); 616 } 617 618 // Finally draw text 619 $this->renderText( 620 $text['id'], 621 $string, 622 $chars[$text['font']->path], 623 $text['font']->type, 624 $text['font']->path, 625 $text['font']->color, 626 $position, 627 $size, 628 $text['rotation'] 629 ); 630 631 $text['position']->y += $size * $this->options->lineSpacing; 632 } 633 } 634 } 635 636 /** 637 * Draws a sector of cirlce 638 * 639 * @param ezcGraphCoordinate $center Center of circle 640 * @param mixed $width Width 641 * @param mixed $height Height 642 * @param mixed $startAngle Start angle of circle sector 643 * @param mixed $endAngle End angle of circle sector 644 * @param ezcGraphColor $color Color 645 * @param mixed $filled Filled 646 * @return void 647 */ 648 public function drawCircleSector( ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, ezcGraphColor $color, $filled = true ) 649 { 650 if ( $startAngle > $endAngle ) 651 { 652 $tmp = $startAngle; 653 $startAngle = $endAngle; 654 $endAngle = $tmp; 655 } 656 657 $movie = $this->getDocument(); 658 659 $shape = new SWFShape(); 660 $this->setShapeColor( $shape, $color, 1, $filled ); 661 662 if ( !$filled ) 663 { 664 try 665 { 666 $reduced = $this->reduceEllipseSize( $center, $width, $height, $startAngle, $endAngle, .5 ); 667 } 668 catch ( ezcGraphReducementFailedException $e ) 669 { 670 return false; 671 } 672 673 $startAngle = $reduced['startAngle']; 674 $endAngle = $reduced['endAngle']; 675 676 $width -= 1; 677 $height -= 1; 678 } 679 680 $shape->movePenTo( $this->modifyCoordinate( $center->x ), $this->modifyCoordinate( $center->y ) ); 681 682 // @TODO: User SWFShape::curveTo 683 for( 684 $angle = $startAngle; 685 $angle <= $endAngle; 686 $angle = min( $angle + $this->options->circleResolution, $endAngle ) ) 687 { 688 $shape->drawLineTo( 689 $this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ), 690 $this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 ) 691 ); 692 693 if ( $angle === $endAngle ) 694 { 695 break; 696 } 697 } 698 699 $shape->drawLineTo( 700 $this->modifyCoordinate( $center->x ), 701 $this->modifyCoordinate( $center->y ) 702 ); 703 704 $object = $movie->add( $shape ); 705 $object->setName( $id = 'ezcGraphCircleSector_' . $this->id++ ); 706 707 return $id; 708 } 709 710 /** 711 * Draws a circular arc consisting of several minor steps on the bounding 712 * lines. 713 * 714 * @param ezcGraphCoordinate $center 715 * @param mixed $width 716 * @param mixed $height 717 * @param mixed $size 718 * @param mixed $startAngle 719 * @param mixed $endAngle 720 * @param ezcGraphColor $color 721 * @param bool $filled 722 * @return string Element id 723 */ 724 protected function simulateCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled ) 725 { 726 $movie = $this->getDocument(); 727 $id = 'ezcGraphCircularArc_' . $this->id++; 728 729 for ( 730 $tmpAngle = min( ceil ( $startAngle / 180 ) * 180, $endAngle ); 731 $tmpAngle <= $endAngle; 732 $tmpAngle = min( ceil ( $startAngle / 180 + 1 ) * 180, $endAngle ) ) 733 { 734 $shape = new SWFShape(); 735 $this->setShapeColor( $shape, $color, 1, $filled ); 736 737 $shape->movePenTo( 738 $this->modifyCoordinate( $center->x + cos( deg2rad( $startAngle ) ) * $width / 2 ), 739 $this->modifyCoordinate( $center->y + sin( deg2rad( $startAngle ) ) * $height / 2 ) 740 ); 741 742 // @TODO: Use SWFShape::curveTo 743 for( 744 $angle = $startAngle; 745 $angle <= $tmpAngle; 746 $angle = min( $angle + $this->options->circleResolution, $tmpAngle ) ) 747 { 748 $shape->drawLineTo( 749 $this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ), 750 $this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 + $size ) 751 ); 752 753 if ( $angle === $tmpAngle ) 754 { 755 break; 756 } 757 } 758 759 for( 760 $angle = $tmpAngle; 761 $angle >= $startAngle; 762 $angle = max( $angle - $this->options->circleResolution, $startAngle ) ) 763 { 764 $shape->drawLineTo( 765 $this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ), 766 $this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 ) 767 ); 768 769 if ( $angle === $startAngle ) 770 { 771 break; 772 } 773 } 774 775 $object = $movie->add( $shape ); 776 $object->setName( $id ); 777 778 $startAngle = $tmpAngle; 779 if ( $tmpAngle === $endAngle ) 780 { 781 break; 782 } 783 } 784 785 return $id; 786 } 787 788 /** 789 * Draws a circular arc 790 * 791 * @param ezcGraphCoordinate $center Center of ellipse 792 * @param integer $width Width of ellipse 793 * @param integer $height Height of ellipse 794 * @param integer $size Height of border 795 * @param float $startAngle Starting angle of circle sector 796 * @param float $endAngle Ending angle of circle sector 797 * @param ezcGraphColor $color Color of Border 798 * @param bool $filled 799 * @return void 800 */ 801 public function drawCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled = true ) 802 { 803 if ( $startAngle > $endAngle ) 804 { 805 $tmp = $startAngle; 806 $startAngle = $endAngle; 807 $endAngle = $tmp; 808 } 809 810 $id = $this->simulateCircularArc( $center, $width, $height, $size, $startAngle, $endAngle, $color, $filled ); 811 812 if ( ( $this->options->shadeCircularArc !== false ) && 813 $filled ) 814 { 815 $gradient = new ezcGraphLinearGradient( 816 new ezcGraphCoordinate( 817 $center->x - $width, 818 $center->y 819 ), 820 new ezcGraphCoordinate( 821 $center->x + $width, 822 $center->y 823 ), 824 ezcGraphColor::fromHex( '#FFFFFF' )->transparent( $this->options->shadeCircularArc * 1.5 ), 825 ezcGraphColor::fromHex( '#000000' )->transparent( $this->options->shadeCircularArc * 1.5 ) 826 ); 827 828 $this->simulateCircularArc( $center, $width, $height, $size, $startAngle, $endAngle, $gradient, $filled ); 829 } 830 831 return $id; 832 } 833 834 /** 835 * Draw circle 836 * 837 * @param ezcGraphCoordinate $center Center of ellipse 838 * @param mixed $width Width of ellipse 839 * @param mixed $height height of ellipse 840 * @param ezcGraphColor $color Color 841 * @param mixed $filled Filled 842 * @return void 843 */ 844 public function drawCircle( ezcGraphCoordinate $center, $width, $height, ezcGraphColor $color, $filled = true ) 845 { 846 $movie = $this->getDocument(); 847 848 $shape = new SWFShape(); 849 $this->setShapeColor( $shape, $color, 1, $filled ); 850 851 // Reduce size 852 if ( !$filled ) 853 { 854 $width -= 1; 855 $height -= 1; 856 } 857 858 $shape->movePenTo( 859 $this->modifyCoordinate( $center->x + $width / 2 ), 860 $this->modifyCoordinate( $center->y ) 861 ); 862 863 // @TODO: User SWFShape::curveTo 864 for ( $angle = $this->options->circleResolution; $angle < 360; $angle += $this->options->circleResolution ) 865 { 866 $shape->drawLineTo( 867 $this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ), 868 $this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 ) 869 ); 870 } 871 872 $shape->drawLineTo( 873 $this->modifyCoordinate( $center->x + $width / 2 ), 874 $this->modifyCoordinate( $center->y ) 875 ); 876 877 $object = $movie->add( $shape ); 878 $object->setName( $id = 'ezcGraphCircle_' . $this->id++ ); 879 880 return $id; 881 } 882 883 /** 884 * Draw an image 885 * 886 * The image will be inlined in the SVG document using data URL scheme. For 887 * this the mime type and base64 encoded file content will be merged to 888 * URL. 889 * 890 * @param mixed $file Image file 891 * @param ezcGraphCoordinate $position Top left position 892 * @param float $width Width of image in destination image 893 * @param float $height Height of image in destination image 894 * @return void 895 */ 896 public function drawImage( $file, ezcGraphCoordinate $position, $width, $height ) 897 { 898 $movie = $this->getDocument(); 899 900 $imageData = getimagesize( $file ); 901 if ( ( $imageData[2] !== IMAGETYPE_JPEG ) && ( $imageData[2] !== IMAGETYPE_PNG ) ) 902 { 903 throw new ezcGraphFlashBitmapTypeException( $imageData[2] ); 904 } 905 906 // Try to create a new SWFBitmap object from provided file 907 $bitmap = new SWFBitmap( fopen( $file, 'rb' ) ); 908 909 // Add the image to the movie 910 $object = $this->movie->add( $bitmap ); 911 912 // Image size is calculated on the base of a tick size of 20, so 913 // that we need to transform this, to our tick size. 914 $factor = $this->modifyCoordinate( 1 ) / 20; 915 $object->scale( $factor, $factor ); 916 917 // Scale by ratio of requested and original image size 918 $object->scale( 919 $width / $imageData[0], 920 $height / $imageData[1] 921 ); 922 923 // Move object to the right position 924 $object->moveTo( 925 $this->modifyCoordinate( $position->x ), 926 $this->modifyCoordinate( $position->y ) 927 ); 928 929 // Create, set and return unique ID 930 $object->setName( $id = 'ezcGraphImage_'. $this->id++ ); 931 return $id; 932 } 933 934 /** 935 * Return mime type for current image format 936 * 937 * @return string 938 */ 939 public function getMimeType() 940 { 941 return 'application/x-shockwave-flash'; 942 } 943 944 /** 945 * Finally save image 946 * 947 * @param string $file Destination filename 948 * @return void 949 */ 950 public function render( $file ) 951 { 952 $this->drawAllTexts(); 953 $movie = $this->getDocument(); 954 $movie->save( $file, $this->options->compression ); 955 } 956 957 /** 958 * Get resource of rendered result 959 * 960 * Return the resource of the rendered result. You should not use this 961 * method before you called either renderToOutput() or render(), as the 962 * image may not be completely rendered until then. 963 * 964 * @return SWFMovie 965 */ 966 public function getResource() 967 { 968 return $this->movie; 969 } 970 } 971 972 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |