[ Index ]
 

Code source de Cr@wltr@ck 2.2.1

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/graphs/artichow/php5/inc/drivers/ -> gd.class.php (source)

   1  <?php
   2  /*
   3   * This work is hereby released into the Public Domain.
   4   * To view a copy of the public domain dedication,
   5   * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
   6   * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
   7   *
   8   */
   9   
  10  require_once dirname(__FILE__)."/../Driver.class.php";
  11  
  12  /**
  13   * Draw your objects
  14   *
  15   * @package Artichow
  16   */
  17  
  18  class awGDDriver extends Driver {
  19      
  20      /**
  21       * A GD resource
  22       *
  23       * @var $resource
  24       */
  25      public $resource;
  26      
  27  	public function __construct() {
  28          parent::__construct();
  29          
  30          $this->driverString = 'gd';
  31      }
  32  
  33  	public function init(awImage $image) {
  34          
  35          if($this->resource === NULL) {
  36              
  37              $this->setImageSize($image->width, $image->height);
  38              
  39              // Create image
  40              $this->resource = imagecreatetruecolor($this->imageWidth, $this->imageHeight);
  41              if(!$this->resource) {
  42                  awImage::drawError("Class Image: Unable to create a graph.");
  43              }
  44              
  45              imagealphablending($this->resource, TRUE);
  46              
  47              // Antialiasing is now handled by the Driver object
  48              $this->setAntiAliasing($image->getAntiAliasing());
  49              
  50              // Original color
  51              $this->filledRectangle(
  52                  new awWhite,
  53                  new awLine(
  54                      new awPoint(0, 0),
  55                      new awPoint($this->imageWidth, $this->imageHeight)
  56                  )
  57              );
  58              
  59              $shadow = $image->shadow;
  60              if($shadow !== NULL) {
  61                  $shadow = $shadow->getSpace();
  62                  $p1 = new awPoint($shadow->left, $shadow->top);
  63                  $p2 = new awPoint($this->imageWidth - $shadow->right - 1, $this->imageHeight - $shadow->bottom - 1);
  64                  
  65                  
  66                  // Draw image background
  67                  $this->filledRectangle($image->getBackground(), new awLine($p1, $p2));
  68                  
  69                  // Draw image border
  70                  $image->border->rectangle($this, $p1, $p2);
  71              }
  72              
  73          }
  74      }
  75      
  76  	public function initFromFile(awFileImage $fileImage, $file) {
  77          
  78          $image = @getimagesize((string)$file);
  79          
  80          if($image and in_array($image[2], array(2, 3))) {
  81          
  82              $fileImage->setSize($image[0], $image[1]);
  83              
  84              switch($image[2]) {
  85              
  86                  case 2 :
  87                      $this->resource = imagecreatefromjpeg($file);
  88                      break;
  89              
  90                  case 3 :
  91                      $this->resource = imagecreatefrompng($file);
  92                      break;
  93              
  94              }
  95  
  96              $this->setImageSize($fileImage->width, $fileImage->height);
  97          } else {
  98              awImage::drawError("Class FileImage: Artichow does not support the format of this image (must be in PNG or JPEG)");
  99          }
 100      }
 101      
 102  	public function setImageSize($width, $height) {
 103      
 104          $this->imageWidth = $width;
 105          $this->imageHeight = $height;
 106      
 107      }
 108      
 109  	public function setPosition($x, $y) {
 110          
 111          // Calculate absolute position
 112          $this->x = round($x * $this->imageWidth - $this->w / 2);
 113          $this->y = round($y * $this->imageHeight - $this->h / 2);
 114      
 115      }
 116      
 117  	public function setAbsPosition($x, $y) {
 118          
 119          $this->x = $x;
 120          $this->y = $y;
 121      
 122      }
 123      
 124  	public function movePosition($x, $y) {
 125  
 126          $this->x += (int)$x;
 127          $this->y += (int)$y;
 128      
 129      }
 130      
 131  	public function setSize($w, $h) {
 132      
 133          // Calcul absolute size
 134          $this->w = round($w * $this->imageWidth);
 135          $this->h = round($h * $this->imageHeight);
 136          
 137          return $this->getSize();
 138      
 139      }
 140      
 141  	public function setAbsSize($w, $h) {
 142      
 143          $this->w = $w;
 144          $this->h = $h;
 145          
 146          return $this->getSize();
 147      
 148      }
 149      
 150  	public function getSize() {
 151          
 152          return array($this->w, $this->h);
 153      
 154      }
 155      
 156  	public function setAntiAliasing($bool) {
 157          
 158          if(function_exists('imageantialias')) {
 159              imageantialias($this->resource, (bool)$bool);
 160  
 161              $this->antiAliasing = (bool)$bool;
 162          } else {
 163              awImage::drawErrorFile('missing-anti-aliasing');
 164          }
 165      }
 166      
 167  	public function getColor(awColor $color) {
 168  
 169          if($color->alpha === 0 or function_exists('imagecolorallocatealpha') === FALSE) {
 170              $gdColor = imagecolorallocate($this->resource, $color->red, $color->green, $color->blue);
 171          } else {
 172              $gdColor = imagecolorallocatealpha($this->resource, $color->red, $color->green, $color->blue, $color->alpha);
 173          }
 174  
 175          return $gdColor;
 176      }
 177      
 178  	public function copyImage(awImage $image, awPoint $p1, awPoint $p2) {
 179      
 180          list($x1, $y1) = $p1->getLocation();
 181          list($x2, $y2) = $p2->getLocation();
 182      
 183          $driver = $image->getDriver();
 184          imagecopy($this->resource, $driver->resource, $this->x + $x1, $this->y + $y1, 0, 0, $x2 - $x1, $y2 - $y1);
 185      
 186      }
 187      
 188  	public function copyResizeImage(awImage $image, awPoint $d1, awPoint $d2, awPoint $s1, awPoint $s2, $resample = TRUE) {
 189          
 190          if($resample) {
 191              $function = 'imagecopyresampled';
 192          } else {
 193              $function = 'imagecopyresized';
 194          }
 195          
 196          $driver = $image->getDriver();
 197      
 198          $function(
 199              $this->resource,
 200              $driver->resource,
 201              $this->x + $d1->x, $this->y + $d1->y,
 202              $s1->x, $s1->y,
 203              $d2->x - $d1->x, $d2->y - $d1->y,
 204              $s2->x - $s1->x, $s2->y - $s1->y
 205          );
 206      
 207      }
 208      
 209  	public function string(awText $text, awPoint $point, $width = NULL) {
 210          
 211          $font = $text->getFont();
 212          
 213          // Can we deal with that font?
 214          if($this->isCompatibleWithFont($font) === FALSE) {
 215              awImage::drawError('Class GDDriver: Incompatible font type (\''.get_class($font).'\')');
 216          }
 217          
 218          // Check which FontDriver to use
 219          if($font instanceof awPHPFont) {
 220              $fontDriver = $this->phpFontDriver;
 221          } else {
 222              $fontDriver = $this->fileFontDriver;
 223          }
 224          
 225          if($text->getBackground() !== NULL or $text->border->visible()) {
 226          
 227              list($left, $right, $top, $bottom) = $text->getPadding();
 228  
 229              $textWidth = $fontDriver->getTextWidth($text, $this);
 230              $textHeight = $fontDriver->getTextHeight($text, $this);
 231              
 232              $x1 = floor($point->x - $left);
 233              $y1 = floor($point->y - $top);
 234              $x2 = $x1 + $textWidth + $left + $right;
 235              $y2 = $y1 + $textHeight + $top + $bottom;
 236              
 237              $this->filledRectangle(
 238                  $text->getBackground(),
 239                  awLine::build($x1, $y1, $x2, $y2)
 240              );
 241              
 242              $text->border->rectangle(
 243                  $this,
 244                  new awPoint($x1 - 1, $y1 - 1),
 245                  new awPoint($x2 + 1, $y2 + 1)
 246              );
 247              
 248          }
 249          
 250          $fontDriver->string($this, $text, $point, $width);
 251          
 252      }
 253      
 254  	public function point(awColor $color, awPoint $p) {
 255      
 256          if($p->isHidden() === FALSE) {
 257              $rgb = $this->getColor($color);
 258              imagesetpixel($this->resource, $this->x + round($p->x), $this->y + round($p->y), $rgb);
 259          }
 260      
 261      }
 262      
 263  	public function line(awColor $color, awLine $line) {
 264      
 265          if($line->thickness > 0 and $line->isHidden() === FALSE) {
 266      
 267              $rgb = $this->getColor($color);
 268              $thickness = $line->thickness;
 269              
 270              list($p1, $p2) = $line->getLocation();
 271              
 272              $this->startThickness($thickness);
 273              
 274              switch($line->getStyle()) {
 275              
 276                  case awLine::SOLID :
 277                      imageline($this->resource, $this->x + round($p1->x), $this->y + round($p1->y), $this->x + round($p2->x), $this->y + round($p2->y), $rgb);
 278                      break;
 279                      
 280                  case awLine::DOTTED :
 281                      $size = sqrt(pow($p2->y - $p1->y, 2) + pow($p2->x - $p1->x, 2));
 282                      $cos = ($p2->x - $p1->x) / $size;
 283                      $sin = ($p2->y - $p1->y) / $size;
 284                      for($i = 0; $i <= $size; $i += 2) {
 285                          $p = new awPoint(
 286                              round($i * $cos + $p1->x),
 287                              round($i * $sin + $p1->y)
 288                          );
 289                          $this->point($color, $p);
 290                      }
 291                      break;
 292                      
 293                  case awLine::DASHED :
 294                      $width = $p2->x - $p1->x;
 295                      $height = $p2->y - $p1->y;
 296                      $size = sqrt(pow($height, 2) + pow($width, 2));
 297                      
 298                      if($size == 0) {
 299                          return;
 300                      }
 301                      
 302                      $cos = $width / $size;
 303                      $sin = $height / $size;
 304                      
 305                      $functionX = ($width  > 0) ? 'min' : 'max';
 306                      $functionY = ($height > 0) ? 'min' : 'max';
 307                      
 308                      for($i = 0; $i <= $size; $i += 6) {
 309                          
 310                          $t1 = new awPoint(
 311                              round($i * $cos + $p1->x),
 312                              round($i * $sin + $p1->y)
 313                          );
 314                          
 315                          $t2 = new awPoint(
 316                              round($functionX(($i + 3) * $cos, $width) + $p1->x),
 317                              round($functionY(($i + 3) * $sin, $height) + $p1->y)
 318                          );
 319                          
 320                          $this->line($color, new awLine($t1, $t2));
 321                          
 322                      }
 323                      break;
 324              
 325              }
 326              
 327              $this->stopThickness($thickness);
 328              
 329          }
 330          
 331      }
 332      
 333  	public function arc(awColor $color, awPoint $center, $width, $height, $from, $to) {
 334      
 335          imagefilledarc(
 336              $this->resource,
 337              $this->x + $center->x, $this->y + $center->y,
 338              $width, $height,
 339              $from, $to,
 340              $this->getColor($color),
 341              IMG_ARC_EDGED | IMG_ARC_NOFILL
 342          );
 343      
 344      }
 345      
 346  	public function filledArc(awColor $color, awPoint $center, $width, $height, $from, $to) {
 347      
 348          imagefilledarc(
 349              $this->resource,
 350              $this->x + $center->x, $this->y + $center->y,
 351              $width, $height,
 352              $from, $to,
 353              $this->getColor($color),
 354              IMG_ARC_PIE
 355          );
 356      
 357      }
 358      
 359  	public function ellipse(awColor $color, awPoint $center, $width, $height) {
 360      
 361          list($x, $y) = $center->getLocation();
 362      
 363          $rgb = $this->getColor($color);
 364          imageellipse(
 365              $this->resource,
 366              $this->x + $x,
 367              $this->y + $y,
 368              $width,
 369              $height,
 370              $rgb
 371          );
 372          
 373      }
 374      
 375  	public function filledEllipse($background, awPoint $center, $width, $height) {
 376      
 377          if($background instanceof awColor) {
 378      
 379              list($x, $y) = $center->getLocation();
 380          
 381              $rgb = $this->getColor($background);
 382              
 383              imagefilledellipse(
 384                  $this->resource,
 385                  $this->x + $x,
 386                  $this->y + $y,
 387                  $width,
 388                  $height,
 389                  $rgb
 390              );
 391              
 392          } else if($background instanceof awGradient) {
 393      
 394              list($x, $y) = $center->getLocation();
 395              
 396              $x1 = $x - round($width / 2);
 397              $y1 = $y - round($height / 2);
 398              $x2 = $x1 + $width;
 399              $y2 = $y1 + $height;
 400          
 401              $gradientDriver = new awGDGradientDriver($this);
 402              $gradientDriver->filledEllipse(
 403                  $background,
 404                  $x1, $y1,
 405                  $x2, $y2
 406              );
 407          
 408          }
 409          
 410      }
 411      
 412  	public function rectangle(awColor $color, awLine $line) {
 413      
 414          list($p1, $p2) = $line->getLocation();
 415          
 416          switch($line->getStyle()) {
 417          
 418              case awLine::SOLID :
 419                  $thickness = $line->getThickness();
 420                  $this->startThickness($thickness);
 421                  $rgb = $this->getColor($color);
 422                  imagerectangle($this->resource, $this->x + $p1->x, $this->y + $p1->y, $this->x + $p2->x, $this->y + $p2->y, $rgb);
 423                  $this->stopThickness($thickness);
 424                  break;
 425              
 426              default :
 427                  /* <php5> */
 428                  $side = clone $line;
 429                  /* </php5> */
 430                  
 431                  /* <php4> --
 432                  $side = new Line($p1, $p2);
 433                  -- </php4> */
 434                  
 435                  // Top side
 436                  $side->setLocation(
 437                      new awPoint($p1->x, $p1->y),
 438                      new awPoint($p2->x, $p1->y)
 439                  );
 440                  $this->line($color, $side);
 441                  
 442                  // Right side
 443                  $side->setLocation(
 444                      new awPoint($p2->x, $p1->y),
 445                      new awPoint($p2->x, $p2->y)
 446                  );
 447                  $this->line($color, $side);
 448                  
 449                  // Bottom side
 450                  $side->setLocation(
 451                      new awPoint($p1->x, $p2->y),
 452                      new awPoint($p2->x, $p2->y)
 453                  );
 454                  $this->line($color, $side);
 455                  
 456                  // Left side
 457                  $side->setLocation(
 458                      new awPoint($p1->x, $p1->y),
 459                      new awPoint($p1->x, $p2->y)
 460                  );
 461                  $this->line($color, $side);
 462              
 463                  break;
 464          
 465          }
 466      
 467      }
 468      
 469  	public function filledRectangle($background, awLine $line) {
 470      
 471          $p1 = $line->p1;
 472          $p2 = $line->p2;
 473      
 474          if($background instanceof awColor) {
 475              $rgb = $this->getColor($background);
 476              imagefilledrectangle($this->resource, $this->x + $p1->x, $this->y + $p1->y, $this->x + $p2->x, $this->y + $p2->y, $rgb);
 477          } else if($background instanceof awGradient) {
 478              $gradientDriver = new awGDGradientDriver($this);
 479              $gradientDriver->filledRectangle($background, $p1, $p2);
 480          }
 481      
 482      }
 483      
 484  	public function polygon(awColor $color, awPolygon $polygon) {
 485          
 486          switch($polygon->getStyle()) {
 487          
 488              case awPolygon::SOLID :
 489                  $thickness = $polygon->getThickness();
 490                  $this->startThickness($thickness);
 491                  $points = $this->getPolygonPoints($polygon);
 492                  $rgb = $this->getColor($color);
 493                  imagepolygon($this->resource, $points, $polygon->count(), $rgb);
 494                  $this->stopThickness($thickness);
 495                  break;
 496                  
 497              default :
 498              
 499                  if($polygon->count() > 1) {
 500                  
 501                      $prev = $polygon->get(0);
 502                      
 503                      $line = new awLine;
 504                      $line->setStyle($polygon->getStyle());
 505                      $line->setThickness($polygon->getThickness());
 506                      
 507                      for($i = 1; $i < $polygon->count(); $i++) {
 508                          $current = $polygon->get($i);
 509                          $line->setLocation($prev, $current);
 510                          $this->line($color, $line);
 511                          $prev = $current;
 512                      }
 513                      
 514                      // Close the polygon
 515                      $line->setLocation($prev, $polygon->get(0));
 516                      $this->line($color, $line);
 517                      
 518                  }
 519          
 520          }
 521          
 522      }
 523      
 524  	public function filledPolygon($background, awPolygon $polygon) {
 525          
 526          if($background instanceof awColor) {
 527              
 528              $points = $this->getPolygonPoints($polygon);
 529              $rgb = $this->getColor($background);
 530              
 531              imagefilledpolygon($this->resource, $points, $polygon->count(), $rgb);
 532              
 533          } else if($background instanceof awGradient) {
 534              
 535              $gradientDriver = new awGDGradientDriver($this);
 536              $gradientDriver->filledPolygon($background, $polygon);
 537              
 538          }
 539  
 540      }
 541  
 542  	public function send(awImage $image) {
 543  
 544          $this->drawImage($image);
 545  
 546      }
 547      
 548  	public function get(awImage $image) {
 549          
 550          return $this->drawImage($image, TRUE, FALSE);
 551          
 552      }
 553      
 554  	public function getTextWidth(awText $text) {
 555          $font = $text->getFont();
 556          
 557          if($font instanceof awPHPFont) {
 558              $fontDriver = $this->phpFontDriver;
 559          } else {
 560              $fontDriver = $this->fileFontDriver;
 561          }
 562          
 563          return $fontDriver->getTextWidth($text, $this);
 564      }
 565      
 566  	public function getTextHeight(awText $text) {
 567          $font = $text->getFont();
 568          
 569          if($font instanceof awPHPFont) {
 570              $fontDriver = $this->phpFontDriver;
 571          } else {
 572              $fontDriver = $this->fileFontDriver;
 573          }
 574          
 575          return $fontDriver->getTextHeight($text, $this);
 576      }
 577      
 578  	protected function isCompatibleWithFont(awFont $font) {
 579          if($font instanceof awFDBFont) {
 580              return FALSE;
 581          } else {
 582              return TRUE;
 583          }
 584      }
 585      
 586  	private function drawImage(awImage $image, $return = FALSE, $header = TRUE) {
 587          
 588          $format = $image->getFormatString();
 589          
 590          // Test if format is available
 591          if((imagetypes() & $image->getFormat()) === FALSE) {
 592              awImage::drawError("Class Image: Format '".$format."' is not available on your system. Check that your PHP has been compiled with the good libraries.");
 593          }
 594      
 595          // Get some infos about this image
 596          switch($format) {
 597              case 'jpeg' :
 598                  $function = 'imagejpeg';
 599                  break;
 600              case 'png' :
 601                  $function = 'imagepng';
 602                  break;
 603              case 'gif' :
 604                  $function = 'imagegif';
 605                  break;
 606          }
 607          
 608          // Send headers to the browser
 609          if($header === TRUE) {
 610              $image->sendHeaders();
 611          }
 612          
 613          if($return) {
 614              ob_start();
 615          }
 616          
 617          $function($this->resource);
 618          
 619          if($return) {
 620              return ob_get_clean();
 621          }
 622      }
 623      
 624  	private function getPolygonPoints(awPolygon $polygon) {
 625          
 626          $points = array();
 627          
 628          foreach($polygon->all() as $point) {
 629              $points[] = $point->x + $this->x;
 630              $points[] = $point->y + $this->y;
 631          }
 632          
 633          return $points;
 634          
 635      }
 636      
 637  	private function startThickness($thickness) {
 638          
 639          if($thickness > 1) {
 640          
 641              // Beurk :'(
 642              if($this->antiAliasing and function_exists('imageantialias')) {
 643                  imageantialias($this->resource, FALSE);
 644              }
 645              imagesetthickness($this->resource, $thickness);
 646              
 647          }
 648          
 649      }
 650      
 651  	private function stopThickness($thickness) {
 652          
 653          if($thickness > 1) {
 654          
 655              if($this->antiAliasing and function_exists('imageantialias')) {
 656                  imageantialias($this->resource, TRUE);
 657              }
 658              imagesetthickness($this->resource, 1);
 659              
 660          }
 661          
 662      }
 663      
 664  
 665  }
 666  
 667  registerClass('GDDriver');
 668  
 669  /**
 670   * To your gradients
 671   *
 672   * @package Artichow
 673   */
 674  
 675  class awGDGradientDriver {
 676  
 677      /**
 678       * A driver
 679       *
 680       * @var awGDDriver
 681       */
 682      protected $driver;
 683  
 684      /**
 685       * Build your GDGradientDriver
 686       *
 687       * @var awGDDriver $driver 
 688       */
 689  	public function __construct(awGDDriver $driver) {
 690      
 691          $this->driver = $driver;
 692          
 693      }
 694      
 695  	public function drawFilledFlatTriangle(awGradient $gradient, awPoint $a, awPoint $b, awPoint $c) {
 696      
 697          if($gradient->angle !== 0) {
 698              awImage::drawError("Class GDGradientDriver: Flat triangles can only be used with 0 degree gradients.");
 699          }
 700      
 701          // Look for right-angled triangle
 702          if($a->x !== $b->x and $b->x !== $c->x) {
 703              awImage::drawError("Class GDGradientDriver: Not right-angled flat triangles are not supported yet.");
 704          }
 705          
 706          if($a->x === $b->x) {
 707              $d = $a;
 708              $e = $c;
 709          } else {
 710              $d = $c;
 711              $e = $a;
 712          }
 713          
 714          $this->init($gradient, $b->y - $d->y);
 715      
 716          for($i = $c->y + 1; $i < $b->y; $i++) {
 717              
 718              $color = $this->color($i - $d->y);
 719              $pos = ($i - $d->y) / ($b->y - $d->y);
 720              
 721              $p1 = new awPoint($e->x, $i);
 722              $p2 = new awPoint(1 + floor($e->x - $pos * ($e->x - $d->x)), $i);
 723              
 724              $this->driver->filledRectangle($color, new awLine($p1, $p2));
 725              
 726              unset($color);
 727              
 728          }
 729      
 730      }
 731      
 732  	protected function drawFilledTriangle(awGradient $gradient, awPolygon $polygon) {
 733          
 734          if($gradient->angle === 0) {
 735              $this->drawFilledTriangleVertically($gradient, $polygon);
 736          } elseif($gradient->angle === 90) {
 737              $this->drawFilledTriangleHorizontally($gradient, $polygon);
 738          }
 739          
 740      }
 741      
 742  	private function drawFilledTriangleVertically(awGradient $gradient, awPolygon $polygon) {
 743          list($yMin, $yMax) = $polygon->getBoxYRange();
 744          
 745          $this->init($gradient, $yMax - $yMin);
 746          
 747          // Get the triangle line we will draw our lines from
 748          $fromLine = NULL;
 749          $lines = $polygon->getLines();
 750                  
 751          $count = count($lines);
 752                      
 753          // Pick the side of the triangle going from the top
 754          // to the bottom of the surrounding box
 755          for($i = 0; $i < $count; $i++) {
 756              if($lines[$i]->isTopToBottom($polygon)) {
 757                  list($fromLine) = array_splice($lines, $i, 1);
 758                  break;
 759              }
 760          }
 761          
 762          // If for some reason the three points are aligned,
 763          // $fromLine will still be NULL
 764          if($fromLine === NULL) {
 765              return;
 766          }
 767                          
 768          $fillLine = NULL;
 769          for($y = round($yMin); $y < round($yMax); $y++) {
 770              
 771              $fromX = $fromLine->getXFrom($y);
 772              
 773              $toX = array();
 774              foreach($lines as $line) {
 775                  $xValue = $line->getXFrom($y);
 776                  
 777                  if(!is_null($xValue)) {
 778                      $toX[] = $xValue;
 779                  }
 780              }
 781              
 782              if(count($toX) === 1) {
 783                  $fillLine = new Line(
 784                      new Point($fromX, $y),
 785                      new Point($toX[0], $y)
 786                  );
 787              } else {
 788              
 789                  $line1 = new Line(
 790                      new Point($fromX, $y),
 791                      new Point($toX[0], $y)
 792                  );
 793                  $line2 = new  Line(
 794                      new Point($fromX, $y),
 795                      new Point($toX[1], $y)
 796                  );
 797              
 798                  if($line1->getSize() < $line2->getSize()) {
 799                      $fillLine = $line1;
 800                  } else {
 801                      $fillLine = $line2;
 802                  }
 803              }
 804              
 805              if(!$fillLine->isPoint()) {
 806                  $color = $this->color($y - $yMin);
 807                  $this->driver->line($color, $fillLine);
 808                  
 809                  unset($color);
 810              }
 811          }
 812      
 813      }
 814      
 815  	private function drawFilledTriangleHorizontally(awGradient $gradient, awPolygon $polygon) {
 816          list($xMin, $xMax) = $polygon->getBoxXRange();
 817          
 818          $this->init($gradient, $xMax - $xMin);
 819          
 820          // Get the triangle line we will draw our lines from
 821          $fromLine = NULL;
 822          $lines = $polygon->getLines();
 823                  
 824          $count = count($lines);
 825                      
 826          // Pick the side of the triangle going all the way
 827          // from the left side to the right side of the surrounding box
 828          for($i = 0; $i < $count; $i++) {
 829              if($lines[$i]->isLeftToRight($polygon)) {
 830                  list($fromLine) = array_splice($lines, $i, 1);
 831                  break;
 832              }
 833          }
 834          
 835          // If for some reason the three points are aligned,
 836          // $fromLine will still be NULL
 837          if($fromLine === NULL) {
 838              return;
 839          }
 840  
 841          $fillLine = NULL;
 842          for($x = round($xMin); $x < round($xMax); $x++) {
 843              
 844              $fromY = floor($fromLine->getYFrom($x));
 845              
 846              $toY = array();
 847              foreach($lines as $line) {
 848                  $yValue = $line->getYFrom($x);
 849                  
 850                  if(!is_null($yValue)) {
 851                      $toY[] = floor($yValue);
 852                  }
 853              }
 854              
 855              if(count($toY) === 1) {
 856                  $fillLine = new Line(
 857                      new Point($x, $fromY),
 858                      new Point($x, $toY[0])
 859                  );
 860              } else {
 861              
 862                  $line1 = new Line(
 863                      new Point($x, $fromY),
 864                      new Point($x, $toY[0])
 865                  );
 866                  $line2 = new  Line(
 867                      new Point($x, $fromY),
 868                      new Point($x, $toY[1])
 869                  );
 870              
 871                  if($line1->getSize() < $line2->getSize()) {
 872                      $fillLine = $line1;
 873                  } else {
 874                      $fillLine = $line2;
 875                  }
 876              }
 877              
 878              $color = $this->color($x - $xMin);
 879              if($fillLine->isPoint()) {
 880                  $this->driver->point($color, $fillLine->p1);
 881              } elseif($fillLine->getSize() >= 1) {
 882                  $this->driver->line($color, $fillLine);
 883              }
 884              unset($color);
 885          }
 886      
 887      }
 888      
 889  	public function filledRectangle(awGradient $gradient, awPoint $p1, awPoint $p2) {
 890      
 891          list($x1, $y1) = $p1->getLocation();
 892          list($x2, $y2) = $p2->getLocation();
 893      
 894          if($y1 < $y2) {
 895              $y1 ^= $y2 ^= $y1 ^= $y2;
 896          }
 897      
 898          if($x2 < $x1) {
 899              $x1 ^= $x2 ^= $x1 ^= $x2;
 900          }
 901          
 902          if($gradient instanceof awLinearGradient) {
 903              $this->rectangleLinearGradient($gradient, new awPoint($x1, $y1), new awPoint($x2, $y2));
 904          } else {
 905              awImage::drawError("Class GDGradientDriver: This gradient is not supported by rectangles.");
 906          }
 907      
 908      }
 909      
 910  	public function filledPolygon(awGradient $gradient, awPolygon $polygon) {
 911      
 912          if($gradient instanceof awLinearGradient) {
 913              $this->polygonLinearGradient($gradient, $polygon);
 914          } else {
 915              awImage::drawError("Class GDGradientDriver: This gradient is not supported by polygons.");
 916          }
 917      
 918      }
 919      
 920  	protected function rectangleLinearGradient(awLinearGradient $gradient, awPoint $p1, awPoint $p2) {
 921      
 922          list($x1, $y1) = $p1->getLocation();
 923          list($x2, $y2) = $p2->getLocation();
 924      
 925          if($y1 - $y2 > 0) {
 926          
 927              if($gradient->angle === 0) {
 928              
 929                  $this->init($gradient, $y1 - $y2);
 930          
 931                  for($i = $y2; $i <= $y1; $i++) {
 932                  
 933                      $color = $this->color($i - $y2);
 934                      
 935                      $p1 = new awPoint($x1, $i);
 936                      $p2 = new awPoint($x2, $i);
 937              
 938                      $this->driver->filledRectangle($color, new awLine($p1, $p2));
 939                      
 940                      unset($color);
 941                      
 942                  }
 943                  
 944              } else if($gradient->angle === 90) {
 945              
 946                  $this->init($gradient, $x2 - $x1);
 947          
 948                  for($i = $x1; $i <= $x2; $i++) {
 949                  
 950                      $color = $this->color($i - $x1);
 951                      
 952                      $p1 = new awPoint($i, $y2);
 953                      $p2 = new awPoint($i, $y1);
 954              
 955                      $this->driver->filledRectangle($color, new awLine($p1, $p2));
 956                      
 957                      unset($color);
 958                      
 959                  }
 960                  
 961              }
 962              
 963          }
 964      
 965      }
 966      
 967  	public function filledEllipse(awGradient $gradient, $x1, $y1, $x2, $y2) {
 968      
 969          if($y1 < $y2) {
 970              $y1 ^= $y2 ^= $y1 ^= $y2;
 971          }
 972      
 973          if($x2 < $x1) {
 974              $x1 ^= $x2 ^= $x1 ^= $x2;
 975          }
 976          
 977          if($gradient instanceof awRadialGradient) {
 978              $this->ellipseRadialGradient($gradient, $x1, $y1, $x2, $y2);
 979          } else if($gradient instanceof awLinearGradient) {
 980              $this->ellipseLinearGradient($gradient, $x1, $y1, $x2, $y2);
 981          } else {
 982              awImage::drawError("Class GDGradientDriver: This gradient is not supported by ellipses.");
 983          }
 984      
 985      }
 986      
 987  	protected function ellipseRadialGradient(awGradient $gradient, $x1, $y1, $x2, $y2) {
 988      
 989          if($y1 - $y2 > 0) {
 990      
 991              if($y1 - $y2 != $x2 - $x1) {
 992                  awImage::drawError("Class GDGradientDriver: Radial gradients are only implemented on circle, not ellipses.");
 993              }
 994              
 995              $c = new awPoint($x1 + ($x2 - $x1) / 2, $y1 + ($y2 - $y1) / 2); 
 996              $r = ($x2 - $x1) / 2;
 997              $ok = array();
 998              
 999              // Init gradient
1000              $this->init($gradient, $r);
1001              
1002              for($i = 0; $i <= $r; $i += 0.45) {
1003              
1004                  $p = ceil((2 * M_PI * $i));
1005                  
1006                  if($p > 0) {
1007                      $interval = 360 / $p;
1008                  } else {
1009                      $interval = 360;
1010                  }
1011                  
1012                  $color = $this->color($i);
1013                  
1014                  for($j = 0; $j < 360; $j += $interval) {
1015                  
1016                      $rad = ($j / 360) * (2 * M_PI);
1017                      
1018                      $x = round($i * cos($rad));
1019                      $y = round($i * sin($rad));
1020                      
1021                      $l = sqrt($x * $x + $y * $y);
1022                      
1023                      if($l <= $r) {
1024                      
1025                          if(
1026                              array_key_exists((int)$x, $ok) === FALSE or
1027                              array_key_exists((int)$y, $ok[$x]) === FALSE
1028                          ) {
1029                          
1030                              // Print the point
1031                              $this->driver->point($color, new awPoint($c->x + $x, $c->y + $y));
1032                              
1033                              $ok[(int)$x][(int)$y] = TRUE;
1034                          
1035                          }
1036                          
1037                      }
1038                  
1039                  }
1040                  
1041                  unset($color);
1042              
1043              }
1044          
1045          }
1046      
1047      }
1048      
1049  	protected function ellipseLinearGradient(awGradient $gradient, $x1, $y1, $x2, $y2) {
1050      
1051          // Gauche->droite : 90°
1052      
1053          if($y1 - $y2 > 0) {
1054      
1055              if($y1 - $y2 != $x2 - $x1) {
1056                  awImage::drawError("Class GDGradientDriver: Linear gradients are only implemented on circle, not ellipses.");
1057              }
1058              
1059              $r = ($x2 - $x1) / 2;
1060              
1061              // Init gradient
1062              $this->init($gradient, $x2 - $x1);
1063              
1064              for($i = -$r; $i <= $r; $i++) {
1065                  
1066                  $h = sin(acos($i / $r)) * $r;
1067                  
1068                  $color = $this->color($i + $r);
1069                  
1070                  if($gradient->angle === 90) {
1071                  
1072                      // Print the line
1073                      $p1 = new awPoint(
1074                          $x1 + $i + $r,
1075                          round(max($y2 + $r - $h + 1, $y2))
1076                      );
1077                      
1078                      $p2 = new awPoint(
1079                          $x1 + $i + $r,
1080                          round(min($y1 - $r + $h - 1, $y1))
1081                      );
1082                      
1083                  } else {
1084                  
1085                      // Print the line
1086                      $p1 = new awPoint(
1087                          round(max($x1 + $r - $h + 1, $x1)),
1088                          $y2 + $i + $r
1089                      );
1090                      
1091                      $p2 = new awPoint(
1092                          round(min($x2 - $r + $h - 1, $x2)),
1093                          $y2 + $i + $r
1094                      );
1095                      
1096                  }
1097                  
1098                  $this->driver->filledRectangle($color, new awLine($p1, $p2));
1099                  
1100                  unset($color);
1101              
1102              }
1103          
1104          }
1105      
1106      }
1107      
1108  	protected function polygonLinearGradient(awLinearGradient $gradient, awPolygon $polygon) {
1109      
1110          $count = $polygon->count();
1111          
1112          if($count >= 4) {
1113          
1114              $left = $polygon->get(0);
1115              $right = $polygon->get($count - 1);
1116              
1117              if($gradient->angle === 0) {
1118              
1119                  // Get polygon maximum and minimum
1120                  $offset = $polygon->get(0);
1121                  $max = $min = $offset->y;
1122                  for($i = 1; $i < $count - 1; $i++) {
1123                      $offset = $polygon->get($i);
1124                      $max = max($max, $offset->y);
1125                      $min = min($min, $offset->y);
1126                  }
1127                  
1128                  $this->init($gradient, $max - $min);
1129              
1130                  $prev = $polygon->get(1);
1131                  
1132                  $sum = 0;
1133              
1134                  for($i = 2; $i < $count - 1; $i++) {
1135                  
1136                      $current = $polygon->get($i);
1137                      
1138                      $interval = 1;
1139                      
1140                      if($i !== $count - 2) {
1141                          $current->x -= $interval;
1142                      }
1143                      
1144                      if($current->x - $prev->x > 0) {
1145                  
1146                          // Draw rectangle
1147                          $x1 = $prev->x;
1148                          $x2 = $current->x;
1149                          $y1 = max($prev->y, $current->y);
1150                          $y2 = $left->y;
1151                          
1152                          $gradient = new awLinearGradient(
1153                              $this->color($max - $min - ($y2 - $y1)),
1154                              $this->color($max - $min),
1155                              0
1156                          );
1157                          
1158                          if($y1 > $y2) {
1159                              $y2 = $y1;
1160                          }
1161                          
1162                          $this->driver->filledRectangle(
1163                              $gradient,
1164                              awLine::build($x1, $y1, $x2, $y2)
1165                          );
1166                          
1167                          $top = ($prev->y < $current->y) ? $current : $prev;
1168                          $bottom = ($prev->y >= $current->y) ? $current : $prev;
1169                          
1170                          $gradient = new awLinearGradient(
1171                              $this->color($bottom->y - $min),
1172                              $this->color($max - $min - ($y2 - $y1)),
1173                              0
1174                          );
1175                          
1176      
1177                          $gradientDriver = new awGDGradientDriver($this->driver);
1178                          $gradientDriver->drawFilledFlatTriangle(
1179                              $gradient,
1180                              new awPoint($prev->x, min($prev->y, $current->y)),
1181                              $top,
1182                              new awPoint($current->x, min($prev->y, $current->y))
1183                          );
1184                          unset($gradientDriver);
1185                          
1186                          $sum += $current->x - $prev->x;
1187                          
1188                      }
1189                      
1190                      $prev = $current;
1191                      $prev->x += $interval;
1192                  
1193                  }
1194              
1195              } else if($gradient->angle === 90) {
1196                  
1197                  $width = $right->x - $left->x;
1198                  $this->init($gradient, $width);
1199                  
1200                  $pos = 1;
1201                  $next = $polygon->get($pos++);
1202                  
1203                  $this->next($polygon, $pos, $prev, $next);
1204              
1205                  for($i = 0; $i <= $width; $i++) {
1206                  
1207                      $x = $left->x + $i;
1208                      
1209                      $y1 = round($prev->y + ($next->y - $prev->y) * (($i + $left->x - $prev->x) / ($next->x - $prev->x)));
1210                      $y2 = $left->y;
1211                  
1212                      // Draw line
1213                      $color = $this->color($i);
1214                      // YaPB : PHP does not handle alpha on lines
1215                      $this->driver->filledRectangle($color, awLine::build($x, $y1, $x, $y2));
1216  
1217                      unset($color);
1218                      
1219                      // Jump to next point
1220                      if($next->x == $i + $left->x) {
1221                      
1222                          $this->next($polygon, $pos, $prev, $next);
1223                          
1224                      }
1225                  
1226                  }
1227      
1228              }
1229              
1230          } else if($count === 3) {
1231              $this->drawFilledTriangle(
1232                  $gradient,
1233                  $polygon
1234              );
1235          }
1236      
1237      }
1238      
1239  	private function next($polygon, &$pos, &$prev, &$next) {
1240      
1241          do {
1242              $prev = $next;
1243              $next = $polygon->get($pos++);
1244          }
1245          while($next->x - $prev->x == 0 and $pos < $polygon->count());
1246          
1247      }
1248      
1249      /**
1250       * Start colors
1251       *
1252       * @var int
1253       */
1254      private $r1, $g1, $b1, $a1;
1255      
1256      /**
1257       * Stop colors
1258       *
1259       * @var int
1260       */
1261      private $r2, $g2, $b2, $a2;
1262      
1263      /**
1264       * Gradient size in pixels
1265       *
1266       * @var int
1267       */
1268      private $size;
1269      
1270      
1271  	private function init(awGradient $gradient, $size) {
1272          
1273          list(
1274              $this->r1, $this->g1, $this->b1, $this->a1
1275          ) = $gradient->from->rgba();
1276          
1277          list(
1278              $this->r2, $this->g2, $this->b2, $this->a2
1279          ) = $gradient->to->rgba();
1280          
1281          $this->size = $size;
1282      }
1283      
1284  	private function color($pos) {
1285      
1286          return new awColor(
1287              $this->getRed($pos),
1288              $this->getGreen($pos),
1289              $this->getBlue($pos),
1290              $this->getAlpha($pos)
1291          );
1292          
1293      }
1294      
1295      
1296  	private function getRed($pos) {
1297          if((float)$this->size !== 0.0) {
1298              return (int)round($this->r1 + ($pos / $this->size) * ($this->r2 - $this->r1));
1299          } else {
1300              return 0;
1301          }
1302      }
1303      
1304  	private function getGreen($pos) {
1305          if((float)$this->size !== 0.0) {
1306              return (int)round($this->g1 + ($pos / $this->size) * ($this->g2 - $this->g1));
1307          } else {
1308              return 0;
1309          }
1310      }
1311      
1312  	private function getBlue($pos) {
1313          if((float)$this->size !== 0.0) {
1314              return (int)round($this->b1 + ($pos / $this->size) * ($this->b2 - $this->b1));
1315          } else {
1316              return 0;
1317          }
1318      }
1319      
1320  	private function getAlpha($pos) {
1321          if((float)$this->size !== 0.0) {
1322              return (int)round(($this->a1 + ($pos / $this->size) * ($this->a2 - $this->a1)) / 127 * 100);
1323          } else {
1324              return 0;
1325          }
1326      }
1327  
1328  }
1329  
1330  registerClass('GDGradientDriver');
1331  
1332  /*
1333   * Check for GD2
1334   */
1335  if(function_exists('imagecreatetruecolor') === FALSE) {
1336      awImage::drawErrorFile('missing-gd2');
1337  }
1338  
1339  ?>


Généré le : Thu Sep 6 14:14:11 2007 par Balluche grâce à PHPXref 0.7