Subversion Repositories Applications.gtt

Rev

Rev 61 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
60 jpm 1
<?php
2
/*
3
 * This work is hereby released into the Public Domain.
4
 * To view a copy of the public domain dedication,
5
 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
6
 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
7
 *
8
 */
9
 
10
 
11
if(is_file(dirname(__FILE__)."/Artichow.cfg.php")) { // For PHP 4+5 version
12
	require_once dirname(__FILE__)."/Artichow.cfg.php";
13
}
14
 
15
 
16
 
17
 
18
/*
19
 * Register a class with the prefix in configuration file
20
 */
21
function registerClass($class, $abstract = FALSE) {
22
 
23
	if(ARTICHOW_PREFIX === 'aw') {
24
		return;
25
	}
26
 
27
 
28
	if($abstract) {
29
		$abstract = 'abstract';
30
	} else {
31
		$abstract = '';
32
	}
33
 
34
 
35
	eval($abstract." class ".ARTICHOW_PREFIX.$class." extends aw".$class." { }");
36
 
37
}
38
 
39
/*
40
 * Register an interface with the prefix in configuration file
41
 */
42
function registerInterface($interface) {
43
 
44
	if(ARTICHOW_PREFIX === 'aw') {
45
		return;
46
	}
47
 
48
 
49
	eval("interface ".ARTICHOW_PREFIX.$interface." extends aw".$interface." { }");
50
 
51
 
52
}
53
 
54
// Some useful files
55
require_once ARTICHOW."/Component.class.php";
56
 
57
require_once ARTICHOW."/inc/Grid.class.php";
58
require_once ARTICHOW."/inc/Tools.class.php";
59
require_once ARTICHOW."/inc/Driver.class.php";
60
require_once ARTICHOW."/inc/Math.class.php";
61
require_once ARTICHOW."/inc/Tick.class.php";
62
require_once ARTICHOW."/inc/Axis.class.php";
63
require_once ARTICHOW."/inc/Legend.class.php";
64
require_once ARTICHOW."/inc/Mark.class.php";
65
require_once ARTICHOW."/inc/Label.class.php";
66
require_once ARTICHOW."/inc/Text.class.php";
67
require_once ARTICHOW."/inc/Color.class.php";
68
require_once ARTICHOW."/inc/Font.class.php";
69
require_once ARTICHOW."/inc/Gradient.class.php";
70
require_once ARTICHOW."/inc/Shadow.class.php";
71
require_once ARTICHOW."/inc/Border.class.php";
72
 
73
require_once ARTICHOW."/common.php";
74
 
75
/**
76
 * An image for a graph
77
 *
78
 * @package Artichow
79
 */
