376 lines
13 KiB
PHP
376 lines
13 KiB
PHP
<?php
|
|
/*=======================================================================
|
|
// File: JPGRAPH_MGRAPH.PHP
|
|
// Description: Class to handle multiple graphs in the same image
|
|
// Created: 2006-01-15
|
|
// Ver: $Id: jpgraph_mgraph.php 1770 2009-08-17 06:10:22Z ljp $
|
|
//
|
|
// Copyright (c) Asial Corporation. All rights reserved.
|
|
//========================================================================
|
|
*/
|
|
|
|
//=============================================================================
|
|
// CLASS MGraph
|
|
// Description: Create a container image that can hold several graph
|
|
//=============================================================================
|
|
class MGraph
|
|
{
|
|
public $title = null;
|
|
public $subtitle = null;
|
|
public $subsubtitle = null;
|
|
|
|
protected $img=null;
|
|
protected $iCnt=0;
|
|
protected $iGraphs = array(); // image_handle, x, y, fx, fy, sizex, sizey
|
|
protected $iFillColor='white';
|
|
protected $iCurrentColor=0;
|
|
protected $lm=4;
|
|
protected $rm=4;
|
|
protected $tm=4;
|
|
protected $bm=4;
|
|
protected $iDoFrame = false;
|
|
protected $iFrameColor = 'black';
|
|
protected $iFrameWeight = 1;
|
|
protected $iLineWeight = 1;
|
|
protected $expired=false;
|
|
protected $cache=null;
|
|
protected $cache_name = '';
|
|
protected $inline=true;
|
|
protected $image_format='png';
|
|
protected $image_quality=75;
|
|
protected $iWidth=null;
|
|
protected $iHeight=null;
|
|
protected $background_image='';
|
|
protected $background_image_center=true;
|
|
protected $backround_image_format='';
|
|
protected $background_image_mix=100;
|
|
protected $background_image_y=null;
|
|
protected $background_image_x=null;
|
|
private $doshadow=false;
|
|
private $shadow_width=4;
|
|
private $shadow_color='gray@0.5';
|
|
public $footer;
|
|
|
|
|
|
// Create a new instane of the combined graph
|
|
public function __construct($aWidth=null, $aHeight=null, $aCachedName='', $aTimeOut=0, $aInline=true)
|
|
{
|
|
$this->iWidth = $aWidth;
|
|
$this->iHeight = $aHeight;
|
|
|
|
// If the cached version exist just read it directly from the
|
|
// cache, stream it back to browser and exit
|
|
if ($aCachedName!='' && READ_CACHE && $aInline) {
|
|
$this->cache = new ImgStreamCache();
|
|
$this->cache->SetTimeOut($aTimeOut);
|
|
$image = new Image();
|
|
if ($this->cache->GetAndStream($image, $aCachedName)) {
|
|
exit();
|
|
}
|
|
}
|
|
$this->inline = $aInline;
|
|
$this->cache_name = $aCachedName;
|
|
|
|
$this->title = new Text();
|
|
$this->title->ParagraphAlign('center');
|
|
$this->title->SetFont(FF_FONT2, FS_BOLD);
|
|
$this->title->SetMargin(3);
|
|
$this->title->SetAlign('center');
|
|
|
|
$this->subtitle = new Text();
|
|
$this->subtitle->ParagraphAlign('center');
|
|
$this->subtitle->SetFont(FF_FONT1, FS_BOLD);
|
|
$this->subtitle->SetMargin(3);
|
|
$this->subtitle->SetAlign('center');
|
|
|
|
$this->subsubtitle = new Text();
|
|
$this->subsubtitle->ParagraphAlign('center');
|
|
$this->subsubtitle->SetFont(FF_FONT1, FS_NORMAL);
|
|
$this->subsubtitle->SetMargin(3);
|
|
$this->subsubtitle->SetAlign('center');
|
|
|
|
$this->footer = new Footer();
|
|
}
|
|
|
|
// Specify background fill color for the combined graph
|
|
public function SetFillColor($aColor)
|
|
{
|
|
$this->iFillColor = $aColor;
|
|
}
|
|
|
|
// Add a frame around the combined graph
|
|
public function SetFrame($aFlg, $aColor='black', $aWeight=1)
|
|
{
|
|
$this->iDoFrame = $aFlg;
|
|
$this->iFrameColor = $aColor;
|
|
$this->iFrameWeight = $aWeight;
|
|
}
|
|
|
|
// Specify a background image blend
|
|
public function SetBackgroundImageMix($aMix)
|
|
{
|
|
$this->background_image_mix = $aMix ;
|
|
}
|
|
|
|
// Specify a background image
|
|
public function SetBackgroundImage($aFileName, $aCenter_aX=null, $aY=null)
|
|
{
|
|
// Second argument can be either a boolean value or
|
|
// a numeric
|
|
$aCenter=true;
|
|
$aX=null;
|
|
|
|
if (is_numeric($aCenter_aX)) {
|
|
$aX=$aCenter_aX;
|
|
}
|
|
|
|
// Get extension to determine image type
|
|
$e = explode('.', $aFileName);
|
|
if (!$e) {
|
|
JpGraphError::RaiseL(12002, $aFileName);
|
|
//('Incorrect file name for MGraph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
|
|
}
|
|
|
|
$valid_formats = array('png', 'jpg', 'gif');
|
|
$aImgFormat = strtolower($e[count($e)-1]);
|
|
if ($aImgFormat == 'jpeg') {
|
|
$aImgFormat = 'jpg';
|
|
} elseif (!in_array($aImgFormat, $valid_formats)) {
|
|
JpGraphError::RaiseL(12003, $aImgFormat, $aFileName);
|
|
//('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName);
|
|
}
|
|
|
|
$this->background_image = $aFileName;
|
|
$this->background_image_center=$aCenter;
|
|
$this->background_image_format=$aImgFormat;
|
|
$this->background_image_x = $aX;
|
|
$this->background_image_y = $aY;
|
|
}
|
|
|
|
public function _strokeBackgroundImage()
|
|
{
|
|
if ($this->background_image == '') {
|
|
return;
|
|
}
|
|
|
|
$bkgimg = Graph::LoadBkgImage('', $this->background_image);
|
|
|
|
// Background width & Heoght
|
|
$bw = imagesx($bkgimg);
|
|
$bh = imagesy($bkgimg);
|
|
|
|
// Canvas width and height
|
|
$cw = imagesx($this->img);
|
|
$ch = imagesy($this->img);
|
|
|
|
if ($this->doshadow) {
|
|
$cw -= $this->shadow_width;
|
|
$ch -= $this->shadow_width;
|
|
}
|
|
|
|
if ($this->background_image_x === null || $this->background_image_y === null) {
|
|
if ($this->background_image_center) {
|
|
// Center original image in the plot area
|
|
$x = round($cw/2-$bw/2);
|
|
$y = round($ch/2-$bh/2);
|
|
} else {
|
|
// Just copy the image from left corner, no resizing
|
|
$x=0;
|
|
$y=0;
|
|
}
|
|
} else {
|
|
$x = $this->background_image_x;
|
|
$y = $this->background_image_y;
|
|
}
|
|
imagecopymerge($this->img, $bkgimg, $x, $y, 0, 0, $bw, $bh, $this->background_image_mix);
|
|
}
|
|
|
|
public function AddMix($aGraph, $x=0, $y=0, $mix=100, $fx=0, $fy=0, $w=0, $h=0)
|
|
{
|
|
$this->_gdImgHandle($aGraph->Stroke(_IMG_HANDLER), $x, $y, $fx=0, $fy=0, $w, $h, $mix);
|
|
}
|
|
|
|
public function Add($aGraph, $x=0, $y=0, $fx=0, $fy=0, $w=0, $h=0)
|
|
{
|
|
$this->_gdImgHandle($aGraph->Stroke(_IMG_HANDLER), $x, $y, $fx=0, $fy=0, $w, $h);
|
|
}
|
|
|
|
public function _gdImgHandle($agdCanvas, $x, $y, $fx=0, $fy=0, $w=0, $h=0, $mix=100)
|
|
{
|
|
if ($w == 0) {
|
|
$w = @imagesx($agdCanvas);
|
|
}
|
|
if ($w === null) {
|
|
JpGraphError::RaiseL(12007);
|
|
//('Argument to MGraph::Add() is not a valid GD image handle.');
|
|
return;
|
|
}
|
|
if ($h == 0) {
|
|
$h = @imagesy($agdCanvas);
|
|
}
|
|
$this->iGraphs[$this->iCnt++] = array($agdCanvas,$x,$y,$fx,$fy,$w,$h,$mix);
|
|
}
|
|
|
|
public function SetMargin($lm, $rm, $tm, $bm)
|
|
{
|
|
$this->lm = $lm;
|
|
$this->rm = $rm;
|
|
$this->tm = $tm;
|
|
$this->bm = $bm;
|
|
}
|
|
|
|
public function SetExpired($aFlg=true)
|
|
{
|
|
$this->expired = $aFlg;
|
|
}
|
|
|
|
public function SetImgFormat($aFormat, $aQuality=75)
|
|
{
|
|
$this->image_format = $aFormat;
|
|
$this->image_quality = $aQuality;
|
|
}
|
|
|
|
// Set the shadow around the whole image
|
|
public function SetShadow($aShowShadow=true, $aShadowWidth=4, $aShadowColor='gray@0.3')
|
|
{
|
|
$this->doshadow = $aShowShadow;
|
|
$this->shadow_color = $aShadowColor;
|
|
$this->shadow_width = $aShadowWidth;
|
|
$this->footer->iBottomMargin += $aShadowWidth;
|
|
$this->footer->iRightMargin += $aShadowWidth;
|
|
}
|
|
|
|
public function StrokeTitle($image, $w, $h)
|
|
{
|
|
// Stroke title
|
|
if ($this->title->t !== '') {
|
|
$margin = 3;
|
|
|
|
$y = $this->title->margin;
|
|
if ($this->title->halign == 'center') {
|
|
$this->title->Center(0, $w, $y);
|
|
} elseif ($this->title->halign == 'left') {
|
|
$this->title->SetPos($this->title->margin+2, $y);
|
|
} elseif ($this->title->halign == 'right') {
|
|
$indent = 0;
|
|
if ($this->doshadow) {
|
|
$indent = $this->shadow_width+2;
|
|
}
|
|
$this->title->SetPos($w-$this->title->margin-$indent, $y, 'right');
|
|
}
|
|
$this->title->Stroke($image);
|
|
|
|
// ... and subtitle
|
|
$y += $this->title->GetTextHeight($image) + $margin + $this->subtitle->margin;
|
|
if ($this->subtitle->halign == 'center') {
|
|
$this->subtitle->Center(0, $w, $y);
|
|
} elseif ($this->subtitle->halign == 'left') {
|
|
$this->subtitle->SetPos($this->subtitle->margin+2, $y);
|
|
} elseif ($this->subtitle->halign == 'right') {
|
|
$indent = 0;
|
|
if ($this->doshadow) {
|
|
$indent = $this->shadow_width+2;
|
|
}
|
|
$this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent, $y, 'right');
|
|
}
|
|
$this->subtitle->Stroke($image);
|
|
|
|
// ... and subsubtitle
|
|
$y += $this->subtitle->GetTextHeight($image) + $margin + $this->subsubtitle->margin;
|
|
if ($this->subsubtitle->halign == 'center') {
|
|
$this->subsubtitle->Center(0, $w, $y);
|
|
} elseif ($this->subsubtitle->halign == 'left') {
|
|
$this->subsubtitle->SetPos($this->subsubtitle->margin+2, $y);
|
|
} elseif ($this->subsubtitle->halign == 'right') {
|
|
$indent = 0;
|
|
if ($this->doshadow) {
|
|
$indent = $this->shadow_width+2;
|
|
}
|
|
$this->subsubtitle->SetPos($w-$this->subsubtitle->margin-$indent, $y, 'right');
|
|
}
|
|
$this->subsubtitle->Stroke($image);
|
|
}
|
|
}
|
|
|
|
public function Stroke($aFileName='')
|
|
{
|
|
// Find out the necessary size for the container image
|
|
$w=0;
|
|
$h=0;
|
|
for ($i=0; $i < $this->iCnt; ++$i) {
|
|
$maxw = $this->iGraphs[$i][1]+$this->iGraphs[$i][5];
|
|
$maxh = $this->iGraphs[$i][2]+$this->iGraphs[$i][6];
|
|
$w = max($w, $maxw);
|
|
$h = max($h, $maxh);
|
|
}
|
|
$w += $this->lm+$this->rm;
|
|
$h += $this->tm+$this->bm;
|
|
|
|
// User specified width,height overrides
|
|
if ($this->iWidth !== null && $this->iWidth !== 0) {
|
|
$w = $this->iWidth;
|
|
}
|
|
if ($this->iHeight!== null && $this->iHeight !== 0) {
|
|
$h = $this->iHeight;
|
|
}
|
|
|
|
if ($this->doshadow) {
|
|
$w += $this->shadow_width;
|
|
$h += $this->shadow_width;
|
|
}
|
|
|
|
$image = new Image($w, $h);
|
|
$image->SetImgFormat($this->image_format, $this->image_quality);
|
|
|
|
if ($this->doshadow) {
|
|
$image->SetColor($this->iFrameColor);
|
|
$image->ShadowRectangle(0, 0, $w-1, $h-1, $this->iFillColor, $this->shadow_width, $this->shadow_color);
|
|
$w -= $this->shadow_width;
|
|
$h -= $this->shadow_width;
|
|
} else {
|
|
$image->SetColor($this->iFillColor);
|
|
$image->FilledRectangle(0, 0, $w-1, $h-1);
|
|
}
|
|
$image->SetExpired($this->expired);
|
|
|
|
$this->img = $image->img;
|
|
$this->_strokeBackgroundImage();
|
|
|
|
if ($this->iDoFrame && ! $this->doshadow) {
|
|
$image->SetColor($this->iFrameColor);
|
|
$image->SetLineWeight($this->iFrameWeight);
|
|
$image->Rectangle(0, 0, $w-1, $h-1);
|
|
}
|
|
|
|
// Copy all sub graphs to the container
|
|
for ($i=0; $i < $this->iCnt; ++$i) {
|
|
$image->CopyMerge(
|
|
$this->iGraphs[$i][0],
|
|
$this->iGraphs[$i][1]+$this->lm,
|
|
$this->iGraphs[$i][2]+$this->tm,
|
|
$this->iGraphs[$i][3],
|
|
$this->iGraphs[$i][4],
|
|
$this->iGraphs[$i][5],
|
|
$this->iGraphs[$i][6],
|
|
-1,
|
|
-1, /* Full from width and height */
|
|
$this->iGraphs[$i][7]
|
|
);
|
|
}
|
|
|
|
$this->StrokeTitle($image, $w, $h);
|
|
$this->footer->Stroke($image);
|
|
|
|
// Output image
|
|
if ($aFileName == _IMG_HANDLER) {
|
|
return $image->img;
|
|
} else {
|
|
//Finally stream the generated picture
|
|
$this->cache = new ImgStreamCache();
|
|
$this->cache->PutAndStream($image, $this->cache_name, $this->inline, $aFileName);
|
|
}
|
|
}
|
|
}
|
|
|
|
// EOF
|