diff --git a/external-libs/Artichow/Artichow.cfg.php b/external-libs/Artichow/Artichow.cfg.php
new file mode 100644
index 00000000000..4a8790b1b72
--- /dev/null
+++ b/external-libs/Artichow/Artichow.cfg.php
@@ -0,0 +1,79 @@
+
\ No newline at end of file
diff --git a/external-libs/Artichow/BarPlot.class.php b/external-libs/Artichow/BarPlot.class.php
new file mode 100644
index 00000000000..812c4c548f1
--- /dev/null
+++ b/external-libs/Artichow/BarPlot.class.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/external-libs/Artichow/Graph.class.php b/external-libs/Artichow/Graph.class.php
new file mode 100644
index 00000000000..e665e0f7fb3
--- /dev/null
+++ b/external-libs/Artichow/Graph.class.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/external-libs/Artichow/Image.class.php b/external-libs/Artichow/Image.class.php
new file mode 100644
index 00000000000..065db04e0fc
--- /dev/null
+++ b/external-libs/Artichow/Image.class.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/external-libs/Artichow/Pie.class.php b/external-libs/Artichow/Pie.class.php
new file mode 100644
index 00000000000..ec81bed4aff
--- /dev/null
+++ b/external-libs/Artichow/Pie.class.php
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/AntiSpam.class.php b/external-libs/Artichow/php4/AntiSpam.class.php
new file mode 100644
index 00000000000..f104ffbb475
--- /dev/null
+++ b/external-libs/Artichow/php4/AntiSpam.class.php
@@ -0,0 +1,217 @@
+string = (string)$string;
+
+ }
+
+ /**
+ * Create a random string
+ *
+ * @param int $length String length
+ * @return string String created
+ */
+ function setRand($length) {
+
+ $length = (int)$length;
+
+ $this->string = '';
+
+ $letters = 'aAbBCDeEFgGhHJKLmMnNpPqQRsStTuVwWXYZz2345679';
+ $number = strlen($letters);
+
+ for($i = 0; $i < $length; $i++) {
+ $this->string .= $letters{mt_rand(0, $number - 1)};
+ }
+
+ return $this->string;
+
+ }
+
+ /**
+ * Set noise on image
+ *
+ * @param int $nois Noise intensity (from 0 to 10)
+ */
+ function setNoise($noise) {
+ if($noise < 0) {
+ $noise = 0;
+ }
+ if($noise > 10) {
+ $noise = 10;
+ }
+ $this->noise = (int)$noise;
+ }
+
+ /**
+ * Save string value in session
+ * You can use check() to verify the value later
+ *
+ * @param string $qName A name that identify the anti-spam image
+ */
+ function save($qName) {
+ $this->session();
+ $session = 'artichow_'.(string)$qName;
+ $_SESSION[$session] = $this->string;
+ }
+
+ /**
+ * Verify user entry
+ *
+ * @param string $qName A name that identify the anti-spam image
+ * @param string $value User-defined value
+ * @param bool $case TRUE for case insensitive check, FALSE for case sensitive check ? (default to TRUE)
+ * @return bool TRUE if the value is correct, FALSE otherwise
+ */
+ function check($qName, $value, $case = TRUE) {
+
+ $this->session();
+
+ $session = 'artichow_'.(string)$qName;
+
+ return (
+ array_key_exists($session, $_SESSION) === TRUE and
+ $case ?
+ (strtolower($_SESSION[$session]) === strtolower((string)$value)) :
+ ($_SESSION[$session] === (string)$value)
+ );
+
+ }
+
+ /**
+ * Draw image
+ */
+ function draw() {
+
+ $fonts = array(
+ ARTICHOW_FONT.DIRECTORY_SEPARATOR.'Tuffy.ttf',
+ ARTICHOW_FONT.DIRECTORY_SEPARATOR.'TuffyBold.ttf',
+ ARTICHOW_FONT.DIRECTORY_SEPARATOR.'TuffyItalic.ttf',
+ ARTICHOW_FONT.DIRECTORY_SEPARATOR.'TuffyBoldItalic.ttf'
+ );
+
+ $sizes = array(12, 12.5, 13, 13.5, 14, 15, 16, 17, 18, 19);
+
+ $widths = array();
+ $heights = array();
+ $texts = array();
+
+ for($i = 0; $i < strlen($this->string); $i++) {
+
+ $fontKey = array_rand($fonts);
+ $sizeKey = array_rand($sizes);
+
+ $font = new awTTFFont(
+ $fonts[$fontKey], $sizes[$sizeKey]
+ );
+
+ $text = new awText(
+ $this->string{$i},
+ $font,
+ NULL,
+ mt_rand(-15, 15)
+ );
+
+ $widths[] = $font->getTextWidth($text);
+ $heights[] = $font->getTextHeight($text);
+ $texts[] = $text;
+
+ }
+
+ $width = array_sum($widths);
+ $height = array_max($heights);
+
+ $totalWidth = $width + 10 + count($texts) * 10;
+ $totalHeight = $height + 20;
+
+ $this->setSize($totalWidth, $totalHeight);
+
+ $this->create();
+
+ for($i = 0; $i < strlen($this->string); $i++) {
+
+ $this->drawer->string(
+ $texts[$i],
+ new awPoint(
+ 5 + array_sum(array_slice($widths, 0, $i)) + $widths[$i] / 2 + $i * 10,
+ 10 + ($height - $heights[$i]) / 2
+ )
+ );
+
+ }
+
+ $this->drawNoise($totalWidth, $totalHeight);
+
+ $this->send();
+
+ }
+
+ function drawNoise($width, $height) {
+
+ $points = $this->noise * 30;
+ $color = new awColor(0, 0, 0);
+
+ for($i = 0; $i < $points; $i++) {
+ $this->drawer->point(
+ $color,
+ new awPoint(
+ mt_rand(0, $width),
+ mt_rand(0, $height)
+ )
+ );
+ }
+
+ }
+
+ function session() {
+
+ // Start session if needed
+ if(!session_id()) {
+ session_start();
+ }
+
+ }
+
+}
+
+registerClass('AntiSpam');
+?>
diff --git a/external-libs/Artichow/php4/BarPlot.class.php b/external-libs/Artichow/php4/BarPlot.class.php
new file mode 100644
index 00000000000..38cb51f201d
--- /dev/null
+++ b/external-libs/Artichow/php4/BarPlot.class.php
@@ -0,0 +1,364 @@
+label = new awLabel;
+
+ $this->barPadding = new awSide(0.08, 0.08, 0, 0);
+ $this->barShadow = new awShadow(SHADOW_RIGHT_TOP);
+ $this->barBorder = new awBorder;
+
+ $this->setValues($values);
+
+ $this->identifier = (int)$identifier;
+ $this->number = (int)$number;
+ $this->depth = (int)$depth;
+
+ $this->move = new awSide;
+
+ // Hide vertical grid
+ $this->grid->hideVertical(TRUE);
+
+ }
+
+ /**
+ * Change bars padding
+ * This method is not compatible with awBarPlot::setBarPadding()
+ *
+ * @param float $left Left padding (between 0 and 1)
+ * @param float $right Right padding (between 0 and 1)
+ */
+ function setBarPadding($left = NULL, $right = NULL) {
+ $this->barPadding->set($left, $right);
+ }
+
+ /**
+ * Change bars size
+ * This method is not compatible with awBarPlot::setBarPadding()
+ *
+ * @param int $width Bars size (between 0 and 1)
+ */
+ function setBarSize($size) {
+ $padding = (1 - $size) / 2;
+ $this->barPadding->set($padding, $padding);
+ }
+
+ /**
+ * Move bars
+ *
+ * @param int $x
+ * @param int $y
+ */
+ function move($x, $y) {
+ $this->move->set($x, NULL, $y, NULL);
+ }
+
+ /**
+ * Change bars space
+ *
+ * @param int $space Space in pixels
+ */
+ function setBarSpace($space) {
+ $this->barSpace = (int)$space;
+ }
+
+ /**
+ * Change line background color
+ *
+ * @param $color
+ */
+ function setBarColor($color) {
+ $this->barBackground = $color;
+ }
+
+ /**
+ * Change line background gradient
+ *
+ * @param $gradient
+ */
+ function setBarGradient($gradient) {
+ $this->barBackground = $gradient;
+ }
+
+ /**
+ * Get the line thickness
+ *
+ * @return int
+ */
+ function getLegendLineThickness() {
+ }
+
+ /**
+ * Get the line type
+ *
+ * @return int
+ */
+ function getLegendLineStyle() {
+ }
+
+ /**
+ * Get the color of line
+ *
+ * @return Color
+ */
+ function getLegendLineColor() {
+ }
+
+ /**
+ * Get the background color or gradient of an element of the component
+ *
+ * @return Color, Gradient
+ */
+ function getLegendBackground() {
+ return $this->barBackground;
+ }
+
+ /**
+ * Get a mark object
+ *
+ * @return Mark
+ */
+ function getLegendMark() {
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ $count = count($this->datay);
+ $max = $this->getRealYMax(NULL);
+ $min = $this->getRealYMin(NULL);
+
+ // Find zero for bars
+ if($this->xAxisZero and $min <= 0 and $max >= 0) {
+ $zero = 0;
+ } else if($max < 0) {
+ $zero = $max;
+ } else {
+ $zero = $min;
+ }
+
+ // Get base position
+ $zero = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint(0, $zero));
+
+ // Distance between two values on the graph
+ $distance = $this->xAxis->getDistance(0, 1);
+
+ // Compute paddings
+ $leftPadding = $this->barPadding->left * $distance;
+ $rightPadding = $this->barPadding->right * $distance;
+
+ $padding = $leftPadding + $rightPadding;
+ $space = $this->barSpace * ($this->number - 1);
+
+ $barSize = ($distance - $padding - $space) / $this->number;
+ $barPosition = $leftPadding + $barSize * ($this->identifier - 1);
+
+ for($key = 0; $key < $count; $key++) {
+
+ $value = $this->datay[$key];
+
+ if($value !== NULL) {
+
+ $position = awAxis::toPosition(
+ $this->xAxis,
+ $this->yAxis,
+ new awPoint($key, $value)
+ );
+
+ $barStart = $barPosition + ($this->identifier - 1) * $this->barSpace + $position->x;
+ $barStop = $barStart + $barSize;
+
+ $t1 = min($zero->y, $position->y);
+ $t2 = max($zero->y, $position->y);
+
+ if(round($t2 - $t1) == 0) {
+ continue;
+ }
+
+ $p1 = new awPoint(
+ round($barStart) + $this->depth + $this->move->left,
+ round($t1) - $this->depth + $this->move->top
+ );
+
+ $p2 = new awPoint(
+ round($barStop) + $this->depth + $this->move->left,
+ round($t2) - $this->depth + $this->move->top
+ );
+
+ $this->drawBar($drawer, $p1, $p2);
+
+ }
+
+ }
+
+ // Draw labels
+ foreach($this->datay as $key => $value) {
+
+ if($value !== NULL) {
+
+ $position = awAxis::toPosition(
+ $this->xAxis,
+ $this->yAxis,
+ new awPoint($key, $value)
+ );
+
+ $point = new awPoint(
+ $barPosition + ($this->identifier - 1) * $this->barSpace + $position->x + $barSize / 2 + 1 + $this->depth,
+ $position->y - $this->depth
+ );
+
+ $this->label->draw($drawer, $point, $key);
+
+ }
+
+ }
+
+ }
+
+ function getXAxisNumber() {
+ return count($this->datay) + 1;
+ }
+ // ça bidouille à fond ici !
+ function getXMax() {
+ return array_max($this->datax) + 1;
+ }
+
+ function getXCenter() {
+ return TRUE;
+ }
+
+ function drawBar($drawer, $p1, $p2) {
+
+ // Draw shadow
+ $this->barShadow->draw(
+ $drawer,
+ $p1,
+ $p2,
+ SHADOW_OUT
+ );
+
+ if(abs($p2->y - $p1->y) > 1) {
+
+ $this->barBorder->rectangle(
+ $drawer,
+ $p1,
+ $p2
+ );
+
+ if($this->barBackground !== NULL) {
+
+ $size = $this->barBorder->visible() ? 1 : 0;
+
+ $b1 = $p1->move($size, $size);
+ $b2 = $p2->move(-1 * $size, -1 * $size);
+
+ // Draw background
+ $drawer->filledRectangle(
+ $this->barBackground,
+ new awLine($b1, $b2)
+ );
+
+ }
+
+ }
+ }
+
+}
+
+registerClass('BarPlot');
+?>
diff --git a/external-libs/Artichow/php4/Component.class.php b/external-libs/Artichow/php4/Component.class.php
new file mode 100644
index 00000000000..4c7e36b5ac9
--- /dev/null
+++ b/external-libs/Artichow/php4/Component.class.php
@@ -0,0 +1,415 @@
+components = array();
+ }
+
+ /**
+ * Add a component to the group
+ *
+ * @param &$component A component
+ */
+ function add(&$component) {
+ $this->components[] = $component;
+ }
+
+}
+
+registerClass('ComponentGroup', TRUE);
+
+ class awComponent {
+
+ /**
+ * Component drawer
+ *
+ * @var Drawer
+ */
+ var $drawer;
+
+ /**
+ * Component width
+ *
+ * @var float
+ */
+ var $width = 1.0;
+
+ /**
+ * Component height
+ *
+ * @var float
+ */
+ var $height = 1.0;
+
+ /**
+ * Position X of the center the graph (from 0 to 1)
+ *
+ * @var float
+ */
+ var $x = 0.5;
+
+ /**
+ * Position Y of the center the graph (from 0 to 1)
+ *
+ * @var float
+ */
+ var $y = 0.5;
+
+ /**
+ * Component absolute width (in pixels)
+ *
+ *
+ * @var int
+ */
+ var $w;
+
+ /**
+ * Component absolute height (in pixels)
+ *
+ *
+ * @var int
+ */
+ var $h;
+
+ /**
+ * Left-top corner Y position
+ *
+ * @var float
+ */
+ var $top;
+
+ /**
+ * Left-top corner X position
+ *
+ * @var float
+ */
+ var $left;
+
+ /**
+ * Component background color
+ *
+ * @var Color
+ */
+ var $background;
+
+ /**
+ * Component padding
+ *
+ * @var Side
+ */
+ var $padding;
+
+ /**
+ * Component space
+ *
+ * @var Side
+ */
+ var $space;
+
+ /**
+ * Component title
+ *
+ * @var Label
+ */
+ var $title;
+
+ /**
+ * Adjust automatically the component ?
+ *
+ * @var bool
+ */
+ var $auto = TRUE;
+
+ /**
+ * Legend
+ *
+ * @var Legend
+ */
+ var $legend;
+
+ /**
+ * Build the component
+ */
+ function awComponent() {
+
+ // Component legend
+ $this->legend = new awLegend();
+
+ $this->padding = new awSide(25, 25, 25, 25);
+ $this->space = new awSide(0, 0, 0, 0);
+
+ // Component title
+ $this->title = new awLabel(
+ NULL,
+ new awTuffy(10),
+ NULL,
+ 0
+ );
+ $this->title->setAlign(LABEL_CENTER, LABEL_TOP);
+
+ }
+
+ /**
+ * Adjust automatically the component ?
+ *
+ * @param bool $auto
+ */
+ function auto($auto) {
+ $this->auto = (bool)$auto;
+ }
+
+ /**
+ * Change the size of the component
+ *
+ * @param int $width Component width (from 0 to 1)
+ * @param int $height Component height (from 0 to 1)
+ */
+ function setSize($width, $height) {
+
+ $this->width = (float)$width;
+ $this->height = (float)$height;
+
+ }
+
+ /**
+ * Change the absolute size of the component
+ *
+ * @param int $w Component width (in pixels)
+ * @param int $h Component height (in pixels)
+ */
+ function setAbsSize($w, $h) {
+
+ $this->w = (int)$w;
+ $this->h = (int)$h;
+
+ }
+
+ /**
+ * Change component background color
+ *
+ * @param $color (can be null)
+ */
+ function setBackgroundColor($color) {
+ if($color === NULL or is_a($color, 'awColor')) {
+ $this->background = $color;
+ }
+ }
+
+ /**
+ * Change component background gradient
+ *
+ * @param $gradient (can be null)
+ */
+ function setBackgroundGradient($gradient) {
+ if($gradient === NULL or is_a($gradient, 'awGradient')) {
+ $this->background = $gradient;
+ }
+ }
+
+ /**
+ * Change component background image
+ *
+ * @param &$image (can be null)
+ */
+ function setBackgroundImage($image) {
+ if($image === NULL or is_a($image, 'awImage')) {
+ $this->background = $image;
+ }
+ }
+
+ /**
+ * Return the component background
+ *
+ * @return Color, Gradient
+ */
+ function getBackground() {
+ return $this->background;
+ }
+
+ /**
+ * Change component padding
+ *
+ * @param int $left Padding in pixels (NULL to keep old value)
+ * @param int $right Padding in pixels (NULL to keep old value)
+ * @param int $top Padding in pixels (NULL to keep old value)
+ * @param int $bottom Padding in pixels (NULL to keep old value)
+ */
+ function setPadding($left = NULL, $right = NULL, $top = NULL, $bottom = NULL) {
+ $this->padding->set($left, $right, $top, $bottom);
+ }
+
+ /**
+ * Change component space
+ *
+ * @param float $left Space in % (NULL to keep old value)
+ * @param float $right Space in % (NULL to keep old value)
+ * @param float $bottom Space in % (NULL to keep old value)
+ * @param float $top Space in % (NULL to keep old value)
+ */
+ function setSpace($left = NULL, $right = NULL, $bottom = NULL, $top = NULL) {
+ $this->space->set($left, $right, $bottom, $top);
+ }
+
+ /**
+ * Change the absolute position of the component on the graph
+ *
+ * @var int $x Left-top corner X position
+ * @var int $y Left-top corner Y position
+ */
+ function setAbsPosition($left, $top) {
+
+ $this->left = (int)$left;
+ $this->top = (int)$top;
+
+ }
+
+ /**
+ * Set the center of the component
+ *
+ * @param int $x Position on X axis of the center of the component
+ * @param int $y Position on Y axis of the center of the component
+ */
+ function setCenter($x, $y) {
+
+ $this->x = (float)$x;
+ $this->y = (float)$y;
+
+ }
+
+ /**
+ * Get component coords with its padding
+ *
+ * @return array Coords of the component
+ */
+ function getPosition() {
+
+ // Get component coords
+ $x1 = $this->padding->left;
+ $y1 = $this->padding->top;
+ $x2 = $this->w - $this->padding->right;
+ $y2 = $this->h - $this->padding->bottom;
+
+ return array($x1, $y1, $x2, $y2);
+
+ }
+
+ /**
+ * Init the drawing of the component
+ */
+ function init($drawer) {
+
+ // Set component background
+ $background = $this->getBackground();
+
+ if($background !== NULL) {
+
+ $p1 = new awPoint(0, 0);
+ $p2 = new awPoint($this->w - 1, $this->h - 1);
+
+ if(is_a($background, 'awImage')) {
+
+ $drawer->copyImage(
+ $background,
+ $p1,
+ $p2
+ );
+
+ } else {
+
+ $drawer->filledRectangle(
+ $background,
+ new awLine($p1, $p2)
+ );
+
+ }
+
+ }
+ }
+
+ /**
+ * Finalize the drawing of the component
+ */
+ function finalize($drawer) {
+
+ // Draw component title
+ $point = new awPoint(
+ $this->w / 2,
+ $this->padding->top - 8
+ );
+ $this->title->draw($drawer, $point);
+
+ // Draw legend
+ $this->legend->draw($drawer);
+
+ }
+
+ /**
+ * Draw the grid around your component
+ *
+ * @param Drawer A drawer
+ * @return array Coords for the component
+ */
+
+
+ /**
+ * Draw the component on the graph
+ * Component should be drawed into specified coords
+ *
+ * @param Drawer A drawer
+ * @param int $x1
+ * @param int $y1
+ * @param int $x2
+ * @param int $y2
+ * @param bool $aliasing Use anti-aliasing to draw the component ?
+ */
+
+
+ /**
+ * Get space width in pixels
+ *
+ * @param int $width Component width
+ * @param int $height Component height
+ * @return array
+ */
+ function getSpace($width, $height) {
+
+ $left = (int)($width * $this->space->left / 100);
+ $right = (int)($width * $this->space->right / 100);
+ $top = (int)($height * $this->space->top / 100);
+ $bottom = (int)($height * $this->space->bottom / 100);
+
+ return array($left, $right, $top, $bottom);
+
+ }
+
+}
+
+registerClass('Component', TRUE);
+?>
diff --git a/external-libs/Artichow/php4/Graph.class.php b/external-libs/Artichow/php4/Graph.class.php
new file mode 100644
index 00000000000..47f5b5f55dc
--- /dev/null
+++ b/external-libs/Artichow/php4/Graph.class.php
@@ -0,0 +1,389 @@
+setSize($width, $height);
+
+ if(ARTICHOW_CACHE) {
+
+ $this->name = $name;
+ $this->timeout = $timeout;
+
+ // Clean sometimes all the cache
+ if(mt_rand(0, 5000) === 0) {
+ awGraph::cleanCache();
+ }
+
+ if($this->name !== NULL) {
+
+ $file = ARTICHOW_CACHE_DIRECTORY."/".$this->name."-time";
+
+ if(is_file($file)) {
+
+ $type = awGraph::cleanGraphCache($file);
+
+ if($type === NULL) {
+ awGraph::deleteFromCache($this->name);
+ } else {
+ header("Content-Type: image/".$type);
+ readfile(ARTICHOW_CACHE_DIRECTORY."/".$this->name."");
+ exit;
+ }
+
+ }
+
+ }
+
+ }
+
+ $this->title = new awLabel(
+ NULL,
+ new awTuffy(16),
+ NULL,
+ 0
+ );
+ $this->title->setAlign(LABEL_CENTER, LABEL_BOTTOM);
+
+ }
+
+ /**
+ * Delete a graph from the cache
+ *
+ * @param string $name Graph name
+ * @return bool TRUE on success, FALSE on failure
+ */
+ function deleteFromCache($name) {
+
+ if(ARTICHOW_CACHE) {
+
+ if(is_file(ARTICHOW_CACHE_DIRECTORY."/".$name."-time")) {
+ unlink(ARTICHOW_CACHE_DIRECTORY."/".$name."");
+ unlink(ARTICHOW_CACHE_DIRECTORY."/".$name."-time");
+ }
+
+ }
+
+ }
+
+ /**
+ * Delete all graphs from the cache
+ */
+ function deleteAllCache() {
+
+ if(ARTICHOW_CACHE) {
+
+ $dp = opendir(ARTICHOW_CACHE_DIRECTORY);
+
+ while($file = readdir($dp)) {
+ if($file !== '.' and $file != '..') {
+ unlink(ARTICHOW_CACHE_DIRECTORY."/".$file);
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Clean cache
+ */
+ function cleanCache() {
+
+ if(ARTICHOW_CACHE) {
+
+ $glob = glob(ARTICHOW_CACHE_DIRECTORY."/*-time");
+
+ foreach($glob as $file) {
+
+ $type = awGraph::cleanGraphCache($file);
+
+ if($type === NULL) {
+ $name = ereg_replace(".*/(.*)\-time", "\\1", $file);
+ awGraph::deleteFromCache($name);
+ }
+
+ }
+
+ }
+
+ }
+
+ /**
+ * Enable/Disable Graph timing
+ *
+ * @param bool $timing
+ */
+ function setTiming($timing) {
+ $this->timing = (bool)$timing;
+ }
+
+ /**
+ * Add a component to the graph
+ *
+ * @param &$component
+ */
+ function add(&$component) {
+
+ $this->components[] = $component;
+
+ }
+
+ /**
+ * Add a label to the component
+ *
+ * @param &$label
+ * @param int $x Position on X axis of the center of the text
+ * @param int $y Position on Y axis of the center of the text
+ */
+ function addLabel(&$label, $x, $y) {
+
+ $this->labels[] = array(
+ $label, $x, $y
+ );
+
+ }
+
+ /**
+ * Add a label to the component with aboslute position
+ *
+ * @param &$label
+ * @param $point Text position
+ */
+ function addAbsLabel(&$label, $point) {
+
+ $this->labels[] = array(
+ $label, $point
+ );
+
+ }
+
+ /**
+ * Build the graph and draw component on it
+ * Image is sent to the user browser
+ *
+ * @param string $file Save the image in the specified file. Let it null to print image to screen.
+ */
+ function draw($file = NULL) {
+
+ if($this->timing) {
+ $time = microtimeFloat();
+ }
+
+ $this->create();
+
+ foreach($this->components as $component) {
+
+ $this->drawComponent($component);
+
+ }
+
+ $this->drawTitle();
+ $this->drawShadow();
+ $this->drawLabels();
+
+ if($this->timing) {
+ $this->drawTiming(microtimeFloat() - $time);
+ }
+
+ if(ARTICHOW_CACHE and $this->name !== NULL) {
+ ob_start();
+ }
+
+ $this->send($file);
+
+ if(ARTICHOW_CACHE and $this->name !== NULL) {
+
+ $data = ob_get_contents();
+
+ if(is_writable(ARTICHOW_CACHE_DIRECTORY) === FALSE) {
+ trigger_error("Cache directory is not writable");
+ }
+
+ $file = ARTICHOW_CACHE_DIRECTORY."/".$this->name."";
+ file_put_contents($file, $data);
+
+ $file .= "-time";
+ file_put_contents($file, $this->timeout."\n".$this->getFormat());
+
+ ob_clean();
+
+ echo $data;
+
+ }
+
+ }
+
+ function drawLabels() {
+
+ $drawer = $this->getDrawer();
+
+ foreach($this->labels as $array) {
+
+ if(count($array) === 3) {
+
+ // Text in relative position
+ list($label, $x, $y) = $array;
+
+ $point = new awPoint(
+ $x * $this->width,
+ $y * $this->height
+ );
+
+ } else {
+
+ // Text in absolute position
+ list($label, $point) = $array;
+
+ }
+
+ $label->draw($drawer, $point);
+
+ }
+
+ }
+
+ function drawTitle() {
+
+ $drawer = $this->getDrawer();
+
+ $point = new awPoint(
+ $this->width / 2,
+ 10
+ );
+
+ $this->title->draw($drawer, $point);
+
+ }
+
+ function drawTiming($time) {
+
+ $drawer = $this->getDrawer();
+
+ $label = new awLabel;
+ $label->set("(".sprintf("%.3f", $time)." s)");
+ $label->setAlign(LABEL_LEFT, LABEL_TOP);
+ $label->border->show();
+ $label->setPadding(1, 0, 0, 0);
+ $label->setBackgroundColor(new awColor(230, 230, 230, 25));
+
+ $label->draw($drawer, new awPoint(5, $drawer->height - 5));
+
+ }
+
+ function cleanGraphCache($file) {
+
+ list(
+ $time,
+ $type
+ ) = explode("\n", file_get_contents($file));
+
+ $time = (int)$time;
+
+ if($time !== 0 and $time < time()) {
+ return NULL;
+ } else {
+ return $type;
+ }
+
+
+ }
+
+}
+
+registerClass('Graph');
+
+/*
+ * To preserve PHP 4 compatibility
+ */
+function microtimeFloat() {
+ list($usec, $sec) = explode(" ", microtime());
+ return (float)$usec + (float)$sec;
+}
+?>
diff --git a/external-libs/Artichow/php4/Image.class.php b/external-libs/Artichow/php4/Image.class.php
new file mode 100644
index 00000000000..86b2e93df6f
--- /dev/null
+++ b/external-libs/Artichow/php4/Image.class.php
@@ -0,0 +1,421 @@
+ */
+
+define("IMAGE_JPEG", 1);
+define("IMAGE_PNG", 2);
+define("IMAGE_GIF", 3);
+
+/* */
+
+/*
+ * Check for GD2
+ */
+if(function_exists('imagecreatetruecolor') === FALSE) {
+ trigger_error("You must compile PHP with GD2 support to use Artichow", E_USER_ERROR);
+}
+
+require_once ARTICHOW."/inc/Shadow.class.php";
+require_once ARTICHOW."/inc/Border.class.php";
+
+/**
+ * An image for a graph
+ *
+ * @package Artichow
+ */
+class awImage {
+
+ /**
+ * Graph width
+ *
+ * @var int
+ */
+ var $width;
+
+ /**
+ * Graph height
+ *
+ * @var int
+ */
+ var $height;
+
+ /**
+ * Use anti-aliasing ?
+ *
+ * @var bool
+ */
+ var $antiAliasing = FALSE;
+
+ /**
+ * Image format
+ *
+ * @var int
+ */
+ var $format = IMAGE_PNG;
+
+ /**
+ * Image background color
+ *
+ * @var Color
+ */
+ var $background;
+
+ /**
+ * GD resource
+ *
+ * @var resource
+ */
+ var $resource;
+
+ /**
+ * Image drawer
+ *
+ * @var Drawer
+ */
+ var $drawer;
+
+ /**
+ * Shadow
+ *
+ * @var Shadow
+ */
+ var $shadow;
+
+ /**
+ * Image border
+ *
+ * @var Border
+ */
+ var $border;
+
+ /**
+ * Use JPEG for image
+ *
+ * @var int
+ */
+
+
+ /**
+ * Use PNG for image
+ *
+ * @var int
+ */
+
+
+ /**
+ * Use GIF for image
+ *
+ * @var int
+ */
+
+
+ /**
+ * Build the image
+ */
+ function awImage() {
+
+ $this->background = new awColor(255, 255, 255);
+ $this->shadow = new awShadow(SHADOW_RIGHT_BOTTOM);
+ $this->border = new awBorder;
+
+ }
+
+ /**
+ * Get drawer of the image
+ *
+ * @param int $w Drawer width (from 0 to 1) (default to 1)
+ * @param int $h Drawer height (from 0 to 1) (default to 1)
+ * @param float $x Position on X axis of the center of the drawer (default to 0.5)
+ * @param float $y Position on Y axis of the center of the drawer (default to 0.5)
+ * @return Drawer
+ */
+ function getDrawer($w = 1, $h = 1, $x = 0.5, $y = 0.5) {
+ $this->create();
+ $this->drawer->setSize($w, $h);
+ $this->drawer->setPosition($x, $y);
+ return $this->drawer;
+ }
+
+ /**
+ * Change the image size
+ *
+ * @var int $width Image width
+ * @var int $height Image height
+ */
+ function setSize($width, $height) {
+
+ if($width !== NULL) {
+ $this->width = (int)$width;
+ }
+ if($height !== NULL) {
+ $this->height = (int)$height;
+ }
+
+ }
+
+ /**
+ * Change image background color
+ *
+ * @param $color
+ */
+ function setBackgroundColor($color) {
+ $this->background = $color;
+ }
+
+ /**
+ * Change image background gradient
+ *
+ * @param $gradient
+ */
+ function setBackgroundGradient($gradient) {
+ $this->background = $gradient;
+ }
+
+ /**
+ * Can we use anti-aliasing ?
+ *
+ * @var bool $bool
+ */
+ function setAntiAliasing($bool) {
+ $this->antiAliasing = (bool)$bool;
+ }
+
+ /**
+ * Change image format
+ *
+ * @var int $format New image format
+ */
+ function setFormat($format) {
+ if($format === IMAGE_JPEG or $format === IMAGE_PNG or $format === IMAGE_GIF) {
+ $this->format = $format;
+ }
+ }
+
+ /**
+ * Create a new awimage
+ */
+ function create() {
+
+ if($this->resource === NULL) {
+
+ // Create image
+
+ $this->resource = imagecreatetruecolor($this->width, $this->height);
+ if(!$this->resource) {
+ trigger_error("Unable to create a graph", E_USER_ERROR);
+ }
+
+ imagealphablending($this->resource, TRUE);
+
+ if($this->antiAliasing and function_exists('imageantialias')) {
+ imageantialias($this->resource, TRUE);
+ }
+
+ $this->drawer = new awDrawer($this->resource);
+ $this->drawer->setImageSize($this->width, $this->height);
+
+ // Original color
+ $this->drawer->filledRectangle(
+ new awWhite,
+ new awLine(
+ new awPoint(0, 0),
+ new awPoint($this->width, $this->height)
+ )
+ );
+
+ $shadow = $this->shadow->getSpace();
+
+ $p1 = new awPoint($shadow->left, $shadow->top);
+ $p2 = new awPoint($this->width - $shadow->right - 1, $this->height - $shadow->bottom - 1);
+
+ // Draw image background
+ $this->drawer->filledRectangle($this->background, new awLine($p1, $p2));
+ $this->background->free();
+
+ // Draw image border
+ $this->border->rectangle($this->drawer, $p1, $p2);
+
+ }
+
+ }
+
+ /**
+ * Draw a component on the image
+ *
+ * @var &$component A component
+ */
+ function drawComponent(&$component) {
+
+ $shadow = $this->shadow->getSpace(); // Image shadow
+ $border = $this->border->visible() ? 1 : 0; // Image border size
+
+ $drawer = $this->drawer;
+ $drawer->setImageSize(
+ $this->width - $shadow->left - $shadow->right - $border * 2,
+ $this->height - $shadow->top - $shadow->bottom - $border * 2
+ );
+
+ // No absolute size specified
+ if($component->w === NULL and $component->h === NULL) {
+
+ list($width, $height) = $drawer->setSize($component->width, $component->height);
+
+ // Set component size in pixels
+ $component->setAbsSize($width, $height);
+
+ } else {
+
+ $drawer->setAbsSize($component->w, $component->h);
+
+ }
+
+ if($component->top !== NULL and $component->left !== NULL) {
+ $drawer->setAbsPosition(
+ $border + $shadow->left + $component->left,
+ $border + $shadow->top + $component->top
+ );
+ } else {
+ $drawer->setPosition($component->x, $component->y);
+ }
+
+ $drawer->movePosition($border + $shadow->left, $border + $shadow->top);
+
+ list($x1, $y1, $x2, $y2) = $component->getPosition();
+
+ $component->init($drawer);
+
+ $component->drawComponent($drawer, $x1, $y1, $x2, $y2, $this->antiAliasing);
+ $component->drawEnvelope($drawer, $x1, $y1, $x2, $y2);
+
+ $component->finalize($drawer);
+
+ }
+
+ function drawShadow() {
+
+ $drawer = $this->getDrawer();
+
+ $this->shadow->draw(
+ $drawer,
+ new awPoint(0, 0),
+ new awPoint($this->width, $this->height),
+ SHADOW_IN
+ );
+
+ }
+
+ /**
+ * Send the image into a file or to the user browser
+ *
+ * @var string $file Save image into a file if you provide a file name
+ */
+ function send($file = NULL) {
+
+ // Test if format is available
+ if((imagetypes() & $this->format) === FALSE) {
+ trigger_error("Format '".$this->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($this->format) {
+ case IMAGE_JPEG :
+ $function = 'imagejpeg';
+ break;
+ case IMAGE_PNG :
+ $function = 'imagepng';
+ break;
+ case IMAGE_GIF :
+ $function = 'imagegif';
+ break;
+ }
+
+ // Create image
+
+ if($file !== NULL) {
+
+ $function($this->resource, $file);
+
+ } else {
+
+ // Send headers to the browser
+ if(headers_sent() === FALSE) {
+ header("Content-type: image/".$this->getFormat());
+ }
+
+ $function($this->resource);
+
+ }
+
+ }
+
+ function getFormat() {
+
+ switch($this->format) {
+ case IMAGE_JPEG :
+ return 'jpeg';
+ case IMAGE_PNG :
+ return 'png';
+ case IMAGE_GIF :
+ return 'gif';
+ }
+
+ }
+
+}
+
+registerClass('Image');
+
+
+/**
+ * Load an image from a file
+ *
+ * @package Artichow
+ */
+class awFileImage extends awImage {
+
+ /**
+ * Build a new awimage
+ *
+ * @param string $file Image file name
+ */
+ function awFileImage($file) {
+
+ $image = @getimagesize($file);
+
+ if($image and in_array($image[2], array(2, 3))) {
+
+ $this->setSize($image[0], $image[1]);
+
+ switch($image[2]) {
+
+ case 2 :
+ $this->resource = imagecreatefromjpeg($file);
+ break;
+
+ case 3 :
+ $this->resource = imagecreatefrompng($file);
+ break;
+
+ }
+
+ $this->drawer = new awDrawer($this->resource);
+ $this->drawer->setImageSize($this->width, $this->height);
+
+ } else {
+ trigger_error("Artichow does not support this image (must be in PNG or JPEG)", E_USER_ERROR);
+ }
+
+ }
+
+}
+
+registerClass('FileImage');
+?>
diff --git a/external-libs/Artichow/php4/LinePlot.class.php b/external-libs/Artichow/php4/LinePlot.class.php
new file mode 100644
index 00000000000..e24114b9f42
--- /dev/null
+++ b/external-libs/Artichow/php4/LinePlot.class.php
@@ -0,0 +1,596 @@
+ */
+
+define("LINEPLOT_LINE", 0);
+define("LINEPLOT_MIDDLE", 1);
+
+/* */
+
+/**
+ * LinePlot
+ *
+ * @package Artichow
+ */
+class awLinePlot extends awPlot {
+
+ /**
+ * Add marks to your line plot
+ *
+ * @var Mark
+ */
+ var $mark;
+
+ /**
+ * Labels on your line plot
+ *
+ * @var Label
+ */
+ var $label;
+
+ /**
+ * Filled areas
+ *
+ * @var bool
+ */
+ var $areas = array();
+
+ /**
+ * Is the line hidden
+ *
+ * @var bool
+ */
+ var $lineHide = FALSE;
+
+ /**
+ * Line color
+ *
+ * @var Color
+ */
+ var $lineColor;
+
+ /**
+ * Line mode
+ *
+ * @var int
+ */
+ var $lineMode = LINEPLOT_LINE;
+
+ /**
+ * Line type
+ *
+ * @var int
+ */
+ var $lineStyle = LINE_SOLID;
+
+ /**
+ * Line thickness
+ *
+ * @var int
+ */
+ var $lineThickness = 1;
+
+ /**
+ * Line background
+ *
+ * @var Color, Gradient
+ */
+ var $lineBackground;
+
+ /**
+ * Line mode
+ *
+ * @var int
+ */
+
+
+ /**
+ * Line in the middle
+ *
+ * @var int
+ */
+
+
+ /**
+ * Construct a new awLinePlot
+ *
+ * @param array $values Some numeric values for Y axis
+ * @param int $mode
+ */
+ function awLinePlot($values, $mode = LINEPLOT_LINE) {
+
+ parent::awPlot();
+
+ $this->mark = new awMark;
+ $this->label = new awLabel;
+
+ $this->lineMode = (int)$mode;
+
+ $this->setValues($values);
+
+ }
+
+ /**
+ * Hide line
+ *
+ * @param bool $hide
+ */
+ function hideLine($hide) {
+ $this->lineHide = (bool)$hide;
+ }
+
+ /**
+ * Add a filled area
+ *
+ * @param int $start Begining of the area
+ * @param int $end End of the area
+ * @param mixed $background Background color or gradient of the area
+ */
+ function setFilledArea($start, $stop, $background) {
+
+ if($stop <= $start) {
+ trigger_error("End position can not be greater than begin position in awLinePlot::setFilledArea()", E_USER_ERROR);
+ }
+
+ $this->areas[] = array((int)$start, (int)$stop, $background);
+
+ }
+
+ /**
+ * Change line color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->lineColor = $color;
+ }
+
+ /**
+ * Change line style
+ *
+ * @param int $style
+ */
+ function setStyle($style) {
+ $this->lineStyle = (int)$style;
+ }
+
+ /**
+ * Change line tickness
+ *
+ * @param int $tickness
+ */
+ function setThickness($tickness) {
+ $this->lineThickness = (int)$tickness;
+ }
+
+ /**
+ * Change line background color
+ *
+ * @param $color
+ */
+ function setFillColor($color) {
+ $this->lineBackground = $color;
+ }
+
+ /**
+ * Change line background gradient
+ *
+ * @param $gradient
+ */
+ function setFillGradient($gradient) {
+ $this->lineBackground = $gradient;
+ }
+
+ /**
+ * Get the line thickness
+ *
+ * @return int
+ */
+ function getLegendLineThickness() {
+ return $this->lineThickness;
+ }
+
+ /**
+ * Get the line type
+ *
+ * @return int
+ */
+ function getLegendLineStyle() {
+ return $this->lineStyle;
+ }
+
+ /**
+ * Get the color of line
+ *
+ * @return Color
+ */
+ function getLegendLineColor() {
+ return $this->lineColor;
+ }
+
+ /**
+ * Get the background color or gradient of an element of the component
+ *
+ * @return Color, Gradient
+ */
+ function getLegendBackground() {
+ return $this->lineBackground;
+ }
+
+ /**
+ * Get a mark object
+ *
+ * @return Mark
+ */
+ function getLegendMark() {
+ return $this->mark;
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ $max = $this->getRealYMax();
+ $min = $this->getRealYMin();
+
+ // Get start and stop values
+ list($start, $stop) = $this->getLimit();
+
+ if($this->lineMode === LINEPLOT_MIDDLE) {
+ $inc = $this->xAxis->getDistance(0, 1) / 2;
+ } else {
+ $inc = 0;
+ }
+
+ // Build the polygon
+ $polygon = new awPolygon;
+
+ for($key = $start; $key <= $stop; $key++) {
+
+ $value = $this->datay[$key];
+
+ if($value !== NULL) {
+
+ $p = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($key, $value));
+ $p = $p->move($inc, 0);
+ $polygon->set($key, $p);
+
+ }
+
+ }
+
+ // Draw backgrounds
+ if(is_a($this->lineBackground, 'awColor') or is_a($this->lineBackground, 'awGradient')) {
+
+ $backgroundPolygon = new awPolygon;
+
+ $p = $this->xAxisPoint($start);
+ $p = $p->move($inc, 0);
+ $backgroundPolygon->append($p);
+
+ // Add others points
+ foreach($polygon->all() as $point) {
+ $backgroundPolygon->append($point);
+ }
+
+ $p = $this->xAxisPoint($stop);
+ $p = $p->move($inc, 0);
+ $backgroundPolygon->append($p);
+
+ // Draw polygon background
+ $drawer->filledPolygon($this->lineBackground, $backgroundPolygon);
+
+ }
+
+ $this->drawArea($drawer, $polygon);
+
+ // Draw line
+ $prev = NULL;
+
+ // Line color
+ if($this->lineHide === FALSE) {
+
+ if($this->lineColor === NULL) {
+ $this->lineColor = new awColor(0, 0, 0);
+ }
+
+ foreach($polygon->all() as $point) {
+
+ if($prev !== NULL) {
+ $drawer->line(
+ $this->lineColor,
+ new awLine(
+ $prev,
+ $point,
+ $this->lineStyle,
+ $this->lineThickness
+ )
+ );
+ }
+ $prev = $point;
+
+ }
+
+ $this->lineColor->free();
+
+ }
+
+ // Draw marks and labels
+ foreach($polygon->all() as $key => $point) {
+
+ $this->mark->draw($drawer, $point);
+ $this->label->draw($drawer, $point, $key);
+
+ }
+
+ }
+
+ function drawArea($drawer, &$polygon) {
+
+ $starts = array();
+ foreach($this->areas as $area) {
+ list($start) = $area;
+ $starts[$start] = TRUE;
+ }
+
+ // Draw filled areas
+ foreach($this->areas as $area) {
+
+ list($start, $stop, $background) = $area;
+
+ $polygonArea = new awPolygon;
+
+ $p = $this->xAxisPoint($start);
+ $polygonArea->append($p);
+
+ for($i = $start; $i <= $stop; $i++) {
+ $p = $polygon->get($i);
+ if($i === $stop and array_key_exists($stop, $starts)) {
+ $p = $p->move(-1, 0);
+ }
+ $polygonArea->append($p);
+ }
+
+ $p = $this->xAxisPoint($stop);
+ if(array_key_exists($stop, $starts)) {
+ $p = $p->move(-1, 0);
+ }
+ $polygonArea->append($p);
+
+ // Draw area
+ $drawer->filledPolygon($background, $polygonArea);
+
+ }
+
+ }
+
+ function getXAxisNumber() {
+ if($this->lineMode === LINEPLOT_MIDDLE) {
+ return count($this->datay) + 1;
+ } else {
+ return count($this->datay);
+ }
+ }
+
+ function xAxisPoint($position) {
+ $y = $this->xAxisZero ? 0 : $this->getRealYMin();
+ return awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($position, $y));
+ }
+
+ function getXCenter() {
+ return ($this->lineMode === LINEPLOT_MIDDLE);
+ }
+
+}
+
+registerClass('LinePlot');
+
+
+/**
+ * Simple LinePlot
+ * Useful to draw simple horizontal lines
+ *
+ * @package Artichow
+ */
+class awSimpleLinePlot extends awPlot {
+
+ /**
+ * Line color
+ *
+ * @var Color
+ */
+ var $lineColor;
+
+ /**
+ * Line start
+ *
+ * @var int
+ */
+ var $lineStart;
+
+ /**
+ * Line stop
+ *
+ * @var int
+ */
+ var $lineStop;
+
+ /**
+ * Line value
+ *
+ * @var flaot
+ */
+ var $lineValue;
+
+ /**
+ * Line mode
+ *
+ * @var int
+ */
+ var $lineMode = LINEPLOT_LINE;
+
+ /**
+ * Line type
+ *
+ * @var int
+ */
+ var $lineStyle = LINE_SOLID;
+
+ /**
+ * Line thickness
+ *
+ * @var int
+ */
+ var $lineThickness = 1;
+
+ /**
+ * Line mode
+ *
+ * @var int
+ */
+
+
+ /**
+ * Line in the middle
+ *
+ * @var int
+ */
+
+
+ /**
+ * Construct a new awLinePlot
+ *
+ * @param float $value A Y value
+ * @param int $start Line start index
+ * @param int $stop Line stop index
+ * @param int $mode Line mode
+ */
+ function awSimpleLinePlot($value, $start, $stop, $mode = LINEPLOT_LINE) {
+
+ parent::awPlot();
+
+ $this->lineMode = (int)$mode;
+
+ $this->lineStart = (int)$start;
+ $this->lineStop = (int)$stop;
+ $this->lineValue = (float)$value;
+
+ $this->lineColor = new awColor(0, 0, 0);
+
+ }
+
+ /**
+ * Change line color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->lineColor = $color;
+ }
+
+ /**
+ * Change line style
+ *
+ * @param int $style
+ */
+ function setStyle($style) {
+ $this->lineStyle = (int)$style;
+ }
+
+ /**
+ * Change line tickness
+ *
+ * @param int $tickness
+ */
+ function setThickness($tickness) {
+ $this->lineThickness = (int)$tickness;
+ }
+
+ /**
+ * Get the line thickness
+ *
+ * @return int
+ */
+ function getLegendLineThickness() {
+ return $this->lineThickness;
+ }
+
+ /**
+ * Get the line type
+ *
+ * @return int
+ */
+ function getLegendLineStyle() {
+ return $this->lineStyle;
+ }
+
+ /**
+ * Get the color of line
+ *
+ * @return Color
+ */
+ function getLegendLineColor() {
+ return $this->lineColor;
+ }
+
+ function getLegendBackground() {
+ return NULL;
+ }
+
+ function getLegendMark() {
+ return NULL;
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ if($this->lineMode === LINEPLOT_MIDDLE) {
+ $inc = $this->xAxis->getDistance(0, 1) / 2;
+ } else {
+ $inc = 0;
+ }
+
+ $p1 = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($this->lineStart, $this->lineValue));
+ $p2 = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($this->lineStop, $this->lineValue));
+
+ $drawer->line(
+ $this->lineColor,
+ new awLine(
+ $p1->move($inc, 0),
+ $p2->move($inc, 0),
+ $this->lineStyle,
+ $this->lineThickness
+ )
+ );
+
+ $this->lineColor->free();
+
+ }
+
+ function getXAxisNumber() {
+ if($this->lineMode === LINEPLOT_MIDDLE) {
+ return count($this->datay) + 1;
+ } else {
+ return count($this->datay);
+ }
+ }
+
+ function xAxisPoint($position) {
+ $y = $this->xAxisZero ? 0 : $this->getRealYMin();
+ return awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($position, $y));
+ }
+
+ function getXCenter() {
+ return ($this->lineMode === LINEPLOT_MIDDLE);
+ }
+
+}
+
+registerClass('SimpleLinePlot');
+?>
diff --git a/external-libs/Artichow/php4/MathPlot.class.php b/external-libs/Artichow/php4/MathPlot.class.php
new file mode 100644
index 00000000000..86f8e2b3fa8
--- /dev/null
+++ b/external-libs/Artichow/php4/MathPlot.class.php
@@ -0,0 +1,439 @@
+f = (string)$f;
+ $this->fromX = is_null($fromX) ? NULL : (float)$fromX;
+ $this->toX = is_null($toX) ? NULL : (float)$toX;
+
+ $this->line = new awLine;
+ $this->mark = new awMark;
+ $this->color = new awBlack;
+
+ }
+
+ /**
+ * Change line color
+ *
+ * @param $color A new awcolor
+ */
+ function setColor($color) {
+ $this->color = $color;
+ }
+
+ /**
+ * Get line color
+ *
+ * @return Color
+ */
+ function getColor() {
+ return $this->color;
+ }
+
+ /**
+ * Get the background color or gradient of an element of the component
+ *
+ * @return Color, Gradient
+ */
+ function getLegendBackground() {
+ }
+
+ /**
+ * Get the line thickness
+ *
+ * @return NULL
+ */
+ function getLegendLineThickness() {
+ return $this->line->getThickness();
+ }
+
+ /**
+ * Get the line type
+ *
+ * @return NULL
+ */
+ function getLegendLineStyle() {
+ return $this->line->getStyle();
+ }
+
+ /**
+ * Get the color of line
+ *
+ * @return NULL
+ */
+ function getLegendLineColor() {
+ return $this->color;
+ }
+
+ /**
+ * Get a mark object
+ *
+ * @return NULL
+ */
+ function getLegendMark() {
+ return $this->mark;
+ }
+
+}
+
+registerClass('MathFunction');
+
+/**
+ * For mathematics functions
+ *
+ * @package Artichow
+ */
+class awMathPlot extends awComponent {
+
+ /**
+ * Functions
+ *
+ * @var array
+ */
+ var $functions = array();
+
+ /**
+ * Grid properties
+ *
+ * @var Grid
+ */
+ var $grid;
+
+ /**
+ * X axis
+ *
+ * @var Axis
+ */
+ var $xAxis;
+
+ /**
+ * Y axis
+ *
+ * @var Axis
+ */
+ var $yAxis;
+
+ /**
+ * Extremum
+ *
+ * @var Side
+ */
+ var $extremum = NULL;
+
+ /**
+ * Interval
+ *
+ * @var float
+ */
+ var $interval = 1;
+
+ /**
+ * Build the plot
+ *
+ * @param int $xMin Minimum X value
+ * @param int $xMax Maximum X value
+ * @param int $yMax Maximum Y value
+ * @param int $yMin Minimum Y value
+ */
+ function awMathPlot($xMin, $xMax, $yMax, $yMin) {
+
+ parent::awComponent();
+
+ $this->setPadding(8, 8, 8, 8);
+
+ $this->grid = new awGrid;
+
+ // Hide grid by default
+ $this->grid->hide(TRUE);
+
+ // Set extremum
+ $this->extremum = new awSide($xMin, $xMax, $yMax, $yMin);
+
+ // Create axis
+ $this->xAxis = new awAxis;
+ $this->xAxis->setTickStyle(TICK_IN);
+ $this->xAxis->label->hideValue(0);
+ $this->initAxis($this->xAxis);
+
+ $this->yAxis = new awAxis;
+ $this->yAxis->setTickStyle(TICK_IN);
+ $this->yAxis->label->hideValue(0);
+ $this->initAxis($this->yAxis);
+
+ }
+
+ function initAxis(&$axis) {
+
+ $axis->setLabelPrecision(1);
+ $axis->addTick('major', new awTick(0, 5));
+ $axis->addTick('minor', new awTick(0, 3));
+ $axis->addTick('micro', new awTick(0, 1));
+ $axis->setNumberByTick('minor', 'major', 1);
+ $axis->setNumberByTick('micro', 'minor', 4);
+ $axis->label->setFont(new awTuffy(7));
+
+ }
+
+ /**
+ * Interval to calculate values
+ *
+ * @param float $interval
+ */
+ function setInterval($interval) {
+ $this->interval = (float)$interval;
+ }
+
+ /**
+ * Add a formula f(x)
+ *
+ * @param &$function
+ * @param string $name Name for the legend (can be NULL if you don't want to set a legend)
+ * @param int $type Type for the legend
+ */
+ function add(&$function, $name = NULL, $type = LEGEND_LINE) {
+
+ $this->functions[] = $function;
+
+ if($name !== NULL) {
+ $this->legend->add($function, $name, $type);
+ }
+
+ }
+
+ function init($drawer) {
+
+ list($x1, $y1, $x2, $y2) = $this->getPosition();
+
+ $this->xAxis->line->setX($x1, $x2);
+ $this->xAxis->label->setAlign(NULL, LABEL_BOTTOM);
+ $this->xAxis->label->move(0, 3);
+ $this->xAxis->setRange($this->extremum->left, $this->extremum->right);
+
+ $this->yAxis->line->setY($y2, $y1);
+ $this->yAxis->label->setAlign(LABEL_RIGHT);
+ $this->yAxis->label->move(-6, 0);
+ $this->yAxis->reverseTickStyle();
+ $this->yAxis->setRange($this->extremum->bottom, $this->extremum->top);
+
+
+ $this->xAxis->setYCenter($this->yAxis, 0);
+ $this->yAxis->setXCenter($this->xAxis, 0);
+
+ if($this->yAxis->getLabelNumber() === NULL) {
+ $number = $this->extremum->top - $this->extremum->bottom + 1;
+ $this->yAxis->setLabelNumber($number);
+ }
+
+ if($this->xAxis->getLabelNumber() === NULL) {
+ $number = $this->extremum->right - $this->extremum->left + 1;
+ $this->xAxis->setLabelNumber($number);
+ }
+
+ // Set ticks
+
+ $this->xAxis->ticks['major']->setNumber($this->xAxis->getLabelNumber());
+ $this->yAxis->ticks['major']->setNumber($this->yAxis->getLabelNumber());
+
+
+ // Set axis labels
+ $labels = array();
+ for($i = 0, $count = $this->xAxis->getLabelNumber(); $i < $count; $i++) {
+ $labels[] = $i;
+ }
+ $this->xAxis->label->set($labels);
+
+ $labels = array();
+ for($i = 0, $count = $this->yAxis->getLabelNumber(); $i < $count; $i++) {
+ $labels[] = $i;
+ }
+ $this->yAxis->label->set($labels);
+
+ parent::init($drawer);
+
+ // Create the grid
+ $this->createGrid();
+
+ // Draw the grid
+ $this->grid->draw($drawer, $x1, $y1, $x2, $y2);
+
+ }
+
+ function drawEnvelope($drawer) {
+
+ // Draw axis
+ $this->xAxis->draw($drawer);
+ $this->yAxis->draw($drawer);
+
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ foreach($this->functions as $function) {
+
+ $f = $function->f;
+ $fromX = is_null($function->fromX) ? $this->extremum->left : $function->fromX;
+ $toX = is_null($function->toX) ? $this->extremum->right : $function->toX;
+
+ $old = NULL;
+
+ for($i = $fromX; $i <= $toX; $i += $this->interval) {
+
+ $p = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($i, $f($i)));
+
+ if($p->y >= $y1 and $p->y <= $y2) {
+ $function->mark->draw($drawer, $p);
+ }
+
+ if($old !== NULL) {
+
+ $line = $function->line;
+ $line->setLocation($old, $p);
+
+ if(
+ ($line->p1->y >= $y1 and $line->p1->y <= $y2) or
+ ($line->p2->y >= $y1 and $line->p2->y <= $y2)
+ ) {
+ $drawer->line(
+ $function->getColor(),
+ $line
+ );
+ }
+
+ }
+
+ $old = $p;
+
+ }
+
+ // Draw last point if needed
+ if($old !== NULL and $i - $this->interval != $toX) {
+
+ $p = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($toX, $f($toX)));
+
+ if($p->y >= $y1 and $p->y <= $y2) {
+ $function->mark->draw($drawer, $p);
+ }
+
+
+ $line = $function->line;
+ $line->setLocation($old, $p);
+
+ if(
+ ($line->p1->y >= $y1 and $line->p1->y <= $y2) or
+ ($line->p2->y >= $y1 and $line->p2->y <= $y2)
+ ) {
+ $drawer->line(
+ $function->getColor(),
+ $line
+ );
+ }
+
+ }
+
+ }
+
+ }
+
+ function createGrid() {
+
+ // Horizontal lines of the grid
+
+ $major = $this->yAxis->tick('major');
+ $interval = $major->getInterval();
+ $number = $this->yAxis->getLabelNumber() - 1;
+
+ $h = array();
+ if($number > 0) {
+ for($i = 0; $i <= $number; $i++) {
+ $h[] = $i / $number;
+ }
+ }
+
+ // Vertical lines
+
+ $major = $this->xAxis->tick('major');
+ $interval = $major->getInterval();
+ $number = $this->xAxis->getLabelNumber() - 1;
+
+ $w = array();
+ if($number > 0) {
+ for($i = 0; $i <= $number; $i++) {
+ if($i%$interval === 0) {
+ $w[] = $i / $number;
+ }
+ }
+ }
+
+ $this->grid->setGrid($w, $h);
+
+ }
+
+}
+
+registerClass('MathPlot');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/Pattern.class.php b/external-libs/Artichow/php4/Pattern.class.php
new file mode 100644
index 00000000000..ff0f300e2e1
--- /dev/null
+++ b/external-libs/Artichow/php4/Pattern.class.php
@@ -0,0 +1,97 @@
+args[$name] = $value;
+ }
+ }
+
+ /**
+ * Get an argument
+ *
+ * @param string $name
+ * @param mixed $default Default value if the argument does not exist (default to NULL)
+ * @return mixed Argument value
+ */
+ function getArg($name, $default = NULL) {
+ if(array_key_exists($name, $this->args)) {
+ return $this->args[$name];
+ } else {
+ return $default;
+ }
+ }
+
+ /**
+ * Change several arguments
+ *
+ * @param array $args New arguments
+ */
+ function setArgs($args) {
+ if(is_array($args)) {
+ foreach($args as $name => $value) {
+ $this->setArg($name, $value);
+ }
+ }
+ }
+
+}
+
+registerClass('Pattern', TRUE);
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/Pie.class.php b/external-libs/Artichow/php4/Pie.class.php
new file mode 100644
index 00000000000..88a5630f2b8
--- /dev/null
+++ b/external-libs/Artichow/php4/Pie.class.php
@@ -0,0 +1,680 @@
+ */
+
+define("PIE_DARK", 1);
+define("PIE_COLORED", 2);
+define("PIE_AQUA", 3);
+define("PIE_EARTH", 4);
+
+/* */
+
+/**
+ * Pie
+ *
+ * @package Artichow
+ */
+class awPie extends awComponent {
+
+ /**
+ * A dark theme for pies
+ *
+ *
+ * @var int
+ */
+
+
+ /**
+ * A colored theme for pies
+ *
+ * @var int
+ */
+
+
+ /**
+ * A water theme for pies
+ *
+ * @var int
+ */
+
+
+ /**
+ * A earth theme for pies
+ *
+ * @var int
+ */
+
+
+ /**
+ * Pie values
+ *
+ * @var array
+ */
+ var $values;
+
+ /**
+ * Pie colors
+ *
+ * @var array
+ */
+ var $colors;
+
+ /**
+ * Pie legend
+ *
+ * @var array
+ */
+ var $legendValues = array();
+
+ /**
+ * Intensity of the 3D effect
+ *
+ * @var int
+ */
+ var $size;
+
+ /**
+ * Border color
+ *
+ * @var Color
+ */
+ var $border;
+
+ /**
+ * Pie explode
+ *
+ * @var array
+ */
+ var $explode = array();
+
+ /**
+ * Initial angle
+ *
+ * @var int
+ */
+ var $angle = 0;
+
+ /**
+ * Labels precision
+ *
+ * @var int
+ */
+ var $precision;
+
+ /**
+ * Labels number
+ *
+ * @var int
+ */
+ var $number;
+
+ /**
+ * Labels minimum
+ *
+ * @var int
+ */
+ var $minimum;
+
+ /**
+ * Labels position
+ *
+ * @var int
+ */
+ var $position = 15;
+
+ /**
+ * Labels of your pie
+ *
+ * @var Label
+ */
+ var $label;
+
+ /**
+ * Build the plot
+ *
+ * @param array $values Pie values
+ */
+ function awPie($values, $colors = PIE_COLORED) {
+
+ $this->setValues($values);
+
+ if(is_array($colors)) {
+ $this->colors = $colors;
+ } else {
+
+ switch($colors) {
+
+ case PIE_AQUA :
+ $this->colors = array(
+ new awColor(131, 220, 215),
+ new awColor(131, 190, 215),
+ new awColor(131, 160, 215),
+ new awColor(160, 140, 215),
+ new awColor(190, 131, 215),
+ new awColor(220, 131, 215)
+ );
+ break;
+
+ case PIE_EARTH :
+ $this->colors = array(
+ new awColor(97, 179, 110),
+ new awColor(130, 179, 97),
+ new awColor(168, 179, 97),
+ new awColor(179, 147, 97),
+ new awColor(179, 108, 97),
+ new awColor(99, 107, 189),
+ new awColor(99, 165, 189)
+ );
+ break;
+
+ case PIE_DARK :
+ $this->colors = array(
+ new awColor(140, 100, 170),
+ new awColor(130, 170, 100),
+ new awColor(160, 160, 120),
+ new awColor(150, 110, 140),
+ new awColor(130, 150, 160),
+ new awColor(90, 170, 140)
+ );
+ break;
+
+ default :
+ $this->colors = array(
+ new awColor(187, 213, 151),
+ new awColor(223, 177, 151),
+ new awColor(111, 186, 132),
+ new awColor(197, 160, 230),
+ new awColor(165, 169, 63),
+ new awColor(218, 177, 89),
+ new awColor(116, 205, 121),
+ new awColor(200, 201, 78),
+ new awColor(127, 205, 177),
+ new awColor(205, 160, 160),
+ new awColor(190, 190, 190)
+ );
+ break;
+
+ }
+
+ }
+
+ parent::awComponent();
+
+ $this->label = new awLabel;
+ $this->label->setCallbackFunction('callbackPerCent');
+
+ }
+
+ /**
+ * Change legend values
+ *
+ * @param array $legend An array of values for each part of the pie
+ */
+ function setLegend($legend) {
+
+ $this->legendValues = (array)$legend;
+
+ }
+
+ /**
+ * Set a border all around the pie
+ *
+ * @param $color A color for the border
+ */
+ function setBorder($color) {
+ $this->border = $color;
+ }
+
+ /**
+ * Change 3D effect intensity
+ *
+ * @param int $size Effect size
+ */
+ function set3D($size) {
+ $this->size = (int)$size;
+ }
+
+ /**
+ * Change initial angle
+ *
+ * @param int $angle New angle in degrees
+ */
+ function setStartAngle($angle) {
+ $this->angle = (int)$angle;
+ }
+
+ /**
+ * Change label precision
+ *
+ * @param int $precision New precision
+ */
+ function setLabelPrecision($precision) {
+ $this->precision = (int)$precision;
+ }
+
+ /**
+ * Change label position
+ *
+ * @param int $position New position in pixels
+ */
+ function setLabelPosition($position) {
+ $this->position = (int)$position;
+ }
+
+ /**
+ * Change label number
+ *
+ * @param int $number New number
+ */
+ function setLabelNumber($number) {
+ $this->number = is_null($number) ? $number : (int)$number;
+ }
+
+ /**
+ * Change label minimum
+ *
+ * @param int $minimum New minimum
+ */
+ function setLabelMinimum($minimum) {
+ $this->minimum = is_null($minimum) ? $minimum : (int)$minimum;
+ }
+
+ /**
+ * Change Pie explode
+ *
+ * @param array $explode
+ */
+ function explode($explode) {
+ $this->explode = (array)$explode;
+ }
+
+ function drawEnvelope($drawer) {
+
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ $count = count($this->values);
+ $sum = array_sum($this->values);
+
+ $width = $x2 - $x1;
+ $height = $y2 - $y1;
+
+ if($aliasing) {
+ $x = $width / 2;
+ $y = $height / 2;
+ } else {
+ $x = $width / 2 + $x1;
+ $y = $height / 2 + $y1;
+ }
+
+ $position = $this->angle;
+ $values = array();
+ $parts = array();
+ $angles = 0;
+
+ if($aliasing) {
+ $side = new awSide(0, 0, 0, 0);
+ }
+
+ foreach($this->values as $key => $value) {
+
+ $angle = ($value / $sum * 360);
+
+ if($key === $count - 1) {
+ $angle = 360 - $angles;
+ }
+
+ $angles += $angle;
+
+ if(array_key_exists($key, $this->explode)) {
+ $middle = 360 - ($position + $angle / 2);
+ $posX = $this->explode[$key] * cos($middle * M_PI / 180);
+ $posY = $this->explode[$key] * sin($middle * M_PI / 180) * -1;
+
+ if($aliasing) {
+ $explode = new awPoint(
+ $posX * 2,
+ $posY * 2
+ );
+ $side->set(
+ max($side->left, $posX * -2),
+ max($side->right, $posX * 2),
+ max($side->top, $posY * -2),
+ max($side->bottom, $posY * 2)
+ );
+ } else {
+ $explode = new awPoint(
+ $posX,
+ $posY
+ );
+ }
+
+ } else {
+ $explode = new awPoint(0, 0);
+ }
+
+ $values[$key] = array(
+ $position, ($position + $angle), $explode
+ );
+
+ $color = $this->colors[$key % count($this->colors)];
+ $parts[$key] = new awPiePart($color);
+
+ // Add part to the legend
+ $legend = array_key_exists($key, $this->legendValues) ? $this->legendValues[$key] : $key;
+ $this->legend->add($parts[$key], $legend, LEGEND_BACKGROUND);
+
+ $position += $angle;
+
+ }
+
+ if($aliasing) {
+
+ $mainDrawer = $drawer;
+
+ $x *= 2;
+ $y *= 2;
+ $width *= 2;
+ $height *= 2;
+ $this->size *= 2;
+
+ $image = new awImage;
+ $image->border->hide();
+ $image->setSize(
+ $width + $side->left + $side->right,
+ $height + $side->top + $side->bottom + $this->size + 1 /* bugs.php.net ! */
+ );
+
+ $drawer = $image->getDrawer(
+ $width / $image->width,
+ $height / $image->height,
+ ($width / 2 + $side->left) / $image->width,
+ ($height / 2 + $side->top) / $image->height
+ );
+
+ }
+
+ // Draw 3D effect
+ for($i = $this->size; $i > 0; $i--) {
+
+ foreach($values as $key => $value) {
+
+ $color = $this->colors[$key % count($this->colors)];
+ $color->brightness(-50);
+
+ list($from, $to, $explode) = $value;
+
+ $drawer->filledArc($color, $explode->move($x, $y + $i), $width, $height, $from, $to);
+
+ $color->free();
+ unset($color);
+
+ if(is_a($this->border, 'awColor')) {
+
+ $point = $explode->move($x, $y);
+
+ if($i === $this->size) {
+
+ $drawer->arc($this->border, $point->move(0, $this->size), $width, $height, $from, $to);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ foreach($values as $key => $value) {
+
+ $color = $this->colors[$key % count($this->colors)];
+
+ list($from, $to, $explode) = $value;
+
+ $drawer->filledArc($color, $explode->move($x, $y), $width, $height, $from, $to);
+
+ if(is_a($this->border, 'awColor')) {
+
+ $point = $explode->move($x, $y);
+ $drawer->arc($this->border, $point, $width, $height, $from, $to);
+ }
+
+ }
+
+ if($aliasing) {
+
+ $x = $x / 2 + $x1;
+ $y = $y / 2 + $y1;
+ $width /= 2;
+ $height /= 2;
+ $this->size /= 2;
+
+ foreach($values as $key => $value) {
+ $old = $values[$key][2];
+ $values[$key][2] = new awPoint(
+ $old->x / 2, $old->y / 2
+ );
+ }
+
+ $mainDrawer->copyResizeImage(
+ $image,
+ new awPoint($x1 - $side->left / 2, $y1 - $side->top / 2),
+ new awPoint($x1 - $side->left / 2 + $image->width / 2, $y1 - $side->top / 2 + $image->height/ 2),
+ new awPoint(0, 0),
+ new awPoint($image->width, $image->height),
+ TRUE
+ );
+
+ $drawer = $mainDrawer;
+
+ }
+
+ // Get labels values
+ $pc = array();
+ foreach($this->values as $key => $value) {
+ $pc[$key] = round($value / $sum * 100, $this->precision);
+ }
+ if($this->label->count() === 0) { // Check that there is no user defined values
+ $this->label->set($pc);
+ }
+
+ $position = 0;
+
+ foreach($pc as $key => $value) {
+
+ // Limit number of labels to display
+ if($position === $this->number) {
+ break;
+ }
+
+ if(is_null($this->minimum) === FALSE and $value < $this->minimum) {
+ continue;
+ }
+
+ $position++;
+
+ list($from, $to, $explode) = $values[$key];
+
+ $angle = $from + ($to - $from) / 2;
+ $angleRad = (360 - $angle) * M_PI / 180;
+
+ $point = new awPoint(
+ $x + $explode->x + cos($angleRad) * ($width / 2 + $this->position),
+ $y + $explode->y - sin($angleRad) * ($height / 2 + $this->position)
+ );
+
+ $angle %= 360;
+
+ // We don't display labels on the 3D effect
+ if($angle > 0 and $angle < 180) {
+ $point = $point->move(0, -1 * sin($angleRad) * $this->size);
+ }
+
+ if($angle >= 45 and $angle < 135) {
+ $this->label->setAlign(LABEL_CENTER, LABEL_BOTTOM);
+ } else if($angle >= 135 and $angle < 225) {
+ $this->label->setAlign(LABEL_RIGHT, LABEL_MIDDLE);
+ } else if($angle >= 225 and $angle < 315) {
+ $this->label->setAlign(LABEL_CENTER, LABEL_TOP);
+ } else {
+ $this->label->setAlign(LABEL_LEFT, LABEL_MIDDLE);
+ }
+
+ $this->label->draw(
+ $drawer,
+ $point,
+ $key
+ );
+
+ }
+
+ }
+
+ /**
+ * Return margins around the component
+ *
+ * @return array Left, right, top and bottom margins
+ */
+ function getMargin() {
+
+ // Get axis informations
+
+ $leftAxis = $this->padding->left;
+ $rightAxis = $this->padding->right;
+ $topAxis = $this->padding->top;
+ $bottomAxis = $this->padding->bottom;
+
+ return array($leftAxis, $rightAxis, $topAxis, $bottomAxis);
+
+ }
+
+
+ /**
+ * Change values of Y axis
+ * This method ignores not numeric values
+ *
+ * @param array $values
+ */
+ function setValues($values) {
+
+ $this->checkArray($values);
+ $this->values = $values;
+
+ }
+
+
+ /**
+ * Return values of Y axis
+ *
+ * @return array
+ */
+ function getValues() {
+ return $this->values;
+ }
+
+ function checkArray(&$array) {
+
+ if(is_array($array) === FALSE) {
+ trigger_error("You tried to set values that are not an array");
+ }
+
+ foreach($array as $key => $value) {
+ if(is_numeric($value) === FALSE) {
+ unset($array[$key]);
+ }
+ }
+
+ if(count($array) < 1) {
+ trigger_error("Your graph must have at least 1 value");
+ }
+
+ }
+
+}
+
+registerClass('Pie');
+
+/**
+ * Pie
+ *
+ * @package Artichow
+ */
+class awPiePart {
+
+ /**
+ * Pie part color
+ *
+ * @var Color
+ */
+ var $color;
+
+ /**
+ * Build a new awPiePart
+ *
+ * @param $color Pie part color
+ */
+ function awPiePart($color) {
+
+ $this->color = $color;
+
+ }
+
+ /**
+ * Get the background color or gradient of an element of the component
+ *
+ * @return Color, Gradient
+ */
+ function getLegendBackground() {
+ return $this->color;
+ }
+
+ /**
+ * Get the line thickness
+ *
+ * @return NULL
+ */
+ function getLegendLineThickness() {
+ }
+
+ /**
+ * Get the line type
+ *
+ * @return NULL
+ */
+ function getLegendLineStyle() {
+ }
+
+ /**
+ * Get the color of line
+ *
+ * @return NULL
+ */
+ function getLegendLineColor() {
+ }
+
+ /**
+ * Get a mark object
+ *
+ * @return NULL
+ */
+ function getLegendMark() {
+ }
+
+}
+
+registerClass('PiePart');
+
+function callbackPerCent($value) {
+ return $value.'%';
+}
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/Plot.class.php b/external-libs/Artichow/php4/Plot.class.php
new file mode 100644
index 00000000000..8eea0d56ac3
--- /dev/null
+++ b/external-libs/Artichow/php4/Plot.class.php
@@ -0,0 +1,1464 @@
+ */
+
+define("PLOT_LEFT", 'left');
+define("PLOT_RIGHT", 'right');
+define("PLOT_TOP", 'top');
+define("PLOT_BOTTOM", 'bottom');
+define("PLOT_BOTH", 'both');
+
+/* */
+
+/**
+ * Graph using X and Y axis
+ *
+ * @package Artichow
+ */
+ class awPlot extends awComponent {
+
+ /**
+ * Values for Y axis
+ *
+ * @var array
+ */
+ var $datay;
+
+ /**
+ * Values for X axis
+ *
+ * @var array
+ */
+ var $datax;
+
+ /**
+ * Grid properties
+ *
+ * @var Grid
+ */
+ var $grid;
+
+ /**
+ * X axis
+ *
+ * @var Axis
+ */
+ var $xAxis;
+
+ /**
+ * Y axis
+ *
+ * @var Axis
+ */
+ var $yAxis;
+
+ /**
+ * Position of X axis
+ *
+ * @var int
+ */
+ var $xAxisPosition = PLOT_BOTTOM;
+
+ /**
+ * Set X axis on zero ?
+ *
+ * @var bool
+ */
+ var $xAxisZero = TRUE;
+
+ /**
+ * Set Y axis on zero ?
+ *
+ * @var bool
+ */
+ var $yAxisZero = FALSE;
+
+ /**
+ * Position of Y axis
+ *
+ * @var int
+ */
+ var $yAxisPosition = PLOT_LEFT;
+
+ /**
+ * Change min value for Y axis
+ *
+ * @var mixed
+ */
+ var $yMin = NULL;
+
+ /**
+ * Change max value for Y axis
+ *
+ * @var mixed
+ */
+ var $yMax = NULL;
+
+ /**
+ * Change min value for X axis
+ *
+ * @var mixed
+ */
+ var $xMin = NULL;
+
+ /**
+ * Change max value for X axis
+ *
+ * @var mixed
+ */
+ var $xMax = NULL;
+
+ /**
+ * Left axis
+ *
+ * @var int
+ */
+
+
+ /**
+ * RIGHT axis
+ *
+ * @var int
+ */
+
+
+ /**
+ * Top axis
+ *
+ * @var int
+ */
+
+
+ /**
+ * Bottom axis
+ *
+ * @var int
+ */
+
+
+ /**
+ * Both left/right or top/bottom axis
+ *
+ * @var int
+ */
+
+
+ /**
+ * Build the plot
+ *
+ */
+ function awPlot() {
+
+ parent::awComponent();
+
+ $this->grid = new awGrid;
+ $this->grid->setBackgroundColor(new awWhite);
+
+ $this->padding->add(20, 0, 0, 20);
+
+ $this->xAxis = new awAxis;
+ $this->xAxis->addTick('major', new awTick(0, 5));
+ $this->xAxis->addTick('minor', new awTick(0, 3));
+ $this->xAxis->setTickStyle(TICK_OUT);
+ $this->xAxis->label->setFont(new awTuffy(7));
+
+ $this->yAxis = new awAxis;
+ $this->yAxis->auto(TRUE);
+ $this->yAxis->addTick('major', new awTick(0, 5));
+ $this->yAxis->addTick('minor', new awTick(0, 3));
+ $this->yAxis->setTickStyle(TICK_OUT);
+ $this->yAxis->setNumberByTick('minor', 'major', 3);
+ $this->yAxis->label->setFont(new awTuffy(7));
+ $this->yAxis->title->setAngle(90);
+
+ }
+
+ /**
+ * Get plot values
+ *
+ * @return array
+ */
+ function getValues() {
+ return $this->datay;
+ }
+
+ /**
+ * Reduce number of values in the plot
+ *
+ * @param int $number Reduce number of values to $number
+ */
+ function reduce($number) {
+
+ $count = count($this->datay);
+ $ratio = ceil($count / $number);
+
+ if($ratio > 1) {
+
+ $tmpy = $this->datay;
+ $datay = array();
+
+ $datax = array();
+ $cbLabel = $this->xAxis->label->getCallbackFunction();
+
+ for($i = 0; $i < $count; $i += $ratio) {
+
+ $slice = array_slice($tmpy, $i, $ratio);
+ $datay[] = array_sum($slice) / count($slice);
+
+ // Reduce data on X axis if needed
+ if($cbLabel !== NULL) {
+ $datax[] = $cbLabel($i + round($ratio / 2));
+ }
+
+ }
+
+ $this->setValues($datay);
+
+ if($cbLabel !== NULL) {
+ $this->xAxis->setLabelText($datax);
+ }
+
+
+ }
+
+ }
+
+ /**
+ * Count values in the plot
+ *
+ * @return int
+ */
+ function getXAxisNumber() {
+ list($min, $max) = $this->xAxis->getRange();
+ return ($max - $min + 1);
+ }
+
+ /**
+ * Change X axis
+ *
+ * @param int $axis
+ */
+ function setXAxis($axis) {
+ $this->xAxisPosition = $axis;
+ }
+
+ /**
+ * Get X axis
+ *
+ * @return int
+ */
+ function getXAxis() {
+ return $this->xAxisPosition;
+ }
+
+ /**
+ * Set X axis on zero
+ *
+ * @param bool $zero
+ */
+ function setXAxisZero($zero) {
+ $this->xAxisZero = (bool)$zero;
+ }
+
+ /**
+ * Set Y axis on zero
+ *
+ * @param bool $zero
+ */
+ function setYAxisZero($zero) {
+ $this->yAxisZero = (bool)$zero;
+ }
+
+ /**
+ * Change Y axis
+ *
+ * @param int $axis
+ */
+ function setYAxis($axis) {
+ $this->yAxisPosition = $axis;
+ }
+
+ /**
+ * Get Y axis
+ *
+ * @return int
+ */
+ function getYAxis() {
+ return $this->yAxisPosition;
+ }
+
+ /**
+ * Change min value for Y axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setYMin($value) {
+ $this->yMin = $value;
+ $this->yAxis->auto(FALSE);
+ $this->updateAxis();
+ }
+
+ /**
+ * Change max value for Y axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setYMax($value) {
+ $this->yMax = $value;
+ $this->yAxis->auto(FALSE);
+ $this->updateAxis();
+ }
+
+ /**
+ * Change min value for X axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setXMin($value) {
+ $this->xMin = $value;
+ $this->updateAxis();
+ }
+
+ /**
+ * Change max value for X axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setXMax($value) {
+ $this->xMax = $value;
+ $this->updateAxis();
+ }
+
+ /**
+ * Get min value for Y axis
+ *
+ * @return float $value
+ */
+ function getYMin() {
+ if($this->auto) {
+ if(is_null($this->yMin)) {
+ $min = array_min($this->datay);
+ if($min > 0) {
+ return 0;
+ }
+ }
+ }
+ return is_null($this->yMin) ? array_min($this->datay) : (float)$this->yMin;
+ }
+
+ /**
+ * Get max value for Y axis
+ *
+ * @return float $value
+ */
+ function getYMax() {
+ if($this->auto) {
+ if(is_null($this->yMax)) {
+ $max = array_max($this->datay);
+ if($max < 0) {
+ return 0;
+ }
+ }
+ }
+ return is_null($this->yMax) ? array_max($this->datay) : (float)$this->yMax;
+ }
+
+ /**
+ * Get min value for X axis
+ *
+ * @return float $value
+ */
+ function getXMin() {
+ return floor(is_null($this->xMin) ? array_min($this->datax) : $this->xMin);
+ }
+
+ /**
+ * Get max value for X axis
+ *
+ * @return float $value
+ */
+ function getXMax() {
+ return (ceil(is_null($this->xMax) ? array_max($this->datax) : (float)$this->xMax)) + ($this->getXCenter() ? 1 : 0);
+ }
+
+ /**
+ * Get min value with spaces for Y axis
+ *
+ * @return float $value
+ */
+ function getRealYMin() {
+ $min = $this->getYMin();
+ if($this->space->bottom !== NULL) {
+ $interval = ($this->getYMax() - $min) * $this->space->bottom / 100;
+ return $min - $interval;
+ } else {
+ return is_null($this->yMin) ? $min : (float)$this->yMin;
+ }
+ }
+
+ /**
+ * Get max value with spaces for Y axis
+ *
+ * @return float $value
+ */
+ function getRealYMax() {
+ $max = $this->getYMax();
+ if($this->space->top !== NULL) {
+ $interval = ($max - $this->getYMin()) * $this->space->top / 100;
+ return $max + $interval;
+ } else {
+ return is_null($this->yMax) ? $max : (float)$this->yMax;
+ }
+ }
+
+ function init($drawer) {
+
+ list($x1, $y1, $x2, $y2) = $this->getPosition();
+
+ // Get space informations
+ list($leftSpace, $rightSpace, $topSpace, $bottomSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
+
+ $this->xAxis->setPadding($leftSpace, $rightSpace);
+
+ if($this->space->bottom > 0 or $this->space->top > 0) {
+
+ list($min, $max) = $this->yAxis->getRange();
+ $interval = $max - $min;
+
+ $this->yAxis->setRange(
+ $min - $interval * $this->space->bottom / 100,
+ $max + $interval * $this->space->top / 100
+ );
+
+ }
+
+ // Auto-scaling mode
+ $this->yAxis->autoScale();
+
+ // Number of labels is not specified
+ if($this->yAxis->getLabelNumber() === NULL) {
+ $number = round(($y2 - $y1) / 75) + 2;
+ $this->yAxis->setLabelNumber($number);
+ }
+
+ $this->xAxis->line->setX($x1, $x2);
+ $this->yAxis->line->setY($y2, $y1);
+
+ // Set ticks
+
+ $this->xAxis->ticks['major']->setNumber($this->getXAxisNumber());
+ $this->yAxis->ticks['major']->setNumber($this->yAxis->getLabelNumber());
+
+
+ // Center X axis on zero
+ if($this->xAxisZero) {
+ $this->xAxis->setYCenter($this->yAxis, 0);
+ }
+
+ // Center Y axis on zero
+ if($this->yAxisZero) {
+ $this->yAxis->setXCenter($this->xAxis, 0);
+ }
+
+ // Set axis labels
+ $labels = array();
+ for($i = 0, $count = $this->getXAxisNumber(); $i < $count; $i++) {
+ $labels[] = $i;
+ }
+ $this->xAxis->label->set($labels);
+
+ parent::init($drawer);
+
+ list($x1, $y1, $x2, $y2) = $this->getPosition();
+
+ list($leftSpace, $rightSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
+
+ // Create the grid
+ $this->createGrid();
+
+ // Draw the grid
+ $this->grid->setSpace($leftSpace, $rightSpace, 0, 0);
+ $this->grid->draw($drawer, $x1, $y1, $x2, $y2);
+
+ }
+
+ function drawEnvelope($drawer) {
+
+ list($x1, $y1, $x2, $y2) = $this->getPosition();
+
+ if($this->getXCenter()) {
+ $size = $this->xAxis->getDistance(0, 1);
+ $this->xAxis->label->move($size / 2, 0);
+ $this->xAxis->label->hideLast(TRUE);
+ }
+
+ // Draw top axis
+ if($this->xAxisPosition === PLOT_TOP or $this->xAxisPosition === PLOT_BOTH) {
+ $top = $this->xAxis;
+ if($this->xAxisZero === FALSE) {
+ $top->line->setY($y1, $y1);
+ }
+ $top->label->setAlign(NULL, LABEL_TOP);
+ $top->label->move(0, -3);
+ $top->title->move(0, -25);
+ $top->draw($drawer);
+ }
+
+ // Draw bottom axis
+ if($this->xAxisPosition === PLOT_BOTTOM or $this->xAxisPosition === PLOT_BOTH) {
+ $bottom = $this->xAxis;
+ if($this->xAxisZero === FALSE) {
+ $bottom->line->setY($y2, $y2);
+ }
+ $bottom->label->setAlign(NULL, LABEL_BOTTOM);
+ $bottom->label->move(0, 3);
+ $bottom->reverseTickStyle();
+ $bottom->title->move(0, 25);
+ $bottom->draw($drawer);
+ }
+
+ // Draw left axis
+ if($this->yAxisPosition === PLOT_LEFT or $this->yAxisPosition === PLOT_BOTH) {
+ $left = $this->yAxis;
+ if($this->yAxisZero === FALSE) {
+ $left->line->setX($x1, $x1);
+ }
+ $left->label->setAlign(LABEL_RIGHT);
+ $left->label->move(-6, 0);
+ $left->title->move(-25, 0);
+ $left->draw($drawer);
+ }
+
+ // Draw right axis
+ if($this->yAxisPosition === PLOT_RIGHT or $this->yAxisPosition === PLOT_BOTH) {
+ $right = $this->yAxis;
+ if($this->yAxisZero === FALSE) {
+ $right->line->setX($x2, $x2);
+ }
+ $right->label->setAlign(LABEL_LEFT);
+ $right->label->move(6, 0);
+ $right->reverseTickStyle();
+ $right->title->move(25, 0);
+ $right->draw($drawer);
+ }
+
+ }
+
+ function createGrid() {
+
+ $max = $this->getRealYMax();
+ $min = $this->getRealYMin();
+
+ $number = $this->yAxis->getLabelNumber() - 1;
+
+ if($number < 1) {
+ return;
+ }
+
+ // Horizontal lines of the grid
+
+ $h = array();
+ for($i = 0; $i <= $number; $i++) {
+ $h[] = $i / $number;
+ }
+
+ // Vertical lines
+
+ $major = $this->yAxis->tick('major');
+ $interval = $major->getInterval();
+ $number = $this->getXAxisNumber() - 1;
+
+ $w = array();
+
+ if($number > 0) {
+
+ for($i = 0; $i <= $number; $i++) {
+ if($i%$interval === 0) {
+ $w[] = $i / $number;
+ }
+ }
+
+ }
+
+ $this->grid->setGrid($w, $h);
+
+ }
+
+ /**
+ * Change values of Y axis
+ * This method ignores not numeric values
+ *
+ * @param array $datay
+ * @param array $datax
+ */
+ function setValues($datay, $datax = NULL) {
+
+ $this->checkArray($datay);
+
+ foreach($datay as $key => $value) {
+ unset($datay[$key]);
+ $datay[(int)$key] = $value;
+ }
+
+ if($datax === NULL) {
+ $datax = array();
+ for($i = 0; $i < count($datay); $i++) {
+ $datax[] = $i;
+ }
+ } else {
+ foreach($datax as $key => $value) {
+ unset($datax[$key]);
+ $datax[(int)$key] = $value;
+ }
+ }
+
+ $this->checkArray($datax);
+
+ if(count($datay) === count($datax)) {
+
+ // Set values
+ $this->datay = $datay;
+ $this->datax = $datax;
+ // Update axis with the new awvalues
+ $this->updateAxis();
+ } else {
+ trigger_error("Plots must have the same number of X and Y points", E_USER_ERROR);
+ }
+
+ }
+
+ /**
+ * Return begin and end values
+ *
+ * @return array
+ */
+ function getLimit() {
+
+ $i = 0;
+ while(array_key_exists($i, $this->datay) and $this->datay[$i] === NULL) {
+ $i++;
+ }
+ $start = $i;
+ $i = count($this->datay) - 1;
+ while(array_key_exists($i, $this->datay) and $this->datay[$i] === NULL) {
+ $i--;
+ }
+ $stop = $i;
+
+ return array($start, $stop);
+
+ }
+
+ /**
+ * Return TRUE if labels must be centered on X axis, FALSE otherwise
+ *
+ * @return bool
+ */
+
+
+ function updateAxis() {
+
+ $this->xAxis->setRange(
+ $this->getXMin(),
+ $this->getXMax()
+ );
+ $this->yAxis->setRange(
+ $this->getRealYMin(),
+ $this->getRealYMax()
+ );
+
+ }
+
+ function checkArray(&$array) {
+
+ if(is_array($array) === FALSE) {
+ trigger_error("You tried to set a value that is not an array", E_USER_ERROR);
+ }
+
+ foreach($array as $key => $value) {
+ if(is_numeric($value) === FALSE and is_null($value) === FALSE) {
+ trigger_error("Expected numeric values for the plot", E_USER_ERROR);
+ }
+ }
+
+ if(count($array) < 1) {
+ trigger_error("Your plot must have at least 1 value", E_USER_ERROR);
+ }
+
+ }
+
+}
+
+registerClass('Plot', TRUE);
+
+class awPlotAxis {
+
+ /**
+ * Left axis
+ *
+ * @var Axis
+ */
+ var $left;
+
+ /**
+ * Right axis
+ *
+ * @var Axis
+ */
+ var $right;
+
+ /**
+ * Top axis
+ *
+ * @var Axis
+ */
+ var $top;
+
+ /**
+ * Bottom axis
+ *
+ * @var Axis
+ */
+ var $bottom;
+
+ /**
+ * Build the group of axis
+ */
+ function awPlotAxis() {
+
+ $this->left = new awAxis;
+ $this->left->auto(TRUE);
+ $this->left->label->setAlign(LABEL_RIGHT);
+ $this->left->label->move(-6, 0);
+ $this->yAxis($this->left);
+ $this->left->setTickStyle(TICK_OUT);
+ $this->left->title->move(-25, 0);
+
+ $this->right = new awAxis;
+ $this->right->auto(TRUE);
+ $this->right->label->setAlign(LABEL_LEFT);
+ $this->right->label->move(6, 0);
+ $this->yAxis($this->right);
+ $this->right->setTickStyle(TICK_IN);
+ $this->right->title->move(25, 0);
+
+ $this->top = new awAxis;
+ $this->top->label->setAlign(NULL, LABEL_TOP);
+ $this->top->label->move(0, -3);
+ $this->xAxis($this->top);
+ $this->top->setTickStyle(TICK_OUT);
+ $this->top->title->move(0, -25);
+
+ $this->bottom = new awAxis;
+ $this->bottom->label->setAlign(NULL, LABEL_BOTTOM);
+ $this->bottom->label->move(0, 3);
+ $this->xAxis($this->bottom);
+ $this->bottom->setTickStyle(TICK_IN);
+ $this->bottom->title->move(0, 25);
+
+ }
+
+ function xAxis(&$axis) {
+
+ $axis->addTick('major', new awTick(0, 5));
+ $axis->addTick('minor', new awTick(0, 3));
+ $axis->label->setFont(new awTuffy(7));
+
+ }
+
+ function yAxis(&$axis) {
+
+ $axis->addTick('major', new awTick(0, 5));
+ $axis->addTick('minor', new awTick(0, 3));
+ $axis->setNumberByTick('minor', 'major', 3);
+ $axis->label->setFont(new awTuffy(7));
+ $axis->title->setAngle(90);
+
+ }
+
+}
+
+registerClass('PlotAxis');
+
+/**
+ * A graph with axis can contain some groups of components
+ *
+ * @package Artichow
+ */
+class awPlotGroup extends awComponentGroup {
+
+ /**
+ * Grid properties
+ *
+ * @var Grid
+ */
+ var $grid;
+
+ /**
+ * Left, right, top and bottom axis
+ *
+ * @var PlotAxis
+ */
+ var $axis;
+
+ /**
+ * Set the X axis on zero
+ *
+ * @var bool
+ */
+ var $xAxisZero = TRUE;
+
+ /**
+ * Set the Y axis on zero
+ *
+ * @var bool
+ */
+ var $yAxisZero = FALSE;
+
+ /**
+ * Real axis used for Y axis
+ *
+ * @var string
+ */
+ var $yRealAxis = PLOT_LEFT;
+
+ /**
+ * Real axis used for X axis
+ *
+ * @var string
+ */
+ var $xRealAxis = PLOT_BOTTOM;
+
+ /**
+ * Change min value for Y axis
+ *
+ * @var mixed
+ */
+ var $yMin = NULL;
+
+ /**
+ * Change max value for Y axis
+ *
+ * @var mixed
+ */
+ var $yMax = NULL;
+
+ /**
+ * Change min value for X axis
+ *
+ * @var mixed
+ */
+ var $xMin = NULL;
+
+ /**
+ * Change max value for X axis
+ *
+ * @var mixed
+ */
+ var $xMax = NULL;
+
+ /**
+ * Build the PlotGroup
+ *
+ */
+ function awPlotGroup() {
+
+ parent::awComponentGroup();
+
+ $this->grid = new awGrid;
+ $this->grid->setBackgroundColor(new awWhite);
+
+ $this->axis = new awPlotAxis;
+
+ }
+
+ /**
+ * Set the X axis on zero or not
+ *
+ * @param bool $zero
+ */
+ function setXAxisZero($zero) {
+ $this->xAxisZero = (bool)$zero;
+ }
+
+ /**
+ * Set the Y axis on zero or not
+ *
+ * @param bool $zero
+ */
+ function setYAxisZero($zero) {
+ $this->yAxisZero = (bool)$zero;
+ }
+
+ /**
+ * Change min value for Y axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setYMin($value) {
+ $this->axis->left->auto(FALSE);
+ $this->axis->right->auto(FALSE);
+ $this->yMin = $value;
+ }
+
+ /**
+ * Change max value for Y axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setYMax($value) {
+ $this->axis->left->auto(FALSE);
+ $this->axis->right->auto(FALSE);
+ $this->yMax = $value;
+ }
+
+ /**
+ * Change min value for X axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setXMin($value) {
+ $this->xMin = $value;
+ }
+
+ /**
+ * Change max value for X axis
+ * Set NULL for auto selection.
+ *
+ * @param float $value
+ */
+ function setXMax($value) {
+ $this->xMax = $value;
+ }
+
+ /**
+ * Get min value for X axis
+ *
+ * @return float $value
+ */
+ function getXMin() {
+
+ return $this->getX('min');
+
+ }
+
+ /**
+ * Get max value for X axis
+ *
+ * @return float $value
+ */
+ function getXMax() {
+
+ return $this->getX('max');
+
+ }
+
+ function getX($type) {
+
+ switch($type) {
+ case 'max' :
+ if($this->xMax !== NULL) {
+ return $this->xMax;
+ }
+ break;
+ case 'min' :
+ if($this->xMin !== NULL) {
+ return $this->xMin;
+ }
+ break;
+ }
+
+ $value = NULL;
+ $get = 'getX'.ucfirst($type);
+
+ for($i = 0; $i < count($this->components); $i++) {
+
+ $component = $this->components[$i];
+
+ if($value === NULL) {
+ $value = $component->$get();
+ } else {
+ $value = $type($value, $component->$get());
+ }
+
+ }
+
+ return $value;
+
+ }
+
+ /**
+ * Get min value with spaces for Y axis
+ *
+ * @param string $axis Axis name
+ * @return float $value
+ */
+ function getRealYMin($axis = NULL) {
+
+ if($axis === NULL) {
+ return NULL;
+ }
+
+ $min = $this->getRealY('min', $axis);
+ $max = $this->getRealY('max', $axis);
+
+ if($this->space->bottom !== NULL) {
+ $interval = ($min - $max) * $this->space->bottom / 100;
+ return $min + $interval;
+ } else {
+ return $min;
+ }
+
+ }
+
+ /**
+ * Get max value with spaces for Y axis
+ *
+ * @param string $axis Axis name
+ * @return float $value
+ */
+ function getRealYMax($axis = NULL) {
+
+ if($axis === NULL) {
+ return NULL;
+ }
+
+ $min = $this->getRealY('min', $axis);
+ $max = $this->getRealY('max', $axis);
+
+ if($this->space->top !== NULL) {
+ $interval = ($max - $min) * $this->space->top / 100;
+ return $max + $interval;
+ } else {
+ return $max;
+ }
+
+ }
+
+ function getRealY($type, $axis) {
+
+ switch($type) {
+ case 'max' :
+ if($this->yMax !== NULL) {
+ return $this->yMax;
+ }
+ break;
+ case 'min' :
+ if($this->yMin !== NULL) {
+ return $this->yMin;
+ }
+ break;
+ }
+
+ $value = NULL;
+ $get = 'getY'.ucfirst($type);
+
+ for($i = 0; $i < count($this->components); $i++) {
+
+ $component = $this->components[$i];
+
+ switch($axis) {
+
+ case PLOT_LEFT :
+ case PLOT_RIGHT :
+ $test = ($component->getYAxis() === $axis);
+ break;
+ default :
+ $test = FALSE;
+
+ }
+
+ if($test) {
+ if($value === NULL) {
+ $value = $component->$get();
+ } else {
+ $value = $type($value, $component->$get());
+ }
+ }
+
+ }
+
+ return $value;
+
+ }
+
+ function init($drawer) {
+
+ list($x1, $y1, $x2, $y2) = $this->getPosition();
+
+ // Get PlotGroup space
+ list($leftSpace, $rightSpace, $topSpace, $bottomSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
+
+ // Count values in the group
+ $values = $this->getXAxisNumber();
+
+ // Init the PlotGroup
+ $this->axis->top->line->setX($x1, $x2);
+ $this->axis->bottom->line->setX($x1, $x2);
+ $this->axis->left->line->setY($y2, $y1);
+ $this->axis->right->line->setY($y2, $y1);
+
+ $this->axis->top->setPadding($leftSpace, $rightSpace);
+ $this->axis->bottom->setPadding($leftSpace, $rightSpace);
+
+ $xMin = $this->getXMin();
+ $xMax = $this->getXMax();
+
+ $this->axis->top->setRange($xMin, $xMax);
+ $this->axis->bottom->setRange($xMin, $xMax);
+
+ for($i = 0; $i < count($this->components); $i++) {
+
+
+ $component = &$this->components[$i];
+
+ $component->auto($this->auto);
+
+ // Copy space to the component
+
+ $component->setSpace($this->space->left, $this->space->right, $this->space->top, $this->space->bottom);
+
+ $component->xAxis->setPadding($leftSpace, $rightSpace);
+ $component->xAxis->line->setX($x1, $x2);
+
+ $component->yAxis->line->setY($y2, $y1);
+
+ }
+
+ // Set Y axis range
+ foreach(array('left', 'right') as $axis) {
+
+ if($this->isAxisUsed($axis)) {
+
+ $min = $this->getRealYMin($axis);
+ $max = $this->getRealYMax($axis);
+
+ $interval = $max - $min;
+
+ $this->axis->{$axis}->setRange(
+ $min - $interval * $this->space->bottom / 100,
+ $max + $interval * $this->space->top / 100
+ );
+
+ // Auto-scaling mode
+ $this->axis->{$axis}->autoScale();
+
+ }
+
+ }
+
+ if($this->axis->left->getLabelNumber() === NULL) {
+ $number = round(($y2 - $y1) / 75) + 2;
+ $this->axis->left->setLabelNumber($number);
+ }
+
+ if($this->axis->right->getLabelNumber() === NULL) {
+ $number = round(($y2 - $y1) / 75) + 2;
+ $this->axis->right->setLabelNumber($number);
+ }
+
+ // Center labels on X axis if needed
+ $test = array(PLOT_TOP => FALSE, PLOT_BOTTOM => FALSE);
+
+ for($i = 0; $i < count($this->components); $i++) {
+
+
+ $component = &$this->components[$i];
+
+
+ if($component->getValues() !== NULL) {
+
+ $axis = $component->getXAxis();
+
+ if($test[$axis] === FALSE) {
+
+ // Center labels for bar plots
+ if($component->getXCenter()) {
+ $size = $this->axis->{$axis}->getDistance(0, 1);
+ $this->axis->{$axis}->label->move($size / 2, 0);
+ $this->axis->{$axis}->label->hideLast(TRUE);
+ $test[$axis] = TRUE;
+ }
+
+ }
+
+ }
+
+
+ }
+
+ // Set axis labels
+ $labels = array();
+ for($i = $xMin; $i <= $xMax; $i++) {
+ $labels[] = $i;
+ }
+ if($this->axis->top->label->count() === 0) {
+ $this->axis->top->label->set($labels);
+ }
+ if($this->axis->bottom->label->count() === 0) {
+ $this->axis->bottom->label->set($labels);
+ }
+
+ // Set ticks
+
+ $this->axis->top->ticks['major']->setNumber($values);
+ $this->axis->bottom->ticks['major']->setNumber($values);
+ $this->axis->left->ticks['major']->setNumber($this->axis->left->getLabelNumber());
+ $this->axis->right->ticks['major']->setNumber($this->axis->right->getLabelNumber());
+
+
+ // Set X axis on zero
+ if($this->xAxisZero) {
+ $axis = $this->selectYAxis();
+ $this->axis->bottom->setYCenter($axis, 0);
+ $this->axis->top->setYCenter($axis, 0);
+ }
+
+ // Set Y axis on zero
+ if($this->yAxisZero) {
+ $axis = $this->selectXAxis();
+ $this->axis->left->setXCenter($axis, 1);
+ $this->axis->right->setXCenter($axis, 1);
+ }
+
+ parent::init($drawer);
+
+ list($leftSpace, $rightSpace, $topSpace, $bottomSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
+
+ // Create the grid
+ $this->createGrid();
+
+ // Draw the grid
+ $this->grid->setSpace($leftSpace, $rightSpace, 0, 0);
+ $this->grid->draw($drawer, $x1, $y1, $x2, $y2);
+
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ $xMin = $this->getXMin();
+ $xMax = $this->getXMax();
+
+ $maxLeft = $this->getRealYMax(PLOT_LEFT);
+ $maxRight = $this->getRealYMax(PLOT_RIGHT);
+
+ $minLeft = $this->getRealYMin(PLOT_LEFT);
+ $minRight = $this->getRealYMin(PLOT_RIGHT);
+
+ foreach($this->components as $component) {
+
+ $min = $component->getYMin();
+ $max = $component->getYMax();
+
+ // Set component minimum and maximum
+ if($component->getYAxis() === PLOT_LEFT) {
+
+ list($min, $max) = $this->axis->left->getRange();
+
+ $component->setYMin($min);
+ $component->setYMax($max);
+
+ } else {
+
+ list($min, $max) = $this->axis->right->getRange();
+
+ $component->setYMin($min);
+ $component->setYMax($max);
+
+ }
+
+ $component->setXAxisZero($this->xAxisZero);
+ $component->setYAxisZero($this->yAxisZero);
+
+ $component->xAxis->setRange($xMin, $xMax);
+
+ $component->drawComponent(
+ $drawer,
+ $x1, $y1,
+ $x2, $y2,
+ $aliasing
+ );
+
+ $component->setYMin($min);
+ $component->setYMax($max);
+
+ }
+
+ }
+
+ function drawEnvelope($drawer) {
+
+ list($x1, $y1, $x2, $y2) = $this->getPosition();
+
+ // Hide unused axis
+ foreach(array(PLOT_LEFT, PLOT_RIGHT, PLOT_TOP, PLOT_BOTTOM) as $axis) {
+ if($this->isAxisUsed($axis) === FALSE) {
+ $this->axis->{$axis}->hide(TRUE);
+ }
+ }
+
+ // Draw top axis
+ $top = $this->axis->top;
+ if($this->xAxisZero === FALSE) {
+ $top->line->setY($y1, $y1);
+ }
+ $top->draw($drawer);
+
+ // Draw bottom axis
+ $bottom = $this->axis->bottom;
+ if($this->xAxisZero === FALSE) {
+ $bottom->line->setY($y2, $y2);
+ }
+ $bottom->draw($drawer);
+
+ // Draw left axis
+ $left = $this->axis->left;
+ if($this->yAxisZero === FALSE) {
+ $left->line->setX($x1, $x1);
+ }
+ $left->draw($drawer);
+
+ // Draw right axis
+ $right = $this->axis->right;
+ if($this->yAxisZero === FALSE) {
+ $right->line->setX($x2, $x2);
+ }
+ $right->draw($drawer);
+
+ }
+
+ /**
+ * Is the specified axis used ?
+ *
+ * @param string $axis Axis name
+ * @return bool
+ */
+ function isAxisUsed($axis) {
+
+ for($i = 0; $i < count($this->components); $i++) {
+
+ $component = $this->components[$i];
+
+ switch($axis) {
+
+ case PLOT_LEFT :
+ case PLOT_RIGHT :
+ if($component->getYAxis() === $axis) {
+ return TRUE;
+ }
+ break;
+
+ case PLOT_TOP :
+ case PLOT_BOTTOM :
+ if($component->getXAxis() === $axis) {
+ return TRUE;
+ }
+ break;
+
+ }
+
+ }
+
+ return FALSE;
+
+ }
+
+ function createGrid() {
+
+ $max = $this->getRealYMax(PLOT_LEFT);
+ $min = $this->getRealYMin(PLOT_RIGHT);
+
+ // Select axis (left if possible, right otherwise)
+ $axis = $this->selectYAxis();
+
+ $number = $axis->getLabelNumber() - 1;
+
+ if($number < 1) {
+ return;
+ }
+
+ // Horizontal lines of grid
+
+ $h = array();
+ for($i = 0; $i <= $number; $i++) {
+ $h[] = $i / $number;
+ }
+
+ // Vertical lines
+
+ $major = $axis->tick('major');
+ $interval = $major->getInterval();
+ $number = $this->getXAxisNumber() - 1;
+
+ $w = array();
+
+ if($number > 0) {
+
+ for($i = 0; $i <= $number; $i++) {
+ if($i%$interval === 0) {
+ $w[] = $i / $number;
+ }
+ }
+
+ }
+
+ $this->grid->setGrid($w, $h);
+
+ }
+
+ function selectYAxis(){
+
+ // Select axis (left if possible, right otherwise)
+ if($this->isAxisUsed(PLOT_LEFT)) {
+ $axis = $this->axis->left;
+ } else {
+ $axis = $this->axis->right;
+ }
+
+ return $axis;
+
+ }
+
+ function selectXAxis(){
+
+ // Select axis (bottom if possible, top otherwise)
+ if($this->isAxisUsed(PLOT_BOTTOM)) {
+ $axis = $this->axis->bottom;
+ } else {
+ $axis = $this->axis->top;
+ }
+
+ return $axis;
+
+ }
+
+ function getXAxisNumber() {
+ $offset = $this->components[0];
+ $max = $offset->getXAxisNumber();
+ for($i = 1; $i < count($this->components); $i++) {
+ $offset = $this->components[$i];
+ $max = max($max, $offset->getXAxisNumber());
+ }
+ return $max;
+ }
+
+}
+
+registerClass('PlotGroup');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/ScatterPlot.class.php b/external-libs/Artichow/php4/ScatterPlot.class.php
new file mode 100644
index 00000000000..e82b664c73d
--- /dev/null
+++ b/external-libs/Artichow/php4/ScatterPlot.class.php
@@ -0,0 +1,303 @@
+mark = new awMark;
+ $this->mark->setType(MARK_CIRCLE);
+ $this->mark->setSize(7);
+ $this->mark->border->show();
+
+ $this->label = new awLabel;
+
+ $this->setValues($datay, $datax);
+ $this->setColor(new awBlack);
+
+ }
+
+ /**
+ * Display plot as impulses
+ *
+ * @param $impulse Impulses color (or NULL to disable impulses)
+ */
+ function setImpulse($color) {
+ $this->impulse = $color;
+ }
+
+ /**
+ * Link scatter plot points
+ *
+ * @param bool $link
+ * @param $color Line color (default to black)
+ */
+ function link($link, $color = NULL) {
+ $this->link = (bool)$link;
+ if(is_a($color, 'awColor')) {
+ $this->setColor($color);
+ }
+ }
+
+ /**
+ * Ignore null values for Y data and continue linking
+ *
+ * @param bool $link
+ */
+ function linkNull($link) {
+ $this->linkNull = (bool)$link;
+ }
+
+ /**
+ * Change line color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->lineColor = $color;
+ }
+
+ /**
+ * Change line style
+ *
+ * @param int $style
+ */
+ function setStyle($style) {
+ $this->lineStyle = (int)$style;
+ }
+
+ /**
+ * Change line tickness
+ *
+ * @param int $tickness
+ */
+ function setThickness($tickness) {
+ $this->lineThickness = (int)$tickness;
+ }
+
+ /**
+ * Get the line thickness
+ *
+ * @return int
+ */
+ function getLegendLineThickness() {
+ return $this->lineThickness;
+ }
+
+ /**
+ * Get the line type
+ *
+ * @return int
+ */
+ function getLegendLineStyle() {
+ return $this->lineStyle;
+ }
+
+ /**
+ * Get the color of line
+ *
+ * @return Color
+ */
+ function getLegendLineColor() {
+ return $this->lineColor;
+ }
+
+ /**
+ * Get the background color or gradient of an element of the component
+ *
+ * @return Color, Gradient
+ */
+ function getLegendBackground() {
+ return NULL;
+ }
+
+ /**
+ * Get a mark object
+ *
+ * @return Mark
+ */
+ function getLegendMark() {
+ return $this->mark;
+ }
+
+ function drawComponent($drawer, $x1, $y1, $x2, $y2, $aliasing) {
+
+ $count = count($this->datay);
+
+ // Get start and stop values
+ list($start, $stop) = $this->getLimit();
+
+ // Build the polygon
+ $polygon = new awPolygon;
+
+ for($key = 0; $key < $count; $key++) {
+
+ $x = $this->datax[$key];
+ $y = $this->datay[$key];
+
+ if($y !== NULL) {
+ $p = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($x, $y));
+ $polygon->set($key, $p);
+ } else if($this->linkNull === FALSE) {
+ $polygon->set($key, NULL);
+ }
+
+ }
+
+ // Link points if needed
+ if($this->link) {
+
+ $prev = NULL;
+
+ foreach($polygon->all() as $point) {
+
+ if($prev !== NULL and $point !== NULL) {
+ $drawer->line(
+ $this->lineColor,
+ new awLine(
+ $prev,
+ $point,
+ $this->lineStyle,
+ $this->lineThickness
+ )
+ );
+ }
+ $prev = $point;
+
+ }
+
+ $this->lineColor->free();
+
+ }
+
+ // Draw impulses
+ if(is_a($this->impulse, 'awColor')) {
+
+ foreach($polygon->all() as $key => $point) {
+
+ if($point !== NULL) {
+
+ $zero = awAxis::toPosition(
+ $this->xAxis,
+ $this->yAxis,
+ new awPoint($key, 0)
+ );
+
+ $drawer->line(
+ $this->impulse,
+ new awLine(
+ $zero,
+ $point,
+ LINE_SOLID,
+ 1
+ )
+ );
+
+ }
+
+ }
+
+ }
+
+ // Draw marks and labels
+ foreach($polygon->all() as $key => $point) {
+
+ $this->mark->draw($drawer, $point);
+ $this->label->draw($drawer, $point, $key);
+
+ }
+
+ }
+
+ function xAxisPoint($position) {
+ $y = $this->xAxisZero ? 0 : $this->getRealYMin();
+ return awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($position, $y));
+ }
+
+ function getXCenter() {
+ return FALSE;
+ }
+
+}
+
+registerClass('ScatterPlot');
+?>
diff --git a/external-libs/Artichow/php4/common.php b/external-libs/Artichow/php4/common.php
new file mode 100644
index 00000000000..d399f73c781
--- /dev/null
+++ b/external-libs/Artichow/php4/common.php
@@ -0,0 +1,102 @@
+ 0) {
+
+ do {
+ $min = array_pop($array);
+ if(is_numeric($min === FALSE)) {
+ $min = NULL;
+ }
+ } while(count($array) > 0 and $min === NULL);
+
+ if($min !== NULL) {
+ $min = (float)$min;
+ }
+
+ foreach($array as $value) {
+ if(is_numeric($value) and (float)$value < $min) {
+ $min = (float)$value;
+ }
+ }
+
+ return $min;
+
+ }
+
+ return NULL;
+
+}
+
+/*
+ * Get the maximum of an array and ignore non numeric values
+ */
+function array_max($array) {
+
+ if(is_array($array) and count($array) > 0) {
+
+ do {
+ $max = array_pop($array);
+ if(is_numeric($max === FALSE)) {
+ $max = NULL;
+ }
+ } while(count($array) > 0 and $max === NULL);
+
+ if($max !== NULL) {
+ $max = (float)$max;
+ }
+
+ foreach($array as $value) {
+ if(is_numeric($value) and (float)$value > $max) {
+ $max = (float)$value;
+ }
+ }
+
+ return $max;
+
+ }
+
+ return NULL;
+
+}
+
+/*
+ * Register a class with the prefix in configuration file
+ */
+function registerClass($class, $abstract = FALSE) {
+
+ if(ARTICHOW_PREFIX === 'aw') {
+ return;
+ }
+
+
+ $abstract = '';
+
+
+ eval($abstract." class ".ARTICHOW_PREFIX.$class." extends aw".$class." { }");
+
+}
+
+/*
+ * Register an interface with the prefix in configuration file
+ */
+function registerInterface($interface) {
+
+ if(ARTICHOW_PREFIX === 'aw') {
+ return;
+ }
+
+
+}
+?>
diff --git a/external-libs/Artichow/php4/inc/Axis.class.php b/external-libs/Artichow/php4/inc/Axis.class.php
new file mode 100644
index 00000000000..7cc138ab53c
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Axis.class.php
@@ -0,0 +1,769 @@
+ '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
+ */
+ function awAxis($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
+ */
+ function auto($auto) {
+ $this->auto = (bool)$auto;
+ }
+
+ /**
+ * Get auto-scaling mode status
+ *
+ * @return bool
+ */
+ function isAuto() {
+ return $this->auto;
+ }
+
+ /**
+ * Hide axis
+ *
+ * @param bool $hide
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show axis
+ *
+ * @param bool $show
+ */
+ function show($show = TRUE) {
+ $this->hide = !(bool)$show;
+ }
+
+ /**
+ * Return a tick object from its name
+ *
+ * @param string $name Tick object name
+ * @return Tick
+ */
+ function tick($name) {
+
+ if(array_key_exists($name, $this->ticks)) {
+ return $tick = &$this->ticks[$name];
+ } else {
+ return NULL;
+ }
+
+ }
+
+ /**
+ * Add a tick object
+ *
+ * @param string $name Tick object name
+ * @param &$tick Tick object
+ */
+ function addTick($name, &$tick) {
+
+ $this->ticks[$name] = &$tick;
+
+ }
+
+ /**
+ * Delete a tick object
+ *
+ * @param string $name Tick object name
+ */
+ function deleteTick($name) {
+ if(array_key_exists($name, $this->ticks)) {
+ unset($this->ticks[$name]);
+ }
+ }
+
+ /**
+ * Hide all ticks
+ *
+ * @param bool $hide Hide or not ?
+ */
+ function hideTicks($hide = TRUE) {
+
+ foreach($this->ticks as $key => $tick) {
+ $this->ticks[$key]->hide($hide);
+ }
+
+ }
+
+ /**
+ * Change ticks style
+ *
+ * @param int $style Ticks style
+ */
+ function setTickStyle($style) {
+
+ foreach($this->ticks as $key => $tick) {
+ $this->ticks[$key]->setStyle($style);
+ }
+
+ }
+
+ /**
+ * Change ticks interval
+ *
+ * @param int $interval Ticks interval
+ */
+ function setTickInterval($interval) {
+
+ foreach($this->ticks as $key => $tick) {
+ $this->ticks[$key]->setInterval($interval);
+ }
+
+ }
+
+ /**
+ * Change number of ticks relative to others ticks
+ *
+ * @param &$to Change number of theses ticks
+ * @param &$from Ticks reference
+ * @param float $number Number of ticks by the reference
+ */
+ function setNumberByTick($to, $from, $number) {
+ $this->ticks[$to]->setNumberByTick($this->ticks[$from], $number);
+ }
+
+ /**
+ * Reverse ticks style
+ */
+ function reverseTickStyle() {
+
+ foreach($this->ticks as $key => $tick) {
+ if($this->ticks[$key]->getStyle() === TICK_IN) {
+ $this->ticks[$key]->setStyle(TICK_OUT);
+ } else if($this->ticks[$key]->getStyle() === TICK_OUT) {
+ $this->ticks[$key]->setStyle(TICK_IN);
+ }
+ }
+
+ }
+
+ /**
+ * Change interval of labels
+ *
+ * @param int $interval Interval
+ */
+ 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)
+ */
+ function setLabelNumber($number) {
+ $this->auto(FALSE);
+ $this->labelNumber = is_null($number) ? NULL : (int)$number;
+ }
+
+ /**
+ * Get number of labels
+ *
+ * @return int
+ */
+ function getLabelNumber() {
+ return $this->labelNumber;
+ }
+
+ /**
+ * Change precision of labels
+ *
+ * @param int $precision Precision
+ */
+ 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
+ */
+ 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 &$xAxis X axis
+ * @param &$yAxis Y axis
+ * @param $p Position of the point
+ * @return Point Position on the axis
+ */
+ function toPosition(&$xAxis, &$yAxis, $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
+ */
+ function setTitleAlignment($alignment) {
+
+ switch($alignment) {
+
+ case LABEL_TOP :
+ $this->setTitlePosition(1);
+ $this->title->setAlign(NULL, LABEL_BOTTOM);
+ break;
+
+ case LABEL_BOTTOM :
+ $this->setTitlePosition(0);
+ $this->title->setAlign(NULL, LABEL_TOP);
+ break;
+
+ case LABEL_LEFT :
+ $this->setTitlePosition(0);
+ $this->title->setAlign(LABEL_LEFT);
+ break;
+
+ case LABEL_RIGHT :
+ $this->setTitlePosition(1);
+ $this->title->setAlign(LABEL_RIGHT);
+ break;
+
+ }
+
+ }
+
+ /**
+ * Change title position on the axis
+ *
+ * @param float $position A new awposition between 0 and 1
+ */
+ function setTitlePosition($position) {
+ $this->titlePosition = (float)$position;
+ }
+
+ /**
+ * Change axis and axis title color
+ *
+ * @param $color
+ */
+ function setColor($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
+ */
+ function setPadding($left, $right) {
+ $this->padding->set($left, $right);
+ }
+
+ /**
+ * Get axis padding
+ *
+ * @return Side
+ */
+ function getPadding() {
+ return $this->padding;
+ }
+
+ /**
+ * Change axis range
+ *
+ * @param float $min
+ * @param float $max
+ */
+ 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
+ */
+ 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
+ */
+ function setRangeCallback($toValue, $toPosition) {
+ $this->rangeCallback = array(
+ 'toValue' => (string)$toValue,
+ 'toPosition' => (string)$toPosition
+ );
+ }
+
+ /**
+ * Center X values of the axis
+ *
+ * @param &$axis An axis
+ * @param float $value The reference value on the axis
+ */
+ function setXCenter(&$axis, $value) {
+
+ // Check vector angle
+ if($this->line->isVertical() === FALSE) {
+ trigger_error("setXCenter() can only be used on vertical axes", E_USER_ERROR);
+ }
+
+ $p = $axis->getPointFromValue($value);
+
+ $this->line->setX(
+ $p->x,
+ $p->x
+ );
+
+ }
+
+ /**
+ * Center Y values of the axis
+ *
+ * @param &$axis An axis
+ * @param float $value The reference value on the axis
+ */
+ function setYCenter(&$axis, $value) {
+
+ // Check vector angle
+ if($this->line->isHorizontal() === FALSE) {
+ trigger_error("setYCenter() can only be used on horizontal axes", E_USER_ERROR);
+ }
+
+ $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
+ */
+ 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
+ */
+ 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
+ */
+ 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 $drawer A drawer
+ */
+ function draw($drawer) {
+
+ if($this->hide) {
+ return;
+ }
+
+ $vector = $this->getVector();
+
+ // Draw axis ticks
+ $this->drawTicks($drawer, $vector);
+
+ // Draw axis line
+ $this->line($drawer);
+
+ // Draw labels
+ $this->drawLabels($drawer);
+
+ // Draw axis title
+ $p = $this->getPointFromPosition($this->titlePosition);
+ $this->title->draw($drawer, $p);
+
+ }
+
+ 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++;
+ }
+
+ $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);
+
+ }
+
+ function line($drawer) {
+
+ $drawer->line(
+ $this->color,
+ $this->line
+ );
+
+ }
+
+ function drawTicks($drawer, &$vector) {
+
+ foreach($this->ticks as $tick) {
+ $tick->setColor($this->color);
+ $tick->draw($drawer, $vector);
+ }
+
+ }
+
+ function drawLabels($drawer) {
+
+ 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($drawer, $p, $i);
+
+ }
+
+ }
+
+ 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;
+
+ }
+
+ function __clone() {
+
+ $this->label = $this->label;
+ $this->line = $this->line;
+ $this->title = $this->title;
+
+ foreach($this->ticks as $name => $tick) {
+ $this->ticks[$name] = $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);
+}
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Border.class.php b/external-libs/Artichow/php4/inc/Border.class.php
new file mode 100644
index 00000000000..5e8f6f50f99
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Border.class.php
@@ -0,0 +1,158 @@
+setStyle($style);
+
+ if(is_a($color, 'awColor')) {
+ $this->setColor($color);
+ } else {
+ $this->setColor(new awBlack);
+ }
+
+ }
+
+ /**
+ * Change border color
+ * This method automatically shows the border if it is hidden
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->color = $color;
+ $this->show();
+ }
+
+ /**
+ * Change border style
+ *
+ * @param int $style
+ */
+ function setStyle($style) {
+ $this->style = (int)$style;
+ }
+
+ /**
+ * Hide border ?
+ *
+ * @param bool $hide
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show border ?
+ *
+ * @param bool $show
+ */
+ function show($show = TRUE) {
+ $this->hide = (bool)!$show;
+ }
+
+ /**
+ * Is the border visible ?
+ *
+ * @return bool
+ */
+ function visible() {
+ return !$this->hide;
+ }
+
+ /**
+ * Draw border as a rectangle
+ *
+ * @param $drawer
+ * @param $p1 Top-left corner
+ * @param $p2 Bottom-right corner
+ */
+ function rectangle($drawer, $p1, $p2) {
+
+ // Border is hidden
+ if($this->hide) {
+ return;
+ }
+
+ $line = new awLine;
+ $line->setStyle($this->style);
+ $line->setLocation($p1, $p2);
+
+ $drawer->rectangle($this->color, $line);
+
+ }
+
+ /**
+ * Draw border as an ellipse
+ *
+ * @param $drawer
+ * @param $center Ellipse center
+ * @param int $width Ellipse width
+ * @param int $height Ellipse height
+ */
+ function ellipse($drawer, $center, $width, $height) {
+
+ // Border is hidden
+ if($this->hide) {
+ return;
+ }
+
+ switch($this->style) {
+
+ case LINE_SOLID :
+ $drawer->ellipse($this->color, $center, $width, $height);
+ break;
+
+ default :
+ trigger_error("Dashed and dotted borders and not yet implemented on ellipses", E_USER_ERROR);
+ break;
+
+ }
+
+
+ }
+
+}
+
+registerClass('Border');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Color.class.php b/external-libs/Artichow/php4/inc/Color.class.php
new file mode 100644
index 00000000000..5b40a5c926a
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Color.class.php
@@ -0,0 +1,201 @@
+red = (int)$red;
+ $this->green = (int)$green;
+ $this->blue = (int)$blue;
+ $this->alpha = (int)round($alpha * 127 / 100);
+
+ }
+
+ /**
+ * Return a GDised color
+ *
+ * @param resource $resource A GD resource
+ * @return int
+ */
+ function getColor($resource) {
+
+ $this->resource = $resource;
+
+ if($this->color === NULL) {
+
+ if($this->alpha === 0 or function_exists('imagecolorallocatealpha') === FALSE) {
+ $this->color = imagecolorallocate($this->resource, $this->red, $this->green, $this->blue);
+ } else {
+ $this->color = imagecolorallocatealpha($this->resource, $this->red, $this->green, $this->blue, $this->alpha);
+ }
+
+ }
+
+ return $this->color;
+
+ }
+
+ /**
+ * Change color brightness
+ *
+ * @param int $brightness Add this intensity to the color (betweeen -255 and +255)
+ */
+ 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
+ */
+ function rgba() {
+
+ return array($this->red, $this->green, $this->blue, $this->alpha);
+
+ }
+
+ /**
+ * Free resources used for this color
+ */
+ function free() {
+
+ if($this->resource !== NULL) {
+
+ @imagecolordeallocate($this->resource, $this->color);
+ $this->resource = NULL;
+
+ }
+
+ }
+
+ function php5Destructor() {
+
+ $this->free();
+
+ }
+
+}
+
+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 {
+
+ function aw'.$name.'($alpha = 0) {
+ parent::awColor('.$red.', '.$green.', '.$blue.', $alpha);
+ }
+
+ }
+ ';
+
+ if(ARTICHOW_PREFIX !== 'aw') {
+ $php .= '
+ class '.ARTICHOW_PREFIX.$name.' extends aw'.$name.' {
+
+ }
+ ';
+ }
+
+}
+
+eval($php);
+
+
+
+?>
diff --git a/external-libs/Artichow/php4/inc/Drawer.class.php b/external-libs/Artichow/php4/inc/Drawer.class.php
new file mode 100644
index 00000000000..e145056a413
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Drawer.class.php
@@ -0,0 +1,1131 @@
+resource = $resource;
+
+ }
+
+ /**
+ * Change the image size
+ *
+ * @param int $width Image width
+ * @param int $height Image height
+ */
+ function setImageSize($width, $height) {
+
+ $this->width = $width;
+ $this->height = $height;
+
+ }
+
+ /**
+ * Inform the drawer 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
+ */
+ function setPosition($x, $y) {
+
+ // Calcul absolute position
+ $this->x = round($x * $this->width - $this->w / 2);
+ $this->y = round($y * $this->height - $this->h / 2);
+
+ }
+
+ /**
+ * Inform the drawer 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
+ */
+ 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
+ */
+ function movePosition($x, $y) {
+
+ $this->x += (int)$x;
+ $this->y += (int)$y;
+
+ }
+
+ /**
+ * Inform the drawer 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
+ */
+ function setSize($w, $h) {
+
+ // Calcul absolute size
+ $this->w = round($w * $this->width);
+ $this->h = round($h * $this->height);
+
+ return $this->getSize();
+
+ }
+
+ /**
+ * Inform the drawer of the size of your image
+ * You can set absolute size with this method.
+ *
+ * @param int $w Image width
+ * @param int $h Image height
+ */
+ function setAbsSize($w, $h) {
+
+ $this->w = $w;
+ $this->h = $h;
+
+ return $this->getSize();
+
+ }
+
+ /**
+ * Get the size of the component handled by the drawer
+ *
+ * @return array Absolute width and height of the component
+ */
+ function getSize() {
+
+ return array($this->w, $this->h);
+
+ }
+
+ /**
+ * Draw an image here
+ *
+ * @param &$image Image
+ * @param int $p1 Image top-left point
+ * @param int $p2 Image bottom-right point
+ */
+ function copyImage(&$image, $p1, $p2) {
+
+ list($x1, $y1) = $p1->getLocation();
+ list($x2, $y2) = $p2->getLocation();
+
+ $drawer = $image->getDrawer();
+ imagecopy($this->resource, $drawer->resource, $this->x + $x1, $this->y + $y1, 0, 0, $x2 - $x1, $y2 - $y1);
+
+ }
+
+ /**
+ * Draw an image here
+ *
+ * @param &$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)
+ */
+ function copyResizeImage(&$image, $d1, $d2, $s1, $s2, $resample = TRUE) {
+
+ if($resample) {
+ $function = 'imagecopyresampled';
+ } else {
+ $function = 'imagecopyresized';
+ }
+
+ $drawer = $image->getDrawer();
+
+ $function(
+ $this->resource,
+ $drawer->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
+ );
+
+ }
+
+ /**
+ * Draw a string
+ *
+ * @var &$text Text to print
+ * @param $point Draw the text at this point
+ */
+ function string(&$text, $point) {
+
+ $font = $text->getFont();
+
+ if($text->getBackground() !== NULL or $text->border->visible()) {
+
+ list($left, $right, $top, $bottom) = $text->getPadding();
+
+ $width = $font->getTextWidth($text);
+ $height = $font->getTextHeight($text);
+
+ $x1 = floor($point->x - $left);
+ $y1 = floor($point->y - $top);
+ $x2 = $x1 + $width + $left + $right;
+ $y2 = $y1 + $height + $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)
+ );
+
+ }
+
+ $font->draw($this, $point, $text);
+
+ }
+
+ /**
+ * Draw a pixel
+ *
+ * @param $color Pixel color
+ * @param $p
+ */
+ function point($color, $p) {
+
+ if($p->isHidden() === FALSE) {
+ $rgb = $color->getColor($this->resource);
+ imagesetpixel($this->resource, $this->x + round($p->x), $this->y + round($p->y), $rgb);
+ }
+
+ }
+
+ /**
+ * Draw a colored line
+ *
+ * @param $color Line color
+ * @param $line
+ * @param int $thickness Line tickness
+ */
+ function line($color, $line) {
+
+ if($line->thickness > 0 and $line->isHidden() === FALSE) {
+
+ $rgb = $color->getColor($this->resource);
+ $thickness = $line->thickness;
+
+ list($p1, $p2) = $line->getLocation();
+
+ $this->startThickness($thickness);
+
+ switch($line->getStyle()) {
+
+ case LINE_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 LINE_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 LINE_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;
+
+ for($i = 0; $i <= $size; $i += 6) {
+
+ $t1 = new awPoint(
+ round($i * $cos + $p1->x),
+ round($i * $sin + $p1->y)
+ );
+
+ $function = ($height > 0) ? 'min' : 'max';
+ $t2 = new awPoint(
+ round(min(($i + 3) * $cos, $width) + $p1->x),
+ round($function(($i + 3) * $sin, $height) + $p1->y)
+ );
+
+ $this->line($color, new awLine($t1, $t2));
+
+ }
+ break;
+
+ }
+
+ $this->stopThickness($thickness);
+
+ }
+
+ }
+
+ /**
+ * Draw a color arc
+
+ * @param $color Arc color
+ * @param $center Point center
+ * @param int $width Ellipse width
+ * @param int $height Ellipse height
+ * @param int $from Start angle
+ * @param int $to End angle
+ */
+ function arc($color, $center, $width, $height, $from, $to) {
+
+ imagefilledarc(
+ $this->resource,
+ $this->x + $center->x, $this->y + $center->y,
+ $width, $height,
+ $from, $to,
+ $color->getColor($this->resource),
+ IMG_ARC_EDGED | IMG_ARC_NOFILL
+ );
+
+ }
+
+ /**
+ * Draw an arc with a background color
+ *
+ * @param $color Arc background color
+ * @param $center Point center
+ * @param int $width Ellipse width
+ * @param int $height Ellipse height
+ * @param int $from Start angle
+ * @param int $to End angle
+ */
+ function filledArc($color, $center, $width, $height, $from, $to) {
+
+ imagefilledarc(
+ $this->resource,
+ $this->x + $center->x, $this->y + $center->y,
+ $width, $height,
+ $from, $to,
+ $color->getColor($this->resource),
+ IMG_ARC_PIE
+ );
+
+ }
+
+ /**
+ * Draw a colored ellipse
+ *
+ * @param $color Ellipse color
+ * @param $center Ellipse center
+ * @param int $width Ellipse width
+ * @param int $height Ellipse height
+ */
+ function ellipse($color, $center, $width, $height) {
+
+ list($x, $y) = $center->getLocation();
+
+ $rgb = $color->getColor($this->resource);
+ imageellipse(
+ $this->resource,
+ $this->x + $x,
+ $this->y + $y,
+ $width,
+ $height,
+ $rgb
+ );
+
+ }
+
+ /**
+ * Draw an ellipse with a background
+ *
+ * @param mixed $background Background (can be a color or a gradient)
+ * @param $center Ellipse center
+ * @param int $width Ellipse width
+ * @param int $height Ellipse height
+ */
+ function filledEllipse($background, $center, $width, $height) {
+
+ if(is_a($background, 'awColor')) {
+
+ list($x, $y) = $center->getLocation();
+
+ $rgb = $background->getColor($this->resource);
+
+ imagefilledellipse(
+ $this->resource,
+ $this->x + $x,
+ $this->y + $y,
+ $width,
+ $height,
+ $rgb
+ );
+
+ } else if(is_a($background, 'awGradient')) {
+
+ list($x, $y) = $center->getLocation();
+
+ $x1 = $x - round($width / 2);
+ $y1 = $y - round($height / 2);
+ $x2 = $x1 + $width;
+ $y2 = $y1 + $height;
+
+ $gradientDrawer = new awGradientDrawer($this);
+ $gradientDrawer->filledEllipse(
+ $background,
+ $x1, $y1,
+ $x2, $y2
+ );
+
+ }
+
+ }
+
+ /**
+ * Draw a colored rectangle
+ *
+ * @param $color Rectangle color
+ * @param $line Rectangle diagonale
+ * @param $p2
+ */
+ function rectangle($color, $line) {
+
+ $p1 = $line->p1;
+ $p2 = $line->p2;
+
+ switch($line->getStyle()) {
+
+ case LINE_SOLID :
+ $thickness = $line->getThickness();
+ $this->startThickness($thickness);
+ $rgb = $color->getColor($this->resource);
+ 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 :
+
+ // Top side
+ $line->setLocation(
+ new awPoint($p1->x, $p1->y),
+ new awPoint($p2->x, $p1->y)
+ );
+ $this->line($color, $line);
+
+ // Right side
+ $line->setLocation(
+ new awPoint($p2->x, $p1->y),
+ new awPoint($p2->x, $p2->y)
+ );
+ $this->line($color, $line);
+
+ // Bottom side
+ $line->setLocation(
+ new awPoint($p1->x, $p2->y),
+ new awPoint($p2->x, $p2->y)
+ );
+ $this->line($color, $line);
+
+ // Left side
+ $line->setLocation(
+ new awPoint($p1->x, $p1->y),
+ new awPoint($p1->x, $p2->y)
+ );
+ $this->line($color, $line);
+
+ break;
+
+ }
+
+ }
+
+ /**
+ * Draw a rectangle with a background
+ *
+ * @param mixed $background Background (can be a color or a gradient)
+ * @param $line Rectangle diagonale
+ */
+ function filledRectangle($background, $line) {
+
+ $p1 = $line->p1;
+ $p2 = $line->p2;
+
+ if(is_a($background, 'awColor')) {
+ $rgb = $background->getColor($this->resource);
+ imagefilledrectangle($this->resource, $this->x + $p1->x, $this->y + $p1->y, $this->x + $p2->x, $this->y + $p2->y, $rgb);
+ } else if(is_a($background, 'awGradient')) {
+ $gradientDrawer = new awGradientDrawer($this);
+ $gradientDrawer->filledRectangle($background, $p1, $p2);
+ }
+
+ }
+
+ /**
+ * Draw a polygon
+ *
+ * @param $color Polygon color
+ * @param Polygon A polygon
+ */
+ function polygon($color, &$polygon) {
+
+ switch($polygon->getStyle()) {
+
+ case POLYGON_SOLID :
+ $thickness = $line->getThickness();
+ $this->startThickness($thickness);
+ $points = $this->getPolygonPoints($polygon);
+ $rgb = $color->getColor($this->resource);
+ 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;
+ }
+
+ }
+
+ }
+
+ }
+
+ /**
+ * Draw a polygon with a background
+ *
+ * @param mixed $background Background (can be a color or a gradient)
+ * @param Polygon A polygon
+ */
+ function filledPolygon($background, &$polygon) {
+
+ if(is_a($background, 'awColor')) {
+ $points = $this->getPolygonPoints($polygon);
+ $rgb = $background->getColor($this->resource);
+ imagefilledpolygon($this->resource, $points, $polygon->count(), $rgb);
+ } else if(is_a($background, 'awGradient')) {
+ $gradientDrawer = new awGradientDrawer($this);
+ $gradientDrawer->filledPolygon($background, $polygon);
+ }
+
+ }
+
+ function getPolygonPoints(&$polygon) {
+
+ $points = array();
+
+ foreach($polygon->all() as $point) {
+ $points[] = $point->x + $this->x;
+ $points[] = $point->y + $this->y;
+ }
+
+ return $points;
+
+ }
+
+ function startThickness($thickness) {
+
+ if($thickness > 1) {
+
+ // Beurk :'(
+ if(function_exists('imageantialias')) {
+ imageantialias($this->resource, FALSE);
+ }
+ imagesetthickness($this->resource, $thickness);
+
+ }
+
+ }
+
+ function stopThickness($thickness) {
+
+ if($thickness > 1) {
+
+ if(function_exists('imageantialias')) {
+ imageantialias($this->resource, TRUE);
+ }
+ imagesetthickness($this->resource, 1);
+
+ }
+
+ }
+
+
+}
+
+registerClass('Drawer');
+
+/**
+ * To your gradients
+ *
+ * @package Artichow
+ */
+
+class awGradientDrawer {
+
+ /**
+ * A drawer
+ *
+ * @var Drawer
+ */
+ var $drawer;
+
+ /**
+ * Build your GradientDrawer
+ *
+ * @var $drawer
+ */
+ function awGradientDrawer($drawer) {
+
+ $this->drawer = $drawer;
+
+ }
+
+ function drawFilledFlatTriangle($gradient, $a, $b, $c) {
+
+ if($gradient->angle !== 0) {
+ trigger_error("Flat triangles can only be used with 0 degree gradients", E_USER_ERROR);
+ }
+
+ // Look for right-angled triangle
+ if($a->x !== $b->x and $b->x !== $c->x) {
+ trigger_error("Not right-angled flat triangles are not supported yet", E_USER_ERROR);
+ }
+
+ 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->drawer->filledRectangle($color, new awLine($p1, $p2));
+
+ $color->free();
+ unset($color);
+
+ }
+
+ }
+
+ function filledRectangle($gradient, $p1, $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(is_a($gradient, 'awLinearGradient')) {
+ $this->rectangleLinearGradient($gradient, new awPoint($x1, $y1), new awPoint($x2, $y2));
+ } else {
+ trigger_error("This gradient is not supported by rectangles", E_USER_ERROR);
+ }
+
+ }
+
+ function filledPolygon($gradient, &$polygon) {
+
+ if(is_a($gradient, 'awLinearGradient')) {
+ $this->polygonLinearGradient($gradient, $polygon);
+ } else {
+ trigger_error("This gradient is not supported by polygons", E_USER_ERROR);
+ }
+
+ }
+
+ function rectangleLinearGradient(&$gradient, $p1, $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->drawer->filledRectangle($color, new awLine($p1, $p2));
+
+ $color->free();
+ 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->drawer->filledRectangle($color, new awLine($p1, $p2));
+
+ $color->free();
+ unset($color);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ function filledEllipse($gradient, $x1, $y1, $x2, $y2) {
+
+ if($y1 < $y2) {
+ $y1 ^= $y2 ^= $y1 ^= $y2;
+ }
+
+ if($x2 < $x1) {
+ $x1 ^= $x2 ^= $x1 ^= $x2;
+ }
+
+ if(is_a($gradient, 'awRadialGradient')) {
+ $this->ellipseRadialGradient($gradient, $x1, $y1, $x2, $y2);
+ } else if(is_a($gradient, 'awLinearGradient')) {
+ $this->ellipseLinearGradient($gradient, $x1, $y1, $x2, $y2);
+ } else {
+ trigger_error("This gradient is not supported by ellipses", E_USER_ERROR);
+ }
+
+ }
+
+ function ellipseRadialGradient($gradient, $x1, $y1, $x2, $y2) {
+
+ if($y1 - $y2 > 0) {
+
+ if($y1 - $y2 != $x2 - $x1) {
+ trigger_error("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->drawer->point($color, new awPoint($c->x + $x, $c->y + $y));
+
+ $ok[(int)$x][(int)$y] = TRUE;
+
+ }
+
+ }
+
+ }
+
+ $color->free();
+ unset($color);
+
+ }
+
+ }
+
+ }
+
+ function ellipseLinearGradient($gradient, $x1, $y1, $x2, $y2) {
+
+ // Gauche->droite : 90°
+
+ if($y1 - $y2 > 0) {
+
+ if($y1 - $y2 != $x2 - $x1) {
+ trigger_error("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->drawer->filledRectangle($color, new awLine($p1, $p2));
+
+ $color->free();
+ unset($color);
+
+ }
+
+ }
+
+ }
+
+ function polygonLinearGradient(&$gradient, &$polygon) {
+
+ $count = $polygon->count();
+
+ if($count >= 3) {
+
+ $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->drawer->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
+ );
+
+
+ $gradientDrawer = new awGradientDrawer($this->drawer);
+ $gradientDrawer->drawFilledFlatTriangle(
+ $gradient,
+ new awPoint($prev->x, min($prev->y, $current->y)),
+ $top,
+ new awPoint($current->x, min($prev->y, $current->y))
+ );
+ unset($gradientDrawer);
+
+ $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->drawer->filledRectangle($color, awLine::build($x, $y1, $x, $y2));
+ $color->free();
+ unset($color);
+
+ // Jump to next point
+ if($next->x == $i + $left->x) {
+
+ $this->next($polygon, $pos, $prev, $next);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ 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
+ */
+ var $r1, $g1, $b1, $a1;
+
+ /**
+ * Stop colors
+ *
+ * @var int
+ */
+ var $r2, $g2, $b2, $a2;
+
+ /**
+ * Gradient size in pixels
+ *
+ * @var int
+ */
+ var $size;
+
+
+ function init($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;
+ }
+
+ function color($pos) {
+
+ return new awColor(
+ $this->getRed($pos),
+ $this->getGreen($pos),
+ $this->getBlue($pos),
+ $this->getAlpha($pos)
+ );
+
+ }
+
+
+ function getRed($pos) {
+ return (int)round($this->r1 + ($pos / $this->size) * ($this->r2 - $this->r1));
+ }
+
+ function getGreen($pos) {
+ return (int)round($this->g1 + ($pos / $this->size) * ($this->g2 - $this->g1));
+ }
+
+ function getBlue($pos) {
+ return (int)round($this->b1 + ($pos / $this->size) * ($this->b2 - $this->b1));
+ }
+
+ function getAlpha($pos) {
+ return (int)round(($this->a1 + ($pos / $this->size) * ($this->a2 - $this->a1)) / 127 * 100);
+ }
+
+}
+
+registerClass('GradientDrawer');
+?>
diff --git a/external-libs/Artichow/php4/inc/Font.class.php b/external-libs/Artichow/php4/inc/Font.class.php
new file mode 100644
index 00000000000..3648e5dd35a
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Font.class.php
@@ -0,0 +1,295 @@
+font = $font;
+
+ }
+
+ /**
+ * Draw a text
+ *
+ * @param $drawer
+ * @param $p Draw text at this point
+ * @param &$text The text
+ */
+ function draw($drawer, $p, &$text) {
+
+ $angle = $text->getAngle();
+
+ if($angle !== 90 and $angle !== 0) {
+ trigger_error("You can only use 0° and 90°", E_USER_ERROR);
+ }
+
+ if($angle === 90) {
+ $function = 'imagestringup';
+ } else {
+ $function = 'imagestring';
+ }
+
+ if($angle === 90) {
+ $add = $this->getTextHeight($text);
+ } else {
+ $add = 0;
+ }
+
+ $color = $text->getColor();
+ $rgb = $color->getColor($drawer->resource);
+
+ $function(
+ $drawer->resource,
+ $this->font,
+ $drawer->x + $p->x,
+ $drawer->y + $p->y + $add,
+ $text->getText(),
+ $rgb
+ );
+
+ }
+
+ /**
+ * Get the width of a string
+ *
+ * @param &$text A string
+ */
+ function getTextWidth(&$text) {
+
+ if($text->getAngle() === 90) {
+ $text->setAngle(45);
+ return $this->getTextHeight($text);
+ } else if($text->getAngle() === 45) {
+ $text->setAngle(90);
+ }
+
+ $font = $text->getFont();
+ $fontWidth = imagefontwidth($font->font);
+
+ if($fontWidth === FALSE) {
+ trigger_error("Unable to get font size", E_USER_ERROR);
+ }
+
+ return (int)$fontWidth * strlen($text->getText());
+
+ }
+
+ /**
+ * Get the height of a string
+ *
+ * @param &$text A string
+ */
+ function getTextHeight(&$text) {
+
+ if($text->getAngle() === 90) {
+ $text->setAngle(45);
+ return $this->getTextWidth($text);
+ } else if($text->getAngle() === 45) {
+ $text->setAngle(90);
+ }
+
+ $font = $text->getFont();
+ $fontHeight = imagefontheight($font->font);
+
+ if($fontHeight === FALSE) {
+ trigger_error("Unable to get font size", E_USER_ERROR);
+ }
+
+ return (int)$fontHeight;
+
+ }
+
+}
+
+registerClass('Font');
+
+/**
+ * TTF fonts
+ *
+ * @package Artichow
+ */
+class awTTFFont extends awFont {
+
+ /**
+ * Font size
+ *
+ * @var int
+ */
+ var $size;
+
+ /**
+ * Font file
+ *
+ * @param string $font Font file
+ * @param int $size Font size
+ */
+ function awTTFFont($font, $size) {
+
+ parent::awFont($font);
+
+ $this->size = (int)$size;
+
+ }
+
+ /**
+ * Draw a text
+ *
+ * @param $drawer
+ * @param $p Draw text at this point
+ * @param &$text The text
+ */
+ function draw($drawer, $p, &$text) {
+
+ // Make easier font positionment
+ $text->setText($text->getText()." ");
+
+ $color = $text->getColor();
+ $rgb = $color->getColor($drawer->resource);
+
+ $box = imagettfbbox($this->size, $text->getAngle(), $this->font, $text->getText());
+
+ $height = - $box[5];
+
+ $box = imagettfbbox($this->size, 90, $this->font, $text->getText());
+ $width = abs($box[6] - $box[2]);
+
+ // Restore old text
+ $text->setText(substr($text->getText(), 0, strlen($text->getText()) - 1));
+
+ imagettftext(
+ $drawer->resource,
+ $this->size,
+ $text->getAngle(),
+ $drawer->x + $p->x + $width * sin($text->getAngle() / 180 * M_PI),
+ $drawer->y + $p->y + $height,
+ $rgb,
+ $this->font,
+ $text->getText()
+ );
+
+ }
+
+ /**
+ * Get the width of a string
+ *
+ * @param &$text A string
+ */
+ function getTextWidth(&$text) {
+
+ $box = imagettfbbox($this->size, $text->getAngle(), $this->font, $text->getText());
+
+ if($box === FALSE) {
+ trigger_error("Unable to get font size", E_USER_ERROR);
+ return;
+ }
+
+ list(, , $x2, $y2, , , $x1, $y1) = $box;
+
+ return abs($x2 - $x1);
+
+ }
+
+ /**
+ * Get the height of a string
+ *
+ * @param &$text A string
+ */
+ function getTextHeight(&$text) {
+
+ $box = imagettfbbox($this->size, $text->getAngle(), $this->font, $text->getText());
+
+ if($box === FALSE) {
+ trigger_error("Unable to get font size", E_USER_ERROR);
+ return;
+ }
+
+ list(, , $x2, $y2, , , $x1, $y1) = $box;
+
+ return abs($y2 - $y1);
+
+ }
+
+}
+
+registerClass('TTFFont');
+
+
+
+$php = '';
+
+for($i = 1; $i <= 5; $i++) {
+
+ $php .= '
+ class awFont'.$i.' extends awFont {
+
+ function awFont'.$i.'() {
+ parent::awFont('.$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 awTTFFont {
+
+ function aw'.$font.'($size) {
+ parent::awTTFFont(\''.(ARTICHOW_FONT.DIRECTORY_SEPARATOR.$font.'.ttf').'\', $size);
+ }
+
+ }
+ ';
+
+ if(ARTICHOW_PREFIX !== 'aw') {
+ $php .= '
+ class '.ARTICHOW_PREFIX.$font.' extends aw'.$font.' {
+ }
+ ';
+ }
+
+}
+
+eval($php);
+
+
+
+?>
diff --git a/external-libs/Artichow/php4/inc/Gradient.class.php b/external-libs/Artichow/php4/inc/Gradient.class.php
new file mode 100644
index 00000000000..52abec7e64c
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Gradient.class.php
@@ -0,0 +1,149 @@
+from = $from;
+ $this->to = $to;
+
+ }
+
+ /**
+ * Free memory used by the colors of the gradient
+ */
+ function free() {
+
+ $this->from->free();
+ $this->to->free();
+
+ }
+
+ function php5Destructor( ){
+
+ $this->free();
+
+ }
+
+}
+
+registerClass('Gradient', TRUE);
+
+
+/**
+ * Create a linear gradient
+ *
+ * @package Artichow
+ */
+class awLinearGradient extends awGradient {
+
+ /**
+ * Gradient angle
+ *
+ * @var int
+ */
+ var $angle;
+
+ /**
+ * Build the linear gradient
+ *
+ * @param $from From color
+ * @param $to To color
+ * @param int $angle Gradient angle
+ */
+ function awLinearGradient($from, $to, $angle) {
+
+ parent::awGradient(
+ $from, $to
+ );
+
+ $this->angle = $angle;
+
+ }
+
+}
+
+registerClass('LinearGradient');
+
+
+/**
+ * Create a bilinear gradient
+ *
+ * @package Artichow
+ */
+class awBilinearGradient extends awLinearGradient {
+
+ /**
+ * Gradient center
+ *
+ * @var int Center between 0 and 1
+ */
+ var $center;
+
+ /**
+ * Build the bilinear gradient
+ *
+ * @param $from From color
+ * @param $to To color
+ * @param int $angle Gradient angle
+ * @param int $center Gradient center
+ */
+ function awBilinearGradient($from, $to, $angle, $center = 0.5) {
+
+ parent::awLinearGradient(
+ $from, $to, $angle
+ );
+
+ $this->center = $center;
+
+ }
+
+}
+
+registerClass('BilinearGradient');
+
+/**
+ * Create a radial gradient
+ *
+ * @package Artichow
+ */
+class awRadialGradient extends awGradient {
+
+}
+
+registerClass('RadialGradient');
+?>
diff --git a/external-libs/Artichow/php4/inc/Grid.class.php b/external-libs/Artichow/php4/inc/Grid.class.php
new file mode 100644
index 00000000000..d9b86723f3f
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Grid.class.php
@@ -0,0 +1,289 @@
+color = new awColor(210, 210, 210);
+ $this->background = new awColor(255, 255, 255, 100);
+
+ }
+
+ /**
+ * Hide grid ?
+ *
+ * @param bool $hide
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Hide horizontal lines ?
+ *
+ * @param bool $hideHorizontal
+ */
+ function hideHorizontal($hide = TRUE) {
+ $this->hideHorizontal = (bool)$hide;
+ }
+
+ /**
+ * Hide vertical lines ?
+ *
+ * @param bool $hideVertical
+ */
+ function hideVertical($hide = TRUE) {
+ $this->hideVertical = (bool)$hide;
+ }
+
+ /**
+ * Change grid color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->color = $color;
+ }
+
+ /**
+ * Remove grid background
+ */
+ function setNoBackground() {
+ $this->background = NULL;
+ }
+
+ /**
+ * Change grid background color
+ *
+ * @param $color
+ */
+ function setBackgroundColor($color) {
+ $this->background = $color;
+ }
+
+ /**
+ * Change line type
+ *
+ * @param int $type
+ */
+ function setType($type) {
+ $this->type = (int)$type;
+ }
+
+ /**
+ * Change grid interval
+ *
+ * @param int $hInterval
+ * @param int $vInterval
+ */
+ 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
+ */
+ 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
+ */
+ function setGrid($xgrid, $ygrid) {
+
+ $this->xgrid = $xgrid;
+ $this->ygrid = $ygrid;
+
+ }
+
+ /**
+ * Draw grids
+ *
+ * @param $drawer A drawer object
+ * @param int $x1
+ * @param int $y1
+ * @param int $x2
+ * @param int $y2
+ */
+ function draw($drawer, $x1, $y1, $x2, $y2) {
+
+ if(is_a($this->background, 'awColor')) {
+
+ // Draw background color
+ $drawer->filledRectangle(
+ $this->background,
+ awLine::build($x1, $y1, $x2, $y2)
+ );
+
+ $this->background->free();
+
+ }
+
+ if($this->hide === FALSE) {
+
+ $this->drawGrid(
+ $drawer,
+ $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]
+ );
+
+ }
+
+ $this->color->free();
+
+ }
+
+ function drawGrid(
+ $drawer, $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);
+ $drawer->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);
+ $drawer->line(
+ $color,
+ new awLine(
+ new awPoint($x1, $pos),
+ new awPoint($x2, $pos),
+ $type
+ )
+ );
+
+ }
+
+ }
+
+ }
+
+}
+
+registerClass('Grid');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Label.class.php b/external-libs/Artichow/php4/inc/Label.class.php
new file mode 100644
index 00000000000..ac6cb7eb662
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Label.class.php
@@ -0,0 +1,596 @@
+ */
+
+define("LABEL_LEFT", 1);
+define("LABEL_RIGHT", 2);
+define("LABEL_CENTER", 3);
+define("LABEL_TOP", 4);
+define("LABEL_BOTTOM", 5);
+define("LABEL_MIDDLE", 6);
+
+/* */
+
+/**
+ * Draw labels
+ *
+ * @package Artichow
+ */
+class awLabel {
+
+ /**
+ * Label border
+ *
+ * @var int
+ */
+ var $border;
+
+ /**
+ * Label texts
+ *
+ * @var array
+ */
+ var $texts;
+
+ /**
+ * Text font
+ *
+ * @var int
+ */
+ var $font;
+
+ /**
+ * Text angle
+ *
+ * @var int
+ */
+ var $angle = 0;
+
+ /**
+ * Text color
+ *
+ * @var Color
+ */
+ var $color;
+
+ /**
+ * Text background
+ *
+ * @var Color, Gradient
+ */
+ var $background;
+
+ /**
+ * Callback function
+ *
+ * @var string
+ */
+ var $function;
+
+ /**
+ * Padding
+ *
+ * @var int
+ */
+ var $padding;
+
+ /**
+ * Move position from this vector
+ *
+ * @var Point
+ */
+ var $move;
+
+ /**
+ * Label interval
+ *
+ * @var int
+ */
+ var $interval = 1;
+
+ /**
+ * Horizontal align
+ *
+ * @var int
+ */
+ var $hAlign = LABEL_CENTER;
+
+ /**
+ * Vertical align
+ *
+ * @var int
+ */
+ var $vAlign = LABEL_MIDDLE;
+
+ /**
+ * Hide all labels ?
+ *
+ * @var bool
+ */
+ var $hide = FALSE;
+
+ /**
+ * Keys to hide
+ *
+ * @var array
+ */
+ var $hideKey = array();
+
+ /**
+ * Values to hide
+ *
+ * @var array
+ */
+ var $hideValue = array();
+
+ /**
+ * Hide first label
+ *
+ * @var bool
+ */
+ var $hideFirst = FALSE;
+
+ /**
+ * Hide last label
+ *
+ * @var bool
+ */
+ var $hideLast = FALSE;
+
+ /**
+ * Build the label
+ *
+ * @param string $label First label
+ */
+ function awLabel($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(is_a($color, '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
+ */
+ function get($key) {
+ return array_key_exists($key, $this->texts) ? $this->texts[$key] : NULL;
+ }
+
+ /**
+ * Get all labels
+ *
+ * @return array
+ */
+ function all() {
+ return $this->texts;
+ }
+
+ /**
+ * Set one or several labels
+ *
+ * @param array $labels Array of string or a string
+ */
+ function set($labels) {
+
+ if(is_string($labels)) {
+ $this->texts = array($labels);
+ } else if(is_array($labels)) {
+ $this->texts = $labels;
+ }
+
+ }
+
+ /**
+ * Count number of texts in the label
+ *
+ * @return int
+ */
+ function count() {
+ return is_array($this->texts) ? count($this->texts) : 0;
+ }
+
+ /**
+ * Set a callback function for labels
+ *
+ * @param string $function
+ */
+ function setCallbackFunction($function) {
+ $this->function = is_null($function) ? $function : (string)$function;
+ }
+
+ /**
+ * Return the callback function for labels
+ *
+ * @return string
+ */
+ function getCallbackFunction() {
+ return $this->function;
+ }
+
+ /**
+ * Change labels format
+ *
+ * @param string $format New format (printf style: %.2f for example)
+ */
+ 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 &$font New font
+ * @param $color Font color (can be NULL)
+ */
+ function setFont(&$font, $color = NULL) {
+ $this->font = $font;
+ if(is_a($color, 'awColor')) {
+ $this->setColor($color);
+ }
+ }
+
+ /**
+ * Change font angle
+ *
+ * @param int $angle New angle
+ */
+ function setAngle($angle) {
+ $this->angle = (int)$angle;
+ }
+
+ /**
+ * Change font color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->color = $color;
+ }
+
+ /**
+ * Change text background
+ *
+ * @param mixed $background
+ */
+ function setBackground($background) {
+ $this->background = $background;
+ }
+
+ /**
+ * Change text background color
+ *
+ * @param Color
+ */
+ function setBackgroundColor($color) {
+ $this->background = $color;
+ }
+
+ /**
+ * Change text background gradient
+ *
+ * @param Gradient
+ */
+ function setBackgroundGradient($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
+ */
+ function setPadding($left, $right, $top, $bottom) {
+ $this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom);
+ }
+
+ /**
+ * Hide all labels ?
+ *
+ * @param bool $hide
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show all labels ?
+ *
+ * @param bool $show
+ */
+ function show($show = TRUE) {
+ $this->hide = (bool)!$show;
+ }
+
+ /**
+ * Hide a key
+ *
+ * @param int $key The key to hide
+ */
+ function hideKey($key) {
+ $this->hideKey[$key] = TRUE;
+ }
+
+ /**
+ * Hide a value
+ *
+ * @param int $value The value to hide
+ */
+ function hideValue($value) {
+ $this->hideValue[] = $value;
+ }
+
+ /**
+ * Hide first label
+ *
+ * @param bool $hide
+ */
+ function hideFirst($hide) {
+ $this->hideFirst = (bool)$hide;
+ }
+
+ /**
+ * Hide last label
+ *
+ * @param bool $hide
+ */
+ function hideLast($hide) {
+ $this->hideLast = (bool)$hide;
+ }
+
+ /**
+ * Set label interval
+ *
+ * @param int
+ */
+ 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
+ */
+ function move($x, $y) {
+
+ $this->move = $this->move->move($x, $y);
+
+ }
+
+ /**
+ * Change alignment
+ *
+ * @param int $h Horizontal alignment
+ * @param int $v Vertical alignment
+ */
+ 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
+ */
+ 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(is_a($this->background, 'awColor')) {
+ $text->setBackgroundColor($this->background);
+ } else if(is_a($this->background, '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 $drawer A drawer
+ * @return int
+ */
+ function getMaxWidth($drawer) {
+
+ return $this->getMax($drawer, 'getTextWidth');
+
+ }
+
+ /**
+ * Get max height of all texts
+ *
+ * @param $drawer A drawer
+ * @return int
+ */
+ function getMaxHeight($drawer) {
+
+ return $this->getMax($drawer, 'getTextHeight');
+
+ }
+
+ /**
+ * Draw the label
+ *
+ * @param $drawer
+ * @param $p Label center
+ * @param int $key Text position in the array of texts (default to zero)
+ */
+ function draw($drawer, $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 = $font->getTextWidth($text);
+ $height = $font->getTextHeight($text);
+
+ switch($this->hAlign) {
+
+ case LABEL_RIGHT :
+ $x -= ($width + $right);
+ break;
+
+ case LABEL_CENTER :
+ $x -= ($width - $left + $right) / 2;
+ break;
+
+ case LABEL_LEFT :
+ $x += $left;
+ break;
+
+ }
+
+ switch($this->vAlign) {
+
+ case LABEL_TOP :
+ $y -= ($height + $bottom);
+ break;
+
+ case LABEL_MIDDLE :
+ $y -= ($height - $top + $bottom) / 2;
+ break;
+
+ case LABEL_BOTTOM :
+ $y += $top;
+ break;
+
+ }
+
+ $drawer->string($text, $this->move->move($x, $y));
+
+ }
+
+ }
+
+ function getMax($drawer, $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');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Legend.class.php b/external-libs/Artichow/php4/inc/Legend.class.php
new file mode 100644
index 00000000000..2b2d840d3fc
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Legend.class.php
@@ -0,0 +1,691 @@
+ */
+
+define("LEGEND_LINE", 1);
+define("LEGEND_BACKGROUND", 2);
+define("LEGEND_MARK", 3);
+define("LEGEND_MARKONLY", 4);
+
+define("LEGEND_MODEL_RIGHT", 1);
+define("LEGEND_MODEL_BOTTOM", 2);
+
+define("LEGEND_LEFT", 1);
+define("LEGEND_RIGHT", 2);
+define("LEGEND_CENTER", 3);
+define("LEGEND_TOP", 4);
+define("LEGEND_BOTTOM", 5);
+define("LEGEND_MIDDLE", 6);
+
+/* */
+
+/**
+ * Some legends
+ *
+ * @package Artichow
+ */
+class awLegend {
+
+ /**
+ * Legends added
+ *
+ * @var array
+ */
+ var $legends = array();
+
+ /**
+ * The current component
+ *
+ * @var Component
+ */
+ var $component;
+
+ /**
+ * Background color or gradient
+ *
+ * @var Color, Gradient
+ */
+ var $background;
+
+ /**
+ * Text color
+ *
+ * @var Color
+ */
+ var $textColor;
+
+ /**
+ * Text font
+ *
+ * @var Font
+ */
+ var $textFont;
+
+ /**
+ * Text margin
+ *
+ * @var Side
+ */
+ var $textMargin;
+
+ /**
+ * Number of columns
+ *
+ * @var int
+ */
+ var $columns = NULL;
+
+ /**
+ * Number of rows
+ *
+ * @var int
+ */
+ var $rows = NULL;
+
+ /**
+ * Legend position
+ *
+ * @var Point
+ */
+ var $position;
+
+ /**
+ * Hide legend ?
+ *
+ * @var bool
+ */
+ var $hide = FALSE;
+
+ /**
+ * Space between each legend
+ *
+ * @var int
+ */
+ var $space = 4;
+
+ /**
+ * Horizontal alignment
+ *
+ * @var int
+ */
+ var $hAlign;
+
+ /**
+ * Vertical alignment
+ *
+ * @var int
+ */
+ var $vAlign;
+
+ /**
+ * Margin
+ *
+ * @var array Array for left, right, top and bottom margins
+ */
+ var $margin;
+
+ /**
+ * Legend shadow
+ *
+ * @var Shadow
+ */
+ var $shadow;
+
+ /**
+ * Legend border
+ *
+ * @var Border
+ */
+ var $border;
+
+ /**
+ * Line legend
+ *
+ * @var int
+ */
+
+
+ /**
+ * Color/Gradient background legend
+ *
+ * @var int
+ */
+
+
+ /**
+ * Use marks and line as legend
+ *
+ * @var int
+ */
+
+
+ /**
+ * Use marks as legend
+ *
+ * @var int
+ */
+
+
+ /**
+ * Right side model
+ *
+ * @var int
+ */
+
+
+ /**
+ * Bottom side model
+ *
+ * @var int
+ */
+
+
+ /**
+ * Build the legend
+ *
+ * @param int $model Legend model
+ */
+ function awLegend($model = LEGEND_MODEL_RIGHT) {
+
+ $this->shadow = new awShadow(SHADOW_LEFT_BOTTOM);
+ $this->border = new awBorder;
+
+ $this->textMargin = new awSide(4);
+ $this->setModel($model);
+
+ }
+
+ /**
+ * Set a predefined model for the legend
+ *
+ * @param int $model
+ */
+ 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 LEGEND_MODEL_RIGHT :
+
+ $this->setColumns(1);
+ $this->setAlign(LEGEND_RIGHT, LEGEND_MIDDLE);
+ $this->setPosition(0.96, 0.50);
+
+ break;
+
+ case LEGEND_MODEL_BOTTOM :
+
+ $this->setRows(1);
+ $this->setAlign(LEGEND_CENTER, LEGEND_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
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show legend ?
+ *
+ * @param bool $show
+ */
+ function show($show = TRUE) {
+ $this->hide = (bool)!$show;
+ }
+
+
+ /**
+ * Add a Legendable object to the legend
+ *
+ * @param &$legendable
+ * @param string $title Legend title
+ * @param int $type Legend type (default to LEGEND_LINE)
+ */
+ function add(&$legendable, $title, $type = LEGEND_LINE) {
+
+ $legend = array($legendable, $title, $type);
+
+ $this->legends[] = $legend;
+
+ }
+
+ /**
+ * Change legend padding
+ *
+ * @param int $left
+ * @param int $right
+ * @param int $top
+ * @param int $bottom
+ */
+ 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
+ */
+ function setSpace($space) {
+ $this->space = (int)$space;
+ }
+
+ /**
+ * Change alignment
+ *
+ * @param int $h Horizontal alignment
+ * @param int $v Vertical alignment
+ */
+ 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
+ */
+ function setColumns($columns) {
+ $this->rows = NULL;
+ $this->columns = (int)$columns;
+ }
+
+ /**
+ * Change number of rows
+ *
+ * @param int $rows
+ */
+ 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
+ */
+ 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
+ */
+ function getPosition() {
+ return $this->position;
+ }
+
+ /**
+ * Change text font
+ *
+ * @param &$font
+ */
+ function setTextFont(&$font) {
+ $this->textFont = $font;
+ }
+
+ /**
+ * Change text margin
+ *
+ * @param int $left
+ * @param int $right
+ */
+ function setTextMargin($left, $right) {
+ $this->textMargin->set($left, $right);
+ }
+
+ /**
+ * Change text color
+ *
+ * @param $color
+ */
+ function setTextColor($color) {
+ $this->textColor = $color;
+ }
+
+ /**
+ * Change background
+ *
+ * @param mixed $background
+ */
+ function setBackground($background) {
+ $this->background = $background;
+ }
+
+ /**
+ * Change background color
+ *
+ * @param $color
+ */
+ function setBackgroundColor($color) {
+ $this->background = $color;
+ }
+
+ /**
+ * Change background gradient
+ *
+ * @param $gradient
+ */
+ function setBackgroundGradient($gradient) {
+ $this->background = $gradient;
+ }
+
+ /**
+ * Count the number of Legendable objects in the legend
+ *
+ * @return int
+ */
+ function count() {
+ return count($this->legends);
+ }
+
+ function draw($drawer) {
+
+ 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] = $font->getTextWidth($text) + $this->textMargin->left + $this->textMargin->right;
+ $heights[$i] = $font->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) = $drawer->getSize();
+
+ $p = new awPoint(
+ $this->position->x * $x,
+ $this->position->y * $y
+ );
+
+ switch($this->hAlign) {
+
+ case LEGEND_CENTER :
+ $p->x -= $width / 2;
+ break;
+
+ case LEGEND_RIGHT :
+ $p->x -= $width;
+ break;
+
+ }
+
+ switch($this->vAlign) {
+
+ case LEGEND_MIDDLE :
+ $p->y -= $height / 2;
+ break;
+
+ case LEGEND_BOTTOM :
+ $p->y -= $height;
+ break;
+
+ }
+
+ // Draw legend shadow
+ $this->shadow->draw(
+ $drawer,
+ $p,
+ $p->move($width, $height),
+ SHADOW_OUT
+ );
+
+ // Draw legends base
+ $this->drawBase($drawer, $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
+ $drawer->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 LEGEND_LINE :
+ case LEGEND_MARK :
+ case LEGEND_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(is_a($color, 'awColor') and $type !== LEGEND_MARKONLY) {
+
+ $drawer->line(
+ $color,
+ new awLine(
+ $p->move(
+ $x, // YaPB ??
+ $y + $component->getLegendLineThickness() / 2
+ ),
+ $p->move(
+ $x + 10,
+ $y + $component->getLegendLineThickness() / 2
+ ),
+ $component->getLegendLineStyle(),
+ $component->getLegendLineThickness()
+ )
+ );
+
+ $color->free();
+ unset($color);
+
+ }
+
+ }
+
+ if($type === LEGEND_MARK or $type === LEGEND_MARKONLY) {
+
+ $mark = $component->getLegendMark();
+
+ if($mark !== NULL) {
+ $mark->draw(
+ $drawer,
+ $p->move(
+ $x + 5.5,
+ $y + $component->getLegendLineThickness() / 2
+ )
+ );
+ }
+
+ unset($mark);
+
+ }
+
+ break;
+
+ case LEGEND_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) {
+
+ $drawer->filledRectangle(
+ $component->getLegendBackground(),
+ new awLine($from, $to)
+ );
+
+ // Draw rectangle border
+ $this->border->rectangle(
+ $drawer,
+ $from->move(0, 0),
+ $to->move(0, 0)
+ );
+
+ }
+
+ unset($background, $from, $to);
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ function drawBase($drawer, $p, $width, $height) {
+
+ $this->border->rectangle(
+ $drawer,
+ $p,
+ $p->move($width, $height)
+ );
+
+ $size = $this->border->visible() ? 1 : 0;
+
+ $drawer->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
+ */
+
+
+registerInterface('Legendable');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Mark.class.php b/external-libs/Artichow/php4/inc/Mark.class.php
new file mode 100644
index 00000000000..c88756f7a43
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Mark.class.php
@@ -0,0 +1,335 @@
+ */
+
+define("MARK_CIRCLE", 1);
+define("MARK_SQUARE", 2);
+define("MARK_IMAGE", 3);
+define("MARK_STAR", 4);
+define("MARK_PAPERCLIP", 5);
+define("MARK_BOOK", 6);
+
+/* */
+
+/**
+ * Draw marks
+ *
+ * @package Artichow
+ */
+class awMark {
+
+ /**
+ * Circle mark
+ *
+ * @var int
+ */
+
+
+ /**
+ * Quare mark
+ *
+ * @var int
+ */
+
+
+ /**
+ * Image mark
+ *
+ * @var int
+ */
+
+
+ /**
+ * Star mark
+ *
+ * @var int
+ */
+
+
+ /**
+ * Paperclip mark
+ *
+ * @var int
+ */
+
+
+ /**
+ * Book mark
+ *
+ * @var int
+ */
+
+
+ /**
+ * Must marks be hidden ?
+ *
+ * @var bool
+ */
+ var $hide;
+
+ /**
+ * Mark type
+ *
+ * @var int
+ */
+ var $type;
+
+ /**
+ * Mark size
+ *
+ * @var int
+ */
+ var $size = 8;
+
+ /**
+ * Fill mark
+ *
+ * @var Color, Gradient
+ */
+ var $fill;
+
+ /**
+ * Mark image
+ *
+ * @var Image
+ */
+ var $image;
+
+ /**
+ * To draw marks
+ *
+ * @var Drawer
+ */
+ var $drawer;
+
+ /**
+ * Move position from this vector
+ *
+ * @var Point
+ */
+ var $move;
+
+ /**
+ * Marks border
+ *
+ * @var Border
+ */
+ var $border;
+
+ /**
+ * Build the mark
+ */
+ function awMark() {
+
+ $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
+ */
+ function move($x, $y) {
+
+ $this->move = $this->move->move($x, $y);
+
+ }
+
+ /**
+ * Hide marks ?
+ *
+ * @param bool $hide TRUE to hide marks, FALSE otherwise
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show marks ?
+ *
+ * @param bool $show
+ */
+ function show($show = TRUE) {
+ $this->hide = (bool)!$show;
+ }
+
+ /**
+ * Change mark type
+ *
+ * @param int $size Size in pixels
+ */
+ function setSize($size) {
+ $this->size = (int)$size;
+ }
+
+ /**
+ * Change mark type
+ *
+ * @param int $type New mark type
+ * @param int $size Mark size (can be NULL)
+ */
+ 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
+ */
+ function setFill($fill) {
+ if(is_a($fill, 'awColor') or is_a($fill, 'awGradient')) {
+ $this->fill = $fill;
+ }
+ }
+
+ /**
+ * Set an image
+ * Only for MARK_IMAGE type.
+ *
+ * @param Image An image
+ */
+ function setImage(&$image) {
+ $this->image = $image;
+ }
+
+ /**
+ * Draw the mark
+ *
+ * @param $drawer
+ * @param $point Mark center
+ */
+ function draw($drawer, $point) {
+
+ // Hide marks ?
+ if($this->hide) {
+ return;
+ }
+
+ // Check if we can print marks
+ if($this->type !== NULL) {
+
+ $this->drawer = $drawer;
+ $realPoint = $this->move->move($point->x, $point->y);
+
+ switch($this->type) {
+
+ case MARK_CIRCLE :
+ $this->drawCircle($realPoint);
+ break;
+
+ case MARK_SQUARE :
+ $this->drawSquare($realPoint);
+ break;
+
+ case MARK_IMAGE :
+ $this->drawImage($realPoint);
+ break;
+
+ case MARK_STAR :
+ $this->changeType('star');
+ $this->draw($drawer, $point);
+ break;
+
+ case MARK_PAPERCLIP :
+ $this->changeType('paperclip');
+ $this->draw($drawer, $point);
+ break;
+
+ case MARK_BOOK :
+ $this->changeType('book');
+ $this->draw($drawer, $point);
+ break;
+
+ }
+
+ }
+
+ }
+
+ function changeType($image) {
+ $this->setType(MARK_IMAGE);
+ $this->setImage(new awFileImage(ARTICHOW_IMAGE.DIRECTORY_SEPARATOR.$image.'.png'));
+ }
+
+ function drawCircle($point) {
+
+ $this->drawer->filledEllipse(
+ $this->fill,
+ $point,
+ $this->size, $this->size
+ );
+
+ $this->border->ellipse(
+ $this->drawer,
+ $point,
+ $this->size, $this->size
+ );
+
+ }
+
+ function drawSquare($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->drawer, new awPoint($x1, $y1), new awPoint($x2, $y2));
+
+ $size = $this->border->visible() ? 1 : 0;
+
+ $this->drawer->filledRectangle(
+ $this->fill,
+ new awLine(
+ new awPoint($x1 + $size, $y1 + $size),
+ new awPoint($x2 - $size, $y2 - $size)
+ )
+ );
+
+ }
+
+ function drawImage($point) {
+
+ if(is_a($this->image, '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->drawer, new awPoint($x1 - 1, $y1 - 1), new awPoint($x2 + 1, $y2 + 1));
+
+ $this->drawer->copyImage($this->image, new awPoint($x1, $y1), new awPoint($x2, $y2));
+
+ }
+
+ }
+
+}
+
+registerClass('Mark');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Math.class.php b/external-libs/Artichow/php4/inc/Math.class.php
new file mode 100644
index 00000000000..00716756b76
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Math.class.php
@@ -0,0 +1,492 @@
+style = (int)$style;
+ }
+
+ /**
+ * Return shape style
+ *
+ * @return int
+ */
+ function getStyle() {
+ return $this->style;
+ }
+
+ /**
+ * Change shape thickness
+ *
+ * @param int $thickness Shape thickness in pixels
+ */
+ function setThickness($thickness) {
+ $this->thickness = (int)$thickness;
+ }
+
+ /**
+ * Return shape thickness
+ *
+ * @return int
+ */
+ function getThickness() {
+ return $this->thickness;
+ }
+
+ /**
+ * Hide the shape
+ *
+ * @param bool $hide
+ */
+ function hide($hide) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show the shape
+ *
+ * @param bool $shape
+ */
+ function show($shape) {
+ $this->hide = (bool)!$shape;
+ }
+
+ /**
+ * Is the line hidden ?
+ *
+ * @return bool
+ */
+ function isHidden() {
+ return $this->hide;
+ }
+
+}
+
+registerClass('Shape', TRUE);
+
+/**
+ * Describe a point
+ *
+ * @package Artichow
+ */
+class awPoint extends awShape {
+
+ /**
+ * X coord
+ *
+ * @var float
+ */
+ var $x;
+
+ /**
+ * Y coord
+ *
+ * @var float
+ */
+ var $y;
+
+ /**
+ * Build a new awpoint
+ *
+ * @param float $x
+ * @param float $y
+ */
+ function awPoint($x, $y) {
+
+ $this->setLocation($x, $y);
+
+ }
+
+ /**
+ * Change X value
+ *
+ * @param float $x
+ */
+ function setX($x) {
+ $this->x = (float)$x;
+ }
+
+ /**
+ * Change Y value
+ *
+ * @param float $y
+ */
+ function setY($y) {
+ $this->y = (float)$y;
+ }
+
+ /**
+ * Change point location
+ *
+ * @param float $x
+ * @param float $y
+ */
+ function setLocation($x, $y) {
+ $this->setX($x);
+ $this->setY($y);
+ }
+
+ /**
+ * Get point location
+ *
+ * @param array Point location
+ */
+ function getLocation() {
+ return array($this->x, $this->y);
+ }
+
+ /**
+ * Get distance to another point
+ *
+ * @param $p A point
+ * @return float
+ */
+ function getDistance($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
+ */
+ function move($x, $y) {
+
+ return new awPoint(
+ $this->x + $x,
+ $this->y + $y
+ );
+
+ }
+
+}
+
+registerClass('Point');
+
+/* */
+
+define("LINE_SOLID", 1);
+define("LINE_DOTTED", 2);
+define("LINE_DASHED", 3);
+
+/* */
+
+/**
+ * Describe a line
+ *
+ * @package Artichow
+ */
+class awLine extends awShape {
+
+ /**
+ * Line first point
+ *
+ * @param Point
+ */
+ var $p1;
+
+ /**
+ * Line second point
+ *
+ * @param Point
+ */
+ var $p2;
+
+ /**
+ * Build a new awline
+ *
+ * @param $p1 First point
+ * @param $p2 Second point
+ * @param int $type Style of line (default to solid)
+ * @param int $thickness Line thickness (default to 1)
+ */
+ function awLine($p1 = NULL, $p2 = NULL, $type = LINE_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
+ */
+ 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
+ */
+ function setX($x1, $x2) {
+ $this->p1->setX($x1);
+ $this->p2->setX($x2);
+ }
+
+ /**
+ * Change Y values of the line
+ *
+ * @param int $y1 Begin value
+ * @param int $y2 End value
+ */
+ function setY($y1, $y2) {
+ $this->p1->setY($y1);
+ $this->p2->setY($y2);
+ }
+
+ /**
+ * Change line location
+ *
+ * @param $p1 First point
+ * @param $p2 Second point
+ */
+ function setLocation($p1, $p2) {
+ if(is_null($p1) or is_a($p1, 'awPoint')) {
+ $this->p1 = $p1;
+ }
+ if(is_null($p2) or is_a($p2, 'awPoint')) {
+ $this->p2 = $p2;
+ }
+ }
+
+ /**
+ * Get line location
+ *
+ * @param array Line location
+ */
+ function getLocation() {
+ return array($this->p1, $this->p2);
+ }
+
+ /**
+ * Get the line size
+ *
+ * @return float
+ */
+ function getSize() {
+
+ $square = pow($this->p2->x - $this->p1->x, 2) + pow($this->p2->y - $this->p1->y, 2);
+ return sqrt($square);
+
+ }
+
+ /**
+ * Test if the line can be considered as a point
+ *
+ * @return bool
+ */
+ 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
+ */
+ function isVertical() {
+ return ($this->p1->x === $this->p2->x);
+ }
+
+ /**
+ * Test if the line is an horizontal line
+ *
+ * @return bool
+ */
+ function isHorizontal() {
+ return ($this->p1->y === $this->p2->y);
+ }
+
+}
+
+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
+ */
+ 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');
+
+/* */
+
+define("POLYGON_SOLID", 1);
+define("POLYGON_DOTTED", 2);
+define("POLYGON_DASHED", 3);
+
+/* */
+
+/**
+ * Describe a polygon
+ *
+ * @package Artichow
+ */
+class awPolygon extends awShape {
+
+ /**
+ * Polygon points
+ *
+ * @var array
+ */
+ var $points = array();
+
+ /**
+ * Set a point in the polygon
+ *
+ * @param int $pos Point position
+ * @param $point
+ */
+ function set($pos, $point) {
+ if(is_null($point) or is_a($point, 'awPoint')) {
+ $this->points[$pos] = $point;
+ }
+ }
+
+ /**
+ * Add a point at the end of the polygon
+ *
+ * @param $point
+ */
+ function append($point) {
+ if(is_null($point) or is_a($point, 'awPoint')) {
+ $this->points[] = $point;
+ }
+ }
+
+ /**
+ * Get a point at a position in the polygon
+ *
+ * @param int $pos Point position
+ * @return Point
+ */
+ function get($pos) {
+ return $this->points[$pos];
+ }
+
+ /**
+ * Count number of points in the polygon
+ *
+ * @return int
+ */
+ function count() {
+ return count($this->points);
+ }
+
+ /**
+ * Returns all points in the polygon
+ *
+ * @return array
+ */
+ function all() {
+ return $this->points;
+ }
+
+}
+
+registerClass('Polygon');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Shadow.class.php b/external-libs/Artichow/php4/inc/Shadow.class.php
new file mode 100644
index 00000000000..d117e83905b
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Shadow.class.php
@@ -0,0 +1,415 @@
+ */
+
+define("SHADOW_LEFT_TOP", 1);
+define("SHADOW_LEFT_BOTTOM", 2);
+define("SHADOW_RIGHT_TOP", 3);
+define("SHADOW_RIGHT_BOTTOM", 4);
+
+define("SHADOW_IN", 1);
+define("SHADOW_OUT", 2);
+
+/* */
+
+/**
+ * Draw shadows
+ *
+ */
+class awShadow {
+
+ /**
+ * Shadow on left and top sides
+ *
+ * @var int
+ */
+
+
+ /**
+ * Shadow on left and bottom sides
+ *
+ * @var int
+ */
+
+
+
+ /**
+ * Shadow on right and top sides
+ *
+ * @var int
+ */
+
+
+ /**
+ * Shadow on right and bottom sides
+ *
+ * @var int
+ */
+
+
+ /**
+ * In mode
+ *
+ * @var int
+ */
+
+
+ /**
+ * Out mode
+ *
+ * @var int
+ */
+
+
+ /**
+ * Shadow size
+ *
+ * @var int
+ */
+ var $size = 0;
+
+ /**
+ * Hide shadow ?
+ *
+ * @var bool
+ */
+ var $hide = FALSE;
+
+ /**
+ * Shadow color
+ *
+ * @var Color
+ */
+ var $color;
+
+ /**
+ * Shadow position
+ *
+ * @var int
+ */
+ var $position;
+
+ /**
+ * Smooth shadow ?
+ *
+ * @var bool
+ */
+ var $smooth = FALSE;
+
+ /**
+ * Shadow constructor
+ *
+ * @param int $position Shadow position
+ */
+ function awShadow($position) {
+ $this->setPosition($position);
+ }
+
+ /**
+ * Hide shadow ?
+ *
+ * @param bool $hide
+ */
+ function hide($hide = TRUE) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Show shadow ?
+ *
+ * @param bool $show
+ */
+ function show($show = TRUE) {
+ $this->hide = (bool)!$show;
+ }
+
+ /**
+ * Change shadow size
+ *
+ * @param int $size
+ * @param bool $smooth Smooth the shadow (facultative argument)
+ */
+ function setSize($size, $smooth = NULL) {
+ $this->size = (int)$size;
+ if($smooth !== NULL) {
+ $this->smooth($smooth);
+ }
+ }
+
+ /**
+ * Change shadow color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->color = $color;
+ }
+
+ /**
+ * Change shadow position
+ *
+ * @param int $position
+ */
+ function setPosition($position) {
+ $this->position = (int)$position;
+ }
+
+ /**
+ * Smooth shadow ?
+ *
+ * @param bool $smooth
+ */
+ function smooth($smooth) {
+ $this->smooth = (bool)$smooth;
+ }
+
+ /**
+ * Get the space taken by the shadow
+ *
+ * @return Side
+ */
+ function getSpace() {
+
+ return new awSide(
+ ($this->position === SHADOW_LEFT_TOP or $this->position === SHADOW_LEFT_BOTTOM) ? $this->size : 0,
+ ($this->position === SHADOW_RIGHT_TOP or $this->position === SHADOW_RIGHT_BOTTOM) ? $this->size : 0,
+ ($this->position === SHADOW_LEFT_TOP or $this->position === SHADOW_RIGHT_TOP) ? $this->size : 0,
+ ($this->position === SHADOW_LEFT_BOTTOM or $this->position === SHADOW_RIGHT_BOTTOM) ? $this->size : 0
+ );
+
+ }
+
+ /**
+ * Draw shadow
+ *
+ * @param $drawer
+ * @param $p1 Top-left point
+ * @param $p2 Right-bottom point
+ * @param int Drawing mode
+ */
+ function draw($drawer, $p1, $p2, $mode) {
+
+ if($this->hide) {
+ return;
+ }
+
+ if($this->size <= 0) {
+ return;
+ }
+
+
+
+ $color = (is_a($this->color, 'awColor')) ? $this->color : new awColor(125, 125, 125);
+
+ switch($this->position) {
+
+ case SHADOW_RIGHT_BOTTOM :
+
+ if($mode === SHADOW_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;
+
+ $drawer->setAbsPosition($t1->x + $drawer->x, $t1->y + $drawer->y);
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint($width - $this->size, $this->size),
+ new awPoint($width - 1, $height - 1)
+ )
+ );
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint($this->size, $height - $this->size),
+ new awPoint($width - $this->size - 1, $height - 1)
+ )
+ );
+
+ $this->smoothPast($drawer, $color, $width, $height);
+
+ break;
+
+ case SHADOW_LEFT_TOP :
+
+ if($mode === SHADOW_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;
+
+ $drawer->setAbsPosition($t1->x + $drawer->x, $t1->y + $drawer->y);
+
+ $height = max($height + 1, $this->size);
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint(0, 0),
+ new awPoint($this->size - 1, $height - $this->size - 1)
+ )
+ );
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint($this->size, 0),
+ new awPoint($width - $this->size - 1, $this->size - 1)
+ )
+ );
+
+ $this->smoothPast($drawer, $color, $width, $height);
+
+ break;
+
+ case SHADOW_RIGHT_TOP :
+
+ if($mode === SHADOW_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;
+
+ $drawer->setAbsPosition($t1->x + $drawer->x, $t1->y + $drawer->y);
+
+ $height = max($height + 1, $this->size);
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint($width - $this->size, 0),
+ new awPoint($width - 1, $height - $this->size - 1)
+ )
+ );
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint($this->size, 0),
+ new awPoint($width - $this->size - 1, $this->size - 1)
+ )
+ );
+
+ $this->smoothFuture($drawer, $color, $width, $height);
+
+ break;
+
+ case SHADOW_LEFT_BOTTOM :
+
+ if($mode === SHADOW_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;
+
+ $drawer->setAbsPosition($t1->x + $drawer->x, $t1->y + $drawer->y);
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint(0, $this->size),
+ new awPoint($this->size - 1, $height - 1)
+ )
+ );
+
+ $drawer->filledRectangle(
+ $color,
+ new awLine(
+ new awPoint($this->size, $height - $this->size),
+ new awPoint($width - $this->size - 1, $height - 1)
+ )
+ );
+
+ $this->smoothFuture($drawer, $color, $width, $height);
+
+ break;
+
+ }
+
+ }
+
+ function smoothPast($drawer, $color, $width, $height) {
+
+ if($this->smooth) {
+
+ for($i = 0; $i < $this->size; $i++) {
+ for($j = 0; $j <= $i; $j++) {
+ $drawer->point(
+ $color,
+ new awPoint($i, $j + $height - $this->size)
+ );
+ }
+ }
+
+ for($i = 0; $i < $this->size; $i++) {
+ for($j = 0; $j <= $i; $j++) {
+ $drawer->point(
+ $color,
+ new awPoint($width - $this->size + $j, $i)
+ );
+ }
+ }
+
+ }
+
+ }
+
+ function smoothFuture($drawer, $color, $width, $height) {
+
+ if($this->smooth) {
+
+ for($i = 0; $i < $this->size; $i++) {
+ for($j = 0; $j <= $i; $j++) {
+ $drawer->point(
+ $color,
+ new awPoint($i, $this->size - $j - 1)
+ );
+ }
+ }
+
+ for($i = 0; $i < $this->size; $i++) {
+ for($j = 0; $j <= $i; $j++) {
+ $drawer->point(
+ $color,
+ new awPoint($width - $this->size + $j, $height - $i - 1)
+ );
+ }
+ }
+
+ }
+ }
+
+}
+
+registerClass('Shadow');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Text.class.php b/external-libs/Artichow/php4/inc/Text.class.php
new file mode 100644
index 00000000000..71d9dbe3521
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Text.class.php
@@ -0,0 +1,217 @@
+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
+ */
+ function getText() {
+ return $this->text;
+ }
+
+ /**
+ * Change text
+ *
+ * @param string $text New text
+ */
+ function setText($text) {
+ $this->text = (string)$text;
+ }
+
+ /**
+ * Change text font
+ *
+ * @param Font
+ */
+ function setFont(&$font) {
+ $this->font = $font;
+ }
+
+ /**
+ * Get text font
+ *
+ * @return int
+ */
+ function getFont() {
+ return $this->font;
+ }
+
+ /**
+ * Change text angle
+ *
+ * @param int
+ */
+ function setAngle($angle) {
+ $this->angle = (int)$angle;
+ }
+
+ /**
+ * Get text angle
+ *
+ * @return int
+ */
+ function getAngle() {
+ return $this->angle;
+ }
+
+ /**
+ * Change text color
+ *
+ * @param Color
+ */
+ function setColor($color) {
+ $this->color = $color;
+ }
+
+ /**
+ * Get text color
+ *
+ * @return Color
+ */
+ function getColor() {
+ return $this->color;
+ }
+
+ /**
+ * Change text background color
+ *
+ * @param $color
+ */
+ function setBackgroundColor($color) {
+ $this->background = $color;
+ }
+
+ /**
+ * Change text background gradient
+ *
+ * @param $gradient
+ */
+ function setBackgroundGradient($gradient) {
+ $this->background = $gradient;
+ }
+
+ /**
+ * Get text background
+ *
+ * @return Color, Gradient
+ */
+ 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
+ */
+ function setPadding($left, $right, $top, $bottom) {
+ $this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom);
+ }
+
+ /**
+ * Get current padding
+ *
+ * @return array
+ */
+ function getPadding() {
+ return $this->padding;
+ }
+
+}
+
+registerClass('Text');
+?>
diff --git a/external-libs/Artichow/php4/inc/Tick.class.php b/external-libs/Artichow/php4/inc/Tick.class.php
new file mode 100644
index 00000000000..468a081cf8e
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Tick.class.php
@@ -0,0 +1,349 @@
+ */
+
+define("TICK_IN", 0);
+define("TICK_OUT", 1);
+define("TICK_IN_OUT", 2);
+
+/* */
+
+/**
+ * Handle ticks
+ *
+ * @package Artichow
+ */
+class awTick {
+
+ /**
+ * Ticks style
+ *
+ * @var int
+ */
+ var $style = TICK_IN;
+
+ /**
+ * Ticks size
+ *
+ * @var int
+ */
+ var $size;
+
+ /**
+ * Ticks color
+ *
+ * @var Color
+ */
+ var $color;
+
+ /**
+ * Ticks number
+ *
+ * @var int
+ */
+ var $number;
+
+ /**
+ * Ticks number by other tick
+ *
+ * @var array
+ */
+ var $numberByTick;
+
+ /**
+ * Ticks interval
+ *
+ * @var int
+ */
+ var $interval = 1;
+
+ /**
+ * Hide ticks
+ *
+ * @var bool
+ */
+ var $hide = FALSE;
+
+ /**
+ * Hide first tick
+ *
+ * @var bool
+ */
+ var $hideFirst = FALSE;
+
+ /**
+ * Hide last tick
+ *
+ * @var bool
+ */
+ var $hideLast = FALSE;
+
+ /**
+ * In mode
+ *
+ * @param int
+ */
+
+
+ /**
+ * Out mode
+ *
+ * @param int
+ */
+
+
+ /**
+ * In and out mode
+ *
+ * @param int
+ */
+
+
+ /**
+ * Build the ticks
+ *
+ * @param int $number Number of ticks
+ * @param int $size Ticks size
+ */
+ function awTick($number, $size) {
+
+ $this->setSize($size);
+ $this->setNumber($number);
+ $this->setColor(new awBlack);
+ $this->style = TICK_IN;
+
+ }
+
+ /**
+ * Change ticks style
+ *
+ * @param int $style
+ */
+ function setStyle($style) {
+ $this->style = (int)$style;
+ }
+
+ /**
+ * Get ticks style
+ *
+ * @return int
+ */
+ function getStyle() {
+ return $this->style;
+ }
+
+ /**
+ * Change ticks color
+ *
+ * @param $color
+ */
+ function setColor($color) {
+ $this->color = $color;
+ }
+
+ /**
+ * Change ticks size
+ *
+ * @param int $size
+ */
+ function setSize($size) {
+ $this->size = (int)$size;
+ }
+
+ /**
+ * Change interval of ticks
+ *
+ * @param int $interval
+ */
+ function setInterval($interval) {
+ $this->interval = (int)$interval;
+ }
+
+ /**
+ * Get interval between each tick
+ *
+ * @return int
+ */
+ function getInterval() {
+ return $this->interval;
+ }
+
+ /**
+ * Change number of ticks
+ *
+ * @param int $number
+ */
+ function setNumber($number) {
+ $this->number = (int)$number;
+ }
+
+ /**
+ * Get number of ticks
+ *
+ * @return int
+ */
+ function getNumber() {
+ return $this->number;
+ }
+
+ /**
+ * Change number of ticks relative to others ticks
+ *
+ * @param &$tick Ticks reference
+ * @param int $number Number of ticks
+ */
+ function setNumberByTick(&$tick, $number) {
+
+ $this->numberByTick = array(&$tick, (int)$number);
+
+ }
+
+ /**
+ * Hide ticks
+ *
+ * @param bool $hide
+ */
+ function hide($hide) {
+ $this->hide = (bool)$hide;
+ }
+
+ /**
+ * Hide first tick
+ *
+ * @param bool $hide
+ */
+ function hideFirst($hide) {
+ $this->hideFirst = (bool)$hide;
+ }
+
+ /**
+ * Hide last tick
+ *
+ * @param bool $hide
+ */
+ function hideLast($hide) {
+ $this->hideLast = (bool)$hide;
+ }
+
+ /**
+ * Draw ticks on a vector
+ *
+ * @param $drawer A drawer
+ * @param &$vector A vector
+ */
+ function draw($drawer, &$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."
";
+ switch($this->style) {
+
+ case TICK_IN :
+ $this->drawTicks($drawer, $vector, NULL, $angle + M_PI / 2);
+ break;
+
+ case TICK_OUT :
+ $this->drawTicks($drawer, $vector, $angle + 3 * M_PI / 2, NULL);
+ break;
+
+ default :
+ $this->drawTicks($drawer, $vector, $angle + M_PI / 2, $angle + 3 * M_PI / 2);
+ break;
+
+ }
+
+ }
+
+ function drawTicks($drawer, &$vector, $from, $to) {
+
+ // Draw last tick
+ if($this->hideLast === FALSE) {
+
+ //echo '';
+ if(($this->number - 1) % $this->interval === 0) {
+ $this->drawTick($drawer, $vector->p2, $from, $to);
+ }
+ //echo '';
+
+ }
+
+ $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($drawer, $p, $from, $to);
+ }
+
+ $position++;
+
+ }
+ //echo '
';
+ }
+
+ function drawTick($drawer, $p, $from, $to) {
+// echo $this->size.':'.$angle.'|'.cos($angle).'/';
+ // 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
+ );
+
+ $drawer->line(
+ $this->color,
+ $vector
+ );
+
+ }
+
+}
+
+registerClass('Tick');
+?>
\ No newline at end of file
diff --git a/external-libs/Artichow/php4/inc/Tools.class.php b/external-libs/Artichow/php4/inc/Tools.class.php
new file mode 100644
index 00000000000..bdcf36d24bf
--- /dev/null
+++ b/external-libs/Artichow/php4/inc/Tools.class.php
@@ -0,0 +1,121 @@
+set($left, $right, $top, $bottom);
+ }
+
+
+ /**
+ * Change side values
+ *
+ * @param mixed $left
+ * @param mixed $right
+ * @param mixed $top
+ * @param mixed $bottom
+ */
+ 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
+ */
+ 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');
+?>
\ No newline at end of file