80
class awImage {
81
 
82
	/**
83
	 * Graph width
84
	 *
85
	 * @var int
86
	 */
87
	public $width;
88
 
89
	/**
90
	 * Graph height
91
	 *
92
	 * @var int
93
	 */
94
	public $height;
95
 
96
	/**
97
	 * Use anti-aliasing ?
98
	 *
99
	 * @var bool
100
	 */
101
	protected $antiAliasing = FALSE;
102
 
103
	/**
104
	 * Image format
105
	 *
106
	 * @var int
107
	 */
108
	protected $format = awImage::PNG;
109
 
110
	/**
111
	 * Image background color
112
	 *
113
	 * @var Color
114
	 */
115
	protected $background;
116
 
117
	/**
118
	 * GD resource
119
	 *
120
	 * @var resource
121
	 */
122
	protected $resource;
123
 
124
	/**
125
	 * A Driver object
126
	 *
127
	 * @var Driver
128
	 */
129
	protected $driver;
130
 
131
	/**
132
	 * Driver string
133
	 *
134
	 * @var string
135
	 */
136
	protected $driverString;
137
 
138
	/**
139
	 * Shadow
140
	 *
141
	 * @var Shadow
142
	 */
143
	public $shadow;
144
 
145
	/**
146
	 * Image border
147
	 *
148
	 * @var Border
149
	 */
150
	public $border;
151
 
152
	/**
153
	 * Use JPEG for image
154
	 *
155
	 * @var int
156
	 */
157
	const JPEG = IMG_JPG;
158
 
159
	/**
160
	 * Use PNG for image
161
	 *
162
	 * @var int
163
	 */
164
	const PNG = IMG_PNG;
165
 
166
	/**
167
	 * Use GIF for image
168
	 *
169
	 * @var int
170
	 */
171
	const GIF = IMG_GIF;
172
 
173
	/**
174
	 * Build the image
175
	 */
176
	public function __construct() {
177
 
178
		$this->background = new awColor(255, 255, 255);
179
		$this->shadow = new awShadow(awShadow::RIGHT_BOTTOM);
180
		$this->border = new awBorder;
181
 
182
	}
183
 
184
	/**
185
	 * Get driver of the image
186
	 *
187
	 * @param int $w Driver width (from 0 to 1) (default to 1)
188
	 * @param int $h Driver height (from 0 to 1) (default to 1)
189
	 * @param float $x Position on X axis of the center of the driver (default to 0.5)
190
	 * @param float $y Position on Y axis of the center of the driver (default to 0.5)
191
	 * @return Driver
192
	 */
193
	public function getDriver($w = 1, $h = 1, $x = 0.5, $y = 0.5) {
194
		$this->create();
195
		$this->driver->setSize($w, $h);
196
		$this->driver->setPosition($x, $y);
197
		return $this->driver;
198
	}
199
 
200
	/**
201
	 * Sets the driver that will be used to draw the graph
202
	 *
203
	 * @param string $driverString
204
	 */
205
	public function setDriver($driverString) {
206
		$this->driver = $this->selectDriver($driverString);
207
 
208
		$this->driver->init($this);
209
	}
210
 
211
	/**
212
	 * Change the image size
213
	 *
214
	 * @var int $width Image width
215
	 * @var int $height Image height
216
	 */
217
	public function setSize($width, $height) {
218
 
219
		if($width !== NULL) {
220
			$this->width = (int)$width;
221
		}
222
		if($height !== NULL) {
223
			$this->height = (int)$height;
224
		}
225
 
226
	}
227
 
228
	/**
229
	 * Change image background
230
	 *
231
	 * @param mixed $background
232
	 */
233
	public function setBackground($background) {
234
		if($background instanceof awColor) {
235
			$this->setBackgroundColor($background);
236
		} elseif($background instanceof awGradient) {
237
			$this->setBackgroundGradient($background);
238
		}
239
	}
240
 
241
	/**
242
	 * Change image background color
243
	 *
244
	 * @param awColor $color
245
	 */
246
	public function setBackgroundColor(awColor $color) {
247
		$this->background = $color;
248
	}
249
 
250
	/**
251
	 * Change image background gradient
252
	 *
253
	 * @param awGradient $gradient
254
	 */
255
	public function setBackgroundGradient(awGradient $gradient) {
256
		$this->background = $gradient;
257
	}
258
 
259
	/**
260
	 * Return image background, whether a Color or a Gradient
261
	 *
262
	 * @return mixed
263
	 */
264
	public function getBackground() {
265
		return $this->background;
266
	}
267
 
268
	/**
269
	 * Turn antialiasing on or off
270
	 *
271
	 * @var bool $bool
272
	 */
273
	public function setAntiAliasing($bool) {
274
		$this->antiAliasing = (bool)$bool;
275
	}
276
 
277
	/**
278
	 * Return the antialiasing setting
279
	 *
280
	 * @return bool
281
	 */
282
	public function getAntiAliasing() {
283
		return $this->antiAliasing;
284
	}
285
 
286
	/**
287
	 * Change image format
288
	 *
289
	 * @var int $format New image format
290
	 */
291
	public function setFormat($format) {
292
		if($format === awImage::JPEG or $format === awImage::PNG or $format === awImage::GIF) {
293
			$this->format = $format;
294
		}
295
	}
296
 
297
	/**
298
	 * Returns the image format as an integer
299
	 *
300
	 * @return unknown
301
	 */
302
	public function getFormat() {
303
		return $this->format;
304
	}
305
 
306
	/**
307
	 * Returns the image format as a string
308
	 *
309
	 * @return string
310
	 */
311
	public function getFormatString() {
312
 
313
		switch($this->format) {
314
			case awImage::JPEG :
315
				return 'jpeg';
316
			case awImage::PNG :
317
				return 'png';
318
			case awImage::GIF :
319
				return 'gif';
320
		}
321
 
322
	}
323
 
324
	/**
325
	 * Create a new awimage
326
	 */
327
	public function create() {
328
 
329
		if($this->driver === NULL) {
330
			$driver = $this->selectDriver($this->driverString);
331
 
332
			$driver->init($this);
333
 
334
			$this->driver = $driver;
335
		}
336
 
337
	}
338
 
339
	/**
340
	 * Select the correct driver
341
	 *
342
	 * @param string $driver The desired driver
343
	 * @return mixed
344
	 */
345
	protected function selectDriver($driver) {
346
		$drivers = array('gd');
347
		$driver = strtolower((string)$driver);
348
 
349
		if(in_array($driver, $drivers, TRUE)) {
350
			$string = $driver;
351
		} else {
352
			$string = ARTICHOW_DRIVER;
353
		}
354
 
355
		switch ($string) {
356
				case 'gd':
357
					require_once ARTICHOW.'/inc/drivers/gd.class.php';
358
					$this->driverString = $string;
359
					return new awGDDriver();
360
 
361
				default:
362
					// We should never get here, unless the wrong string is used AND the ARTICHOW_DRIVER
363
					// global has been messed with.
364
					awImage::drawError('Class Image: Unknown driver type (\''.$string.'\')');
365
					break;
366
			}
367
	}
368
 
369
	/**
370
	 * Draw a component on the image
371
	 *
372
	 * @var awComponent $component A component
373
	 */
374
	public function drawComponent(awComponent $component) {
375
 
376
		$shadow = $this->shadow->getSpace(); // Image shadow
377
		$border = $this->border->visible() ? 1 : 0; // Image border size
378
 
379
		$driver = clone $this->driver;
380
		$driver->setImageSize(
381
			$this->width - $shadow->left - $shadow->right - $border * 2,
382
			$this->height - $shadow->top - $shadow->bottom - $border * 2
383
		);
384
 
385
		// No absolute size specified
386
		if($component->w === NULL and $component->h === NULL) {
387
 
388
			list($width, $height) = $driver->setSize($component->width, $component->height);
389
 
390
			// Set component size in pixels
391
			$component->setAbsSize($width, $height);
392
 
393
		} else {
394
 
395
			$driver->setAbsSize($component->w, $component->h);
396
 
397
		}
398
 
399
		if($component->top !== NULL and $component->left !== NULL) {
400
			$driver->setAbsPosition(
401
				$border + $shadow->left + $component->left,
402
				$border + $shadow->top + $component->top
403
			);
404
		} else {
405
			$driver->setPosition($component->x, $component->y);
406
		}
407
 
408
		$driver->movePosition($border + $shadow->left, $border + $shadow->top);
409
 
410
		list($x1, $y1, $x2, $y2) = $component->getPosition();
411
 
412
		$component->init($driver);
413
 
414
		$component->drawComponent($driver, $x1, $y1, $x2, $y2, $this->antiAliasing);
415
		$component->drawEnvelope($driver, $x1, $y1, $x2, $y2);
416
 
417
		$component->finalize($driver);
418
 
419
	}
420
 
421
	protected function drawShadow() {
422
 
423
		$driver = $this->getDriver();
424
 
425
		$this->shadow->draw(
426
			$driver,
427
			new awPoint(0, 0),
428
			new awPoint($this->width, $this->height),
429
			awShadow::IN
430
		);
431
 
432
	}
433
 
434
	/**
435
	 * Send the image into a file or to the user browser
436
	 *
437
	 */
438
	public function send() {
439
		$this->driver->send($this);
440
	}
441
 
442
	/**
443
	 * Return the image content as binary data
444
	 *
445
	 */
446
	public function get() {
447
		return $this->driver->get($this);
448
	}
449
 
450
	/**
451
	 * Send the correct HTTP header according to the image type
452
	 *
453
	 */
454
	public function sendHeaders() {
455
 
456
		if(headers_sent() === FALSE) {
457
 
458
			switch ($this->driverString) {
459
				case 'gd' :
460
					header('Content-type: image/'.$this->getFormatString());
461
					break;
462
 
463
			}
464
 
465
		}
466
 
467
	}
468
 
469
 
470
	private static $errorWriting = FALSE;
471
 
472
 
473
	/*
474
	 * Display an error image and exit
475
	 *
476
	 * @param string $message Error message
477
	 */
478
	public static function drawError($message) {
479
 
480
 
481
		if(self::$errorWriting) {
482
			return;
483
		}
484
 
485
		self::$errorWriting = TRUE;
486
 
487
		$message = wordwrap($message, 40, "\n", TRUE);
488
 
489
		$width = 400;
490
		$height = max(100, 40 + 22.5 * (substr_count($message, "\n") + 1));
491
 
492
		$image = new awImage();
493
		$image->setSize($width, $height);
494
		$image->setDriver('gd');
495
 
496
		$driver = $image->getDriver();
497
		$driver->init($image);
498
 
499
		// Display title
500
		$driver->filledRectangle(
501
			new awWhite,
502
			new awLine(
503
				new awPoint(0, 0),
504
				new awPoint($width, $height)
505
			)
506
		);
507
 
508
		$driver->filledRectangle(
509
			new awRed,
510
			new awLine(
511
				new awPoint(0, 0),
512
				new awPoint(110, 25)
513
			)
514
		);
515
 
516
		$text = new awText(
517
			"Artichow error",
518
			new awFont3,
519
			new awWhite,
520
 
521
		);
522
 
523
		$driver->string($text, new awPoint(5, 6));
524
 
525
		// Display red box
526
		$driver->rectangle(
527
			new awRed,
528
			new awLine(
529
				new awPoint(0, 25),
530
				new awPoint($width - 90, $height - 1)
531
			)
532
		);
533
 
534
		// Display error image
535
		$file = ARTICHOW_IMAGE.DIRECTORY_SEPARATOR.'error.png';
536
 
537
		$imageError = new awFileImage($file);
538
		$driver->copyImage(
539
			$imageError,
540
			new awPoint($width - 81, $height - 81),
541
			new awPoint($width - 1, $height - 1)
542
		);
543
 
544
		// Draw message
545
		$text = new awText(
546
			strip_tags($message),
547
			new awFont2,
548
			new awBlack,
549
 
550
		);
551
 
552
		$driver->string($text, new awPoint(10, 40));
553
 
554
		$image->send();
555
 
556
		exit;
557
 
558
	}
559
 
560
	/*
561
	 * Display an error image located in a file and exit
562
	 *
563
	 * @param string $error Error name
564
	 */
565
	public static function drawErrorFile($error) {
566
 
567
		$file = ARTICHOW_IMAGE.DIRECTORY_SEPARATOR.'errors'.DIRECTORY_SEPARATOR.$error.'.png';
568
 
569
		header("Content-Type: image/png");
570
		readfile($file);
571
		exit;
572
 
573
	}
574
 
575
}
576
 
577
registerClass('Image');
578
 
579
 
580
/**
581
 * Load an image from a file
582
 *
583
 * @package Artichow
584
 */
585
class awFileImage extends awImage {
586
 
587
	/**
588
	 * Build a new awimage
589
	 *
590
	 * @param string $file Image file name
591
	 */
592
	public function __construct($file) {
593
 
594
		$driver = $this->selectDriver($this->driverString);
595
 
596
		$driver->initFromFile($this, $file);
597
 
598
		$this->driver = $driver;
599
 
600
	}
601
 
602
}
603
 
604
registerClass('FileImage');
605
 
606
?>