Add dot to image
@param $x
@param $y
@param $w
@param $h
@param array $rgb
969008
public function addDot($x, $y, $w, $h, $rgb = [0, 0, 255])
    {
        // choose a color for the ellipse
        $ellipseColor = imagecolorallocate($this->image(), $rgb[0], $rgb[1], $rgb[2]);
        // draw the blue ellipse
        imagefilledellipse($this->image(), $x, $y, $w, $h, $ellipseColor);
    }
511600
public void drawImage(Image image, float x, float y) {
		drawImage(image, x, y, Color.white);
	}
1069808
public function drawLegend($X, $Y, array $Format = [])
    {
        $Family = isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX;
        $FontName = isset($Format["FontName"]) ? $this->loadFont($Format["FontName"], 'fonts') : $this->FontName;
        $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize;
        $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->FontColorR;
        $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->FontColorG;
        $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->FontColorB;
        $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5;
        $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5;
        $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth;
        $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight;
        $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
        $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
        $R = isset($Format["R"]) ? $Format["R"] : 200;
        $G = isset($Format["G"]) ? $Format["G"] : 200;
        $B = isset($Format["B"]) ? $Format["B"] : 200;
        $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
        $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
        $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
        $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
        $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
        $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
        $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;

        if ($Surrounding != null) {
            $BorderR = $R + $Surrounding;
            $BorderG = $G + $Surrounding;
            $BorderB = $B + $Surrounding;
        }

        $Data = $this->DataSet->getData();

        foreach ($Data["Series"] as $SerieName => $Serie) {
            if ($Serie["isDrawable"] == true
                && $SerieName != $Data["Abscissa"]
                && isset($Serie["Picture"])
            ) {
                list($PicWidth, $PicHeight) = $this->getPicInfo($Serie["Picture"]);
                if ($IconAreaWidth < $PicWidth) {
                    $IconAreaWidth = $PicWidth;
                }
                if ($IconAreaHeight < $PicHeight) {
                    $IconAreaHeight = $PicHeight;
                }
            }
        }

        $YStep = max($this->FontSize, $IconAreaHeight) + 5;
        $XStep = $IconAreaWidth + 5;
        $XStep = $XSpacing;

        $Boundaries = [];
        $Boundaries["L"] = $X;
        $Boundaries["T"] = $Y;
        $Boundaries["R"] = 0;
        $Boundaries["B"] = 0;
        $vY = $Y;
        $vX = $X;
        foreach ($Data["Series"] as $SerieName => $Serie) {
            if ($Serie["isDrawable"] == true && $SerieName != $Data["Abscissa"]) {
                if ($Mode == LEGEND_VERTICAL) {
                    $BoxArray = $this->getTextBox(
                        $vX + $IconAreaWidth + 4,
                        $vY + $IconAreaHeight / 2,
                        $FontName,
                        $FontSize,
                        0,
                        $Serie["Description"]
                    );

                    if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
                        $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
                    }
                    if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
                        $Boundaries["R"] = $BoxArray[1]["X"] + 2;
                    }
                    if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
                        $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
                    }

                    $Lines = preg_split("/\n/", $Serie["Description"]);
                    $vY = $vY + max($this->FontSize * count($Lines), $IconAreaHeight) + 5;
                } elseif ($Mode == LEGEND_HORIZONTAL) {
                    $Lines = preg_split("/\n/", $Serie["Description"]);
                    $Width = [];
                    foreach ($Lines as $Key => $Value) {
                        $BoxArray = $this->getTextBox(
                            $vX + $IconAreaWidth + 6,
                            $Y + $IconAreaHeight / 2 + (($this->FontSize + 3) * $Key),
                            $FontName,
                            $FontSize,
                            0,
                            $Value
                        );

                        if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
                            $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
                        }
                        if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
                            $Boundaries["R"] = $BoxArray[1]["X"] + 2;
                        }
                        if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
                            $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
                        }

                        $Width[] = $BoxArray[1]["X"];
                    }

                    $vX = max($Width) + $XStep;
                }
            }
        }
        $vY = $vY - $YStep;
        $vX = $vX - $XStep;

        $TopOffset = $Y - $Boundaries["T"];
        if ($Boundaries["B"] - ($vY + $IconAreaHeight) < $TopOffset) {
            $Boundaries["B"] = $vY + $IconAreaHeight + $TopOffset;
        }

        if ($Style == LEGEND_ROUND) {
            $this->drawRoundedFilledRectangle(
                $Boundaries["L"] - $Margin,
                $Boundaries["T"] - $Margin,
                $Boundaries["R"] + $Margin,
                $Boundaries["B"] + $Margin,
                $Margin,
                [
                    "R" => $R,
                    "G" => $G,
                    "B" => $B,
                    "Alpha" => $Alpha,
                    "BorderR" => $BorderR,
                    "BorderG" => $BorderG,
                    "BorderB" => $BorderB
                ]
            );
        } elseif ($Style == LEGEND_BOX) {
            $this->drawFilledRectangle(
                $Boundaries["L"] - $Margin,
                $Boundaries["T"] - $Margin,
                $Boundaries["R"] + $Margin,
                $Boundaries["B"] + $Margin,
                [
                    "R" => $R,
                    "G" => $G,
                    "B" => $B,
                    "Alpha" => $Alpha,
                    "BorderR" => $BorderR,
                    "BorderG" => $BorderG,
                    "BorderB" => $BorderB
                ]
            );
        }

        $RestoreShadow = $this->Shadow;
        $this->Shadow = false;
        foreach ($Data["Series"] as $SerieName => $Serie) {
            if ($Serie["isDrawable"] == true && $SerieName != $Data["Abscissa"]) {
                $R = $Serie["Color"]["R"];
                $G = $Serie["Color"]["G"];
                $B = $Serie["Color"]["B"];
                $Ticks = $Serie["Ticks"];
                $Weight = $Serie["Weight"];

                if (isset($Serie["Picture"])) {
                    $Picture = $Serie["Picture"];
                    list($PicWidth, $PicHeight) = $this->getPicInfo($Picture);
                    $PicX = $X + $IconAreaWidth / 2;
                    $PicY = $Y + $IconAreaHeight / 2;

                    $this->drawFromPNG($PicX - $PicWidth / 2, $PicY - $PicHeight / 2, $Picture);
                } else {
                    if ($Family == LEGEND_FAMILY_BOX) {
                        $XOffset = 0;
                        if ($BoxWidth != $IconAreaWidth) {
                            $XOffset = floor(($IconAreaWidth - $BoxWidth) / 2);
                        }
                        $YOffset = 0;
                        if ($BoxHeight != $IconAreaHeight) {
                            $YOffset = floor(($IconAreaHeight - $BoxHeight) / 2);
                        }

                        $this->drawFilledRectangle(
                            $X + 1 + $XOffset,
                            $Y + 1 + $YOffset,
                            $X + $BoxWidth + $XOffset + 1,
                            $Y + $BoxHeight + 1 + $YOffset,
                            ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]
                        );
                        $this->drawFilledRectangle(
                            $X + $XOffset,
                            $Y + $YOffset,
                            $X + $BoxWidth + $XOffset,
                            $Y + $BoxHeight + $YOffset,
                            ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]
                        );
                    } elseif ($Family == LEGEND_FAMILY_CIRCLE) {
                        $this->drawFilledCircle(
                            $X + 1 + $IconAreaWidth / 2,
                            $Y + 1 + $IconAreaHeight / 2,
                            min($IconAreaHeight / 2, $IconAreaWidth / 2),
                            ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]
                        );
                        $this->drawFilledCircle(
                            $X + $IconAreaWidth / 2,
                            $Y + $IconAreaHeight / 2,
                            min($IconAreaHeight / 2, $IconAreaWidth / 2),
                            ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]
                        );
                    } elseif ($Family == LEGEND_FAMILY_LINE) {
                        $this->drawLine(
                            $X + 1,
                            $Y + 1 + $IconAreaHeight / 2,
                            $X + 1 + $IconAreaWidth,
                            $Y + 1 + $IconAreaHeight / 2,
                            ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20, "Ticks" => $Ticks, "Weight" => $Weight]
                        );
                        $this->drawLine(
                            $X,
                            $Y + $IconAreaHeight / 2,
                            $X + $IconAreaWidth,
                            $Y + $IconAreaHeight / 2,
                            ["R" => $R, "G" => $G, "B" => $B, "Ticks" => $Ticks, "Weight" => $Weight]
                        );
                    }
                }

                if ($Mode == LEGEND_VERTICAL) {
                    $Lines = preg_split("/\n/", $Serie["Description"]);
                    foreach ($Lines as $Key => $Value) {
                        $this->drawText(
                            $X + $IconAreaWidth + 4,
                            $Y + $IconAreaHeight / 2 + (($this->FontSize + 3) * $Key),
                            $Value,
                            [
                                "R" => $FontR,
                                "G" => $FontG,
                                "B" => $FontB,
                                "Align" => TEXT_ALIGN_MIDDLELEFT,
                                "FontSize" => $FontSize,
                                "FontName" => $FontName
                            ]
                        );
                    }
                    $Y = $Y + max($this->FontSize * count($Lines), $IconAreaHeight) + 5;
                } elseif ($Mode == LEGEND_HORIZONTAL) {
                    $Lines = preg_split("/\n/", $Serie["Description"]);
                    $Width = [];
                    foreach ($Lines as $Key => $Value) {
                        $BoxArray = $this->drawText(
                            $X + $IconAreaWidth + 4,
                            $Y + $IconAreaHeight / 2 + (($this->FontSize + 3) * $Key),
                            $Value,
                            [
                                "R" => $FontR,
                                "G" => $FontG,
                                "B" => $FontB,
                                "Align" => TEXT_ALIGN_MIDDLELEFT,
                                "FontSize" => $FontSize,
                                "FontName" => $FontName
                            ]
                        );
                        $Width[] = $BoxArray[1]["X"];
                    }
                    $X = max($Width) + 2 + $XStep;
                }
            }
        }


        $this->Shadow = $RestoreShadow;
    }
