Source for file gd.class.php
Documentation is available at gd.class.php 
 * This work is hereby released into the Public Domain.  
 * To view a copy of the public domain dedication,  
 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to  
 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.  
require_once dirname(__FILE__ ). "/../Driver.class.php";  
 * @package linea21.externals  
    $this->driverString =  'gd';  
  public function init(awImage $image) {  
      // Antialiasing is now handled by the Driver object  
      new awPoint($this->imageWidth, $this->imageHeight)  
      $shadow =  $image->shadow;  
        $shadow =  $shadow->getSpace();  
        $p1 =  new awPoint($shadow->left, $shadow->top);  
        $p2 =  new awPoint($this->imageWidth -  $shadow->right -  1, $this->imageHeight -  $shadow->bottom -  1);  
        $image->border->rectangle($this, $p1, $p2);  
  public function initFromFile(awFileImage $fileImage, $file) {  
    if($image and in_array($image[2], array(2, 3))) {  
      $fileImage->setSize($image[0], $image[1]);  
      awImage::drawError("Class FileImage: Artichow does not support the format of this image (must be in PNG or JPEG)");  
    $this->imageWidth =  $width;  
    $this->imageHeight =  $height;  
    // Calculate absolute position  
    $this->x =  round($x *  $this->imageWidth -  $this->w /  2);  
    $this->y =  round($y *  $this->imageHeight -  $this->h /  2);  
    $this->w =  round($w *  $this->imageWidth);  
    $this->h =  round($h *  $this->imageHeight);  
    return array($this->w, $this->h);  
      imageantialias($this->resource, (bool) $bool);  
      $this->antiAliasing = (bool) $bool;  
    } elseif($bool ==  true) {  
  public function getColor(awColor $color) {  
    if($color->alpha ===  0 or function_exists('imagecolorallocatealpha') ===  FALSE) {  
  public function copyImage(awImage $image, awPoint $p1, awPoint $p2) {  
    list ($x1, $y1) =  $p1->getLocation(); 
    list ($x2, $y2) =  $p2->getLocation(); 
    $driver =  $image->getDriver();  
    imagecopy($this->resource, $driver->resource, $this->x +  $x1, $this->y +  $y1, 0, 0, $x2 -  $x1, $y2 -  $y1);  
  public function copyResizeImage(awImage $image, awPoint $d1, awPoint $d2, awPoint $s1, awPoint $s2, $resample =  TRUE) {  
      $function =  'imagecopyresampled';  
      $function =  'imagecopyresized';  
    $driver =  $image->getDriver();  
    $this->x +  $d1->x, $this->y +  $d1->y,  
    $d2->x -  $d1->x, $d2->y -  $d1->y,  
    $s2->x -  $s1->x, $s2->y -  $s1->y  
  public function string(awText $text, awPoint $point, $width =  NULL) {  
    $font =  $text->getFont();  
    // Can we deal with that font?  
    if($this->isCompatibleWithFont($font) === FALSE) {  
    awImage::drawError('Class GDDriver: Incompatible font type (\''.get_class($font).'\')');  
    // Check which FontDriver to use  
      $fontDriver =  $this->phpFontDriver;  
      $fontDriver =  $this->fileFontDriver;  
    if($text->getBackground() !==  NULL or $text->border->visible()) {  
      list ($left, $right, $top, $bottom) =  $text->getPadding(); 
      $textWidth =  $fontDriver->getTextWidth($text, $this);  
      $textHeight =  $fontDriver->getTextHeight($text, $this);  
      $x1 =  floor($point->x -  $left);  
      $y1 =  floor($point->y -  $top);  
      $x2 =  $x1 +  $textWidth +  $left +  $right;  
      $y2 =  $y1 +  $textHeight +  $top +  $bottom;  
      $text->border->rectangle(  
    $fontDriver->string($this, $text, $point, $width);  
  public function point(awColor $color, awPoint $p) {  
    if($p->isHidden() ===  FALSE) {  
  public function line(awColor $color, awLine $line) {  
    if($line->thickness >  0 and $line->isHidden() ===  FALSE) {  
      $thickness =  $line->thickness;  
      list ($p1, $p2) =  $line->getLocation(); 
      $this->startThickness($thickness);  
      switch($line->getStyle()) {  
          $size =  sqrt(pow($p2->y -  $p1->y, 2) +  pow($p2->x -  $p1->x, 2));  
          $cos =  ($p2->x -  $p1->x) /  $size;  
          $sin =  ($p2->y -  $p1->y) /  $size;  
          for($i =  0; $i <=  $size; $i +=  2) {  
            round($i *  $cos +  $p1->x),  
            round($i *  $sin +  $p1->y)  
            $this->point($color, $p);  
          $width =  $p2->x -  $p1->x;  
          $height =  $p2->y -  $p1->y;  
          $functionX =  ($width  >  0) ?  'min' :  'max';  
          $functionY =  ($height >  0) ?  'min' :  'max';  
          for($i =  0; $i <=  $size; $i +=  6) {  
            round($i *  $cos +  $p1->x),  
            round($i *  $sin +  $p1->y)  
            round($functionX(($i +  3) *  $cos, $width) +  $p1->x),  
            round($functionY(($i +  3) *  $sin, $height) +  $p1->y)  
      $this->stopThickness($thickness);  
  public function arc(awColor $color, awPoint $center, $width, $height, $from, $to) {  
    $this->x +  $center->x, $this->y +  $center->y,  
    IMG_ARC_EDGED |  IMG_ARC_NOFILL  
  public function filledArc(awColor $color, awPoint $center, $width, $height, $from, $to) {  
    $this->x +  $center->x, $this->y +  $center->y,  
  public function ellipse(awColor $color, awPoint $center, $width, $height) {  
    list ($x, $y) =  $center->getLocation(); 
  public function filledEllipse($background, awPoint $center, $width, $height) {  
    if($background instanceof  awColor) {  
      list ($x, $y) =  $center->getLocation(); 
      list ($x, $y) =  $center->getLocation(); 
      $x1 =  $x -  round($width /  2);  
      $y1 =  $y -  round($height /  2);  
      $gradientDriver->filledEllipse(  
  public function rectangle(awColor $color, awLine $line) {  
    list ($p1, $p2) =  $line->getLocation(); 
    switch($line->getStyle()) {  
        $thickness =  $line->getThickness();  
        $this->startThickness($thickness);  
        imagerectangle($this->resource, $this->x +  $p1->x, $this->y +  $p1->y, $this->x +  $p2->x, $this->y +  $p2->y, $rgb);  
        $this->stopThickness($thickness);  
         $side = new Line($p1, $p2);  
        $this->line($color, $side);  
        $this->line($color, $side);  
        $this->line($color, $side);  
        $this->line($color, $side);  
    if($background instanceof  awColor) {  
      $gradientDriver->filledRectangle($background, $p1, $p2);  
  public function polygon(awColor $color, awPolygon $polygon) {  
    switch($polygon->getStyle()) {  
        $thickness =  $polygon->getThickness();  
        $this->startThickness($thickness);  
        $points =  $this->getPolygonPoints($polygon);  
        $this->stopThickness($thickness);  
        if($polygon->count() >  1) {  
          $prev =  $polygon->get(0);  
          $line->setStyle($polygon->getStyle());  
          $line->setThickness($polygon->getThickness());  
          for($i =  1; $i <  $polygon->count(); $i++ ) {  
            $current =  $polygon->get($i);  
            $line->setLocation($prev, $current);  
            $this->line($color, $line);  
          $line->setLocation($prev, $polygon->get(0));  
          $this->line($color, $line);  
    if($background instanceof  awColor) {  
      $points =  $this->getPolygonPoints($polygon);  
      $gradientDriver->filledPolygon($background, $polygon);  
  public function send(awImage $image) {  
    $this->drawImage($image);  
  public function get(awImage $image) {  
    return $this->drawImage($image, TRUE, FALSE);  
    $font =  $text->getFont();  
      $fontDriver =  $this->phpFontDriver;  
      $fontDriver =  $this->fileFontDriver;  
    return $fontDriver->getTextWidth($text, $this);  
    $font =  $text->getFont();  
      $fontDriver =  $this->phpFontDriver;  
      $fontDriver =  $this->fileFontDriver;  
    return $fontDriver->getTextHeight($text, $this);  
    if($font instanceof  awFDBFont) {  
  private function drawImage(awImage $image, $return =  FALSE, $header =  TRUE) {  
    $format =  $image->getFormatString();  
    // Test if format is available  
    if((imagetypes() & $image->getFormat()) ===  FALSE) {  
      awImage::drawError("Class Image: Format '". $format. "' is not available on your system. Check that your PHP has been compiled with the good libraries.");  
    // Get some infos about this image  
    // Send headers to the browser  
  private function getPolygonPoints(awPolygon $polygon) {  
    foreach($polygon->all() as $point) {  
      $points[] =  $point->x +  $this->x;  
      $points[] =  $point->y +  $this->y;  
  private function startThickness($thickness) {  
  private function stopThickness($thickness) {  
 * @package linea21.externals  
   * Build your GDGradientDriver  
   * @var awGDDriver $driver   
    if($gradient->angle !==  0) {  
      awImage::drawError("Class GDGradientDriver: Flat triangles can only be used with 0 degree gradients.");  
    // Look for right-angled triangle  
    if($a->x !==  $b->x and $b->x !==  $c->x) {  
      awImage::drawError("Class GDGradientDriver: Not right-angled flat triangles are not supported yet.");  
    $this->init($gradient, $b->y -  $d->y);  
    for($i =  $c->y +  1; $i <  $b->y; $i++ ) {  
      $color =  $this->color($i -  $d->y);  
      $pos =  ($i -  $d->y) /  ($b->y -  $d->y);  
      $p2 =  new awPoint(1 +  floor($e->x -  $pos *  ($e->x -  $d->x)), $i);  
    if($gradient->angle ===  0) {  
      $this->drawFilledTriangleVertically($gradient, $polygon);  
    } elseif($gradient->angle ===  90) {  
      $this->drawFilledTriangleHorizontally($gradient, $polygon);  
  private function drawFilledTriangleVertically(awGradient $gradient, awPolygon $polygon) {  
    list ($yMin, $yMax) =  $polygon->getBoxYRange(); 
    $this->init($gradient, $yMax -  $yMin);  
    // Get the triangle line we will draw our lines from  
    $lines =  $polygon->getLines();  
    // Pick the side of the triangle going from the top  
    // to the bottom of the surrounding box  
    for($i =  0; $i <  $count; $i++ ) {  
      if($lines[$i]->isTopToBottom($polygon)) {  
    // If for some reason the three points are aligned,  
    // $fromLine will still be NULL  
      $fromX =  $fromLine->getXFrom($y);  
      foreach($lines as $line) {  
        $xValue =  $line->getXFrom($y);  
        if($line1->getSize() <  $line2->getSize()) {  
      if(!$fillLine->isPoint()) {  
        $color =  $this->color($y -  $yMin);  
  private function drawFilledTriangleHorizontally(awGradient $gradient, awPolygon $polygon) {  
    list ($xMin, $xMax) =  $polygon->getBoxXRange(); 
    $this->init($gradient, $xMax -  $xMin);  
    // Get the triangle line we will draw our lines from  
    $lines =  $polygon->getLines();  
    // Pick the side of the triangle going all the way  
    // from the left side to the right side of the surrounding box  
    for($i =  0; $i <  $count; $i++ ) {  
      if($lines[$i]->isLeftToRight($polygon)) {  
    // If for some reason the three points are aligned,  
    // $fromLine will still be NULL  
      $fromY =  floor($fromLine->getYFrom($x));  
      foreach($lines as $line) {  
        $yValue =  $line->getYFrom($x);  
        if($line1->getSize() <  $line2->getSize()) {  
      $color =  $this->color($x -  $xMin);  
      if($fillLine->isPoint()) {  
      } elseif($fillLine->getSize() >=  1) {  
  public function filledRectangle(awGradient $gradient, awPoint $p1, awPoint $p2) {  
    list ($x1, $y1) =  $p1->getLocation(); 
    list ($x2, $y2) =  $p2->getLocation(); 
      $y1 ^=  $y2 ^=  $y1 ^=  $y2;  
      $x1 ^=  $x2 ^=  $x1 ^=  $x2;  
      awImage::drawError("Class GDGradientDriver: This gradient is not supported by rectangles.");  
  public function filledPolygon(awGradient $gradient, awPolygon $polygon) {  
      awImage::drawError("Class GDGradientDriver: This gradient is not supported by polygons.");  
    list ($x1, $y1) =  $p1->getLocation(); 
    list ($x2, $y2) =  $p2->getLocation(); 
      if($gradient->angle ===  0) {  
        $this->init($gradient, $y1 -  $y2);  
        for($i =  $y2; $i <=  $y1; $i++ ) {  
          $color =  $this->color($i -  $y2);  
      } else if($gradient->angle ===  90) {  
        $this->init($gradient, $x2 -  $x1);  
        for($i =  $x1; $i <=  $x2; $i++ ) {  
          $color =  $this->color($i -  $x1);  
  public function filledEllipse(awGradient $gradient, $x1, $y1, $x2, $y2) {  
      $y1 ^=  $y2 ^=  $y1 ^=  $y2;  
      $x1 ^=  $x2 ^=  $x1 ^=  $x2;  
      awImage::drawError("Class GDGradientDriver: This gradient is not supported by ellipses.");  
      if($y1 -  $y2 !=  $x2 -  $x1) {  
        awImage::drawError("Class GDGradientDriver: Radial gradients are only implemented on circle, not ellipses.");  
      $c =  new awPoint($x1 +  ($x2 -  $x1) /  2, $y1 +  ($y2 -  $y1) /  2);  
      $this->init($gradient, $r);  
      for($i =  0; $i <=  $r; $i +=  0.45) {  
        $p =  ceil((2 *  M_PI *  $i));  
        $color =  $this->color($i);  
        for($j =  0; $j <  360; $j +=  $interval) {  
          $rad =  ($j /  360) *  (2 *  M_PI);  
          $l =  sqrt($x *  $x +  $y *  $y);  
              $ok[(int) $x][(int) $y] =  TRUE;  
      if($y1 -  $y2 !=  $x2 -  $x1) {  
        awImage::drawError("Class GDGradientDriver: Linear gradients are only implemented on circle, not ellipses.");  
      $this->init($gradient, $x2 -  $x1);  
      for($i = - $r; $i <=  $r; $i++ ) {  
        $color =  $this->color($i +  $r);  
        if($gradient->angle ===  90) {  
    $count =  $polygon->count();  
      $left =  $polygon->get(0);  
      $right =  $polygon->get($count -  1);  
      if($gradient->angle ===  0) {  
        // Get polygon maximum and minimum  
        $offset =  $polygon->get(0);  
        $max =  $min =  $offset->y;  
        for($i =  1; $i <  $count -  1; $i++ ) {  
          $offset =  $polygon->get($i);  
          $max =  max($max, $offset->y);  
          $min =  min($min, $offset->y);  
        $this->init($gradient, $max -  $min);  
        $prev =  $polygon->get(1);  
        for($i =  2; $i <  $count -  1; $i++ ) {  
          $current =  $polygon->get($i);  
            $current->x -=  $interval;  
          if($current->x -  $prev->x >  0) {  
            $y1 =  max($prev->y, $current->y);  
            $this->color($max -  $min -  ($y2 -  $y1)),  
            $this->color($max -  $min),  
            $top =  ($prev->y <  $current->y) ?  $current :  $prev;  
            $bottom =  ($prev->y >=  $current->y) ?  $current :  $prev;  
            $this->color($bottom->y -  $min),  
            $this->color($max -  $min -  ($y2 -  $y1)),  
            $gradientDriver->drawFilledFlatTriangle(  
            new awPoint($prev->x, min($prev->y, $current->y)),  
            new awPoint($current->x, min($prev->y, $current->y))  
            $sum +=  $current->x -  $prev->x;  
      } else if($gradient->angle ===  90) {  
        $width =  $right->x -  $left->x;  
        $this->init($gradient, $width);  
        $next =  $polygon->get($pos++ );  
        $this->next($polygon, $pos, $prev, $next);  
        for($i =  0; $i <=  $width; $i++ ) {  
          $y1 =  round($prev->y +  ($next->y -  $prev->y) *  (($i +  $left->x -  $prev->x) /  ($next->x -  $prev->x)));  
          $color =  $this->color($i);  
          // YaPB : PHP does not handle alpha on lines  
          if($next->x ==  $i +  $left->x) {  
            $this->next($polygon, $pos, $prev, $next);  
    } else if($count ===  3) {  
  private function next($polygon, &$pos, &$prev, &$next) {  
      $next =  $polygon->get($pos++ );  
    while($next->x -  $prev->x ==  0 and $pos <  $polygon->count());  
  private $r1, $g1, $b1, $a1;  
  private $r2, $g2, $b2, $a2;  
   * Gradient size in pixels  
  private function init(awGradient $gradient, $size) {  
    $this->r1, $this->g1, $this->b1, $this->a1  
    ) =  $gradient->from->rgba();  
    $this->r2, $this->g2, $this->b2, $this->a2  
    ) =  $gradient->to->rgba();  
  private function color($pos) {  
  private function getRed($pos) {  
    if((float) $this->size !==  0.0) {  
      return (int) round($this->r1 +  ($pos /  $this->size) *  ($this->r2 -  $this->r1));  
  private function getGreen($pos) {  
    if((float) $this->size !==  0.0) {  
      return (int) round($this->g1 +  ($pos /  $this->size) *  ($this->g2 -  $this->g1));  
  private function getBlue($pos) {  
    if((float) $this->size !==  0.0) {  
      return (int) round($this->b1 +  ($pos /  $this->size) *  ($this->b2 -  $this->b1));  
  private function getAlpha($pos) {  
    if((float) $this->size !==  0.0) {  
      return (int) round(($this->a1 +  ($pos /  $this->size) *  ($this->a2 -  $this->a1)) /  127 *  100);  
 
 
        
       |