[ Index ] |
|
Code source de Cr@wltr@ck 2.2.1 |
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 var $resource; 26 27 function awGDDriver() { 28 parent::Driver(); 29 30 $this->driverString = 'gd'; 31 } 32 33 function init(&$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 function initFromFile(&$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 function setImageSize($width, $height) { 103 104 $this->imageWidth = $width; 105 $this->imageHeight = $height; 106 107 } 108 109 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 function setAbsPosition($x, $y) { 118 119 $this->x = $x; 120 $this->y = $y; 121 122 } 123 124 function movePosition($x, $y) { 125 126 $this->x += (int)$x; 127 $this->y += (int)$y; 128 129 } 130 131 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 function setAbsSize($w, $h) { 142 143 $this->w = $w; 144 $this->h = $h; 145 146 return $this->getSize(); 147 148 } 149 150 function getSize() { 151 152 return array($this->w, $this->h); 153 154 } 155 156 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 function getColor($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 function copyImage(&$image, $p1, $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 function copyResizeImage(&$image, $d1, $d2, $s1, $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 function string(&$text, $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(is_a($font, '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 function point($color, $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 function line($color, $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 LINE_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 LINE_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 LINE_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 function arc($color, $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 function filledArc($color, $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 function ellipse($color, $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 function filledEllipse($background, $center, $width, $height) { 376 377 if(is_a($background, '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(is_a($background, '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 function rectangle($color, $line) { 413 414 list($p1, $p2) = $line->getLocation(); 415 416 switch($line->getStyle()) { 417 418 case LINE_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 428 429 $side = new Line($p1, $p2); 430 431 432 // Top side 433 $side->setLocation( 434 new awPoint($p1->x, $p1->y), 435 new awPoint($p2->x, $p1->y) 436 ); 437 $this->line($color, $side); 438 439 // Right side 440 $side->setLocation( 441 new awPoint($p2->x, $p1->y), 442 new awPoint($p2->x, $p2->y) 443 ); 444 $this->line($color, $side); 445 446 // Bottom side 447 $side->setLocation( 448 new awPoint($p1->x, $p2->y), 449 new awPoint($p2->x, $p2->y) 450 ); 451 $this->line($color, $side); 452 453 // Left side 454 $side->setLocation( 455 new awPoint($p1->x, $p1->y), 456 new awPoint($p1->x, $p2->y) 457 ); 458 $this->line($color, $side); 459 460 break; 461 462 } 463 464 } 465 466 function filledRectangle($background, $line) { 467 468 $p1 = $line->p1; 469 $p2 = $line->p2; 470 471 if(is_a($background, 'awColor')) { 472 $rgb = $this->getColor($background); 473 imagefilledrectangle($this->resource, $this->x + $p1->x, $this->y + $p1->y, $this->x + $p2->x, $this->y + $p2->y, $rgb); 474 } else if(is_a($background, 'awGradient')) { 475 $gradientDriver = new awGDGradientDriver($this); 476 $gradientDriver->filledRectangle($background, $p1, $p2); 477 } 478 479 } 480 481 function polygon($color, &$polygon) { 482 483 switch($polygon->getStyle()) { 484 485 case POLYGON_SOLID : 486 $thickness = $polygon->getThickness(); 487 $this->startThickness($thickness); 488 $points = $this->getPolygonPoints($polygon); 489 $rgb = $this->getColor($color); 490 imagepolygon($this->resource, $points, $polygon->count(), $rgb); 491 $this->stopThickness($thickness); 492 break; 493 494 default : 495 496 if($polygon->count() > 1) { 497 498 $prev = $polygon->get(0); 499 500 $line = new awLine; 501 $line->setStyle($polygon->getStyle()); 502 $line->setThickness($polygon->getThickness()); 503 504 for($i = 1; $i < $polygon->count(); $i++) { 505 $current = $polygon->get($i); 506 $line->setLocation($prev, $current); 507 $this->line($color, $line); 508 $prev = $current; 509 } 510 511 // Close the polygon 512 $line->setLocation($prev, $polygon->get(0)); 513 $this->line($color, $line); 514 515 } 516 517 } 518 519 } 520 521 function filledPolygon($background, &$polygon) { 522 523 if(is_a($background, 'awColor')) { 524 525 $points = $this->getPolygonPoints($polygon); 526 $rgb = $this->getColor($background); 527 528 imagefilledpolygon($this->resource, $points, $polygon->count(), $rgb); 529 530 } else if(is_a($background, 'awGradient')) { 531 532 $gradientDriver = new awGDGradientDriver($this); 533 $gradientDriver->filledPolygon($background, $polygon); 534 535 } 536 537 } 538 539 function send(&$image) { 540 541 $this->drawImage($image); 542 543 } 544 545 function get(&$image) { 546 547 return $this->drawImage($image, TRUE, FALSE); 548 549 } 550 551 function getTextWidth(&$text) { 552 $font = $text->getFont(); 553 554 if(is_a($font, 'awPHPFont')) { 555 $fontDriver = $this->phpFontDriver; 556 } else { 557 $fontDriver = $this->fileFontDriver; 558 } 559 560 return $fontDriver->getTextWidth($text, $this); 561 } 562 563 function getTextHeight(&$text) { 564 $font = $text->getFont(); 565 566 if(is_a($font, 'awPHPFont')) { 567 $fontDriver = $this->phpFontDriver; 568 } else { 569 $fontDriver = $this->fileFontDriver; 570 } 571 572 return $fontDriver->getTextHeight($text, $this); 573 } 574 575 function isCompatibleWithFont(&$font) { 576 if(is_a($font, 'awFDBFont')) { 577 return FALSE; 578 } else { 579 return TRUE; 580 } 581 } 582 583 function drawImage(&$image, $return = FALSE, $header = TRUE) { 584 585 $format = $image->getFormatString(); 586 587 // Test if format is available 588 if((imagetypes() & $image->getFormat()) === FALSE) { 589 awImage::drawError("Class Image: Format '".$format."' is not available on your system. Check that your PHP has been compiled with the good libraries."); 590 } 591 592 // Get some infos about this image 593 switch($format) { 594 case 'jpeg' : 595 $function = 'imagejpeg'; 596 break; 597 case 'png' : 598 $function = 'imagepng'; 599 break; 600 case 'gif' : 601 $function = 'imagegif'; 602 break; 603 } 604 605 // Send headers to the browser 606 if($header === TRUE) { 607 $image->sendHeaders(); 608 } 609 610 if($return) { 611 ob_start(); 612 } 613 614 $function($this->resource); 615 616 if($return) { 617 return ob_get_clean(); 618 } 619 } 620 621 function getPolygonPoints(&$polygon) { 622 623 $points = array(); 624 625 foreach($polygon->all() as $point) { 626 $points[] = $point->x + $this->x; 627 $points[] = $point->y + $this->y; 628 } 629 630 return $points; 631 632 } 633 634 function startThickness($thickness) { 635 636 if($thickness > 1) { 637 638 // Beurk :'( 639 if($this->antiAliasing and function_exists('imageantialias')) { 640 imageantialias($this->resource, FALSE); 641 } 642 imagesetthickness($this->resource, $thickness); 643 644 } 645 646 } 647 648 function stopThickness($thickness) { 649 650 if($thickness > 1) { 651 652 if($this->antiAliasing and function_exists('imageantialias')) { 653 imageantialias($this->resource, TRUE); 654 } 655 imagesetthickness($this->resource, 1); 656 657 } 658 659 } 660 661 662 } 663 664 registerClass('GDDriver'); 665 666 /** 667 * To your gradients 668 * 669 * @package Artichow 670 */ 671 672 class awGDGradientDriver { 673 674 /** 675 * A driver 676 * 677 * @var awGDDriver 678 */ 679 var $driver; 680 681 /** 682 * Build your GDGradientDriver 683 * 684 * @var $driver 685 */ 686 function awGDGradientDriver($driver) { 687 688 $this->driver = $driver; 689 690 } 691 692 function drawFilledFlatTriangle($gradient, $a, $b, $c) { 693 694 if($gradient->angle !== 0) { 695 awImage::drawError("Class GDGradientDriver: Flat triangles can only be used with 0 degree gradients."); 696 } 697 698 // Look for right-angled triangle 699 if($a->x !== $b->x and $b->x !== $c->x) { 700 awImage::drawError("Class GDGradientDriver: Not right-angled flat triangles are not supported yet."); 701 } 702 703 if($a->x === $b->x) { 704 $d = $a; 705 $e = $c; 706 } else { 707 $d = $c; 708 $e = $a; 709 } 710 711 $this->init($gradient, $b->y - $d->y); 712 713 for($i = $c->y + 1; $i < $b->y; $i++) { 714 715 $color = $this->color($i - $d->y); 716 $pos = ($i - $d->y) / ($b->y - $d->y); 717 718 $p1 = new awPoint($e->x, $i); 719 $p2 = new awPoint(1 + floor($e->x - $pos * ($e->x - $d->x)), $i); 720 721 $this->driver->filledRectangle($color, new awLine($p1, $p2)); 722 723 unset($color); 724 725 } 726 727 } 728 729 function drawFilledTriangle($gradient, &$polygon) { 730 731 if($gradient->angle === 0) { 732 $this->drawFilledTriangleVertically($gradient, $polygon); 733 } elseif($gradient->angle === 90) { 734 $this->drawFilledTriangleHorizontally($gradient, $polygon); 735 } 736 737 } 738 739 function drawFilledTriangleVertically($gradient, &$polygon) { 740 list($yMin, $yMax) = $polygon->getBoxYRange(); 741 742 $this->init($gradient, $yMax - $yMin); 743 744 // Get the triangle line we will draw our lines from 745 $fromLine = NULL; 746 $lines = $polygon->getLines(); 747 748 $count = count($lines); 749 750 // Pick the side of the triangle going from the top 751 // to the bottom of the surrounding box 752 for($i = 0; $i < $count; $i++) { 753 if($lines[$i]->isTopToBottom($polygon)) { 754 list($fromLine) = array_splice($lines, $i, 1); 755 break; 756 } 757 } 758 759 // If for some reason the three points are aligned, 760 // $fromLine will still be NULL 761 if($fromLine === NULL) { 762 return; 763 } 764 765 $fillLine = NULL; 766 for($y = round($yMin); $y < round($yMax); $y++) { 767 768 $fromX = $fromLine->getXFrom($y); 769 770 $toX = array(); 771 foreach($lines as $line) { 772 $xValue = $line->getXFrom($y); 773 774 if(!is_null($xValue)) { 775 $toX[] = $xValue; 776 } 777 } 778 779 if(count($toX) === 1) { 780 $fillLine = new Line( 781 new Point($fromX, $y), 782 new Point($toX[0], $y) 783 ); 784 } else { 785 786 $line1 = new Line( 787 new Point($fromX, $y), 788 new Point($toX[0], $y) 789 ); 790 $line2 = new Line( 791 new Point($fromX, $y), 792 new Point($toX[1], $y) 793 ); 794 795 if($line1->getSize() < $line2->getSize()) { 796 $fillLine = $line1; 797 } else { 798 $fillLine = $line2; 799 } 800 } 801 802 if(!$fillLine->isPoint()) { 803 $color = $this->color($y - $yMin); 804 $this->driver->line($color, $fillLine); 805 806 unset($color); 807 } 808 } 809 810 } 811 812 function drawFilledTriangleHorizontally($gradient, &$polygon) { 813 list($xMin, $xMax) = $polygon->getBoxXRange(); 814 815 $this->init($gradient, $xMax - $xMin); 816 817 // Get the triangle line we will draw our lines from 818 $fromLine = NULL; 819 $lines = $polygon->getLines(); 820 821 $count = count($lines); 822 823 // Pick the side of the triangle going all the way 824 // from the left side to the right side of the surrounding box 825 for($i = 0; $i < $count; $i++) { 826 if($lines[$i]->isLeftToRight($polygon)) { 827 list($fromLine) = array_splice($lines, $i, 1); 828 break; 829 } 830 } 831 832 // If for some reason the three points are aligned, 833 // $fromLine will still be NULL 834 if($fromLine === NULL) { 835 return; 836 } 837 838 $fillLine = NULL; 839 for($x = round($xMin); $x < round($xMax); $x++) { 840 841 $fromY = floor($fromLine->getYFrom($x)); 842 843 $toY = array(); 844 foreach($lines as $line) { 845 $yValue = $line->getYFrom($x); 846 847 if(!is_null($yValue)) { 848 $toY[] = floor($yValue); 849 } 850 } 851 852 if(count($toY) === 1) { 853 $fillLine = new Line( 854 new Point($x, $fromY), 855 new Point($x, $toY[0]) 856 ); 857 } else { 858 859 $line1 = new Line( 860 new Point($x, $fromY), 861 new Point($x, $toY[0]) 862 ); 863 $line2 = new Line( 864 new Point($x, $fromY), 865 new Point($x, $toY[1]) 866 ); 867 868 if($line1->getSize() < $line2->getSize()) { 869 $fillLine = $line1; 870 } else { 871 $fillLine = $line2; 872 } 873 } 874 875 $color = $this->color($x - $xMin); 876 if($fillLine->isPoint()) { 877 $this->driver->point($color, $fillLine->p1); 878 } elseif($fillLine->getSize() >= 1) { 879 $this->driver->line($color, $fillLine); 880 } 881 unset($color); 882 } 883 884 } 885 886 function filledRectangle($gradient, $p1, $p2) { 887 888 list($x1, $y1) = $p1->getLocation(); 889 list($x2, $y2) = $p2->getLocation(); 890 891 if($y1 < $y2) { 892 $y1 ^= $y2 ^= $y1 ^= $y2; 893 } 894 895 if($x2 < $x1) { 896 $x1 ^= $x2 ^= $x1 ^= $x2; 897 } 898 899 if(is_a($gradient, 'awLinearGradient')) { 900 $this->rectangleLinearGradient($gradient, new awPoint($x1, $y1), new awPoint($x2, $y2)); 901 } else { 902 awImage::drawError("Class GDGradientDriver: This gradient is not supported by rectangles."); 903 } 904 905 } 906 907 function filledPolygon($gradient, &$polygon) { 908 909 if(is_a($gradient, 'awLinearGradient')) { 910 $this->polygonLinearGradient($gradient, $polygon); 911 } else { 912 awImage::drawError("Class GDGradientDriver: This gradient is not supported by polygons."); 913 } 914 915 } 916 917 function rectangleLinearGradient(&$gradient, $p1, $p2) { 918 919 list($x1, $y1) = $p1->getLocation(); 920 list($x2, $y2) = $p2->getLocation(); 921 922 if($y1 - $y2 > 0) { 923 924 if($gradient->angle === 0) { 925 926 $this->init($gradient, $y1 - $y2); 927 928 for($i = $y2; $i <= $y1; $i++) { 929 930 $color = $this->color($i - $y2); 931 932 $p1 = new awPoint($x1, $i); 933 $p2 = new awPoint($x2, $i); 934 935 $this->driver->filledRectangle($color, new awLine($p1, $p2)); 936 937 unset($color); 938 939 } 940 941 } else if($gradient->angle === 90) { 942 943 $this->init($gradient, $x2 - $x1); 944 945 for($i = $x1; $i <= $x2; $i++) { 946 947 $color = $this->color($i - $x1); 948 949 $p1 = new awPoint($i, $y2); 950 $p2 = new awPoint($i, $y1); 951 952 $this->driver->filledRectangle($color, new awLine($p1, $p2)); 953 954 unset($color); 955 956 } 957 958 } 959 960 } 961 962 } 963 964 function filledEllipse($gradient, $x1, $y1, $x2, $y2) { 965 966 if($y1 < $y2) { 967 $y1 ^= $y2 ^= $y1 ^= $y2; 968 } 969 970 if($x2 < $x1) { 971 $x1 ^= $x2 ^= $x1 ^= $x2; 972 } 973 974 if(is_a($gradient, 'awRadialGradient')) { 975 $this->ellipseRadialGradient($gradient, $x1, $y1, $x2, $y2); 976 } else if(is_a($gradient, 'awLinearGradient')) { 977 $this->ellipseLinearGradient($gradient, $x1, $y1, $x2, $y2); 978 } else { 979 awImage::drawError("Class GDGradientDriver: This gradient is not supported by ellipses."); 980 } 981 982 } 983 984 function ellipseRadialGradient($gradient, $x1, $y1, $x2, $y2) { 985 986 if($y1 - $y2 > 0) { 987 988 if($y1 - $y2 != $x2 - $x1) { 989 awImage::drawError("Class GDGradientDriver: Radial gradients are only implemented on circle, not ellipses."); 990 } 991 992 $c = new awPoint($x1 + ($x2 - $x1) / 2, $y1 + ($y2 - $y1) / 2); 993 $r = ($x2 - $x1) / 2; 994 $ok = array(); 995 996 // Init gradient 997 $this->init($gradient, $r); 998 999 for($i = 0; $i <= $r; $i += 0.45) { 1000 1001 $p = ceil((2 * M_PI * $i)); 1002 1003 if($p > 0) { 1004 $interval = 360 / $p; 1005 } else { 1006 $interval = 360; 1007 } 1008 1009 $color = $this->color($i); 1010 1011 for($j = 0; $j < 360; $j += $interval) { 1012 1013 $rad = ($j / 360) * (2 * M_PI); 1014 1015 $x = round($i * cos($rad)); 1016 $y = round($i * sin($rad)); 1017 1018 $l = sqrt($x * $x + $y * $y); 1019 1020 if($l <= $r) { 1021 1022 if( 1023 array_key_exists((int)$x, $ok) === FALSE or 1024 array_key_exists((int)$y, $ok[$x]) === FALSE 1025 ) { 1026 1027 // Print the point 1028 $this->driver->point($color, new awPoint($c->x + $x, $c->y + $y)); 1029 1030 $ok[(int)$x][(int)$y] = TRUE; 1031 1032 } 1033 1034 } 1035 1036 } 1037 1038 unset($color); 1039 1040 } 1041 1042 } 1043 1044 } 1045 1046 function ellipseLinearGradient($gradient, $x1, $y1, $x2, $y2) { 1047 1048 // Gauche->droite : 90° 1049 1050 if($y1 - $y2 > 0) { 1051 1052 if($y1 - $y2 != $x2 - $x1) { 1053 awImage::drawError("Class GDGradientDriver: Linear gradients are only implemented on circle, not ellipses."); 1054 } 1055 1056 $r = ($x2 - $x1) / 2; 1057 1058 // Init gradient 1059 $this->init($gradient, $x2 - $x1); 1060 1061 for($i = -$r; $i <= $r; $i++) { 1062 1063 $h = sin(acos($i / $r)) * $r; 1064 1065 $color = $this->color($i + $r); 1066 1067 if($gradient->angle === 90) { 1068 1069 // Print the line 1070 $p1 = new awPoint( 1071 $x1 + $i + $r, 1072 round(max($y2 + $r - $h + 1, $y2)) 1073 ); 1074 1075 $p2 = new awPoint( 1076 $x1 + $i + $r, 1077 round(min($y1 - $r + $h - 1, $y1)) 1078 ); 1079 1080 } else { 1081 1082 // Print the line 1083 $p1 = new awPoint( 1084 round(max($x1 + $r - $h + 1, $x1)), 1085 $y2 + $i + $r 1086 ); 1087 1088 $p2 = new awPoint( 1089 round(min($x2 - $r + $h - 1, $x2)), 1090 $y2 + $i + $r 1091 ); 1092 1093 } 1094 1095 $this->driver->filledRectangle($color, new awLine($p1, $p2)); 1096 1097 unset($color); 1098 1099 } 1100 1101 } 1102 1103 } 1104 1105 function polygonLinearGradient(&$gradient, &$polygon) { 1106 1107 $count = $polygon->count(); 1108 1109 if($count >= 4) { 1110 1111 $left = $polygon->get(0); 1112 $right = $polygon->get($count - 1); 1113 1114 if($gradient->angle === 0) { 1115 1116 // Get polygon maximum and minimum 1117 $offset = $polygon->get(0); 1118 $max = $min = $offset->y; 1119 for($i = 1; $i < $count - 1; $i++) { 1120 $offset = $polygon->get($i); 1121 $max = max($max, $offset->y); 1122 $min = min($min, $offset->y); 1123 } 1124 1125 $this->init($gradient, $max - $min); 1126 1127 $prev = $polygon->get(1); 1128 1129 $sum = 0; 1130 1131 for($i = 2; $i < $count - 1; $i++) { 1132 1133 $current = $polygon->get($i); 1134 1135 $interval = 1; 1136 1137 if($i !== $count - 2) { 1138 $current->x -= $interval; 1139 } 1140 1141 if($current->x - $prev->x > 0) { 1142 1143 // Draw rectangle 1144 $x1 = $prev->x; 1145 $x2 = $current->x; 1146 $y1 = max($prev->y, $current->y); 1147 $y2 = $left->y; 1148 1149 $gradient = new awLinearGradient( 1150 $this->color($max - $min - ($y2 - $y1)), 1151 $this->color($max - $min), 1152 0 1153 ); 1154 1155 if($y1 > $y2) { 1156 $y2 = $y1; 1157 } 1158 1159 $this->driver->filledRectangle( 1160 $gradient, 1161 awLine::build($x1, $y1, $x2, $y2) 1162 ); 1163 1164 $top = ($prev->y < $current->y) ? $current : $prev; 1165 $bottom = ($prev->y >= $current->y) ? $current : $prev; 1166 1167 $gradient = new awLinearGradient( 1168 $this->color($bottom->y - $min), 1169 $this->color($max - $min - ($y2 - $y1)), 1170 0 1171 ); 1172 1173 1174 $gradientDriver = new awGDGradientDriver($this->driver); 1175 $gradientDriver->drawFilledFlatTriangle( 1176 $gradient, 1177 new awPoint($prev->x, min($prev->y, $current->y)), 1178 $top, 1179 new awPoint($current->x, min($prev->y, $current->y)) 1180 ); 1181 unset($gradientDriver); 1182 1183 $sum += $current->x - $prev->x; 1184 1185 } 1186 1187 $prev = $current; 1188 $prev->x += $interval; 1189 1190 } 1191 1192 } else if($gradient->angle === 90) { 1193 1194 $width = $right->x - $left->x; 1195 $this->init($gradient, $width); 1196 1197 $pos = 1; 1198 $next = $polygon->get($pos++); 1199 1200 $this->next($polygon, $pos, $prev, $next); 1201 1202 for($i = 0; $i <= $width; $i++) { 1203 1204 $x = $left->x + $i; 1205 1206 $y1 = round($prev->y + ($next->y - $prev->y) * (($i + $left->x - $prev->x) / ($next->x - $prev->x))); 1207 $y2 = $left->y; 1208 1209 // Draw line 1210 $color = $this->color($i); 1211 // YaPB : PHP does not handle alpha on lines 1212 $this->driver->filledRectangle($color, awLine::build($x, $y1, $x, $y2)); 1213 1214 unset($color); 1215 1216 // Jump to next point 1217 if($next->x == $i + $left->x) { 1218 1219 $this->next($polygon, $pos, $prev, $next); 1220 1221 } 1222 1223 } 1224 1225 } 1226 1227 } else if($count === 3) { 1228 $this->drawFilledTriangle( 1229 $gradient, 1230 $polygon 1231 ); 1232 } 1233 1234 } 1235 1236 function next($polygon, &$pos, &$prev, &$next) { 1237 1238 do { 1239 $prev = $next; 1240 $next = $polygon->get($pos++); 1241 } 1242 while($next->x - $prev->x == 0 and $pos < $polygon->count()); 1243 1244 } 1245 1246 /** 1247 * Start colors 1248 * 1249 * @var int 1250 */ 1251 var $r1, $g1, $b1, $a1; 1252 1253 /** 1254 * Stop colors 1255 * 1256 * @var int 1257 */ 1258 var $r2, $g2, $b2, $a2; 1259 1260 /** 1261 * Gradient size in pixels 1262 * 1263 * @var int 1264 */ 1265 var $size; 1266 1267 1268 function init($gradient, $size) { 1269 1270 list( 1271 $this->r1, $this->g1, $this->b1, $this->a1 1272 ) = $gradient->from->rgba(); 1273 1274 list( 1275 $this->r2, $this->g2, $this->b2, $this->a2 1276 ) = $gradient->to->rgba(); 1277 1278 $this->size = $size; 1279 } 1280 1281 function color($pos) { 1282 1283 return new awColor( 1284 $this->getRed($pos), 1285 $this->getGreen($pos), 1286 $this->getBlue($pos), 1287 $this->getAlpha($pos) 1288 ); 1289 1290 } 1291 1292 1293 function getRed($pos) { 1294 if((float)$this->size !== 0.0) { 1295 return (int)round($this->r1 + ($pos / $this->size) * ($this->r2 - $this->r1)); 1296 } else { 1297 return 0; 1298 } 1299 } 1300 1301 function getGreen($pos) { 1302 if((float)$this->size !== 0.0) { 1303 return (int)round($this->g1 + ($pos / $this->size) * ($this->g2 - $this->g1)); 1304 } else { 1305 return 0; 1306 } 1307 } 1308 1309 function getBlue($pos) { 1310 if((float)$this->size !== 0.0) { 1311 return (int)round($this->b1 + ($pos / $this->size) * ($this->b2 - $this->b1)); 1312 } else { 1313 return 0; 1314 } 1315 } 1316 1317 function getAlpha($pos) { 1318 if((float)$this->size !== 0.0) { 1319 return (int)round(($this->a1 + ($pos / $this->size) * ($this->a2 - $this->a1)) / 127 * 100); 1320 } else { 1321 return 0; 1322 } 1323 } 1324 1325 } 1326 1327 registerClass('GDGradientDriver'); 1328 1329 /* 1330 * Check for GD2 1331 */ 1332 if(function_exists('imagecreatetruecolor') === FALSE) { 1333 awImage::drawErrorFile('missing-gd2'); 1334 } 1335 1336 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Sep 6 14:14:11 2007 | par Balluche grâce à PHPXref 0.7 |