214845
public void rectangle(float x, float y, float w, float h) {
        content.append(x).append(' ').append(y).append(' ').append(w).append(' ').append(h).append(" re").append_i(separator);
    }
396527
public function applyToImage(Image $image, $x = 0, $y = 0)
    {
        $background = new Color($this->background);
        imagefilledrectangle($image->getCore(), $this->x1, $this->y1, $this->x2, $this->y2, $background->getInt());

        if ($this->hasBorder()) {
            $border_color = new Color($this->border_color);
            imagesetthickness($image->getCore(), $this->border_width);
            imagerectangle($image->getCore(), $this->x1, $this->y1, $this->x2, $this->y2, $border_color->getInt());
        }

        return true;
    }
1350616
public function getPixel($image, $x, $y)
    {
        return imagecolorsforindex($image, imagecolorat($image, $x, $y));
    }
123951
public function setColor($x, $y, $color) {
		return imagesetpixel($this->image, $x, $y, $this->getColorWithRGB($color));
	}
915556
public function addText($text, $x = 0, $y = 0, $fontSize = 16, $color = '#000', $fontFamily = 5, $angle = 0) {
		$color = $this->getColorWithRGB($color);
		if (is_string($fontFamily) && is_file($fontFamily)) {
			return imagettftext($this->image, $fontSize, $angle, $x, $y, $color, $fontFamily, $text);
		}
		$fontFamily = intval($fontFamily);
		return imagestring($this->image, $fontFamily, $x, $y, $text, $color);
	}
1203042
public function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '')
    {
        if (preg_match("/\.png$/i", $file) || strtolower($type) == "png") {
            $file = $this->fixInterlacedPNG($file);

            // This may return a temp without a png extension
            $type = "png";
        }

        return parent::Image($file, $x, $y, $w, $h, $type, $link);
    }
1301197
public function rgbXY($x, $y) {
        $color = $this->colorXY($x, $y);
        return array(($color >> 16) & 0xFF, ($color >> 8) & 0xFF, $color & 0xFF);
    }
