|
<?php |
|
/* |
|
pDraw - class extension with drawing methods |
|
|
|
Version : 2.1.0 |
|
Made by : Jean-Damien POGOLOTTI |
|
Last Update : 26/01/11 |
|
|
|
This file can be distributed under the license you can find at : |
|
|
|
http://www.pchart.net/license |
|
|
|
You can find the whole class documentation on the pChart web site. |
|
*/ |
|
|
|
define("DIRECTION_VERTICAL" , 690001); |
|
define("DIRECTION_HORIZONTAL" , 690002); |
|
|
|
define("SCALE_POS_LEFTRIGHT" , 690101); |
|
define("SCALE_POS_TOPBOTTOM" , 690102); |
|
|
|
define("SCALE_MODE_FLOATING" , 690201); |
|
define("SCALE_MODE_START0" , 690202); |
|
define("SCALE_MODE_ADDALL" , 690203); |
|
define("SCALE_MODE_ADDALL_START0" , 690204); |
|
define("SCALE_MODE_MANUAL" , 690205); |
|
|
|
define("SCALE_SKIP_NONE" , 690301); |
|
define("SCALE_SKIP_SAME" , 690302); |
|
define("SCALE_SKIP_NUMBERS" , 690303); |
|
|
|
define("TEXT_ALIGN_TOPLEFT" , 690401); |
|
define("TEXT_ALIGN_TOPMIDDLE" , 690402); |
|
define("TEXT_ALIGN_TOPRIGHT" , 690403); |
|
define("TEXT_ALIGN_MIDDLELEFT" , 690404); |
|
define("TEXT_ALIGN_MIDDLEMIDDLE" , 690405); |
|
define("TEXT_ALIGN_MIDDLERIGHT" , 690406); |
|
define("TEXT_ALIGN_BOTTOMLEFT" , 690407); |
|
define("TEXT_ALIGN_BOTTOMMIDDLE" , 690408); |
|
define("TEXT_ALIGN_BOTTOMRIGHT" , 690409); |
|
|
|
define("POSITION_TOP" , 690501); |
|
define("POSITION_BOTTOM" , 690502); |
|
|
|
define("LABEL_POS_LEFT" , 690601); |
|
define("LABEL_POS_CENTER" , 690602); |
|
define("LABEL_POS_RIGHT" , 690603); |
|
define("LABEL_POS_TOP" , 690604); |
|
define("LABEL_POS_BOTTOM" , 690605); |
|
define("LABEL_POS_INSIDE" , 690606); |
|
define("LABEL_POS_OUTSIDE" , 690607); |
|
|
|
define("ORIENTATION_HORIZONTAL" , 690701); |
|
define("ORIENTATION_VERTICAL" , 690702); |
|
|
|
define("LEGEND_NOBORDER" , 690800); |
|
define("LEGEND_BOX" , 690801); |
|
define("LEGEND_ROUND" , 690802); |
|
|
|
define("LEGEND_VERTICAL" , 690901); |
|
define("LEGEND_HORIZONTAL" , 690902); |
|
|
|
define("LEGEND_FAMILY_BOX" , 691051); |
|
define("LEGEND_FAMILY_CIRCLE" , 691052); |
|
define("LEGEND_FAMILY_LINE" , 691053); |
|
|
|
define("DISPLAY_AUTO" , 691001); |
|
define("DISPLAY_MANUAL" , 691002); |
|
|
|
define("LABELING_ALL" , 691011); |
|
define("LABELING_DIFFERENT" , 691012); |
|
|
|
define("BOUND_MIN" , 691021); |
|
define("BOUND_MAX" , 691022); |
|
define("BOUND_BOTH" , 691023); |
|
|
|
define("BOUND_LABEL_POS_TOP" , 691031); |
|
define("BOUND_LABEL_POS_BOTTOM" , 691032); |
|
define("BOUND_LABEL_POS_AUTO" , 691033); |
|
|
|
define("CAPTION_LEFT_TOP" , 691041); |
|
define("CAPTION_RIGHT_BOTTOM" , 691042); |
|
|
|
define("GRADIENT_SIMPLE" , 691051); |
|
define("GRADIENT_EFFECT_CAN" , 691052); |
|
|
|
define("PI" , 3.14159265); |
|
define("ALL" , 69); |
|
define("NONE" , 31); |
|
define("AUTO" , 690000); |
|
define("OUT_OF_SIGHT" , -10000000000000); |
|
|
|
class pDraw |
|
{ |
|
/* Returns the number of drawable series */ |
|
function countDrawableSeries() |
|
{ |
|
$Results = 0; |
|
$Data = $this->DataSet->getData(); |
|
|
|
foreach($Data["Series"] as $SerieName => $Serie) |
|
{ if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) { $Results++; } } |
|
|
|
return($Results); |
|
} |
|
|
|
/* Fix box coordinates */ |
|
function fixBoxCoordinates($Xa,$Ya,$Xb,$Yb) |
|
{ |
|
$X1 = min($Xa,$Xb); $Y1 = min($Ya,$Yb); |
|
$X2 = max($Xa,$Xb); $Y2 = max($Ya,$Yb); |
|
|
|
return(array($X1,$Y1,$X2,$Y2)); |
|
} |
|
|
|
/* Draw a polygon */ |
|
function drawPolygon($Points,$Format="") |
|
{ |
|
$R = isset($Format["R"]) ? $Format["R"] : 0; |
|
$G = isset($Format["G"]) ? $Format["G"] : 0; |
|
$B = isset($Format["B"]) ? $Format["B"] : 0; |
|
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; |
|
$NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; |
|
$BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; |
|
$BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; |
|
$BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; |
|
$BorderAlpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $Alpha / 2; |
|
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; |
|
$SkipX = isset($Format["SkipX"]) ? $Format["SkipX"] : OUT_OF_SIGHT; |
|
$SkipY = isset($Format["SkipY"]) ? $Format["SkipY"] : OUT_OF_SIGHT; |
|
|
|
/* Calling the ImageFilledPolygon() function over the $Points array will round it */ |
|
$Backup = $Points; |
|
|
|
if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } |
|
|
|
if ( $SkipX != OUT_OF_SIGHT ) { $SkipX = floor($SkipX); } |
|
if ( $SkipY != OUT_OF_SIGHT ) { $SkipY = floor($SkipY); } |
|
|
|
$RestoreShadow = $this->Shadow; |
|
if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) |
|
{ |
|
$this->Shadow = FALSE; |
|
for($i=0;$i<=count($Points)-1;$i=$i+2) |
|
{ $Shadow[] = $Points[$i] + $this->ShadowX; $Shadow[] = $Points[$i+1] + $this->ShadowY; } |
|
$this->drawPolygon($Shadow,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"NoBorder"=>TRUE)); |
|
} |
|
|
|
$FillColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); |
|
|
|
if ( count($Points) >= 6 ) |
|
{ ImageFilledPolygon($this->Picture,$Points,count($Points)/2,$FillColor); } |
|
|
|
if ( !$NoBorder ) |
|
{ |
|
$Points = $Backup; |
|
|
|
$BorderSettings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha); |
|
for($i=0;$i<=count($Points)-1;$i=$i+2) |
|
{ |
|
if ( isset($Points[$i+2]) ) |
|
{ |
|
if ( !($Points[$i] == $Points[$i+2] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[$i+3] && $Points[$i+1] == $SkipY ) ) |
|
$this->drawLine($Points[$i],$Points[$i+1],$Points[$i+2],$Points[$i+3],$BorderSettings); |
|
} |
|
else |
|
{ |
|
if ( !($Points[$i] == $Points[0] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[1] && $Points[$i+1] == $SkipY ) ) |
|
$this->drawLine($Points[$i],$Points[$i+1],$Points[0],$Points[1],$BorderSettings); |
|
} |
|
} |
|
} |
|
|
|
$this->Shadow = $RestoreShadow; |
|
} |
|
|
|
/* Apply AALias correction to the rounded box boundaries */ |
|
function offsetCorrection($Value,$Mode) |
|
{ |
|
$Value = round($Value,1); |
|
|
|
if ( $Value == 0 && $Mode == 1 ) { return(.9); } |
|
if ( $Value == 0 ) { return(0); } |
|
|
|
if ( $Mode == 1) |
|
{ if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.9); }; if ( $Value == .2 ) { return(.8); }; if ( $Value == .3 ) { return(.8); }; if ( $Value == .4 ) { return(.7); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.6); }; if ( $Value == .9 ) { return(.9); }; } |
|
|
|
if ( $Mode == 2) |
|
{ if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.8); }; if ( $Value == .9 ) { return(.9); }; } |
|
|
|
if ( $Mode == 3) |
|
{ if ( $Value == 1 ) { return(.1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.9); }; if ( $Value == .6 ) { return(.6); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.4); }; if ( $Value == .9 ) { return(.5); }; } |
|
|
|
if ( $Mode == 4) |
|
{ if ( $Value == 1 ) { return(-1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.1); }; if ( $Value == .5 ) { return(-.1); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.1); }; if ( $Value == .8 ) { return(.1); }; if ( $Value == .9 ) { return(.1); }; } |
|
} |
|
|
|
/* Draw a rectangle with rounded corners */ |
|
function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="") |
|
{ |
|
$R = isset($Format["R"]) ? $Format["R"] : 0; |
|
$G = isset($Format["G"]) ? $Format["G"] : 0; |
|
$B = isset($Format["B"]) ? $Format["B"] : 0; |
|
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; |
|
|
|
list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); |
|
|
|
if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); } |
|
if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); } |
|
|
|
$Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE); |
|
|
|
if ( $Radius <= 0 ) { $this->drawRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); } |
|
|
|
if ( $this->Antialias ) |
|
{ |
|
$this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color); |
|
$this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color); |
|
$this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color); |
|
$this->drawLine($X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color); |
|
} |
|
else |
|
{ |
|
$Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); |
|
imageline($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color); |
|
imageline($this->Picture,$X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color); |
|
imageline($this->Picture,$X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color); |
|
imageline($this->Picture,$X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color); |
|
} |
|
|
|
$Step = 360 / (2 * PI * $Radius); |
|
for($i=0;$i<=90;$i=$i+$Step) |
|
{ |
|
$X = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; |
|
$Y = sin(($i+180)*PI/180) * $Radius + $Y1 + $Radius; |
|
$this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); |
|
|
|
$X = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; |
|
$Y = sin(($i+90)*PI/180) * $Radius + $Y2 - $Radius; |
|
$this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); |
|
|
|
$X = cos($i*PI/180) * $Radius + $X2 - $Radius; |
|
$Y = sin($i*PI/180) * $Radius + $Y2 - $Radius; |
|
$this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); |
|
|
|
$X = cos(($i+270)*PI/180) * $Radius + $X2 - $Radius; |
|
$Y = sin(($i+270)*PI/180) * $Radius + $Y1 + $Radius; |
|
$this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); |
|
} |
|
} |
|
|
|
/* Draw a rectangle with rounded corners */ |
|
function drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="") |
|
{ |
|
$R = isset($Format["R"]) ? $Format["R"] : 0; |
|
$G = isset($Format["G"]) ? $Format["G"] : 0; |
|
$B = isset($Format["B"]) ? $Format["B"] : 0; |
|
$BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; |
|
$BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; |
|
$BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; |
|
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; |
|
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; |
|
|
|
if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } |
|
if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; } |
|
|
|
list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); |
|
|
|
if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); } |
|
if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); } |
|
|
|
$RestoreShadow = $this->Shadow; |
|
if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) |
|
{ |
|
$this->Shadow = FALSE; |
|
$this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); |
|
} |
|
|
|
$Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE); |
|
|
|
if ( $Radius <= 0 ) { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); } |
|
|
|
$YTop = $Y1+$Radius; |
|
$YBottom = $Y2-$Radius; |
|
|
|
$Step = 360 / (2 * PI * $Radius); |
|
$Positions = ""; $Radius--; $MinY = ""; $MaxY = ""; |
|
for($i=0;$i<=90;$i=$i+$Step) |
|
{ |
|
$Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; |
|
$Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius; |
|
$Yp = floor(sin(($i+180)*PI/180) * $Radius + $YTop); |
|
if ( $MinY == "" || $Yp > $MinY ) { $MinY = $Yp; } |
|
|
|
if ( !isset($Positions[$Yp]) ) |
|
{ $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; } |
|
else |
|
{ $Positions[$Yp]["X1"] = min($Positions[$Yp]["X1"],$Xp1); $Positions[$Yp]["X2"] = max($Positions[$Yp]["X2"],$Xp2); } |
|
|
|
$Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; |
|
$Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius; |
|
$Yp = floor(sin(($i+90)*PI/180) * $Radius + $YBottom); |
|
if ( $MaxY == "" || $Yp < $MaxY ) { $MaxY = $Yp; } |
|
|
|
if ( !isset($Positions[$Yp]["Bottom"]) ) |
|
{ $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; } |
|
else |
|
{ $Positions[$Yp]["X1"] = min($Positions[$Yp]["X1"],$Xp1); $Positions[$Yp]["X2"] = max($Positions[$Yp]["X2"],$Xp2); } |
|
} |
|
|
|
$ManualColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); |
|
foreach($Positions as $Yp => $Bounds) |
|
{ |
|
$X1 = $Bounds["X1"]; $X1Dec = $this->getFirstDecimal($X1); if ( $X1Dec != 0 ) { $X1 = floor($X1)+1; } |
|
$X2 = $Bounds["X2"]; $X2Dec = $this->getFirstDecimal($X2); if ( $X2Dec != 0 ) { $X2 = floor($X2)-1; } |
|
|
|
imageline($this->Picture,$X1,$Yp,$X2,$Yp,$ManualColor); |
|
} |
|
$this->drawFilledRectangle($X1,$MinY+1,floor($X2),$MaxY-1,$Color); |
|
|
|
$Radius++; |
|
$this->drawRoundedRectangle($X1,$Y1,$X2+1,$Y2-1,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); |
|
|
|
$this->Shadow = $RestoreShadow; |
|
} |
|
|
|
/* Draw a rectangle with rounded corners */ |
|
function drawRoundedFilledRectangle_deprecated($X1,$Y1,$X2,$Y2,$Radius,$Format="") |
|
{ |
|
$R = isset($Format["R"]) ? $Format["R"] : 0; |
|
$G = isset($Format["G"]) ? $Format["G"] : 0; |
|
$B = isset($Format["B"]) ? $Format["B"] : 0; |
|
$BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; |
|
$BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; |
|
$BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; |
|
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; |
|
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; |
|
|
|
if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } |
|
if ( $BorderR == -1 ) { $BorderR = |