src/graph/Shape.php
<?php
/**
* JPGraph v4.0.3
*/
namespace Amenadiel\JpGraph\Graph;
/*
* File: JPGRAPH_CANVTOOLS.PHP
* // Description: Some utilities for text and shape drawing on a canvas
* // Created: 2002-08-23
* // Ver: $Id: jpgraph_canvtools.php 1857 2009-09-28 14:38:14Z ljp $
* //
* // Copyright (c) Asial Corporation. All rights reserved.
*/
define('CORNER_TOPLEFT', 0);
define('CORNER_TOPRIGHT', 1);
define('CORNER_BOTTOMRIGHT', 2);
define('CORNER_BOTTOMLEFT', 3);
/**
* @class Shape
* // Description: Methods to draw shapes on canvas
*/
class Shape
{
private $img;
private $scale;
public function __construct($aGraph, $scale)
{
$this->img = $aGraph->img;
$this->img->SetColor('black');
$this->scale = $scale;
}
public function SetColor($aColor)
{
$this->img->SetColor($aColor);
}
public function Line($x1, $y1, $x2, $y2)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
list($x2, $y2) = $this->scale->Translate($x2, $y2);
$this->img->Line($x1, $y1, $x2, $y2);
}
public function SetLineWeight($aWeight)
{
$this->img->SetLineWeight($aWeight);
}
public function Polygon($p, $aClosed = false)
{
$n = safe_count($p);
for ($i = 0; $i < $n; $i += 2) {
$p[$i] = $this->scale->TranslateX($p[$i]);
$p[$i + 1] = $this->scale->TranslateY($p[$i + 1]);
}
$this->img->Polygon($p, $aClosed);
}
public function FilledPolygon($p)
{
$n = safe_count($p);
for ($i = 0; $i < $n; $i += 2) {
$p[$i] = $this->scale->TranslateX($p[$i]);
$p[$i + 1] = $this->scale->TranslateY($p[$i + 1]);
}
$this->img->FilledPolygon($p);
}
// Draw a bezier curve with defining points in the $aPnts array
// using $aSteps steps.
// 0=x0, 1=y0
// 2=x1, 3=y1
// 4=x2, 5=y2
// 6=x3, 7=y3
public function Bezier($p, $aSteps = 40)
{
$x0 = $p[0];
$y0 = $p[1];
// Calculate coefficients
$cx = 3 * ($p[2] - $p[0]);
$bx = 3 * ($p[4] - $p[2]) - $cx;
$ax = $p[6] - $p[0] - $cx - $bx;
$cy = 3 * ($p[3] - $p[1]);
$by = 3 * ($p[5] - $p[3]) - $cy;
$ay = $p[7] - $p[1] - $cy - $by;
// Step size
$delta = 1.0 / $aSteps;
$x_old = $x0;
$y_old = $y0;
for ($t = $delta; $t <= 1.0; $t += $delta) {
$tt = $t * $t;
$ttt = $tt * $t;
$x = $ax * $ttt + $bx * $tt + $cx * $t + $x0;
$y = $ay * $ttt + $by * $tt + $cy * $t + $y0;
$this->Line($x_old, $y_old, $x, $y);
$x_old = $x;
$y_old = $y;
}
$this->Line($x_old, $y_old, $p[6], $p[7]);
}
public function Rectangle($x1, $y1, $x2, $y2)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
list($x2, $y2) = $this->scale->Translate($x2, $y2);
$this->img->Rectangle($x1, $y1, $x2, $y2);
}
public function FilledRectangle($x1, $y1, $x2, $y2)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
list($x2, $y2) = $this->scale->Translate($x2, $y2);
$this->img->FilledRectangle($x1, $y1, $x2, $y2);
}
public function Circle($x1, $y1, $r)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
if ($r >= 0) {
$r = $this->scale->TranslateX($r);
} else {
$r = -$r;
}
$this->img->Circle($x1, $y1, $r);
}
public function FilledCircle($x1, $y1, $r)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
if ($r >= 0) {
$r = $this->scale->TranslateX($r);
} else {
$r = -$r;
}
$this->img->FilledCircle($x1, $y1, $r);
}
public function RoundedRectangle($x1, $y1, $x2, $y2, $r = null)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
list($x2, $y2) = $this->scale->Translate($x2, $y2);
if ($r == null) {
$r = 5;
} elseif ($r >= 0) {
$r = $this->scale->TranslateX($r);
} else {
$r = -$r;
}
$this->img->RoundedRectangle($x1, $y1, $x2, $y2, $r);
}
public function FilledRoundedRectangle($x1, $y1, $x2, $y2, $r = null)
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
list($x2, $y2) = $this->scale->Translate($x2, $y2);
if ($r == null) {
$r = 5;
} elseif ($r > 0) {
$r = $this->scale->TranslateX($r);
} else {
$r = -$r;
}
$this->img->FilledRoundedRectangle($x1, $y1, $x2, $y2, $r);
}
public function ShadowRectangle($x1, $y1, $x2, $y2, $fcolor = false, $shadow_width = null, $shadow_color = [102, 102, 102])
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
list($x2, $y2) = $this->scale->Translate($x2, $y2);
if ($shadow_width == null) {
$shadow_width = 4;
} else {
$shadow_width = $this->scale->TranslateX($shadow_width);
}
$this->img->ShadowRectangle($x1, $y1, $x2, $y2, $fcolor, $shadow_width, $shadow_color);
}
public function SetTextAlign($halign, $valign = 'bottom')
{
$this->img->SetTextAlign($halign, $valign = 'bottom');
}
public function StrokeText($x1, $y1, $txt, $dir = 0, $paragraph_align = 'left')
{
list($x1, $y1) = $this->scale->Translate($x1, $y1);
$this->img->StrokeText($x1, $y1, $txt, $dir, $paragraph_align);
}
// A rounded rectangle where one of the corner has been moved "into" the
// rectangle 'iw' width and 'ih' height. Corners:
// 0=Top left, 1=top right, 2=bottom right, 3=bottom left
public function IndentedRectangle($xt, $yt, $w, $h, $iw = 0, $ih = 0, $aCorner = 3, $aFillColor = '', $r = 4)
{
list($xt, $yt) = $this->scale->Translate($xt, $yt);
list($w, $h) = $this->scale->Translate($w, $h);
list($iw, $ih) = $this->scale->Translate($iw, $ih);
$xr = $xt + $w - 0;
$yl = $yt + $h - 0;
switch ($aCorner) {
case 0:
// Bottom line, left & right arc
$this->img->Line($xt + $r, $yl, $xr - $r, $yl);
$this->img->Arc($xt + $r, $yl - $r, $r * 2, $r * 2, 90, 180);
$this->img->Arc($xr - $r, $yl - $r, $r * 2, $r * 2, 0, 90);
// Right line, Top right arc
$this->img->Line($xr, $yt + $r, $xr, $yl - $r);
$this->img->Arc($xr - $r, $yt + $r, $r * 2, $r * 2, 270, 360);
// Top line, Top left arc
$this->img->Line($xt + $iw + $r, $yt, $xr - $r, $yt);
$this->img->Arc($xt + $iw + $r, $yt + $r, $r * 2, $r * 2, 180, 270);
// Left line
$this->img->Line($xt, $yt + $ih + $r, $xt, $yl - $r);
// Indent horizontal, Lower left arc
$this->img->Line($xt + $r, $yt + $ih, $xt + $iw - $r, $yt + $ih);
$this->img->Arc($xt + $r, $yt + $ih + $r, $r * 2, $r * 2, 180, 270);
// Indent vertical, Indent arc
$this->img->Line($xt + $iw, $yt + $r, $xt + $iw, $yt + $ih - $r);
$this->img->Arc($xt + $iw - $r, $yt + $ih - $r, $r * 2, $r * 2, 0, 90);
if ($aFillColor != '') {
$bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor);
$this->img->FillToBorder($xr - $r, $yl - $r, $bc);
$this->img->PopColor();
}
break;
case 1:
// Bottom line, left & right arc
$this->img->Line($xt + $r, $yl, $xr - $r, $yl);
$this->img->Arc($xt + $r, $yl - $r, $r * 2, $r * 2, 90, 180);
$this->img->Arc($xr - $r, $yl - $r, $r * 2, $r * 2, 0, 90);
// Left line, Top left arc
$this->img->Line($xt, $yt + $r, $xt, $yl - $r);
$this->img->Arc($xt + $r, $yt + $r, $r * 2, $r * 2, 180, 270);
// Top line, Top right arc
$this->img->Line($xt + $r, $yt, $xr - $iw - $r, $yt);
$this->img->Arc($xr - $iw - $r, $yt + $r, $r * 2, $r * 2, 270, 360);
// Right line
$this->img->Line($xr, $yt + $ih + $r, $xr, $yl - $r);
// Indent horizontal, Lower right arc
$this->img->Line($xr - $iw + $r, $yt + $ih, $xr - $r, $yt + $ih);
$this->img->Arc($xr - $r, $yt + $ih + $r, $r * 2, $r * 2, 270, 360);
// Indent vertical, Indent arc
$this->img->Line($xr - $iw, $yt + $r, $xr - $iw, $yt + $ih - $r);
$this->img->Arc($xr - $iw + $r, $yt + $ih - $r, $r * 2, $r * 2, 90, 180);
if ($aFillColor != '') {
$bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor);
$this->img->FillToBorder($xt + $r, $yl - $r, $bc);
$this->img->PopColor();
}
break;
case 2: // Lower right
// Top line, Top left & Top right arc
$this->img->Line($xt + $r, $yt, $xr - $r, $yt);
$this->img->Arc($xt + $r, $yt + $r, $r * 2, $r * 2, 180, 270);
$this->img->Arc($xr - $r, $yt + $r, $r * 2, $r * 2, 270, 360);
// Left line, Bottom left arc
$this->img->Line($xt, $yt + $r, $xt, $yl - $r);
$this->img->Arc($xt + $r, $yl - $r, $r * 2, $r * 2, 90, 180);
// Bottom line, Bottom right arc
$this->img->Line($xt + $r, $yl, $xr - $iw - $r, $yl);
$this->img->Arc($xr - $iw - $r, $yl - $r, $r * 2, $r * 2, 0, 90);
// Right line
$this->img->Line($xr, $yt + $r, $xr, $yl - $ih - $r);
// Indent horizontal, Lower right arc
$this->img->Line($xr - $r, $yl - $ih, $xr - $iw + $r, $yl - $ih);
$this->img->Arc($xr - $r, $yl - $ih - $r, $r * 2, $r * 2, 0, 90);
// Indent vertical, Indent arc
$this->img->Line($xr - $iw, $yl - $r, $xr - $iw, $yl - $ih + $r);
$this->img->Arc($xr - $iw + $r, $yl - $ih + $r, $r * 2, $r * 2, 180, 270);
if ($aFillColor != '') {
$bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor);
$this->img->FillToBorder($xt + $r, $yt + $r, $bc);
$this->img->PopColor();
}
break;
case 3: // Lower left
// Top line, Top left & Top right arc
$this->img->Line($xt + $r, $yt, $xr - $r, $yt);
$this->img->Arc($xt + $r, $yt + $r, $r * 2, $r * 2, 180, 270);
$this->img->Arc($xr - $r, $yt + $r, $r * 2, $r * 2, 270, 360);
// Right line, Bottom right arc
$this->img->Line($xr, $yt + $r, $xr, $yl - $r);
$this->img->Arc($xr - $r, $yl - $r, $r * 2, $r * 2, 0, 90);
// Bottom line, Bottom left arc
$this->img->Line($xt + $iw + $r, $yl, $xr - $r, $yl);
$this->img->Arc($xt + $iw + $r, $yl - $r, $r * 2, $r * 2, 90, 180);
// Left line
$this->img->Line($xt, $yt + $r, $xt, $yl - $ih - $r);
// Indent horizontal, Lower left arc
$this->img->Line($xt + $r, $yl - $ih, $xt + $iw - $r, $yl - $ih);
$this->img->Arc($xt + $r, $yl - $ih - $r, $r * 2, $r * 2, 90, 180);
// Indent vertical, Indent arc
$this->img->Line($xt + $iw, $yl - $ih + $r, $xt + $iw, $yl - $r);
$this->img->Arc($xt + $iw - $r, $yl - $ih + $r, $r * 2, $r * 2, 270, 360);
if ($aFillColor != '') {
$bc = $this->img->current_color_name;
$this->img->PushColor($aFillColor);
$this->img->FillToBorder($xr - $r, $yt + $r, $bc);
$this->img->PopColor();
}
break;
}
}
}