733572
public function draw3DPie($X, $Y, array $Format = [])
    {
        /* Rendering layout */
        $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 80;
        $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0;
        $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .5;
        $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 20;
        $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0;
        $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0;
        $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : true;
        $Border = isset($Format["Border"]) ? $Format["Border"] : false;
        $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : false;
        $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : false;
        $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : false;
        $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL;
        $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0;
        $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0;
        $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0;
        $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100;
        $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : null; //PIE_VALUE_PERCENTAGE
        $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_INSIDE;
        $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 15;
        $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : "";
        $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255;
        $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255;
        $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255;
        $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100;
        $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;

        /* Error correction for overlaying rounded corners */
        if ($SkewFactor < .5) {
            $SkewFactor = .5;
        }

        /* Data Processing */
        $Data = $this->pDataObject->getData();
        $Palette = $this->pDataObject->getPalette();

        /* Do we have an abscissa serie defined? */
        if ($Data["Abscissa"] == "") {
            return PIE_NO_ABSCISSA;
        }

        /* Try to find the data serie */
        $DataSerie = null;
        foreach ($Data["Series"] as $SerieName => $SerieData) {
            if ($SerieName != $Data["Abscissa"]) {
                $DataSerie = $SerieName;
            }
        }

        /* Do we have data to compute? */
        if (!$DataSerie) {
            return PIE_NO_DATASERIE;
        }

        /* Remove unused data */
        list($Data, $Palette) = $this->clean0Values($Data, $Palette, $DataSerie, $Data["Abscissa"]);

        /* Compute the pie sum */
        $SerieSum = $this->pDataObject->getSum($DataSerie);

        /* Do we have data to draw? */
        if ($SerieSum == 0) {
            return PIE_SUMISNULL;
        }

        /* Dump the real number of data to draw */
        $Values = [];
        foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) {
            if ($Value != 0) {
                $Values[] = $Value;
            }
        }

        /* Compute the wasted angular space between series */
        if (count($Values) == 1) {
            $WastedAngular = 0;
        } else {
            $WastedAngular = count($Values) * $DataGapAngle;
        }

        /* Compute the scale */
        $ScaleFactor = (360 - $WastedAngular) / $SerieSum;

        $RestoreShadow = $this->pChartObject->Shadow;
        if ($this->pChartObject->Shadow) {
            $this->pChartObject->Shadow = false;
        }

        /* Draw the polygon pie elements */
        $Step = 360 / (2 * PI * $Radius);
        $Offset = 360;
        $ID = count($Values) - 1;
        $Values = array_reverse($Values);
        $Slice = 0;
        $Slices = [];
        $SliceColors = [];
        $Visible = [];
        $SliceAngle = [];
        foreach ($Values as $Key => $Value) {
            if (!isset($Palette[$ID]["R"])) {
                $Color = $this->pChartObject->getRandomColor();
                $Palette[$ID] = $Color;
                $this->pDataObject->savePalette($ID, $Color);
            }
            $Settings = [
                "R" => $Palette[$ID]["R"],
                "G" => $Palette[$ID]["G"],
                "B" => $Palette[$ID]["B"],
                "Alpha" => $Palette[$ID]["Alpha"]
            ];

            $SliceColors[$Slice] = $Settings;

            $StartAngle = $Offset;
            $EndAngle = $Offset - ($Value * $ScaleFactor);
            if ($EndAngle < 0) {
                $EndAngle = 0;
            }

            if ($StartAngle > 180) {
                $Visible[$Slice]["Start"] = true;
            } else {
                $Visible[$Slice]["Start"] = true;
            }
            if ($EndAngle < 180) {
                $Visible[$Slice]["End"] = false;
            } else {
                $Visible[$Slice]["End"] = true;
            }

            if ($DataGapAngle == 0) {
                $X0 = $X;
                $Y0 = $Y;
            } else {
                $Angle = ($EndAngle - $Offset) / 2 + $Offset;
                $X0 = cos(($Angle - 90) * PI / 180) * $DataGapRadius + $X;
                $Y0 = sin(($Angle - 90) * PI / 180) * $DataGapRadius * $SkewFactor + $Y;
            }
            $Slices[$Slice][] = $X0;
            $Slices[$Slice][] = $Y0;
            $SliceAngle[$Slice][] = 0;

            for ($i = $Offset; $i >= $EndAngle; $i = $i - $Step) {
                $Xc = cos(($i - 90) * PI / 180) * $Radius + $X;
                $Yc = sin(($i - 90) * PI / 180) * $Radius * $SkewFactor + $Y;

                if (($SecondPass || $RestoreShadow) && ($i < 90)) {
                    $Yc++;
                }
                if (($SecondPass || $RestoreShadow) && ($i > 90 && $i < 180)) {
                    $Xc++;
                }
                if (($SecondPass || $RestoreShadow) && ($i > 180 && $i < 270)) {
                    $Xc++;
                }
                if (($SecondPass || $RestoreShadow) && ($i >= 270)) {
                    $Xc++;
                    $Yc++;
                }

                $Slices[$Slice][] = $Xc;
                $Slices[$Slice][] = $Yc;
                $SliceAngle[$Slice][] = $i;
            }

            $Offset = $i - $DataGapAngle;
            $ID--;
            $Slice++;
        }

        /* Draw the bottom shadow if needed */
        if ($RestoreShadow && ($this->pChartObject->ShadowX != 0 || $this->pChartObject->ShadowY != 0)) {
            foreach ($Slices as $SliceID => $Plots) {
                $ShadowPie = [];
                for ($i = 0; $i < count($Plots); $i = $i + 2) {
                    $ShadowPie[] = $Plots[$i] + $this->pChartObject->ShadowX;
                    $ShadowPie[] = $Plots[$i + 1] + $this->pChartObject->ShadowY;
                }

                $Settings = [
                    "R" => $this->pChartObject->ShadowR,
                    "G" => $this->pChartObject->ShadowG,
                    "B" => $this->pChartObject->ShadowB,
                    "Alpha" => $this->pChartObject->Shadowa,
                    "NoBorder" => true
                ];
                $this->pChartObject->drawPolygon($ShadowPie, $Settings);
            }

            $Step = 360 / (2 * PI * $Radius);
            $Offset = 360;
            foreach ($Values as $Key => $Value) {
                $EndAngle = $Offset - ($Value * $ScaleFactor);
                if ($EndAngle < 0) {
                    $EndAngle = 0;
                }

                for ($i = $Offset; $i >= $EndAngle; $i = $i - $Step) {
                    $Xc = cos(($i - 90) * PI / 180) * $Radius + $X + $this->pChartObject->ShadowX;
                    $Yc = sin(($i - 90) * PI / 180) * $Radius * $SkewFactor + $Y + $this->pChartObject->ShadowY;

                    $this->pChartObject->drawAntialiasPixel($Xc, $Yc, $Settings);
                }

                $Offset = $i - $DataGapAngle;
                $ID--;
            }
        }

        /* Draw the bottom pie splice */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $this->pChartObject->drawPolygon($Plots, $Settings);

            if ($SecondPass) {
                $Settings = $SliceColors[$SliceID];
                if ($Border) {
                    $Settings["R"] += 30;
                    $Settings["G"] += 30;
                    $Settings["B"] += 30;
                }
                /* Empty error handling */
                if (isset($SliceAngle[$SliceID][1])) {
                    $Angle = $SliceAngle[$SliceID][1];
                    $Xc = cos(($Angle - 90) * PI / 180) * $Radius + $X;
                    $Yc = sin(($Angle - 90) * PI / 180) * $Radius * $SkewFactor + $Y;
                    $this->pChartObject->drawLine($Plots[0], $Plots[1], $Xc, $Yc, $Settings);

                    $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID]) - 1];
                    $Xc = cos(($Angle - 90) * PI / 180) * $Radius + $X;
                    $Yc = sin(($Angle - 90) * PI / 180) * $Radius * $SkewFactor + $Y;
                    $this->pChartObject->drawLine($Plots[0], $Plots[1], $Xc, $Yc, $Settings);
                }
            }
        }

        /* Draw the two vertical edges */
        $Slices = array_reverse($Slices);
        $SliceColors = array_reverse($SliceColors);
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["R"] += 10;
            $Settings["G"] += 10;
            $Settings["B"] += 10;
            $Settings["NoBorder"] = true;
            /* Empty error handling */
            if ($Visible[$SliceID]["Start"] && isset($Plots[2])) {
                $this->pChartObject->drawLine(
                    $Plots[2],
                    $Plots[3],
                    $Plots[2],
                    $Plots[3] - $SliceHeight,
                    ["R" => $Settings["R"], "G" => $Settings["G"], "B" => $Settings["B"]]
                );
                $Border = [];
                $Border[] = $Plots[0];
                $Border[] = $Plots[1];
                $Border[] = $Plots[0];
                $Border[] = $Plots[1] - $SliceHeight;
                $Border[] = $Plots[2];
                $Border[] = $Plots[3] - $SliceHeight;
                $Border[] = $Plots[2];
                $Border[] = $Plots[3];
                $this->pChartObject->drawPolygon($Border, $Settings);
            }
        }

        $Slices = array_reverse($Slices);
        $SliceColors = array_reverse($SliceColors);
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["R"] += 10;
            $Settings["G"] += 10;
            $Settings["B"] += 10;
            $Settings["NoBorder"] = true;
            if ($Visible[$SliceID]["End"]) {
                $this->pChartObject->drawLine(
                    $Plots[count($Plots) - 2],
                    $Plots[count($Plots) - 1],
                    $Plots[count($Plots) - 2],
                    $Plots[count($Plots) - 1] - $SliceHeight,
                    ["R" => $Settings["R"], "G" => $Settings["G"], "B" => $Settings["B"]]
                );

                $Border = [];
                $Border[] = $Plots[0];
                $Border[] = $Plots[1];
                $Border[] = $Plots[0];
                $Border[] = $Plots[1] - $SliceHeight;
                $Border[] = $Plots[count($Plots) - 2];
                $Border[] = $Plots[count($Plots) - 1] - $SliceHeight;
                $Border[] = $Plots[count($Plots) - 2];
                $Border[] = $Plots[count($Plots) - 1];
                $this->pChartObject->drawPolygon($Border, $Settings);
            }
        }

        /* Draw the rounded edges */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["R"] += 10;
            $Settings["G"] += 10;
            $Settings["B"] += 10;
            $Settings["NoBorder"] = true;

            for ($j = 2; $j < count($Plots) - 2; $j = $j + 2) {
                $Angle = $SliceAngle[$SliceID][$j / 2];
                if ($Angle < 270 && $Angle > 90) {
                    $Border = [];
                    $Border[] = $Plots[$j];
                    $Border[] = $Plots[$j + 1];
                    $Border[] = $Plots[$j + 2];
                    $Border[] = $Plots[$j + 3];
                    $Border[] = $Plots[$j + 2];
                    $Border[] = $Plots[$j + 3] - $SliceHeight;
                    $Border[] = $Plots[$j];
                    $Border[] = $Plots[$j + 1] - $SliceHeight;
                    $this->pChartObject->drawPolygon($Border, $Settings);
                }
            }

            if ($SecondPass) {
                $Settings = $SliceColors[$SliceID];
                if (count($Border)) {
                    $Settings["R"] += 30;
                    $Settings["G"] += 30;
                    $Settings["B"] += 30;
                }

                /* Empty error handling */
                if (isset($SliceAngle[$SliceID][1])) {
                    $Angle = $SliceAngle[$SliceID][1];
                    if ($Angle < 270 && $Angle > 90) {
                        $Xc = cos(($Angle - 90) * PI / 180) * $Radius + $X;
                        $Yc = sin(($Angle - 90) * PI / 180) * $Radius * $SkewFactor + $Y;
                        $this->pChartObject->drawLine($Xc, $Yc, $Xc, $Yc - $SliceHeight, $Settings);
                    }
                }

                $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID]) - 1];
                if ($Angle < 270 && $Angle > 90) {
                    $Xc = cos(($Angle - 90) * PI / 180) * $Radius + $X;
                    $Yc = sin(($Angle - 90) * PI / 180) * $Radius * $SkewFactor + $Y;
                    $this->pChartObject->drawLine($Xc, $Yc, $Xc, $Yc - $SliceHeight, $Settings);
                }

                if (isset($SliceAngle[$SliceID][1])
                    && $SliceAngle[$SliceID][1] > 270
                    && $SliceAngle[$SliceID][count($SliceAngle[$SliceID]) - 1] < 270
                ) {
                    $Xc = cos((270 - 90) * PI / 180) * $Radius + $X;
                    $Yc = sin((270 - 90) * PI / 180) * $Radius * $SkewFactor + $Y;
                    $this->pChartObject->drawLine($Xc, $Yc, $Xc, $Yc - $SliceHeight, $Settings);
                }

                if (isset($SliceAngle[$SliceID][1])
                    && $SliceAngle[$SliceID][1] > 90
                    && $SliceAngle[$SliceID][count($SliceAngle[$SliceID]) - 1] < 90
                ) {
                    $Xc = cos((0) * PI / 180) * $Radius + $X;
                    $Yc = sin((0) * PI / 180) * $Radius * $SkewFactor + $Y;
                    $this->pChartObject->drawLine($Xc, $Yc, $Xc, $Yc - $SliceHeight, $Settings);
                }
            }
        }

        /* Draw the top splice */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["R"] += 20;
            $Settings["G"] += 20;
            $Settings["B"] += 20;

            $Top = [];
            for ($j = 0; $j < count($Plots); $j = $j + 2) {
                $Top[] = $Plots[$j];
                $Top[] = $Plots[$j + 1] - $SliceHeight;
            }
            $this->pChartObject->drawPolygon($Top, $Settings);

            if ($RecordImageMap && !$Shadow) {
                $this->pChartObject->addToImageMap(
                    "POLY",
                    $this->arraySerialize($Top),
                    $this->pChartObject->toHTMLColor(
                        $Settings["R"],
                        $Settings["G"],
                        $Settings["B"]
                    ),
                    $Data["Series"][$Data["Abscissa"]]["Data"][count($Slices) - $SliceID - 1],
                    $Values[$SliceID]
                );
            }
        }


        /* Second pass to smooth the angles */
        if ($SecondPass) {
            $Step = 360 / (2 * PI * $Radius);
            $Offset = 360;
            $ID = count($Values) - 1;
            foreach ($Values as $Key => $Value) {
                $FirstPoint = true;
                if ($Shadow) {
                    $Settings = [
                        "R" => $this->pChartObject->ShadowR,
                        "G" => $this->pChartObject->ShadowG,
                        "B" => $this->pChartObject->ShadowB,
                        "Alpha" => $this->pChartObject->Shadowa
                    ];
                } else {
                    if ($Border) {
                        $Settings = [
                            "R" => $Palette[$ID]["R"] + 30,
                            "G" => $Palette[$ID]["G"] + 30,
                            "B" => $Palette[$ID]["B"] + 30,
                            "Alpha" => $Palette[$ID]["Alpha"]
                        ];
                    } else {
                        $Settings = [
                            "R" => $Palette[$ID]["R"],
                            "G" => $Palette[$ID]["G"],
                            "B" => $Palette[$ID]["B"],
                            "Alpha" => $Palette[$ID]["Alpha"]
                        ];
                    }
                }

                $EndAngle = $Offset - ($Value * $ScaleFactor);
                if ($EndAngle < 0) {
                    $EndAngle = 0;
                }

                if ($DataGapAngle == 0) {
                    $X0 = $X;
                    $Y0 = $Y - $SliceHeight;
                } else {
                    $Angle = ($EndAngle - $Offset) / 2 + $Offset;
                    $X0 = cos(($Angle - 90) * PI / 180) * $DataGapRadius + $X;
                    $Y0 = sin(($Angle - 90) * PI / 180) * $DataGapRadius * $SkewFactor + $Y - $SliceHeight;
                }
                $Plots[] = $X0;
                $Plots[] = $Y0;

                for ($i = $Offset; $i >= $EndAngle; $i = $i - $Step) {
                    $Xc = cos(($i - 90) * PI / 180) * $Radius + $X;
                    $Yc = sin(($i - 90) * PI / 180) * $Radius * $SkewFactor + $Y - $SliceHeight;

                    if ($FirstPoint) {
                        $this->pChartObject->drawLine($Xc, $Yc, $X0, $Y0, $Settings);
                        $FirstPoint = false;
                    }

                    $this->pChartObject->drawAntialiasPixel($Xc, $Yc, $Settings);
                    if ($i < 270 && $i > 90) {
                        $this->pChartObject->drawAntialiasPixel($Xc, $Yc + $SliceHeight, $Settings);
                    }
                }
                $this->pChartObject->drawLine($Xc, $Yc, $X0, $Y0, $Settings);

                $Offset = $i - $DataGapAngle;
                $ID--;
            }
        }

        if ($WriteValues != null) {
            $Step = 360 / (2 * PI * $Radius);
            $Offset = 360;
            $ID = count($Values) - 1;
            $Settings = [
                "Align" => TEXT_ALIGN_MIDDLEMIDDLE,
                "R" => $ValueR,
                "G" => $ValueG,
                "B" => $ValueB,
                "Alpha" => $ValueAlpha
            ];
            foreach ($Values as $Key => $Value) {
                $EndAngle = $Offset - ($Value * $ScaleFactor);
                if ($EndAngle < 0) {
                    $EndAngle = 0;
                }

                $Angle = ($EndAngle - $Offset) / 2 + $Offset;

                if ($ValuePosition == PIE_VALUE_OUTSIDE) {
                    $Xc = cos(($Angle - 90) * PI / 180) * ($Radius + $ValuePadding) + $X;
                    $Yc = sin(($Angle - 90) * PI / 180)
                        * (($Radius * $SkewFactor) + $ValuePadding)
                        + $Y - $SliceHeight
                    ;
                } else {
                    $Xc = cos(($Angle - 90) * PI / 180) * ($Radius) / 2 + $X;
                    $Yc = sin(($Angle - 90) * PI / 180) * ($Radius * $SkewFactor) / 2 + $Y - $SliceHeight;
                }

                if ($WriteValues == PIE_VALUE_PERCENTAGE) {
                    $Display = round((100 / $SerieSum) * $Value, $Precision) . "%";
                } elseif ($WriteValues == PIE_VALUE_NATURAL) {
                    $Display = $Value . $ValueSuffix;
                }

                $this->pChartObject->drawText($Xc, $Yc, $Display, $Settings);

                $Offset = $EndAngle - $DataGapAngle;
                $ID--;
            }
        }

        if ($DrawLabels) {
            $Step = 360 / (2 * PI * $Radius);
            $Offset = 360;
            $ID = count($Values) - 1;
            foreach ($Values as $Key => $Value) {
                if ($LabelColor == PIE_LABEL_COLOR_AUTO) {
                    $Settings = [
                        "FillR" => $Palette[$ID]["R"],
                        "FillG" => $Palette[$ID]["G"],
                        "FillB" => $Palette[$ID]["B"],
                        "Alpha" => $Palette[$ID]["Alpha"]
                    ];
                } else {
                    $Settings = [
                        "FillR" => $LabelR,
                        "FillG" => $LabelG,
                        "FillB" => $LabelB,
                        "Alpha" => $LabelAlpha
                    ];
                }

                $EndAngle = $Offset - ($Value * $ScaleFactor);
                if ($EndAngle < 0) {
                    $EndAngle = 0;
                }

                $Angle = ($EndAngle - $Offset) / 2 + $Offset;
                $Xc = cos(($Angle - 90) * PI / 180) * $Radius + $X;
                $Yc = sin(($Angle - 90) * PI / 180) * $Radius * $SkewFactor + $Y - $SliceHeight;

                if (isset($Data["Series"][$Data["Abscissa"]]["Data"][$ID])) {
                    $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$ID];

                    if ($LabelStacked) {
                        $this->writePieLabel($Xc, $Yc, $Label, $Angle, $Settings, true, $X, $Y, $Radius, true);
                    } else {
                        $this->writePieLabel($Xc, $Yc, $Label, $Angle, $Settings, false);
                    }
                }

                $Offset = $EndAngle - $DataGapAngle;
                $ID--;
            }
        }

        if ($DrawLabels && $LabelStacked) {
            $this->writeShiftedLabels();
        }

        $this->pChartObject->Shadow = $RestoreShadow;

        return PIE_RENDERED;
    }
