Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions
+274
View File
@@ -0,0 +1,274 @@
<?php
namespace CpChart\Barcode;
use CpChart\Image;
use Exception;
/**
* pBarcode128 - class to create barcodes (128B)
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Barcode128
{
/**
* @var array
*/
public $Codes;
/**
* @var array
*/
public $Reverse;
/**
* @var string
*/
public $Result;
/**
* @var Image
*/
public $pChartObject;
/**
* @var integer
*/
public $CRC;
/**
* @param string $filePath
* @throws Exception
*/
public function __construct($filePath = '')
{
$this->Codes = [];
$this->Reverse = [];
if (!file_exists($filePath)) {
$filePath = sprintf('%s/../../resources/barcode/128B.db', __DIR__);
}
$FileHandle = @fopen($filePath, "r");
if (!$FileHandle) {
throw new Exception(
sprintf("Cannot find barcode database (%s).", $filePath)
);
}
while (!feof($FileHandle)) {
$Buffer = fgets($FileHandle, 4096);
$Buffer = str_replace(chr(10), "", $Buffer);
$Buffer = str_replace(chr(13), "", $Buffer);
$Values = preg_split("/;/", $Buffer);
$this->Codes[$Values[1]]["ID"] = $Values[0];
$this->Codes[$Values[1]]["Code"] = $Values[2];
$this->Reverse[$Values[0]]["Code"] = $Values[2];
$this->Reverse[$Values[0]]["Asc"] = $Values[1];
}
fclose($FileHandle);
}
/**
* Return the projected size of a barcode
*
* @param string $TextString
* @param string $Format
* @return array
*/
public function getSize($TextString, $Format = "")
{
$Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0;
$ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : false;
$LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5;
$DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : false;
$FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : 12;
$Height = isset($Format["Height"]) ? $Format["Height"] : 30;
$TextString = $this->encode128($TextString);
$BarcodeLength = strlen($this->Result);
$WOffset = $DrawArea ? 20 : 0;
$HOffset = $ShowLegend ? $FontSize + $LegendOffset + $WOffset : 0;
$X1 = cos($Angle * PI / 180) * ($WOffset + $BarcodeLength);
$Y1 = sin($Angle * PI / 180) * ($WOffset + $BarcodeLength);
$X2 = $X1 + cos(($Angle + 90) * PI / 180) * ($HOffset + $Height);
$Y2 = $Y1 + sin(($Angle + 90) * PI / 180) * ($HOffset + $Height);
$AreaWidth = max(abs($X1), abs($X2));
$AreaHeight = max(abs($Y1), abs($Y2));
return ["Width" => $AreaWidth, "Height" => $AreaHeight];
}
/**
*
* @param string $Value
* @param string $Format
* @return string
*/
public function encode128($Value, $Format = "")
{
$this->Result = "11010010000";
$this->CRC = 104;
$TextString = "";
for ($i = 1; $i <= strlen($Value); $i++) {
$CharCode = ord($this->mid($Value, $i, 1));
if (isset($this->Codes[$CharCode])) {
$this->Result = $this->Result . $this->Codes[$CharCode]["Code"];
$this->CRC = $this->CRC + $i * $this->Codes[$CharCode]["ID"];
$TextString = $TextString . chr($CharCode);
}
}
$this->CRC = $this->CRC - floor($this->CRC / 103) * 103;
$this->Result = $this->Result . $this->Reverse[$this->CRC]["Code"];
$this->Result = $this->Result . "1100011101011";
return $TextString;
}
/**
* Create the encoded string
* @param Image $Object
* @param string $Value
* @param int $X
* @param int $Y
* @param array $Format
*/
public function draw(Image $Object, $Value, $X, $Y, $Format = [])
{
$this->pChartObject = $Object;
$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;
$Height = isset($Format["Height"]) ? $Format["Height"] : 30;
$Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0;
$ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : false;
$LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5;
$DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : false;
$AreaR = isset($Format["AreaR"]) ? $Format["AreaR"] : 255;
$AreaG = isset($Format["AreaG"]) ? $Format["AreaG"] : 255;
$AreaB = isset($Format["AreaB"]) ? $Format["AreaB"] : 255;
$AreaBorderR = isset($Format["AreaBorderR"]) ? $Format["AreaBorderR"] : $AreaR;
$AreaBorderG = isset($Format["AreaBorderG"]) ? $Format["AreaBorderG"] : $AreaG;
$AreaBorderB = isset($Format["AreaBorderB"]) ? $Format["AreaBorderB"] : $AreaB;
$TextString = $this->encode128($Value);
if ($DrawArea) {
$X1 = $X + cos(($Angle - 135) * PI / 180) * 10;
$Y1 = $Y + sin(($Angle - 135) * PI / 180) * 10;
$X2 = $X1 + cos($Angle * PI / 180) * (strlen($this->Result) + 20);
$Y2 = $Y1 + sin($Angle * PI / 180) * (strlen($this->Result) + 20);
if ($ShowLegend) {
$X3 = $X2
+ cos(($Angle + 90) * PI / 180)
* ($Height + $LegendOffset + $this->pChartObject->FontSize + 10)
;
$Y3 = $Y2
+ sin(($Angle + 90) * PI / 180)
* ($Height + $LegendOffset + $this->pChartObject->FontSize + 10)
;
} else {
$X3 = $X2 + cos(($Angle + 90) * PI / 180) * ($Height + 20);
$Y3 = $Y2 + sin(($Angle + 90) * PI / 180) * ($Height + 20);
}
$X4 = $X3 + cos(($Angle + 180) * PI / 180) * (strlen($this->Result) + 20);
$Y4 = $Y3 + sin(($Angle + 180) * PI / 180) * (strlen($this->Result) + 20);
$Polygon = [$X1, $Y1, $X2, $Y2, $X3, $Y3, $X4, $Y4];
$Settings = [
"R" => $AreaR,
"G" => $AreaG,
"B" => $AreaB,
"BorderR" => $AreaBorderR,
"BorderG" => $AreaBorderG,
"BorderB" => $AreaBorderB
];
$this->pChartObject->drawPolygon($Polygon, $Settings);
}
for ($i = 1; $i <= strlen($this->Result); $i++) {
if ($this->mid($this->Result, $i, 1) == 1) {
$X1 = $X + cos($Angle * PI / 180) * $i;
$Y1 = $Y + sin($Angle * PI / 180) * $i;
$X2 = $X1 + cos(($Angle + 90) * PI / 180) * $Height;
$Y2 = $Y1 + sin(($Angle + 90) * PI / 180) * $Height;
$Settings = ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha];
$this->pChartObject->drawLine($X1, $Y1, $X2, $Y2, $Settings);
}
}
if ($ShowLegend) {
$X1 = $X + cos($Angle * PI / 180) * (strlen($this->Result) / 2);
$Y1 = $Y + sin($Angle * PI / 180) * (strlen($this->Result) / 2);
$LegendX = $X1 + cos(($Angle + 90) * PI / 180) * ($Height + $LegendOffset);
$LegendY = $Y1 + sin(($Angle + 90) * PI / 180) * ($Height + $LegendOffset);
$Settings = [
"R" => $R,
"G" => $G,
"B" => $B,
"Alpha" => $Alpha,
"Angle" => -$Angle,
"Align" => TEXT_ALIGN_TOPMIDDLE
];
$this->pChartObject->drawText($LegendX, $LegendY, $TextString, $Settings);
}
}
/**
*
* @param string $value
* @param int $NbChar
* @return string
*/
public function left($value, $NbChar)
{
return substr($value, 0, $NbChar);
}
/**
*
* @param string $value
* @param int $NbChar
* @return string
*/
public function right($value, $NbChar)
{
return substr($value, strlen($value) - $NbChar, $NbChar);
}
/**
*
* @param string $value
* @param int $Depart
* @param int $NbChar
* @return string
*/
public function mid($value, $Depart, $NbChar)
{
return substr($value, $Depart - 1, $NbChar);
}
}
+296
View File
@@ -0,0 +1,296 @@
<?php
namespace CpChart\Barcode;
use CpChart\Image;
use Exception;
/**
* pBarcode39 - class to create barcodes (39B)
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Barcode39
{
/**
* @var array
*/
public $Codes;
/**
* @var array
*/
public $Reverse;
/**
* @var string
*/
public $Result;
/**
* @var Image
*/
public $pChartObject;
/**
* @var integer
*/
public $CRC;
/**
* @var boolean
*/
public $MOD43;
/**
* @param string $filePath
* @param boolean $EnableMOD43
* @throws Exception
*/
public function __construct($filePath = "", $EnableMOD43 = false)
{
$this->MOD43 = (boolean) $EnableMOD43;
$this->Codes = [];
$this->Reverse = [];
if (!file_exists($filePath)) {
$filePath = sprintf('%s/../../resources/barcode/39.db', __DIR__);
}
$FileHandle = @fopen($filePath, "r");
if (!$FileHandle) {
throw new Exception(
"Cannot find barcode database (" . $filePath . ")."
);
}
while (!feof($FileHandle)) {
$Buffer = fgets($FileHandle, 4096);
$Buffer = str_replace(chr(10), "", $Buffer);
$Buffer = str_replace(chr(13), "", $Buffer);
$Values = preg_split("/;/", $Buffer);
$this->Codes[$Values[0]] = $Values[1];
}
fclose($FileHandle);
}
/**
* Return the projected size of a barcode
*
* @param string $TextString
* @param string $Format
* @return array
*/
public function getSize($TextString, $Format = "")
{
$Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0;
$ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : false;
$LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5;
$DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : false;
$FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : 12;
$Height = isset($Format["Height"]) ? $Format["Height"] : 30;
$TextString = $this->encode39($TextString);
$BarcodeLength = strlen($this->Result);
$WOffset = $DrawArea ? 20 : 0;
$HOffset = $ShowLegend ? $FontSize + $LegendOffset + $WOffset : 0;
$X1 = cos($Angle * PI / 180) * ($WOffset + $BarcodeLength);
$Y1 = sin($Angle * PI / 180) * ($WOffset + $BarcodeLength);
$X2 = $X1 + cos(($Angle + 90) * PI / 180) * ($HOffset + $Height);
$Y2 = $Y1 + sin(($Angle + 90) * PI / 180) * ($HOffset + $Height);
$AreaWidth = max(abs($X1), abs($X2));
$AreaHeight = max(abs($Y1), abs($Y2));
return ["Width" => $AreaWidth, "Height" => $AreaHeight];
}
/**
* Create the encoded string
*
* @param string $Value
* @return string
*/
public function encode39($Value)
{
$this->Result = "100101101101" . "0";
$TextString = "";
for ($i = 1; $i <= strlen($Value); $i++) {
$CharCode = ord($this->mid($Value, $i, 1));
if ($CharCode >= 97 && $CharCode <= 122) {
$CharCode = $CharCode - 32;
}
if (isset($this->Codes[chr($CharCode)])) {
$this->Result = $this->Result . $this->Codes[chr($CharCode)] . "0";
$TextString = $TextString . chr($CharCode);
}
}
if ($this->MOD43) {
$Checksum = $this->checksum($TextString);
$this->Result = $this->Result . $this->Codes[$Checksum] . "0";
}
$this->Result = $this->Result . "100101101101";
$TextString = "*" . $TextString . "*";
return $TextString;
}
/**
* Create the encoded string
* @param Image $Object
* @param type $Value
* @param type $X
* @param type $Y
* @param array $Format
*/
public function draw(Image $Object, $Value, $X, $Y, $Format = [])
{
$this->pChartObject = $Object;
$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;
$Height = isset($Format["Height"]) ? $Format["Height"] : 30;
$Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0;
$ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : false;
$LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5;
$DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : false;
$AreaR = isset($Format["AreaR"]) ? $Format["AreaR"] : 255;
$AreaG = isset($Format["AreaG"]) ? $Format["AreaG"] : 255;
$AreaB = isset($Format["AreaB"]) ? $Format["AreaB"] : 255;
$AreaBorderR = isset($Format["AreaBorderR"]) ? $Format["AreaBorderR"] : $AreaR;
$AreaBorderG = isset($Format["AreaBorderG"]) ? $Format["AreaBorderG"] : $AreaG;
$AreaBorderB = isset($Format["AreaBorderB"]) ? $Format["AreaBorderB"] : $AreaB;
$TextString = $this->encode39($Value);
if ($DrawArea) {
$X1 = $X + cos(($Angle - 135) * PI / 180) * 10;
$Y1 = $Y + sin(($Angle - 135) * PI / 180) * 10;
$X2 = $X1 + cos($Angle * PI / 180) * (strlen($this->Result) + 20);
$Y2 = $Y1 + sin($Angle * PI / 180) * (strlen($this->Result) + 20);
if ($ShowLegend) {
$X3 = $X2
+ cos(($Angle + 90) * PI / 180)
* ($Height + $LegendOffset + $this->pChartObject->FontSize + 10)
;
$Y3 = $Y2
+ sin(($Angle + 90) * PI / 180)
* ($Height + $LegendOffset + $this->pChartObject->FontSize + 10)
;
} else {
$X3 = $X2 + cos(($Angle + 90) * PI / 180) * ($Height + 20);
$Y3 = $Y2 + sin(($Angle + 90) * PI / 180) * ($Height + 20);
}
$X4 = $X3 + cos(($Angle + 180) * PI / 180) * (strlen($this->Result) + 20);
$Y4 = $Y3 + sin(($Angle + 180) * PI / 180) * (strlen($this->Result) + 20);
$Polygon = [$X1, $Y1, $X2, $Y2, $X3, $Y3, $X4, $Y4];
$Settings = [
"R" => $AreaR,
"G" => $AreaG,
"B" => $AreaB,
"BorderR" => $AreaBorderR,
"BorderG" => $AreaBorderG,
"BorderB" => $AreaBorderB
];
$this->pChartObject->drawPolygon($Polygon, $Settings);
}
for ($i = 1; $i <= strlen($this->Result); $i++) {
if ($this->mid($this->Result, $i, 1) == 1) {
$X1 = $X + cos($Angle * PI / 180) * $i;
$Y1 = $Y + sin($Angle * PI / 180) * $i;
$X2 = $X1 + cos(($Angle + 90) * PI / 180) * $Height;
$Y2 = $Y1 + sin(($Angle + 90) * PI / 180) * $Height;
$Settings = ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha];
$this->pChartObject->drawLine($X1, $Y1, $X2, $Y2, $Settings);
}
}
if ($ShowLegend) {
$X1 = $X + cos($Angle * PI / 180) * (strlen($this->Result) / 2);
$Y1 = $Y + sin($Angle * PI / 180) * (strlen($this->Result) / 2);
$LegendX = $X1 + cos(($Angle + 90) * PI / 180) * ($Height + $LegendOffset);
$LegendY = $Y1 + sin(($Angle + 90) * PI / 180) * ($Height + $LegendOffset);
$Settings = [
"R" => $R,
"G" => $G,
"B" => $B,
"Alpha" => $Alpha,
"Angle" => -$Angle,
"Align" => TEXT_ALIGN_TOPMIDDLE
];
$this->pChartObject->drawText($LegendX, $LegendY, $TextString, $Settings);
}
}
/**
* @param string $string
* @return string
*/
public function checksum($string)
{
$checksum = 0;
$length = strlen($string);
$charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%';
for ($i = 0; $i < $length; ++$i) {
$checksum += strpos($charset, $string[$i]);
}
return substr($charset, ($checksum % 43), 1);
}
/**
* @param string $value
* @param int $NbChar
* @return string
*/
public function left($value, $NbChar)
{
return substr($value, 0, $NbChar);
}
/**
* @param string $value
* @param int $NbChar
* @return string|false
*/
public function right($value, $NbChar)
{
return substr($value, strlen($value) - $NbChar, $NbChar);
}
/**
* @param string $value
* @param int $Depart
* @param int $NbChar
* @return string
*/
public function mid($value, $Depart, $NbChar)
{
return substr($value, $Depart - 1, $NbChar);
}
}
File diff suppressed because it is too large Load Diff
+392
View File
@@ -0,0 +1,392 @@
<?php
namespace CpChart;
/**
* Cache - speed up the rendering by caching up the pictures
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Cache
{
/**
* @var string
*/
public $CacheFolder;
/**
* @var string
*/
public $CacheIndex;
/**
* @var string
*/
public $CacheDB;
/**
* @param array $Settings
*/
public function __construct(array $Settings = [])
{
$CacheFolder = isset($Settings["CacheFolder"]) ? $Settings["CacheFolder"] : __DIR__ . "/../cache";
$CacheIndex = isset($Settings["CacheIndex"]) ? $Settings["CacheIndex"] : "index.db";
$CacheDB = isset($Settings["CacheDB"]) ? $Settings["CacheDB"] : "cache.db";
$this->CacheFolder = $CacheFolder;
$this->CacheIndex = $CacheIndex;
$this->CacheDB = $CacheDB;
if (!file_exists($this->CacheFolder . "/" . $this->CacheIndex)) {
touch($this->CacheFolder . "/" . $this->CacheIndex);
}
if (!file_exists($this->CacheFolder . "/" . $this->CacheDB)) {
touch($this->CacheFolder . "/" . $this->CacheDB);
}
}
/**
* Flush the cache contents
*/
public function flush()
{
if (file_exists($this->CacheFolder . "/" . $this->CacheIndex)) {
unlink($this->CacheFolder . "/" . $this->CacheIndex);
touch($this->CacheFolder . "/" . $this->CacheIndex);
}
if (file_exists($this->CacheFolder . "/" . $this->CacheDB)) {
unlink($this->CacheFolder . "/" . $this->CacheDB);
touch($this->CacheFolder . "/" . $this->CacheDB);
}
}
/**
* Return the MD5 of the data array to clearly identify the chart
*
* @param Data $Data
* @param string $Marker
* @return string
*/
public function getHash(Data $Data, $Marker = "")
{
return md5($Marker . serialize($Data->Data));
}
/**
* Write the generated picture to the cache
*
* @param string $ID
* @param Image $pChartObject
*/
public function writeToCache($ID, Image $pChartObject)
{
/* Compute the paths */
$TemporaryFile = tempnam($this->CacheFolder, "tmp_");
$Database = $this->CacheFolder . "/" . $this->CacheDB;
$Index = $this->CacheFolder . "/" . $this->CacheIndex;
/* Flush the picture to a temporary file */
imagepng($pChartObject->Picture, $TemporaryFile);
/* Retrieve the files size */
$PictureSize = filesize($TemporaryFile);
$DBSize = filesize($Database);
/* Save the index */
$Handle = fopen($Index, "a");
fwrite($Handle, $ID . "," . $DBSize . "," . $PictureSize . "," . time() . ",0\r\n");
fclose($Handle);
/* Get the picture raw contents */
$Handle = fopen($TemporaryFile, "r");
$Raw = fread($Handle, $PictureSize);
fclose($Handle);
/* Save the picture in the solid database file */
$Handle = fopen($Database, "a");
fwrite($Handle, $Raw);
fclose($Handle);
/* Remove temporary file */
unlink($TemporaryFile);
}
/**
* Remove object older than the specified TS
* @param int $Expiry
*/
public function removeOlderThan($Expiry)
{
$this->dbRemoval(["Expiry" => $Expiry]);
}
/**
* Remove an object from the cache
* @param string $ID
*/
public function remove($ID)
{
$this->dbRemoval(["Name" => $ID]);
}
/**
* Remove with specified criterias.
*
* @param array $Settings
* @return int
*/
public function dbRemoval(array $Settings)
{
$ID = isset($Settings["Name"]) ? $Settings["Name"] : null;
$Expiry = isset($Settings["Expiry"]) ? $Settings["Expiry"] : -(24 * 60 * 60);
$TS = time() - $Expiry;
/* Compute the paths */
$Database = $this->CacheFolder . "/" . $this->CacheDB;
$Index = $this->CacheFolder . "/" . $this->CacheIndex;
$DatabaseTemp = $this->CacheFolder . "/" . $this->CacheDB . ".tmp";
$IndexTemp = $this->CacheFolder . "/" . $this->CacheIndex . ".tmp";
/* Single file removal */
if ($ID != null) {
/* Retrieve object informations */
$Object = $this->isInCache($ID, true);
/* If it's not in the cache DB, go away */
if (!$Object) {
return(0);
}
}
/* Create the temporary files */
if (!file_exists($DatabaseTemp)) {
touch($DatabaseTemp);
}
if (!file_exists($IndexTemp)) {
touch($IndexTemp);
}
/* Open the file handles */
$IndexHandle = @fopen($Index, "r");
$IndexTempHandle = @fopen($IndexTemp, "w");
$DBHandle = @fopen($Database, "r");
$DBTempHandle = @fopen($DatabaseTemp, "w");
/* Remove the selected ID from the database */
while (!feof($IndexHandle)) {
$Entry = fgets($IndexHandle, 4096);
$Entry = str_replace("\r", "", $Entry);
$Entry = str_replace("\n", "", $Entry);
$Settings = preg_split("/,/", $Entry);
if ($Entry != "") {
$PicID = $Settings[0];
$DBPos = $Settings[1];
$PicSize = $Settings[2];
$GeneratedTS = $Settings[3];
$Hits = $Settings[4];
if ($Settings[0] != $ID && $GeneratedTS > $TS) {
$CurrentPos = ftell($DBTempHandle);
fwrite(
$IndexTempHandle,
sprintf(
"%s,%s,%s,%s,%s\r\n",
$PicID,
$CurrentPos,
$PicSize,
$GeneratedTS,
$Hits
)
);
fseek($DBHandle, $DBPos);
$Picture = fread($DBHandle, $PicSize);
fwrite($DBTempHandle, $Picture);
}
}
}
/* Close the handles */
fclose($IndexHandle);
fclose($IndexTempHandle);
fclose($DBHandle);
fclose($DBTempHandle);
/* Remove the prod files */
unlink($Database);
unlink($Index);
/* Swap the temp & prod DB */
rename($DatabaseTemp, $Database);
rename($IndexTemp, $Index);
}
/**
* Is the file in cache?
*
* @param string $ID
* @param boolean $Verbose
* @param boolean $UpdateHitsCount
* @return boolean
*/
public function isInCache($ID, $Verbose = false, $UpdateHitsCount = false)
{
/* Compute the paths */
$Index = $this->CacheFolder . "/" . $this->CacheIndex;
/* Search the picture in the index file */
$Handle = @fopen($Index, "r");
while (!feof($Handle)) {
$IndexPos = ftell($Handle);
$Entry = fgets($Handle, 4096);
if ($Entry != "") {
$Settings = preg_split("/,/", $Entry);
$PicID = $Settings[0];
if ($PicID == $ID) {
fclose($Handle);
$DBPos = $Settings[1];
$PicSize = $Settings[2];
$GeneratedTS = $Settings[3];
$Hits = intval($Settings[4]);
if ($UpdateHitsCount) {
$Hits++;
if (strlen($Hits) < 7) {
$Hits = $Hits . str_repeat(" ", 7 - strlen($Hits));
}
$Handle = @fopen($Index, "r+");
fseek($Handle, $IndexPos);
fwrite(
$Handle,
sprintf(
"%s,%s,%s,%s,%s\r\n",
$PicID,
$DBPos,
$PicSize,
$GeneratedTS,
$Hits
)
);
fclose($Handle);
}
if ($Verbose) {
return [
"DBPos" => $DBPos,
"PicSize" => $PicSize,
"GeneratedTS" => $GeneratedTS,
"Hits" => $Hits
];
} else {
return true;
}
}
}
}
fclose($Handle);
/* Picture isn't in the cache */
return false;
}
/**
* Automatic output method based on the calling interface
* @param string $ID
* @param string $Destination
*/
public function autoOutput($ID, $Destination = "output.png")
{
if (php_sapi_name() == "cli") {
$this->saveFromCache($ID, $Destination);
} else {
$this->strokeFromCache($ID);
}
}
/**
* Show image from cache
* @param string $ID
* @return boolean
*/
public function strokeFromCache($ID)
{
/* Get the raw picture from the cache */
$Picture = $this->getFromCache($ID);
/* Do we have a hit? */
if ($Picture == null) {
return false;
}
header('Content-type: image/png');
echo $Picture;
return true;
}
/**
* Save file from cache.
* @param string $ID
* @param string $Destination
* @return boolean
*/
public function saveFromCache($ID, $Destination)
{
/* Get the raw picture from the cache */
$Picture = $this->getFromCache($ID);
/* Do we have a hit? */
if ($Picture == null) {
return false;
}
/* Flush the picture to a file */
$Handle = fopen($Destination, "w");
fwrite($Handle, $Picture);
fclose($Handle);
/* All went fine */
return true;
}
/**
* Get file from cache
* @param string $ID
* @return string|null
*/
public function getFromCache($ID)
{
/* Compute the path */
$Database = $this->CacheFolder . "/" . $this->CacheDB;
/* Lookup for the picture in the cache */
$CacheInfo = $this->isInCache($ID, true, true);
/* Not in the cache */
if (!$CacheInfo) {
return null;
}
/* Get the database extended information */
$DBPos = $CacheInfo["DBPos"];
$PicSize = $CacheInfo["PicSize"];
/* Extract the picture from the solid cache file */
$Handle = @fopen($Database, "r");
fseek($Handle, $DBPos);
$Picture = fread($Handle, $PicSize);
fclose($Handle);
/* Return back the raw picture data */
return $Picture;
}
}
+532
View File
@@ -0,0 +1,532 @@
<?php
namespace CpChart\Chart;
use CpChart\Data;
use CpChart\Image;
/**
* Bubble - class to draw bubble charts
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Bubble
{
/**
* @var Image
*/
public $pChartObject;
/**
* @var Data
*/
public $pDataObject;
/**
* @param Image $pChartObject
* @param Data $pDataObject
*/
public function __construct(Image $pChartObject, Data $pDataObject)
{
$this->pChartObject = $pChartObject;
$this->pDataObject = $pDataObject;
}
/**
* Prepare the scale
*
* @param mixed $DataSeries
* @param mixed $WeightSeries
*/
public function bubbleScale($DataSeries, $WeightSeries)
{
if (!is_array($DataSeries)) {
$DataSeries = [$DataSeries];
}
if (!is_array($WeightSeries)) {
$WeightSeries = [$WeightSeries];
}
/* Parse each data series to find the new min & max boundaries to scale */
$NewPositiveSerie = [];
$NewNegativeSerie = [];
$MaxValues = 0;
$LastPositive = 0;
$LastNegative = 0;
foreach ($DataSeries as $Key => $SerieName) {
$SerieWeightName = $WeightSeries[$Key];
$this->pDataObject->setSerieDrawable($SerieWeightName, false);
$serieData = $this->pDataObject->Data["Series"][$SerieName]["Data"];
if (count($serieData) > $MaxValues) {
$MaxValues = count($serieData);
}
foreach ($serieData as $Key => $Value) {
if ($Value >= 0) {
$BubbleBounds = $Value + $this->pDataObject->Data["Series"][$SerieWeightName]["Data"][$Key];
if (!isset($NewPositiveSerie[$Key])) {
$NewPositiveSerie[$Key] = $BubbleBounds;
} elseif ($NewPositiveSerie[$Key] < $BubbleBounds) {
$NewPositiveSerie[$Key] = $BubbleBounds;
}
$LastPositive = $BubbleBounds;
} else {
$BubbleBounds = $Value - $this->pDataObject->Data["Series"][$SerieWeightName]["Data"][$Key];
if (!isset($NewNegativeSerie[$Key])) {
$NewNegativeSerie[$Key] = $BubbleBounds;
} elseif ($NewNegativeSerie[$Key] > $BubbleBounds) {
$NewNegativeSerie[$Key] = $BubbleBounds;
}
$LastNegative = $BubbleBounds;
}
}
}
/* Check for missing values and all the fake positive serie */
if (count($NewPositiveSerie)) {
for ($i = 0; $i < $MaxValues; $i++) {
if (!isset($NewPositiveSerie[$i])) {
$NewPositiveSerie[$i] = $LastPositive;
}
}
$this->pDataObject->addPoints($NewPositiveSerie, "BubbleFakePositiveSerie");
}
/* Check for missing values and all the fake negative serie */
if (count($NewNegativeSerie)) {
for ($i = 0; $i < $MaxValues; $i++) {
if (!isset($NewNegativeSerie[$i])) {
$NewNegativeSerie[$i] = $LastNegative;
}
}
$this->pDataObject->addPoints($NewNegativeSerie, "BubbleFakeNegativeSerie");
}
}
public function resetSeriesColors()
{
$Data = $this->pDataObject->getData();
$Palette = $this->pDataObject->getPalette();
$ID = 0;
foreach ($Data["Series"] as $SerieName => $SeriesParameters) {
if ($SeriesParameters["isDrawable"]) {
$this->pDataObject->Data["Series"][$SerieName]["Color"]["R"] = $Palette[$ID]["R"];
$this->pDataObject->Data["Series"][$SerieName]["Color"]["G"] = $Palette[$ID]["G"];
$this->pDataObject->Data["Series"][$SerieName]["Color"]["B"] = $Palette[$ID]["B"];
$this->pDataObject->Data["Series"][$SerieName]["Color"]["Alpha"] = $Palette[$ID]["Alpha"];
$ID++;
}
}
}
/* Prepare the scale */
public function drawBubbleChart($DataSeries, $WeightSeries, $Format = "")
{
$ForceAlpha = isset($Format["ForceAlpha"]) ? $Format["ForceAlpha"] : VOID;
$DrawBorder = isset($Format["DrawBorder"]) ? $Format["DrawBorder"] : true;
$BorderWidth = isset($Format["BorderWidth"]) ? $Format["BorderWidth"] : 1;
$Shape = isset($Format["Shape"]) ? $Format["Shape"] : BUBBLE_SHAPE_ROUND;
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
$BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0;
$BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0;
$BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0;
$BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30;
$RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;
if (!is_array($DataSeries)) {
$DataSeries = [$DataSeries];
}
if (!is_array($WeightSeries)) {
$WeightSeries = [$WeightSeries];
}
$Data = $this->pDataObject->getData();
$Palette = $this->pDataObject->getPalette();
if (isset($Data["Series"]["BubbleFakePositiveSerie"])) {
$this->pDataObject->setSerieDrawable("BubbleFakePositiveSerie", false);
}
if (isset($Data["Series"]["BubbleFakeNegativeSerie"])) {
$this->pDataObject->setSerieDrawable("BubbleFakeNegativeSerie", false);
}
$this->resetSeriesColors();
list($XMargin, $XDivs) = $this->pChartObject->scaleGetXSettings();
foreach ($DataSeries as $Key => $SerieName) {
$AxisID = $Data["Series"][$SerieName]["Axis"];
$Mode = $Data["Axis"][$AxisID]["Display"];
$Format = $Data["Axis"][$AxisID]["Format"];
$Unit = $Data["Axis"][$AxisID]["Unit"];
if (isset($Data["Series"][$SerieName]["Description"])) {
$SerieDescription = $Data["Series"][$SerieName]["Description"];
} else {
$SerieDescription = $SerieName;
}
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2) / $XDivs;
$X = $this->pChartObject->GraphAreaX1 + $XMargin;
$Y = $this->pChartObject->GraphAreaY1 + $XMargin;
$Color = [
"R" => $Palette[$Key]["R"],
"G" => $Palette[$Key]["G"],
"B" => $Palette[$Key]["B"],
"Alpha" => $Palette[$Key]["Alpha"]
];
if ($ForceAlpha != VOID) {
$Color["Alpha"] = $ForceAlpha;
}
if ($DrawBorder) {
if ($BorderWidth != 1) {
if ($Surrounding != null) {
$BorderR = $Palette[$Key]["R"] + $Surrounding;
$BorderG = $Palette[$Key]["G"] + $Surrounding;
$BorderB = $Palette[$Key]["B"] + $Surrounding;
}
if ($ForceAlpha != VOID) {
$BorderAlpha = $ForceAlpha / 2;
}
$BorderColor = [
"R" => $BorderR,
"G" => $BorderG,
"B" => $BorderB,
"Alpha" => $BorderAlpha
];
} else {
$Color["BorderAlpha"] = $BorderAlpha;
if ($Surrounding != null) {
$Color["BorderR"] = $Palette[$Key]["R"] + $Surrounding;
$Color["BorderG"] = $Palette[$Key]["G"] + $Surrounding;
$Color["BorderB"] = $Palette[$Key]["B"] + $Surrounding;
} else {
$Color["BorderR"] = $BorderR;
$Color["BorderG"] = $BorderG;
$Color["BorderB"] = $BorderB;
}
if ($ForceAlpha != VOID) {
$Color["BorderAlpha"] = $ForceAlpha / 2;
}
}
}
foreach ($Data["Series"][$SerieName]["Data"] as $iKey => $Point) {
$Weight = $Point + $Data["Series"][$WeightSeries[$Key]]["Data"][$iKey];
$PosArray = $this->pChartObject->scaleComputeY(
$Point,
["AxisID" => $AxisID]
);
$WeightArray = $this->pChartObject->scaleComputeY(
$Weight,
["AxisID" => $AxisID]
);
if ($Data["Orientation"] == SCALE_POS_LEFTRIGHT) {
if ($XDivs == 0) {
$XStep = 0;
} else {
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2)
/ $XDivs
;
}
$Y = floor($PosArray);
$CircleRadius = floor(abs($PosArray - $WeightArray) / 2);
if ($Shape == BUBBLE_SHAPE_SQUARE) {
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"RECT",
(
floor($X - $CircleRadius)
. "," . floor($Y - $CircleRadius)
. "," . floor($X + $CircleRadius)
. "," . floor($Y + $CircleRadius)
),
$this->pChartObject->toHTMLColor(
$Palette[$Key]["R"],
$Palette[$Key]["G"],
$Palette[$Key]["B"]
),
$SerieDescription,
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
);
}
if ($BorderWidth != 1) {
$this->pChartObject->drawFilledRectangle(
$X - $CircleRadius - $BorderWidth,
$Y - $CircleRadius - $BorderWidth,
$X + $CircleRadius + $BorderWidth,
$Y + $CircleRadius + $BorderWidth,
$BorderColor
);
$this->pChartObject->drawFilledRectangle(
$X - $CircleRadius,
$Y - $CircleRadius,
$X + $CircleRadius,
$Y + $CircleRadius,
$Color
);
} else {
$this->pChartObject->drawFilledRectangle(
$X - $CircleRadius,
$Y - $CircleRadius,
$X + $CircleRadius,
$Y + $CircleRadius,
$Color
);
}
} elseif ($Shape == BUBBLE_SHAPE_ROUND) {
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"CIRCLE",
floor($X) . "," . floor($Y) . "," . floor($CircleRadius),
$this->pChartObject->toHTMLColor(
$Palette[$Key]["R"],
$Palette[$Key]["G"],
$Palette[$Key]["B"]
),
$SerieDescription,
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
);
}
if ($BorderWidth != 1) {
$this->pChartObject->drawFilledCircle(
$X,
$Y,
$CircleRadius + $BorderWidth,
$BorderColor
);
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
} else {
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
}
}
$X = $X + $XStep;
} elseif ($Data["Orientation"] == SCALE_POS_TOPBOTTOM) {
if ($XDivs == 0) {
$XStep = 0;
} else {
$XStep = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $XMargin * 2)
/ $XDivs
;
}
$X = floor($PosArray);
$CircleRadius = floor(abs($PosArray - $WeightArray) / 2);
if ($Shape == BUBBLE_SHAPE_SQUARE) {
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"RECT",
(
floor($X - $CircleRadius) . ","
. floor($Y - $CircleRadius) . ","
. floor($X + $CircleRadius) . ","
. floor($Y + $CircleRadius)
),
$this->pChartObject->toHTMLColor(
$Palette[$Key]["R"],
$Palette[$Key]["G"],
$Palette[$Key]["B"]
),
$SerieDescription,
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
);
}
if ($BorderWidth != 1) {
$this->pChartObject->drawFilledRectangle(
$X - $CircleRadius - $BorderWidth,
$Y - $CircleRadius - $BorderWidth,
$X + $CircleRadius + $BorderWidth,
$Y + $CircleRadius + $BorderWidth,
$BorderColor
);
$this->pChartObject->drawFilledRectangle(
$X - $CircleRadius,
$Y - $CircleRadius,
$X + $CircleRadius,
$Y + $CircleRadius,
$Color
);
} else {
$this->pChartObject->drawFilledRectangle(
$X - $CircleRadius,
$Y - $CircleRadius,
$X + $CircleRadius,
$Y + $CircleRadius,
$Color
);
}
} elseif ($Shape == BUBBLE_SHAPE_ROUND) {
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"CIRCLE",
floor($X) . "," . floor($Y) . "," . floor($CircleRadius),
$this->pChartObject->toHTMLColor(
$Palette[$Key]["R"],
$Palette[$Key]["G"],
$Palette[$Key]["B"]
),
$SerieDescription,
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
);
}
if ($BorderWidth != 1) {
$this->pChartObject->drawFilledCircle(
$X,
$Y,
$CircleRadius + $BorderWidth,
$BorderColor
);
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
} else {
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
}
}
$Y = $Y + $XStep;
}
}
}
}
public function writeBubbleLabel($SerieName, $SerieWeightName, $Points, $Format = "")
{
$DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX;
if (!is_array($Points)) {
$Point = $Points;
$Points = [];
$Points[] = $Point;
}
$Data = $this->pDataObject->getData();
if (!isset($Data["Series"][$SerieName])
|| !isset($Data["Series"][$SerieWeightName])
) {
return(0);
}
list($XMargin, $XDivs) = $this->pChartObject->scaleGetXSettings();
$AxisID = $Data["Series"][$SerieName]["Axis"];
$AxisMode = $Data["Axis"][$AxisID]["Display"];
$AxisFormat = $Data["Axis"][$AxisID]["Format"];
$AxisUnit = $Data["Axis"][$AxisID]["Unit"];
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2) / $XDivs;
$X = $InitialX = $this->pChartObject->GraphAreaX1 + $XMargin;
$Y = $InitialY = $this->pChartObject->GraphAreaY1 + $XMargin;
$Color = [
"R" => $Data["Series"][$SerieName]["Color"]["R"],
"G" => $Data["Series"][$SerieName]["Color"]["G"],
"B" => $Data["Series"][$SerieName]["Color"]["B"],
"Alpha" => $Data["Series"][$SerieName]["Color"]["Alpha"]
];
foreach ($Points as $Key => $Point) {
$Value = $Data["Series"][$SerieName]["Data"][$Point];
$PosArray = $this->pChartObject->scaleComputeY($Value, ["AxisID" => $AxisID]);
if (isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Point])) {
$Abscissa = $Data["Series"][$Data["Abscissa"]]["Data"][$Point] . " : ";
} else {
$Abscissa = "";
}
$Value = $this->pChartObject->scaleFormat($Value, $AxisMode, $AxisFormat, $AxisUnit);
$Weight = $Data["Series"][$SerieWeightName]["Data"][$Point];
$Caption = $Abscissa . $Value . " / " . $Weight;
if (isset($Data["Series"][$SerieName]["Description"])) {
$Description = $Data["Series"][$SerieName]["Description"];
} else {
$Description = "No description";
}
$Series = [["Format" => $Color, "Caption" => $Caption]];
if ($Data["Orientation"] == SCALE_POS_LEFTRIGHT) {
if ($XDivs == 0) {
$XStep = 0;
} else {
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2)
/ $XDivs
;
}
$X = floor($InitialX + $Point * $XStep);
$Y = floor($PosArray);
} else {
if ($XDivs == 0) {
$YStep = 0;
} else {
$YStep = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $XMargin * 2)
/ $XDivs
;
}
$X = floor($PosArray);
$Y = floor($InitialY + $Point * $YStep);
}
if ($DrawPoint == LABEL_POINT_CIRCLE) {
$this->pChartObject->drawFilledCircle(
$X,
$Y,
3,
[
"R" => 255,
"G" => 255,
"B" => 255,
"BorderR" => 0,
"BorderG" => 0,
"BorderB" => 0
]
);
} elseif ($DrawPoint == LABEL_POINT_BOX) {
$this->pChartObject->drawFilledRectangle(
$X - 2,
$Y - 2,
$X + 2,
$Y + 2,
[
"R" => 255,
"G" => 255,
"B" => 255,
"BorderR" => 0,
"BorderG" => 0,
"BorderB" => 0
]
);
}
$this->pChartObject->drawLabelBox($X, $Y - 3, $Description, $Series, $Format);
}
}
}
+377
View File
@@ -0,0 +1,377 @@
<?php
namespace CpChart\Chart;
use CpChart\Image;
/**
* Indicator - class to draw indicators
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Indicator
{
/**
* @var Image
*/
public $pChartObject;
/**
* @param Image $pChartObject
*/
public function __construct(Image $pChartObject)
{
$this->pChartObject = $pChartObject;
}
/**
* Draw an indicator
*
* @param int $X
* @param int $Y
* @param int $Width
* @param int $Height
* @param array $Format
* @return null|int
*/
public function draw($X, $Y, $Width, $Height, array $Format = [])
{
$Values = isset($Format["Values"]) ? $Format["Values"] : VOID;
$IndicatorSections = isset($Format["IndicatorSections"]) ? $Format["IndicatorSections"] : null;
$ValueDisplay = isset($Format["ValueDisplay"]) ? $Format["ValueDisplay"] : INDICATOR_VALUE_BUBBLE;
$SectionsMargin = isset($Format["SectionsMargin"]) ? $Format["SectionsMargin"] : 4;
$DrawLeftHead = isset($Format["DrawLeftHead"]) ? $Format["DrawLeftHead"] : true;
$DrawRightHead = isset($Format["DrawRightHead"]) ? $Format["DrawRightHead"] : true;
$HeadSize = isset($Format["HeadSize"]) ? $Format["HeadSize"] : floor($Height / 4);
$TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 4;
$CaptionLayout = isset($Format["CaptionLayout"]) ? $Format["CaptionLayout"] : INDICATOR_CAPTION_EXTENDED;
$CaptionPosition = isset($Format["CaptionPosition"]) ? $Format["CaptionPosition"] : INDICATOR_CAPTION_INSIDE;
$CaptionColorFactor = isset($Format["CaptionColorFactor"]) ? $Format["CaptionColorFactor"] : null;
$CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255;
$CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255;
$CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255;
$CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100;
$SubCaptionColorFactor = isset($Format["SubCaptionColorFactor"]) ? $Format["SubCaptionColorFactor"] : null;
$SubCaptionR = isset($Format["SubCaptionR"]) ? $Format["SubCaptionR"] : 50;
$SubCaptionG = isset($Format["SubCaptionG"]) ? $Format["SubCaptionG"] : 50;
$SubCaptionB = isset($Format["SubCaptionB"]) ? $Format["SubCaptionB"] : 50;
$SubCaptionAlpha = isset($Format["SubCaptionAlpha"]) ? $Format["SubCaptionAlpha"] : 100;
$ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName;
$ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize;
$CaptionFontName = isset($Format["CaptionFontName"])
? $Format["CaptionFontName"] : $this->pChartObject->FontName
;
$CaptionFontSize = isset($Format["CaptionFontSize"])
? $Format["CaptionFontSize"] : $this->pChartObject->FontSize
;
$Unit = isset($Format["Unit"]) ? $Format["Unit"] : "";
/* Convert the Values to display to an array if needed */
if (!is_array($Values)) {
$Values = [$Values];
}
/* No section, let's die */
if ($IndicatorSections == null) {
return 0;
}
/* Determine indicator visual configuration */
$OverallMin = $IndicatorSections[0]["End"];
$OverallMax = $IndicatorSections[0]["Start"];
foreach ($IndicatorSections as $Key => $Settings) {
if ($Settings["End"] > $OverallMax) {
$OverallMax = $Settings["End"];
}
if ($Settings["Start"] < $OverallMin) {
$OverallMin = $Settings["Start"];
}
}
$RealWidth = $Width - (count($IndicatorSections) - 1) * $SectionsMargin;
$XScale = $RealWidth / ($OverallMax - $OverallMin);
$X1 = $X;
$ValuesPos = [];
foreach ($IndicatorSections as $Key => $Settings) {
$Color = ["R" => $Settings["R"], "G" => $Settings["G"], "B" => $Settings["B"]];
$Caption = $Settings["Caption"];
$SubCaption = $Settings["Start"] . " - " . $Settings["End"];
$X2 = $X1 + ($Settings["End"] - $Settings["Start"]) * $XScale;
if ($Key == 0 && $DrawLeftHead) {
$Poly = [];
$Poly[] = $X1 - 1;
$Poly[] = $Y;
$Poly[] = $X1 - 1;
$Poly[] = $Y + $Height;
$Poly[] = $X1 - 1 - $HeadSize;
$Poly[] = $Y + ($Height / 2);
$this->pChartObject->drawPolygon($Poly, $Color);
$this->pChartObject->drawLine($X1 - 2, $Y, $X1 - 2 - $HeadSize, $Y + ($Height / 2), $Color);
$this->pChartObject->drawLine(
$X1 - 2,
$Y + $Height,
$X1 - 2 - $HeadSize,
$Y + ($Height / 2),
$Color
);
}
/* Determine the position of the breaks */
$Break = [];
foreach ($Values as $iKey => $Value) {
if ($Value >= $Settings["Start"] && $Value <= $Settings["End"]) {
$XBreak = $X1 + ($Value - $Settings["Start"]) * $XScale;
$ValuesPos[$Value] = $XBreak;
$Break[] = floor($XBreak);
}
}
if ($ValueDisplay == INDICATOR_VALUE_LABEL) {
if (!count($Break)) {
$this->pChartObject->drawFilledRectangle($X1, $Y, $X2, $Y + $Height, $Color);
} else {
sort($Break);
$Poly = [];
$Poly[] = $X1;
$Poly[] = $Y;
$LastPointWritten = false;
foreach ($Break as $iKey => $Value) {
if ($Value - 5 >= $X1) {
$Poly[] = $Value - 5;
$Poly[] = $Y;
} elseif ($X1 - ($Value - 5) > 0) {
$Offset = $X1 - ($Value - 5);
$Poly = [$X1, $Y + $Offset];
}
$Poly[] = $Value;
$Poly[] = $Y + 5;
if ($Value + 5 <= $X2) {
$Poly[] = $Value + 5;
$Poly[] = $Y;
} elseif (($Value + 5) > $X2) {
$Offset = ($Value + 5) - $X2;
$Poly[] = $X2;
$Poly[] = $Y + $Offset;
$LastPointWritten = true;
}
}
if (!$LastPointWritten) {
$Poly[] = $X2;
$Poly[] = $Y;
}
$Poly[] = $X2;
$Poly[] = $Y + $Height;
$Poly[] = $X1;
$Poly[] = $Y + $Height;
$this->pChartObject->drawPolygon($Poly, $Color);
}
} else {
$this->pChartObject->drawFilledRectangle($X1, $Y, $X2, $Y + $Height, $Color);
}
if ($Key == count($IndicatorSections) - 1 && $DrawRightHead) {
$Poly = [];
$Poly[] = $X2 + 1;
$Poly[] = $Y;
$Poly[] = $X2 + 1;
$Poly[] = $Y + $Height;
$Poly[] = $X2 + 1 + $HeadSize;
$Poly[] = $Y + ($Height / 2);
$this->pChartObject->drawPolygon($Poly, $Color);
$this->pChartObject->drawLine($X2 + 1, $Y, $X2 + 1 + $HeadSize, $Y + ($Height / 2), $Color);
$this->pChartObject->drawLine(
$X2 + 1,
$Y + $Height,
$X2 + 1 + $HeadSize,
$Y + ($Height / 2),
$Color
);
}
$YOffset = 0;
$XOffset = 0;
if ($CaptionPosition == INDICATOR_CAPTION_INSIDE) {
$TxtPos = $this->pChartObject->getTextBox(
$X1,
$Y + $Height + $TextPadding,
$CaptionFontName,
$CaptionFontSize,
0,
$Caption
);
$YOffset = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding;
if ($CaptionLayout == INDICATOR_CAPTION_EXTENDED) {
$TxtPos = $this->pChartObject->getTextBox(
$X1,
$Y + $Height + $TextPadding,
$CaptionFontName,
$CaptionFontSize,
0,
$SubCaption
);
$YOffset = $YOffset + ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding * 2;
}
$XOffset = $TextPadding;
}
if ($CaptionColorFactor == null) {
$CaptionColor = [
"Align" => TEXT_ALIGN_TOPLEFT,
"FontName" => $CaptionFontName,
"FontSize" => $CaptionFontSize,
"R" => $CaptionR,
"G" => $CaptionG,
"B" => $CaptionB,
"Alpha" => $CaptionAlpha
];
} else {
$CaptionColor = [
"Align" => TEXT_ALIGN_TOPLEFT,
"FontName" => $CaptionFontName,
"FontSize" => $CaptionFontSize,
"R" => $Settings["R"] + $CaptionColorFactor,
"G" => $Settings["G"] + $CaptionColorFactor,
"B" => $Settings["B"] + $CaptionColorFactor
];
}
if ($SubCaptionColorFactor == null) {
$SubCaptionColor = [
"Align" => TEXT_ALIGN_TOPLEFT,
"FontName" => $CaptionFontName,
"FontSize" => $CaptionFontSize,
"R" => $SubCaptionR,
"G" => $SubCaptionG,
"B" => $SubCaptionB,
"Alpha" => $SubCaptionAlpha
];
} else {
$SubCaptionColor = [
"Align" => TEXT_ALIGN_TOPLEFT,
"FontName" => $CaptionFontName,
"FontSize" => $CaptionFontSize,
"R" => $Settings["R"] + $SubCaptionColorFactor,
"G" => $Settings["G"] + $SubCaptionColorFactor,
"B" => $Settings["B"] + $SubCaptionColorFactor
];
}
$RestoreShadow = $this->pChartObject->Shadow;
$this->pChartObject->Shadow = false;
if ($CaptionLayout == INDICATOR_CAPTION_DEFAULT) {
$this->pChartObject->drawText($X1, $Y + $Height + $TextPadding, $Caption, $CaptionColor);
} elseif ($CaptionLayout == INDICATOR_CAPTION_EXTENDED) {
$TxtPos = $this->pChartObject->getTextBox(
$X1,
$Y + $Height + $TextPadding,
$CaptionFontName,
$CaptionFontSize,
0,
$Caption
);
$CaptionHeight = $TxtPos[0]["Y"] - $TxtPos[2]["Y"];
$this->pChartObject->drawText(
$X1 + $XOffset,
$Y + $Height - $YOffset + $TextPadding,
$Caption,
$CaptionColor
);
$this->pChartObject->drawText(
$X1 + $XOffset,
$Y + $Height - $YOffset + $CaptionHeight + $TextPadding * 2,
$SubCaption,
$SubCaptionColor
);
}
$this->pChartObject->Shadow = $RestoreShadow;
$X1 = $X2 + $SectionsMargin;
}
$RestoreShadow = $this->pChartObject->Shadow;
$this->pChartObject->Shadow = false;
foreach ($Values as $Key => $Value) {
if ($Value >= $OverallMin && $Value <= $OverallMax) {
foreach ($IndicatorSections as $Key => $Settings) {
if ($Value >= $Settings["Start"] && $Value <= $Settings["End"]) {
$X1 = $ValuesPos[$Value]; //$X + $Key*$SectionsMargin + ($Value - $OverallMin) * $XScale;
if ($ValueDisplay == INDICATOR_VALUE_BUBBLE) {
$TxtPos = $this->pChartObject->getTextBox(
$X1,
$Y,
$ValueFontName,
$ValueFontSize,
0,
$Value . $Unit
);
$Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $TextPadding * 4) / 2);
$this->pChartObject->drawFilledCircle(
$X1,
$Y,
$Radius + 4,
[
"R" => $Settings["R"] + 20,
"G" => $Settings["G"] + 20,
"B" => $Settings["B"] + 20
]
);
$this->pChartObject->drawFilledCircle(
$X1,
$Y,
$Radius,
["R" => 255, "G" => 255, "B" => 255]
);
$TextSettings = [
"Align" => TEXT_ALIGN_MIDDLEMIDDLE,
"FontName" => $ValueFontName,
"FontSize" => $ValueFontSize
];
$this->pChartObject->drawText($X1 - 1, $Y - 1, $Value . $Unit, $TextSettings);
} elseif ($ValueDisplay == INDICATOR_VALUE_LABEL) {
$Caption = [
[
"Format" => [
"R" => $Settings["R"],
"G" => $Settings["G"],
"B" => $Settings["B"],
"Alpha" => 100
],
"Caption" => $Value . $Unit
]
];
$this->pChartObject->drawLabelBox(
floor($X1),
floor($Y) + 2,
"Value - " . $Settings["Caption"],
$Caption
);
}
}
$X1 = $X2 + $SectionsMargin;
}
}
}
$this->pChartObject->Shadow = $RestoreShadow;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+180
View File
@@ -0,0 +1,180 @@
<?php
namespace CpChart\Chart;
use CpChart\Data;
use CpChart\Image;
/**
* Split - class to draw spline splitted charts
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Split
{
/**
* @var Image
*/
public $pChartObject;
/**
* Create the encoded string
* @param Image $Object
* @param Data $Values
* @param array $Format
*/
public function drawSplitPath(Image $Object, Data $Values, array $Format = [])
{
$this->pChartObject = $Object;
$Spacing = isset($Format["Spacing"]) ? $Format["Spacing"] : 20;
$TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 2;
$TextPos = isset($Format["TextPos"]) ? $Format["TextPos"] : TEXT_POS_TOP;
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
$Force = isset($Format["Force"]) ? $Format["Force"] : 70;
$Segments = isset($Format["Segments"]) ? $Format["Segments"] : 15;
$X1 = $Object->GraphAreaX1;
$Y1 = $Object->GraphAreaY1;
$X2 = $Object->GraphAreaX2;
$Y2 = $Object->GraphAreaY2;
/* Data Processing */
$Data = $Values->getData();
$Palette = $Values->getPalette();
$LabelSerie = $Data["Abscissa"];
$DataSerie = [];
foreach ($Data["Series"] as $SerieName => $Value) {
if ($SerieName != $LabelSerie && empty($DataSerie)) {
$DataSerie = $SerieName;
}
}
$DataSerieSum = array_sum($Data["Series"][$DataSerie]["Data"]);
$DataSerieCount = count($Data["Series"][$DataSerie]["Data"]);
/* Scale Processing */
if ($TextPos == TEXT_POS_RIGHT) {
$YScale = (($Y2 - $Y1) - (($DataSerieCount + 1) * $Spacing)) / $DataSerieSum;
} else {
$YScale = (($Y2 - $Y1) - ($DataSerieCount * $Spacing)) / $DataSerieSum;
}
$LeftHeight = $DataSerieSum * $YScale;
/* Re-compute graph width depending of the text mode choosen */
if ($TextPos == TEXT_POS_RIGHT) {
$MaxWidth = 0;
foreach ($Data["Series"][$LabelSerie]["Data"] as $Key => $Label) {
$Boundardies = $Object->getTextBox(0, 0, $Object->FontName, $Object->FontSize, 0, $Label);
if ($Boundardies[1]["X"] > $MaxWidth) {
$MaxWidth = $Boundardies[1]["X"] + $TextPadding * 2;
}
}
$X2 = $X2 - $MaxWidth;
}
/* Drawing */
$LeftY = ((($Y2 - $Y1) / 2) + $Y1) - ($LeftHeight / 2);
$RightY = $Y1;
foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) {
if (isset($Data["Series"][$LabelSerie]["Data"][$Key])) {
$Label = $Data["Series"][$LabelSerie]["Data"][$Key];
} else {
$Label = "-";
}
$LeftY1 = $LeftY;
$LeftY2 = $LeftY + $Value * $YScale;
$RightY1 = $RightY + $Spacing;
$RightY2 = $RightY + $Spacing + $Value * $YScale;
$Settings = [
"R" => $Palette[$Key]["R"],
"G" => $Palette[$Key]["G"],
"B" => $Palette[$Key]["B"],
"Alpha" => $Palette[$Key]["Alpha"],
"NoDraw" => true,
"Segments" => $Segments,
"Surrounding" => $Surrounding
];
$Angle = $Object->getAngle($X2, $RightY1, $X1, $LeftY1);
$VectorX1 = cos(deg2rad($Angle + 90)) * $Force + ($X2 - $X1) / 2 + $X1;
$VectorY1 = sin(deg2rad($Angle + 90)) * $Force + ($RightY1 - $LeftY1) / 2 + $LeftY1;
$VectorX2 = cos(deg2rad($Angle - 90)) * $Force + ($X2 - $X1) / 2 + $X1;
$VectorY2 = sin(deg2rad($Angle - 90)) * $Force + ($RightY1 - $LeftY1) / 2 + $LeftY1;
$Points = $Object->drawBezier(
$X1,
$LeftY1,
$X2,
$RightY1,
$VectorX1,
$VectorY1,
$VectorX2,
$VectorY2,
$Settings
);
$PolyGon = [];
foreach ($Points as $Key => $Pos) {
$PolyGon[] = $Pos["X"];
$PolyGon[] = $Pos["Y"];
}
$Angle = $Object->getAngle($X2, $RightY2, $X1, $LeftY2);
$VectorX1 = cos(deg2rad($Angle + 90)) * $Force + ($X2 - $X1) / 2 + $X1;
$VectorY1 = sin(deg2rad($Angle + 90)) * $Force + ($RightY2 - $LeftY2) / 2 + $LeftY2;
$VectorX2 = cos(deg2rad($Angle - 90)) * $Force + ($X2 - $X1) / 2 + $X1;
$VectorY2 = sin(deg2rad($Angle - 90)) * $Force + ($RightY2 - $LeftY2) / 2 + $LeftY2;
$Points = $Object->drawBezier(
$X1,
$LeftY2,
$X2,
$RightY2,
$VectorX1,
$VectorY1,
$VectorX2,
$VectorY2,
$Settings
);
$Points = array_reverse($Points);
foreach ($Points as $Key => $Pos) {
$PolyGon[] = $Pos["X"];
$PolyGon[] = $Pos["Y"];
}
$Object->drawPolygon($PolyGon, $Settings);
if ($TextPos == TEXT_POS_RIGHT) {
$Object->drawText(
$X2 + $TextPadding,
($RightY2 - $RightY1) / 2 + $RightY1,
$Label,
["Align" => TEXT_ALIGN_MIDDLELEFT]
);
} else {
$Object->drawText(
$X2,
$RightY1 - $TextPadding,
$Label,
["Align" => TEXT_ALIGN_BOTTOMRIGHT]
);
}
$LeftY = $LeftY2;
$RightY = $RightY2;
}
}
}
File diff suppressed because it is too large Load Diff
+453
View File
@@ -0,0 +1,453 @@
<?php
namespace CpChart\Chart;
use CpChart\Data;
use CpChart\Image;
/**
* Stock - class to draw stock charts
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Stock
{
/**
* @var Image
*/
public $pChartObject;
/**
* @var Data
*/
public $pDataObject;
/**
* @param Image $pChartObject
* @param Data $pDataObject
*/
public function __construct(Image $pChartObject, Data $pDataObject)
{
$this->pChartObject = $pChartObject;
$this->pDataObject = $pDataObject;
}
/**
* Draw a stock chart
* @param array $Format
* @return integer|null
*/
public function drawStockChart(array $Format = [])
{
$SerieOpen = isset($Format["SerieOpen"]) ? $Format["SerieOpen"] : "Open";
$SerieClose = isset($Format["SerieClose"]) ? $Format["SerieClose"] : "Close";
$SerieMin = isset($Format["SerieMin"]) ? $Format["SerieMin"] : "Min";
$SerieMax = isset($Format["SerieMax"]) ? $Format["SerieMax"] : "Max";
$SerieMedian = isset($Format["SerieMedian"]) ? $Format["SerieMedian"] : null;
$LineWidth = isset($Format["LineWidth"]) ? $Format["LineWidth"] : 1;
$LineR = isset($Format["LineR"]) ? $Format["LineR"] : 0;
$LineG = isset($Format["LineG"]) ? $Format["LineG"] : 0;
$LineB = isset($Format["LineB"]) ? $Format["LineB"] : 0;
$LineAlpha = isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 100;
$ExtremityWidth = isset($Format["ExtremityWidth"]) ? $Format["ExtremityWidth"] : 1;
$ExtremityLength = isset($Format["ExtremityLength"]) ? $Format["ExtremityLength"] : 3;
$ExtremityR = isset($Format["ExtremityR"]) ? $Format["ExtremityR"] : 0;
$ExtremityG = isset($Format["ExtremityG"]) ? $Format["ExtremityG"] : 0;
$ExtremityB = isset($Format["ExtremityB"]) ? $Format["ExtremityB"] : 0;
$ExtremityAlpha = isset($Format["ExtremityAlpha"]) ? $Format["ExtremityAlpha"] : 100;
$BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 8;
$BoxUpR = isset($Format["BoxUpR"]) ? $Format["BoxUpR"] : 188;
$BoxUpG = isset($Format["BoxUpG"]) ? $Format["BoxUpG"] : 224;
$BoxUpB = isset($Format["BoxUpB"]) ? $Format["BoxUpB"] : 46;
$BoxUpAlpha = isset($Format["BoxUpAlpha"]) ? $Format["BoxUpAlpha"] : 100;
$BoxUpSurrounding = isset($Format["BoxUpSurrounding"]) ? $Format["BoxUpSurrounding"] : null;
$BoxUpBorderR = isset($Format["BoxUpBorderR"]) ? $Format["BoxUpBorderR"] : $BoxUpR - 20;
$BoxUpBorderG = isset($Format["BoxUpBorderG"]) ? $Format["BoxUpBorderG"] : $BoxUpG - 20;
$BoxUpBorderB = isset($Format["BoxUpBorderB"]) ? $Format["BoxUpBorderB"] : $BoxUpB - 20;
$BoxUpBorderAlpha = isset($Format["BoxUpBorderAlpha"]) ? $Format["BoxUpBorderAlpha"] : 100;
$BoxDownR = isset($Format["BoxDownR"]) ? $Format["BoxDownR"] : 224;
$BoxDownG = isset($Format["BoxDownG"]) ? $Format["BoxDownG"] : 100;
$BoxDownB = isset($Format["BoxDownB"]) ? $Format["BoxDownB"] : 46;
$BoxDownAlpha = isset($Format["BoxDownAlpha"]) ? $Format["BoxDownAlpha"] : 100;
$BoxDownSurrounding = isset($Format["BoxDownSurrounding"]) ? $Format["BoxDownSurrounding"] : null;
$BoxDownBorderR = isset($Format["BoxDownBorderR"]) ? $Format["BoxDownBorderR"] : $BoxDownR - 20;
$BoxDownBorderG = isset($Format["BoxDownBorderG"]) ? $Format["BoxDownBorderG"] : $BoxDownG - 20;
$BoxDownBorderB = isset($Format["BoxDownBorderB"]) ? $Format["BoxDownBorderB"] : $BoxDownB - 20;
$BoxDownBorderAlpha = isset($Format["BoxDownBorderAlpha"]) ? $Format["BoxDownBorderAlpha"] : 100;
$ShadowOnBoxesOnly = isset($Format["ShadowOnBoxesOnly"]) ? $Format["ShadowOnBoxesOnly"] : true;
$MedianR = isset($Format["MedianR"]) ? $Format["MedianR"] : 255;
$MedianG = isset($Format["MedianG"]) ? $Format["MedianG"] : 0;
$MedianB = isset($Format["MedianB"]) ? $Format["MedianB"] : 0;
$MedianAlpha = isset($Format["MedianAlpha"]) ? $Format["MedianAlpha"] : 100;
$RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;
$ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : "Stock Chart";
/* Data Processing */
if ($BoxUpSurrounding != null) {
$BoxUpBorderR = $BoxUpR + $BoxUpSurrounding;
$BoxUpBorderG = $BoxUpG + $BoxUpSurrounding;
$BoxUpBorderB = $BoxUpB + $BoxUpSurrounding;
}
if ($BoxDownSurrounding != null) {
$BoxDownBorderR = $BoxDownR + $BoxDownSurrounding;
$BoxDownBorderG = $BoxDownG + $BoxDownSurrounding;
$BoxDownBorderB = $BoxDownB + $BoxDownSurrounding;
}
if ($LineWidth != 1) {
$LineOffset = $LineWidth / 2;
}
$BoxOffset = $BoxWidth / 2;
$Data = $this->pChartObject->DataSet->getData();
list($XMargin, $XDivs) = $this->pChartObject->scaleGetXSettings();
if (!isset($Data["Series"][$SerieOpen])
|| !isset($Data["Series"][$SerieClose])
|| !isset($Data["Series"][$SerieMin])
|| !isset($Data["Series"][$SerieMax])
) {
return STOCK_MISSING_SERIE;
}
$Plots = [];
foreach ($Data["Series"][$SerieOpen]["Data"] as $Key => $Value) {
$Point = [];
if (isset($Data["Series"][$SerieClose]["Data"][$Key])
|| isset($Data["Series"][$SerieMin]["Data"][$Key])
|| isset($Data["Series"][$SerieMax]["Data"][$Key])
) {
$Point = [
$Value,
$Data["Series"][$SerieClose]["Data"][$Key],
$Data["Series"][$SerieMin]["Data"][$Key],
$Data["Series"][$SerieMax]["Data"][$Key]
];
}
if ($SerieMedian != null && isset($Data["Series"][$SerieMedian]["Data"][$Key])) {
$Point[] = $Data["Series"][$SerieMedian]["Data"][$Key];
}
$Plots[] = $Point;
}
$AxisID = $Data["Series"][$SerieOpen]["Axis"];
$Format = $Data["Axis"][$AxisID]["Format"];
$YZero = $this->pChartObject->scaleComputeY(0, ["AxisID" => $AxisID]);
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2) / $XDivs;
$X = $this->pChartObject->GraphAreaX1 + $XMargin;
$Y = $this->pChartObject->GraphAreaY1 + $XMargin;
$LineSettings = ["R" => $LineR, "G" => $LineG, "B" => $LineB, "Alpha" => $LineAlpha];
$ExtremitySettings = [
"R" => $ExtremityR,
"G" => $ExtremityG,
"B" => $ExtremityB,
"Alpha" => $ExtremityAlpha
];
$BoxUpSettings = [
"R" => $BoxUpR,
"G" => $BoxUpG,
"B" => $BoxUpB,
"Alpha" => $BoxUpAlpha,
"BorderR" => $BoxUpBorderR,
"BorderG" => $BoxUpBorderG,
"BorderB" => $BoxUpBorderB,
"BorderAlpha" => $BoxUpBorderAlpha
];
$BoxDownSettings = [
"R" => $BoxDownR,
"G" => $BoxDownG,
"B" => $BoxDownB,
"Alpha" => $BoxDownAlpha,
"BorderR" => $BoxDownBorderR,
"BorderG" => $BoxDownBorderG,
"BorderB" => $BoxDownBorderB,
"BorderAlpha" => $BoxDownBorderAlpha
];
$MedianSettings = ["R" => $MedianR, "G" => $MedianG, "B" => $MedianB, "Alpha" => $MedianAlpha];
foreach ($Plots as $Key => $Points) {
$PosArray = $this->pChartObject->scaleComputeY($Points, ["AxisID" => $AxisID]);
$Values = "Open :" . $Data["Series"][$SerieOpen]["Data"][$Key]
. "<BR>Close : " . $Data["Series"][$SerieClose]["Data"][$Key]
. "<BR>Min : " . $Data["Series"][$SerieMin]["Data"][$Key]
. "<BR>Max : " . $Data["Series"][$SerieMax]["Data"][$Key] . "<BR>";
if ($SerieMedian != null) {
$Values = $Values . "Median : " . $Data["Series"][$SerieMedian]["Data"][$Key] . "<BR>";
}
if ($PosArray[0] > $PosArray[1]) {
$ImageMapColor = $this->pChartObject->toHTMLColor($BoxUpR, $BoxUpG, $BoxUpB);
} else {
$ImageMapColor = $this->pChartObject->toHTMLColor($BoxDownR, $BoxDownG, $BoxDownB);
}
if ($Data["Orientation"] == SCALE_POS_LEFTRIGHT) {
if ($YZero > $this->pChartObject->GraphAreaY2 - 1) {
$YZero = $this->pChartObject->GraphAreaY2 - 1;
}
if ($YZero < $this->pChartObject->GraphAreaY1 + 1) {
$YZero = $this->pChartObject->GraphAreaY1 + 1;
}
if ($XDivs == 0) {
$XStep = 0;
} else {
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2)
/ $XDivs
;
}
if ($ShadowOnBoxesOnly) {
$RestoreShadow = $this->pChartObject->Shadow;
$this->pChartObject->Shadow = false;
}
if ($LineWidth == 1) {
$this->pChartObject->drawLine($X, $PosArray[2], $X, $PosArray[3], $LineSettings);
} else {
$this->pChartObject->drawFilledRectangle(
$X - $LineOffset,
$PosArray[2],
$X + $LineOffset,
$PosArray[3],
$LineSettings
);
}
if ($ExtremityWidth == 1) {
$this->pChartObject->drawLine(
$X - $ExtremityLength,
$PosArray[2],
$X + $ExtremityLength,
$PosArray[2],
$ExtremitySettings
);
$this->pChartObject->drawLine(
$X - $ExtremityLength,
$PosArray[3],
$X + $ExtremityLength,
$PosArray[3],
$ExtremitySettings
);
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"RECT",
sprintf(
"%s,%s,%s,%s",
floor($X - $ExtremityLength),
floor($PosArray[2]),
floor($X + $ExtremityLength),
floor($PosArray[3])
),
$ImageMapColor,
$ImageMapTitle,
$Values
);
}
} else {
$this->pChartObject->drawFilledRectangle(
$X - $ExtremityLength,
$PosArray[2],
$X + $ExtremityLength,
$PosArray[2] - $ExtremityWidth,
$ExtremitySettings
);
$this->pChartObject->drawFilledRectangle(
$X - $ExtremityLength,
$PosArray[3],
$X + $ExtremityLength,
$PosArray[3] + $ExtremityWidth,
$ExtremitySettings
);
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"RECT",
sprintf(
"%s,%s,%s,%s",
floor($X - $ExtremityLength),
floor($PosArray[2] - $ExtremityWidth),
floor($X + $ExtremityLength),
floor($PosArray[3] + $ExtremityWidth)
),
$ImageMapColor,
$ImageMapTitle,
$Values
);
}
}
if ($ShadowOnBoxesOnly) {
$this->pChartObject->Shadow = $RestoreShadow;
}
if ($PosArray[0] > $PosArray[1]) {
$this->pChartObject->drawFilledRectangle(
$X - $BoxOffset,
$PosArray[0],
$X + $BoxOffset,
$PosArray[1],
$BoxUpSettings
);
} else {
$this->pChartObject->drawFilledRectangle(
$X - $BoxOffset,
$PosArray[0],
$X + $BoxOffset,
$PosArray[1],
$BoxDownSettings
);
}
if (isset($PosArray[4])) {
$this->pChartObject->drawLine(
$X - $ExtremityLength,
$PosArray[4],
$X + $ExtremityLength,
$PosArray[4],
$MedianSettings
);
}
$X = $X + $XStep;
} elseif ($Data["Orientation"] == SCALE_POS_TOPBOTTOM) {
if ($YZero > $this->pChartObject->GraphAreaX2 - 1) {
$YZero = $this->pChartObject->GraphAreaX2 - 1;
}
if ($YZero < $this->pChartObject->GraphAreaX1 + 1) {
$YZero = $this->pChartObject->GraphAreaX1 + 1;
}
if ($XDivs == 0) {
$XStep = 0;
} else {
$XStep = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $XMargin * 2)
/ $XDivs
;
}
if ($LineWidth == 1) {
$this->pChartObject->drawLine($PosArray[2], $Y, $PosArray[3], $Y, $LineSettings);
} else {
$this->pChartObject->drawFilledRectangle(
$PosArray[2],
$Y - $LineOffset,
$PosArray[3],
$Y + $LineOffset,
$LineSettings
);
}
if ($ShadowOnBoxesOnly) {
$RestoreShadow = $this->pChartObject->Shadow;
$this->pChartObject->Shadow = false;
}
if ($ExtremityWidth == 1) {
$this->pChartObject->drawLine(
$PosArray[2],
$Y - $ExtremityLength,
$PosArray[2],
$Y + $ExtremityLength,
$ExtremitySettings
);
$this->pChartObject->drawLine(
$PosArray[3],
$Y - $ExtremityLength,
$PosArray[3],
$Y + $ExtremityLength,
$ExtremitySettings
);
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"RECT",
sprintf(
"%s,%s,%s,%s",
floor($PosArray[2]),
floor($Y - $ExtremityLength),
floor($PosArray[3]),
floor($Y + $ExtremityLength)
),
$ImageMapColor,
$ImageMapTitle,
$Values
);
}
} else {
$this->pChartObject->drawFilledRectangle(
$PosArray[2],
$Y - $ExtremityLength,
$PosArray[2] - $ExtremityWidth,
$Y + $ExtremityLength,
$ExtremitySettings
);
$this->pChartObject->drawFilledRectangle(
$PosArray[3],
$Y - $ExtremityLength,
$PosArray[3] + $ExtremityWidth,
$Y + $ExtremityLength,
$ExtremitySettings
);
if ($RecordImageMap) {
$this->pChartObject->addToImageMap(
"RECT",
sprintf(
"%s,%s,%s,%s",
floor($PosArray[2] - $ExtremityWidth),
floor($Y - $ExtremityLength),
floor($PosArray[3] + $ExtremityWidth),
floor($Y + $ExtremityLength)
),
$ImageMapColor,
$ImageMapTitle,
$Values
);
}
}
if ($ShadowOnBoxesOnly) {
$this->pChartObject->Shadow = $RestoreShadow;
}
if ($PosArray[0] < $PosArray[1]) {
$this->pChartObject->drawFilledRectangle(
$PosArray[0],
$Y - $BoxOffset,
$PosArray[1],
$Y + $BoxOffset,
$BoxUpSettings
);
} else {
$this->pChartObject->drawFilledRectangle(
$PosArray[0],
$Y - $BoxOffset,
$PosArray[1],
$Y + $BoxOffset,
$BoxDownSettings
);
}
if (isset($PosArray[4])) {
$this->pChartObject->drawLine(
$PosArray[4],
$Y - $ExtremityLength,
$PosArray[4],
$Y + $ExtremityLength,
$MedianSettings
);
}
$Y = $Y + $XStep;
}
}
}
}
+414
View File
@@ -0,0 +1,414 @@
<?php
namespace CpChart\Chart;
use CpChart\Image;
/**
* Surface - class to draw surface charts
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Surface
{
/**
* @var Image
*/
public $pChartObject;
/**
* @var int
*/
public $GridSizeX;
/**
* @var int
*/
public $GridSizeY;
/**
* @var array
*/
public $Points = [];
/**
* @param Image $pChartObject
*/
public function __construct(Image $pChartObject)
{
$this->pChartObject = $pChartObject;
}
/**
* Define the grid size and initialise the 2D matrix
* @param int $XSize
* @param int $YSize
*/
public function setGrid($XSize = 10, $YSize = 10)
{
for ($X = 0; $X <= $XSize; $X++) {
for ($Y = 0; $Y <= $YSize; $Y++) {
$this->Points[$X][$Y] = UNKNOWN;
}
}
$this->GridSizeX = $XSize;
$this->GridSizeY = $YSize;
}
/**
* Add a point on the grid
* @param int $X
* @param int $Y
* @param int|float $Value
* @param boolean $Force
* @return null
*/
public function addPoint($X, $Y, $Value, $Force = true)
{
if ($X < 0 || $X > $this->GridSizeX) {
return 0;
}
if ($Y < 0 || $Y > $this->GridSizeY) {
return 0;
}
if ($this->Points[$X][$Y] == UNKNOWN || $Force) {
$this->Points[$X][$Y] = $Value;
} elseif ($this->Points[$X][$Y] == UNKNOWN) {
$this->Points[$X][$Y] = $Value;
} else {
$this->Points[$X][$Y] = ($this->Points[$X][$Y] + $Value) / 2;
}
}
/**
* Write the X labels
* @param array $Format
* @return null|int
*/
public function writeXLabels(array $Format = [])
{
$R = isset($Format["R"]) ? $Format["R"] : $this->pChartObject->FontColorR;
$G = isset($Format["G"]) ? $Format["G"] : $this->pChartObject->FontColorG;
$B = isset($Format["B"]) ? $Format["B"] : $this->pChartObject->FontColorB;
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->pChartObject->FontColorA;
$Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0;
$Padding = isset($Format["Padding"]) ? $Format["Padding"] : 5;
$Position = isset($Format["Position"]) ? $Format["Position"] : LABEL_POSITION_TOP;
$Labels = isset($Format["Labels"]) ? $Format["Labels"] : null;
$CountOffset = isset($Format["CountOffset"]) ? $Format["CountOffset"] : 0;
if ($Labels != null && !is_array($Labels)) {
$Label = $Labels;
$Labels = [$Label];
}
$X0 = $this->pChartObject->GraphAreaX1;
$XSize = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / ($this->GridSizeX + 1);
$Settings = ["Angle" => $Angle, "R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha];
if ($Position == LABEL_POSITION_TOP) {
$YPos = $this->pChartObject->GraphAreaY1 - $Padding;
if ($Angle == 0) {
$Settings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE;
}
if ($Angle != 0) {
$Settings["Align"] = TEXT_ALIGN_MIDDLELEFT;
}
} elseif ($Position == LABEL_POSITION_BOTTOM) {
$YPos = $this->pChartObject->GraphAreaY2 + $Padding;
if ($Angle == 0) {
$Settings["Align"] = TEXT_ALIGN_TOPMIDDLE;
}
if ($Angle != 0) {
$Settings["Align"] = TEXT_ALIGN_MIDDLERIGHT;
}
} else {
return -1;
}
for ($X = 0; $X <= $this->GridSizeX; $X++) {
$XPos = floor($X0 + $X * $XSize + $XSize / 2);
if ($Labels == null || !isset($Labels[$X])) {
$Value = $X + $CountOffset;
} else {
$Value = $Labels[$X];
}
$this->pChartObject->drawText($XPos, $YPos, $Value, $Settings);
}
}
/**
* Write the Y labels
* @param array $Format
* @return type
*/
public function writeYLabels(array $Format = [])
{
$R = isset($Format["R"]) ? $Format["R"] : $this->pChartObject->FontColorR;
$G = isset($Format["G"]) ? $Format["G"] : $this->pChartObject->FontColorG;
$B = isset($Format["B"]) ? $Format["B"] : $this->pChartObject->FontColorB;
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->pChartObject->FontColorA;
$Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0;
$Padding = isset($Format["Padding"]) ? $Format["Padding"] : 5;
$Position = isset($Format["Position"]) ? $Format["Position"] : LABEL_POSITION_LEFT;
$Labels = isset($Format["Labels"]) ? $Format["Labels"] : null;
$CountOffset = isset($Format["CountOffset"]) ? $Format["CountOffset"] : 0;
if ($Labels != null && !is_array($Labels)) {
$Label = $Labels;
$Labels = [$Label];
}
$Y0 = $this->pChartObject->GraphAreaY1;
$YSize = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / ($this->GridSizeY + 1);
$Settings = ["Angle" => $Angle, "R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha];
if ($Position == LABEL_POSITION_LEFT) {
$XPos = $this->pChartObject->GraphAreaX1 - $Padding;
$Settings["Align"] = TEXT_ALIGN_MIDDLERIGHT;
} elseif ($Position == LABEL_POSITION_RIGHT) {
$XPos = $this->pChartObject->GraphAreaX2 + $Padding;
$Settings["Align"] = TEXT_ALIGN_MIDDLELEFT;
} else {
return -1;
}
for ($Y = 0; $Y <= $this->GridSizeY; $Y++) {
$YPos = floor($Y0 + $Y * $YSize + $YSize / 2);
if ($Labels == null || !isset($Labels[$Y])) {
$Value = $Y + $CountOffset;
} else {
$Value = $Labels[$Y];
}
$this->pChartObject->drawText($XPos, $YPos, $Value, $Settings);
}
}
/**
* Draw the area arround the specified Threshold
* @param int|float $Threshold
* @param array $Format
*/
public function drawContour($Threshold, array $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;
$Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 3;
$Padding = isset($Format["Padding"]) ? $Format["Padding"] : 0;
$X0 = $this->pChartObject->GraphAreaX1;
$Y0 = $this->pChartObject->GraphAreaY1;
$XSize = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / ($this->GridSizeX + 1);
$YSize = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / ($this->GridSizeY + 1);
$Color = ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha, "Ticks" => $Ticks];
for ($X = 0; $X <= $this->GridSizeX; $X++) {
for ($Y = 0; $Y <= $this->GridSizeY; $Y++) {
$Value = $this->Points[$X][$Y];
if ($Value != UNKNOWN && $Value != IGNORED && $Value >= $Threshold) {
$X1 = floor($X0 + $X * $XSize) + $Padding;
$Y1 = floor($Y0 + $Y * $YSize) + $Padding;
$X2 = floor($X0 + $X * $XSize + $XSize);
$Y2 = floor($Y0 + $Y * $YSize + $YSize);
if ($X > 0 && $this->Points[$X - 1][$Y] != UNKNOWN
&& $this->Points[$X - 1][$Y] != IGNORED
&& $this->Points[$X - 1][$Y] < $Threshold
) {
$this->pChartObject->drawLine($X1, $Y1, $X1, $Y2, $Color);
}
if ($Y > 0 && $this->Points[$X][$Y - 1] != UNKNOWN
&& $this->Points[$X][$Y - 1] != IGNORED
&& $this->Points[$X][$Y - 1] < $Threshold
) {
$this->pChartObject->drawLine($X1, $Y1, $X2, $Y1, $Color);
}
if ($X < $this->GridSizeX
&& $this->Points[$X + 1][$Y] != UNKNOWN
&& $this->Points[$X + 1][$Y] != IGNORED
&& $this->Points[$X + 1][$Y] < $Threshold
) {
$this->pChartObject->drawLine($X2, $Y1, $X2, $Y2, $Color);
}
if ($Y < $this->GridSizeY
&& $this->Points[$X][$Y + 1] != UNKNOWN
&& $this->Points[$X][$Y + 1] != IGNORED
&& $this->Points[$X][$Y + 1] < $Threshold
) {
$this->pChartObject->drawLine($X1, $Y2, $X2, $Y2, $Color);
}
}
}
}
}
/**
* Draw the surface chart
* @param array $Format
*/
public function drawSurface(array $Format = [])
{
$Palette = isset($Format["Palette"]) ? $Format["Palette"] : null;
$ShadeR1 = isset($Format["ShadeR1"]) ? $Format["ShadeR1"] : 77;
$ShadeG1 = isset($Format["ShadeG1"]) ? $Format["ShadeG1"] : 205;
$ShadeB1 = isset($Format["ShadeB1"]) ? $Format["ShadeB1"] : 21;
$ShadeA1 = isset($Format["ShadeA1"]) ? $Format["ShadeA1"] : 40;
$ShadeR2 = isset($Format["ShadeR2"]) ? $Format["ShadeR2"] : 227;
$ShadeG2 = isset($Format["ShadeG2"]) ? $Format["ShadeG2"] : 135;
$ShadeB2 = isset($Format["ShadeB2"]) ? $Format["ShadeB2"] : 61;
$ShadeA2 = isset($Format["ShadeA2"]) ? $Format["ShadeA2"] : 100;
$Border = isset($Format["Border"]) ? $Format["Border"] : false;
$BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0;
$BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0;
$BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0;
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : -1;
$Padding = isset($Format["Padding"]) ? $Format["Padding"] : 1;
$X0 = $this->pChartObject->GraphAreaX1;
$Y0 = $this->pChartObject->GraphAreaY1;
$XSize = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / ($this->GridSizeX + 1);
$YSize = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / ($this->GridSizeY + 1);
for ($X = 0; $X <= $this->GridSizeX; $X++) {
for ($Y = 0; $Y <= $this->GridSizeY; $Y++) {
$Value = $this->Points[$X][$Y];
if ($Value != UNKNOWN && $Value != IGNORED) {
$X1 = floor($X0 + $X * $XSize) + $Padding;
$Y1 = floor($Y0 + $Y * $YSize) + $Padding;
$X2 = floor($X0 + $X * $XSize + $XSize);
$Y2 = floor($Y0 + $Y * $YSize + $YSize);
if ($Palette != null) {
if (isset($Palette[$Value]) && isset($Palette[$Value]["R"])) {
$R = $Palette[$Value]["R"];
} else {
$R = 0;
}
if (isset($Palette[$Value]) && isset($Palette[$Value]["G"])) {
$G = $Palette[$Value]["G"];
} else {
$G = 0;
}
if (isset($Palette[$Value]) && isset($Palette[$Value]["B"])) {
$B = $Palette[$Value]["B"];
} else {
$B = 0;
}
if (isset($Palette[$Value]) && isset($Palette[$Value]["Alpha"])) {
$Alpha = $Palette[$Value]["Alpha"];
} else {
$Alpha = 1000;
}
} else {
$R = (($ShadeR2 - $ShadeR1) / 100) * $Value + $ShadeR1;
$G = (($ShadeG2 - $ShadeG1) / 100) * $Value + $ShadeG1;
$B = (($ShadeB2 - $ShadeB1) / 100) * $Value + $ShadeB1;
$Alpha = (($ShadeA2 - $ShadeA1) / 100) * $Value + $ShadeA1;
}
$Settings = ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha];
if ($Border) {
$Settings["BorderR"] = $BorderR;
$Settings["BorderG"] = $BorderG;
$Settings["BorderB"] = $BorderB;
}
if ($Surrounding != -1) {
$Settings["BorderR"] = $R + $Surrounding;
$Settings["BorderG"] = $G + $Surrounding;
$Settings["BorderB"] = $B + $Surrounding;
}
$this->pChartObject->drawFilledRectangle($X1, $Y1, $X2 - 1, $Y2 - 1, $Settings);
}
}
}
}
/**
* Compute the missing points
*/
public function computeMissing()
{
$Missing = [];
for ($X = 0; $X <= $this->GridSizeX; $X++) {
for ($Y = 0; $Y <= $this->GridSizeY; $Y++) {
if ($this->Points[$X][$Y] == UNKNOWN) {
$Missing[] = $X . "," . $Y;
}
}
}
shuffle($Missing);
foreach ($Missing as $Pos) {
$Pos = preg_split("/,/", $Pos);
$X = $Pos[0];
$Y = $Pos[1];
if ($this->Points[$X][$Y] == UNKNOWN) {
$NearestNeighbor = $this->getNearestNeighbor($X, $Y);
$Value = 0;
$Points = 0;
for ($Xi = $X - $NearestNeighbor; $Xi <= $X + $NearestNeighbor; $Xi++) {
for ($Yi = $Y - $NearestNeighbor; $Yi <= $Y + $NearestNeighbor; $Yi++) {
if ($Xi >= 0
&& $Yi >= 0
&& $Xi <= $this->GridSizeX
&& $Yi <= $this->GridSizeY
&& $this->Points[$Xi][$Yi] != UNKNOWN
&& $this->Points[$Xi][$Yi] != IGNORED
) {
$Value = $Value + $this->Points[$Xi][$Yi];
$Points++;
}
}
}
if ($Points != 0) {
$this->Points[$X][$Y] = $Value / $Points;
}
}
}
}
/**
* Return the nearest Neighbor distance of a point
* @param int $Xp
* @param int $Yp
* @return int
*/
public function getNearestNeighbor($Xp, $Yp)
{
$Nearest = UNKNOWN;
for ($X = 0; $X <= $this->GridSizeX; $X++) {
for ($Y = 0; $Y <= $this->GridSizeY; $Y++) {
if ($this->Points[$X][$Y] != UNKNOWN && $this->Points[$X][$Y] != IGNORED) {
$DistanceX = max($Xp, $X) - min($Xp, $X);
$DistanceY = max($Yp, $Y) - min($Yp, $Y);
$Distance = max($DistanceX, $DistanceY);
if ($Distance < $Nearest || $Nearest == UNKNOWN) {
$Nearest = $Distance;
}
}
}
}
return $Nearest;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+748
View File
@@ -0,0 +1,748 @@
<?php
namespace CpChart;
/**
* Image - The actual class to do most of the drawing. Extends the Draw class
* with the bulk of drawing methods.
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* 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.
*/
class Image extends Draw
{
/**
* @param int $XSize
* @param int $YSize
* @param Data $DataSet
* @param boolean $TransparentBackground
*/
public function __construct(
$XSize,
$YSize,
Data $DataSet = null,
$TransparentBackground = false
) {
parent::__construct();
$this->TransparentBackground = $TransparentBackground;
$this->DataSet = null !== $DataSet ? $DataSet : new Data();
$this->XSize = $XSize;
$this->YSize = $YSize;
$this->Picture = imagecreatetruecolor($XSize, $YSize);
if ($this->TransparentBackground) {
imagealphablending($this->Picture, false);
imagefilledrectangle(
$this->Picture,
0,
0,
$XSize,
$YSize,
imagecolorallocatealpha($this->Picture, 255, 255, 255, 127)
);
imagealphablending($this->Picture, true);
imagesavealpha($this->Picture, true);
} else {
$C_White = $this->AllocateColor($this->Picture, 255, 255, 255);
imagefilledrectangle($this->Picture, 0, 0, $XSize, $YSize, $C_White);
}
}
/**
* Enable / Disable and set shadow properties
* @param boolean $Enabled
* @param array $Format
*/
public function setShadow($Enabled = true, array $Format = [])
{
$X = isset($Format["X"]) ? $Format["X"] : 2;
$Y = isset($Format["Y"]) ? $Format["Y"] : 2;
$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"] : 10;
$this->Shadow = $Enabled;
$this->ShadowX = $X;
$this->ShadowY = $Y;
$this->ShadowR = $R;
$this->ShadowG = $G;
$this->ShadowB = $B;
$this->Shadowa = $Alpha;
}
/**
* Set the graph area position
* @param int $X1
* @param int $Y1
* @param int $X2
* @param int $Y2
* @return int|null
*/
public function setGraphArea($X1, $Y1, $X2, $Y2)
{
if ($X2 < $X1 || $X1 == $X2 || $Y2 < $Y1 || $Y1 == $Y2) {
return -1;
}
$this->GraphAreaX1 = $X1;
$this->DataSet->Data["GraphArea"]["X1"] = $X1;
$this->GraphAreaY1 = $Y1;
$this->DataSet->Data["GraphArea"]["Y1"] = $Y1;
$this->GraphAreaX2 = $X2;
$this->DataSet->Data["GraphArea"]["X2"] = $X2;
$this->GraphAreaY2 = $Y2;
$this->DataSet->Data["GraphArea"]["Y2"] = $Y2;
}
/**
* Return the width of the picture
* @return int
*/
public function getWidth()
{
return $this->XSize;
}
/**
* Return the heigth of the picture
* @return int
*/
public function getHeight()
{
return $this->YSize;
}
/**
* Render the picture to a file
* @param string $FileName
*/
public function render($FileName)
{
if ($this->TransparentBackground) {
imagealphablending($this->Picture, false);
imagesavealpha($this->Picture, true);
}
imagepng($this->Picture, $FileName);
}
public function __toString()
{
if ($this->TransparentBackground) {
imagealphablending($this->Picture, false);
imagesavealpha($this->Picture, true);
}
ob_start();
imagepng($this->Picture);
return ob_get_clean();
}
public function toDataURI()
{
return 'data:image/png;base64,' . base64_encode($this->__toString());
}
/**
* Render the picture to a web browser stream
* @param boolean $BrowserExpire
*/
public function stroke($BrowserExpire = false)
{
if ($this->TransparentBackground) {
imagealphablending($this->Picture, false);
imagesavealpha($this->Picture, true);
}
if ($BrowserExpire) {
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache");
header("Pragma: no-cache");
}
header('Content-type: image/png');
imagepng($this->Picture);
}
/**
* Automatic output method based on the calling interface
* @param string $FileName
*/
public function autoOutput($FileName = "output.png")
{
if (php_sapi_name() == "cli") {
$this->Render($FileName);
} else {
$this->Stroke();
}
}
/**
* Return the length between two points
* @param int $X1
* @param int $Y1
* @param int $X2
* @param int $Y2
* @return float
*/
public function getLength($X1, $Y1, $X2, $Y2)
{
return sqrt(
pow(max($X1, $X2) - min($X1, $X2), 2) + pow(max($Y1, $Y2) - min($Y1, $Y2), 2)
);
}
/**
* Return the orientation of a line
* @param int $X1
* @param int $Y1
* @param int $X2
* @param int $Y2
* @return int
*/
public function getAngle($X1, $Y1, $X2, $Y2)
{
$Opposite = $Y2 - $Y1;
$Adjacent = $X2 - $X1;
$Angle = rad2deg(atan2($Opposite, $Adjacent));
if ($Angle > 0) {
return $Angle;
} else {
return 360 - abs($Angle);
}
}
/**
* Return the surrounding box of text area
* @param int $X
* @param int $Y
* @param string $FontName
* @param int $FontSize
* @param int $Angle
* @param int $Text
* @return array
*/
public function getTextBox($X, $Y, $FontName, $FontSize, $Angle, $Text)
{
$coords = imagettfbbox($FontSize, 0, $this->loadFont($FontName, 'fonts'), $Text);
$a = deg2rad($Angle);
$ca = cos($a);
$sa = sin($a);
$RealPos = [];
for ($i = 0; $i < 7; $i += 2) {
$RealPos[$i / 2]["X"] = $X + round($coords[$i] * $ca + $coords[$i + 1] * $sa);
$RealPos[$i / 2]["Y"] = $Y + round($coords[$i + 1] * $ca - $coords[$i] * $sa);
}
$RealPos[TEXT_ALIGN_BOTTOMLEFT]["X"] = $RealPos[0]["X"];
$RealPos[TEXT_ALIGN_BOTTOMLEFT]["Y"] = $RealPos[0]["Y"];
$RealPos[TEXT_ALIGN_BOTTOMRIGHT]["X"] = $RealPos[1]["X"];
$RealPos[TEXT_ALIGN_BOTTOMRIGHT]["Y"] = $RealPos[1]["Y"];
$RealPos[TEXT_ALIGN_TOPLEFT]["X"] = $RealPos[3]["X"];
$RealPos[TEXT_ALIGN_TOPLEFT]["Y"] = $RealPos[3]["Y"];
$RealPos[TEXT_ALIGN_TOPRIGHT]["X"] = $RealPos[2]["X"];
$RealPos[TEXT_ALIGN_TOPRIGHT]["Y"] = $RealPos[2]["Y"];
$RealPos[TEXT_ALIGN_BOTTOMMIDDLE]["X"] = ($RealPos[1]["X"] - $RealPos[0]["X"]) / 2 + $RealPos[0]["X"];
$RealPos[TEXT_ALIGN_BOTTOMMIDDLE]["Y"] = ($RealPos[0]["Y"] - $RealPos[1]["Y"]) / 2 + $RealPos[1]["Y"];
$RealPos[TEXT_ALIGN_TOPMIDDLE]["X"] = ($RealPos[2]["X"] - $RealPos[3]["X"]) / 2 + $RealPos[3]["X"];
$RealPos[TEXT_ALIGN_TOPMIDDLE]["Y"] = ($RealPos[3]["Y"] - $RealPos[2]["Y"]) / 2 + $RealPos[2]["Y"];
$RealPos[TEXT_ALIGN_MIDDLELEFT]["X"] = ($RealPos[0]["X"] - $RealPos[3]["X"]) / 2 + $RealPos[3]["X"];
$RealPos[TEXT_ALIGN_MIDDLELEFT]["Y"] = ($RealPos[0]["Y"] - $RealPos[3]["Y"]) / 2 + $RealPos[3]["Y"];
$RealPos[TEXT_ALIGN_MIDDLERIGHT]["X"] = ($RealPos[1]["X"] - $RealPos[2]["X"]) / 2 + $RealPos[2]["X"];
$RealPos[TEXT_ALIGN_MIDDLERIGHT]["Y"] = ($RealPos[1]["Y"] - $RealPos[2]["Y"]) / 2 + $RealPos[2]["Y"];
$RealPos[TEXT_ALIGN_MIDDLEMIDDLE]["X"] = ($RealPos[1]["X"] - $RealPos[3]["X"]) / 2 + $RealPos[3]["X"];
$RealPos[TEXT_ALIGN_MIDDLEMIDDLE]["Y"] = ($RealPos[0]["Y"] - $RealPos[2]["Y"]) / 2 + $RealPos[2]["Y"];
return $RealPos;
}
/**
* Set current font properties
* @param array $Format
*/
public function setFontProperties($Format = [])
{
$R = isset($Format["R"]) ? $Format["R"] : -1;
$G = isset($Format["G"]) ? $Format["G"] : -1;
$B = isset($Format["B"]) ? $Format["B"] : -1;
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
$FontName = isset($Format["FontName"]) ? $Format["FontName"] : null;
$FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : null;
if ($R != -1) {
$this->FontColorR = $R;
}
if ($G != -1) {
$this->FontColorG = $G;
}
if ($B != -1) {
$this->FontColorB = $B;
}
if ($Alpha != null) {
$this->FontColorA = $Alpha;
}
if ($FontName != null) {
$this->FontName = $this->loadFont($FontName, 'fonts');
}
if ($FontSize != null) {
$this->FontSize = $FontSize;
}
}
/**
* Returns the 1st decimal values (used to correct AA bugs)
* @param mixed $Value
* @return mixed
*/
public function getFirstDecimal($Value)
{
$Values = preg_split("/\./", $Value);
if (isset($Values[1])) {
return substr($Values[1], 0, 1);
} else {
return 0;
}
}
/**
* Attach a dataset to your pChart Object
* @param Data $DataSet
*/
public function setDataSet(Data $DataSet)
{
$this->DataSet = $DataSet;
}
/**
* Print attached dataset contents to STDOUT
*/
public function printDataSet()
{
print_r($this->DataSet);
}
/**
* Initialise the image map methods
* @param string $Name
* @param int $StorageMode
* @param string $UniqueID
* @param string $StorageFolder
*/
public function initialiseImageMap(
$Name = "pChart",
$StorageMode = IMAGE_MAP_STORAGE_SESSION,
$UniqueID = "imageMap",
$StorageFolder = "tmp"
) {
$this->ImageMapIndex = $Name;
$this->ImageMapStorageMode = $StorageMode;
if ($StorageMode == IMAGE_MAP_STORAGE_SESSION) {
if (!isset($_SESSION)) {
session_start();
}
$_SESSION[$this->ImageMapIndex] = null;
} elseif ($StorageMode == IMAGE_MAP_STORAGE_FILE) {
$this->ImageMapFileName = $UniqueID;
$this->ImageMapStorageFolder = $StorageFolder;
$path = sprintf("%s/%s.map", $StorageFolder, $UniqueID);
if (file_exists($path)) {
unlink($path);
}
}
}
/**
* Add a zone to the image map
*
* @param string $Type
* @param string $Plots
* @param string|null $Color
* @param string $Title
* @param string $Message
* @param boolean $HTMLEncode
*/
public function addToImageMap(
$Type,
$Plots,
$Color = null,
$Title = null,
$Message = null,
$HTMLEncode = false
) {
if ($this->ImageMapStorageMode == null) {
$this->initialiseImageMap();
}
/* Encode the characters in the imagemap in HTML standards */
$Title = htmlentities(
str_replace("&#8364;", "\u20AC", $Title),
ENT_QUOTES,
"ISO-8859-15"
);
if ($HTMLEncode) {
$Message = str_replace(
"&gt;",
">",
str_replace(
"&lt;",
"<",
htmlentities($Message, ENT_QUOTES, "ISO-8859-15")
)
);
}
if ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION) {
if (!isset($_SESSION)) {
$this->initialiseImageMap();
}
$_SESSION[$this->ImageMapIndex][] = [$Type, $Plots, $Color, $Title, $Message];
} elseif ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE) {
$Handle = fopen(
sprintf("%s/%s.map", $this->ImageMapStorageFolder, $this->ImageMapFileName),
'a'
);
fwrite(
$Handle,
sprintf(
"%s%s%s%s%s%s%s%s%s\r\n",
$Type,
IMAGE_MAP_DELIMITER,
$Plots,
IMAGE_MAP_DELIMITER,
$Color,
IMAGE_MAP_DELIMITER,
$Title,
IMAGE_MAP_DELIMITER,
$Message
)
);
fclose($Handle);
}
}
/**
* Remove VOID values from an imagemap custom values array
* @param string $SerieName
* @param array $Values
* @return array
*/
public function removeVOIDFromArray($SerieName, array $Values)
{
if (!isset($this->DataSet->Data["Series"][$SerieName])) {
return -1;
}
$Result = [];
foreach ($this->DataSet->Data["Series"][$SerieName]["Data"] as $Key => $Value) {
if ($Value != VOID && isset($Values[$Key])) {
$Result[] = $Values[$Key];
}
}
return $Result;
}
/**
* Replace the title of one image map serie
* @param string $OldTitle
* @param string|array $NewTitle
* @return null|int
*/
public function replaceImageMapTitle($OldTitle, $NewTitle)
{
if ($this->ImageMapStorageMode == null) {
return -1;
}
if (is_array($NewTitle)) {
$NewTitle = $this->removeVOIDFromArray($OldTitle, $NewTitle);
}
if ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION) {
if (!isset($_SESSION)) {
return -1;
}
if (is_array($NewTitle)) {
$ID = 0;
foreach ($_SESSION[$this->ImageMapIndex] as $Key => $Settings) {
if ($Settings[3] == $OldTitle && isset($NewTitle[$ID])) {
$_SESSION[$this->ImageMapIndex][$Key][3] = $NewTitle[$ID];
$ID++;
}
}
} else {
foreach ($_SESSION[$this->ImageMapIndex] as $Key => $Settings) {
if ($Settings[3] == $OldTitle) {
$_SESSION[$this->ImageMapIndex][$Key][3] = $NewTitle;
}
}
}
} elseif ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE) {
$TempArray = [];
$Handle = $this->openFileHandle();
if ($Handle) {
while (($Buffer = fgets($Handle, 4096)) !== false) {
$Fields = preg_split(
sprintf("/%s/", IMAGE_MAP_DELIMITER),
str_replace([chr(10), chr(13)], "", $Buffer)
);
$TempArray[] = [$Fields[0], $Fields[1], $Fields[2], $Fields[3], $Fields[4]];
}
fclose($Handle);
if (is_array($NewTitle)) {
$ID = 0;
foreach ($TempArray as $Key => $Settings) {
if ($Settings[3] == $OldTitle && isset($NewTitle[$ID])) {
$TempArray[$Key][3] = $NewTitle[$ID];
$ID++;
}
}
} else {
foreach ($TempArray as $Key => $Settings) {
if ($Settings[3] == $OldTitle) {
$TempArray[$Key][3] = $NewTitle;
}
}
}
$Handle = $this->openFileHandle("w");
foreach ($TempArray as $Key => $Settings) {
fwrite(
$Handle,
sprintf(
"%s%s%s%s%s%s%s%s%s\r\n",
$Settings[0],
IMAGE_MAP_DELIMITER,
$Settings[1],
IMAGE_MAP_DELIMITER,
$Settings[2],
IMAGE_MAP_DELIMITER,
$Settings[3],
IMAGE_MAP_DELIMITER,
$Settings[4]
)
);
}
fclose($Handle);
}
}
}
/**
* Replace the values of the image map contents
* @param string $Title
* @param array $Values
* @return null|int
*/
public function replaceImageMapValues($Title, array $Values)
{
if ($this->ImageMapStorageMode == null) {
return -1;
}
$Values = $this->removeVOIDFromArray($Title, $Values);
$ID = 0;
if ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION) {
if (!isset($_SESSION)) {
return -1;
}
foreach ($_SESSION[$this->ImageMapIndex] as $Key => $Settings) {
if ($Settings[3] == $Title) {
if (isset($Values[$ID])) {
$_SESSION[$this->ImageMapIndex][$Key][4] = $Values[$ID];
}
$ID++;
}
}
} elseif ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE) {
$TempArray = [];
$Handle = $this->openFileHandle();
if ($Handle) {
while (($Buffer = fgets($Handle, 4096)) !== false) {
$Fields = preg_split(
"/" . IMAGE_MAP_DELIMITER . "/",
str_replace([chr(10), chr(13)], "", $Buffer)
);
$TempArray[] = [$Fields[0], $Fields[1], $Fields[2], $Fields[3], $Fields[4]];
}
fclose($Handle);
foreach ($TempArray as $Key => $Settings) {
if ($Settings[3] == $Title) {
if (isset($Values[$ID])) {
$TempArray[$Key][4] = $Values[$ID];
}
$ID++;
}
}
$Handle = $this->openFileHandle("w");
foreach ($TempArray as $Key => $Settings) {
fwrite(
$Handle,
sprintf(
"%s%s%s%s%s%s%s%s%s\r\n",
$Settings[0],
IMAGE_MAP_DELIMITER,
$Settings[1],
IMAGE_MAP_DELIMITER,
$Settings[2],
IMAGE_MAP_DELIMITER,
$Settings[3],
IMAGE_MAP_DELIMITER,
$Settings[4]
)
);
}
fclose($Handle);
}
}
}
/**
* Dump the image map
* @param string $Name
* @param int $StorageMode
* @param string $UniqueID
* @param string $StorageFolder
*/
public function dumpImageMap(
$Name = "pChart",
$StorageMode = IMAGE_MAP_STORAGE_SESSION,
$UniqueID = "imageMap",
$StorageFolder = "tmp"
) {
$this->ImageMapIndex = $Name;
$this->ImageMapStorageMode = $StorageMode;
if ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION) {
if (!isset($_SESSION)) {
session_start();
}
if ($_SESSION[$Name] != null) {
foreach ($_SESSION[$Name] as $Key => $Params) {
echo $Params[0] . IMAGE_MAP_DELIMITER . $Params[1]
. IMAGE_MAP_DELIMITER . $Params[2] . IMAGE_MAP_DELIMITER
. $Params[3] . IMAGE_MAP_DELIMITER . $Params[4] . "\r\n";
}
}
} elseif ($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE) {
if (file_exists($StorageFolder . "/" . $UniqueID . ".map")) {
$Handle = @fopen($StorageFolder . "/" . $UniqueID . ".map", "r");
if ($Handle) {
while (($Buffer = fgets($Handle, 4096)) !== false) {
echo $Buffer;
}
}
fclose($Handle);
if ($this->ImageMapAutoDelete) {
unlink($StorageFolder . "/" . $UniqueID . ".map");
}
}
}
/* When the image map is returned to the client, the script ends */
exit();
}
/**
* Return the HTML converted color from the RGB composite values
* @param int $R
* @param int $G
* @param int $B
* @return string
*/
public function toHTMLColor($R, $G, $B)
{
$R = intval($R);
$G = intval($G);
$B = intval($B);
$R = dechex($R < 0 ? 0 : ($R > 255 ? 255 : $R));
$G = dechex($G < 0 ? 0 : ($G > 255 ? 255 : $G));
$B = dechex($B < 0 ? 0 : ($B > 255 ? 255 : $B));
$Color = "#" . (strlen($R) < 2 ? '0' : '') . $R;
$Color .= (strlen($G) < 2 ? '0' : '') . $G;
$Color .= (strlen($B) < 2 ? '0' : '') . $B;
return $Color;
}
/**
* Reverse an array of points
* @param array $Plots
* @return array
*/
public function reversePlots(array $Plots)
{
$Result = [];
for ($i = count($Plots) - 2; $i >= 0; $i = $i - 2) {
$Result[] = $Plots[$i];
$Result[] = $Plots[$i + 1];
}
return $Result;
}
/**
* Mirror Effect
* @param int $X
* @param int $Y
* @param int $Width
* @param int $Height
* @param array $Format
*/
public function drawAreaMirror($X, $Y, $Width, $Height, array $Format = [])
{
$StartAlpha = isset($Format["StartAlpha"]) ? $Format["StartAlpha"] : 80;
$EndAlpha = isset($Format["EndAlpha"]) ? $Format["EndAlpha"] : 0;
$AlphaStep = ($StartAlpha - $EndAlpha) / $Height;
$Picture = imagecreatetruecolor($this->XSize, $this->YSize);
imagecopy($Picture, $this->Picture, 0, 0, 0, 0, $this->XSize, $this->YSize);
for ($i = 1; $i <= $Height; $i++) {
if ($Y + ($i - 1) < $this->YSize && $Y - $i > 0) {
imagecopymerge(
$Picture,
$this->Picture,
$X,
$Y + ($i - 1),
$X,
$Y - $i,
$Width,
1,
$StartAlpha - $AlphaStep * $i
);
}
}
imagecopy($this->Picture, $Picture, 0, 0, 0, 0, $this->XSize, $this->YSize);
}
/**
* Open a handle to image storage file.
* @param string $mode
* @return resource
*/
private function openFileHandle($mode = "r")
{
return @fopen(
sprintf("%s/%s.map", $this->ImageMapStorageFolder, $this->ImageMapFileName),
$mode
);
}
}