* @license BSD */ namespace Domframework; /** * The graphStyleLine : draw a graph with lines */ class GraphStyleLinePoints { /** * The line color. To hide the lines, choose "transparent" */ protected $lineColor; /** * The point color background. To hide the points, choose "transparent" */ protected $pointBgcolor; /** * The point color border */ protected $pointColor; /** * The point shape (square, circle, triangle, lozenge) */ protected $pointShape; /** * The point width in pixel */ protected $pointWidth; /** * The number of the colors/shapes to use */ protected $number; /** * The allowed shapes */ protected $allowedShapes = ["square", "circle", "triangle", "lozenge"]; /** * The palette to use */ protected $palette; /** * Return the name of the style */ public function name() { return "lineAndPoints"; } /** * Set the line color if the parameter is provided. * Get the line color if the parameter is not provided * @param string|null $lineColor The line color */ public function lineColor($lineColor = null) { if ($lineColor === null) { return $this->lineColor; } if ( ! is_string($lineColor) || ($lineColor !== "transparent" && ! in_array($lineColor, Color::colorList(), true)) ) { throw new \Exception(dgettext( "domframework", "Invalid lineColor provided to line style" ), 406); } $this->lineColor = $lineColor; return $this; } /** * Set the palette to use if the parameter is provided * Get the palette if the parameter is not provided * @param string|null $palette The palette to use */ public function palette($palette = null) { if ($palette === null) { return $this->palette; } if (! is_string($palette)) { throw new \Exception(dgettext( "domframework", "Invalid palette provided to line style" ), 406); } $this->palette = $palette; return $this; } /** * Set the point background color if the parameter is provided. * Get the point background color if the parameter is not provided * @param string|null $pointBgcolor The point background color */ public function pointBgcolor($pointBgcolor = null) { if ($pointBgcolor === null) { return $this->pointBgcolor; } if ( ! is_string($pointBgcolor) || ($pointBgcolor !== "transparent" && ! in_array($pointBgcolor, Color::colorList(), true)) ) { throw new \Exception(dgettext( "domframework", "Invalid pointBgcolor provided to line style" ), 406); } $this->pointBgcolor = $pointBgcolor; return $this; } /** * Set the point border color if the parameter is provided. * Get the point border color if the parameter is not provided * @param string|null $pointColor The point border color */ public function pointColor($pointColor = null) { if ($pointColor === null) { return $this->pointColor; } if ( ! is_string($pointColor) || ($pointColor !== "transparent" && ! in_array($pointColor, Color::colorList(), true)) ) { throw new \Exception(dgettext( "domframework", "Invalid pointColor provided to line style" ), 406); } $this->pointColor = $pointColor; return $this; } /** * Set the point shape if the parameter is provided. * Get the point shape if the parameter is not provided * @param string|null $pointShape The point shape */ public function pointShape($pointShape = null) { if ($pointShape === null) { return $this->pointShape; } if ( ! is_string($pointShape) || ! in_array($pointShape, $this->allowedShapes, true) ) { throw new \Exception(dgettext( "domframework", "Invalid pointShape provided to line style" ), 406); } $this->pointShape = $pointShape; return $this; } /** * Set the point width if the parameter is provided. * Get the point width if the parameter is not provided * @param string|null $pointWidth The point width */ public function pointWidth($pointWidth = null) { if ($pointWidth === null) { return $this->pointWidth; } if (! is_integer($pointWidth) || $pointWidth < 3 || $pointWidth > 20) { throw new \Exception(dgettext( "domframework", "Invalid pointWidth provided to line style" ), 406); } $this->pointWidth = $pointWidth; return $this; } /** * Select the colors, shapes by the serie number. * Do not change any property if the property is already defined * If the parameter is not provided, return the value * @param integer|null $number The serie number */ public function number($number = null) { if ($number === null) { return $this->number; } if (! is_int($number) || $number < 0) { throw new \Exception(dgettext( "domframework", "Invalid number provided to line style number" ), 406); } $this->number = $number; if ($this->pointShape === null) { $this->pointShape = $this->allowedShapes[ ($number % count($this->allowedShapes))]; } $palette = GraphPalette::getPalette($this->palette); if ($this->pointBgcolor === null) { $this->pointBgcolor = $palette[($number % count($palette))]["bgcolor"]; } if ($this->pointColor === null) { $this->pointColor = $palette[($number % count($palette))]["color"]; } if ($this->lineColor === null) { $this->lineColor = $palette[($number % count($palette))]["color"]; } } /** * Draw in the $gd resource, in the $free array, the data with the parameter * of the style * @param resource $gd The resource to modify * @param array $free The free space coordinates on the graphic * @param array $data The data to graph * @param object $axisX The X axis used to graph * @param object $axisY The Y axis used to graph */ public function draw($gd, $free, $data, $axisX, $axisY) { if ($this->lineColor !== "transparent") { $lineColor = Color::allocateFromText($gd, $this->lineColor); } $lastX = null; $lastY = null; foreach ($data as $key => $value) { $posX = $axisX->position($key); $posY = $axisY->position($value); if ($posX === null || $posY === null) { // NULL position : skip the point $lastX = null; $lastY = null; continue; } // Draw the lines between points (except if the last point was null, or // if the line color is "transparent") if ( $lastX !== null && $lastY !== null && $this->lineColor !== "transparent" ) { imageline($gd, $lastX, $lastY, $posX, $posY, $lineColor); // Redraw the old point which was scratch by the new created line $this->drawPoint($gd, $lastX, $lastY); } if ($lastX === null) { $lastX = $posX; } if ($lastY === null) { $lastY = $posY; } // Draw the point. Will overwrite the lines if ($this->pointWidth === null) { $this->pointWidth = 6; } $this->drawPoint($gd, $posX, $posY); $lastX = $posX; $lastY = $posY; } } /** * Draw a point defined in the property of the class * @param resource $gd The resource to modify * @param integer $posX The X position to draw the point * @param integer $posY The Y position to draw the point */ private function drawPoint($gd, $posX, $posY) { if ($this->pointColor !== "transparent") { $pointColor = Color::allocateFromText($gd, $this->pointColor); } if ($this->pointBgcolor !== "transparent") { $pointBgcolor = Color::allocateFromText($gd, $this->pointBgcolor); } $half = intval($this->pointWidth / 2); switch ($this->pointShape) { case "circle": if ($this->pointBgcolor !== "transparent") { imagefilledellipse( $gd, $posX, $posY, $this->pointWidth, $this->pointWidth, $pointBgcolor + 2 ); } if ($this->pointColor !== "transparent") { imageellipse( $gd, $posX, $posY, $this->pointWidth + 2, $this->pointWidth + 2, $pointColor ); } break; case "lozenge": if ($this->pointBgcolor !== "transparent") { imagefilledpolygon( $gd, [$posX - $half - 2, $posY, $posX, $posY - $half - 2, $posX + $half + 2, $posY, $posX, $posY + $half + 2], 4, $pointBgcolor ); } if ($this->pointColor !== "transparent") { imagepolygon( $gd, [$posX - $half - 2, $posY, $posX, $posY - $half - 2, $posX + $half + 2, $posY, $posX, $posY + $half + 2], 4, $pointColor ); } break; case "square": if ($this->pointBgcolor !== "transparent") { imagefilledrectangle( $gd, $posX - $half - 1, $posY - $half - 1, $posX + $half + 1, $posY + $half + 1, $pointBgcolor ); } if ($this->pointColor !== "transparent") { imagerectangle( $gd, $posX - $half - 1, $posY - $half - 1, $posX + $half + 1, $posY + $half + 1, $pointColor ); } break; case "triangle": if ($this->pointBgcolor !== "transparent") { imagefilledpolygon( $gd, [$posX - $half - 2, $posY + $half + 2, $posX, $posY - $half - 2, $posX + $half + 2, $posY + $half + 2], 3, $pointBgcolor ); } if ($this->pointColor !== "transparent") { imagepolygon( $gd, [$posX - $half - 2, $posY + $half + 2, $posX, $posY - $half - 2, $posX + $half + 2, $posY + $half + 2], 3, $pointColor ); } break; default: throw new \Exception(dgettext( "domframework", "Unknown pointShape for serie" ), 406); } } /** * Draw a sample of the style for the legend * @param resource $gd The resource to modify * @param integer $x The central position of the sample in x * @param integer $y The central position of the sample in y */ public function sample($gd, $x, $y) { if ($this->lineColor !== "transparent") { $lineColor = Color::allocateFromText($gd, $this->lineColor); imageline($gd, $x - 10, $y, $x + 10, $y, $lineColor); } if ($this->pointWidth === null) { $this->pointWidth = 6; } $this->drawPoint($gd, $x, $y); } }