412448
private static double dot(double[] x, double[] w) {
        int i = 0;
        double dot = 0.0;

        for (; i < x.length; i++) {
            dot += x[i] * w[i];
        }

        return dot + w[i];
    }
951630
public function add($color, $untilX) 
    {
        $samplesLeft = 
            (int)($untilX * $this->samplesPerPixel) - 
            $this->subPixelOffset - 
            $this->pixelOffset * $this->samplesPerPixel;

        // ColorUtils methods inlined for performance reasons
        $a = ($color) & 0xff;
        $r = ($color >> 24) & 0xff;
        $g = ($color >> 16) & 0xff;
        $b = ($color >> 8) & 0xff;
        
        // First partial pixel
        if ($this->subPixelOffset > 0) {
            $samples = $this->samplesPerPixel - $this->subPixelOffset;
            if ($samples > $samplesLeft) {
                $samples = $samplesLeft;
            }
            $samplesLeft -= $samples;

            $this->_add($samples, $a, $r, $g, $b);

            $this->subPixelOffset += $samples;
            if ($this->subPixelOffset == $this->samplesPerPixel) {
                $this->subPixelOffset = 0;
                $this->pixelOffset++;
            }
        }

        // Full pixels
        $fullPixels = (int)($samplesLeft / $this->samplesPerPixel);
        if ($fullPixels > 0) {
            for ($i = 0; $i < $fullPixels; $i++) {
                $this->_add($this->samplesPerPixel, $a, $r, $g, $b);
                $this->pixelOffset++;
            }

            $samplesLeft -= $fullPixels * $this->samplesPerPixel;
        }

        // Last partial pixel
        if ($samplesLeft > 0) {
            $this->_add($samplesLeft, $a, $r, $g, $b);

            $this->subPixelOffset += $samplesLeft;

            if ($this->subPixelOffset == $this->samplesPerPixel) {
                $this->subPixelOffset = 0;
                $this->pixelOffset++;
            }
        }
    }
