vendor/amenadiel/jpgraph/src/image/Image.php line 1204

  1. <?php
  2. /**
  3.  * JPGraph v4.0.3
  4.  */
  5. namespace Amenadiel\JpGraph\Image;
  6. use Amenadiel\JpGraph\Text\LanguageConv;
  7. use Amenadiel\JpGraph\Text\TTF;
  8. use Amenadiel\JpGraph\Util;
  9. use Amenadiel\JpGraph\Util\ErrMsgText;
  10. // load fonts only once, and define a constant for them
  11. define("GD_FF_FONT0"imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT0.gdf'));
  12. define("GD_FF_FONT1"imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT1.gdf'));
  13. define("GD_FF_FONT2"imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT2.gdf'));
  14. define("GD_FF_FONT1_BOLD"imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT1-Bold.gdf'));
  15. define("GD_FF_FONT2_BOLD"imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT2-Bold.gdf'));
  16. /**
  17.  * File:        GD_IMAGE.INC.PHP
  18.  * // Description: PHP Graph Plotting library. Low level image drawing routines
  19.  * // Created:     2001-01-08, refactored 2008-03-29
  20.  * // Ver:         $Id: gd_image.inc.php 1922 2010-01-11 11:42:50Z ljp $
  21.  * //
  22.  * // Copyright (c) Asial Corporation. All rights reserved.
  23.  */
  24. /**
  25.  * @class Image
  26.  * // Description: The very coor image drawing class that encapsulates all
  27.  * //              calls to the GD library
  28.  * //              Note: The class used by the library is the decendant
  29.  * //              class RotImage which extends the Image class with transparent
  30.  * //              rotation.
  31.  */
  32. class Image
  33. {
  34.     public $img;
  35.     public $rgb;
  36.     public $img_format;
  37.     public $ttf;
  38.     public $line_style LINESTYLE_SOLID;
  39.     public $current_color;
  40.     public $current_color_name;
  41.     public $original_width  0;
  42.     public $original_height 0;
  43.     public $plotwidth       0;
  44.     public $plotheight      0;
  45.     // for __get, __set
  46.     private $_left_margin   30;
  47.     private $_right_margin  30;
  48.     private $_top_margin    20;
  49.     private $_bottom_margin 30;
  50.     //private $_plotwidth=0,$_plotheight=0;
  51.     private $_width       0;
  52.     private $_height      0;
  53.     private $_line_weight 1;
  54.     protected $expired           true;
  55.     protected $lastx             0;
  56.     protected $lasty             0;
  57.     protected $obs_list          = [];
  58.     protected $font_size         12;
  59.     protected $font_family       FF_DEFAULT;
  60.     protected $font_style        FS_NORMAL;
  61.     protected $font_file         '';
  62.     protected $text_halign       'left';
  63.     protected $text_valign       'bottom';
  64.     protected $use_anti_aliasing false;
  65.     protected $quality;
  66.     protected $colorstack    = [];
  67.     protected $colorstackidx 0;
  68.     protected $canvascolor   'white';
  69.     protected $langconv;
  70.     protected $iInterlace false;
  71.     protected $bbox_cache = []; // STore the last found tetx bounding box
  72.     protected $ff_font0;
  73.     protected $ff_font0_bold;
  74.     protected $ff_font1;
  75.     protected $ff_font1_bold;
  76.     protected $ff_font2;
  77.     protected $ff_font2_bold;
  78.     /**
  79.      * CONSTRUCTOR.
  80.      *
  81.      * @param mixed $aWidth
  82.      * @param mixed $aHeight
  83.      * @param mixed $aFormat
  84.      * @param mixed $aSetAutoMargin
  85.      */
  86.     public function __construct($aWidth 0$aHeight 0$aFormat DEFAULT_GFORMAT$aSetAutoMargin true)
  87.     {
  88.         $this->original_width  $aWidth;
  89.         $this->original_height $aHeight;
  90.         $this->CreateImgCanvas($aWidth$aHeight);
  91.         if ($aSetAutoMargin) {
  92.             $this->SetAutoMargin();
  93.         }
  94.         if (!$this->SetImgFormat($aFormat)) {
  95.             Util\JpGraphError::RaiseL(25081$aFormat); //("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]");
  96.         }
  97.         $this->ttf      = new TTF();
  98.         $this->langconv = new LanguageConv();
  99.         $this->ff_font0 =  GD_FF_FONT0;
  100.         $this->ff_font1 =  GD_FF_FONT1;
  101.         $this->ff_font2 =  GD_FF_FONT2;
  102.         $this->ff_font1_bold =  GD_FF_FONT1_BOLD;
  103.         $this->ff_font2_bold =  GD_FF_FONT2_BOLD;
  104.     }
  105.     // Enable interlacing in images
  106.     public function SetInterlace($aFlg true)
  107.     {
  108.         $this->iInterlace $aFlg;
  109.     }
  110.     // Should we use anti-aliasing. Note: This really slows down graphics!
  111.     public function SetAntiAliasing($aFlg true)
  112.     {
  113.         $this->use_anti_aliasing $aFlg;
  114.         if (function_exists('imageantialias')) {
  115.             imageantialias($this->img$aFlg);
  116.         } /*else {
  117.     Util\JpGraphError::RaiseL(25128); //('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.')
  118.     }*/
  119.     }
  120.     public function GetAntiAliasing()
  121.     {
  122.         return $this->use_anti_aliasing;
  123.     }
  124.     public function CreateRawCanvas($aWidth 0$aHeight 0)
  125.     {
  126.         $aWidth *= SUPERSAMPLING_SCALE;
  127.         $aHeight *= SUPERSAMPLING_SCALE;
  128.         if ($aWidth <= || $aHeight <= 1) {
  129.             Util\JpGraphError::RaiseL(25082$aWidth$aHeight); //("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)");
  130.         }
  131.         $this->img = @imagecreatetruecolor($aWidth$aHeight);
  132.         if ($this->img === false) {
  133.             Util\JpGraphError::RaiseL(25126);
  134.             //die("Can't create truecolor image. Check that you really have GD2 library installed.");
  135.         }
  136.         $this->SetAlphaBlending();
  137.         if ($this->iInterlace) {
  138.             imageinterlace($this->img1);
  139.         }
  140.         if ($this->rgb != null) {
  141.             $this->rgb->img $this->img;
  142.         } else {
  143.             $this->rgb = new RGB($this->img);
  144.         }
  145.     }
  146.     public function CloneCanvasH()
  147.     {
  148.         $oldimage $this->img;
  149.         $this->CreateRawCanvas($this->width$this->height);
  150.         imagecopy($this->img$oldimage0000$this->width$this->height);
  151.         return $oldimage;
  152.     }
  153.     public function CreateImgCanvas($aWidth 0$aHeight 0)
  154.     {
  155.         $old = [$this->img$this->width$this->height];
  156.         $aWidth  round($aWidth);
  157.         $aHeight round($aHeight);
  158.         $this->width  $aWidth;
  159.         $this->height $aHeight;
  160.         if ($aWidth == || $aHeight == 0) {
  161.             // We will set the final size later.
  162.             // Note: The size must be specified before any other
  163.             // img routines that stroke anything are called.
  164.             $this->img null;
  165.             $this->rgb null;
  166.             return $old;
  167.         }
  168.         $this->CreateRawCanvas($aWidth$aHeight);
  169.         // Set canvas color (will also be the background color for a
  170.         // a pallett image
  171.         $this->SetColor($this->canvascolor);
  172.         $this->FilledRectangle(00$this->width 1$this->height 1);
  173.         return $old;
  174.     }
  175.     public function CopyCanvasH($aToHdl$aFromHdl$aToX$aToY$aFromX$aFromY$aWidth$aHeight$aw = -1$ah = -1)
  176.     {
  177.         if ($aw === -1) {
  178.             $aw $aWidth;
  179.             $ah $aHeight;
  180.             $f  'imagecopyresized';
  181.         } else {
  182.             $f 'imagecopyresampled';
  183.         }
  184.         $f($aToHdl$aFromHdl$aToX$aToY$aFromX$aFromY$aWidth$aHeight$aw$ah);
  185.     }
  186.     public function Copy($fromImg$toX$toY$fromX$fromY$toWidth$toHeight$fromWidth = -1$fromHeight = -1)
  187.     {
  188.         $this->CopyCanvasH($this->img$fromImg$toX$toY$fromX$fromY$toWidth$toHeight$fromWidth$fromHeight);
  189.     }
  190.     public function CopyMerge($fromImg$toX$toY$fromX$fromY$toWidth$toHeight$fromWidth = -1$fromHeight = -1$aMix 100)
  191.     {
  192.         if ($aMix == 100) {
  193.             $this->CopyCanvasH(
  194.                 $this->img,
  195.                 $fromImg,
  196.                 $toX,
  197.                 $toY,
  198.                 $fromX,
  199.                 $fromY,
  200.                 $toWidth,
  201.                 $toHeight,
  202.                 $fromWidth,
  203.                 $fromHeight
  204.             );
  205.         } else {
  206.             if (($fromWidth != -&& ($fromWidth != $toWidth)) || ($fromHeight != -&& ($fromHeight != $fromHeight))) {
  207.                 // Create a new canvas that will hold the re-scaled original from image
  208.                 if ($toWidth <= || $toHeight <= 1) {
  209.                     Util\JpGraphError::RaiseL(25083); //('Illegal image size when copying image. Size for copied to image is 1 pixel or less.');
  210.                 }
  211.                 $tmpimg = @imagecreatetruecolor($toWidth$toHeight);
  212.                 if ($tmpimg 1) {
  213.                     Util\JpGraphError::RaiseL(25084); //('Failed to create temporary GD canvas. Out of memory ?');
  214.                 }
  215.                 $this->CopyCanvasH(
  216.                     $tmpimg,
  217.                     $fromImg,
  218.                     0,
  219.                     0,
  220.                     0,
  221.                     0,
  222.                     $toWidth,
  223.                     $toHeight,
  224.                     $fromWidth,
  225.                     $fromHeight
  226.                 );
  227.                 $fromImg $tmpimg;
  228.             }
  229.             imagecopymerge($this->img$fromImg$toX$toY$fromX$fromY$toWidth$toHeight$aMix);
  230.         }
  231.     }
  232.     public static function GetWidth($aImg null)
  233.     {
  234.         if ($aImg === null) {
  235.             $aImg $this->img;
  236.         }
  237.         return imagesx($aImg);
  238.     }
  239.     public static function GetHeight($aImg null)
  240.     {
  241.         if ($aImg === null) {
  242.             $aImg $this->img;
  243.         }
  244.         return imagesy($aImg);
  245.     }
  246.     public static function CreateFromString($aStr)
  247.     {
  248.         $img imagecreatefromstring($aStr);
  249.         if ($img === false) {
  250.             Util\JpGraphError::RaiseL(25085);
  251.             //('An image can not be created from the supplied string. It is either in a format not supported or the string is representing an corrupt image.');
  252.         }
  253.         return $img;
  254.     }
  255.     public function SetCanvasH($aHdl)
  256.     {
  257.         $this->img      $aHdl;
  258.         $this->rgb->img $aHdl;
  259.     }
  260.     public function SetCanvasColor($aColor)
  261.     {
  262.         $this->canvascolor $aColor;
  263.     }
  264.     public function SetAlphaBlending($aFlg true)
  265.     {
  266.         imagealphablending($this->img$aFlg);
  267.     }
  268.     public function SetAutoMargin()
  269.     {
  270.         $min_bm 5;
  271.         $lm     min(40$this->width 7);
  272.         $rm     min(20$this->width 10);
  273.         $tm     max(5$this->height 7);
  274.         $bm     max($min_bm$this->height 6);
  275.         $this->SetMargin($lm$rm$tm$bm);
  276.     }
  277.     /**
  278.      * PUBLIC METHODS.
  279.      *
  280.      * @param mixed $family
  281.      * @param mixed $style
  282.      * @param mixed $size
  283.      */
  284.     public function SetFont($family$style FS_NORMAL$size 10)
  285.     {
  286.         $this->font_family $family;
  287.         $this->font_style  $style;
  288.         $this->font_size   $size SUPERSAMPLING_SCALE;
  289.         $this->font_file   '';
  290.         if (($this->font_family == FF_FONT1 || $this->font_family == FF_FONT2) && $this->font_style == FS_BOLD) {
  291.             ++$this->font_family;
  292.         }
  293.         if ($this->font_family FF_FONT2 1) {
  294.             // A TTF font so get the font file
  295.             // Check that this PHP has support for TTF fonts
  296.             if (!function_exists('imagettfbbox')) {
  297.                 // use internal font when php is configured without '--with-ttf'
  298.                 $this->font_family FF_FONT1;
  299.             //  Util\JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.');
  300.             } else {
  301.                 $this->font_file $this->ttf->File($this->font_family$this->font_style);
  302.             }
  303.         }
  304.     }
  305.     // Get the specific height for a text string
  306.     public function GetTextHeight($txt ''$angle 0)
  307.     {
  308.         $tmp preg_split('/\n/'$txt);
  309.         $n   safe_count($tmp);
  310.         $m   0;
  311.         for ($i 0$i $n; ++$i) {
  312.             $m max($mstrlen($tmp[$i]));
  313.         }
  314.         if ($this->font_family <= FF_FONT2 1) {
  315.             if ($angle == 0) {
  316.                 $h imagefontheight($this->font_family);
  317.                 if ($h === false) {
  318.                     Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
  319.                 }
  320.                 return $n $h;
  321.             }
  322.             $w = @imagefontwidth($this->font_family);
  323.             if ($w === false) {
  324.                 Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
  325.             }
  326.             return $m $w;
  327.         }
  328.         $bbox $this->GetTTFBBox($txt$angle);
  329.         return $bbox[1] - $bbox[5] + 1;
  330.     }
  331.     // Estimate font height
  332.     public function GetFontHeight($angle 0)
  333.     {
  334.         $txt 'XOMg';
  335.         return $this->GetTextHeight($txt$angle);
  336.     }
  337.     // Approximate font width with width of letter "O"
  338.     public function GetFontWidth($angle 0)
  339.     {
  340.         $txt 'O';
  341.         return $this->GetTextWidth($txt$angle);
  342.     }
  343.     // Get actual width of text in absolute pixels. Note that the width is the
  344.     // texts projected with onto the x-axis. Call with angle=0 to get the true
  345.     // etxt width.
  346.     public function GetTextWidth($txt$angle 0)
  347.     {
  348.         $tmp preg_split('/\n/'$txt);
  349.         $n   safe_count($tmp);
  350.         if ($this->font_family <= FF_FONT2 1) {
  351.             $m 0;
  352.             for ($i 0$i $n; ++$i) {
  353.                 $l strlen($tmp[$i]);
  354.                 if ($l $m) {
  355.                     $m $l;
  356.                 }
  357.             }
  358.             if ($angle == 0) {
  359.                 $w = @imagefontwidth($this->font_family);
  360.                 if ($w === false) {
  361.                     Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
  362.                 }
  363.                 return $m $w;
  364.             }
  365.             // 90 degrees internal so height becomes width
  366.             $h = @imagefontheight($this->font_family);
  367.             if ($h === false) {
  368.                 Util\JpGraphError::RaiseL(25089); //('You have a misconfigured GD font support. The call to imagefontheight() fails.');
  369.             }
  370.             return $n $h;
  371.         }
  372.         // For TTF fonts we must walk through a lines and find the
  373.         // widest one which we use as the width of the multi-line
  374.         // paragraph
  375.         $m 0;
  376.         for ($i 0$i $n; ++$i) {
  377.             $bbox $this->GetTTFBBox($tmp[$i], $angle);
  378.             $mm   $bbox[2] - $bbox[0];
  379.             if ($mm $m) {
  380.                 $m $mm;
  381.             }
  382.         }
  383.         return $m;
  384.     }
  385.     // Draw text with a box around it
  386.     public function StrokeBoxedText(
  387.         $x,
  388.         $y,
  389.         $txt,
  390.         $dir 0,
  391.         $fcolor 'white',
  392.         $bcolor 'black',
  393.         $shadowcolor false,
  394.         $paragraph_align 'left',
  395.         $xmarg 6,
  396.         $ymarg 4,
  397.         $cornerradius 0,
  398.         $dropwidth 3
  399.     ) {
  400.         $oldx $this->lastx;
  401.         $oldy $this->lasty;
  402.         if (!is_numeric($dir)) {
  403.             if ($dir == 'h') {
  404.                 $dir 0;
  405.             } elseif ($dir == 'v') {
  406.                 $dir 90;
  407.             } else {
  408.                 Util\JpGraphError::RaiseL(25090$dir);
  409.             }
  410.             //(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
  411.         }
  412.         if ($this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2 1) {
  413.             $width  $this->GetTextWidth($txt$dir);
  414.             $height $this->GetTextHeight($txt$dir);
  415.         } else {
  416.             $width  $this->GetBBoxWidth($txt$dir);
  417.             $height $this->GetBBoxHeight($txt$dir);
  418.         }
  419.         $height += $ymarg;
  420.         $width += $xmarg;
  421.         if ($this->text_halign == 'right') {
  422.             $x -= $width;
  423.         } elseif ($this->text_halign == 'center') {
  424.             $x -= $width 2;
  425.         }
  426.         if ($this->text_valign == 'bottom') {
  427.             $y -= $height;
  428.         } elseif ($this->text_valign == 'center') {
  429.             $y -= $height 2;
  430.         }
  431.         $olda $this->SetAngle(0);
  432.         if ($shadowcolor) {
  433.             $this->PushColor($shadowcolor);
  434.             $this->FilledRoundedRectangle(
  435.                 $x $xmarg $dropwidth,
  436.                 $y $ymarg $dropwidth,
  437.                 $x $width $dropwidth,
  438.                 $y $height $ymarg $dropwidth,
  439.                 $cornerradius
  440.             );
  441.             $this->PopColor();
  442.             $this->PushColor($fcolor);
  443.             $this->FilledRoundedRectangle(
  444.                 $x $xmarg,
  445.                 $y $ymarg,
  446.                 $x $width,
  447.                 $y $height $ymarg,
  448.                 $cornerradius
  449.             );
  450.             $this->PopColor();
  451.             $this->PushColor($bcolor);
  452.             $this->RoundedRectangle(
  453.                 $x $xmarg,
  454.                 $y $ymarg,
  455.                 $x $width,
  456.                 $y $height $ymarg,
  457.                 $cornerradius
  458.             );
  459.             $this->PopColor();
  460.         } else {
  461.             if ($fcolor) {
  462.                 $oc $this->current_color;
  463.                 $this->SetColor($fcolor);
  464.                 $this->FilledRoundedRectangle($x $xmarg$y $ymarg$x $width$y $height $ymarg$cornerradius);
  465.                 $this->current_color $oc;
  466.             }
  467.             if ($bcolor) {
  468.                 $oc $this->current_color;
  469.                 $this->SetColor($bcolor);
  470.                 $this->RoundedRectangle($x $xmarg$y $ymarg$x $width$y $height $ymarg$cornerradius);
  471.                 $this->current_color $oc;
  472.             }
  473.         }
  474.         $h $this->text_halign;
  475.         $v $this->text_valign;
  476.         $this->SetTextAlign('left''top');
  477.         $debug false;
  478.         $this->StrokeText($x$y$txt$dir$paragraph_align$debug);
  479.         $bb = [$x $xmarg$y $height $ymarg$x $width$y $height $ymarg,
  480.             $x $width$y $ymarg$x $xmarg$y $ymarg, ];
  481.         $this->SetTextAlign($h$v);
  482.         $this->SetAngle($olda);
  483.         $this->lastx $oldx;
  484.         $this->lasty $oldy;
  485.         return $bb;
  486.     }
  487.     // Draw text with a box around it. This time the box will be rotated
  488.     // with the text. The previous method will just make a larger enough non-rotated
  489.     // box to hold the text inside.
  490.     public function StrokeBoxedText2(
  491.         $x,
  492.         $y,
  493.         $txt,
  494.         $dir 0,
  495.         $fcolor 'white',
  496.         $bcolor 'black',
  497.         $shadowcolor false,
  498.         $paragraph_align 'left',
  499.         $xmarg 6,
  500.         $ymarg 4,
  501.         $cornerradius 0,
  502.         $dropwidth 3
  503.     ) {
  504.         // This version of boxed text will stroke a rotated box round the text
  505.         // thta will follow the angle of the text.
  506.         // This has two implications:
  507.         // 1) This methos will only support TTF fonts
  508.         // 2) The only two alignment that makes sense are centered or baselined
  509.         if ($this->font_family <= FF_FONT2 1) {
  510.             Util\JpGraphError::RaiseL(25131); //StrokeBoxedText2() Only support TTF fonts and not built in bitmap fonts
  511.         }
  512.         $oldx $this->lastx;
  513.         $oldy $this->lasty;
  514.         $dir  $this->NormAngle($dir);
  515.         if (!is_numeric($dir)) {
  516.             if ($dir == 'h') {
  517.                 $dir 0;
  518.             } elseif ($dir == 'v') {
  519.                 $dir 90;
  520.             } else {
  521.                 Util\JpGraphError::RaiseL(25090$dir);
  522.             }
  523.             //(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
  524.         }
  525.         $width       $this->GetTextWidth($txt0) + $xmarg;
  526.         $height      $this->GetTextHeight($txt0) + $ymarg;
  527.         $rect_width  $this->GetBBoxWidth($txt$dir);
  528.         $rect_height $this->GetBBoxHeight($txt$dir);
  529.         $baseline_offset $this->bbox_cache[1] - 1;
  530.         if ($this->text_halign == 'center') {
  531.             if ($dir >= && $dir <= 90) {
  532.                 $x -= $rect_width 2;
  533.                 $x += sin($dir M_PI 180) * $height;
  534.                 $y += $rect_height 2;
  535.             } elseif ($dir >= 270 && $dir <= 360) {
  536.                 $x -= $rect_width 2;
  537.                 $y -= $rect_height 2;
  538.                 $y += cos($dir M_PI 180) * $height;
  539.             } elseif ($dir >= 90 && $dir <= 180) {
  540.                 $x += $rect_width 2;
  541.                 $y += $rect_height 2;
  542.                 $y += cos($dir M_PI 180) * $height;
  543.             } else {
  544.                 // $dir > 180 &&  $dir < 270
  545.                 $x += $rect_width 2;
  546.                 $x += sin($dir M_PI 180) * $height;
  547.                 $y -= $rect_height 2;
  548.             }
  549.         }
  550.         // Rotate the box around this point
  551.         $this->SetCenter($x$y);
  552.         $olda $this->SetAngle(-$dir);
  553.         // We need to use adjusted coordinats for the box to be able
  554.         // to draw the box below the baseline. This cannot be done before since
  555.         // the rotating point must be the original x,y since that is arounbf the
  556.         // point where the text will rotate and we cannot change this since
  557.         // that is where the GD/GreeType will rotate the text
  558.         // For smaller <14pt font we need to do some additional
  559.         // adjustments to make it look good
  560.         if ($this->font_size 14) {
  561.             $x -= 2;
  562.             $y += 2;
  563.         }
  564.         //  $y += $baseline_offset;
  565.         if ($shadowcolor) {
  566.             $this->PushColor($shadowcolor);
  567.             $this->FilledRectangle(
  568.                 $x $xmarg $dropwidth,
  569.                 $y $ymarg $dropwidth $height,
  570.                 $x $width $dropwidth,
  571.                 $y $ymarg $dropwidth
  572.             );
  573.             //$cornerradius);
  574.             $this->PopColor();
  575.             $this->PushColor($fcolor);
  576.             $this->FilledRectangle(
  577.                 $x $xmarg,
  578.                 $y $ymarg $height,
  579.                 $x $width,
  580.                 $y $ymarg
  581.             );
  582.             //$cornerradius);
  583.             $this->PopColor();
  584.             $this->PushColor($bcolor);
  585.             $this->Rectangle(
  586.                 $x $xmarg,
  587.                 $y $ymarg $height,
  588.                 $x $width,
  589.                 $y $ymarg
  590.             );
  591.             //$cornerradius);
  592.             $this->PopColor();
  593.         } else {
  594.             if ($fcolor) {
  595.                 $oc $this->current_color;
  596.                 $this->SetColor($fcolor);
  597.                 $this->FilledRectangle($x $xmarg$y $ymarg $height$x $width$y $ymarg); //,$cornerradius);
  598.                 $this->current_color $oc;
  599.             }
  600.             if ($bcolor) {
  601.                 $oc $this->current_color;
  602.                 $this->SetColor($bcolor);
  603.                 $this->Rectangle($x $xmarg$y $ymarg $height$x $width$y $ymarg); //,$cornerradius);
  604.                 $this->current_color $oc;
  605.             }
  606.         }
  607.         if ($this->font_size 14) {
  608.             $x += 2;
  609.             $y -= 2;
  610.         }
  611.         // Restore the original y before we stroke the text
  612.         // $y -= $baseline_offset;
  613.         $this->SetCenter(00);
  614.         $this->SetAngle($olda);
  615.         $h $this->text_halign;
  616.         $v $this->text_valign;
  617.         if ($this->text_halign == 'center') {
  618.             $this->SetTextAlign('center''basepoint');
  619.         } else {
  620.             $this->SetTextAlign('basepoint''basepoint');
  621.         }
  622.         $debug false;
  623.         $this->StrokeText($x$y$txt$dir$paragraph_align$debug);
  624.         $bb = [$x $xmarg$y $height $ymarg,
  625.             $x $width$y $height $ymarg,
  626.             $x $width$y $ymarg,
  627.             $x $xmarg$y $ymarg, ];
  628.         $this->SetTextAlign($h$v);
  629.         $this->SetAngle($olda);
  630.         $this->lastx $oldx;
  631.         $this->lasty $oldy;
  632.         return $bb;
  633.     }
  634.     // Set text alignment
  635.     public function SetTextAlign($halign$valign 'bottom')
  636.     {
  637.         $this->text_halign $halign;
  638.         $this->text_valign $valign;
  639.     }
  640.     public function _StrokeBuiltinFont($x$y$txt$dir$paragraph_align, &$aBoundingBox$aDebug false)
  641.     {
  642.         if (is_numeric($dir) && $dir != 90 && $dir != 0) {
  643.             Util\JpGraphError::RaiseL(25091);
  644.         }
  645.         //(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.");
  646.         $h  $this->GetTextHeight($txt);
  647.         $fh $this->GetFontHeight();
  648.         $w  $this->GetTextWidth($txt);
  649.         if ($this->text_halign == 'right') {
  650.             $x -= $dir == $w $h;
  651.         } elseif ($this->text_halign == 'center') {
  652.             // For center we subtract 1 pixel since this makes the middle
  653.             // be prefectly in the middle
  654.             $x -= $dir == $w $h 2;
  655.         }
  656.         if ($this->text_valign == 'top') {
  657.             $y += $dir == $h $w;
  658.         } elseif ($this->text_valign == 'center') {
  659.             $y += $dir == $h $w 2;
  660.         }
  661.         $use_font $this->font_family;
  662.         if ($dir == 90) {
  663.             imagestringup($this->img$use_font$x$y$txt$this->current_color);
  664.             $aBoundingBox = [round($x), round($y), round($x), round($y $w), round($x $h), round($y $w), round($x $h), round($y)];
  665.             if ($aDebug) {
  666.                 // Draw bounding box
  667.                 $this->PushColor('green');
  668.                 $this->Polygon($aBoundingBoxtrue);
  669.                 $this->PopColor();
  670.             }
  671.         } else {
  672.             if (preg_match('/\n/'$txt)) {
  673.                 $tmp preg_split('/\n/'$txt);
  674.                 for ($i 0$i safe_count($tmp); ++$i) {
  675.                     $w1 $this->GetTextWidth($tmp[$i]);
  676.                     if ($paragraph_align == 'left') {
  677.                         imagestring($this->img$use_font$x$y $h $i $fh$tmp[$i], $this->current_color);
  678.                     } elseif ($paragraph_align == 'right') {
  679.                         imagestring($this->img$use_font$x + ($w $w1), $y $h $i $fh$tmp[$i], $this->current_color);
  680.                     } else {
  681.                         imagestring($this->img$use_font$x $w $w1 2$y $h $i $fh$tmp[$i], $this->current_color);
  682.                     }
  683.                 }
  684.             } else {
  685.                 //Put the text
  686.                 imagestring($this->img$use_font$x$y $h 1$txt$this->current_color);
  687.             }
  688.             if ($aDebug) {
  689.                 // Draw the bounding rectangle and the bounding box
  690.                 $p1 = [round($x), round($y), round($x), round($y $h), round($x $w), round($y $h), round($x $w), round($y)];
  691.                 // Draw bounding box
  692.                 $this->PushColor('green');
  693.                 $this->Polygon($p1true);
  694.                 $this->PopColor();
  695.             }
  696.             $aBoundingBox = [round($x), round($y), round($x), round($y $h), round($x $w), round($y $h), round($x $w), round($y)];
  697.         }
  698.     }
  699.     public function AddTxtCR($aTxt)
  700.     {
  701.         // If the user has just specified a '\n'
  702.         // instead of '\n\t' we have to add '\r' since
  703.         // the width will be too muchy otherwise since when
  704.         // we print we stroke the individually lines by hand.
  705.         $e explode("\n"$aTxt);
  706.         $n safe_count($e);
  707.         for ($i 0$i $n; ++$i) {
  708.             $e[$i] = str_replace("\r"''$e[$i]);
  709.         }
  710.         return implode("\n\r"$e);
  711.     }
  712.     public function NormAngle($a)
  713.     {
  714.         // Normalize angle in degrees
  715.         // Normalize angle to be between 0-360
  716.         while ($a 360) {
  717.             $a -= 360;
  718.         }
  719.         while ($a < -360) {
  720.             $a += 360;
  721.         }
  722.         if ($a 0) {
  723.             $a 360 $a;
  724.         }
  725.         return $a;
  726.     }
  727.     public function imagettfbbox_fixed($size$angle$fontfile$text)
  728.     {
  729.         if (!USE_LIBRARY_IMAGETTFBBOX) {
  730.             $bbox = @imagettfbbox($size$angle$fontfile$text);
  731.             if ($bbox === false) {
  732.                 Util\JpGraphError::RaiseL(25092$this->font_file);
  733.                 //("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
  734.             }
  735.             $this->bbox_cache $bbox;
  736.             return $bbox;
  737.         }
  738.         // The built in imagettfbbox is buggy for angles != 0 so
  739.         // we calculate this manually by getting the bounding box at
  740.         // angle = 0 and then rotate the bounding box manually
  741.         $bbox = @imagettfbbox($size0$fontfile$text);
  742.         if ($bbox === false && !is_readable($this->font_file)) {
  743.             Util\JpGraphError::RaiseL(25092$this->font_file);
  744.             //("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
  745.         }
  746.         $angle $this->NormAngle($angle);
  747.         $a   $angle M_PI 180;
  748.         $ca  cos($a);
  749.         $sa  sin($a);
  750.         $ret = [];
  751.         // We always add 1 pixel to the left since the left edge of the bounding
  752.         // box is sometimes coinciding with the first pixel of the text
  753.         //$bbox[0] -= 1;
  754.         //$bbox[6] -= 1;
  755.         // For roatated text we need to add extra width for rotated
  756.         // text since the kerning and stroking of the TTF is not the same as for
  757.         // text at a 0 degree angle
  758.         if ($angle 0.001 && abs($angle 360) > 0.001) {
  759.             $h abs($bbox[7] - $bbox[1]);
  760.             $w abs($bbox[2] - $bbox[0]);
  761.             $bbox[0] -= 2;
  762.             $bbox[6] -= 2;
  763.             // The width is underestimated so compensate for that
  764.             $bbox[2] += round($w 0.06);
  765.             $bbox[4] += round($w 0.06);
  766.             // and we also need to compensate with increased height
  767.             $bbox[5] -= round($h 0.1);
  768.             $bbox[7] -= round($h 0.1);
  769.             if ($angle 90) {
  770.                 // For angles > 90 we also need to extend the height further down
  771.                 // by the baseline since that is also one more problem
  772.                 $bbox[1] += round($h 0.15);
  773.                 $bbox[3] += round($h 0.15);
  774.                 // and also make it slighty less height
  775.                 $bbox[7] += round($h 0.05);
  776.                 $bbox[5] += round($h 0.05);
  777.                 // And we need to move the box slightly top the rright (from a tetx perspective)
  778.                 $bbox[0] += round($w 0.02);
  779.                 $bbox[6] += round($w 0.02);
  780.                 if ($angle 180) {
  781.                     // And we need to move the box slightly to the left (from a text perspective)
  782.                     $bbox[0] -= round($w 0.02);
  783.                     $bbox[6] -= round($w 0.02);
  784.                     $bbox[2] -= round($w 0.02);
  785.                     $bbox[4] -= round($w 0.02);
  786.                 }
  787.             }
  788.             for ($i 0$i 7$i += 2) {
  789.                 $ret[$i]     = round($bbox[$i] * $ca $bbox[$i 1] * $sa);
  790.                 $ret[$i 1] = round($bbox[$i 1] * $ca $bbox[$i] * $sa);
  791.             }
  792.             $this->bbox_cache $ret;
  793.             return $ret;
  794.         }
  795.         $this->bbox_cache $bbox;
  796.         return $bbox;
  797.     }
  798.     // Deprecated
  799.     public function GetTTFBBox($aTxt$aAngle 0)
  800.     {
  801.         $bbox $this->imagettfbbox_fixed($this->font_size$aAngle$this->font_file$aTxt);
  802.         return $bbox;
  803.     }
  804.     public function GetBBoxTTF($aTxt$aAngle 0)
  805.     {
  806.         // Normalize the bounding box to become a minimum
  807.         // enscribing rectangle
  808.         $aTxt $this->AddTxtCR($aTxt);
  809.         if (!is_readable($this->font_file)) {
  810.             Util\JpGraphError::RaiseL(25093$this->font_file);
  811.             //('Can not read font file ('.$this->font_file.') in call to Image::GetBBoxTTF. Please make sure that you have set a font before calling this method and that the font is installed in the TTF directory.');
  812.         }
  813.         $bbox $this->imagettfbbox_fixed($this->font_size$aAngle$this->font_file$aTxt);
  814.         if ($aAngle == 0) {
  815.             return $bbox;
  816.         }
  817.         if ($aAngle >= 0) {
  818.             if ($aAngle <= 90) {
  819.                 //<=0
  820.                 $bbox = [$bbox[6], $bbox[1], $bbox[2], $bbox[1],
  821.                     $bbox[2], $bbox[5], $bbox[6], $bbox[5], ];
  822.             } elseif ($aAngle <= 180) {
  823.                 //<= 2
  824.                 $bbox = [$bbox[4], $bbox[7], $bbox[0], $bbox[7],
  825.                     $bbox[0], $bbox[3], $bbox[4], $bbox[3], ];
  826.             } elseif ($aAngle <= 270) {
  827.                 //<= 3
  828.                 $bbox = [$bbox[2], $bbox[5], $bbox[6], $bbox[5],
  829.                     $bbox[6], $bbox[1], $bbox[2], $bbox[1], ];
  830.             } else {
  831.                 $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
  832.                     $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
  833.             }
  834.         } elseif ($aAngle 0) {
  835.             if ($aAngle <= -270) {
  836.                 // <= -3
  837.                 $bbox = [$bbox[6], $bbox[1], $bbox[2], $bbox[1],
  838.                     $bbox[2], $bbox[5], $bbox[6], $bbox[5], ];
  839.             } elseif ($aAngle <= -180) {
  840.                 // <= -2
  841.                 $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
  842.                     $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
  843.             } elseif ($aAngle <= -90) {
  844.                 // <= -1
  845.                 $bbox = [$bbox[2], $bbox[5], $bbox[6], $bbox[5],
  846.                     $bbox[6], $bbox[1], $bbox[2], $bbox[1], ];
  847.             } else {
  848.                 $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
  849.                     $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
  850.             }
  851.         }
  852.         return $bbox;
  853.     }
  854.     public function GetBBoxHeight($aTxt$aAngle 0)
  855.     {
  856.         $box $this->GetBBoxTTF($aTxt$aAngle);
  857.         return abs($box[7] - $box[1]);
  858.     }
  859.     public function GetBBoxWidth($aTxt$aAngle 0)
  860.     {
  861.         $box $this->GetBBoxTTF($aTxt$aAngle);
  862.         return $box[2] - $box[0] + 1;
  863.     }
  864.     public function _StrokeTTF($x$y$txt$dir$paragraph_align, &$aBoundingBox$debug false)
  865.     {
  866.         // Setup default inter line margin for paragraphs to be
  867.         // 3% of the font height.
  868.         $ConstLineSpacing 0.03;
  869.         // Remember the anchor point before adjustment
  870.         if ($debug) {
  871.             $ox $x;
  872.             $oy $y;
  873.         }
  874.         if (!preg_match('/\n/'$txt) || ($dir && preg_match('/\n/'$txt))) {
  875.             // Format a single line
  876.             $txt    $this->AddTxtCR($txt);
  877.             $bbox   $this->GetBBoxTTF($txt$dir);
  878.             $width  $this->GetBBoxWidth($txt$dir);
  879.             $height $this->GetBBoxHeight($txt$dir);
  880.             // The special alignment "basepoint" is mostly used internally
  881.             // in the library. This will put the anchor position at the left
  882.             // basepoint of the tetx. This is the default anchor point for
  883.             // TTF text.
  884.             if ($this->text_valign != 'basepoint') {
  885.                 // Align x,y ot lower left corner of bbox
  886.                 if ($this->text_halign == 'right') {
  887.                     $x -= $width;
  888.                     $x -= $bbox[0];
  889.                 } elseif ($this->text_halign == 'center') {
  890.                     $x -= $width 2;
  891.                     $x -= $bbox[0];
  892.                 } elseif ($this->text_halign == 'baseline') {
  893.                     // This is only support for text at 90 degree !!
  894.                     // Do nothing the text is drawn at baseline by default
  895.                 }
  896.                 if ($this->text_valign == 'top') {
  897.                     $y -= $bbox[1]; // Adjust to bottom of text
  898.                     $y += $height;
  899.                 } elseif ($this->text_valign == 'center') {
  900.                     $y -= $bbox[1]; // Adjust to bottom of text
  901.                     $y += $height 2;
  902.                 } elseif ($this->text_valign == 'baseline') {
  903.                     // This is only support for text at 0 degree !!
  904.                     // Do nothing the text is drawn at baseline by default
  905.                 }
  906.             }
  907.             imagettftext(
  908.                 $this->img,
  909.                 $this->font_size,
  910.                 $dir,
  911.                 $x,
  912.                 $y,
  913.                 $this->current_color,
  914.                 $this->font_file,
  915.                 $txt
  916.             );
  917.             // Calculate and return the co-ordinates for the bounding box
  918.             $box $this->imagettfbbox_fixed($this->font_size$dir$this->font_file$txt);
  919.             $p1  = [];
  920.             for ($i 0$i 4; ++$i) {
  921.                 $p1[] = round($box[$i 2] + $x);
  922.                 $p1[] = round($box[$i 1] + $y);
  923.             }
  924.             $aBoundingBox $p1;
  925.             // Debugging code to highlight the bonding box and bounding rectangle
  926.             // For text at 0 degrees the bounding box and bounding rectangle are the
  927.             // same
  928.             if ($debug) {
  929.                 // Draw the bounding rectangle and the bounding box
  930.                 $p  = [];
  931.                 $p1 = [];
  932.                 for ($i 0$i 4; ++$i) {
  933.                     $p[]  = $bbox[$i 2] + $x;
  934.                     $p[]  = $bbox[$i 1] + $y;
  935.                     $p1[] = $box[$i 2] + $x;
  936.                     $p1[] = $box[$i 1] + $y;
  937.                 }
  938.                 // Draw bounding box
  939.                 $this->PushColor('green');
  940.                 $this->Polygon($p1true);
  941.                 $this->PopColor();
  942.                 // Draw bounding rectangle
  943.                 $this->PushColor('darkgreen');
  944.                 $this->Polygon($ptrue);
  945.                 $this->PopColor();
  946.                 // Draw a cross at the anchor point
  947.                 $this->PushColor('red');
  948.                 $this->Line($ox 15$oy$ox 15$oy);
  949.                 $this->Line($ox$oy 15$ox$oy 15);
  950.                 $this->PopColor();
  951.             }
  952.         } else {
  953.             // Format a text paragraph
  954.             $fh $this->GetFontHeight();
  955.             // Line margin is 25% of font height
  956.             $linemargin round($fh $ConstLineSpacing);
  957.             $fh += $linemargin;
  958.             $w $this->GetTextWidth($txt);
  959.             $y -= $linemargin 2;
  960.             $tmp preg_split('/\n/'$txt);
  961.             $nl  safe_count($tmp);
  962.             $h   $nl $fh;
  963.             if ($this->text_halign == 'right') {
  964.                 $x -= $dir == $w $h;
  965.             } elseif ($this->text_halign == 'center') {
  966.                 $x -= $dir == $w $h 2;
  967.             }
  968.             if ($this->text_valign == 'top') {
  969.                 $y += $dir == $h $w;
  970.             } elseif ($this->text_valign == 'center') {
  971.                 $y += $dir == $h $w 2;
  972.             }
  973.             // Here comes a tricky bit.
  974.             // Since we have to give the position for the string at the
  975.             // baseline this means thaht text will move slightly up
  976.             // and down depending on any of it's character descend below
  977.             // the baseline, for example a 'g'. To adjust the Y-position
  978.             // we therefore adjust the text with the baseline Y-offset
  979.             // as used for the current font and size. This will keep the
  980.             // baseline at a fixed positoned disregarding the actual
  981.             // characters in the string.
  982.             $standardbox  $this->GetTTFBBox('Gg'$dir);
  983.             $yadj         $standardbox[1];
  984.             $xadj         $standardbox[0];
  985.             $aBoundingBox = [];
  986.             for ($i 0$i $nl; ++$i) {
  987.                 $wl   $this->GetTextWidth($tmp[$i]);
  988.                 $bbox $this->GetTTFBBox($tmp[$i], $dir);
  989.                 if ($paragraph_align == 'left') {
  990.                     $xl $x;
  991.                 } elseif ($paragraph_align == 'right') {
  992.                     $xl $x + ($w $wl);
  993.                 } else {
  994.                     // Center
  995.                     $xl $x $w $wl 2;
  996.                 }
  997.                 // In theory we should adjust with full pre-lead to get the lines
  998.                 // lined up but this doesn't look good so therfore we only adjust with
  999.                 // half th pre-lead
  1000.                 $xl -= $bbox[0] / 2;
  1001.                 $yl $y $yadj;
  1002.                 //$xl = $xl- $xadj;
  1003.                 imagettftext(
  1004.                     $this->img,
  1005.                     $this->font_size,
  1006.                     $dir,
  1007.                     $xl,
  1008.                     $yl - ($h $fh) + $fh $i,
  1009.                     $this->current_color,
  1010.                     $this->font_file,
  1011.                     $tmp[$i]
  1012.                 );
  1013.                 // echo "xl=$xl,".$tmp[$i]." <br>";
  1014.                 if ($debug) {
  1015.                     // Draw the bounding rectangle around each line
  1016.                     $box = @imagettfbbox($this->font_size$dir$this->font_file$tmp[$i]);
  1017.                     $p   = [];
  1018.                     for ($j 0$j 4; ++$j) {
  1019.                         $p[] = $bbox[$j 2] + $xl;
  1020.                         $p[] = $bbox[$j 1] + $yl - ($h $fh) + $fh $i;
  1021.                     }
  1022.                     // Draw bounding rectangle
  1023.                     $this->PushColor('darkgreen');
  1024.                     $this->Polygon($ptrue);
  1025.                     $this->PopColor();
  1026.                 }
  1027.             }
  1028.             // Get the bounding box
  1029.             $bbox $this->GetBBoxTTF($txt$dir);
  1030.             for ($j 0$j 4; ++$j) {
  1031.                 $bbox[$j 2] += round($x);
  1032.                 $bbox[$j 1] += round($y - ($h $fh) - $yadj);
  1033.             }
  1034.             $aBoundingBox $bbox;
  1035.             if ($debug) {
  1036.                 // Draw a cross at the anchor point
  1037.                 $this->PushColor('red');
  1038.                 $this->Line($ox 25$oy$ox 25$oy);
  1039.                 $this->Line($ox$oy 25$ox$oy 25);
  1040.                 $this->PopColor();
  1041.             }
  1042.         }
  1043.     }
  1044.     public function StrokeText($x$y$txt$dir 0$paragraph_align 'left'$debug false)
  1045.     {
  1046.         $x round($x);
  1047.         $y round($y);
  1048.         // Do special language encoding
  1049.         $txt $this->langconv->Convert($txt$this->font_family);
  1050.         if (!is_numeric($dir)) {
  1051.             Util\JpGraphError::RaiseL(25094); //(" Direction for text most be given as an angle between 0 and 90.");
  1052.         }
  1053.         if ($this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2 1) {
  1054.             $this->_StrokeBuiltinFont($x$y$txt$dir$paragraph_align$boundingbox$debug);
  1055.         } elseif ($this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT) {
  1056.             $this->_StrokeTTF($x$y$txt$dir$paragraph_align$boundingbox$debug);
  1057.         } else {
  1058.             Util\JpGraphError::RaiseL(25095); //(" Unknown font font family specification. ");
  1059.         }
  1060.         return $boundingbox;
  1061.     }
  1062.     public function SetMargin($lm$rm$tm$bm)
  1063.     {
  1064.         $this->left_margin   $lm;
  1065.         $this->right_margin  $rm;
  1066.         $this->top_margin    $tm;
  1067.         $this->bottom_margin $bm;
  1068.         $this->plotwidth  $this->width $this->left_margin $this->right_margin;
  1069.         $this->plotheight $this->height $this->top_margin $this->bottom_margin;
  1070.         if ($this->width && $this->height 0) {
  1071.             if ($this->plotwidth || $this->plotheight 0) {
  1072.                 Util\JpGraphError::RaiseL(25130$this->plotwidth$this->plotheight);
  1073.                 //Util\JpGraphError::raise("To small plot area. ($lm,$rm,$tm,$bm : $this->plotwidth x $this->plotheight). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.");
  1074.             }
  1075.         }
  1076.     }
  1077.     public function SetTransparent($color)
  1078.     {
  1079.         imagecolortransparent($this->img$this->rgb->allocate($color));
  1080.     }
  1081.     public function SetColor($color$aAlpha 0)
  1082.     {
  1083.         $this->current_color_name $color;
  1084.         $this->current_color      $this->rgb->allocate($color$aAlpha);
  1085.         if ($this->current_color == -1) {
  1086.             $tc imagecolorstotal($this->img);
  1087.             Util\JpGraphError::RaiseL(25096);
  1088.             //("Can't allocate any more colors. Image has already allocated maximum of <b>$tc colors</b>. This might happen if you have anti-aliasing turned on together with a background image or perhaps gradient fill since this requires many, many colors. Try to turn off anti-aliasing. If there is still a problem try downgrading the quality of the background image to use a smaller pallete to leave some entries for your graphs. You should try to limit the number of colors in your background image to 64. If there is still problem set the constant DEFINE(\"USE_APPROX_COLORS\",true); in jpgraph.php This will use approximative colors when the palette is full. Unfortunately there is not much JpGraph can do about this since the palette size is a limitation of current graphic format and what the underlying GD library suppports.");
  1089.         }
  1090.         return $this->current_color;
  1091.     }
  1092.     public function PushColor($color)
  1093.     {
  1094.         if ($color != '') {
  1095.             $this->colorstack[$this->colorstackidx]     = $this->current_color_name;
  1096.             $this->colorstack[$this->colorstackidx 1] = $this->current_color;
  1097.             $this->colorstackidx += 2;
  1098.             $this->SetColor($color);
  1099.         } else {
  1100.             Util\JpGraphError::RaiseL(25097); //("Color specified as empty string in PushColor().");
  1101.         }
  1102.     }
  1103.     public function PopColor()
  1104.     {
  1105.         if ($this->colorstackidx 1) {
  1106.             Util\JpGraphError::RaiseL(25098); //(" Negative Color stack index. Unmatched call to PopColor()");
  1107.         }
  1108.         $this->current_color      $this->colorstack[--$this->colorstackidx];
  1109.         $this->current_color_name $this->colorstack[--$this->colorstackidx];
  1110.     }
  1111.     public function SetLineWeight($weight)
  1112.     {
  1113.         $old $this->line_weight;
  1114.         imagesetthickness($this->img$weight);
  1115.         $this->line_weight $weight;
  1116.         return $old;
  1117.     }
  1118.     public function SetStartPoint($x$y)
  1119.     {
  1120.         $this->lastx round($x);
  1121.         $this->lasty round($y);
  1122.     }
  1123.     public function Arc($cx$cy$w$h$s$e)
  1124.     {
  1125.         // GD Arc doesn't like negative angles
  1126.         while ($s 0) {
  1127.             $s += 360;
  1128.         }
  1129.         while ($e 0) {
  1130.             $e += 360;
  1131.         }
  1132.         imagearc($this->imground($cx), round($cy), round($w), round($h), $s$e$this->current_color);
  1133.     }
  1134.     public function FilledArc($xc$yc$w$h$s$e$style '')
  1135.     {
  1136.         $s round($s);
  1137.         $e round($e);
  1138.         while ($s 0) {
  1139.             $s += 360;
  1140.         }
  1141.         while ($e 0) {
  1142.             $e += 360;
  1143.         }
  1144.         if ($style == '') {
  1145.             $style IMG_ARC_PIE;
  1146.         }
  1147.         if (abs($s $e) > 0) {
  1148.             imagefilledarc($this->imground($xc), round($yc), round($w), round($h), $s$e$this->current_color$style);
  1149.             //            $this->DrawImageSmoothArc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style);
  1150.         }
  1151.     }
  1152.     public function FilledCakeSlice($cx$cy$w$h$s$e)
  1153.     {
  1154.         $this->CakeSlice($cx$cy$w$h$s$e$this->current_color_name);
  1155.     }
  1156.     public function CakeSlice($xc$yc$w$h$s$e$fillcolor ''$arccolor '')
  1157.     {
  1158.         $s  round($s);
  1159.         $e  round($e);
  1160.         $w  round($w);
  1161.         $h  round($h);
  1162.         $xc round($xc);
  1163.         $yc round($yc);
  1164.         if ($s == $e) {
  1165.             // A full circle. We draw this a plain circle
  1166.             $this->PushColor($fillcolor);
  1167.             imagefilledellipse($this->img$xc$yc$w$h$this->current_color);
  1168.             // If antialiasing is used then we often don't have any color no the surrounding
  1169.             // arc. So, we need to check for this special case so we don't send an empty
  1170.             // color to the push function. In this case we use the fill color for the arc as well
  1171.             if ($arccolor != '') {
  1172.                 $this->PopColor();
  1173.                 $this->PushColor($arccolor);
  1174.             }
  1175.             imageellipse($this->img$xc$yc$w$h$this->current_color);
  1176.             $this->Line($xc$yccos($s M_PI 180) * $w $xc$yc sin($s M_PI 180) * $h);
  1177.             $this->PopColor();
  1178.         } else {
  1179.             $this->PushColor($fillcolor);
  1180.             $this->FilledArc($xc$yc$w$h$s$e);
  1181.             $this->PopColor();
  1182.             if ($arccolor != '') {
  1183.                 $this->PushColor($arccolor);
  1184.                 // We add 2 pixels to make the Arc() better aligned with
  1185.                 // the filled arc.
  1186.                 imagefilledarc($this->img$xc$yc$w$h$s$e$this->current_colorIMG_ARC_NOFILL IMG_ARC_EDGED);
  1187.                 $this->PopColor();
  1188.             }
  1189.         }
  1190.     }
  1191.     public function Ellipse($xc$yc$w$h)
  1192.     {
  1193.         $this->Arc($xc$yc$w$h0360);
  1194.     }
  1195.     public function Circle($xc$yc$r)
  1196.     {
  1197.         imageellipse($this->imground($xc), round($yc), $r 2$r 2$this->current_color);
  1198.         //        $this->DrawImageSmoothArc($this->img,round($xc),round($yc),$r*2+1,$r*2+1,0,360,$this->current_color);
  1199.         //        $this->imageSmoothCircle($this->img, round($xc),round($yc), $r*2+1, $this->current_color);
  1200.     }
  1201.     public function FilledCircle($xc$yc$r)
  1202.     {
  1203.         imagefilledellipse($this->imground($xc), round($yc), $r$r$this->current_color);
  1204.         //        $this->DrawImageSmoothArc($this->img, round($xc), round($yc), 2*$r, 2*$r, 0, 360, $this->current_color);
  1205.     }
  1206.     // Linear Color InterPolation
  1207.     public function lip($f$t$p)
  1208.     {
  1209.         $p round($p1);
  1210.         $r $f[0] + ($t[0] - $f[0]) * $p;
  1211.         $g $f[1] + ($t[1] - $f[1]) * $p;
  1212.         $b $f[2] + ($t[2] - $f[2]) * $p;
  1213.         return [$r$g$b];
  1214.     }
  1215.     // Set line style dashed, dotted etc
  1216.     public function SetLineStyle($s)
  1217.     {
  1218.         if (is_numeric($s)) {
  1219.             if ($s || $s 4) {
  1220.                 Util\JpGraphError::RaiseL(25101$s); //(" Illegal numeric argument to SetLineStyle(): ($s)");
  1221.             }
  1222.         } elseif (is_string($s)) {
  1223.             if ($s == 'solid') {
  1224.                 $s 1;
  1225.             } elseif ($s == 'dotted') {
  1226.                 $s 2;
  1227.             } elseif ($s == 'dashed') {
  1228.                 $s 3;
  1229.             } elseif ($s == 'longdashed') {
  1230.                 $s 4;
  1231.             } else {
  1232.                 Util\JpGraphError::RaiseL(25102$s); //(" Illegal string argument to SetLineStyle(): $s");
  1233.             }
  1234.         } else {
  1235.             Util\JpGraphError::RaiseL(25103$s); //(" Illegal argument to SetLineStyle $s");
  1236.         }
  1237.         $old              $this->line_style;
  1238.         $this->line_style $s;
  1239.         return $old;
  1240.     }
  1241.     // Same as Line but take the line_style into account
  1242.     public function StyleLine($x1$y1$x2$y2$aStyle ''$from_grid_class false)
  1243.     {
  1244.         if ($this->line_weight <= 0) {
  1245.             return;
  1246.         }
  1247.         if ($aStyle === '') {
  1248.             $aStyle $this->line_style;
  1249.         }
  1250.         $dashed_line_method 'DashedLine';
  1251.         if ($from_grid_class) {
  1252.             $dashed_line_method 'DashedLineForGrid';
  1253.         }
  1254.         // Add error check since dashed line will only work if anti-alias is disabled
  1255.         // this is a limitation in GD
  1256.         if ($aStyle == 1) {
  1257.             // Solid style. We can handle anti-aliasing for this
  1258.             $this->Line($x1$y1$x2$y2);
  1259.         } else {
  1260.             // Since the GD routines doesn't handle AA for styled line
  1261.             // we have no option than to turn it off to get any lines at
  1262.             // all if the weight > 1
  1263.             $oldaa $this->GetAntiAliasing();
  1264.             if ($oldaa && $this->line_weight 1) {
  1265.                 $this->SetAntiAliasing(false);
  1266.             }
  1267.             switch ($aStyle) {
  1268.                 case 2// Dotted
  1269.                     $this->{$dashed_line_method}($x1$y1$x2$y226);
  1270.                     break;
  1271.                 case 3// Dashed
  1272.                     $this->{$dashed_line_method}($x1$y1$x2$y259);
  1273.                     break;
  1274.                 case 4// Longdashes
  1275.                     $this->{$dashed_line_method}($x1$y1$x2$y2913);
  1276.                     break;
  1277.                 default:
  1278.                     Util\JpGraphError::RaiseL(25104$this->line_style); //(" Unknown line style: $this->line_style ");
  1279.                     break;
  1280.             }
  1281.             if ($oldaa) {
  1282.                 $this->SetAntiAliasing(true);
  1283.             }
  1284.         }
  1285.     }
  1286.     public function DashedLine($x1$y1$x2$y2$dash_length 1$dash_space 4)
  1287.     {
  1288.         if ($this->line_weight <= 0) {
  1289.             return;
  1290.         }
  1291.         // Add error check to make sure anti-alias is not enabled.
  1292.         // Dashed line does not work with anti-alias enabled. This
  1293.         // is a limitation in GD.
  1294.         if ($this->use_anti_aliasing) {
  1295.             //            Util\JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
  1296.         }
  1297.         $x1 round($x1);
  1298.         $x2 round($x2);
  1299.         $y1 round($y1);
  1300.         $y2 round($y2);
  1301.         $dash_length *= SUPERSAMPLING_SCALE;
  1302.         $dash_space *= SUPERSAMPLING_SCALE;
  1303.         $style array_fill(0$dash_length$this->current_color);
  1304.         $style array_pad($style$dash_spaceIMG_COLOR_TRANSPARENT);
  1305.         imagesetstyle($this->img$style);
  1306.         imageline($this->img$x1$y1$x2$y2IMG_COLOR_STYLED);
  1307.         $this->lastx $x2;
  1308.         $this->lasty $y2;
  1309.     }
  1310.     public function DashedLineForGrid($x1$y1$x2$y2$dash_length 1$dash_space 4)
  1311.     {
  1312.         if ($this->line_weight <= 0) {
  1313.             return;
  1314.         }
  1315.         // Add error check to make sure anti-alias is not enabled.
  1316.         // Dashed line does not work with anti-alias enabled. This
  1317.         // is a limitation in GD.
  1318.         if ($this->use_anti_aliasing) {
  1319.             //            Util\JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
  1320.         }
  1321.         $x1 round($x1);
  1322.         $x2 round($x2);
  1323.         $y1 round($y1);
  1324.         $y2 round($y2);
  1325.         /*
  1326.         $dash_length *= $this->scale;
  1327.         $dash_space  *= $this->scale;
  1328.          */
  1329.         $dash_length 2;
  1330.         $dash_length 4;
  1331.         imagesetthickness($this->img1);
  1332.         $style array_fill(0$dash_length$this->current_color); //hexdec('CCCCCC'));
  1333.         $style array_pad($style$dash_spaceIMG_COLOR_TRANSPARENT);
  1334.         imagesetstyle($this->img$style);
  1335.         imageline($this->img$x1$y1$x2$y2IMG_COLOR_STYLED);
  1336.         $this->lastx $x2;
  1337.         $this->lasty $y2;
  1338.     }
  1339.     public function Line($x1$y1$x2$y2)
  1340.     {
  1341.         if ($this->line_weight <= 0) {
  1342.             return;
  1343.         }
  1344.         $x1 round($x1);
  1345.         $x2 round($x2);
  1346.         $y1 round($y1);
  1347.         $y2 round($y2);
  1348.         imageline($this->img$x1$y1$x2$y2$this->current_color);
  1349.         //        $this->DrawLine($this->img, $x1, $y1, $x2, $y2, $this->line_weight, $this->current_color);
  1350.         $this->lastx $x2;
  1351.         $this->lasty $y2;
  1352.     }
  1353.     public function Polygon($p$closed false$fast false)
  1354.     {
  1355.         if ($this->line_weight <= 0) {
  1356.             return;
  1357.         }
  1358.         $n    safe_count($p);
  1359.         $oldx $p[0];
  1360.         $oldy $p[1];
  1361.         if ($fast) {
  1362.             for ($i 2$i $n$i += 2) {
  1363.                 imageline($this->img$oldx$oldy$p[$i], $p[$i 1], $this->current_color);
  1364.                 $oldx $p[$i];
  1365.                 $oldy $p[$i 1];
  1366.             }
  1367.             if ($closed) {
  1368.                 imageline($this->img$p[$n 2], $p[$n 1], $p[0], $p[1], $this->current_color);
  1369.             }
  1370.         } else {
  1371.             for ($i 2$i $n$i += 2) {
  1372.                 $this->StyleLine($oldx$oldy$p[$i], $p[$i 1]);
  1373.                 $oldx $p[$i];
  1374.                 $oldy $p[$i 1];
  1375.             }
  1376.             if ($closed) {
  1377.                 $this->StyleLine($oldx$oldy$p[0], $p[1]);
  1378.             }
  1379.         }
  1380.     }
  1381.     public function FilledPolygon($pts)
  1382.     {
  1383.         $n safe_count($pts);
  1384.         if ($n == 0) {
  1385.             Util\JpGraphError::RaiseL(25105); //('NULL data specified for a filled polygon. Check that your data is not NULL.');
  1386.         }
  1387.         for ($i 0$i $n; ++$i) {
  1388.             $pts[$i] = round($pts[$i]);
  1389.         }
  1390.         $old $this->line_weight;
  1391.         imagesetthickness($this->img1);
  1392.         imagefilledpolygon($this->img$ptssafe_count($pts) / 2$this->current_color);
  1393.         $this->line_weight $old;
  1394.         imagesetthickness($this->img$old);
  1395.     }
  1396.     public function Rectangle($xl$yu$xr$yl)
  1397.     {
  1398.         $this->Polygon([$xl$yu$xr$yu$xr$yl$xl$yl$xl$yu]);
  1399.     }
  1400.     public function FilledRectangle($xl$yu$xr$yl)
  1401.     {
  1402.         $this->FilledPolygon([$xl$yu$xr$yu$xr$yl$xl$yl]);
  1403.     }
  1404.     public function FilledRectangle2($xl$yu$xr$yl$color1$color2$style 1)
  1405.     {
  1406.         // Fill a rectangle with lines of two colors
  1407.         if ($style === 1) {
  1408.             // Horizontal stripe
  1409.             if ($yl $yu) {
  1410.                 $t  $yl;
  1411.                 $yl $yu;
  1412.                 $yu $t;
  1413.             }
  1414.             for ($y $yu$y <= $yl; ++$y) {
  1415.                 $this->SetColor($color1);
  1416.                 $this->Line($xl$y$xr$y);
  1417.                 ++$y;
  1418.                 $this->SetColor($color2);
  1419.                 $this->Line($xl$y$xr$y);
  1420.             }
  1421.         } else {
  1422.             if ($xl $xl) {
  1423.                 $t  $xl;
  1424.                 $xl $xr;
  1425.                 $xr $t;
  1426.             }
  1427.             for ($x $xl$x <= $xr; ++$x) {
  1428.                 $this->SetColor($color1);
  1429.                 $this->Line($x$yu$x$yl);
  1430.                 ++$x;
  1431.                 $this->SetColor($color2);
  1432.                 $this->Line($x$yu$x$yl);
  1433.             }
  1434.         }
  1435.     }
  1436.     public function ShadowRectangle($xl$yu$xr$yl$fcolor false$shadow_width 4$shadow_color 'darkgray'$useAlpha true)
  1437.     {
  1438.         // This is complicated by the fact that we must also handle the case where
  1439.         // the reactangle has no fill color
  1440.         $xl floor($xl);
  1441.         $yu floor($yu);
  1442.         $xr floor($xr);
  1443.         $yl floor($yl);
  1444.         $this->PushColor($shadow_color);
  1445.         $shadowAlpha 0;
  1446.         $this->SetLineWeight(1);
  1447.         $this->SetLineStyle('solid');
  1448.         $basecolor    $this->rgb->Color($shadow_color);
  1449.         $shadow_color = [$basecolor[0], $basecolor[1], $basecolor[2]];
  1450.         for ($i 0$i $shadow_width; ++$i) {
  1451.             $this->SetColor($shadow_color$shadowAlpha);
  1452.             $this->Line(
  1453.                 $xr $shadow_width $i,
  1454.                 $yu $shadow_width,
  1455.                 $xr $shadow_width $i,
  1456.                 $yl $shadow_width $i
  1457.             );
  1458.             $this->Line(
  1459.                 $xl $shadow_width,
  1460.                 $yl $shadow_width $i,
  1461.                 $xr $shadow_width $i,
  1462.                 $yl $shadow_width $i
  1463.             );
  1464.             if ($useAlpha) {
  1465.                 $shadowAlpha += 1.0 $shadow_width;
  1466.             }
  1467.         }
  1468.         $this->PopColor();
  1469.         if ($fcolor == false) {
  1470.             $this->Rectangle($xl$yu$xr $shadow_width 1$yl $shadow_width 1);
  1471.         } else {
  1472.             $this->PushColor($fcolor);
  1473.             $this->FilledRectangle($xl$yu$xr $shadow_width 1$yl $shadow_width 1);
  1474.             $this->PopColor();
  1475.             $this->Rectangle($xl$yu$xr $shadow_width 1$yl $shadow_width 1);
  1476.         }
  1477.     }
  1478.     public function FilledRoundedRectangle($xt$yt$xr$yl$r 5)
  1479.     {
  1480.         if ($r == 0) {
  1481.             $this->FilledRectangle($xt$yt$xr$yl);
  1482.             return;
  1483.         }
  1484.         // To avoid overlapping fillings (which will look strange
  1485.         // when alphablending is enabled) we have no choice but
  1486.         // to fill the five distinct areas one by one.
  1487.         // Center square
  1488.         $this->FilledRectangle($xt $r$yt $r$xr $r$yl $r);
  1489.         // Top band
  1490.         $this->FilledRectangle($xt $r$yt$xr $r$yt $r);
  1491.         // Bottom band
  1492.         $this->FilledRectangle($xt $r$yl $r$xr $r$yl);
  1493.         // Left band
  1494.         $this->FilledRectangle($xt$yt $r$xt $r$yl $r);
  1495.         // Right band
  1496.         $this->FilledRectangle($xr $r$yt $r$xr$yl $r);
  1497.         // Topleft & Topright arc
  1498.         $this->FilledArc($xt $r$yt $r$r 2$r 2180270);
  1499.         $this->FilledArc($xr $r$yt $r$r 2$r 2270360);
  1500.         // Bottomleft & Bottom right arc
  1501.         $this->FilledArc($xt $r$yl $r$r 2$r 290180);
  1502.         $this->FilledArc($xr $r$yl $r$r 2$r 2090);
  1503.     }
  1504.     public function RoundedRectangle($xt$yt$xr$yl$r 5)
  1505.     {
  1506.         if ($r == 0) {
  1507.             $this->Rectangle($xt$yt$xr$yl);
  1508.             return;
  1509.         }
  1510.         // Top & Bottom line
  1511.         $this->Line($xt $r$yt$xr $r$yt);
  1512.         $this->Line($xt $r$yl$xr $r$yl);
  1513.         // Left & Right line
  1514.         $this->Line($xt$yt $r$xt$yl $r);
  1515.         $this->Line($xr$yt $r$xr$yl $r);
  1516.         // Topleft & Topright arc
  1517.         $this->Arc($xt $r$yt $r$r 2$r 2180270);
  1518.         $this->Arc($xr $r$yt $r$r 2$r 2270360);
  1519.         // Bottomleft & Bottomright arc
  1520.         $this->Arc($xt $r$yl $r$r 2$r 290180);
  1521.         $this->Arc($xr $r$yl $r$r 2$r 2090);
  1522.     }
  1523.     public function FilledBevel($x1$y1$x2$y2$depth 2$color1 'white@0.4'$color2 'darkgray@0.4')
  1524.     {
  1525.         $this->FilledRectangle($x1$y1$x2$y2);
  1526.         $this->Bevel($x1$y1$x2$y2$depth$color1$color2);
  1527.     }
  1528.     public function Bevel($x1$y1$x2$y2$depth 2$color1 'white@0.4'$color2 'black@0.5')
  1529.     {
  1530.         $this->PushColor($color1);
  1531.         for ($i 0$i $depth; ++$i) {
  1532.             $this->Line($x1 $i$y1 $i$x1 $i$y2 $i);
  1533.             $this->Line($x1 $i$y1 $i$x2 $i$y1 $i);
  1534.         }
  1535.         $this->PopColor();
  1536.         $this->PushColor($color2);
  1537.         for ($i 0$i $depth; ++$i) {
  1538.             $this->Line($x1 $i$y2 $i$x2 $i$y2 $i);
  1539.             $this->Line($x2 $i$y1 $i$x2 $i$y2 $i 1);
  1540.         }
  1541.         $this->PopColor();
  1542.     }
  1543.     public function StyleLineTo($x$y)
  1544.     {
  1545.         $this->StyleLine($this->lastx$this->lasty$x$y);
  1546.         $this->lastx $x;
  1547.         $this->lasty $y;
  1548.     }
  1549.     public function LineTo($x$y)
  1550.     {
  1551.         $this->Line($this->lastx$this->lasty$x$y);
  1552.         $this->lastx $x;
  1553.         $this->lasty $y;
  1554.     }
  1555.     public function Point($x$y)
  1556.     {
  1557.         imagesetpixel($this->imground($x), round($y), $this->current_color);
  1558.     }
  1559.     public function Fill($x$y)
  1560.     {
  1561.         imagefill($this->imground($x), round($y), $this->current_color);
  1562.     }
  1563.     public function FillToBorder($x$y$aBordColor)
  1564.     {
  1565.         $bc $this->rgb->allocate($aBordColor);
  1566.         if ($bc == -1) {
  1567.             Util\JpGraphError::RaiseL(25106); //('Image::FillToBorder : Can not allocate more colors');
  1568.         }
  1569.         imagefilltoborder($this->imground($x), round($y), $bc$this->current_color);
  1570.     }
  1571.     public function SetExpired($aFlg true)
  1572.     {
  1573.         $this->expired $aFlg;
  1574.     }
  1575.     // Generate image header
  1576.     public function Headers()
  1577.     {
  1578.         // In case we are running from the command line with the client version of
  1579.         // PHP we can't send any headers.
  1580.         $sapi php_sapi_name();
  1581.         if ($sapi == 'cli') {
  1582.             return;
  1583.         }
  1584.         // These parameters are set by headers_sent() but they might cause
  1585.         // an undefined variable error unless they are initilized
  1586.         $file   '';
  1587.         $lineno '';
  1588.         if (headers_sent($file$lineno)) {
  1589.             $file basename($file);
  1590.             $t    = new ErrMsgText();
  1591.             $msg  $t->Get(10$file$lineno);
  1592.             die($msg);
  1593.         }
  1594.         if ($this->expired) {
  1595.             header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
  1596.             header('Last-Modified: ' gmdate('D, d M Y H:i:s') . 'GMT');
  1597.             header('Cache-Control: no-cache, must-revalidate');
  1598.             header('Pragma: no-cache');
  1599.         }
  1600.         header("Content-type: image/{$this->img_format}");
  1601.     }
  1602.     // Adjust image quality for formats that allow this
  1603.     public function SetQuality($q)
  1604.     {
  1605.         $this->quality $q;
  1606.     }
  1607.     // Stream image to browser or to file
  1608.     public function Stream($aFile '')
  1609.     {
  1610.         $this->DoSupersampling();
  1611.         $func 'image' $this->img_format;
  1612.         if ($this->img_format == 'jpeg' && $this->quality != null) {
  1613.             $res = @$func($this->img$aFile$this->quality);
  1614.         } else {
  1615.             if ($aFile != '') {
  1616.                 $res = @$func($this->img$aFile);
  1617.                 if (!$res) {
  1618.                     Util\JpGraphError::RaiseL(25107$aFile); //("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
  1619.                 }
  1620.             } else {
  1621.                 $res = @$func($this->img);
  1622.                 if (!$res) {
  1623.                     Util\JpGraphError::RaiseL(25108); //("Can't stream image. This is most likely due to a faulty PHP/GD setup. Try to recompile PHP and use the built-in GD library that comes with PHP.");
  1624.                 }
  1625.             }
  1626.         }
  1627.     }
  1628.     // Do SuperSampling using $scale
  1629.     public function DoSupersampling()
  1630.     {
  1631.         if (SUPERSAMPLING_SCALE <= 1) {
  1632.             return $this->img;
  1633.         }
  1634.         $dst_img = @imagecreatetruecolor($this->original_width$this->original_height);
  1635.         imagecopyresampled($dst_img$this->img0000$this->original_width$this->original_height$this->width$this->height);
  1636.         $this->Destroy();
  1637.         return $this->img $dst_img;
  1638.     }
  1639.     // Clear resources used by image (this is normally not used since all resources are/should be
  1640.     // returned when the script terminates
  1641.     public function Destroy()
  1642.     {
  1643.         imagedestroy($this->img);
  1644.     }
  1645.     // Specify image format. Note depending on your installation
  1646.     // of PHP not all formats may be supported.
  1647.     public function SetImgFormat($aFormat$aQuality 75)
  1648.     {
  1649.         $this->quality $aQuality;
  1650.         $aFormat       strtolower($aFormat);
  1651.         $tst           true;
  1652.         $supported     imagetypes();
  1653.         if ($aFormat == 'auto') {
  1654.             if ($supported IMG_PNG) {
  1655.                 $this->img_format 'png';
  1656.             } elseif ($supported IMG_JPG) {
  1657.                 $this->img_format 'jpeg';
  1658.             } elseif ($supported IMG_GIF) {
  1659.                 $this->img_format 'gif';
  1660.             } elseif ($supported IMG_WBMP) {
  1661.                 $this->img_format 'wbmp';
  1662.             } elseif ($supported IMG_XPM) {
  1663.                 $this->img_format 'xpm';
  1664.             } else {
  1665.                 Util\JpGraphError::RaiseL(25109); //("Your PHP (and GD-lib) installation does not appear to support any known graphic formats. You need to first make sure GD is compiled as a module to PHP. If you also want to use JPEG images you must get the JPEG library. Please see the PHP docs for details.");
  1666.             }
  1667.             return true;
  1668.         }
  1669.         if ($aFormat == 'jpeg' || $aFormat == 'png' || $aFormat == 'gif') {
  1670.             if ($aFormat == 'jpeg' && !($supported IMG_JPG)) {
  1671.                 $tst false;
  1672.             } elseif ($aFormat == 'png' && !($supported IMG_PNG)) {
  1673.                 $tst false;
  1674.             } elseif ($aFormat == 'gif' && !($supported IMG_GIF)) {
  1675.                 $tst false;
  1676.             } elseif ($aFormat == 'wbmp' && !($supported IMG_WBMP)) {
  1677.                 $tst false;
  1678.             } elseif ($aFormat == 'xpm' && !($supported IMG_XPM)) {
  1679.                 $tst false;
  1680.             } else {
  1681.                 $this->img_format $aFormat;
  1682.                 return true;
  1683.             }
  1684.         } else {
  1685.             $tst false;
  1686.         }
  1687.         if (!$tst) {
  1688.             Util\JpGraphError::RaiseL(25110$aFormat); //(" Your PHP installation does not support the chosen graphic format: $aFormat");
  1689.         }
  1690.     }
  1691.     /**
  1692.      * Draw Line.
  1693.      *
  1694.      * @param mixed $im
  1695.      * @param mixed $x1
  1696.      * @param mixed $y1
  1697.      * @param mixed $x2
  1698.      * @param mixed $y2
  1699.      * @param mixed $weight
  1700.      * @param mixed $color
  1701.      */
  1702.     public function DrawLine($im$x1$y1$x2$y2$weight$color)
  1703.     {
  1704.         if ($weight == 1) {
  1705.             return imageline($im$x1$y1$x2$y2$color);
  1706.         }
  1707.         $angle = (atan2(($y1 $y2), ($x2 $x1)));
  1708.         $dist_x $weight * (sin($angle)) / 2;
  1709.         $dist_y $weight * (cos($angle)) / 2;
  1710.         $p1x ceil(($x1 $dist_x));
  1711.         $p1y ceil(($y1 $dist_y));
  1712.         $p2x ceil(($x2 $dist_x));
  1713.         $p2y ceil(($y2 $dist_y));
  1714.         $p3x ceil(($x2 $dist_x));
  1715.         $p3y ceil(($y2 $dist_y));
  1716.         $p4x ceil(($x1 $dist_x));
  1717.         $p4y ceil(($y1 $dist_y));
  1718.         $array = [$p1x$p1y$p2x$p2y$p3x$p3y$p4x$p4y];
  1719.         imagefilledpolygon($im$array, (safe_count($array) / 2), $color);
  1720.         // for antialias
  1721.         imageline($im$p1x$p1y$p2x$p2y$color);
  1722.         imageline($im$p3x$p3y$p4x$p4y$color);
  1723.         return;
  1724.         return imageline($this->img$x1$y1$x2$y2$this->current_color);
  1725.         $weight 8;
  1726.         if ($weight <= 1) {
  1727.             return imageline($this->img$x1$y1$x2$y2$this->current_color);
  1728.         }
  1729.         $pts = [];
  1730.         $weight /= 2;
  1731.         if ($y2 $y1 == 0) {
  1732.             // x line
  1733.             $pts   = [];
  1734.             $pts[] = $x1;
  1735.             $pts[] = $y1 $weight;
  1736.             $pts[] = $x1;
  1737.             $pts[] = $y1 $weight;
  1738.             $pts[] = $x2;
  1739.             $pts[] = $y2 $weight;
  1740.             $pts[] = $x2;
  1741.             $pts[] = $y2 $weight;
  1742.         } elseif ($x2 $x1 == 0) {
  1743.             // y line
  1744.             $pts   = [];
  1745.             $pts[] = $x1 $weight;
  1746.             $pts[] = $y1;
  1747.             $pts[] = $x1 $weight;
  1748.             $pts[] = $y1;
  1749.             $pts[] = $x2 $weight;
  1750.             $pts[] = $y2;
  1751.             $pts[] = $x2 $weight;
  1752.             $pts[] = $y2;
  1753.         } else {
  1754.             $length sqrt(pow($x2 $x12) + pow($y2 $y12));
  1755.             exit;
  1756.             /*
  1757.         $lean = ($y2 - $y1) / ($x2 - $x1);
  1758.         $lean2 = -1 / $lean;
  1759.         $sin = $lean / ($y2 - $y1);
  1760.         $cos = $lean / ($x2 - $x1);
  1761.         $pts[] = $x1 + (-$weight * $sin); $pts[] = $y1 + (-$weight * $cos);
  1762.         $pts[] = $x1 + (+$weight * $sin); $pts[] = $y1 + (+$weight * $cos);
  1763.         $pts[] = $x2 + (+$weight * $sin); $pts[] = $y2 + (+$weight * $cos);
  1764.         $pts[] = $x2 + (-$weight * $sin); $pts[] = $y2 + (-$weight * $cos);
  1765.          */
  1766.         }
  1767.         //print_r($pts);exit;
  1768.         if (safe_count($pts) / 3) {
  1769.             return;
  1770.         }
  1771.         imagesetthickness($im1);
  1772.         imagefilledpolygon($im$ptssafe_count($pts) / 2$color);
  1773.         $weight *= 2;
  1774.         //        $this->DrawImageSmoothArc($im, $x1, $y1, $weight, $weight, 0, 360, $color);
  1775.         //        $this->DrawImageSmoothArc($im, $x2, $y2, $weight, $weight, 0, 360, $color);
  1776.     }
  1777.     public function DrawImageSmoothArc($im$xc$yc$w$h$s$e$color$style null)
  1778.     {
  1779.         $tmp $s;
  1780.         $s   = (360 $e) / 180 M_PI;
  1781.         $e   = (360 $tmp) / 180 M_PI;
  1782.         return $this->imageSmoothArc($imround($xc), round($yc), round($w), round($h), $this->CreateColorForImageSmoothArc($color), $s$e);
  1783.     }
  1784.     public function CreateColorForImageSmoothArc($color)
  1785.     {
  1786.         $alpha $color >> 24 0xFF;
  1787.         $red   $color >> 16 0xFF;
  1788.         $green $color >> 0xFF;
  1789.         $blue  $color 0xFF;
  1790.         return [$red$green$blue$alpha];
  1791.     }
  1792.     public function imageSmoothCircle(&$img$cx$cy$cr$color)
  1793.     {
  1794.         $ir   $cr;
  1795.         $ix   0;
  1796.         $iy   $ir;
  1797.         $ig   $ir 3;
  1798.         $idgr = -6;
  1799.         $idgd $ir 10;
  1800.         $fill imagecolorexactalpha($img$color['R'], $color['G'], $color['B'], 0);
  1801.         imageline($img$cx $cr 1$cy$cx$cy$fill);
  1802.         imageline($img$cx $cr 1$cy$cx 1$cy$fill);
  1803.         imageline($img$cx$cy $cr 1$cx$cy 1$fill);
  1804.         imageline($img$cx$cy $cr 1$cx$cy 1$fill);
  1805.         $draw imagecolorexactalpha($img$color['R'], $color['G'], $color['B'], 42);
  1806.         imagesetpixel($img$cx $cr$cy$draw);
  1807.         imagesetpixel($img$cx $cr$cy$draw);
  1808.         imagesetpixel($img$cx$cy $cr$draw);
  1809.         imagesetpixel($img$cx$cy $cr$draw);
  1810.         while ($ix <= $iy 2) {
  1811.             if ($ig 0) {
  1812.                 $ig += $idgd;
  1813.                 $idgd -= 8;
  1814.                 --$iy;
  1815.             } else {
  1816.                 $ig += $idgr;
  1817.                 $idgd -= 4;
  1818.             }
  1819.             $idgr -= 4;
  1820.             ++$ix;
  1821.             imageline($img$cx $ix$cy $iy 1$cx $ix$cy $ix$fill);
  1822.             imageline($img$cx $ix$cy $iy 1$cx $ix$cy $ix$fill);
  1823.             imageline($img$cx $ix$cy $iy 1$cx $ix$cy $ix$fill);
  1824.             imageline($img$cx $ix$cy $iy 1$cx $ix$cy $ix$fill);
  1825.             imageline($img$cx $iy 1$cy $ix$cx $ix$cy $ix$fill);
  1826.             imageline($img$cx $iy 1$cy $ix$cx $ix$cy $ix$fill);
  1827.             imageline($img$cx $iy 1$cy $ix$cx $ix$cy $ix$fill);
  1828.             imageline($img$cx $iy 1$cy $ix$cx $ix$cy $ix$fill);
  1829.             $filled 0;
  1830.             for ($xx $ix 0.45$xx $ix 0.5$xx += 0.2) {
  1831.                 for ($yy $iy 0.45$yy $iy 0.5$yy += 0.2) {
  1832.                     if (sqrt(pow($xx2) + pow($yy2)) < $cr) {
  1833.                         $filled += 4;
  1834.                     }
  1835.                 }
  1836.             }
  1837.             $draw imagecolorexactalpha($img$color['R'], $color['G'], $color['B'], (100 $filled));
  1838.             imagesetpixel($img$cx $ix$cy $iy$draw);
  1839.             imagesetpixel($img$cx $ix$cy $iy$draw);
  1840.             imagesetpixel($img$cx $ix$cy $iy$draw);
  1841.             imagesetpixel($img$cx $ix$cy $iy$draw);
  1842.             imagesetpixel($img$cx $iy$cy $ix$draw);
  1843.             imagesetpixel($img$cx $iy$cy $ix$draw);
  1844.             imagesetpixel($img$cx $iy$cy $ix$draw);
  1845.             imagesetpixel($img$cx $iy$cy $ix$draw);
  1846.         }
  1847.     }
  1848.     public function __get($name)
  1849.     {
  1850.         if (strpos($name'raw_') !== false) {
  1851.             // if $name == 'raw_left_margin' , return $this->_left_margin;
  1852.             $variable_name '_' str_replace('raw_'''$name);
  1853.             return $this->{$variable_name};
  1854.         }
  1855.         $variable_name '_' $name;
  1856.         if (isset($this->{$variable_name})) {
  1857.             return $this->{$variable_name} * SUPERSAMPLING_SCALE;
  1858.         }
  1859.         Util\JpGraphError::RaiseL('25132'$name);
  1860.     }
  1861.     public function __set($name$value)
  1862.     {
  1863.         $this->{'_' $name} = $value;
  1864.     }
  1865.     /**
  1866.      * Originally written from scratch by Ulrich Mierendorff, 06/2006
  1867.      * Rewritten and improved, 04/2007, 07/2007.
  1868.      *
  1869.      * @param mixed $cx
  1870.      * @param mixed $cy
  1871.      * @param mixed $a
  1872.      * @param mixed $b
  1873.      * @param mixed $aaAngleX
  1874.      * @param mixed $aaAngleY
  1875.      * @param mixed $color
  1876.      * @param mixed $start
  1877.      * @param mixed $stop
  1878.      * @param mixed $seg
  1879.      * @param mixed $img
  1880.      */
  1881.     private function _imageSmoothArcDrawSegment(&$img$cx$cy$a$b$aaAngleX$aaAngleY$color$start$stop$seg)
  1882.     {
  1883.         $fillColor imagecolorexactalpha($img$color[0], $color[1], $color[2], $color[3]);
  1884.         $xStart  abs($a cos($start));
  1885.         $yStart  abs($b sin($start));
  1886.         $xStop   abs($a cos($stop));
  1887.         $yStop   abs($b sin($stop));
  1888.         $dxStart 0;
  1889.         $dyStart 0;
  1890.         $dxStop  0;
  1891.         $dyStop  0;
  1892.         if ($xStart != 0) {
  1893.             $dyStart $yStart $xStart;
  1894.         }
  1895.         if ($xStop != 0) {
  1896.             $dyStop $yStop $xStop;
  1897.         }
  1898.         if ($yStart != 0) {
  1899.             $dxStart $xStart $yStart;
  1900.         }
  1901.         if ($yStop != 0) {
  1902.             $dxStop $xStop $yStop;
  1903.         }
  1904.         if (abs($xStart) >= abs($yStart)) {
  1905.             $aaStartX true;
  1906.         } else {
  1907.             $aaStartX false;
  1908.         }
  1909.         if ($xStop >= $yStop) {
  1910.             $aaStopX true;
  1911.         } else {
  1912.             $aaStopX false;
  1913.         }
  1914.         //$xp = +1; $yp = -1; $xa = +1; $ya = 0;
  1915.         for ($x 0$x $a; ++$x) {
  1916.             /*$y = $b * sqrt( 1 - ($x*$x)/($a*$a) );
  1917.             $error = $y - (int)($y);
  1918.             $y = (int)($y);
  1919.             $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );*/
  1920.             $_y1 $dyStop $x;
  1921.             $_y2 $dyStart $x;
  1922.             if ($xStart $xStop) {
  1923.                 $error1 $_y1 - (int) ($_y1);
  1924.                 $error2 $_y2 + (int) $_y2;
  1925.                 $_y1    $_y1 $error1;
  1926.                 $_y2    $_y2 $error2;
  1927.             } else {
  1928.                 $error1 $_y1 + (int) $_y1;
  1929.                 $error2 $_y2 - (int) ($_y2);
  1930.                 $_y1    $_y1 $error1;
  1931.                 $_y2    $_y2 $error2;
  1932.             }
  1933.             /*
  1934.             if ($aaStopX)
  1935.             $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
  1936.             if ($aaStartX)
  1937.             $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
  1938.              */
  1939.             if ($seg == || $seg == 2) {
  1940.                 $i $seg;
  1941.                 if (!($start $i M_PI && $x $xStart)) {
  1942.                     if ($i == 0) {
  1943.                         $xp = +1;
  1944.                         $yp = -1;
  1945.                         $xa = +1;
  1946.                         $ya 0;
  1947.                     } else {
  1948.                         $xp = -1;
  1949.                         $yp = +1;
  1950.                         $xa 0;
  1951.                         $ya = +1;
  1952.                     }
  1953.                     if ($stop < ($i 1) * (M_PI 2) && $x <= $xStop) {
  1954.                         $diffColor1 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error1);
  1955.                         $y1         $_y1;
  1956.                         if ($aaStopX) {
  1957.                             imagesetpixel($img$cx $xp * ($x) + $xa$cy $yp * ($y1 1) + $ya$diffColor1);
  1958.                         }
  1959.                     } else {
  1960.                         $y         $b sqrt(- ($x $x) / ($a $a));
  1961.                         $error     $y - (int) ($y);
  1962.                         $y         = (int) ($y);
  1963.                         $diffColor imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error);
  1964.                         $y1        $y;
  1965.                         if ($x $aaAngleX) {
  1966.                             imagesetpixel($img$cx $xp $x $xa$cy $yp * ($y1 1) + $ya$diffColor);
  1967.                         }
  1968.                     }
  1969.                     if ($start $i M_PI && $x <= $xStart) {
  1970.                         $diffColor2 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error2);
  1971.                         $y2         $_y2;
  1972.                         if ($aaStartX) {
  1973.                             imagesetpixel($img$cx $xp $x $xa$cy $yp * ($y2 1) + $ya$diffColor2);
  1974.                         }
  1975.                     } else {
  1976.                         $y2 0;
  1977.                     }
  1978.                     if ($y2 <= $y1) {
  1979.                         imageline($img$cx $xp $x $xa$cy $yp $y1 $ya$cx $xp $x $xa$cy $yp $y2 $ya$fillColor);
  1980.                     }
  1981.                 }
  1982.             }
  1983.             if ($seg == || $seg == 3) {
  1984.                 $i $seg;
  1985.                 if (!($stop < ($i 1) * M_PI && $x $xStop)) {
  1986.                     if ($i == 1) {
  1987.                         $xp = -1;
  1988.                         $yp = -1;
  1989.                         $xa 0;
  1990.                         $ya 0;
  1991.                     } else {
  1992.                         $xp = +1;
  1993.                         $yp = +1;
  1994.                         $xa 1;
  1995.                         $ya 1;
  1996.                     }
  1997.                     if ($start $i M_PI && $x $xStart) {
  1998.                         $diffColor2 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error2);
  1999.                         $y1         $_y2;
  2000.                         if ($aaStartX) {
  2001.                             imagesetpixel($img$cx $xp $x $xa$cy $yp * ($y1 1) + $ya$diffColor2);
  2002.                         }
  2003.                     } else {
  2004.                         $y         $b sqrt(- ($x $x) / ($a $a));
  2005.                         $error     $y - (int) ($y);
  2006.                         $y         = (int) $y;
  2007.                         $diffColor imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error);
  2008.                         $y1        $y;
  2009.                         if ($x $aaAngleX) {
  2010.                             imagesetpixel($img$cx $xp $x $xa$cy $yp * ($y1 1) + $ya$diffColor);
  2011.                         }
  2012.                     }
  2013.                     if ($stop < ($i 1) * M_PI && $x <= $xStop) {
  2014.                         $diffColor1 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error1);
  2015.                         $y2         $_y1;
  2016.                         if ($aaStopX) {
  2017.                             imagesetpixel($img$cx $xp $x $xa$cy $yp * ($y2 1) + $ya$diffColor1);
  2018.                         }
  2019.                     } else {
  2020.                         $y2 0;
  2021.                     }
  2022.                     if ($y2 <= $y1) {
  2023.                         imageline($img$cx $xp $x $xa$cy $yp $y1 $ya$cx $xp $x $xa$cy $yp $y2 $ya$fillColor);
  2024.                     }
  2025.                 }
  2026.             }
  2027.         }
  2028.         ///YYYYY
  2029.         for ($y 0$y $b; ++$y) {
  2030.             /*$x = $a * sqrt( 1 - ($y*$y)/($b*$b) );
  2031.             $error = $x - (int)($x);
  2032.             $x = (int)($x);
  2033.             $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
  2034.              */
  2035.             $_x1 $dxStop $y;
  2036.             $_x2 $dxStart $y;
  2037.             if ($yStart $yStop) {
  2038.                 $error1 $_x1 - (int) ($_x1);
  2039.                 $error2 $_x2 + (int) $_x2;
  2040.                 $_x1    $_x1 $error1;
  2041.                 $_x2    $_x2 $error2;
  2042.             } else {
  2043.                 $error1 $_x1 + (int) $_x1;
  2044.                 $error2 $_x2 - (int) ($_x2);
  2045.                 $_x1    $_x1 $error1;
  2046.                 $_x2    $_x2 $error2;
  2047.             }
  2048.             /*
  2049.             if (!$aaStopX)
  2050.             $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
  2051.             if (!$aaStartX)
  2052.             $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
  2053.              */
  2054.             if ($seg == || $seg == 2) {
  2055.                 $i $seg;
  2056.                 if (!($start $i M_PI && $y $yStop)) {
  2057.                     if ($i == 0) {
  2058.                         $xp = +1;
  2059.                         $yp = -1;
  2060.                         $xa 1;
  2061.                         $ya 0;
  2062.                     } else {
  2063.                         $xp = -1;
  2064.                         $yp = +1;
  2065.                         $xa 0;
  2066.                         $ya 1;
  2067.                     }
  2068.                     if ($stop < ($i 1) * (M_PI 2) && $y <= $yStop) {
  2069.                         $diffColor1 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error1);
  2070.                         $x1         $_x1;
  2071.                         if (!$aaStopX) {
  2072.                             imagesetpixel($img$cx $xp * ($x1 1) + $xa$cy $yp * ($y) + $ya$diffColor1);
  2073.                         }
  2074.                     }
  2075.                     if ($start $i M_PI && $y $yStart) {
  2076.                         $diffColor2 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error2);
  2077.                         $x2         $_x2;
  2078.                         if (!$aaStartX) {
  2079.                             imagesetpixel($img$cx $xp * ($x2 1) + $xa$cy $yp * ($y) + $ya$diffColor2);
  2080.                         }
  2081.                     } else {
  2082.                         $x         $a sqrt(- ($y $y) / ($b $b));
  2083.                         $error     $x - (int) ($x);
  2084.                         $x         = (int) ($x);
  2085.                         $diffColor imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error);
  2086.                         $x1        $x;
  2087.                         if ($y $aaAngleY && $y <= $yStop) {
  2088.                             imagesetpixel($img$cx $xp * ($x1 1) + $xa$cy $yp $y $ya$diffColor);
  2089.                         }
  2090.                     }
  2091.                 }
  2092.             }
  2093.             if ($seg == || $seg == 3) {
  2094.                 $i $seg;
  2095.                 if (!($stop < ($i 1) * M_PI && $y $yStart)) {
  2096.                     if ($i == 1) {
  2097.                         $xp = -1;
  2098.                         $yp = -1;
  2099.                         $xa 0;
  2100.                         $ya 0;
  2101.                     } else {
  2102.                         $xp = +1;
  2103.                         $yp = +1;
  2104.                         $xa 1;
  2105.                         $ya 1;
  2106.                     }
  2107.                     if ($start $i M_PI && $y $yStart) {
  2108.                         $diffColor2 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error2);
  2109.                         $x1         $_x2;
  2110.                         if (!$aaStartX) {
  2111.                             imagesetpixel($img$cx $xp * ($x1 1) + $xa$cy $yp $y $ya$diffColor2);
  2112.                         }
  2113.                     }
  2114.                     if ($stop < ($i 1) * M_PI && $y <= $yStop) {
  2115.                         $diffColor1 imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error1);
  2116.                         $x2         $_x1;
  2117.                         if (!$aaStopX) {
  2118.                             imagesetpixel($img$cx $xp * ($x2 1) + $xa$cy $yp $y $ya$diffColor1);
  2119.                         }
  2120.                     } else {
  2121.                         $x         $a sqrt(- ($y $y) / ($b $b));
  2122.                         $error     $x - (int) ($x);
  2123.                         $x         = (int) ($x);
  2124.                         $diffColor imagecolorexactalpha($img$color[0], $color[1], $color[2], 127 - (127 $color[3]) * $error);
  2125.                         $x1        $x;
  2126.                         if ($y $aaAngleY && $y $yStart) {
  2127.                             imagesetpixel($img$cx $xp * ($x1 1) + $xa$cy $yp $y $ya$diffColor);
  2128.                         }
  2129.                     }
  2130.                 }
  2131.             }
  2132.         }
  2133.     }
  2134.     public function imageSmoothArc(&$img$cx$cy$w$h$color$start$stop)
  2135.     {
  2136.         // Originally written from scratch by Ulrich Mierendorff, 06/2006
  2137.         // Rewritten and improved, 04/2007, 07/2007
  2138.         // compared to old version:
  2139.         // + Support for transparency added
  2140.         // + Improved quality of edges & antialiasing
  2141.         // note: This function does not represent the fastest way to draw elliptical
  2142.         // arcs. It was written without reading any papers on that subject. Better
  2143.         // algorithms may be twice as fast or even more.
  2144.         // what it cannot do: It does not support outlined arcs, only filled
  2145.         // Parameters:
  2146.         // $cx      - Center of ellipse, X-coord
  2147.         // $cy      - Center of ellipse, Y-coord
  2148.         // $w       - Width of ellipse ($w >= 2)
  2149.         // $h       - Height of ellipse ($h >= 2 )
  2150.         // $color   - Color of ellipse as a four component array with RGBA
  2151.         // $start   - Starting angle of the arc, no limited range!
  2152.         // $stop    - Stop     angle of the arc, no limited range!
  2153.         // $start _can_ be greater than $stop!
  2154.         // If any value is not in the given range, results are undefined!
  2155.         // This script does not use any special algorithms, everything is completely
  2156.         // written from scratch; see http://de.wikipedia.org/wiki/Ellipse for formulas.
  2157.         while ($start 0) {
  2158.             $start += M_PI;
  2159.         }
  2160.         while ($stop 0) {
  2161.             $stop += M_PI;
  2162.         }
  2163.         while ($start M_PI) {
  2164.             $start -= M_PI;
  2165.         }
  2166.         while ($stop M_PI) {
  2167.             $stop -= M_PI;
  2168.         }
  2169.         if ($start $stop) {
  2170.             $this->imageSmoothArc($img$cx$cy$w$h$color$startM_PI);
  2171.             $this->imageSmoothArc($img$cx$cy$w$h$color0$stop);
  2172.             return;
  2173.         }
  2174.         $a  1.0 round($w 2);
  2175.         $b  1.0 round($h 2);
  2176.         $cx 1.0 round($cx);
  2177.         $cy 1.0 round($cy);
  2178.         $aaAngle  atan(($b $b) / ($a $a) * tan(0.25 M_PI));
  2179.         $aaAngleX $a cos($aaAngle);
  2180.         $aaAngleY $b sin($aaAngle);
  2181.         $a -= 0.5// looks better...
  2182.         $b -= 0.5;
  2183.         for ($i 0$i 4; ++$i) {
  2184.             if ($start < ($i 1) * M_PI 2) {
  2185.                 if ($start $i M_PI 2) {
  2186.                     if ($stop > ($i 1) * M_PI 2) {
  2187.                         $this->_imageSmoothArcDrawSegment($img$cx$cy$a$b$aaAngleX$aaAngleY$color$start, ($i 1) * M_PI 2$i);
  2188.                     } else {
  2189.                         $this->_imageSmoothArcDrawSegment($img$cx$cy$a$b$aaAngleX$aaAngleY$color$start$stop$i);
  2190.                         break;
  2191.                     }
  2192.                 } else {
  2193.                     if ($stop > ($i 1) * M_PI 2) {
  2194.                         $this->_imageSmoothArcDrawSegment($img$cx$cy$a$b$aaAngleX$aaAngleY$color$i M_PI 2, ($i 1) * M_PI 2$i);
  2195.                     } else {
  2196.                         $this->_imageSmoothArcDrawSegment($img$cx$cy$a$b$aaAngleX$aaAngleY$color$i M_PI 2$stop$i);
  2197.                         break;
  2198.                     }
  2199.                 }
  2200.             }
  2201.         }
  2202.     }
  2203. // @class