[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/library/ezc/Graph/src/driver/ -> flash.php (source)

   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  ?>


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7