1183317
public function drawPieLegend($X, $Y, array $Format = [])
    {
        $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
        $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
        $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR;
        $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG;
        $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB;
        $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5;
        $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
        $R = isset($Format["R"]) ? $Format["R"] : 200;
        $G = isset($Format["G"]) ? $Format["G"] : 200;
        $B = isset($Format["B"]) ? $Format["B"] : 200;
        $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
        $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
        $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
        $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
        $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
        $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
        $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;

        if ($Surrounding != null) {
            $BorderR = $R + $Surrounding;
            $BorderG = $G + $Surrounding;
            $BorderB = $B + $Surrounding;
        }

        $YStep = max($this->pChartObject->FontSize, $BoxSize) + 5;
        $XStep = $BoxSize + 5;

        /* Data Processing */
        $Data = $this->pDataObject->getData();
        $Palette = $this->pDataObject->getPalette();

        /* Do we have an abscissa serie defined? */
        if ($Data["Abscissa"] == "") {
            return PIE_NO_ABSCISSA;
        }

        $Boundaries = [];
        $Boundaries["L"] = $X;
        $Boundaries["T"] = $Y;
        $Boundaries["R"] = 0;
        $Boundaries["B"] = 0;
        $vY = $Y;
        $vX = $X;
        foreach ($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value) {
            $BoxArray = $this->pChartObject->getTextBox(
                $vX + $BoxSize + 4,
                $vY + $BoxSize / 2,
                $FontName,
                $FontSize,
                0,
                $Value
            );

            if ($Mode == LEGEND_VERTICAL) {
                if ($Boundaries["T"] > $BoxArray[2]["Y"] + $BoxSize / 2) {
                    $Boundaries["T"] = $BoxArray[2]["Y"] + $BoxSize / 2;
                }
                if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
                    $Boundaries["R"] = $BoxArray[1]["X"] + 2;
                }
                if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $BoxSize / 2) {
                    $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $BoxSize / 2;
                }
                $vY = $vY + $YStep;
            } elseif ($Mode == LEGEND_HORIZONTAL) {
                if ($Boundaries["T"] > $BoxArray[2]["Y"] + $BoxSize / 2) {
                    $Boundaries["T"] = $BoxArray[2]["Y"] + $BoxSize / 2;
                }
                if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
                    $Boundaries["R"] = $BoxArray[1]["X"] + 2;
                }
                if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $BoxSize / 2) {
                    $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $BoxSize / 2;
                }
                $vX = $Boundaries["R"] + $XStep;
            }
        }
        $vY = $vY - $YStep;
        $vX = $vX - $XStep;

        $TopOffset = $Y - $Boundaries["T"];
        if ($Boundaries["B"] - ($vY + $BoxSize) < $TopOffset) {
            $Boundaries["B"] = $vY + $BoxSize + $TopOffset;
        }

        if ($Style == LEGEND_ROUND) {
            $this->pChartObject->drawRoundedFilledRectangle(
                $Boundaries["L"] - $Margin,
                $Boundaries["T"] - $Margin,
                $Boundaries["R"] + $Margin,
                $Boundaries["B"] + $Margin,
                $Margin,
                [
                    "R" => $R,
                    "G" => $G,
                    "B" => $B,
                    "Alpha" => $Alpha,
                    "BorderR" => $BorderR,
                    "BorderG" => $BorderG,
                    "BorderB" => $BorderB
                ]
            );
        } elseif ($Style == LEGEND_BOX) {
            $this->pChartObject->drawFilledRectangle(
                $Boundaries["L"] - $Margin,
                $Boundaries["T"] - $Margin,
                $Boundaries["R"] + $Margin,
                $Boundaries["B"] + $Margin,
                [
                    "R" => $R,
                    "G" => $G,
                    "B" => $B,
                    "Alpha" => $Alpha,
                    "BorderR" => $BorderR,
                    "BorderG" => $BorderG,
                    "BorderB" => $BorderB
                ]
            );
        }
        $RestoreShadow = $this->pChartObject->Shadow;
        $this->pChartObject->Shadow = false;
        foreach ($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value) {
            $R = $Palette[$Key]["R"];
            $G = $Palette[$Key]["G"];
            $B = $Palette[$Key]["B"];

            $this->pChartObject->drawFilledRectangle(
                $X + 1,
                $Y + 1,
                $X + $BoxSize + 1,
                $Y + $BoxSize + 1,
                ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]
            );
            $this->pChartObject->drawFilledRectangle(
                $X,
                $Y,
                $X + $BoxSize,
                $Y + $BoxSize,
                ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]
            );
            if ($Mode == LEGEND_VERTICAL) {
                $this->pChartObject->drawText(
                    $X + $BoxSize + 4,
                    $Y + $BoxSize / 2,
                    $Value,
                    [
                        "R" => $FontR,
                        "G" => $FontG,
                        "B" => $FontB,
                        "Align" => TEXT_ALIGN_MIDDLELEFT,
                        "FontName" => $FontName,
                        "FontSize" => $FontSize
                    ]
                );
                $Y = $Y + $YStep;
            } elseif ($Mode == LEGEND_HORIZONTAL) {
                $BoxArray = $this->pChartObject->drawText(
                    $X + $BoxSize + 4,
                    $Y + $BoxSize / 2,
                    $Value,
                    [
                        "R" => $FontR,
                        "G" => $FontG,
                        "B" => $FontB,
                        "Align" => TEXT_ALIGN_MIDDLELEFT,
                        "FontName" => $FontName,
                        "FontSize" => $FontSize
                    ]
                );
                $X = $BoxArray[1]["X"] + 2 + $XStep;
            }
        }

        $this->Shadow = $RestoreShadow;
    }
