/trunk/bibliotheque/artichow/inc/Mark.class.php |
---|
New file |
0,0 → 1,490 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Draw marks |
* |
* @package Artichow |
*/ |
class awMark { |
/** |
* Circle mark |
* |
* @var int |
*/ |
const CIRCLE = 1; |
/** |
* Square mark |
* |
* @var int |
*/ |
const SQUARE = 2; |
/** |
* Triangle mark |
* |
* @var int |
*/ |
const TRIANGLE = 3; |
/** |
* Inverted triangle mark |
* |
* @var int |
*/ |
const INVERTED_TRIANGLE = 4; |
/** |
* Rhombus mark |
* |
* @var int |
*/ |
const RHOMBUS = 5; |
/** |
* Cross (X) mark |
* |
* @var int |
*/ |
const CROSS = 6; |
/** |
* Plus mark |
* |
* @var int |
*/ |
const PLUS = 7; |
/** |
* Image mark |
* |
* @var int |
*/ |
const IMAGE = 8; |
/** |
* Star mark |
* |
* @var int |
*/ |
const STAR = 9; |
/** |
* Paperclip mark |
* |
* @var int |
*/ |
const PAPERCLIP = 10; |
/** |
* Book mark |
* |
* @var int |
*/ |
const BOOK = 11; |
/** |
* Must marks be hidden ? |
* |
* @var bool |
*/ |
protected $hide; |
/** |
* Mark type |
* |
* @var int |
*/ |
protected $type; |
/** |
* Mark size |
* |
* @var int |
*/ |
protected $size = 8; |
/** |
* Fill mark |
* |
* @var Color, Gradient |
*/ |
protected $fill; |
/** |
* Mark image |
* |
* @var Image |
*/ |
protected $image; |
/** |
* To draw marks |
* |
* @var Driver |
*/ |
protected $driver; |
/** |
* Move position from this vector |
* |
* @var Point |
*/ |
protected $move; |
/** |
* Marks border |
* |
* @var Border |
*/ |
public $border; |
/** |
* Build the mark |
*/ |
public function __construct() { |
$this->fill = new awColor(255, 0, 0, 0); |
$this->border = new awBorder; |
$this->border->hide(); |
$this->move = new awPoint(0, 0); |
} |
/** |
* Change mark position |
* |
* @param int $x Add this interval to X coord |
* @param int $y Add this interval to Y coord |
*/ |
public function move($x, $y) { |
$this->move = $this->move->move($x, $y); |
} |
/** |
* Hide marks ? |
* |
* @param bool $hide TRUE to hide marks, FALSE otherwise |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show marks ? |
* |
* @param bool $show |
*/ |
public function show($show = TRUE) { |
$this->hide = (bool)!$show; |
} |
/** |
* Change mark type |
* |
* @param int $size Size in pixels |
*/ |
public function setSize($size) { |
$this->size = (int)$size; |
} |
/** |
* Change mark type |
* |
* @param int $type New mark type |
* @param int $size Mark size (can be NULL) |
*/ |
public function setType($type, $size = NULL) { |
$this->type = (int)$type; |
if($size !== NULL) { |
$this->setSize($size); |
} |
} |
/** |
* Fill the mark with a color or a gradient |
* |
* @param mixed $fill A color or a gradient |
*/ |
public function setFill($fill) { |
if($fill instanceof awColor or $fill instanceof awGradient) { |
$this->fill = $fill; |
} |
} |
/** |
* Set an image |
* Only for awMark::IMAGE type. |
* |
* @param Image An image |
*/ |
public function setImage(awImage $image) { |
$this->image = $image; |
} |
/** |
* Draw the mark |
* |
* @param awDriver $driver |
* @param awPoint $point Mark center |
*/ |
public function draw(awDriver $driver, awPoint $point) { |
// Hide marks ? |
if($this->hide) { |
return; |
} |
// Check if we can print marks |
if($this->type !== NULL) { |
$this->driver = $driver; |
$realPoint = $this->move->move($point->x, $point->y); |
switch($this->type) { |
case awMark::CIRCLE : |
$this->drawCircle($realPoint); |
break; |
case awMark::SQUARE : |
$this->drawSquare($realPoint); |
break; |
case awMark::TRIANGLE : |
$this->drawTriangle($realPoint); |
break; |
case awMark::INVERTED_TRIANGLE : |
$this->drawTriangle($realPoint, TRUE); |
break; |
case awMark::RHOMBUS : |
$this->drawRhombus($realPoint); |
break; |
case awMark::CROSS : |
$this->drawCross($realPoint); |
break; |
case awMark::PLUS : |
$this->drawCross($realPoint, TRUE); |
break; |
case awMark::IMAGE : |
$this->drawImage($realPoint); |
break; |
case awMark::STAR : |
$this->changeType('star'); |
$this->draw($driver, $point); |
break; |
case awMark::PAPERCLIP : |
$this->changeType('paperclip'); |
$this->draw($driver, $point); |
break; |
case awMark::BOOK : |
$this->changeType('book'); |
$this->draw($driver, $point); |
break; |
} |
} |
} |
protected function changeType($image) { |
$this->setType(awMARK::IMAGE); |
$this->setImage(new awFileImage(ARTICHOW_IMAGE.DIRECTORY_SEPARATOR.$image.'.png')); |
} |
protected function drawCircle(awPoint $point) { |
$this->driver->filledEllipse( |
$this->fill, |
$point, |
$this->size, $this->size |
); |
$this->border->ellipse( |
$this->driver, |
$point, |
$this->size, $this->size |
); |
} |
protected function drawSquare(awPoint $point) { |
list($x, $y) = $point->getLocation(); |
$x1 = (int)($x - $this->size / 2); |
$x2 = $x1 + $this->size; |
$y1 = (int)($y - $this->size / 2); |
$y2 = $y1 + $this->size; |
$this->border->rectangle($this->driver, new awPoint($x1, $y1), new awPoint($x2, $y2)); |
$size = $this->border->visible() ? 1 : 0; |
$this->driver->filledRectangle( |
$this->fill, |
new awLine( |
new awPoint($x1 + $size, $y1 + $size), |
new awPoint($x2 - $size, $y2 - $size) |
) |
); |
} |
protected function drawTriangle(awPoint $point, $inverted = FALSE) { |
list($x, $y) = $point->getLocation(); |
$size = $this->size; |
$triangle = new awPolygon; |
// Set default style and thickness |
$triangle->setStyle(awPolygon::SOLID); |
$triangle->setThickness(1); |
if($inverted === TRUE) { |
// Bottom of the triangle |
$triangle->append(new awPoint($x, $y + $size / sqrt(3))); |
// Upper left corner |
$triangle->append(new awPoint($x - $size / 2, $y - $size / (2 * sqrt(3)))); |
// Upper right corner |
$triangle->append(new awPoint($x + $size / 2, $y - $size / (2 * sqrt(3)))); |
} else { |
// Top of the triangle |
$triangle->append(new awPoint($x, $y - $size / sqrt(3))); |
// Lower left corner |
$triangle->append(new awPoint($x - $size / 2, $y + $size / (2 * sqrt(3)))); |
// Lower right corner |
$triangle->append(new awPoint($x + $size / 2, $y + $size / (2 * sqrt(3)))); |
} |
$this->driver->filledPolygon($this->fill, $triangle); |
if($this->border->visible()) { |
$this->border->polygon($this->driver, $triangle); |
} |
} |
protected function drawRhombus(awPoint $point) { |
list($x, $y) = $point->getLocation(); |
$rhombus = new awPolygon; |
// Set default style and thickness |
$rhombus->setStyle(awPolygon::SOLID); |
$rhombus->setThickness(1); |
// Top of the rhombus |
$rhombus->append(new awPoint($x, $y - $this->size / 2)); |
// Right of the rhombus |
$rhombus->append(new awPoint($x + $this->size / 2, $y)); |
// Bottom of the rhombus |
$rhombus->append(new awPoint($x, $y + $this->size / 2)); |
// Left of the rhombus |
$rhombus->append(new awPoint($x - $this->size / 2, $y)); |
$this->driver->filledPolygon($this->fill, $rhombus); |
if($this->border->visible()) { |
$this->border->polygon($this->driver, $rhombus); |
} |
} |
protected function drawCross(awPoint $point, $upright = FALSE) { |
list($x, $y) = $point->getLocation(); |
if($upright === TRUE) { |
$x11 = (int)($x); |
$y11 = (int)($y - $this->size / 2); |
$x12 = (int)($x); |
$y12 = (int)($y + $this->size / 2); |
$y21 = (int)($y); |
$y22 = (int)($y); |
} else { |
$x11 = (int)($x - $this->size / 2); |
$y11 = (int)($y + $this->size / 2); |
$x12 = (int)($x + $this->size / 2); |
$y12 = (int)($y - $this->size / 2); |
$y21 = (int)($y - $this->size / 2); |
$y22 = (int)($y + $this->size / 2); |
} |
$x21 = (int)($x - $this->size / 2); |
$x22 = (int)($x + $this->size / 2); |
$this->driver->line( |
$this->fill, |
new awLine( |
new awPoint($x11, $y11), |
new awPoint($x12, $y12) |
) |
); |
$this->driver->line( |
$this->fill, |
new awLine( |
new awPoint($x21, $y21), |
new awPoint($x22, $y22) |
) |
); |
} |
protected function drawImage(awPoint $point) { |
if($this->image instanceof awImage) { |
$width = $this->image->width; |
$height = $this->image->height; |
list($x, $y) = $point->getLocation(); |
$x1 = (int)($x - $width / 2); |
$x2 = $x1 + $width; |
$y1 = (int)($y - $width / 2); |
$y2 = $y1 + $height; |
$this->border->rectangle($this->driver, new awPoint($x1 - 1, $y1 - 1), new awPoint($x2 + 1, $y2 + 1)); |
$this->driver->copyImage($this->image, new awPoint($x1, $y1), new awPoint($x2, $y2)); |
} |
} |
} |
registerClass('Mark'); |
?> |
/trunk/bibliotheque/artichow/inc/Tick.class.php |
---|
New file |
0,0 → 1,344 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Handle ticks |
* |
* @package Artichow |
*/ |
class awTick { |
/** |
* Ticks style |
* |
* @var int |
*/ |
protected $style = awTick::IN; |
/** |
* Ticks size |
* |
* @var int |
*/ |
protected $size; |
/** |
* Ticks color |
* |
* @var Color |
*/ |
protected $color; |
/** |
* Ticks number |
* |
* @var int |
*/ |
protected $number; |
/** |
* Ticks number by other tick |
* |
* @var array |
*/ |
protected $numberByTick; |
/** |
* Ticks interval |
* |
* @var int |
*/ |
protected $interval = 1; |
/** |
* Hide ticks |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Hide first tick |
* |
* @var bool |
*/ |
protected $hideFirst = FALSE; |
/** |
* Hide last tick |
* |
* @var bool |
*/ |
protected $hideLast = FALSE; |
/** |
* In mode |
* |
* @param int |
*/ |
const IN = 0; |
/** |
* Out mode |
* |
* @param int |
*/ |
const OUT = 1; |
/** |
* In and out mode |
* |
* @param int |
*/ |
const IN_OUT = 2; |
/** |
* Build the ticks |
* |
* @param int $number Number of ticks |
* @param int $size Ticks size |
*/ |
public function __construct($number, $size) { |
$this->setSize($size); |
$this->setNumber($number); |
$this->setColor(new awBlack); |
$this->style = awTick::IN; |
} |
/** |
* Change ticks style |
* |
* @param int $style |
*/ |
public function setStyle($style) { |
$this->style = (int)$style; |
} |
/** |
* Get ticks style |
* |
* @return int |
*/ |
public function getStyle() { |
return $this->style; |
} |
/** |
* Change ticks color |
* |
* @param awColor $color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
} |
/** |
* Change ticks size |
* |
* @param int $size |
*/ |
public function setSize($size) { |
$this->size = (int)$size; |
} |
/** |
* Change interval of ticks |
* |
* @param int $interval |
*/ |
public function setInterval($interval) { |
$this->interval = (int)$interval; |
} |
/** |
* Get interval between each tick |
* |
* @return int |
*/ |
public function getInterval() { |
return $this->interval; |
} |
/** |
* Change number of ticks |
* |
* @param int $number |
*/ |
public function setNumber($number) { |
$this->number = (int)$number; |
} |
/** |
* Get number of ticks |
* |
* @return int |
*/ |
public function getNumber() { |
return $this->number; |
} |
/** |
* Change number of ticks relative to others ticks |
* |
* @param awTick $tick Ticks reference |
* @param int $number Number of ticks |
*/ |
public function setNumberByTick(awTick $tick, $number) { |
$this->numberByTick = array($tick, (int)$number); |
} |
/** |
* Hide ticks |
* |
* @param bool $hide |
*/ |
public function hide($hide) { |
$this->hide = (bool)$hide; |
} |
/** |
* Hide first tick |
* |
* @param bool $hide |
*/ |
public function hideFirst($hide) { |
$this->hideFirst = (bool)$hide; |
} |
/** |
* Hide last tick |
* |
* @param bool $hide |
*/ |
public function hideLast($hide) { |
$this->hideLast = (bool)$hide; |
} |
/** |
* Draw ticks on a vector |
* |
* @param awDriver $driver A driver |
* @param awVector $vector A vector |
*/ |
public function draw(awDriver $driver, awVector $vector) { |
if($this->numberByTick !== NULL) { |
list($tick, $number) = $this->numberByTick; |
$this->number = 1 + ($tick->getNumber() - 1) * ($number + 1); |
$this->interval = $tick->getInterval(); |
} |
if($this->number < 2 or $this->hide) { |
return; |
} |
$angle = $vector->getAngle(); |
// echo "INIT:".$angle."<br>"; |
switch($this->style) { |
case awTick::IN : |
$this->drawTicks($driver, $vector, NULL, $angle + M_PI / 2); |
break; |
case awTick::OUT : |
$this->drawTicks($driver, $vector, $angle + 3 * M_PI / 2, NULL); |
break; |
default : |
$this->drawTicks($driver, $vector, $angle + M_PI / 2, $angle + 3 * M_PI / 2); |
break; |
} |
} |
protected function drawTicks(awDriver $driver, awVector $vector, $from, $to) { |
// Draw last tick |
if($this->hideLast === FALSE) { |
//echo '<b>'; |
if(($this->number - 1) % $this->interval === 0) { |
$this->drawTick($driver, $vector->p2, $from, $to); |
} |
//echo '</b>'; |
} |
$number = $this->number - 1; |
$size = $vector->getSize(); |
// Get tick increment in pixels |
$inc = $size / $number; |
// Check if we must hide the first tick |
$start = $this->hideFirst ? $inc : 0; |
$stop = $inc * $number; |
$position = 0; |
for($i = $start; round($i, 6) < $stop; $i += $inc) { |
if($position % $this->interval === 0) { |
$p = $vector->p1->move( |
round($i * cos($vector->getAngle()), 6), |
round($i * sin($vector->getAngle() * -1), 6) |
); |
$this->drawTick($driver, $p, $from, $to); |
} |
$position++; |
} |
//echo '<br><br>'; |
} |
protected function drawTick(awDriver $driver, awPoint $p, $from, $to) { |
// echo $this->size.':'.$angle.'|<b>'.cos($angle).'</b>/'; |
// The round avoid some errors in the calcul |
// For example, 12.00000008575245 becomes 12 |
$p1 = $p; |
$p2 = $p; |
if($from !== NULL) { |
$p1 = $p1->move( |
round($this->size * cos($from), 6), |
round($this->size * sin($from) * -1, 6) |
); |
} |
if($to !== NULL) { |
$p2 = $p2->move( |
round($this->size * cos($to), 6), |
round($this->size * sin($to) * -1, 6) |
); |
} |
//echo $p1->x.':'.$p2->x.'('.$p1->y.':'.$p2->y.')'.'/'; |
$vector = new awVector( |
$p1, $p2 |
); |
$driver->line( |
$this->color, |
$vector |
); |
} |
} |
registerClass('Tick'); |
?> |
/trunk/bibliotheque/artichow/inc/Driver.class.php |
---|
New file |
0,0 → 1,725 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Draw your objects |
* |
* @package Artichow |
*/ |
abstract class awDriver { |
/** |
* Image width |
* |
* @var int |
*/ |
public $imageWidth; |
/** |
* Image height |
* |
* @var int |
*/ |
public $imageHeight; |
/** |
* Driver X position |
* |
* @var int |
*/ |
public $x; |
/** |
* Driver Y position |
* |
* @var int |
*/ |
public $y; |
/** |
* Use anti-aliasing ? |
* |
* @var bool |
*/ |
protected $antiAliasing = FALSE; |
/** |
* The FontDriver object that will be used to draw text |
* with PHP fonts. |
* |
* @var awPHPFontDriver |
*/ |
protected $phpFontDriver; |
/** |
* The FontDriver object that will be used to draw text |
* with TTF or FDB fonts. |
* |
* @var awFileFontDriver |
*/ |
protected $fileFontDriver; |
/** |
* A string representing the type of the driver |
* |
* @var string |
*/ |
protected $driverString; |
private $w; |
private $h; |
public function __construct() { |
$this->phpFontDriver = new awPHPFontDriver(); |
$this->fileFontDriver = new awFileFontDriver(); |
} |
/** |
* Initialize the driver for a particular awImage object |
* |
* @param awImage $image |
*/ |
abstract public function init(awImage $image); |
/** |
* Initialize the Driver for a particular FileImage object |
* |
* @param awFileImage $fileImage The FileImage object to work on |
* @param string $file Image filename |
*/ |
abstract public function initFromFile(awFileImage $fileImage, $file); |
/** |
* Change the image size |
* |
* @param int $width Image width |
* @param int $height Image height |
*/ |
abstract public function setImageSize($width, $height); |
/** |
* Inform the driver of the position of your image |
* |
* @param float $x Position on X axis of the center of the component |
* @param float $y Position on Y axis of the center of the component |
*/ |
abstract public function setPosition($x, $y); |
/** |
* Inform the driver of the position of your image |
* This method need absolutes values |
* |
* @param int $x Left-top corner X position |
* @param int $y Left-top corner Y position |
*/ |
abstract public function setAbsPosition($x, $y); |
/** |
* Move the position of the image |
* |
* @param int $x Add this value to X axis |
* @param int $y Add this value to Y axis |
*/ |
abstract public function movePosition($x, $y); |
/** |
* Inform the driver of the size of your image |
* Height and width must be between 0 and 1. |
* |
* @param int $w Image width |
* @param int $h Image height |
* @return array Absolute width and height of the image |
*/ |
abstract public function setSize($w, $h); |
/** |
* Inform the driver of the size of your image |
* You can set absolute size with this method. |
* |
* @param int $w Image width |
* @param int $h Image height |
*/ |
abstract public function setAbsSize($w, $h); |
/** |
* Get the size of the component handled by the driver |
* |
* @return array Absolute width and height of the component |
*/ |
abstract public function getSize(); |
/** |
* Turn antialiasing on or off |
* |
* @var bool $bool |
*/ |
abstract public function setAntiAliasing($bool); |
/** |
* When passed a Color object, returns the corresponding |
* color identifier (driver dependant). |
* |
* @param awColor $color A Color object |
* @return int $rgb A color identifier representing the color composed of the given RGB components |
*/ |
abstract public function getColor(awColor $color); |
/** |
* Draw an image here |
* |
* @param awImage $image Image |
* @param int $p1 Image top-left point |
* @param int $p2 Image bottom-right point |
*/ |
abstract public function copyImage(awImage $image, awPoint $p1, awPoint $p2); |
/** |
* Draw an image here |
* |
* @param awImage $image Image |
* @param int $d1 Destination top-left position |
* @param int $d2 Destination bottom-right position |
* @param int $s1 Source top-left position |
* @param int $s2 Source bottom-right position |
* @param bool $resample Resample image ? (default to TRUE) |
*/ |
abstract public function copyResizeImage(awImage $image, awPoint $d1, awPoint $d2, awPoint $s1, awPoint $s2, $resample = TRUE); |
/** |
* Draw a string |
* |
* @var awText $text Text to print |
* @param awPoint $point Draw the text at this point |
* @param int $width Text max width |
*/ |
abstract public function string(awText $text, awPoint $point, $width = NULL); |
/** |
* Draw a pixel |
* |
* @param awColor $color Pixel color |
* @param awPoint $p |
*/ |
abstract public function point(awColor $color, awPoint $p); |
/** |
* Draw a colored line |
* |
* @param awColor $color Line color |
* @param awLine $line |
* @param int $thickness Line tickness |
*/ |
abstract public function line(awColor $color, awLine $line); |
/** |
* Draw a color arc |
* @param awColor $color Arc color |
* @param awPoint $center Point center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
* @param int $from Start angle |
* @param int $to End angle |
*/ |
abstract public function arc(awColor $color, awPoint $center, $width, $height, $from, $to); |
/** |
* Draw an arc with a background color |
* |
* @param awColor $color Arc background color |
* @param awPoint $center Point center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
* @param int $from Start angle |
* @param int $to End angle |
*/ |
abstract public function filledArc(awColor $color, awPoint $center, $width, $height, $from, $to); |
/** |
* Draw a colored ellipse |
* |
* @param awColor $color Ellipse color |
* @param awPoint $center Ellipse center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
*/ |
abstract public function ellipse(awColor $color, awPoint $center, $width, $height); |
/** |
* Draw an ellipse with a background |
* |
* @param mixed $background Background (can be a color or a gradient) |
* @param awPoint $center Ellipse center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
*/ |
abstract public function filledEllipse($background, awPoint $center, $width, $height); |
/** |
* Draw a colored rectangle |
* |
* @param awColor $color Rectangle color |
* @param awLine $line Rectangle diagonale |
* @param awPoint $p2 |
*/ |
abstract public function rectangle(awColor $color, awLine $line); |
/** |
* Draw a rectangle with a background |
* |
* @param mixed $background Background (can be a color or a gradient) |
* @param awLine $line Rectangle diagonale |
*/ |
abstract public function filledRectangle($background, awLine $line); |
/** |
* Draw a polygon |
* |
* @param awColor $color Polygon color |
* @param Polygon A polygon |
*/ |
abstract public function polygon(awColor $color, awPolygon $polygon); |
/** |
* Draw a polygon with a background |
* |
* @param mixed $background Background (can be a color or a gradient) |
* @param Polygon A polygon |
*/ |
abstract public function filledPolygon($background, awPolygon $polygon); |
/** |
* Sends the image, as well as the correct HTTP headers, to the browser |
* |
* @param awImage $image The Image object to send |
*/ |
abstract public function send(awImage $image); |
/** |
* Get the image as binary data |
* |
* @param awImage $image |
*/ |
abstract public function get(awImage $image); |
/** |
* Return the width of some text |
* |
* @param awText $text |
*/ |
abstract public function getTextWidth(awText $text); |
/** |
* Return the height of some text |
* |
* @param awText $text |
*/ |
abstract public function getTextHeight(awText $text); |
/** |
* Return the string representing the type of driver |
* |
* @return string |
*/ |
public function getDriverString() { |
return $this->driverString; |
} |
/** |
* Returns whether or not the driver is compatible with the given font type |
* |
* @param awFont $font |
* @return bool |
*/ |
abstract protected function isCompatibleWithFont(awFont $font); |
// abstract private function drawImage(awImage $image, $return = FALSE, $header = TRUE); |
} |
registerClass('Driver', TRUE); |
/** |
* Abstract class for font drivers. |
* Those are used to do all the grunt work on fonts. |
* |
* @package Artichow |
*/ |
abstract class awFontDriver { |
public function __construct() { |
} |
/** |
* Draw the actual text. |
* |
* @param awDriver $driver The Driver object to draw upon |
* @param awText $text The Text object |
* @param awPoint $point Where to draw the text |
* @param float $width The width of the area containing the text |
*/ |
abstract public function string(awDriver $driver, awText $text, awPoint $point, $width = NULL); |
/** |
* Calculate the width of a given Text. |
* |
* @param awText $text The Text object |
* @param awDriver $driver The awDriver object used to draw the graph |
*/ |
abstract public function getTextWidth(awText $text, awDriver $driver); |
/** |
* Calculate the height of a given Text. |
* |
* @param awText $text The Text object |
* @param awDriver $driver The awDriver object used to draw the graph |
*/ |
abstract public function getTextHeight(awText $text, awDriver $driver); |
} |
registerClass('FontDriver', TRUE); |
/** |
* Class to handle calculations on PHPFont objects |
* |
* @package Artichow |
*/ |
class awPHPFontDriver extends awFontDriver { |
public function __construct() { |
parent::__construct(); |
} |
public function string(awDriver $driver, awText $text, awPoint $point, $width = NULL) { |
switch ($driver->getDriverString()) { |
case 'gd': |
$this->gdString($driver, $text, $point, $width); |
break; |
default: |
awImage::drawError('Class PHPFontDriver: Incompatibility between driver and font - You should never see this error message: have you called awDriver::isCompatibleWithFont() properly?'); |
break; |
} |
} |
/** |
* Draw a string onto a GDDriver object |
* |
* @param awGDDriver $driver The GDDriver to draw the text upon |
* @param awText $text The awText object containing the string to draw |
* @param awPoint $point Where to draw the text |
* @param float $width The width of the text |
*/ |
private function gdString(awGDDriver $driver, awText $text, awPoint $point, $width = NULL) { |
$angle = $text->getAngle(); |
if($angle !== 90 and $angle !== 0) { |
awImage::drawError("Class PHPFontDriver: You can only use 0° and 90° angles."); |
} |
if($angle === 90) { |
$function = 'imagestringup'; |
$addAngle = $this->getGDTextHeight($text); |
} else { |
$function = 'imagestring'; |
$addAngle = 0; |
} |
$color = $text->getColor(); |
$rgb = $driver->getColor($color); |
$textString = $text->getText(); |
$textString = str_replace("\r", "", $textString); |
$textHeight = $this->getGDTextHeight($text); |
// Split text if needed |
if($width !== NULL) { |
$characters = floor($width / ($this->getGDTextWidth($text) / strlen($textString))); |
if($characters > 0) { |
$textString = wordwrap($textString, $characters, "\n", TRUE); |
} |
} |
$font = $text->getFont(); |
$lines = explode("\n", $textString); |
foreach($lines as $i => $line) { |
// Line position handling |
if($angle === 90) { |
$addX = $i * $textHeight; |
$addY = 0; |
} else { |
$addX = 0; |
$addY = $i * $textHeight; |
} |
$function( |
$driver->resource, |
$font->font, |
$driver->x + $point->x + $addX, |
$driver->y + $point->y + $addY + $addAngle, |
$line, |
$rgb |
); |
} |
} |
public function getTextWidth(awText $text, awDriver $driver) { |
switch ($driver->getDriverString()) { |
case 'gd': |
return $this->getGDTextWidth($text); |
default: |
awImage::drawError('Class PHPFontDriver: Cannot get text width - incompatibility between driver and font'); |
break; |
} |
} |
public function getTextHeight(awText $text, awDriver $driver) { |
switch ($driver->getDriverString()) { |
case 'gd': |
return $this->getGDTextHeight($text); |
default: |
awImage::drawError('Class PHPFontDriver: Cannot get text height - incompatibility between driver and font'); |
break; |
} |
} |
/** |
* Return the width of a text for a GDDriver |
* |
* @param awText $text |
* @return int $fontWidth |
*/ |
private function getGDTextWidth(awText $text) { |
$font = $text->getFont(); |
if($text->getAngle() === 90) { |
$text->setAngle(45); |
return $this->getGDTextHeight($text); |
} else if($text->getAngle() === 45) { |
$text->setAngle(90); |
} |
$fontWidth = imagefontwidth($font->font); |
if($fontWidth === FALSE) { |
awImage::drawError("Class PHPFontDriver: Unable to get font size."); |
} |
return (int)$fontWidth * strlen($text->getText()); |
} |
/** |
* Return the height of a text for a GDDriver |
* |
* @param awText $text |
* @return int $fontHeight |
*/ |
private function getGDTextHeight(awText $text) { |
$font = $text->getFont(); |
if($text->getAngle() === 90) { |
$text->setAngle(45); |
return $this->getGDTextWidth($text); |
} else if($text->getAngle() === 45) { |
$text->setAngle(90); |
} |
$fontHeight = imagefontheight($font->font); |
if($fontHeight === FALSE) { |
awImage::drawError("Class PHPFontDriver: Unable to get font size."); |
} |
return (int)$fontHeight; |
} |
} |
registerClass('PHPFontDriver'); |
/** |
* Class to handle calculations on FileFont objects |
* |
* @package Artichow |
*/ |
class awFileFontDriver extends awFontDriver { |
public function __construct() { |
parent::__construct(); |
} |
public function string(awDriver $driver, awText $text, awPoint $point, $width = NULL) { |
switch ($driver->getDriverString()) { |
case 'gd': |
$this->gdString($driver, $text, $point, $width); |
break; |
default: |
awImage::drawError('Class fileFontDriver: Incompatibility between driver and font - You should never see this error message: have you called awDriver::isCompatibleWithFont() properly?'); |
break; |
} |
} |
/** |
* Draw an awFileFont object on a GD ressource |
* |
* @param awGDDriver $driver The awGDDriver object containing the ressource to draw upon |
* @param awText $text The awText object containing the string to draw |
* @param awPoint $point Where to draw the string from |
* @param float $width The width of the area containing the text |
*/ |
private function gdString(awGDDriver $driver, awText $text, awPoint $point, $width = NULL) { |
// Make easier font positionment |
$text->setText($text->getText()." "); |
$font = $text->getFont(); |
if($font instanceof awTTFFont === FALSE and $font->getExtension() === NULL) { |
$font->setExtension('ttf'); |
} |
$filePath = $font->getName().'.'.$font->getExtension(); |
$box = imagettfbbox($font->getSize(), $text->getAngle(), $filePath, $text->getText()); |
$textHeight = - $box[5]; |
$box = imagettfbbox($font->getSize(), 90, $filePath, $text->getText()); |
$textWidth = abs($box[6] - $box[2]); |
// Restore old text |
$text->setText(substr($text->getText(), 0, strlen($text->getText()) - 1)); |
$textString = $text->getText(); |
// Split text if needed |
if($width !== NULL) { |
$characters = floor($width / $this->getGDAverageWidth($font)); |
$textString = wordwrap($textString, $characters, "\n", TRUE); |
} |
$color = $text->getColor(); |
$rgb = $driver->getColor($color); |
imagettftext( |
$driver->resource, |
$font->getSize(), |
$text->getAngle(), |
$driver->x + $point->x + $textWidth * sin($text->getAngle() / 180 * M_PI), |
$driver->y + $point->y + $textHeight, |
$rgb, |
$filePath, |
$textString |
); |
} |
public function getTextWidth(awText $text, awDriver $driver) { |
switch ($driver->getDriverString()) { |
case 'gd': |
return $this->getGDTextWidth($text); |
default: |
awImage::drawError('Class FileFontDriver: Cannot get text width - incompatibility between driver and font'); |
break; |
} |
} |
public function getTextHeight(awText $text, awDriver $driver) { |
switch ($driver->getDriverString()) { |
case 'gd': |
return $this->getGDTextHeight($text); |
default: |
awImage::drawError('Class FileFontDriver: Cannot get text height - incompatibility between driver and font'); |
break; |
} |
} |
private function getGDTextWidth(awText $text) { |
$font = $text->getFont(); |
if($font->getExtension() === NULL) { |
$font->setExtension('ttf'); |
} |
$filePath = $font->getName().'.'.$font->getExtension(); |
$box = imagettfbbox($font->getSize(), $text->getAngle(), $filePath, $text->getText()); |
if($box === FALSE) { |
awImage::drawError("Class FileFontDriver: Unable to get font width (GD)."); |
} |
list(, , $x2, , , , $x1, ) = $box; |
return abs($x2 - $x1); |
} |
private function getGDTextHeight(awText $text) { |
$font = $text->getFont(); |
if($font->getExtension() === NULL) { |
$font->setExtension('ttf'); |
} |
$filePath = $font->getName().'.'.$font->getExtension(); |
$box = imagettfbbox($font->getSize(), $text->getAngle(), $filePath, $text->getText()); |
if($box === FALSE) { |
awImage::drawError("Class FileFontDriver: Unable to get font height (GD)."); |
} |
list(, , , $y2, , , , $y1) = $box; |
return abs($y2 - $y1); |
} |
private function getGDAverageWidth(awFileFont $font) { |
$text = "azertyuiopqsdfghjklmmmmmmmwxcvbbbn,;:!?."; |
$box = imagettfbbox($font->getSize(), 0, $font->getName().'.'.$font->getExtension(), $text); |
if($box === FALSE) { |
awImage::drawError("Class FileFontDriver: Unable to get font average width."); |
} |
list(, , $x2, $y2, , , $x1, $y1) = $box; |
return abs($x2 - $x1) / strlen($text); |
} |
} |
registerClass('FileFontDriver'); |
// Include ARTICHOW_DRIVER by default to preserve backward compatibility. |
require_once dirname(__FILE__).'/drivers/'.ARTICHOW_DRIVER.'.class.php'; |
?> |
/trunk/bibliotheque/artichow/inc/Gradient.class.php |
---|
New file |
0,0 → 1,135 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Create your gradients |
* |
* @package Artichow |
*/ |
abstract class awGradient { |
/** |
* From color |
* |
* @var Color |
*/ |
public $from; |
/** |
* To color |
* |
* @var Color |
*/ |
public $to; |
/** |
* Build the gradient |
* |
* @param awColor $from From color |
* @param awColor $to To color |
*/ |
public function __construct(awColor $from, awColor $to) { |
$this->from = $from; |
$this->to = $to; |
} |
} |
registerClass('Gradient', TRUE); |
/** |
* Create a linear gradient |
* |
* @package Artichow |
*/ |
class awLinearGradient extends awGradient { |
/** |
* Gradient angle |
* |
* @var int |
*/ |
public $angle; |
/** |
* Build the linear gradient |
* |
* @param awColor $from From color |
* @param awColor $to To color |
* @param int $angle Gradient angle |
*/ |
public function __construct($from, $to, $angle) { |
parent::__construct( |
$from, $to |
); |
$this->angle = (int)$angle; |
} |
} |
registerClass('LinearGradient'); |
/** |
* Create a bilinear gradient |
* |
* @package Artichow |
*/ |
class awBilinearGradient extends awLinearGradient { |
/** |
* Gradient center |
* |
* @var float Center between 0 and 1 |
*/ |
public $center; |
/** |
* Build the bilinear gradient |
* |
* @param awColor $from From color |
* @param awColor $to To color |
* @param int $angle Gradient angle |
* @param int $center Gradient center |
*/ |
public function __construct($from, $to, $angle, $center = 0.5) { |
parent::__construct( |
$from, $to, $angle |
); |
$this->center = (float)$center; |
} |
} |
registerClass('BilinearGradient'); |
/** |
* Create a radial gradient |
* |
* @package Artichow |
*/ |
class awRadialGradient extends awGradient { |
} |
registerClass('RadialGradient'); |
?> |
/trunk/bibliotheque/artichow/inc/Legend.class.php |
---|
New file |
0,0 → 1,710 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Some legends |
* |
* @package Artichow |
*/ |
class awLegend implements awPositionable { |
/** |
* Legends added |
* |
* @var array |
*/ |
protected $legends = array(); |
/** |
* The current component |
* |
* @var Component |
*/ |
protected $component; |
/** |
* Background color or gradient |
* |
* @var Color, Gradient |
*/ |
protected $background; |
/** |
* Text color |
* |
* @var Color |
*/ |
protected $textColor; |
/** |
* Text font |
* |
* @var Font |
*/ |
protected $textFont; |
/** |
* Text margin |
* |
* @var Side |
*/ |
protected $textMargin; |
/** |
* Number of columns |
* |
* @var int |
*/ |
protected $columns = NULL; |
/** |
* Number of rows |
* |
* @var int |
*/ |
protected $rows = NULL; |
/** |
* Legend position |
* |
* @var Point |
*/ |
protected $position; |
/** |
* Hide legend ? |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Space between each legend |
* |
* @var int |
*/ |
protected $space = 4; |
/** |
* Horizontal alignment |
* |
* @var int |
*/ |
protected $hAlign; |
/** |
* Vertical alignment |
* |
* @var int |
*/ |
protected $vAlign; |
/** |
* Margin |
* |
* @var array Array for left, right, top and bottom margins |
*/ |
private $margin; |
/** |
* Legend shadow |
* |
* @var Shadow |
*/ |
public $shadow; |
/** |
* Legend border |
* |
* @var Border |
*/ |
public $border; |
/** |
* Line legend |
* |
* @var int |
*/ |
const LINE = 1; |
/** |
* Color/Gradient background legend |
* |
* @var int |
*/ |
const BACKGROUND = 2; |
/** |
* Use marks and line as legend |
* |
* @var int |
*/ |
const MARK = 3; |
/** |
* Use marks as legend |
* |
* @var int |
*/ |
const MARKONLY = 4; |
/** |
* Right side model |
* |
* @var int |
*/ |
const MODEL_RIGHT = 1; |
/** |
* Bottom side model |
* |
* @var int |
*/ |
const MODEL_BOTTOM = 2; |
/** |
* Build the legend |
* |
* @param int $model Legend model |
*/ |
public function __construct($model = awLegend::MODEL_RIGHT) { |
$this->shadow = new awShadow(awShadow::LEFT_BOTTOM); |
$this->border = new awBorder; |
$this->textMargin = new awSide(4); |
$this->setModel($model); |
} |
/** |
* Set a predefined model for the legend |
* |
* @param int $model |
*/ |
public function setModel($model) { |
$this->setBackgroundColor(new awColor(255, 255, 255, 15)); |
$this->setPadding(8, 8, 8, 8); |
$this->setTextFont(new awFont2); |
$this->shadow->setSize(3); |
switch($model) { |
case awLegend::MODEL_RIGHT : |
$this->setColumns(1); |
$this->setAlign(awLegend::RIGHT, awLegend::MIDDLE); |
$this->setPosition(0.96, 0.50); |
break; |
case awLegend::MODEL_BOTTOM : |
$this->setRows(1); |
$this->setAlign(awLegend::CENTER, awLegend::TOP); |
$this->setPosition(0.50, 0.92); |
break; |
default : |
$this->setPosition(0.5, 0.5); |
break; |
} |
} |
/** |
* Hide legend ? |
* |
* @param bool $hide TRUE to hide legend, FALSE otherwise |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show legend ? |
* |
* @param bool $show |
*/ |
public function show($show = TRUE) { |
$this->hide = (bool)!$show; |
} |
/** |
* Add a Legendable object to the legend |
* |
* @param awLegendable $legendable |
* @param string $title Legend title |
* @param int $type Legend type (default to awLegend::LINE) |
*/ |
public function add(awLegendable $legendable, $title, $type = awLegend::LINE) { |
$legend = array($legendable, $title, $type); |
$this->legends[] = $legend; |
} |
/** |
* Change legend padding |
* |
* @param int $left |
* @param int $right |
* @param int $top |
* @param int $bottom |
*/ |
public function setPadding($left, $right, $top, $bottom) { |
$this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom); |
} |
/** |
* Change space between each legend |
* |
* @param int $space |
*/ |
public function setSpace($space) { |
$this->space = (int)$space; |
} |
/** |
* Change alignment |
* |
* @param int $h Horizontal alignment |
* @param int $v Vertical alignment |
*/ |
public function setAlign($h = NULL, $v = NULL) { |
if($h !== NULL) { |
$this->hAlign = (int)$h; |
} |
if($v !== NULL) { |
$this->vAlign = (int)$v; |
} |
} |
/** |
* Change number of columns |
* |
* @param int $columns |
*/ |
public function setColumns($columns) { |
$this->rows = NULL; |
$this->columns = (int)$columns; |
} |
/** |
* Change number of rows |
* |
* @param int $rows |
*/ |
public function setRows($rows) { |
$this->columns = NULL; |
$this->rows = (int)$rows; |
} |
/** |
* Change legend position |
* X and Y positions must be between 0 and 1. |
* |
* @param float $x |
* @param float $y |
*/ |
public function setPosition($x = NULL, $y = NULL) { |
$x = (is_null($x) and !is_null($this->position)) ? $this->position->x : $x; |
$y = (is_null($y) and !is_null($this->position)) ? $this->position->y : $y; |
$this->position = new awPoint($x, $y); |
} |
/** |
* Get legend position |
* |
* @return Point |
*/ |
public function getPosition() { |
return $this->position; |
} |
/** |
* Change text font |
* |
* @param awFont $font |
*/ |
public function setTextFont(awFont $font) { |
$this->textFont = $font; |
} |
/** |
* Change text margin |
* |
* @param int $left |
* @param int $right |
*/ |
public function setTextMargin($left, $right) { |
$this->textMargin->set($left, $right); |
} |
/** |
* Change text color |
* |
* @param awColor $color |
*/ |
public function setTextColor(awColor $color) { |
$this->textColor = $color; |
} |
/** |
* Change background |
* |
* @param mixed $background |
*/ |
public function setBackground($background) { |
$this->background = $background; |
} |
/** |
* Change background color |
* |
* @param awColor $color |
*/ |
public function setBackgroundColor(awColor $color) { |
$this->background = $color; |
} |
/** |
* Change background gradient |
* |
* @param awGradient $gradient |
*/ |
public function setBackgroundGradient(awGradient $gradient) { |
$this->background = $gradient; |
} |
/** |
* Count the number of Legendable objects in the legend |
* |
* @return int |
*/ |
public function count() { |
return count($this->legends); |
} |
public function draw(awDriver $driver) { |
if($this->hide) { |
return; |
} |
$count = $this->count(); |
// No legend to print |
if($count === 0) { |
return; |
} |
// Get text widths and heights of each element of the legend |
$widths = array(); |
$heights = array(); |
$texts = array(); |
for($i = 0; $i < $count; $i++) { |
list(, $title, ) = $this->legends[$i]; |
$text = new awText( |
$title, |
$this->textFont, |
$this->textColor, |
0 |
); |
// $font = $text->getFont(); |
$widths[$i] = $driver->getTextWidth($text) + $this->textMargin->left + $this->textMargin->right; |
$heights[$i] = $driver->getTextHeight($text); |
$texts[$i] = $text; |
} |
// Maximum height of the font used |
$heightMax = array_max($heights); |
// Get number of columns |
if($this->columns !== NULL) { |
$columns = $this->columns; |
} else if($this->rows !== NULL) { |
$columns = ceil($count / $this->rows); |
} else { |
$columns = $count; |
} |
// Number of rows |
$rows = (int)ceil($count / $columns); |
// Get maximum with of each column |
$widthMax = array(); |
for($i = 0; $i < $count; $i++) { |
// Get column width |
$column = $i % $columns; |
if(array_key_exists($column, $widthMax) === FALSE) { |
$widthMax[$column] = $widths[$i]; |
} else { |
$widthMax[$column] = max($widthMax[$column], $widths[$i]); |
} |
} |
$width = $this->padding[0] + $this->padding[1] - $this->space; |
for($i = 0; $i < $columns; $i++) { |
$width += $this->space + 5 + 10 + $widthMax[$i]; |
} |
$height = ($heightMax + $this->space) * $rows - $this->space + $this->padding[2] + $this->padding[3]; |
// Look for legends position |
list($x, $y) = $driver->getSize(); |
$p = new awPoint( |
$this->position->x * $x, |
$this->position->y * $y |
); |
switch($this->hAlign) { |
case awLegend::CENTER : |
$p->x -= $width / 2; |
break; |
case awLegend::RIGHT : |
$p->x -= $width; |
break; |
} |
switch($this->vAlign) { |
case awLegend::MIDDLE : |
$p->y -= $height / 2; |
break; |
case awLegend::BOTTOM : |
$p->y -= $height; |
break; |
} |
// Draw legend shadow |
$this->shadow->draw( |
$driver, |
$p, |
$p->move($width, $height), |
awShadow::OUT |
); |
// Draw legends base |
$this->drawBase($driver, $p, $width, $height); |
// Draw each legend |
for($i = 0; $i < $count; $i++) { |
list($component, $title, $type) = $this->legends[$i]; |
$column = $i % $columns; |
$row = (int)floor($i / $columns); |
// Get width of all previous columns |
$previousColumns = 0; |
for($j = 0; $j < $column; $j++) { |
$previousColumns += $this->space + 10 + 5 + $widthMax[$j]; |
} |
// Draw legend text |
$driver->string( |
$texts[$i], |
$p->move( |
$this->padding[0] + $previousColumns + 10 + 5 + $this->textMargin->left, |
$this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $heights[$i] / 2 |
) |
); |
// Draw legend icon |
switch($type) { |
case awLegend::LINE : |
case awLegend::MARK : |
case awLegend::MARKONLY : |
// Get vertical position |
$x = $this->padding[0] + $previousColumns; |
$y = $this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $component->getLegendLineThickness(); |
// Draw two lines |
if($component->getLegendLineColor() !== NULL) { |
$color = $component->getLegendLineColor(); |
if($color instanceof awColor and $type !== awLegend::MARKONLY) { |
$driver->line( |
$color, |
new awLine( |
$p->move( |
$x, // YaPB ?? |
$y + $component->getLegendLineThickness() / 2 |
), |
$p->move( |
$x + 10, |
$y + $component->getLegendLineThickness() / 2 |
), |
$component->getLegendLineStyle(), |
$component->getLegendLineThickness() |
) |
); |
unset($color); |
} |
} |
if($type === awLegend::MARK or $type === awLegend::MARKONLY) { |
$mark = $component->getLegendMark(); |
if($mark !== NULL) { |
$mark->draw( |
$driver, |
$p->move( |
$x + 5.5, |
$y + $component->getLegendLineThickness() / 2 |
) |
); |
} |
unset($mark); |
} |
break; |
case awLegend::BACKGROUND : |
// Get vertical position |
$x = $this->padding[0] + $previousColumns; |
$y = $this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - 5; |
$from = $p->move( |
$x, |
$y |
); |
$to = $p->move( |
$x + 10, |
$y + 10 |
); |
$background = $component->getLegendBackground(); |
if($background !== NULL) { |
$driver->filledRectangle( |
$component->getLegendBackground(), |
new awLine($from, $to) |
); |
// Draw rectangle border |
$this->border->rectangle( |
$driver, |
$from->move(0, 0), |
$to->move(0, 0) |
); |
} |
unset($background, $from, $to); |
break; |
} |
} |
} |
private function drawBase(awDriver $driver, awPoint $p, $width, $height) { |
$this->border->rectangle( |
$driver, |
$p, |
$p->move($width, $height) |
); |
$size = $this->border->visible() ? 1 : 0; |
$driver->filledRectangle( |
$this->background, |
new awLine( |
$p->move($size, $size), |
$p->move($width - $size, $height - $size) |
) |
); |
} |
} |
registerClass('Legend'); |
/** |
* You can add a legend to components which implements this interface |
* |
* @package Artichow |
*/ |
interface awLegendable { |
/** |
* Get the line type |
* |
* @return int |
*/ |
public function getLegendLineStyle(); |
/** |
* Get the line thickness |
* |
* @return int |
*/ |
public function getLegendLineThickness(); |
/** |
* Get the color of line |
* |
* @return Color |
*/ |
public function getLegendLineColor(); |
/** |
* Get the background color or gradient of an element of the component |
* |
* @return Color, Gradient |
*/ |
public function getLegendBackground(); |
/** |
* Get a Mark object |
* |
* @return Mark |
*/ |
public function getLegendMark(); |
} |
registerInterface('Legendable'); |
?> |
/trunk/bibliotheque/artichow/inc/Tools.class.php |
---|
New file |
0,0 → 1,175 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Objects capable of being positioned |
* |
* @package Artichow |
*/ |
interface awPositionable { |
/** |
* Left align |
* |
* @var int |
*/ |
const LEFT = 1; |
/** |
* Right align |
* |
* @var int |
*/ |
const RIGHT = 2; |
/** |
* Center align |
* |
* @var int |
*/ |
const CENTER = 3; |
/** |
* Top align |
* |
* @var int |
*/ |
const TOP = 4; |
/** |
* Bottom align |
* |
* @var int |
*/ |
const BOTTOM = 5; |
/** |
* Middle align |
* |
* @var int |
*/ |
const MIDDLE = 6; |
/** |
* Change alignment |
* |
* @param int $h Horizontal alignment |
* @param int $v Vertical alignment |
*/ |
public function setAlign($h = NULL, $v = NULL); |
} |
registerInterface('Positionable'); |
/** |
* Manage left, right, top and bottom sides |
* |
* @package Artichow |
*/ |
class awSide { |
/** |
* Left side |
* |
* @var int |
*/ |
public $left = 0; |
/** |
* Right side |
* |
* @var int |
*/ |
public $right = 0; |
/** |
* Top side |
* |
* @var int |
*/ |
public $top = 0; |
/** |
* Bottom side |
* |
* @var int |
*/ |
public $bottom = 0; |
/** |
* Build the side |
* |
* @param mixed $left |
* @param mixed $right |
* @param mixed $top |
* @param mixed $bottom |
*/ |
public function __construct($left = NULL, $right = NULL, $top = NULL, $bottom = NULL) { |
$this->set($left, $right, $top, $bottom); |
} |
/** |
* Change side values |
* |
* @param mixed $left |
* @param mixed $right |
* @param mixed $top |
* @param mixed $bottom |
*/ |
public function set($left = NULL, $right = NULL, $top = NULL, $bottom = NULL) { |
if($left !== NULL) { |
$this->left = (float)$left; |
} |
if($right !== NULL) { |
$this->right = (float)$right; |
} |
if($top !== NULL) { |
$this->top = (float)$top; |
} |
if($bottom !== NULL) { |
$this->bottom = (float)$bottom; |
} |
} |
/** |
* Add values to each side |
* |
* @param mixed $left |
* @param mixed $right |
* @param mixed $top |
* @param mixed $bottom |
*/ |
public function add($left = NULL, $right = NULL, $top = NULL, $bottom = NULL) { |
if($left !== NULL) { |
$this->left += (float)$left; |
} |
if($right !== NULL) { |
$this->right += (float)$right; |
} |
if($top !== NULL) { |
$this->top += (float)$top; |
} |
if($bottom !== NULL) { |
$this->bottom += (float)$bottom; |
} |
} |
} |
registerClass('Side'); |
?> |
/trunk/bibliotheque/artichow/inc/Axis.class.php |
---|
New file |
0,0 → 1,769 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Handle axis |
* |
* @package Artichow |
*/ |
class awAxis { |
/** |
* Axis line |
* |
* @var Line |
*/ |
public $line; |
/** |
* Axis labels |
* |
* @var Label |
*/ |
public $label; |
/** |
* Axis title |
* |
* @var Label |
*/ |
public $title; |
/** |
* Title position |
* |
* @var float |
*/ |
protected $titlePosition = 0.5; |
/** |
* Labels number |
* |
* @var int |
*/ |
protected $labelNumber; |
/** |
* Axis ticks |
* |
* @var array |
*/ |
protected $ticks = array(); |
/** |
* Axis and ticks color |
* |
* @var Color |
*/ |
protected $color; |
/** |
* Axis left and right padding |
* |
* @var Side |
*/ |
protected $padding; |
/** |
* Axis range |
* |
* @var array |
*/ |
protected $range; |
/** |
* Hide axis |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Auto-scaling mode |
* |
* @var bool |
*/ |
protected $auto = TRUE; |
/** |
* Axis range callback function |
* |
* @var array |
*/ |
protected $rangeCallback = array( |
'toValue' => 'toProportionalValue', |
'toPosition' => 'toProportionalPosition' |
); |
/** |
* Build the axis |
* |
* @param float $min Begin of the range of the axis |
* @param float $max End of the range of the axis |
*/ |
public function __construct($min = NULL, $max = NULL) { |
$this->line = new awVector( |
new awPoint(0, 0), |
new awPoint(0, 0) |
); |
$this->label = new awLabel; |
$this->padding = new awSide; |
$this->title = new awLabel( |
NULL, |
NULL, |
NULL, |
0 |
); |
$this->setColor(new awBlack); |
if($min !== NULL and $max !== NULL) { |
$this->setRange($min, $max); |
} |
} |
/** |
* Enable/disable auto-scaling mode |
* |
* @param bool $auto |
*/ |
public function auto($auto) { |
$this->auto = (bool)$auto; |
} |
/** |
* Get auto-scaling mode status |
* |
* @return bool |
*/ |
public function isAuto() { |
return $this->auto; |
} |
/** |
* Hide axis |
* |
* @param bool $hide |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show axis |
* |
* @param bool $show |
*/ |
public function show($show = TRUE) { |
$this->hide = !(bool)$show; |
} |
/** |
* Return a tick object from its name |
* |
* @param string $name Tick object name |
* @return Tick |
*/ |
public function tick($name) { |
return array_key_exists($name, $this->ticks) ? $this->ticks[$name] : NULL; |
} |
/** |
* Add a tick object |
* |
* @param string $name Tick object name |
* @param awTick $tick Tick object |
*/ |
public function addTick($name, awTick $tick) { |
$this->ticks[$name] = $tick; |
} |
/** |
* Delete a tick object |
* |
* @param string $name Tick object name |
*/ |
public function deleteTick($name) { |
if(array_key_exists($name, $this->ticks)) { |
unset($this->ticks[$name]); |
} |
} |
/** |
* Hide all ticks |
* |
* @param bool $hide Hide or not ? |
*/ |
public function hideTicks($hide = TRUE) { |
foreach($this->ticks as $tick) { |
$tick->hide($hide); |
} |
} |
/** |
* Change ticks style |
* |
* @param int $style Ticks style |
*/ |
public function setTickStyle($style) { |
foreach($this->ticks as $tick) { |
$tick->setStyle($style); |
} |
} |
/** |
* Change ticks interval |
* |
* @param int $interval Ticks interval |
*/ |
public function setTickInterval($interval) { |
foreach($this->ticks as $tick) { |
$tick->setInterval($interval); |
} |
} |
/** |
* Change number of ticks relative to others ticks |
* |
* @param awTick $to Change number of theses ticks |
* @param awTick $from Ticks reference |
* @param float $number Number of ticks by the reference |
*/ |
public function setNumberByTick($to, $from, $number) { |
$this->ticks[$to]->setNumberByTick($this->ticks[$from], $number); |
} |
/** |
* Reverse ticks style |
*/ |
public function reverseTickStyle() { |
foreach($this->ticks as $tick) { |
if($tick->getStyle() === awTick::IN) { |
$tick->setStyle(awTick::OUT); |
} else if($tick->getStyle() === awTick::OUT) { |
$tick->setStyle(awTick::IN); |
} |
} |
} |
/** |
* Change interval of labels |
* |
* @param int $interval Interval |
*/ |
public function setLabelInterval($interval) { |
$this->auto(FALSE); |
$this->setTickInterval($interval); |
$this->label->setInterval($interval); |
} |
/** |
* Change number of labels |
* |
* @param int $number Number of labels to display (can be NULL) |
*/ |
public function setLabelNumber($number) { |
$this->auto(FALSE); |
$this->labelNumber = is_null($number) ? NULL : (int)$number; |
} |
/** |
* Get number of labels |
* |
* @return int |
*/ |
public function getLabelNumber() { |
return $this->labelNumber; |
} |
/** |
* Change precision of labels |
* |
* @param int $precision Precision |
*/ |
public function setLabelPrecision($precision) { |
$this->auto(FALSE); |
$function = 'axis'.time().'_'.(microtime() * 1000000); |
eval('function '.$function.'($value) { |
return sprintf("%.'.(int)$precision.'f", $value); |
}'); |
$this->label->setCallbackFunction($function); |
} |
/** |
* Change text of labels |
* |
* @param array $texts Some texts |
*/ |
public function setLabelText($texts) { |
if(is_array($texts)) { |
$this->auto(FALSE); |
$function = 'axis'.time().'_'.(microtime() * 1000000); |
eval('function '.$function.'($value) { |
$texts = '.var_export($texts, TRUE).'; |
return isset($texts[$value]) ? $texts[$value] : \'?\'; |
}'); |
$this->label->setCallbackFunction($function); |
} |
} |
/** |
* Get the position of a point |
* |
* @param awAxis $xAxis X axis |
* @param awAxis $yAxis Y axis |
* @param awPoint $p Position of the point |
* @return Point Position on the axis |
*/ |
public static function toPosition(awAxis $xAxis, awAxis $yAxis, awPoint $p) { |
$p1 = $xAxis->getPointFromValue($p->x); |
$p2 = $yAxis->getPointFromValue($p->y); |
return new awPoint( |
round($p1->x), |
round($p2->y) |
); |
} |
/** |
* Change title alignment |
* |
* @param int $alignment New Alignment |
*/ |
public function setTitleAlignment($alignment) { |
switch($alignment) { |
case awLabel::TOP : |
$this->setTitlePosition(1); |
$this->title->setAlign(NULL, awLabel::BOTTOM); |
break; |
case awLabel::BOTTOM : |
$this->setTitlePosition(0); |
$this->title->setAlign(NULL, awLabel::TOP); |
break; |
case awLabel::LEFT : |
$this->setTitlePosition(0); |
$this->title->setAlign(awLabel::LEFT); |
break; |
case awLabel::RIGHT : |
$this->setTitlePosition(1); |
$this->title->setAlign(awLabel::RIGHT); |
break; |
} |
} |
/** |
* Change title position on the axis |
* |
* @param float $position A new awposition between 0 and 1 |
*/ |
public function setTitlePosition($position) { |
$this->titlePosition = (float)$position; |
} |
/** |
* Change axis and axis title color |
* |
* @param awColor $color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
$this->title->setColor($color); |
} |
/** |
* Change axis padding |
* |
* @param int $left Left padding in pixels |
* @param int $right Right padding in pixels |
*/ |
public function setPadding($left, $right) { |
$this->padding->set($left, $right); |
} |
/** |
* Get axis padding |
* |
* @return Side |
*/ |
public function getPadding() { |
return $this->padding; |
} |
/** |
* Change axis range |
* |
* @param float $min |
* @param float $max |
*/ |
public function setRange($min, $max) { |
if($min !== NULL) { |
$this->range[0] = (float)$min; |
} |
if($max !== NULL) { |
$this->range[1] = (float)$max; |
} |
} |
/** |
* Get axis range |
* |
* @return array |
*/ |
public function getRange() { |
return $this->range; |
} |
/** |
* Change axis range callback function |
* |
* @param string $toValue Transform a position between 0 and 1 to a value |
* @param string $toPosition Transform a value to a position between 0 and 1 on the axis |
*/ |
public function setRangeCallback($toValue, $toPosition) { |
$this->rangeCallback = array( |
'toValue' => (string)$toValue, |
'toPosition' => (string)$toPosition |
); |
} |
/** |
* Center X values of the axis |
* |
* @param awAxis $axis An axis |
* @param float $value The reference value on the axis |
*/ |
public function setXCenter(awAxis $axis, $value) { |
// Check vector angle |
if($this->line->isVertical() === FALSE) { |
awImage::drawError("Class Axis: setXCenter() can only be used on vertical axes."); |
} |
$p = $axis->getPointFromValue($value); |
$this->line->setX( |
$p->x, |
$p->x |
); |
} |
/** |
* Center Y values of the axis |
* |
* @param awAxis $axis An axis |
* @param float $value The reference value on the axis |
*/ |
public function setYCenter(awAxis $axis, $value) { |
// Check vector angle |
if($this->line->isHorizontal() === FALSE) { |
awImage::drawError("Class Axis: setYCenter() can only be used on horizontal axes."); |
} |
$p = $axis->getPointFromValue($value); |
$this->line->setY( |
$p->y, |
$p->y |
); |
} |
/** |
* Get the distance between to values on the axis |
* |
* @param float $from The first value |
* @param float $to The last value |
* @return Point |
*/ |
public function getDistance($from, $to) { |
$p1 = $this->getPointFromValue($from); |
$p2 = $this->getPointFromValue($to); |
return $p1->getDistance($p2); |
} |
/** |
* Get a point on the axis from a value |
* |
* @param float $value |
* @return Point |
*/ |
protected function getPointFromValue($value) { |
$callback = $this->rangeCallback['toPosition']; |
list($min, $max) = $this->range; |
$position = $callback($value, $min, $max); |
return $this->getPointFromPosition($position); |
} |
/** |
* Get a point on the axis from a position |
* |
* @param float $position A position between 0 and 1 |
* @return Point |
*/ |
protected function getPointFromPosition($position) { |
$vector = $this->getVector(); |
$angle = $vector->getAngle(); |
$size = $vector->getSize(); |
return $vector->p1->move( |
cos($angle) * $size * $position, |
-1 * sin($angle) * $size * $position |
); |
} |
/** |
* Draw axis |
* |
* @param awDriver $driver A driver |
*/ |
public function draw(awDriver $driver) { |
if($this->hide) { |
return; |
} |
$vector = $this->getVector(); |
// Draw axis ticks |
$this->drawTicks($driver, $vector); |
// Draw axis line |
$this->line($driver); |
// Draw labels |
$this->drawLabels($driver); |
// Draw axis title |
$p = $this->getPointFromPosition($this->titlePosition); |
$this->title->draw($driver, $p); |
} |
public function autoScale() { |
if($this->isAuto() === FALSE) { |
return; |
} |
list($min, $max) = $this->getRange(); |
$interval = $max - $min; |
if($interval > 0) { |
$partMax = $max / $interval; |
$partMin = $min / $interval; |
} else { |
$partMax = 0; |
$partMin = 0; |
} |
$difference = log($interval) / log(10); |
$difference = floor($difference); |
$pow = pow(10, $difference); |
if($pow > 0) { |
$intervalNormalize = $interval / $pow; |
} else { |
$intervalNormalize = 0; |
} |
if($difference <= 0) { |
$precision = $difference * -1 + 1; |
if($intervalNormalize > 2) { |
$precision--; |
} |
} else { |
$precision = 0; |
} |
if($min != 0 and $max != 0) { |
$precision++; |
} |
if($this->label->getCallbackFunction() === NULL) { |
$this->setLabelPrecision($precision); |
} |
if($intervalNormalize <= 1.5) { |
$intervalReal = 1.5; |
$labelNumber = 4; |
} else if($intervalNormalize <= 2) { |
$intervalReal = 2; |
$labelNumber = 5; |
} else if($intervalNormalize <= 3) { |
$intervalReal = 3; |
$labelNumber = 4; |
} else if($intervalNormalize <= 4) { |
$intervalReal = 4; |
$labelNumber = 5; |
} else if($intervalNormalize <= 5) { |
$intervalReal = 5; |
$labelNumber = 6; |
} else if($intervalNormalize <= 8) { |
$intervalReal = 8; |
$labelNumber = 5; |
} else if($intervalNormalize <= 10) { |
$intervalReal = 10; |
$labelNumber = 6; |
} |
if($min == 0) { |
$this->setRange( |
$min, |
$intervalReal * $pow |
); |
} else if($max == 0) { |
$this->setRange( |
$intervalReal * $pow * -1, |
0 |
); |
} |
$this->setLabelNumber($labelNumber); |
} |
protected function line(awDriver $driver) { |
$driver->line( |
$this->color, |
$this->line |
); |
} |
protected function drawTicks(awDriver $driver, awVector $vector) { |
foreach($this->ticks as $tick) { |
$tick->setColor($this->color); |
$tick->draw($driver, $vector); |
} |
} |
protected function drawLabels($driver) { |
if($this->labelNumber !== NULL) { |
list($min, $max) = $this->range; |
$number = $this->labelNumber - 1; |
if($number < 1) { |
return; |
} |
$function = $this->rangeCallback['toValue']; |
$labels = array(); |
for($i = 0; $i <= $number; $i++) { |
$labels[] = $function($i / $number, $min, $max); |
} |
$this->label->set($labels); |
} |
$labels = $this->label->count(); |
for($i = 0; $i < $labels; $i++) { |
$p = $this->getPointFromValue($this->label->get($i)); |
$this->label->draw($driver, $p, $i); |
} |
} |
protected function getVector() { |
$angle = $this->line->getAngle(); |
// Compute paddings |
$vector = new awVector( |
$this->line->p1->move( |
cos($angle) * $this->padding->left, |
-1 * sin($angle) * $this->padding->left |
), |
$this->line->p2->move( |
-1 * cos($angle) * $this->padding->right, |
-1 * -1 * sin($angle) * $this->padding->right |
) |
); |
return $vector; |
} |
public function __clone() { |
$this->label = clone $this->label; |
$this->line = clone $this->line; |
$this->title = clone $this->title; |
foreach($this->ticks as $name => $tick) { |
$this->ticks[$name] = clone $tick; |
} |
} |
} |
registerClass('Axis'); |
function toProportionalValue($position, $min, $max) { |
return $min + ($max - $min) * $position; |
} |
function toProportionalPosition($value, $min, $max) { |
if($max - $min == 0) { |
return 0; |
} |
return ($value - $min) / ($max - $min); |
} |
?> |
/trunk/bibliotheque/artichow/inc/Font.class.php |
---|
New file |
0,0 → 1,263 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Common font characteristics and methods. |
* Declared abstract only so that it can't be instanciated. |
* Users have to call 'new awPHPFont' or 'new awFileFont', |
* or any of their inherited classes (awFont1, awTuffy, awTTFFont, etc.) |
* |
* @package Artichow |
*/ |
abstract class awFont { |
/** |
* Build the font |
* |
*/ |
public function __construct() { |
} |
/** |
* Draw a text |
* |
* @param awDriver $driver |
* @param awPoint $p Draw text at this point |
* @param awText $text The text |
* @param int $width Text box width |
*/ |
public function draw(awDriver $driver, awPoint $point, awText $text, $width = NULL) { |
$driver->string($this, $text, $point, $width); |
} |
} |
registerClass('Font', TRUE); |
/** |
* Class for fonts that cannot be transformed, |
* like the built-in PHP fonts for example. |
* |
* @package Artichow |
*/ |
class awPHPFont extends awFont { |
/** |
* The used font identifier |
* |
* @var int |
*/ |
public $font; |
public function __construct($font = NULL) { |
parent::__construct(); |
if($font !== NULL) { |
$this->font = (int)$font; |
} |
} |
} |
registerClass('PHPFont'); |
/** |
* Class for fonts that can be transformed (rotated, skewed, etc.), |
* like TTF or FDB fonts for example. |
* |
* @package Artichow |
*/ |
class awFileFont extends awFont { |
/** |
* The name of the font, without the extension |
* |
* @var string |
*/ |
protected $name; |
/** |
* The size of the font |
* |
* @var int |
*/ |
protected $size; |
/** |
* The font filename extension |
* |
* @var string |
*/ |
protected $extension; |
public function __construct($name, $size) { |
parent::__construct(); |
$this->setName($name); |
$this->setSize($size); |
} |
/** |
* Set the name of the font. The $name variable can contain the full path, |
* or just the filename. Artichow will try to do The Right Thing, |
* as well as set the extension property correctly if possible. |
* |
* @param string $name |
*/ |
public function setName($name) { |
$fontInfo = pathinfo((string)$name); |
if(strpos($fontInfo['dirname'], '/') !== 0) { |
// Path is not absolute, use ARTICHOW_FONT |
$name = ARTICHOW_FONT.DIRECTORY_SEPARATOR.$fontInfo['basename']; |
$fontInfo = pathinfo($name); |
} |
$this->name = $fontInfo['dirname'].DIRECTORY_SEPARATOR.$fontInfo['basename']; |
if(array_key_exists('extension', $fontInfo) and $fontInfo['extension'] !== '') { |
$this->setExtension($fontInfo['extension']); |
} |
} |
/** |
* Return the name of the font, i.e. the absolute path and the filename, without the extension. |
* |
* @return string |
*/ |
public function getName() { |
return $this->name; |
} |
/** |
* Set the size of the font, in pixels |
* |
* @param int $size |
*/ |
public function setSize($size) { |
$this->size = (int)$size; |
} |
/** |
* Return the size of the font, in pixels |
* |
* @return int |
*/ |
public function getSize() { |
return $this->size; |
} |
/** |
* Set the extension, without the dot |
* |
* @param string $extension |
*/ |
public function setExtension($extension) { |
$this->extension = (string)$extension; |
} |
/** |
* Get the filename extension for that font |
* |
* @return string |
*/ |
public function getExtension() { |
return $this->extension; |
} |
} |
registerClass('FileFont'); |
/** |
* Class representing TTF fonts |
* |
* @package Artichow |
*/ |
class awTTFFont extends awFileFont { |
public function __construct($name, $size) { |
parent::__construct($name, $size); |
if($this->getExtension() === NULL) { |
$this->setExtension('ttf'); |
} |
} |
} |
registerClass('TTFFont'); |
$php = ''; |
for($i = 1; $i <= 5; $i++) { |
$php .= ' |
class awFont'.$i.' extends awPHPFont { |
public function __construct() { |
parent::__construct('.$i.'); |
} |
} |
'; |
if(ARTICHOW_PREFIX !== 'aw') { |
$php .= ' |
class '.ARTICHOW_PREFIX.'Font'.$i.' extends awFont'.$i.' { |
} |
'; |
} |
} |
eval($php); |
$php = ''; |
foreach($fonts as $font) { |
$php .= ' |
class aw'.$font.' extends awFileFont { |
public function __construct($size) { |
parent::__construct(\''.$font.'\', $size); |
} |
} |
'; |
if(ARTICHOW_PREFIX !== 'aw') { |
$php .= ' |
class '.ARTICHOW_PREFIX.$font.' extends aw'.$font.' { |
} |
'; |
} |
} |
eval($php); |
/* |
* Environment modification for GD2 and TTF fonts |
*/ |
if(function_exists('putenv')) { |
putenv('GDFONTPATH='.ARTICHOW_FONT); |
} |
?> |
/trunk/bibliotheque/artichow/inc/Border.class.php |
---|
New file |
0,0 → 1,198 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Draw border |
* |
* @package Artichow |
*/ |
class awBorder { |
/** |
* Border color |
* |
* @var Color |
*/ |
protected $color; |
/** |
* Hide border ? |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Border line style |
* |
* @var int |
*/ |
protected $style; |
/** |
* Build the border |
* |
* @param awColor $color Border color |
* @param int $style Border style |
*/ |
public function __construct($color = NULL, $style = awLine::SOLID) { |
$this->setStyle($style); |
if($color instanceof awColor) { |
$this->setColor($color); |
} else { |
$this->setColor(new awBlack); |
} |
} |
/** |
* Change border color |
* This method automatically shows the border if it is hidden |
* |
* @param awColor $color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
$this->show(); |
} |
/** |
* Change border style |
* |
* @param int $style |
*/ |
public function setStyle($style) { |
$this->style = (int)$style; |
} |
/** |
* Hide border ? |
* |
* @param bool $hide |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show border ? |
* |
* @param bool $show |
*/ |
public function show($show = TRUE) { |
$this->hide = (bool)!$show; |
} |
/** |
* Is the border visible ? |
* |
* @return bool |
*/ |
public function visible() { |
return !$this->hide; |
} |
/** |
* Draw border as a rectangle |
* |
* @param awDriver $driver |
* @param awPoint $p1 Top-left corner |
* @param awPoint $p2 Bottom-right corner |
*/ |
public function rectangle(awDriver $driver, awPoint $p1, awPoint $p2) { |
// Border is hidden |
if($this->hide) { |
return; |
} |
$line = new awLine; |
$line->setStyle($this->style); |
$line->setLocation($p1, $p2); |
$driver->rectangle($this->color, $line); |
} |
/** |
* Draw border as an ellipse |
* |
* @param awDriver $driver |
* @param awPoint $center Ellipse center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
*/ |
public function ellipse(awDriver $driver, awPoint $center, $width, $height) { |
// Border is hidden |
if($this->hide) { |
return; |
} |
switch($this->style) { |
case awLine::SOLID : |
$driver->ellipse($this->color, $center, $width, $height); |
break; |
default : |
awImage::drawError("Class Border: Dashed and dotted borders and not yet implemented on ellipses."); |
break; |
} |
} |
/** |
* Draw border as a polygon |
* |
* @param awDriver $driver A Driver object |
* @param awPolygon $polygon A Polygon object |
*/ |
public function polygon(awDriver $driver, awPolygon $polygon) { |
// Border is hidden |
if($this->hide) { |
return; |
} |
$polygon->setStyle($this->style); |
$driver->polygon($this->color, $polygon); |
// In case of Line::SOLID, Driver::polygon() uses imagepolygon() |
// which automatically closes the shape. In any other case, |
// we have to do it manually here. |
if($this->style !== Line::SOLID) { |
$this->closePolygon($driver, $polygon); |
} |
} |
/** |
* Draws the last line of a Polygon, between the first and last point |
* |
* @param awDriver $driver A Driver object |
* @param awPolygon $polygon The polygon object to close |
*/ |
private function closePolygon(awDriver $driver, awPolygon $polygon) { |
$first = $polygon->get(0); |
$last = $polygon->get($polygon->count() - 1); |
$line = new awLine($first, $last, $this->style, $polygon->getThickness()); |
$driver->line($this->color, $line); |
} |
} |
registerClass('Border'); |
?> |
/trunk/bibliotheque/artichow/inc/Color.class.php |
---|
New file |
0,0 → 1,165 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Create your colors |
* |
* @package Artichow |
*/ |
class awColor { |
public $red; |
public $green; |
public $blue; |
public $alpha; |
/** |
* Build your color |
* |
* @var int $red Red intensity (from 0 to 255) |
* @var int $green Green intensity (from 0 to 255) |
* @var int $blue Blue intensity (from 0 to 255) |
* @var int $alpha Alpha channel (from 0 to 100) |
*/ |
public function __construct($red, $green, $blue, $alpha = 0) { |
$this->red = (int)$red; |
$this->green = (int)$green; |
$this->blue = (int)$blue; |
$this->alpha = (int)round($alpha * 127 / 100); |
} |
/** |
* Get RGB and alpha values of your color |
* |
* @return array |
*/ |
public function getColor() { |
return $this->rgba(); |
} |
/** |
* Change color brightness |
* |
* @param int $brightness Add this intensity to the color (betweeen -255 and +255) |
*/ |
public function brightness($brightness) { |
$brightness = (int)$brightness; |
$this->red = min(255, max(0, $this->red + $brightness)); |
$this->green = min(255, max(0, $this->green + $brightness)); |
$this->blue = min(255, max(0, $this->blue + $brightness)); |
} |
/** |
* Get RGB and alpha values of your color |
* |
* @return array |
*/ |
public function rgba() { |
return array($this->red, $this->green, $this->blue, $this->alpha); |
} |
} |
registerClass('Color'); |
$colors = array( |
'Black' => array(0, 0, 0), |
'AlmostBlack' => array(48, 48, 48), |
'VeryDarkGray' => array(88, 88, 88), |
'DarkGray' => array(128, 128, 128), |
'MidGray' => array(160, 160, 160), |
'LightGray' => array(195, 195, 195), |
'VeryLightGray' => array(220, 220, 220), |
'White' => array(255, 255, 255), |
'VeryDarkRed' => array(64, 0, 0), |
'DarkRed' => array(128, 0, 0), |
'MidRed' => array(192, 0, 0), |
'Red' => array(255, 0, 0), |
'LightRed' => array(255, 192, 192), |
'VeryDarkGreen' => array(0, 64, 0), |
'DarkGreen' => array(0, 128, 0), |
'MidGreen' => array(0, 192, 0), |
'Green' => array(0, 255, 0), |
'LightGreen' => array(192, 255, 192), |
'VeryDarkBlue' => array(0, 0, 64), |
'DarkBlue' => array(0, 0, 128), |
'MidBlue' => array(0, 0, 192), |
'Blue' => array(0, 0, 255), |
'LightBlue' => array(192, 192, 255), |
'VeryDarkYellow' => array(64, 64, 0), |
'DarkYellow' => array(128, 128, 0), |
'MidYellow' => array(192, 192, 0), |
'Yellow' => array(255, 255, 2), |
'LightYellow' => array(255, 255, 192), |
'VeryDarkCyan' => array(0, 64, 64), |
'DarkCyan' => array(0, 128, 128), |
'MidCyan' => array(0, 192, 192), |
'Cyan' => array(0, 255, 255), |
'LightCyan' => array(192, 255, 255), |
'VeryDarkMagenta' => array(64, 0, 64), |
'DarkMagenta' => array(128, 0, 128), |
'MidMagenta' => array(192, 0, 192), |
'Magenta' => array(255, 0, 255), |
'LightMagenta' => array(255, 192, 255), |
'DarkOrange' => array(192, 88, 0), |
'Orange' => array(255, 128, 0), |
'LightOrange' => array(255, 168, 88), |
'VeryLightOrange' => array(255, 220, 168), |
'DarkPink' => array(192, 0, 88), |
'Pink' => array(255, 0, 128), |
'LightPink' => array(255, 88, 168), |
'VeryLightPink' => array(255, 168, 220), |
'DarkPurple' => array(88, 0, 192), |
'Purple' => array(128, 0, 255), |
'LightPurple' => array(168, 88, 255), |
'VeryLightPurple' => array(220, 168, 255), |
); |
$php = ''; |
foreach($colors as $name => $color) { |
list($red, $green, $blue) = $color; |
$php .= ' |
class aw'.$name.' extends awColor { |
public function __construct($alpha = 0) { |
parent::__construct('.$red.', '.$green.', '.$blue.', $alpha); |
} |
} |
'; |
if(ARTICHOW_PREFIX !== 'aw') { |
$php .= ' |
class '.ARTICHOW_PREFIX.$name.' extends aw'.$name.' { |
} |
'; |
} |
} |
eval($php); |
?> |
/trunk/bibliotheque/artichow/inc/Label.class.php |
---|
New file |
0,0 → 1,588 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Draw labels |
* |
* @package Artichow |
*/ |
class awLabel implements awPositionable { |
/** |
* Label border |
* |
* @var int |
*/ |
public $border; |
/** |
* Label texts |
* |
* @var array |
*/ |
protected $texts; |
/** |
* Text font |
* |
* @var int |
*/ |
protected $font; |
/** |
* Text angle |
* |
* @var int |
*/ |
protected $angle = 0; |
/** |
* Text color |
* |
* @var Color |
*/ |
protected $color; |
/** |
* Text background |
* |
* @var Color, Gradient |
*/ |
private $background; |
/** |
* Callback function |
* |
* @var string |
*/ |
private $function; |
/** |
* Padding |
* |
* @var int |
*/ |
private $padding; |
/** |
* Move position from this vector |
* |
* @var Point |
*/ |
protected $move; |
/** |
* Label interval |
* |
* @var int |
*/ |
protected $interval = 1; |
/** |
* Horizontal align |
* |
* @var int |
*/ |
protected $hAlign = awLabel::CENTER; |
/** |
* Vertical align |
* |
* @var int |
*/ |
protected $vAlign = awLabel::MIDDLE; |
/** |
* Hide all labels ? |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Keys to hide |
* |
* @var array |
*/ |
protected $hideKey = array(); |
/** |
* Values to hide |
* |
* @var array |
*/ |
protected $hideValue = array(); |
/** |
* Hide first label |
* |
* @var bool |
*/ |
protected $hideFirst = FALSE; |
/** |
* Hide last label |
* |
* @var bool |
*/ |
protected $hideLast = FALSE; |
/** |
* Build the label |
* |
* @param string $label First label |
*/ |
public function __construct($label = NULL, $font = NULL, $color = NULL, $angle = 0) { |
if(is_array($label)) { |
$this->set($label); |
} else if(is_string($label)) { |
$this->set(array($label)); |
} |
if($font === NULL) { |
$font = new awFont2; |
} |
$this->setFont($font); |
$this->setAngle($angle); |
if($color instanceof awColor) { |
$this->setColor($color); |
} else { |
$this->setColor(new awColor(0, 0, 0)); |
} |
$this->move = new awPoint(0, 0); |
$this->border = new awBorder; |
$this->border->hide(); |
} |
/** |
* Get an element of the label from its key |
* |
* @param int $key Element key |
* @return string A value |
*/ |
public function get($key) { |
return array_key_exists($key, $this->texts) ? $this->texts[$key] : NULL; |
} |
/** |
* Get all labels |
* |
* @return array |
*/ |
public function all() { |
return $this->texts; |
} |
/** |
* Set one or several labels |
* |
* @param array $labels Array of string or a string |
*/ |
public function set($labels) { |
if(is_array($labels)) { |
$this->texts = $labels; |
} else { |
$this->texts = array((string)$labels); |
} |
} |
/** |
* Count number of texts in the label |
* |
* @return int |
*/ |
public function count() { |
return is_array($this->texts) ? count($this->texts) : 0; |
} |
/** |
* Set a callback function for labels |
* |
* @param string $function |
*/ |
public function setCallbackFunction($function) { |
$this->function = is_null($function) ? $function : (string)$function; |
} |
/** |
* Return the callback function for labels |
* |
* @return string |
*/ |
public function getCallbackFunction() { |
return $this->function; |
} |
/** |
* Change labels format |
* |
* @param string $format New format (printf style: %.2f for example) |
*/ |
public function setFormat($format) { |
$function = 'label'.time().'_'.(microtime() * 1000000); |
eval('function '.$function.'($value) { |
return sprintf("'.addcslashes($format, '"').'", $value); |
}'); |
$this->setCallbackFunction($function); |
} |
/** |
* Change font for label |
* |
* @param awFont $font New font |
* @param awColor $color Font color (can be NULL) |
*/ |
public function setFont(awFont $font, $color = NULL) { |
$this->font = $font; |
if($color instanceof awColor) { |
$this->setColor($color); |
} |
} |
/** |
* Change font angle |
* |
* @param int $angle New angle |
*/ |
public function setAngle($angle) { |
$this->angle = (int)$angle; |
} |
/** |
* Change font color |
* |
* @param awColor $color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
} |
/** |
* Change text background |
* |
* @param mixed $background |
*/ |
public function setBackground($background) { |
$this->background = $background; |
} |
/** |
* Change text background color |
* |
* @param Color |
*/ |
public function setBackgroundColor(awColor $color) { |
$this->background = $color; |
} |
/** |
* Change text background gradient |
* |
* @param Gradient |
*/ |
public function setBackgroundGradient(awGradient $gradient) { |
$this->background = $gradient; |
} |
/** |
* Change padding |
* |
* @param int $left Left padding |
* @param int $right Right padding |
* @param int $top Top padding |
* @param int $bottom Bottom padding |
*/ |
public function setPadding($left, $right, $top, $bottom) { |
$this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom); |
} |
/** |
* Hide all labels ? |
* |
* @param bool $hide |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show all labels ? |
* |
* @param bool $show |
*/ |
public function show($show = TRUE) { |
$this->hide = (bool)!$show; |
} |
/** |
* Hide a key |
* |
* @param int $key The key to hide |
*/ |
public function hideKey($key) { |
$this->hideKey[$key] = TRUE; |
} |
/** |
* Hide a value |
* |
* @param int $value The value to hide |
*/ |
public function hideValue($value) { |
$this->hideValue[] = $value; |
} |
/** |
* Hide first label |
* |
* @param bool $hide |
*/ |
public function hideFirst($hide) { |
$this->hideFirst = (bool)$hide; |
} |
/** |
* Hide last label |
* |
* @param bool $hide |
*/ |
public function hideLast($hide) { |
$this->hideLast = (bool)$hide; |
} |
/** |
* Set label interval |
* |
* @param int |
*/ |
public function setInterval($interval) { |
$this->interval = (int)$interval; |
} |
/** |
* Change label position |
* |
* @param int $x Add this interval to X coord |
* @param int $y Add this interval to Y coord |
*/ |
public function move($x, $y) { |
$this->move = $this->move->move($x, $y); |
} |
/** |
* Change alignment |
* |
* @param int $h Horizontal alignment |
* @param int $v Vertical alignment |
*/ |
public function setAlign($h = NULL, $v = NULL) { |
if($h !== NULL) { |
$this->hAlign = (int)$h; |
} |
if($v !== NULL) { |
$this->vAlign = (int)$v; |
} |
} |
/** |
* Get a text from the labele |
* |
* @param mixed $key Key in the array text |
* @return Text |
*/ |
public function getText($key) { |
if(is_array($this->texts) and array_key_exists($key, $this->texts)) { |
$value = $this->texts[$key]; |
if(is_string($this->function)) { |
$value = call_user_func($this->function, $value); |
} |
$text = new awText($value); |
$text->setFont($this->font); |
$text->setAngle($this->angle); |
$text->setColor($this->color); |
if($this->background instanceof awColor) { |
$text->setBackgroundColor($this->background); |
} else if($this->background instanceof awGradient) { |
$text->setBackgroundGradient($this->background); |
} |
$text->border = $this->border; |
if($this->padding !== NULL) { |
call_user_func_array(array($text, 'setPadding'), $this->padding); |
} |
return $text; |
} else { |
return NULL; |
} |
} |
/** |
* Get max width of all texts |
* |
* @param awDriver $driver A driver |
* @return int |
*/ |
public function getMaxWidth(awDriver $driver) { |
return $this->getMax($driver, 'getTextWidth'); |
} |
/** |
* Get max height of all texts |
* |
* @param awDriver $driver A driver |
* @return int |
*/ |
public function getMaxHeight(awDriver $driver) { |
return $this->getMax($driver, 'getTextHeight'); |
} |
/** |
* Draw the label |
* |
* @param awDriver $driver |
* @param awPoint $p Label center |
* @param int $key Text position in the array of texts (default to zero) |
*/ |
public function draw(awDriver $driver, awPoint $p, $key = 0) { |
if(($key % $this->interval) !== 0) { |
return; |
} |
// Hide all labels |
if($this->hide) { |
return; |
} |
// Key is hidden |
if(array_key_exists($key, $this->hideKey)) { |
return; |
} |
// Hide first label |
if($key === 0 and $this->hideFirst) { |
return; |
} |
// Hide last label |
if($key === count($this->texts) - 1 and $this->hideLast) { |
return; |
} |
$text = $this->getText($key); |
if($text !== NULL) { |
// Value must be hidden |
if(in_array($text->getText(), $this->hideValue)) { |
return; |
} |
$x = $p->x; |
$y = $p->y; |
// Get padding |
list($left, $right, $top, $bottom) = $text->getPadding(); |
// $font = $text->getFont(); |
$width = $driver->getTextWidth($text); |
$height = $driver->getTextHeight($text); |
switch($this->hAlign) { |
case awLabel::RIGHT : |
$x -= ($width + $right); |
break; |
case awLabel::CENTER : |
$x -= ($width - $left + $right) / 2; |
break; |
case awLabel::LEFT : |
$x += $left; |
break; |
} |
switch($this->vAlign) { |
case awLabel::TOP : |
$y -= ($height + $bottom); |
break; |
case awLabel::MIDDLE : |
$y -= ($height - $top + $bottom) / 2; |
break; |
case awLabel::BOTTOM : |
$y += $top; |
break; |
} |
$driver->string($text, $this->move->move($x, $y)); |
} |
} |
protected function getMax(awDriver $driver, $function) { |
$max = NULL; |
foreach($this->texts as $key => $text) { |
$text = $this->getText($key); |
$font = $text->getFont(); |
if(is_null($max)) { |
$max = $font->{$function}($text); |
} else { |
$max = max($max, $font->{$function}($text)); |
} |
} |
return $max; |
} |
} |
registerClass('Label'); |
?> |
/trunk/bibliotheque/artichow/inc/Text.class.php |
---|
New file |
0,0 → 1,233 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* To handle text |
* |
* @package Artichow |
*/ |
class awText { |
/** |
* Your text |
* |
* @var string |
*/ |
private $text; |
/** |
* Text font |
* |
* @var Font |
*/ |
private $font; |
/** |
* Text angle |
* Can be 0 or 90 |
* |
* @var int |
*/ |
private $angle; |
/** |
* Text color |
* |
* @var Color |
*/ |
private $color; |
/** |
* Text background |
* |
* @var Color, Gradient |
*/ |
private $background; |
/** |
* Padding |
* |
* @var array Array for left, right, top and bottom paddings |
*/ |
private $padding; |
/** |
* Text border |
* |
* @var Border |
*/ |
public $border; |
/** |
* Build a new awtext |
* |
* @param string $text Your text |
*/ |
public function __construct($text, $font = NULL, $color = NULL, $angle = 0) { |
if(is_null($font)) { |
$font = new awFont2; |
} |
$this->setText($text); |
$this->setFont($font); |
// Set default color to black |
if($color === NULL) { |
$color = new awColor(0, 0, 0); |
} |
$this->setColor($color); |
$this->setAngle($angle); |
$this->border = new awBorder; |
$this->border->hide(); |
} |
/** |
* Get text |
* |
* @return string |
*/ |
public function getText() { |
return $this->text; |
} |
/** |
* Change text |
* |
* @param string $text New text |
*/ |
public function setText($text) { |
$this->text = (string)$text; |
$this->text = str_replace("\r", "", $text); |
} |
/** |
* Change text font |
* |
* @param Font |
*/ |
public function setFont(awFont $font) { |
$this->font = $font; |
} |
/** |
* Get text font |
* |
* @return int |
*/ |
public function getFont() { |
return $this->font; |
} |
/** |
* Change text angle |
* |
* @param int |
*/ |
public function setAngle($angle) { |
$this->angle = (int)$angle; |
} |
/** |
* Get text angle |
* |
* @return int |
*/ |
public function getAngle() { |
return $this->angle; |
} |
/** |
* Change text color |
* |
* @param Color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
} |
/** |
* Get text color |
* |
* @return Color |
*/ |
public function getColor() { |
return $this->color; |
} |
/** |
* Change text background |
* |
* @param mixed $background |
*/ |
public function setBackground($background) { |
if($background instanceof awColor) { |
$this->setBackgroundColor($background); |
} elseif($background instanceof awGradient) { |
$this->setBackgroundGradient($background); |
} |
} |
/** |
* Change text background color |
* |
* @param awColor $color |
*/ |
public function setBackgroundColor(awColor $color) { |
$this->background = $color; |
} |
/** |
* Change text background gradient |
* |
* @param awGradient $gradient |
*/ |
public function setBackgroundGradient(awGradient $gradient) { |
$this->background = $gradient; |
} |
/** |
* Get text background |
* |
* @return Color, Gradient |
*/ |
public function getBackground() { |
return $this->background; |
} |
/** |
* Change padding |
* |
* @param int $left Left padding |
* @param int $right Right padding |
* @param int $top Top padding |
* @param int $bottom Bottom padding |
*/ |
public function setPadding($left, $right, $top, $bottom) { |
$this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom); |
} |
/** |
* Get current padding |
* |
* @return array |
*/ |
public function getPadding() { |
return $this->padding; |
} |
} |
registerClass('Text'); |
?> |
/trunk/bibliotheque/artichow/inc/drivers/gd.class.php |
---|
New file |
0,0 → 1,1336 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Driver.class.php"; |
/** |
* Draw your objects |
* |
* @package Artichow |
*/ |
class awGDDriver extends Driver { |
/** |
* A GD resource |
* |
* @var $resource |
*/ |
public $resource; |
public function __construct() { |
parent::__construct(); |
$this->driverString = 'gd'; |
} |
public function init(awImage $image) { |
if($this->resource === NULL) { |
$this->setImageSize($image->width, $image->height); |
// Create image |
$this->resource = imagecreatetruecolor($this->imageWidth, $this->imageHeight); |
if(!$this->resource) { |
awImage::drawError("Class Image: Unable to create a graph."); |
} |
imagealphablending($this->resource, TRUE); |
// Antialiasing is now handled by the Driver object |
$this->setAntiAliasing($image->getAntiAliasing()); |
// Original color |
$this->filledRectangle( |
new awWhite, |
new awLine( |
new awPoint(0, 0), |
new awPoint($this->imageWidth, $this->imageHeight) |
) |
); |
$shadow = $image->shadow; |
if($shadow !== NULL) { |
$shadow = $shadow->getSpace(); |
$p1 = new awPoint($shadow->left, $shadow->top); |
$p2 = new awPoint($this->imageWidth - $shadow->right - 1, $this->imageHeight - $shadow->bottom - 1); |
// Draw image background |
$this->filledRectangle($image->getBackground(), new awLine($p1, $p2)); |
// Draw image border |
$image->border->rectangle($this, $p1, $p2); |
} |
} |
} |
public function initFromFile(awFileImage $fileImage, $file) { |
$image = @getimagesize((string)$file); |
if($image and in_array($image[2], array(2, 3))) { |
$fileImage->setSize($image[0], $image[1]); |
switch($image[2]) { |
case 2 : |
$this->resource = imagecreatefromjpeg($file); |
break; |
case 3 : |
$this->resource = imagecreatefrompng($file); |
break; |
} |
$this->setImageSize($fileImage->width, $fileImage->height); |
} else { |
awImage::drawError("Class FileImage: Artichow does not support the format of this image (must be in PNG or JPEG)"); |
} |
} |
public function setImageSize($width, $height) { |
$this->imageWidth = $width; |
$this->imageHeight = $height; |
} |
public function setPosition($x, $y) { |
// Calculate absolute position |
$this->x = round($x * $this->imageWidth - $this->w / 2); |
$this->y = round($y * $this->imageHeight - $this->h / 2); |
} |
public function setAbsPosition($x, $y) { |
$this->x = $x; |
$this->y = $y; |
} |
public function movePosition($x, $y) { |
$this->x += (int)$x; |
$this->y += (int)$y; |
} |
public function setSize($w, $h) { |
// Calcul absolute size |
$this->w = round($w * $this->imageWidth); |
$this->h = round($h * $this->imageHeight); |
return $this->getSize(); |
} |
public function setAbsSize($w, $h) { |
$this->w = $w; |
$this->h = $h; |
return $this->getSize(); |
} |
public function getSize() { |
return array($this->w, $this->h); |
} |
public function setAntiAliasing($bool) { |
if(function_exists('imageantialias')) { |
imageantialias($this->resource, (bool)$bool); |
$this->antiAliasing = (bool)$bool; |
} else { |
awImage::drawErrorFile('missing-anti-aliasing'); |
} |
} |
public function getColor(awColor $color) { |
if($color->alpha === 0 or function_exists('imagecolorallocatealpha') === FALSE) { |
$gdColor = imagecolorallocate($this->resource, $color->red, $color->green, $color->blue); |
} else { |
$gdColor = imagecolorallocatealpha($this->resource, $color->red, $color->green, $color->blue, $color->alpha); |
} |
return $gdColor; |
} |
public function copyImage(awImage $image, awPoint $p1, awPoint $p2) { |
list($x1, $y1) = $p1->getLocation(); |
list($x2, $y2) = $p2->getLocation(); |
$driver = $image->getDriver(); |
imagecopy($this->resource, $driver->resource, $this->x + $x1, $this->y + $y1, 0, 0, $x2 - $x1, $y2 - $y1); |
} |
public function copyResizeImage(awImage $image, awPoint $d1, awPoint $d2, awPoint $s1, awPoint $s2, $resample = TRUE) { |
if($resample) { |
$function = 'imagecopyresampled'; |
} else { |
$function = 'imagecopyresized'; |
} |
$driver = $image->getDriver(); |
$function( |
$this->resource, |
$driver->resource, |
$this->x + $d1->x, $this->y + $d1->y, |
$s1->x, $s1->y, |
$d2->x - $d1->x, $d2->y - $d1->y, |
$s2->x - $s1->x, $s2->y - $s1->y |
); |
} |
public function string(awText $text, awPoint $point, $width = NULL) { |
$font = $text->getFont(); |
// Can we deal with that font? |
if($this->isCompatibleWithFont($font) === FALSE) { |
awImage::drawError('Class GDDriver: Incompatible font type (\''.get_class($font).'\')'); |
} |
// Check which FontDriver to use |
if($font instanceof awPHPFont) { |
$fontDriver = $this->phpFontDriver; |
} else { |
$fontDriver = $this->fileFontDriver; |
} |
if($text->getBackground() !== NULL or $text->border->visible()) { |
list($left, $right, $top, $bottom) = $text->getPadding(); |
$textWidth = $fontDriver->getTextWidth($text, $this); |
$textHeight = $fontDriver->getTextHeight($text, $this); |
$x1 = floor($point->x - $left); |
$y1 = floor($point->y - $top); |
$x2 = $x1 + $textWidth + $left + $right; |
$y2 = $y1 + $textHeight + $top + $bottom; |
$this->filledRectangle( |
$text->getBackground(), |
awLine::build($x1, $y1, $x2, $y2) |
); |
$text->border->rectangle( |
$this, |
new awPoint($x1 - 1, $y1 - 1), |
new awPoint($x2 + 1, $y2 + 1) |
); |
} |
$fontDriver->string($this, $text, $point, $width); |
} |
public function point(awColor $color, awPoint $p) { |
if($p->isHidden() === FALSE) { |
$rgb = $this->getColor($color); |
imagesetpixel($this->resource, $this->x + round($p->x), $this->y + round($p->y), $rgb); |
} |
} |
public function line(awColor $color, awLine $line) { |
if($line->thickness > 0 and $line->isHidden() === FALSE) { |
$rgb = $this->getColor($color); |
$thickness = $line->thickness; |
list($p1, $p2) = $line->getLocation(); |
$this->startThickness($thickness); |
switch($line->getStyle()) { |
case awLine::SOLID : |
imageline($this->resource, $this->x + round($p1->x), $this->y + round($p1->y), $this->x + round($p2->x), $this->y + round($p2->y), $rgb); |
break; |
case awLine::DOTTED : |
$size = sqrt(pow($p2->y - $p1->y, 2) + pow($p2->x - $p1->x, 2)); |
$cos = ($p2->x - $p1->x) / $size; |
$sin = ($p2->y - $p1->y) / $size; |
for($i = 0; $i <= $size; $i += 2) { |
$p = new awPoint( |
round($i * $cos + $p1->x), |
round($i * $sin + $p1->y) |
); |
$this->point($color, $p); |
} |
break; |
case awLine::DASHED : |
$width = $p2->x - $p1->x; |
$height = $p2->y - $p1->y; |
$size = sqrt(pow($height, 2) + pow($width, 2)); |
if($size == 0) { |
return; |
} |
$cos = $width / $size; |
$sin = $height / $size; |
$functionX = ($width > 0) ? 'min' : 'max'; |
$functionY = ($height > 0) ? 'min' : 'max'; |
for($i = 0; $i <= $size; $i += 6) { |
$t1 = new awPoint( |
round($i * $cos + $p1->x), |
round($i * $sin + $p1->y) |
); |
$t2 = new awPoint( |
round($functionX(($i + 3) * $cos, $width) + $p1->x), |
round($functionY(($i + 3) * $sin, $height) + $p1->y) |
); |
$this->line($color, new awLine($t1, $t2)); |
} |
break; |
} |
$this->stopThickness($thickness); |
} |
} |
public function arc(awColor $color, awPoint $center, $width, $height, $from, $to) { |
imagefilledarc( |
$this->resource, |
$this->x + $center->x, $this->y + $center->y, |
$width, $height, |
$from, $to, |
$this->getColor($color), |
IMG_ARC_EDGED | IMG_ARC_NOFILL |
); |
} |
public function filledArc(awColor $color, awPoint $center, $width, $height, $from, $to) { |
imagefilledarc( |
$this->resource, |
$this->x + $center->x, $this->y + $center->y, |
$width, $height, |
$from, $to, |
$this->getColor($color), |
IMG_ARC_PIE |
); |
} |
public function ellipse(awColor $color, awPoint $center, $width, $height) { |
list($x, $y) = $center->getLocation(); |
$rgb = $this->getColor($color); |
imageellipse( |
$this->resource, |
$this->x + $x, |
$this->y + $y, |
$width, |
$height, |
$rgb |
); |
} |
public function filledEllipse($background, awPoint $center, $width, $height) { |
if($background instanceof awColor) { |
list($x, $y) = $center->getLocation(); |
$rgb = $this->getColor($background); |
imagefilledellipse( |
$this->resource, |
$this->x + $x, |
$this->y + $y, |
$width, |
$height, |
$rgb |
); |
} else if($background instanceof awGradient) { |
list($x, $y) = $center->getLocation(); |
$x1 = $x - round($width / 2); |
$y1 = $y - round($height / 2); |
$x2 = $x1 + $width; |
$y2 = $y1 + $height; |
$gradientDriver = new awGDGradientDriver($this); |
$gradientDriver->filledEllipse( |
$background, |
$x1, $y1, |
$x2, $y2 |
); |
} |
} |
public function rectangle(awColor $color, awLine $line) { |
list($p1, $p2) = $line->getLocation(); |
switch($line->getStyle()) { |
case awLine::SOLID : |
$thickness = $line->getThickness(); |
$this->startThickness($thickness); |
$rgb = $this->getColor($color); |
imagerectangle($this->resource, $this->x + $p1->x, $this->y + $p1->y, $this->x + $p2->x, $this->y + $p2->y, $rgb); |
$this->stopThickness($thickness); |
break; |
default : |
$side = clone $line; |
// Top side |
$side->setLocation( |
new awPoint($p1->x, $p1->y), |
new awPoint($p2->x, $p1->y) |
); |
$this->line($color, $side); |
// Right side |
$side->setLocation( |
new awPoint($p2->x, $p1->y), |
new awPoint($p2->x, $p2->y) |
); |
$this->line($color, $side); |
// Bottom side |
$side->setLocation( |
new awPoint($p1->x, $p2->y), |
new awPoint($p2->x, $p2->y) |
); |
$this->line($color, $side); |
// Left side |
$side->setLocation( |
new awPoint($p1->x, $p1->y), |
new awPoint($p1->x, $p2->y) |
); |
$this->line($color, $side); |
break; |
} |
} |
public function filledRectangle($background, awLine $line) { |
$p1 = $line->p1; |
$p2 = $line->p2; |
if($background instanceof awColor) { |
$rgb = $this->getColor($background); |
imagefilledrectangle($this->resource, $this->x + $p1->x, $this->y + $p1->y, $this->x + $p2->x, $this->y + $p2->y, $rgb); |
} else if($background instanceof awGradient) { |
$gradientDriver = new awGDGradientDriver($this); |
$gradientDriver->filledRectangle($background, $p1, $p2); |
} |
} |
public function polygon(awColor $color, awPolygon $polygon) { |
switch($polygon->getStyle()) { |
case awPolygon::SOLID : |
$thickness = $polygon->getThickness(); |
$this->startThickness($thickness); |
$points = $this->getPolygonPoints($polygon); |
$rgb = $this->getColor($color); |
imagepolygon($this->resource, $points, $polygon->count(), $rgb); |
$this->stopThickness($thickness); |
break; |
default : |
if($polygon->count() > 1) { |
$prev = $polygon->get(0); |
$line = new awLine; |
$line->setStyle($polygon->getStyle()); |
$line->setThickness($polygon->getThickness()); |
for($i = 1; $i < $polygon->count(); $i++) { |
$current = $polygon->get($i); |
$line->setLocation($prev, $current); |
$this->line($color, $line); |
$prev = $current; |
} |
// Close the polygon |
$line->setLocation($prev, $polygon->get(0)); |
$this->line($color, $line); |
} |
} |
} |
public function filledPolygon($background, awPolygon $polygon) { |
if($background instanceof awColor) { |
$points = $this->getPolygonPoints($polygon); |
$rgb = $this->getColor($background); |
imagefilledpolygon($this->resource, $points, $polygon->count(), $rgb); |
} else if($background instanceof awGradient) { |
$gradientDriver = new awGDGradientDriver($this); |
$gradientDriver->filledPolygon($background, $polygon); |
} |
} |
public function send(awImage $image) { |
$this->drawImage($image); |
} |
public function get(awImage $image) { |
return $this->drawImage($image, TRUE, FALSE); |
} |
public function getTextWidth(awText $text) { |
$font = $text->getFont(); |
if($font instanceof awPHPFont) { |
$fontDriver = $this->phpFontDriver; |
} else { |
$fontDriver = $this->fileFontDriver; |
} |
return $fontDriver->getTextWidth($text, $this); |
} |
public function getTextHeight(awText $text) { |
$font = $text->getFont(); |
if($font instanceof awPHPFont) { |
$fontDriver = $this->phpFontDriver; |
} else { |
$fontDriver = $this->fileFontDriver; |
} |
return $fontDriver->getTextHeight($text, $this); |
} |
protected function isCompatibleWithFont(awFont $font) { |
if($font instanceof awFDBFont) { |
return FALSE; |
} else { |
return TRUE; |
} |
} |
private function drawImage(awImage $image, $return = FALSE, $header = TRUE) { |
$format = $image->getFormatString(); |
// Test if format is available |
if((imagetypes() & $image->getFormat()) === FALSE) { |
awImage::drawError("Class Image: Format '".$format."' is not available on your system. Check that your PHP has been compiled with the good libraries."); |
} |
// Get some infos about this image |
switch($format) { |
case 'jpeg' : |
$function = 'imagejpeg'; |
break; |
case 'png' : |
$function = 'imagepng'; |
break; |
case 'gif' : |
$function = 'imagegif'; |
break; |
} |
// Send headers to the browser |
if($header === TRUE) { |
$image->sendHeaders(); |
} |
if($return) { |
ob_start(); |
} |
$function($this->resource); |
if($return) { |
return ob_get_clean(); |
} |
} |
private function getPolygonPoints(awPolygon $polygon) { |
$points = array(); |
foreach($polygon->all() as $point) { |
$points[] = $point->x + $this->x; |
$points[] = $point->y + $this->y; |
} |
return $points; |
} |
private function startThickness($thickness) { |
if($thickness > 1) { |
// Beurk :'( |
if($this->antiAliasing and function_exists('imageantialias')) { |
imageantialias($this->resource, FALSE); |
} |
imagesetthickness($this->resource, $thickness); |
} |
} |
private function stopThickness($thickness) { |
if($thickness > 1) { |
if($this->antiAliasing and function_exists('imageantialias')) { |
imageantialias($this->resource, TRUE); |
} |
imagesetthickness($this->resource, 1); |
} |
} |
} |
registerClass('GDDriver'); |
/** |
* To your gradients |
* |
* @package Artichow |
*/ |
class awGDGradientDriver { |
/** |
* A driver |
* |
* @var awGDDriver |
*/ |
protected $driver; |
/** |
* Build your GDGradientDriver |
* |
* @var awGDDriver $driver |
*/ |
public function __construct(awGDDriver $driver) { |
$this->driver = $driver; |
} |
public function drawFilledFlatTriangle(awGradient $gradient, awPoint $a, awPoint $b, awPoint $c) { |
if($gradient->angle !== 0) { |
awImage::drawError("Class GDGradientDriver: Flat triangles can only be used with 0 degree gradients."); |
} |
// Look for right-angled triangle |
if($a->x !== $b->x and $b->x !== $c->x) { |
awImage::drawError("Class GDGradientDriver: Not right-angled flat triangles are not supported yet."); |
} |
if($a->x === $b->x) { |
$d = $a; |
$e = $c; |
} else { |
$d = $c; |
$e = $a; |
} |
$this->init($gradient, $b->y - $d->y); |
for($i = $c->y + 1; $i < $b->y; $i++) { |
$color = $this->color($i - $d->y); |
$pos = ($i - $d->y) / ($b->y - $d->y); |
$p1 = new awPoint($e->x, $i); |
$p2 = new awPoint(1 + floor($e->x - $pos * ($e->x - $d->x)), $i); |
$this->driver->filledRectangle($color, new awLine($p1, $p2)); |
unset($color); |
} |
} |
protected function drawFilledTriangle(awGradient $gradient, awPolygon $polygon) { |
if($gradient->angle === 0) { |
$this->drawFilledTriangleVertically($gradient, $polygon); |
} elseif($gradient->angle === 90) { |
$this->drawFilledTriangleHorizontally($gradient, $polygon); |
} |
} |
private function drawFilledTriangleVertically(awGradient $gradient, awPolygon $polygon) { |
list($yMin, $yMax) = $polygon->getBoxYRange(); |
$this->init($gradient, $yMax - $yMin); |
// Get the triangle line we will draw our lines from |
$fromLine = NULL; |
$lines = $polygon->getLines(); |
$count = count($lines); |
// Pick the side of the triangle going from the top |
// to the bottom of the surrounding box |
for($i = 0; $i < $count; $i++) { |
if($lines[$i]->isTopToBottom($polygon)) { |
list($fromLine) = array_splice($lines, $i, 1); |
break; |
} |
} |
// If for some reason the three points are aligned, |
// $fromLine will still be NULL |
if($fromLine === NULL) { |
return; |
} |
$fillLine = NULL; |
for($y = round($yMin); $y < round($yMax); $y++) { |
$fromX = $fromLine->getXFrom($y); |
$toX = array(); |
foreach($lines as $line) { |
$xValue = $line->getXFrom($y); |
if(!is_null($xValue)) { |
$toX[] = $xValue; |
} |
} |
if(count($toX) === 1) { |
$fillLine = new Line( |
new Point($fromX, $y), |
new Point($toX[0], $y) |
); |
} else { |
$line1 = new Line( |
new Point($fromX, $y), |
new Point($toX[0], $y) |
); |
$line2 = new Line( |
new Point($fromX, $y), |
new Point($toX[1], $y) |
); |
if($line1->getSize() < $line2->getSize()) { |
$fillLine = $line1; |
} else { |
$fillLine = $line2; |
} |
} |
if(!$fillLine->isPoint()) { |
$color = $this->color($y - $yMin); |
$this->driver->line($color, $fillLine); |
unset($color); |
} |
} |
} |
private function drawFilledTriangleHorizontally(awGradient $gradient, awPolygon $polygon) { |
list($xMin, $xMax) = $polygon->getBoxXRange(); |
$this->init($gradient, $xMax - $xMin); |
// Get the triangle line we will draw our lines from |
$fromLine = NULL; |
$lines = $polygon->getLines(); |
$count = count($lines); |
// Pick the side of the triangle going all the way |
// from the left side to the right side of the surrounding box |
for($i = 0; $i < $count; $i++) { |
if($lines[$i]->isLeftToRight($polygon)) { |
list($fromLine) = array_splice($lines, $i, 1); |
break; |
} |
} |
// If for some reason the three points are aligned, |
// $fromLine will still be NULL |
if($fromLine === NULL) { |
return; |
} |
$fillLine = NULL; |
for($x = round($xMin); $x < round($xMax); $x++) { |
$fromY = floor($fromLine->getYFrom($x)); |
$toY = array(); |
foreach($lines as $line) { |
$yValue = $line->getYFrom($x); |
if(!is_null($yValue)) { |
$toY[] = floor($yValue); |
} |
} |
if(count($toY) === 1) { |
$fillLine = new Line( |
new Point($x, $fromY), |
new Point($x, $toY[0]) |
); |
} else { |
$line1 = new Line( |
new Point($x, $fromY), |
new Point($x, $toY[0]) |
); |
$line2 = new Line( |
new Point($x, $fromY), |
new Point($x, $toY[1]) |
); |
if($line1->getSize() < $line2->getSize()) { |
$fillLine = $line1; |
} else { |
$fillLine = $line2; |
} |
} |
$color = $this->color($x - $xMin); |
if($fillLine->isPoint()) { |
$this->driver->point($color, $fillLine->p1); |
} elseif($fillLine->getSize() >= 1) { |
$this->driver->line($color, $fillLine); |
} |
unset($color); |
} |
} |
public function filledRectangle(awGradient $gradient, awPoint $p1, awPoint $p2) { |
list($x1, $y1) = $p1->getLocation(); |
list($x2, $y2) = $p2->getLocation(); |
if($y1 < $y2) { |
$y1 ^= $y2 ^= $y1 ^= $y2; |
} |
if($x2 < $x1) { |
$x1 ^= $x2 ^= $x1 ^= $x2; |
} |
if($gradient instanceof awLinearGradient) { |
$this->rectangleLinearGradient($gradient, new awPoint($x1, $y1), new awPoint($x2, $y2)); |
} else { |
awImage::drawError("Class GDGradientDriver: This gradient is not supported by rectangles."); |
} |
} |
public function filledPolygon(awGradient $gradient, awPolygon $polygon) { |
if($gradient instanceof awLinearGradient) { |
$this->polygonLinearGradient($gradient, $polygon); |
} else { |
awImage::drawError("Class GDGradientDriver: This gradient is not supported by polygons."); |
} |
} |
protected function rectangleLinearGradient(awLinearGradient $gradient, awPoint $p1, awPoint $p2) { |
list($x1, $y1) = $p1->getLocation(); |
list($x2, $y2) = $p2->getLocation(); |
if($y1 - $y2 > 0) { |
if($gradient->angle === 0) { |
$this->init($gradient, $y1 - $y2); |
for($i = $y2; $i <= $y1; $i++) { |
$color = $this->color($i - $y2); |
$p1 = new awPoint($x1, $i); |
$p2 = new awPoint($x2, $i); |
$this->driver->filledRectangle($color, new awLine($p1, $p2)); |
unset($color); |
} |
} else if($gradient->angle === 90) { |
$this->init($gradient, $x2 - $x1); |
for($i = $x1; $i <= $x2; $i++) { |
$color = $this->color($i - $x1); |
$p1 = new awPoint($i, $y2); |
$p2 = new awPoint($i, $y1); |
$this->driver->filledRectangle($color, new awLine($p1, $p2)); |
unset($color); |
} |
} |
} |
} |
public function filledEllipse(awGradient $gradient, $x1, $y1, $x2, $y2) { |
if($y1 < $y2) { |
$y1 ^= $y2 ^= $y1 ^= $y2; |
} |
if($x2 < $x1) { |
$x1 ^= $x2 ^= $x1 ^= $x2; |
} |
if($gradient instanceof awRadialGradient) { |
$this->ellipseRadialGradient($gradient, $x1, $y1, $x2, $y2); |
} else if($gradient instanceof awLinearGradient) { |
$this->ellipseLinearGradient($gradient, $x1, $y1, $x2, $y2); |
} else { |
awImage::drawError("Class GDGradientDriver: This gradient is not supported by ellipses."); |
} |
} |
protected function ellipseRadialGradient(awGradient $gradient, $x1, $y1, $x2, $y2) { |
if($y1 - $y2 > 0) { |
if($y1 - $y2 != $x2 - $x1) { |
awImage::drawError("Class GDGradientDriver: Radial gradients are only implemented on circle, not ellipses."); |
} |
$c = new awPoint($x1 + ($x2 - $x1) / 2, $y1 + ($y2 - $y1) / 2); |
$r = ($x2 - $x1) / 2; |
$ok = array(); |
// Init gradient |
$this->init($gradient, $r); |
for($i = 0; $i <= $r; $i += 0.45) { |
$p = ceil((2 * M_PI * $i)); |
if($p > 0) { |
$interval = 360 / $p; |
} else { |
$interval = 360; |
} |
$color = $this->color($i); |
for($j = 0; $j < 360; $j += $interval) { |
$rad = ($j / 360) * (2 * M_PI); |
$x = round($i * cos($rad)); |
$y = round($i * sin($rad)); |
$l = sqrt($x * $x + $y * $y); |
if($l <= $r) { |
if( |
array_key_exists((int)$x, $ok) === FALSE or |
array_key_exists((int)$y, $ok[$x]) === FALSE |
) { |
// Print the point |
$this->driver->point($color, new awPoint($c->x + $x, $c->y + $y)); |
$ok[(int)$x][(int)$y] = TRUE; |
} |
} |
} |
unset($color); |
} |
} |
} |
protected function ellipseLinearGradient(awGradient $gradient, $x1, $y1, $x2, $y2) { |
// Gauche->droite : 90° |
if($y1 - $y2 > 0) { |
if($y1 - $y2 != $x2 - $x1) { |
awImage::drawError("Class GDGradientDriver: Linear gradients are only implemented on circle, not ellipses."); |
} |
$r = ($x2 - $x1) / 2; |
// Init gradient |
$this->init($gradient, $x2 - $x1); |
for($i = -$r; $i <= $r; $i++) { |
$h = sin(acos($i / $r)) * $r; |
$color = $this->color($i + $r); |
if($gradient->angle === 90) { |
// Print the line |
$p1 = new awPoint( |
$x1 + $i + $r, |
round(max($y2 + $r - $h + 1, $y2)) |
); |
$p2 = new awPoint( |
$x1 + $i + $r, |
round(min($y1 - $r + $h - 1, $y1)) |
); |
} else { |
// Print the line |
$p1 = new awPoint( |
round(max($x1 + $r - $h + 1, $x1)), |
$y2 + $i + $r |
); |
$p2 = new awPoint( |
round(min($x2 - $r + $h - 1, $x2)), |
$y2 + $i + $r |
); |
} |
$this->driver->filledRectangle($color, new awLine($p1, $p2)); |
unset($color); |
} |
} |
} |
protected function polygonLinearGradient(awLinearGradient $gradient, awPolygon $polygon) { |
$count = $polygon->count(); |
if($count >= 4) { |
$left = $polygon->get(0); |
$right = $polygon->get($count - 1); |
if($gradient->angle === 0) { |
// Get polygon maximum and minimum |
$offset = $polygon->get(0); |
$max = $min = $offset->y; |
for($i = 1; $i < $count - 1; $i++) { |
$offset = $polygon->get($i); |
$max = max($max, $offset->y); |
$min = min($min, $offset->y); |
} |
$this->init($gradient, $max - $min); |
$prev = $polygon->get(1); |
$sum = 0; |
for($i = 2; $i < $count - 1; $i++) { |
$current = $polygon->get($i); |
$interval = 1; |
if($i !== $count - 2) { |
$current->x -= $interval; |
} |
if($current->x - $prev->x > 0) { |
// Draw rectangle |
$x1 = $prev->x; |
$x2 = $current->x; |
$y1 = max($prev->y, $current->y); |
$y2 = $left->y; |
$gradient = new awLinearGradient( |
$this->color($max - $min - ($y2 - $y1)), |
$this->color($max - $min), |
0 |
); |
if($y1 > $y2) { |
$y2 = $y1; |
} |
$this->driver->filledRectangle( |
$gradient, |
awLine::build($x1, $y1, $x2, $y2) |
); |
$top = ($prev->y < $current->y) ? $current : $prev; |
$bottom = ($prev->y >= $current->y) ? $current : $prev; |
$gradient = new awLinearGradient( |
$this->color($bottom->y - $min), |
$this->color($max - $min - ($y2 - $y1)), |
0 |
); |
$gradientDriver = new awGDGradientDriver($this->driver); |
$gradientDriver->drawFilledFlatTriangle( |
$gradient, |
new awPoint($prev->x, min($prev->y, $current->y)), |
$top, |
new awPoint($current->x, min($prev->y, $current->y)) |
); |
unset($gradientDriver); |
$sum += $current->x - $prev->x; |
} |
$prev = $current; |
$prev->x += $interval; |
} |
} else if($gradient->angle === 90) { |
$width = $right->x - $left->x; |
$this->init($gradient, $width); |
$pos = 1; |
$next = $polygon->get($pos++); |
$this->next($polygon, $pos, $prev, $next); |
for($i = 0; $i <= $width; $i++) { |
$x = $left->x + $i; |
$y1 = round($prev->y + ($next->y - $prev->y) * (($i + $left->x - $prev->x) / ($next->x - $prev->x))); |
$y2 = $left->y; |
// Draw line |
$color = $this->color($i); |
// YaPB : PHP does not handle alpha on lines |
$this->driver->filledRectangle($color, awLine::build($x, $y1, $x, $y2)); |
unset($color); |
// Jump to next point |
if($next->x == $i + $left->x) { |
$this->next($polygon, $pos, $prev, $next); |
} |
} |
} |
} else if($count === 3) { |
$this->drawFilledTriangle( |
$gradient, |
$polygon |
); |
} |
} |
private function next($polygon, &$pos, &$prev, &$next) { |
do { |
$prev = $next; |
$next = $polygon->get($pos++); |
} |
while($next->x - $prev->x == 0 and $pos < $polygon->count()); |
} |
/** |
* Start colors |
* |
* @var int |
*/ |
private $r1, $g1, $b1, $a1; |
/** |
* Stop colors |
* |
* @var int |
*/ |
private $r2, $g2, $b2, $a2; |
/** |
* Gradient size in pixels |
* |
* @var int |
*/ |
private $size; |
private function init(awGradient $gradient, $size) { |
list( |
$this->r1, $this->g1, $this->b1, $this->a1 |
) = $gradient->from->rgba(); |
list( |
$this->r2, $this->g2, $this->b2, $this->a2 |
) = $gradient->to->rgba(); |
$this->size = $size; |
} |
private function color($pos) { |
return new awColor( |
$this->getRed($pos), |
$this->getGreen($pos), |
$this->getBlue($pos), |
$this->getAlpha($pos) |
); |
} |
private function getRed($pos) { |
if((float)$this->size !== 0.0) { |
return (int)round($this->r1 + ($pos / $this->size) * ($this->r2 - $this->r1)); |
} else { |
return 0; |
} |
} |
private function getGreen($pos) { |
if((float)$this->size !== 0.0) { |
return (int)round($this->g1 + ($pos / $this->size) * ($this->g2 - $this->g1)); |
} else { |
return 0; |
} |
} |
private function getBlue($pos) { |
if((float)$this->size !== 0.0) { |
return (int)round($this->b1 + ($pos / $this->size) * ($this->b2 - $this->b1)); |
} else { |
return 0; |
} |
} |
private function getAlpha($pos) { |
if((float)$this->size !== 0.0) { |
return (int)round(($this->a1 + ($pos / $this->size) * ($this->a2 - $this->a1)) / 127 * 100); |
} else { |
return 0; |
} |
} |
} |
registerClass('GDGradientDriver'); |
/* |
* Check for GD2 |
*/ |
if(function_exists('imagecreatetruecolor') === FALSE) { |
awImage::drawErrorFile('missing-gd2'); |
} |
?> |
/trunk/bibliotheque/artichow/inc/drivers/ming.class.php |
---|
New file |
0,0 → 1,774 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Driver.class.php"; |
/** |
* Draw your objects |
* |
* @package Artichow |
*/ |
class awMingDriver extends awDriver { |
/** |
* The Flash movie |
* |
* @var $movie |
*/ |
public $movie; |
public function __construct() { |
parent::__construct(); |
$this->driverString = 'ming'; |
// Nice defaults |
ming_setScale(20.0); |
ming_useswfversion(6); |
} |
/** |
* Initialize the driver for a particular awImage object |
* |
* @param awImage $image |
*/ |
public function init(awImage $image) { |
if($this->movie === NULL) { |
$this->setImageSize($image->width, $image->height); |
// Create movie |
$this->movie = new SWFMovie(); |
if(!$this->movie) { |
awImage::drawError("Class Image: Unable to create a graph."); |
} |
$this->movie->setDimension($image->width, $image->height); |
$this->setAntiAliasing($image->getAntiAliasing()); |
// Original color |
$this->filledRectangle( |
new awWhite, |
new awLine( |
new awPoint(0, 0), |
new awPoint($this->imageWidth, $this->imageHeight) |
) |
); |
$shadow = $image->shadow; |
if($shadow !== NULL) { |
$shadow = $shadow->getSpace(); |
$p1 = new awPoint($shadow->left, $shadow->top); |
$p2 = new awPoint($this->imageWidth - $shadow->right - 1, $this->imageHeight - $shadow->bottom - 1); |
// Draw image background |
$this->filledRectangle($image->getBackground(), new awLine($p1, $p2)); |
// Draw image border |
$image->border->rectangle($this, $p1, $p2); |
} |
} |
} |
/** |
* Initialize the Driver for a particular FileImage object |
* |
* @param awFileImage $fileImage The FileImage object to work on |
* @param string $file Image filename |
*/ |
public function initFromFile(awFileImage $fileImage, $file) { |
} |
/** |
* Change the image size |
* |
* @param int $width Image width |
* @param int $height Image height |
*/ |
public function setImageSize($width, $height) { |
$this->imageWidth = $width; |
$this->imageHeight = $height; |
} |
/** |
* Inform the driver of the position of your image |
* |
* @param float $x Position on X axis of the center of the component |
* @param float $y Position on Y axis of the center of the component |
*/ |
public function setPosition($x, $y) { |
// Calculate absolute position |
$this->x = round($x * $this->imageWidth - $this->w / 2); |
$this->y = round($y * $this->imageHeight - $this->h / 2); |
} |
/** |
* Inform the driver of the position of your image |
* This method need absolutes values |
* |
* @param int $x Left-top corner X position |
* @param int $y Left-top corner Y position |
*/ |
public function setAbsPosition($x, $y) { |
$this->x = $x; |
$this->y = $y; |
} |
/** |
* Move the position of the image |
* |
* @param int $x Add this value to X axis |
* @param int $y Add this value to Y axis |
*/ |
public function movePosition($x, $y) { |
$this->x += (int)$x; |
$this->y += (int)$y; |
} |
/** |
* Inform the driver of the size of your image |
* Height and width must be between 0 and 1. |
* |
* @param int $w Image width |
* @param int $h Image height |
* @return array Absolute width and height of the image |
*/ |
public function setSize($w, $h) { |
// Calcul absolute size |
$this->w = round($w * $this->imageWidth); |
$this->h = round($h * $this->imageHeight); |
return $this->getSize(); |
} |
/** |
* Inform the driver of the size of your image |
* You can set absolute size with this method. |
* |
* @param int $w Image width |
* @param int $h Image height |
*/ |
public function setAbsSize($w, $h) { |
$this->w = $w; |
$this->h = $h; |
return $this->getSize(); |
} |
/** |
* Get the size of the component handled by the driver |
* |
* @return array Absolute width and height of the component |
*/ |
public function getSize() { |
return array($this->w, $this->h); |
} |
/** |
* Turn antialiasing on or off |
* |
* @var bool $bool |
*/ |
public function setAntiAliasing($bool) { |
if($this->movie !== NULL) { |
$actionscript = ' |
_quality = "%s"; |
'; |
if((bool)$bool) { |
$actionscript = sprintf($actionscript, 'high'); |
} else { |
$actionscript = sprintf($actionscript, 'low'); |
} |
$this->movie->add(new SWFAction(str_replace("\r", "", $actionscript))); |
} |
} |
/** |
* When passed a Color object, returns the corresponding |
* color identifier (driver dependant). |
* |
* @param awColor $color A Color object |
* @return array $rgba A color identifier representing the color composed of the given RGB components |
*/ |
public function getColor(awColor $color) { |
// Ming simply works with R, G, B and Alpha values. |
list($red, $green, $blue, $alpha) = $color->rgba(); |
// However, the Ming alpha channel ranges from 255 (opaque) to 0 (transparent), |
// while the awColor alpha channel ranges from 0 (opaque) to 100 (transparent). |
// First, we convert from 0-100 to 0-255. |
$alpha = (int)($alpha * 255 / 100); |
// Then from 0-255 to 255-0. |
$alpha = abs($alpha - 255); |
return array($red, $green, $blue, $alpha); |
} |
/** |
* Draw an image here |
* |
* @param awImage $image Image |
* @param int $p1 Image top-left point |
* @param int $p2 Image bottom-right point |
*/ |
public function copyImage(awImage $image, awPoint $p1, awPoint $p2) { |
} |
/** |
* Draw an image here |
* |
* @param awImage $image Image |
* @param int $d1 Destination top-left position |
* @param int $d2 Destination bottom-right position |
* @param int $s1 Source top-left position |
* @param int $s2 Source bottom-right position |
* @param bool $resample Resample image ? (default to TRUE) |
*/ |
public function copyResizeImage(awImage $image, awPoint $d1, awPoint $d2, awPoint $s1, awPoint $s2, $resample = TRUE) { |
} |
/** |
* Draw a string |
* |
* @var awText $text Text to print |
* @param awPoint $point Draw the text at this point |
* @param int $width Text max width |
*/ |
public function string(awText $text, awPoint $point, $width = NULL) { |
$font = $text->getFont(); |
// Can we deal with that font? |
if($this->isCompatibleWithFont($font) === FALSE) { |
awImage::drawError('Class MingDriver: Incompatible font type (\''.get_class($font).'\')'); |
} |
// Ming can only work with awFileFont objects for now |
// (i.e. awFDBFont, or awTuffy et al.) |
$fontDriver = $this->fileFontDriver; |
if($text->getBackground() !== NULL or $text->border->visible()) { |
list($left, $right, $top, $bottom) = $text->getPadding(); |
$textWidth = $fontDriver->getTextWidth($text, $this); |
$textHeight = $fontDriver->getTextHeight($text, $this); |
$x1 = floor($point->x - $left); |
$y1 = floor($point->y - $top); |
$x2 = $x1 + $textWidth + $left + $right; |
$y2 = $y1 + $textHeight + $top + $bottom; |
$this->filledRectangle( |
$text->getBackground(), |
awLine::build($x1, $y1, $x2, $y2) |
); |
$text->border->rectangle( |
$this, |
new awPoint($x1 - 1, $y1 - 1), |
new awPoint($x2 + 1, $y2 + 1) |
); |
} |
$fontDriver->string($this, $text, $point, $width); |
} |
/** |
* Draw a pixel |
* |
* @param awColor $color Pixel color |
* @param awPoint $p |
*/ |
public function point(awColor $color, awPoint $p) { |
if($p->isHidden() === FALSE) { |
list($red, $green, $blue, $alpha) = $this->getColor($color); |
$point = new SWFShape(); |
$point->setLine(1, $red, $green, $blue, $alpha); |
$point->movePenTo($this->x + round($p->x), $this->y + round($p->y)); |
$point->drawLine(0.5, 0.5); |
$point->movePen(-0.5, 0); |
$point->drawLine(0.5, -0.5); |
$this->movie->add($point); |
} |
} |
/** |
* Draw a colored line |
* |
* @param awColor $color Line color |
* @param awLine $line |
* @param int $thickness Line tickness |
*/ |
public function line(awColor $color, awLine $line) { |
if($line->getThickness() > 0 and $line->isHidden() === FALSE) { |
list($red, $green, $blue, $alpha) = $this->getColor($color); |
$mingLine = new SWFShape(); |
$mingLine->setLine($line->getThickness(), $red, $green, $blue, $alpha); |
list($p1, $p2) = $line->getLocation(); |
$mingLine->movePenTo($this->x + round($p1->x), $this->y + round($p1->y)); |
switch($line->getStyle()) { |
case awLine::SOLID : |
$mingLine->drawLineTo($this->x + round($p2->x), $this->y + round($p2->y)); |
$this->movie->add($mingLine); |
break; |
case awLine::DOTTED : |
$size = sqrt(pow($p2->y - $p1->y, 2) + pow($p2->x - $p1->x, 2)); |
$cos = ($p2->x - $p1->x) / $size; |
$sin = ($p2->y - $p1->y) / $size; |
for($i = 0; $i <= $size; $i += 2) { |
$p = new awPoint( |
round($i * $cos + $p1->x), |
round($i * $sin + $p1->y) |
); |
$this->point($color, $p); |
} |
break; |
case awLine::DASHED : |
$width = $p2->x - $p1->x; |
$height = $p2->y - $p1->y; |
$size = sqrt(pow($height, 2) + pow($width, 2)); |
if($size == 0) { |
return; |
} |
$cos = $width / $size; |
$sin = $height / $size; |
$functionX = ($width > 0) ? 'min' : 'max'; |
$functionY = ($height > 0) ? 'min' : 'max'; |
for($i = 0; $i <= $size; $i += 6) { |
$t1 = new awPoint( |
round($i * $cos + $p1->x), |
round($i * $sin + $p1->y) |
); |
$t2 = new awPoint( |
round($functionX(($i + 3) * $cos, $width) + $p1->x), |
round($functionY(($i + 3) * $sin, $height) + $p1->y) |
); |
$this->line($color, new awLine($t1, $t2)); |
} |
break; |
} |
} |
} |
/** |
* Draw a color arc |
* @param awColor $color Arc color |
* @param awPoint $center Point center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
* @param int $from Start angle |
* @param int $to End angle |
*/ |
public function arc(awColor $color, awPoint $center, $width, $height, $from, $to) { |
} |
/** |
* Draw an arc with a background color |
* |
* @param awColor $color Arc background color |
* @param awPoint $center Point center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
* @param int $from Start angle |
* @param int $to End angle |
*/ |
public function filledArc(awColor $color, awPoint $center, $width, $height, $from, $to) { |
} |
/** |
* Draw a colored ellipse |
* |
* @param awColor $color Ellipse color |
* @param awPoint $center Ellipse center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
*/ |
public function ellipse(awColor $color, awPoint $center, $width, $height) { |
} |
/** |
* Draw an ellipse with a background |
* |
* @param mixed $background Background (can be a color or a gradient) |
* @param awPoint $center Ellipse center |
* @param int $width Ellipse width |
* @param int $height Ellipse height |
*/ |
public function filledEllipse($background, awPoint $center, $width, $height) { |
} |
/** |
* Draw a colored rectangle |
* |
* @param awColor $color Rectangle color |
* @param awLine $line Rectangle diagonale |
* @param awPoint $p2 |
*/ |
public function rectangle(awColor $color, awLine $line) { |
list($p1, $p2) = $line->getLocation(); |
// Get Red, Green, Blue and Alpha values for the line |
list($r, $g, $b, $a) = $this->getColor($color); |
// Calculate the coordinates of the two other points of the rectangle |
$p3 = new Point($p1->x, $p2->y); |
$p4 = new Point($p2->x, $p1->y); |
$side = clone $line; |
// Draw the four sides of the rectangle, clockwise |
if( |
($p1->x <= $p2->x and $p1->y <= $p2->y) |
or |
($p1->x >= $p2->x and $p1->y >= $p2->y) |
) { |
$side->setLocation($p1, $p4); |
$this->line($color, $side); |
$side->setLocation($p4, $p2); |
$this->line($color, $side); |
$side->setLocation($p2, $p3); |
$this->line($color, $side); |
$side->setLocation($p3, $p1); |
$this->line($color, $side); |
} else { |
$side->setLocation($p1, $p3); |
$this->line($color, $side); |
$side->setLocation($p3, $p2); |
$this->line($color, $side); |
$side->setLocation($p2, $p4); |
$this->line($color, $side); |
$side->setLocation($p4, $p1); |
$this->line($color, $side); |
} |
} |
/** |
* Draw a rectangle with a background |
* |
* @param mixed $background Background (can be a color or a gradient) |
* @param awLine $line Rectangle diagonale |
*/ |
public function filledRectangle($background, awLine $line) { |
list($p1, $p2) = $line->getLocation(); |
// Common shape settings |
$shape = new SWFShape(); |
$shape->setLine(0); |
if($background instanceof awColor) { |
// Get the Red, Green, Blue and Alpha values |
list($r, $g, $b, $a) = $this->getColor($background); |
$shape->setRightFill($r, $g, $b, $a); |
} else if($background instanceof awGradient) { |
// Get the Gradient object as an SWFGradient one |
list($flashGradient, $style) = $this->getGradient($background); |
$fill = $shape->addFill($flashGradient, $style); |
// Angles between Artichow and Ming don't match. |
// Don't use abs() or vertical gradients get inverted. |
$angle = $background->angle - 90; |
$fill->rotateTo($angle); |
// Move the gradient based on the position of the rectangle we're drawing |
$centerX = min($p1->x, $p2->y) + abs($p1->x - $p2->x) / 2; |
$centerY = min($p1->y, $p2->y) + abs($p1->y - $p2->y) / 2; |
$fill->moveTo($centerX, $centerY); |
// Ming draws its gradients on a 1600x1600 image, |
// so we have to resize it. |
if($angle === -90) { |
$ratio = abs($p1->y - $p2->y) / 1600; |
} else { |
$ratio = abs($p1->x - $p2->x) / 1600; |
} |
$fill->scaleTo($ratio); |
$shape->setRightFill($fill); |
} |
// Set starting position |
$shape->movePenTo($this->x + round($p1->x), $this->y + round($p1->y)); |
// Depending on the points' relative positions, |
// we have two drawing possibilities |
if( |
($p1->x <= $p2->x and $p1->y <= $p2->y) |
or |
($p1->x >= $p2->x and $p1->y >= $p2->y) |
) { |
$shape->drawLineTo($this->x + round($p2->x), $this->y + round($p1->y)); |
$shape->drawLineTo($this->x + round($p2->x), $this->y + round($p2->y)); |
$shape->drawLineTo($this->x + round($p1->x), $this->y + round($p2->y)); |
$shape->drawLineTo($this->x + round($p1->x), $this->y + round($p1->y)); |
} else { |
$shape->drawLineTo($this->x + round($p1->x), $this->y + round($p2->y)); |
$shape->drawLineTo($this->x + round($p2->x), $this->y + round($p2->y)); |
$shape->drawLineTo($this->x + round($p2->x), $this->y + round($p1->y)); |
$shape->drawLineTo($this->x + round($p1->x), $this->y + round($p1->y)); |
} |
$this->movie->add($shape); |
} |
/** |
* Draw a polygon |
* |
* @param awColor $color Polygon color |
* @param Polygon A polygon |
*/ |
public function polygon(awColor $color, awPolygon $polygon) { |
$points = $polygon->all(); |
$count = count($points); |
if($count > 1) { |
$side = new awLine; |
$side->setStyle($polygon->getStyle()); |
$side->setThickness($polygon->getThickness()); |
$prev = $points[0]; |
for($i = 1; $i < $count; $i++) { |
$current = $points[$i]; |
$side->setLocation($prev, $current); |
$this->line($color, $side); |
$prev = $current; |
} |
// Close the polygon |
$side->setLocation($prev, $points[0]); |
$this->line($color, $side); |
} |
} |
/** |
* Draw a polygon with a background |
* |
* @param mixed $background Background (can be a color or a gradient) |
* @param Polygon A polygon |
*/ |
public function filledPolygon($background, awPolygon $polygon) { |
$shape = new SWFShape(); |
if($background instanceof awColor) { |
list($red, $green, $blue, $alpha) = $this->getColor($background); |
$shape->setRightFill($red, $green, $blue, $alpha); |
} elseif($background instanceof awGradient) { |
list($flashGradient, $style) = $this->getGradient($background); |
$fill = $shape->addFill($flashGradient, $style); |
list($xMin, $xMax) = $polygon->getBoxXRange(); |
list($yMin, $yMax) = $polygon->getBoxYRange(); |
if($background->angle === 0) { |
$fill->scaleTo(($yMax - $yMin) / 1600); |
} else { |
$fill->scaleTo(($xMax - $xMin) / 1600); |
} |
$fill->moveTo($xMin + ($xMax - $xMin) / 2, $yMin + ($yMax - $yMin) / 2); |
$shape->setRightFill($fill); |
} |
$points = $polygon->all(); |
$count = count($points); |
if($count > 1) { |
$prev = $points[0]; |
$shape->movePenTo($prev->x, $prev->y); |
for($i = 1; $i < $count; $i++) { |
$current = $points[$i]; |
$shape->drawLineTo($current->x, $current->y); |
} |
// Close the polygon |
$shape->drawLineTo($prev->x, $prev->y); |
$this->movie->add($shape); |
} |
} |
/** |
* Sends the image, as well as the correct HTTP headers, to the browser |
* |
* @param awImage $image The Image object to send |
*/ |
public function send(awImage $image) { |
$this->drawImage($image); |
} |
/** |
* Get the image as binary data |
* |
* @param awImage $image |
*/ |
public function get(awImage $image) { |
return $this->drawImage($image, TRUE, FALSE); |
} |
public function getTextWidth(awText $text) { |
$font = $text->getFont(); |
if($this->isCompatibleWithFont($font) === FALSE) { |
awImage::drawError('Class MingDriver: Incompatible font type (\''.get_class($font).'\')'); |
} |
// Ming only supports FileFont |
$fontDriver = $this->fileFontDriver; |
return $fontDriver->getTextWidth($text, $this); |
} |
public function getTextHeight(awText $text) { |
$font = $text->getFont(); |
if($this->isCompatibleWithFont($font) === FALSE) { |
awImage::drawError('Class MingDriver: Incompatible font type (\''.get_class($font).'\')'); |
} |
// Ming only supports FileFont |
$fontDriver = $this->fileFontDriver; |
return $fontDriver->getTextHeight($text, $this); |
} |
protected function isCompatibleWithFont(awFont $font) { |
if($font instanceof awTTFFont or $font instanceof awPHPFont) { |
return FALSE; |
} else { |
return TRUE; |
} |
} |
private function drawImage(awImage $image, $return = FALSE, $header = TRUE) { |
// Send headers to the browser |
if($header === TRUE) { |
$image->sendHeaders(); |
} |
if($return) { |
ob_start(); |
} |
$this->movie->output(); |
if($return) { |
return ob_get_clean(); |
} |
} |
/** |
* Convert an awGradient object to an SWFGradient one. |
* Returns an object as well as the style of the Flash gradient. |
* |
* @param awGradient $gradient The awGradient object to convert |
* @return array |
*/ |
private function getGradient(awGradient $gradient) { |
$flashGradient = new SWFGradient(); |
// Get RGBA values for the gradient boundaries |
list($r1, $g1, $b1, $a1) = $this->getColor($gradient->from); |
list($r2, $g2, $b2, $a2) = $this->getColor($gradient->to); |
$flashGradient->addEntry(0, $r1, $g1, $b1, $a1); |
if($gradient instanceof awBilinearGradient) { |
$flashGradient->addEntry($gradient->center, $r2, $g2, $b2, $a2); |
$flashGradient->addEntry(1, $r1, $g1, $b1, $a1); |
return array($flashGradient, SWFFILL_LINEAR_GRADIENT); |
} else { |
$flashGradient->addEntry(1, $r2, $g2, $b2, $a2); |
if($gradient instanceof awLinearGradient) { |
return array($flashGradient, SWFFILL_LINEAR_GRADIENT); |
} else { |
return array($flashGradient, SWFFILL_RADIAL_GRADIENT); |
} |
} |
} |
// abstract private function getPolygonPoints(awPolygon $polygon); |
} |
registerClass('MingDriver'); |
/* |
* Check for ming presence |
*/ |
if(function_exists('ming_useswfversion') === FALSE) { |
awImage::drawErrorFile('missing-ming'); |
} |
?> |
/trunk/bibliotheque/artichow/inc/Grid.class.php |
---|
New file |
0,0 → 1,291 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Grid |
* |
* @package Artichow |
*/ |
class awGrid { |
/** |
* Vertical lines of the grid |
* |
* @var array |
*/ |
private $xgrid = array(); |
/** |
* Horizontal lines of the grid |
* |
* @var array |
*/ |
private $ygrid = array(); |
/** |
* Is the component grid hidden ? |
* |
* @var bool |
*/ |
private $hide = FALSE; |
/** |
* Are horizontal lines hidden ? |
* |
* @var bool |
*/ |
private $hideHorizontal = FALSE; |
/** |
* Are vertical lines hidden ? |
* |
* @var bool |
*/ |
private $hideVertical = FALSE; |
/** |
* Grid color |
* |
* @var Color |
*/ |
private $color; |
/** |
* Grid space |
* |
* @var int |
*/ |
private $space; |
/** |
* Line type |
* |
* @var int |
*/ |
private $type = awLine::SOLID; |
/** |
* Grid interval |
* |
* @var int |
*/ |
private $interval = array(1, 1); |
/** |
* Grid background color |
* |
* @var Color |
*/ |
private $background; |
/** |
* Build the factory |
*/ |
public function __construct() { |
// Set a grid default color |
$this->color = new awColor(210, 210, 210); |
$this->background = new awColor(255, 255, 255, 100); |
} |
/** |
* Hide grid ? |
* |
* @param bool $hide |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Hide horizontal lines ? |
* |
* @param bool $hideHorizontal |
*/ |
public function hideHorizontal($hide = TRUE) { |
$this->hideHorizontal = (bool)$hide; |
} |
/** |
* Hide vertical lines ? |
* |
* @param bool $hideVertical |
*/ |
public function hideVertical($hide = TRUE) { |
$this->hideVertical = (bool)$hide; |
} |
/** |
* Change grid color |
* |
* @param awColor $color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
} |
/** |
* Remove grid background |
*/ |
public function setNoBackground() { |
$this->background = NULL; |
} |
/** |
* Change grid background color |
* |
* @param awColor $color |
*/ |
public function setBackgroundColor(awColor $color) { |
$this->background = $color; |
} |
/** |
* Change line type |
* |
* @param int $type |
*/ |
public function setType($type) { |
$this->type = (int)$type; |
} |
/** |
* Change grid interval |
* |
* @param int $hInterval |
* @param int $vInterval |
*/ |
public function setInterval($hInterval, $vInterval) { |
$this->interval = array((int)$hInterval, (int)$vInterval); |
} |
/** |
* Set grid space |
* |
* @param int $left Left space in pixels |
* @param int $right Right space in pixels |
* @param int $top Top space in pixels |
* @param int $bottom Bottom space in pixels |
*/ |
public function setSpace($left, $right, $top, $bottom) { |
$this->space = array((int)$left, (int)$right, (int)$top, (int)$bottom); |
} |
/** |
* Change the current grid |
* |
* @param array $xgrid Vertical lines |
* @param array $ygrid Horizontal lines |
*/ |
public function setGrid($xgrid, $ygrid) { |
if(empty($this->xgrid)) { |
$this->xgrid = $xgrid; |
} |
if(empty($this->ygrid)) { |
$this->ygrid = $ygrid; |
} |
} |
/** |
* Draw grids |
* |
* @param awDriver $driver A driver object |
* @param int $x1 |
* @param int $y1 |
* @param int $x2 |
* @param int $y2 |
*/ |
public function draw(awDriver $driver, $x1, $y1, $x2, $y2) { |
if($this->background instanceof awColor) { |
// Draw background color |
$driver->filledRectangle( |
$this->background, |
awLine::build($x1, $y1, $x2, $y2) |
); |
} |
if($this->hide === FALSE) { |
$this->drawGrid( |
$driver, |
$this->color, |
$this->hideVertical ? array() : $this->xgrid, |
$this->hideHorizontal ? array() : $this->ygrid, |
$x1, $y1, $x2, $y2, |
$this->type, |
$this->space, |
$this->interval[0], |
$this->interval[1] |
); |
} |
} |
private function drawGrid( |
awDriver $driver, awColor $color, |
$nx, $ny, $x1, $y1, $x2, $y2, |
$type, $space, $hInterval, $vInterval |
) { |
list($left, $right, $top, $bottom) = $space; |
$width = $x2 - $x1 - $left - $right; |
$height = $y2 - $y1 - $top - $bottom; |
foreach($nx as $key => $n) { |
if(($key % $vInterval) === 0) { |
$pos = (int)round($x1 + $left + $n * $width); |
$driver->line( |
$color, |
new awLine( |
new awPoint($pos, $y1), |
new awPoint($pos, $y2), |
$type |
) |
); |
} |
} |
foreach($ny as $key => $n) { |
if(($key % $hInterval) === 0) { |
$pos = (int)round($y1 + $top + $n * $height); |
$driver->line( |
$color, |
new awLine( |
new awPoint($x1, $pos), |
new awPoint($x2, $pos), |
$type |
) |
); |
} |
} |
} |
} |
registerClass('Grid'); |
?> |
/trunk/bibliotheque/artichow/inc/Shadow.class.php |
---|
New file |
0,0 → 1,406 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
/** |
* Draw shadows |
* |
*/ |
class awShadow { |
/** |
* Shadow on left and top sides |
* |
* @var int |
*/ |
const LEFT_TOP = 1; |
/** |
* Shadow on left and bottom sides |
* |
* @var int |
*/ |
const LEFT_BOTTOM = 2; |
/** |
* Shadow on right and top sides |
* |
* @var int |
*/ |
const RIGHT_TOP = 3; |
/** |
* Shadow on right and bottom sides |
* |
* @var int |
*/ |
const RIGHT_BOTTOM = 4; |
/** |
* In mode |
* |
* @var int |
*/ |
const IN = 1; |
/** |
* Out mode |
* |
* @var int |
*/ |
const OUT = 2; |
/** |
* Shadow size |
* |
* @var int |
*/ |
private $size = 0; |
/** |
* Hide shadow ? |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Shadow color |
* |
* @var Color |
*/ |
private $color; |
/** |
* Shadow position |
* |
* @var int |
*/ |
private $position; |
/** |
* Smooth shadow ? |
* |
* @var bool |
*/ |
private $smooth = FALSE; |
/** |
* Shadow constructor |
* |
* @param int $position Shadow position |
*/ |
public function __construct($position) { |
$this->setPosition($position); |
} |
/** |
* Hide shadow ? |
* |
* @param bool $hide |
*/ |
public function hide($hide = TRUE) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show shadow ? |
* |
* @param bool $show |
*/ |
public function show($show = TRUE) { |
$this->hide = (bool)!$show; |
} |
/** |
* Change shadow size |
* |
* @param int $size |
* @param bool $smooth Smooth the shadow (facultative argument) |
*/ |
public function setSize($size, $smooth = NULL) { |
$this->size = (int)$size; |
if($smooth !== NULL) { |
$this->smooth($smooth); |
} |
} |
/** |
* Change shadow color |
* |
* @param awColor $color |
*/ |
public function setColor(awColor $color) { |
$this->color = $color; |
} |
/** |
* Change shadow position |
* |
* @param int $position |
*/ |
public function setPosition($position) { |
$this->position = (int)$position; |
} |
/** |
* Smooth shadow ? |
* |
* @param bool $smooth |
*/ |
public function smooth($smooth) { |
$this->smooth = (bool)$smooth; |
} |
/** |
* Get the space taken by the shadow |
* |
* @return Side |
*/ |
public function getSpace() { |
return new awSide( |
($this->position === awShadow::LEFT_TOP or $this->position === awShadow::LEFT_BOTTOM) ? $this->size : 0, |
($this->position === awShadow::RIGHT_TOP or $this->position === awShadow::RIGHT_BOTTOM) ? $this->size : 0, |
($this->position === awShadow::LEFT_TOP or $this->position === awShadow::RIGHT_TOP) ? $this->size : 0, |
($this->position === awShadow::LEFT_BOTTOM or $this->position === awShadow::RIGHT_BOTTOM) ? $this->size : 0 |
); |
} |
/** |
* Draw shadow |
* |
* @param awDriver $driver |
* @param awPoint $p1 Top-left point |
* @param awPoint $p2 Right-bottom point |
* @param int Drawing mode |
*/ |
public function draw(awDriver $driver, awPoint $p1, awPoint $p2, $mode) { |
if($this->hide) { |
return; |
} |
if($this->size <= 0) { |
return; |
} |
$driver = clone $driver; |
$color = ($this->color instanceof awColor) ? $this->color : new awColor(125, 125, 125); |
switch($this->position) { |
case awShadow::RIGHT_BOTTOM : |
if($mode === awShadow::OUT) { |
$t1 = $p1->move(0, 0); |
$t2 = $p2->move($this->size + 1, $this->size + 1); |
} else { // PHP 4 compatibility |
$t1 = $p1->move(0, 0); |
$t2 = $p2->move(0, 0); |
} |
$width = $t2->x - $t1->x; |
$height = $t2->y - $t1->y; |
$driver->setAbsPosition($t1->x + $driver->x, $t1->y + $driver->y); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint($width - $this->size, $this->size), |
new awPoint($width - 1, $height - 1) |
) |
); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint($this->size, $height - $this->size), |
new awPoint($width - $this->size - 1, $height - 1) |
) |
); |
$this->smoothPast($driver, $color, $width, $height); |
break; |
case awShadow::LEFT_TOP : |
if($mode === awShadow::OUT) { |
$t1 = $p1->move(- $this->size, - $this->size); |
$t2 = $p2->move(0, 0); |
} else { // PHP 4 compatibility |
$t1 = $p1->move(0, 0); |
$t2 = $p2->move(0, 0); |
} |
$width = $t2->x - $t1->x; |
$height = $t2->y - $t1->y; |
$driver->setAbsPosition($t1->x + $driver->x, $t1->y + $driver->y); |
$height = max($height + 1, $this->size); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint(0, 0), |
new awPoint($this->size - 1, $height - $this->size - 1) |
) |
); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint($this->size, 0), |
new awPoint($width - $this->size - 1, $this->size - 1) |
) |
); |
$this->smoothPast($driver, $color, $width, $height); |
break; |
case awShadow::RIGHT_TOP : |
if($mode === awShadow::OUT) { |
$t1 = $p1->move(0, - $this->size); |
$t2 = $p2->move($this->size + 1, 0); |
} else { // PHP 4 compatibility |
$t1 = $p1->move(0, 0); |
$t2 = $p2->move(0, 0); |
} |
$width = $t2->x - $t1->x; |
$height = $t2->y - $t1->y; |
$driver->setAbsPosition($t1->x + $driver->x, $t1->y + $driver->y); |
$height = max($height + 1, $this->size); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint($width - $this->size, 0), |
new awPoint($width - 1, $height - $this->size - 1) |
) |
); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint($this->size, 0), |
new awPoint($width - $this->size - 1, $this->size - 1) |
) |
); |
$this->smoothFuture($driver, $color, $width, $height); |
break; |
case awShadow::LEFT_BOTTOM : |
if($mode === awShadow::OUT) { |
$t1 = $p1->move(- $this->size, 0); |
$t2 = $p2->move(0, $this->size + 1); |
} else { // PHP 4 compatibility |
$t1 = $p1->move(0, 0); |
$t2 = $p2->move(0, 0); |
} |
$width = $t2->x - $t1->x; |
$height = $t2->y - $t1->y; |
$driver->setAbsPosition($t1->x + $driver->x, $t1->y + $driver->y); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint(0, $this->size), |
new awPoint($this->size - 1, $height - 1) |
) |
); |
$driver->filledRectangle( |
$color, |
new awLine( |
new awPoint($this->size, $height - $this->size), |
new awPoint($width - $this->size - 1, $height - 1) |
) |
); |
$this->smoothFuture($driver, $color, $width, $height); |
break; |
} |
} |
private function smoothPast(awDriver $driver, awColor $color, $width, $height) { |
if($this->smooth) { |
for($i = 0; $i < $this->size; $i++) { |
for($j = 0; $j <= $i; $j++) { |
$driver->point( |
$color, |
new awPoint($i, $j + $height - $this->size) |
); |
} |
} |
for($i = 0; $i < $this->size; $i++) { |
for($j = 0; $j <= $i; $j++) { |
$driver->point( |
$color, |
new awPoint($width - $this->size + $j, $i) |
); |
} |
} |
} |
} |
private function smoothFuture(awDriver $driver, awColor $color, $width, $height) { |
if($this->smooth) { |
for($i = 0; $i < $this->size; $i++) { |
for($j = 0; $j <= $i; $j++) { |
$driver->point( |
$color, |
new awPoint($i, $this->size - $j - 1) |
); |
} |
} |
for($i = 0; $i < $this->size; $i++) { |
for($j = 0; $j <= $i; $j++) { |
$driver->point( |
$color, |
new awPoint($width - $this->size + $j, $height - $i - 1) |
); |
} |
} |
} |
} |
} |
registerClass('Shadow'); |
?> |
/trunk/bibliotheque/artichow/inc/Math.class.php |
---|
New file |
0,0 → 1,832 |
<?php |
/* |
* This work is hereby released into the Public Domain. |
* To view a copy of the public domain dedication, |
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
* |
*/ |
require_once dirname(__FILE__)."/../Graph.class.php"; |
abstract class awShape { |
/** |
* Is the shape hidden ? |
* |
* @var bool |
*/ |
protected $hide = FALSE; |
/** |
* Shape style |
* |
* @var int |
*/ |
public $style; |
/** |
* Shape thickness |
* |
* @var int |
*/ |
public $thickness; |
/** |
* Solid shape |
* |
* @var int |
*/ |
const SOLID = 1; |
/** |
* Dotted shape |
* |
* @var int |
*/ |
const DOTTED = 2; |
/** |
* Dashed shape |
* |
* @var int |
*/ |
const DASHED = 3; |
/** |
* Change shape style |
* |
* @param int $style Line style |
*/ |
public function setStyle($style) { |
$this->style = (int)$style; |
} |
/** |
* Return shape style |
* |
* @return int |
*/ |
public function getStyle() { |
return $this->style; |
} |
/** |
* Change shape thickness |
* |
* @param int $thickness Shape thickness in pixels |
*/ |
public function setThickness($thickness) { |
$this->thickness = (int)$thickness; |
} |
/** |
* Return shape thickness |
* |
* @return int |
*/ |
public function getThickness() { |
return $this->thickness; |
} |
/** |
* Hide the shape |
* |
* @param bool $hide |
*/ |
public function hide($hide) { |
$this->hide = (bool)$hide; |
} |
/** |
* Show the shape |
* |
* @param bool $shape |
*/ |
public function show($shape) { |
$this->hide = (bool)!$shape; |
} |
/** |
* Is the line hidden ? |
* |
* @return bool |
*/ |
public function isHidden() { |
return $this->hide; |
} |
} |
registerClass('Shape', TRUE); |
/** |
* Describe a point |
* |
* @package Artichow |
*/ |
class awPoint extends awShape { |
/** |
* X coord |
* |
* @var float |
*/ |
public $x; |
/** |
* Y coord |
* |
* @var float |
*/ |
public $y; |
/** |
* Build a new awpoint |
* |
* @param float $x |
* @param float $y |
*/ |
public function __construct($x, $y) { |
$this->setLocation($x, $y); |
} |
/** |
* Change X value |
* |
* @param float $x |
*/ |
public function setX($x) { |
$this->x = (float)$x; |
} |
/** |
* Change Y value |
* |
* @param float $y |
*/ |
public function setY($y) { |
$this->y = (float)$y; |
} |
/** |
* Change point location |
* |
* @param float $x |
* @param float $y |
*/ |
public function setLocation($x, $y) { |
$this->setX($x); |
$this->setY($y); |
} |
/** |
* Get point location |
* |
* @param array Point location |
*/ |
public function getLocation() { |
return array($this->x, $this->y); |
} |
/** |
* Get distance to another point |
* |
* @param awPoint $p A point |
* @return float |
*/ |
public function getDistance(awPoint $p) { |
return sqrt(pow($p->x - $this->x, 2) + pow($p->y - $this->y, 2)); |
} |
/** |
* Move the point to another location |
* |
* @param Point A Point with the new awlocation |
*/ |
public function move($x, $y) { |
return new awPoint( |
$this->x + $x, |
$this->y + $y |
); |
} |
} |
registerClass('Point'); |
/** |
* Describe a line |
* |
* @package Artichow |
*/ |
class awLine extends awShape { |
/** |
* Line first point |
* |
* @param Point |
*/ |
public $p1; |
/** |
* Line second point |
* |
* @param Point |
*/ |
public $p2; |
/** |
* The line slope (the m in y = mx + p) |
* |
* @param float |
*/ |
private $slope; |
/** |
* The y-intercept value of the line (the p in y = mx + p) |
* |
* @param float |
*/ |
private $origin; |
/** |
* Build a new awline |
* |
* @param awPoint $p1 First point |
* @param awPoint $p2 Second point |
* @param int $type Style of line (default to solid) |
* @param int $thickness Line thickness (default to 1) |
*/ |
public function __construct($p1 = NULL, $p2 = NULL, $type = awLine::SOLID, $thickness = 1) { |
$this->setLocation($p1, $p2); |
$this->setStyle($type); |
$this->setThickness($thickness); |
} |
/** |
* Build a line from 4 coords |
* |
* @param int $x1 Left position |
* @param int $y1 Top position |
* @param int $x2 Right position |
* @param int $y2 Bottom position |
*/ |
public static function build($x1, $y1, $x2, $y2) { |
return new awLine( |
new awPoint($x1, $y1), |
new awPoint($x2, $y2) |
); |
} |
/** |
* Change X values of the line |
* |
* @param int $x1 Begin value |
* @param int $x2 End value |
*/ |
public function setX($x1, $x2) { |
$this->p1->setX($x1); |
$this->p2->setX($x2); |
// Resets slope and origin values so they are |
// recalculated when and if needed. |
$this->slope = NULL; |
$this->origin = NULL; |
} |
/** |
* Change Y values of the line |
* |
* @param int $y1 Begin value |
* @param int $y2 End value |
*/ |
public function setY($y1, $y2) { |
$this->p1->setY($y1); |
$this->p2->setY($y2); |
// Resets slope and origin values so they are |
// recalculated when and if needed. |
$this->slope = NULL; |
$this->origin = NULL; |
} |
/** |
* Change line location |
* |
* @param awPoint $p1 First point |
* @param awPoint $p2 Second point |
*/ |
public function setLocation($p1, $p2) { |
if(is_null($p1) or $p1 instanceof awPoint) { |
$this->p1 = $p1; |
} |
if(is_null($p2) or $p2 instanceof awPoint) { |
$this->p2 = $p2; |
} |
// Resets slope and origin values so they are |
// recalculated when and if needed. |
$this->slope = NULL; |
$this->origin = NULL; |
} |
/** |
* Get line location |
* |
* @param array Line location |
*/ |
public function getLocation() { |
return array($this->p1, $this->p2); |
} |
/** |
* Get the line size |
* |
* @return float |
*/ |
public function getSize() { |
$square = pow($this->p2->x - $this->p1->x, 2) + pow($this->p2->y - $this->p1->y, 2); |
return sqrt($square); |
} |
/** |
* Calculate the line slope |
* |
*/ |
private function calculateSlope() { |
if($this->isHorizontal()) { |
$this->slope = 0; |
} else { |
$slope = ($this->p1->y - $this->p2->y) / ($this->p1->x - $this->p2->x); |
$this->slope = $slope; |
} |
} |
/** |
* Calculate the y-intercept value of the line |
* |
*/ |
private function calculateOrigin() { |
if($this->isHorizontal()) { |
$this->origin = $this->p1->y; // Or p2->y |
} else { |
$y1 = $this->p1->y; |
$y2 = $this->p2->y; |
$x1 = $this->p1->x; |
$x2 = $this->p2->x; |
$origin = ($y2 * $x1 - $y1 * $x2) / ($x1 - $x2); |
$this->origin = $origin; |
} |
} |
/** |
* Calculate the slope and y-intercept value of the line |
* |
*/ |
private function calculateEquation() { |
$this->calculateSlope(); |
$this->calculateOrigin(); |
} |
/** |
* Get the line slope value |
* |
* @return float |
*/ |
public function getSlope() { |
if($this->isVertical()) { |
return NULL; |
} elseif($this->slope !== NULL) { |
return $this->slope; |
} else { |
$this->calculateSlope(); |
return $this->slope; |
} |
} |
/** |
* Get the line y-intercept value |
* |
* @return float |
*/ |
public function getOrigin() { |
if($this->isVertical()) { |
return NULL; |
} elseif($this->origin !== NULL) { |
return $this->origin; |
} else { |
$this->calculateOrigin(); |
return $this->origin; |
} |
} |
/** |
* Get the line equation |
* |
* @return array An array containing the slope and y-intercept value of the line |
*/ |
public function getEquation() { |
$slope = $this->getSlope(); |
$origin = $this->getOrigin(); |
return array($slope, $origin); |
} |
/** |
* Return the x coordinate of a point on the line |
* given its y coordinate. |
* |
* @param float $y The y coordinate of the Point |
* @return float $x The corresponding x coordinate |
*/ |
public function getXFrom($y) { |
$x = NULL; |
if($this->isVertical()) { |
list($p, ) = $this->getLocation(); |
$x = $p->x; |
} else { |
list($slope, $origin) = $this->getEquation(); |
if($slope !== 0) { |
$y = (float)$y; |
$x = ($y - $origin) / $slope; |
} |
} |
return $x; |
} |
/** |
* Return the y coordinate of a point on the line |
* given its x coordinate. |
* |
* @param float $x The x coordinate of the Point |
* @return float $y The corresponding y coordinate |
*/ |
public function getYFrom($x) { |
$y = NULL; |
if($this->isHorizontal()) { |
list($p, ) = $this->getLocation(); |
$y = $p->y; |
} else { |
list($slope, $origin) = $this->getEquation(); |
if($slope !== NULL) { |
$x = (float)$x; |
$y = $slope * $x + $origin; |
} |
} |
return $y; |
} |
/** |
* Test if the line can be considered as a point |
* |
* @return bool |
*/ |
public function isPoint() { |
return ($this->p1->x === $this->p2->x and $this->p1->y === $this->p2->y); |
} |
/** |
* Test if the line is a vertical line |
* |
* @return bool |
*/ |
public function isVertical() { |
return ($this->p1->x === $this->p2->x); |
} |
/** |
* Test if the line is an horizontal line |
* |
* @return bool |
*/ |
public function isHorizontal() { |
return ($this->p1->y === $this->p2->y); |
} |
/** |
* Returns TRUE if the line is going all the way from the top |
* to the bottom of the polygon surrounding box. |
* |
* @param $polygon Polygon A Polygon object |
* @return bool |
*/ |
public function isTopToBottom(awPolygon $polygon) { |
list($xMin, $xMax) = $polygon->getBoxXRange(); |
list($yMin, $yMax) = $polygon->getBoxYRange(); |
if($this->isHorizontal()) { |
return FALSE; |
} else { |
if($this->p1->y < $this->p2->y) { |
$top = $this->p1; |
$bottom = $this->p2; |
} else { |
$top = $this->p2; |
$bottom = $this->p1; |
} |
return ( |
$this->isOnBoxTopSide($top, $xMin, $xMax, $yMin) |
and |
$this->isOnBoxBottomSide($bottom, $xMin, $xMax, $yMax) |
); |
} |
} |
/** |
* Returns TRUE if the line is going all the way from the left side |
* to the right side of the polygon surrounding box. |
* |
* @param $polygon Polygon A Polygon object |
* @return bool |
*/ |
public function isLeftToRight(awPolygon $polygon) { |
list($xMin, $xMax) = $polygon->getBoxXRange(); |
list($yMin, $yMax) = $polygon->getBoxYRange(); |
if($this->isVertical()) { |
return FALSE; |
} else { |
if($this->p1->x < $this->p2->x) { |
$left = $this->p1; |
$right = $this->p2; |
} else { |
$left = $this->p2; |
$right = $this->p1; |
} |
} |
return ( |
$this->isOnBoxLeftSide($left, $yMin, $yMax, $xMin) |
and |
$this->isOnBoxRightSide($right, $yMin, $yMax, $xMax) |
); |
} |
private function isOnBoxTopSide(awPoint $point, $xMin, $xMax, $yMin) { |
if( |
$point->y === $yMin |
and |
$point->x >= $xMin |
and |
$point->x <= $xMax |
) { |
return TRUE; |
} else { |
return FALSE; |
} |
} |
private function isOnBoxBottomSide(awPoint $point, $xMin, $xMax, $yMax) { |
if( |
$point->y === $yMax |
and |
$point->x >= $xMin |
and |
$point->x <= $xMax |
) { |
return TRUE; |
} else { |
return FALSE; |
} |
} |
private function isOnBoxLeftSide(awPoint $point, $yMin, $yMax, $xMin) { |
if( |
$point->x === $xMin |
and |
$point->y >= $yMin |
and |
$point->y <= $yMax |
) { |
return TRUE; |
} else { |
return FALSE; |
} |
} |
private function isOnBoxRightSide(awPoint $point, $yMin, $yMax, $xMax) { |
if( |
$point->x === $xMax |
and |
$point->y >= $yMin |
and |
$point->y <= $yMax |
) { |
return TRUE; |
} else { |
return FALSE; |
} |
} |
} |
registerClass('Line'); |
/** |
* A vector is a type of line |
* The sense of the vector goes from $p1 to $p2. |
* |
* @package Artichow |
*/ |
class awVector extends awLine { |
/** |
* Get vector angle in radians |
* |
* @return float |
*/ |
public function getAngle() { |
if($this->isPoint()) { |
return 0.0; |
} |
$size = $this->getSize(); |
$width = ($this->p2->x - $this->p1->x); |
$height = ($this->p2->y - $this->p1->y) * -1; |
if($width >= 0 and $height >= 0) { |
return acos($width / $size); |
} else if($width <= 0 and $height >= 0) { |
return acos($width / $size); |
} else { |
$height *= -1; |
if($width >= 0 and $height >= 0) { |
return 2 * M_PI - acos($width / $size); |
} else if($width <= 0 and $height >= 0) { |
return 2 * M_PI - acos($width / $size); |
} |
} |
} |
} |
registerClass('Vector'); |
/** |
* Describe a polygon |
* |
* @package Artichow |
*/ |
class awPolygon extends awShape { |
/** |
* Polygon points |
* |
* @var array |
*/ |
protected $points = array(); |
/** |
* Set a point in the polygon |
* |
* @param int $pos Point position |
* @param awPoint $point |
*/ |
public function set($pos, $point) { |
if(is_null($point) or $point instanceof awPoint) { |
$this->points[$pos] = $point; |
} |
} |
/** |
* Add a point at the end of the polygon |
* |
* @param awPoint $point |
*/ |
public function append($point) { |
if(is_null($point) or $point instanceof awPoint) { |
$this->points[] = $point; |
} |
} |
/** |
* Get a point at a position in the polygon |
* |
* @param int $pos Point position |
* @return Point |
*/ |
public function get($pos) { |
return $this->points[$pos]; |
} |
/** |
* Count number of points in the polygon |
* |
* @return int |
*/ |
public function count() { |
return count($this->points); |
} |
/** |
* Returns all points in the polygon |
* |
* @return array |
*/ |
public function all() { |
return $this->points; |
} |
/** |
* Returns the different lines formed by the polygon vertices |
* |
* @return array |
*/ |
public function getLines() { |
$lines = array(); |
$count = $this->count(); |
for($i = 0; $i < $count - 1; $i++) { |
$lines[] = new Line($this->get($i), $this->get($i + 1)); |
} |
// "Close" the polygon |
$lines[] = new Line($this->get($count - 1), $this->get(0)); |
return $lines; |
} |
/** |
* Get the upper-left and lower-right points |
* of the bounding box around the polygon |
* |
* @return array An array of two Point objects |
*/ |
public function getBoxPoints() { |
$count = $this->count(); |
$x = $y = array(); |
for($i = 0; $i < $count; $i++) { |
$point = $this->get($i); |
list($x[], $y[]) = $point->getLocation(); |
} |
$upperLeft = new Point(min($x), min($y)); |
$lowerRight = new Point(max($x), max($y)); |
return array($upperLeft, $lowerRight); |
} |
/** |
* Return the range of the polygon on the y axis, |
* i.e. the minimum and maximum y value of any point in the polygon |
* |
* @return array |
*/ |
public function getBoxYRange() { |
list($p1, $p2) = $this->getBoxPoints(); |
list(, $yMin) = $p1->getLocation(); |
list(, $yMax) = $p2->getLocation(); |
return array($yMin, $yMax); |
} |
/** |
* Return the range of the polygon on the x axis, |
* i.e. the minimum and maximum x value of any point in the polygon |
* |
* @return array |
*/ |
public function getBoxXRange() { |
list($p1, $p2) = $this->getBoxPoints(); |
list($xMin, ) = $p1->getLocation(); |
list($xMax, ) = $p2->getLocation(); |
return array($xMin, $xMax); |
} |
} |
registerClass('Polygon'); |
?> |