815546
public function draw3DRing($X, $Y, array $Format = [])
    {
        $OuterRadius = isset($Format["OuterRadius"]) ? $Format["OuterRadius"] : 100;
        $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0;
        $InnerRadius = isset($Format["InnerRadius"]) ? $Format["InnerRadius"] : 30;
        $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .6;
        $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 10;
        $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 10;
        $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 10;
        $Border = isset($Format["Border"]) ? $Format["Border"] : false;
        $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : false;
        $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : false;
        $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : false;
        $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL;
        $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0;
        $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0;
        $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0;
        $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100;
        $Cf = isset($Format["Cf"]) ? $Format["Cf"] : 20;
        $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : PIE_VALUE_NATURAL;
        $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : $SliceHeight + 15;
        $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_OUTSIDE;
        $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : "";
        $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255;
        $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255;
        $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255;
        $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100;
        $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;

        /* Error correction for overlaying rounded corners */
        if ($SkewFactor < .5) {
            $SkewFactor = .5;
        }

        /* Data Processing */
        $Data = $this->pDataObject->getData();
        $Palette = $this->pDataObject->getPalette();

        /* Do we have an abscissa serie defined? */
        if ($Data["Abscissa"] == "") {
            return PIE_NO_ABSCISSA;
        }

        /* Try to find the data serie */
        $DataSerie = null;
        foreach ($Data["Series"] as $SerieName => $SerieData) {
            if ($SerieName != $Data["Abscissa"]) {
                $DataSerie = $SerieName;
            }
        }

        /* Do we have data to compute? */
        if (!$DataSerie) {
            return PIE_NO_DATASERIE;
        }

        /* Remove unused data */
        list($Data, $Palette) = $this->clean0Values($Data, $Palette, $DataSerie, $Data["Abscissa"]);

        /* Compute the pie sum */
        $SerieSum = $this->pDataObject->getSum($DataSerie);

        /* Do we have data to draw? */
        if ($SerieSum == 0) {
            return PIE_SUMISNULL;
        }

        /* Dump the real number of data to draw */
        $Values = [];
        foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) {
            if ($Value != 0) {
                $Values[] = $Value;
            }
        }

        /* Compute the wasted angular space between series */
        if (count($Values) == 1) {
            $WastedAngular = 0;
        } else {
            $WastedAngular = count($Values) * $DataGapAngle;
        }

        /* Compute the scale */
        $ScaleFactor = (360 - $WastedAngular) / $SerieSum;

        $RestoreShadow = $this->pChartObject->Shadow;
        if ($this->pChartObject->Shadow) {
            $this->pChartObject->Shadow = false;
        }

        /* Draw the polygon ring elements */
        $Offset = 360;
        $ID = count($Values) - 1;
        $Values = array_reverse($Values);
        $Slice = 0;
        $Slices = [];
        $SliceColors = [];
        $Visible = [];
        $SliceAngle = [];
        foreach ($Values as $Key => $Value) {
            if (!isset($Palette[$ID]["R"])) {
                $Color = $this->pChartObject->getRandomColor();
                $Palette[$ID] = $Color;
                $this->pDataObject->savePalette($ID, $Color);
            }
            $Settings = [
                "R" => $Palette[$ID]["R"],
                "G" => $Palette[$ID]["G"],
                "B" => $Palette[$ID]["B"],
                "Alpha" => $Palette[$ID]["Alpha"]
            ];

            $SliceColors[$Slice] = $Settings;

            $StartAngle = $Offset;
            $EndAngle = $Offset - ($Value * $ScaleFactor);
            if ($EndAngle < 0) {
                $EndAngle = 0;
            }

            if ($StartAngle > 180) {
                $Visible[$Slice]["Start"] = true;
            } else {
                $Visible[$Slice]["Start"] = true;
            }
            if ($EndAngle < 180) {
                $Visible[$Slice]["End"] = false;
            } else {
                $Visible[$Slice]["End"] = true;
            }

            $Step = (360 / (2 * PI * $OuterRadius)) / 2;
            $OutX1 = VOID;
            $OutY1 = VOID;
            for ($i = $Offset; $i >= $EndAngle; $i = $i - $Step) {
                $Xc = cos(($i - 90) * PI / 180) * ($OuterRadius + $DataGapRadius - 2) + $X;
                $Yc = sin(($i - 90) * PI / 180) * ($OuterRadius + $DataGapRadius - 2) * $SkewFactor + $Y;
                $Slices[$Slice]["AA"][] = [$Xc, $Yc];

                $Xc = cos(($i - 90) * PI / 180) * ($OuterRadius + $DataGapRadius - 1) + $X;
                $Yc = sin(($i - 90) * PI / 180) * ($OuterRadius + $DataGapRadius - 1) * $SkewFactor + $Y;
                $Slices[$Slice]["AA"][] = [$Xc, $Yc];

                $Xc = cos(($i - 90) * PI / 180) * ($OuterRadius + $DataGapRadius) + $X;
                $Yc = sin(($i - 90) * PI / 180) * ($OuterRadius + $DataGapRadius) * $SkewFactor + $Y;
                $this->pChartObject->drawAntialiasPixel($Xc, $Yc, $Settings);

                if ($OutX1 == VOID) {
                    $OutX1 = $Xc;
                    $OutY1 = $Yc;
                }

                if ($i < 90) {
                    $Yc++;
                }
                if ($i > 90 && $i < 180) {
                    $Xc++;
                }
                if ($i > 180 && $i < 270) {
                    $Xc++;
                }
                if ($i >= 270) {
                    $Xc++;
                    $Yc++;
                }

                $Slices[$Slice]["BottomPoly"][] = floor($Xc);
                $Slices[$Slice]["BottomPoly"][] = floor($Yc);
                $Slices[$Slice]["TopPoly"][] = floor($Xc);
                $Slices[$Slice]["TopPoly"][] = floor($Yc) - $SliceHeight;
                $Slices[$Slice]["Angle"][] = $i;
            }
            $OutX2 = $Xc;
            $OutY2 = $Yc;

            $Slices[$Slice]["Angle"][] = VOID;
            $Lasti = $i;

            $Step = (360 / (2 * PI * $InnerRadius)) / 2;
            $InX1 = VOID;
            $InY1 = VOID;
            for ($i = $EndAngle; $i <= $Offset; $i = $i + $Step) {
                $Xc = cos(($i - 90) * PI / 180) * ($InnerRadius + $DataGapRadius - 1) + $X;
                $Yc = sin(($i - 90) * PI / 180) * ($InnerRadius + $DataGapRadius - 1) * $SkewFactor + $Y;
                $Slices[$Slice]["AA"][] = [$Xc, $Yc];

                $Xc = cos(($i - 90) * PI / 180) * ($InnerRadius + $DataGapRadius) + $X;
                $Yc = sin(($i - 90) * PI / 180) * ($InnerRadius + $DataGapRadius) * $SkewFactor + $Y;
                $Slices[$Slice]["AA"][] = [$Xc, $Yc];

                if ($InX1 == VOID) {
                    $InX1 = $Xc;
                    $InY1 = $Yc;
                }

                if ($i < 90) {
                    $Yc++;
                }
                if ($i > 90 && $i < 180) {
                    $Xc++;
                }
                if ($i > 180 && $i < 270) {
                    $Xc++;
                }
                if ($i >= 270) {
                    $Xc++;
                    $Yc++;
                }

                $Slices[$Slice]["BottomPoly"][] = floor($Xc);
                $Slices[$Slice]["BottomPoly"][] = floor($Yc);
                $Slices[$Slice]["TopPoly"][] = floor($Xc);
                $Slices[$Slice]["TopPoly"][] = floor($Yc) - $SliceHeight;
                $Slices[$Slice]["Angle"][] = $i;
            }
            $InX2 = $Xc;
            $InY2 = $Yc;

            $Slices[$Slice]["InX1"] = $InX1;
            $Slices[$Slice]["InY1"] = $InY1;
            $Slices[$Slice]["InX2"] = $InX2;
            $Slices[$Slice]["InY2"] = $InY2;
            $Slices[$Slice]["OutX1"] = $OutX1;
            $Slices[$Slice]["OutY1"] = $OutY1;
            $Slices[$Slice]["OutX2"] = $OutX2;
            $Slices[$Slice]["OutY2"] = $OutY2;

            $Offset = $Lasti - $DataGapAngle;
            $ID--;
            $Slice++;
        }

        /* Draw the bottom pie splice */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $this->pChartObject->drawPolygon($Plots["BottomPoly"], $Settings);

            foreach ($Plots["AA"] as $Key => $Pos) {
                $this->pChartObject->drawAntialiasPixel($Pos[0], $Pos[1], $Settings);
            }
            $this->pChartObject->drawLine(
                $Plots["InX1"],
                $Plots["InY1"],
                $Plots["OutX2"],
                $Plots["OutY2"],
                $Settings
            );
            $this->pChartObject->drawLine(
                $Plots["InX2"],
                $Plots["InY2"],
                $Plots["OutX1"],
                $Plots["OutY1"],
                $Settings
            );
        }

        $Slices = array_reverse($Slices);
        $SliceColors = array_reverse($SliceColors);

        /* Draw the vertical edges (semi-visible) */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $Settings["R"] = $Settings["R"] + $Cf;
            $Settings["G"] = $Settings["G"] + $Cf;
            $Settings["B"] = $Settings["B"] + $Cf;

            $StartAngle = $Plots["Angle"][0];
            foreach ($Plots["Angle"] as $Key => $Angle) {
                if ($Angle == VOID) {
                    $EndAngle = $Plots["Angle"][$Key - 1];
                }
            }

            if ($StartAngle >= 270 || $StartAngle <= 90) {
                $this->pChartObject->drawLine(
                    $Plots["OutX1"],
                    $Plots["OutY1"],
                    $Plots["OutX1"],
                    $Plots["OutY1"] - $SliceHeight,
                    $Settings
                );
            }
            if ($StartAngle >= 270 || $StartAngle <= 90) {
                $this->pChartObject->drawLine(
                    $Plots["OutX2"],
                    $Plots["OutY2"],
                    $Plots["OutX2"],
                    $Plots["OutY2"] - $SliceHeight,
                    $Settings
                );
            }
            $this->pChartObject->drawLine(
                $Plots["InX1"],
                $Plots["InY1"],
                $Plots["InX1"],
                $Plots["InY1"] - $SliceHeight,
                $Settings
            );
            $this->pChartObject->drawLine(
                $Plots["InX2"],
                $Plots["InY2"],
                $Plots["InX2"],
                $Plots["InY2"] - $SliceHeight,
                $Settings
            );
        }

        /* Draw the inner vertical slices */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $Settings["R"] = $Settings["R"] + $Cf;
            $Settings["G"] = $Settings["G"] + $Cf;
            $Settings["B"] = $Settings["B"] + $Cf;

            $Outer = true;
            $Inner = false;
            $InnerPlotsA = [];
            $InnerPlotsB = [];
            foreach ($Plots["Angle"] as $ID => $Angle) {
                if ($Angle == VOID) {
                    $Outer = false;
                    $Inner = true;
                } elseif ($Inner && ($Angle < 90 || $Angle > 270) && isset($Plots["BottomPoly"][$ID * 2])) {
                    $Xo = $Plots["BottomPoly"][$ID * 2];
                    $Yo = $Plots["BottomPoly"][$ID * 2 + 1];

                    $InnerPlotsA[] = $Xo;
                    $InnerPlotsA[] = $Yo;
                    $InnerPlotsB[] = $Xo;
                    $InnerPlotsB[] = $Yo - $SliceHeight;
                }
            }

            if (count($InnerPlotsA)) {
                $InnerPlots = array_merge($InnerPlotsA, $this->arrayReverse($InnerPlotsB));
                $this->pChartObject->drawPolygon($InnerPlots, $Settings);
            }
        }

        /* Draw the splice top and left poly */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $Settings["R"] = $Settings["R"] + $Cf * 1.5;
            $Settings["G"] = $Settings["G"] + $Cf * 1.5;
            $Settings["B"] = $Settings["B"] + $Cf * 1.5;

            $StartAngle = $Plots["Angle"][0];
            foreach ($Plots["Angle"] as $Key => $Angle) {
                if ($Angle == VOID) {
                    $EndAngle = $Plots["Angle"][$Key - 1];
                }
            }

            if ($StartAngle < 180) {
                $Points = [];
                $Points[] = $Plots["InX2"];
                $Points[] = $Plots["InY2"];
                $Points[] = $Plots["InX2"];
                $Points[] = $Plots["InY2"] - $SliceHeight;
                $Points[] = $Plots["OutX1"];
                $Points[] = $Plots["OutY1"] - $SliceHeight;
                $Points[] = $Plots["OutX1"];
                $Points[] = $Plots["OutY1"];

                $this->pChartObject->drawPolygon($Points, $Settings);
            }

            if ($EndAngle > 180) {
                $Points = [];
                $Points[] = $Plots["InX1"];
                $Points[] = $Plots["InY1"];
                $Points[] = $Plots["InX1"];
                $Points[] = $Plots["InY1"] - $SliceHeight;
                $Points[] = $Plots["OutX2"];
                $Points[] = $Plots["OutY2"] - $SliceHeight;
                $Points[] = $Plots["OutX2"];
                $Points[] = $Plots["OutY2"];

                $this->pChartObject->drawPolygon($Points, $Settings);
            }
        }


        /* Draw the vertical edges (visible) */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $Settings["R"] = $Settings["R"] + $Cf;
            $Settings["G"] = $Settings["G"] + $Cf;
            $Settings["B"] = $Settings["B"] + $Cf;

            $StartAngle = $Plots["Angle"][0];
            foreach ($Plots["Angle"] as $Key => $Angle) {
                if ($Angle == VOID) {
                    $EndAngle = $Plots["Angle"][$Key - 1];
                }
            }

            if ($StartAngle <= 270 && $StartAngle >= 90) {
                $this->pChartObject->drawLine(
                    $Plots["OutX1"],
                    $Plots["OutY1"],
                    $Plots["OutX1"],
                    $Plots["OutY1"] - $SliceHeight,
                    $Settings
                );
            }
            if ($EndAngle <= 270 && $EndAngle >= 90) {
                $this->pChartObject->drawLine(
                    $Plots["OutX2"],
                    $Plots["OutY2"],
                    $Plots["OutX2"],
                    $Plots["OutY2"] - $SliceHeight,
                    $Settings
                );
            }
        }


        /* Draw the outer vertical slices */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $Settings["R"] = $Settings["R"] + $Cf;
            $Settings["G"] = $Settings["G"] + $Cf;
            $Settings["B"] = $Settings["B"] + $Cf;

            $Outer = true;
            $Inner = false;
            $OuterPlotsA = [];
            $OuterPlotsB = [];
            $InnerPlotsA = [];
            $InnerPlotsB = [];
            foreach ($Plots["Angle"] as $ID => $Angle) {
                if ($Angle == VOID) {
                    $Outer = false;
                    $Inner = true;
                } elseif ($Outer && ($Angle > 90 && $Angle < 270) && isset($Plots["BottomPoly"][$ID * 2])) {
                    $Xo = $Plots["BottomPoly"][$ID * 2];
                    $Yo = $Plots["BottomPoly"][$ID * 2 + 1];

                    $OuterPlotsA[] = $Xo;
                    $OuterPlotsA[] = $Yo;
                    $OuterPlotsB[] = $Xo;
                    $OuterPlotsB[] = $Yo - $SliceHeight;
                }
            }
            if (count($OuterPlotsA)) {
                $OuterPlots = array_merge($OuterPlotsA, $this->arrayReverse($OuterPlotsB));
                $this->pChartObject->drawPolygon($OuterPlots, $Settings);
            }
        }

        $Slices = array_reverse($Slices);
        $SliceColors = array_reverse($SliceColors);

        /* Draw the top pie splice */
        foreach ($Slices as $SliceID => $Plots) {
            $Settings = $SliceColors[$SliceID];
            $Settings["NoBorder"] = true;
            $Settings["R"] = $Settings["R"] + $Cf * 2;
            $Settings["G"] = $Settings["G"] + $Cf * 2;
            $Settings["B"] = $Settings["B"] + $Cf * 2;

            $this->pChartObject->drawPolygon($Plots["TopPoly"], $Settings);

            if ($RecordImageMap) {
                $this->pChartObject->addToImageMap(
                    "POLY",
                    $this->arraySerialize($Plots["TopPoly"]),
                    $this->pChartObject->toHTMLColor(
                        $Settings["R"],
                        $Settings["G"],
                        $Settings["B"]
                    ),
                    $Data["Series"][$Data["Abscissa"]]["Data"][$SliceID],
                    $Data["Series"][$DataSerie]["Data"][count($Slices) - $SliceID - 1]
                );
            }

            foreach ($Plots["AA"] as $Key => $Pos) {
                $this->pChartObject->drawAntialiasPixel(
                    $Pos[0],
                    $Pos[1] - $SliceHeight,
                    $Settings
                );
            }
            $this->pChartObject->drawLine(
                $Plots["InX1"],
                $Plots["InY1"] - $SliceHeight,
                $Plots["OutX2"],
                $Plots["OutY2"] - $SliceHeight,
                $Settings
            );
            $this->pChartObject->drawLine(
                $Plots["InX2"],
                $Plots["InY2"] - $SliceHeight,
                $Plots["OutX1"],
                $Plots["OutY1"] - $SliceHeight,
                $Settings
            );
        }

        if ($DrawLabels) {
            $Offset = 360;
            foreach ($Values as $Key => $Value) {
                $StartAngle = $Offset;
                $EndAngle = $Offset - ($Value * $ScaleFactor);
                if ($EndAngle < 0) {
                    $EndAngle = 0;
                }

                if ($LabelColor == PIE_LABEL_COLOR_AUTO) {
                    $Settings = [
                        "FillR" => $Palette[$ID]["R"],
                        "FillG" => $Palette[$ID]["G"],
                        "FillB" => $Palette[$ID]["B"],
                        "Alpha" => $Palette[$ID]["Alpha"]
                    ];
                } else {
                    $Settings = [
                        "FillR" => $LabelR,
                        "FillG" => $LabelG,
                        "FillB" => $LabelB,
                        "Alpha" => $LabelAlpha
                    ];
                }

                $Angle = ($EndAngle - $Offset) / 2 + $Offset;
                $Xc = cos(($Angle - 90) * PI / 180) * ($OuterRadius + $DataGapRadius) + $X;
                $Yc = sin(($Angle - 90) * PI / 180) * ($OuterRadius + $DataGapRadius) * $SkewFactor + $Y;

                $Label = "";
                if ($WriteValues == PIE_VALUE_PERCENTAGE) {
                    $Label = round((100 / $SerieSum) * $Value, $Precision) . "%";
                } elseif ($WriteValues == PIE_VALUE_NATURAL) {
                    $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key];
                }

                if ($LabelStacked) {
                    $this->writePieLabel(
                        $Xc,
                        $Yc - $SliceHeight,
                        $Label,
                        $Angle,
                        $Settings,
                        true,
                        $X,
                        $Y,
                        $OuterRadius
                    );
                } else {
                    $this->writePieLabel($Xc, $Yc - $SliceHeight, $Label, $Angle, $Settings, false);
                }
                $Offset = $EndAngle - $DataGapAngle;
                $ID--;
                $Slice++;
            }
        }
        if ($DrawLabels && $LabelStacked) {
            $this->writeShiftedLabels();
        }

        $this->pChartObject->Shadow = $RestoreShadow;

        return PIE_RENDERED;
    }
1072107
function addJpegFromFile( $img, $x, $y, $w = 0, $h = 0 )
    {
        // attempt to add a jpeg image straight from a file, using no GD commands
        // note that this function is unable to operate on a remote file.

        if ( !file_exists( $img ) )
        {
            //echo "FILE NOT EXISTS: $img";
            return;
        }

        $tmp = getimagesize( $img );
        $imageWidth = $tmp[0];
        $imageHeight = $tmp[1];

        if ( isset( $tmp['channels'] ) )
        {
            $channels = $tmp['channels'];
        }
        else
        {
            $channels = 3;
        }

        if ( $w <= 0 && $h <= 0 )
        {
            $w = $imageWidth;
        }
        if ( $w == 0 )
        {
            $w = $h / $imageHeight * $imageWidth;
        }
        if ( $h == 0 )
        {
            $h = $w * $imageHeight / $imageWidth;
        }

        $fp = fopen( $img, 'rb' );

        $data = fread( $fp, filesize( $img ) );

        fclose( $fp );

        $this->addJpegImage_common( $data, $x, $y, $w, $h, $imageWidth, $imageHeight, $channels );
    }
497882
protected function doDrawPolygon(array $x, array $y, $type)
    {
        list($image, $point) = $this->getCurrentClip();
        
        $color = $this->createColor($this->state['fillColor']);
        
        $fill = $type > 0;
        
        $coords = array();
        
        foreach($x as $i => $coord)
        {
            $coords[] = $this->translatePoint($point, $coord, $this->convertYCoord($y[$i]));
        }
        
        $polygons = array();
        
        if($this->isFillShape($type))
        {
            $polygons[] = array($this->createColor($this->state['fillColor']), true);
        }
        
        if($this->isStrokeShape($type))
        {
            $polygons[] = array($this->createColor($this->state['lineColor']), false);
        }
        
        foreach($polygons as $polygon)
        {
            list($color, $fill) = $polygon;
            $image->draw()->polygon($coords, $color, $fill);
        }
    }