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
require_once dirname(__FILE__)."/../Graph.class.php";
11
 
12
/**
13
 * Draw your objects
14
 *
15
 * @package Artichow
16
 */
17
abstract class awDriver {
18
 
19
	/**
20
	 * Image width
21
	 *
22
	 * @var int
23
	 */
24
	public $imageWidth;
25
 
26
	/**
27
	 * Image height
28
	 *
29
	 * @var int
30
	 */
31
	public $imageHeight;
32
 
33
	/**
34
	 * Driver X position
35
	 *
36
	 * @var int
37
	 */
38
	public $x;
39
 
40
	/**
41
	 * Driver Y position
42
	 *
43
	 * @var int
44
	 */
45
	public $y;
46
 
47
	/**
48
	 * Use anti-aliasing ?
49
	 *
50
	 * @var bool
51
	 */
52
	protected $antiAliasing = FALSE;
53
 
54
	/**
55
	 * The FontDriver object that will be used to draw text
56
	 * with PHP fonts.
57
	 *
58
	 * @var awPHPFontDriver
59
	 */
60
	protected $phpFontDriver;
61
 
62
	/**
63
	 * The FontDriver object that will be used to draw text
64
	 * with TTF or FDB fonts.
65
	 *
66
	 * @var awFileFontDriver
67
	 */
68
	protected $fileFontDriver;
69
 
70
	/**
71
	 * A string representing the type of the driver
72
	 *
73
	 * @var string
74
	 */
75
	protected $driverString;
76
 
77
	private $w;
78
	private $h;
79
 
80
	public function __construct() {
81
		$this->phpFontDriver = new awPHPFontDriver();
82
		$this->fileFontDriver = new awFileFontDriver();
83
	}
84
 
85
	/**
86
	 * Initialize the driver for a particular awImage object
87
	 *
88
	 * @param awImage $image
89
	 */
90
	abstract public function init(awImage $image);
91
 
92
	/**
93
	 * Initialize the Driver for a particular FileImage object
94
	 *
95
	 * @param awFileImage $fileImage The FileImage object to work on
96
	 * @param string $file Image filename
97
	 */
98
	abstract public function initFromFile(awFileImage $fileImage, $file);
99
 
100
	/**
101
	 * Change the image size
102
	 *
103
	 * @param int $width Image width
104
	 * @param int $height Image height
105
	 */
106
	abstract public function setImageSize($width, $height);
107
 
108
	/**
109
	 * Inform the driver of the position of your image
110
	 *
111
	 * @param float $x Position on X axis of the center of the component
112
	 * @param float $y Position on Y axis of the center of the component
113
	 */
114
	abstract public function setPosition($x, $y);
115
 
116
	/**
117
	 * Inform the driver of the position of your image
118
	 * This method need absolutes values
119
	 *
120
	 * @param int $x Left-top corner X position
121
	 * @param int $y Left-top corner Y position
122
	 */
123
	abstract public function setAbsPosition($x, $y);
124
 
125
	/**
126
	 * Move the position of the image
127
	 *
128
	 * @param int $x Add this value to X axis
129
	 * @param int $y Add this value to Y axis
130
	 */
131
	abstract public function movePosition($x, $y);
132
 
133
	/**
134
	 * Inform the driver of the size of your image
135
	 * Height and width must be between 0 and 1.
136
	 *
137
	 * @param int $w Image width
138
	 * @param int $h Image height
139
	 * @return array Absolute width and height of the image
140
	 */
141
	abstract public function setSize($w, $h);
142
 
143
	/**
144
	 * Inform the driver of the size of your image
145
	 * You can set absolute size with this method.
146
	 *
147
	 * @param int $w Image width
148
	 * @param int $h Image height
149
	 */
150
	abstract public function setAbsSize($w, $h);
151
 
152
	/**
153
	 * Get the size of the component handled by the driver
154
	 *
155
	 * @return array Absolute width and height of the component
156
	 */
157
	abstract public function getSize();
158
 
159
	/**
160
	 * Turn antialiasing on or off
161
	 *
162
	 * @var bool $bool
163
	 */
164
	abstract public function setAntiAliasing($bool);
165
 
166
	/**
167
	 * When passed a Color object, returns the corresponding
168
	 * color identifier (driver dependant).
169
	 *
170
	 * @param awColor $color A Color object
171
	 * @return int $rgb A color identifier representing the color composed of the given RGB components
172
	 */
173
	abstract public function getColor(awColor $color);
174
 
175
	/**
176
	 * Draw an image here
177
	 *
178
	 * @param awImage $image Image
179
	 * @param int $p1 Image top-left point
180
	 * @param int $p2 Image bottom-right point
181
	 */
182
	abstract public function copyImage(awImage $image, awPoint $p1, awPoint $p2);
183
 
184
	/**
185
	 * Draw an image here
186
	 *
187
	 * @param awImage $image Image
188
	 * @param int $d1 Destination top-left position
189
	 * @param int $d2 Destination bottom-right position
190
	 * @param int $s1 Source top-left position
191
	 * @param int $s2 Source bottom-right position
192
	 * @param bool $resample Resample image ? (default to TRUE)
193
	 */
194
	abstract public function copyResizeImage(awImage $image, awPoint $d1, awPoint $d2, awPoint $s1, awPoint $s2, $resample = TRUE);
195
 
196
	/**
197
	 * Draw a string
198
	 *
199
	 * @var awText $text Text to print
200
	 * @param awPoint $point Draw the text at this point
201
	 * @param int $width Text max width
202
	 */
203
	abstract public function string(awText $text, awPoint $point, $width = NULL);
204
 
205
	/**
206
	 * Draw a pixel
207
	 *
208
	 * @param awColor $color Pixel color
209
	 * @param awPoint $p
210
	 */
211
	abstract public function point(awColor $color, awPoint $p);
212
 
213
	/**
214
	 * Draw a colored line
215
	 *
216
	 * @param awColor $color Line color
217
	 * @param awLine $line
218
	 * @param int $thickness Line tickness
219
	 */
220
	abstract public function line(awColor $color, awLine $line);
221
 
222
	/**
223
	 * Draw a color arc
224
 
225
	 * @param awColor $color Arc color
226
	 * @param awPoint $center Point center
227
	 * @param int $width Ellipse width
228
	 * @param int $height Ellipse height
229
	 * @param int $from Start angle
230
	 * @param int $to End angle
231
	 */
232
	abstract public function arc(awColor $color, awPoint $center, $width, $height, $from, $to);
233
 
234
	/**
235
	 * Draw an arc with a background color
236
	 *
237
	 * @param awColor $color Arc background color
238
	 * @param awPoint $center Point center
239
	 * @param int $width Ellipse width
240
	 * @param int $height Ellipse height
241
	 * @param int $from Start angle
242
	 * @param int $to End angle
243
	 */
244
	abstract public function filledArc(awColor $color, awPoint $center, $width, $height, $from, $to);
245
 
246
	/**
247
	 * Draw a colored ellipse
248
	 *
249
	 * @param awColor $color Ellipse color
250
	 * @param awPoint $center Ellipse center
251
	 * @param int $width Ellipse width
252
	 * @param int $height Ellipse height
253
	 */
254
	abstract public function ellipse(awColor $color, awPoint $center, $width, $height);
255
 
256
	/**
257
	 * Draw an ellipse with a background
258
	 *
259
	 * @param mixed $background Background (can be a color or a gradient)
260
	 * @param awPoint $center Ellipse center
261
	 * @param int $width Ellipse width
262
	 * @param int $height Ellipse height
263
	 */
264
	abstract public function filledEllipse($background, awPoint $center, $width, $height);
265
 
266
	/**
267
	 * Draw a colored rectangle
268
	 *
269
	 * @param awColor $color Rectangle color
270
	 * @param awLine $line Rectangle diagonale
271
	 * @param awPoint $p2
272
	 */
273
	abstract public function rectangle(awColor $color, awLine $line);
274
 
275
	/**
276
	 * Draw a rectangle with a background
277
	 *
278
	 * @param mixed $background Background (can be a color or a gradient)
279
	 * @param awLine $line Rectangle diagonale
280
	 */
281
	abstract public function filledRectangle($background, awLine $line);
282
 
283
	/**
284
	 * Draw a polygon
285
	 *
286
	 * @param awColor $color Polygon color
287
	 * @param Polygon A polygon
288
	 */
289
	abstract public function polygon(awColor $color, awPolygon $polygon);
290
 
291
	/**
292
	 * Draw a polygon with a background
293
	 *
294
	 * @param mixed $background Background (can be a color or a gradient)
295
	 * @param Polygon A polygon
296
	 */
297
	abstract public function filledPolygon($background, awPolygon $polygon);
298
 
299
	/**
300
	 * Sends the image, as well as the correct HTTP headers, to the browser
301
	 *
302
	 * @param awImage $image The Image object to send
303
	 */
304
	abstract public function send(awImage $image);
305
 
306
	/**
307
	 * Get the image as binary data
308
	 *
309
	 * @param awImage $image
310
	 */
311
	abstract public function get(awImage $image);
312
 
313
	/**
314
	 * Return the width of some text
315
	 *
316
	 * @param awText $text
317
	 */
318
	abstract public function getTextWidth(awText $text);
319
 
320
	/**
321
	 * Return the height of some text
322
	 *
323
	 * @param awText $text
324
	 */
325
	abstract public function getTextHeight(awText $text);
326
 
327
	/**
328
	 * Return the string representing the type of driver
329
	 *
330
	 * @return string
331
	 */
332
	public function getDriverString() {
333
		return $this->driverString;
334
	}
335
 
336
	/**
337
	 * Returns whether or not the driver is compatible with the given font type
338
	 *
339
	 * @param awFont $font
340
	 * @return bool
341
	 */
342
	abstract protected function isCompatibleWithFont(awFont $font);
343
 
344
//	abstract private function drawImage(awImage $image, $return = FALSE, $header = TRUE);
345
 
346
}
347
 
348
registerClass('Driver', TRUE);
349
 
350
/**
351
 * Abstract class for font drivers.
352
 * Those are used to do all the grunt work on fonts.
353
 *
354
 * @package Artichow
355
 */
356
 
357
abstract class awFontDriver {
358
 
359
	public function __construct() {
360
 
361
	}
362
 
363
	/**
364
	 * Draw the actual text.
365
	 *
366
	 * @param awDriver $driver The Driver object to draw upon
367
	 * @param awText $text The Text object
368
	 * @param awPoint $point Where to draw the text
369
	 * @param float $width The width of the area containing the text
370
	 */
371
	abstract public function string(awDriver $driver, awText $text, awPoint $point, $width = NULL);
372
 
373
	/**
374
	 * Calculate the width of a given Text.
375
	 *
376
	 * @param awText $text The Text object
377
	 * @param awDriver $driver The awDriver object used to draw the graph
378
	 */
379
	abstract public function getTextWidth(awText $text, awDriver $driver);
380
 
381
	/**
382
	 * Calculate the height of a given Text.
383
	 *
384
	 * @param awText $text The Text object
385
	 * @param awDriver $driver The awDriver object used to draw the graph
386
	 */
387
	abstract public function getTextHeight(awText $text, awDriver $driver);
388
 
389
}
390
 
391
registerClass('FontDriver', TRUE);
392
 
393
/**
394
 * Class to handle calculations on PHPFont objects
395
 *
396
 * @package Artichow
397
 */
398
class awPHPFontDriver extends awFontDriver {
399
 
400
	public function __construct() {
401
		parent::__construct();
402
	}
403
 
404
	public function string(awDriver $driver, awText $text, awPoint $point, $width = NULL) {
405
 
406
		switch ($driver->getDriverString()) {
407
			case 'gd':
408
				$this->gdString($driver, $text, $point, $width);
409
				break;
410
 
411
			default:
412
				awImage::drawError('Class PHPFontDriver: Incompatibility between driver and font - You should never see this error message: have you called awDriver::isCompatibleWithFont() properly?');
413
				break;
414
 
415
		}
416
	}
417
 
418
	/**
419
	 * Draw a string onto a GDDriver object
420
	 *
421
	 * @param awGDDriver $driver The GDDriver to draw the text upon
422
	 * @param awText $text The awText object containing the string to draw
423
	 * @param awPoint $point Where to draw the text
424
	 * @param float $width The width of the text
425
	 */
426
	private function gdString(awGDDriver $driver, awText $text, awPoint $point, $width = NULL) {
427
 
428
		$angle = $text->getAngle();
429
		if($angle !== 90 and $angle !== 0) {
430
			awImage::drawError("Class PHPFontDriver: You can only use 0° and 90° angles.");
431
		}
432
 
433
		if($angle === 90) {
434
			$function = 'imagestringup';
435
			$addAngle = $this->getGDTextHeight($text);
436
		} else {
437
			$function = 'imagestring';
438
			$addAngle = 0;
439
		}
440
 
441
		$color = $text->getColor();
442
		$rgb = $driver->getColor($color);
443
 
444
		$textString = $text->getText();
445
		$textString = str_replace("\r", "", $textString);
446
 
447
		$textHeight = $this->getGDTextHeight($text);
448
 
449
		// Split text if needed
450
		if($width !== NULL) {
451
 
452
			$characters = floor($width / ($this->getGDTextWidth($text) / strlen($textString)));
453
 
454
			if($characters > 0) {
455
				$textString = wordwrap($textString, $characters, "\n", TRUE);
456
			}
457
 
458
		}
459
 
460
		$font = $text->getFont();
461
		$lines = explode("\n", $textString);
462
 
463
		foreach($lines as $i => $line) {
464
 
465
			// Line position handling
466
			if($angle === 90) {
467
				$addX = $i * $textHeight;
468
				$addY = 0;
469
			} else {
470
				$addX = 0;
471
				$addY = $i * $textHeight;
472
			}
473
 
474
			$function(
475
				$driver->resource,
476
				$font->font,
477
				$driver->x + $point->x + $addX,
478
				$driver->y + $point->y + $addY + $addAngle,
479
				$line,
480
				$rgb
481
			);
482
 
483
		}
484
	}
485
 
486
	public function getTextWidth(awText $text, awDriver $driver) {
487
 
488
		switch ($driver->getDriverString()) {
489
			case 'gd':
490
				return $this->getGDTextWidth($text);
491
 
492
			default:
493
				awImage::drawError('Class PHPFontDriver: Cannot get text width - incompatibility between driver and font');
494
				break;
495
		}
496
 
497
	}
498
 
499
	public function getTextHeight(awText $text, awDriver $driver) {
500
 
501
		switch ($driver->getDriverString()) {
502
			case 'gd':
503
				return $this->getGDTextHeight($text);
504
 
505
			default:
506
				awImage::drawError('Class PHPFontDriver: Cannot get text height - incompatibility between driver and font');
507
				break;
508
		}
509
 
510
	}
511
 
512
	/**
513
	 * Return the width of a text for a GDDriver
514
	 *
515
	 * @param awText $text
516
	 * @return int $fontWidth
517
	 */
518
	private function getGDTextWidth(awText $text) {
519
		$font = $text->getFont();
520
 
521
		if($text->getAngle() === 90) {
522
			$text->setAngle(45);
523
			return $this->getGDTextHeight($text);
524
		} else if($text->getAngle() === 45) {
525
			$text->setAngle(90);
526
		}
527
 
528
		$fontWidth = imagefontwidth($font->font);
529
 
530
		if($fontWidth === FALSE) {
531
			awImage::drawError("Class PHPFontDriver: Unable to get font size.");
532
		}
533
 
534
		return (int)$fontWidth * strlen($text->getText());
535
	}
536
 
537
	/**
538
	 * Return the height of a text for a GDDriver
539
	 *
540
	 * @param awText $text
541
	 * @return int $fontHeight
542
	 */
543
	private function getGDTextHeight(awText $text) {
544
		$font = $text->getFont();
545
 
546
		if($text->getAngle() === 90) {
547
			$text->setAngle(45);
548
			return $this->getGDTextWidth($text);
549
		} else if($text->getAngle() === 45) {
550
			$text->setAngle(90);
551
		}
552
 
553
		$fontHeight = imagefontheight($font->font);
554
 
555
		if($fontHeight === FALSE) {
556
			awImage::drawError("Class PHPFontDriver: Unable to get font size.");
557
		}
558
 
559
		return (int)$fontHeight;
560
	}
561
}
562
 
563
registerClass('PHPFontDriver');
564
 
565
/**
566
 * Class to handle calculations on FileFont objects
567
 *
568
 * @package Artichow
569
 */
570
class awFileFontDriver extends awFontDriver {
571
 
572
	public function __construct() {
573
		parent::__construct();
574
	}
575
 
576
	public function string(awDriver $driver, awText $text, awPoint $point, $width = NULL) {
577
 
578
		switch ($driver->getDriverString()) {
579
			case 'gd':
580
				$this->gdString($driver, $text, $point, $width);
581
				break;
582
 
583
			default:
584
				awImage::drawError('Class fileFontDriver: Incompatibility between driver and font - You should never see this error message: have you called awDriver::isCompatibleWithFont() properly?');
585
				break;
586
		}
587
	}
588
 
589
	/**
590
	 * Draw an awFileFont object on a GD ressource
591
	 *
592
	 * @param awGDDriver $driver The awGDDriver object containing the ressource to draw upon
593
	 * @param awText $text The awText object containing the string to draw
594
	 * @param awPoint $point Where to draw the string from
595
	 * @param float $width The width of the area containing the text
596
	 */
597
	private function gdString(awGDDriver $driver, awText $text, awPoint $point, $width = NULL) {
598
		// Make easier font positionment
599
		$text->setText($text->getText()." ");
600
 
601
		$font = $text->getFont();
602
		if($font instanceof awTTFFont === FALSE and $font->getExtension() === NULL) {
603
			$font->setExtension('ttf');
604
		}
605
 
606
		$filePath = $font->getName().'.'.$font->getExtension();
607
 
608
		$box = imagettfbbox($font->getSize(), $text->getAngle(), $filePath, $text->getText());
609
		$textHeight = - $box[5];
610
 
611
		$box = imagettfbbox($font->getSize(), 90, $filePath, $text->getText());
612
		$textWidth = abs($box[6] - $box[2]);
613
 
614
		// Restore old text
615
		$text->setText(substr($text->getText(), 0, strlen($text->getText()) - 1));
616
 
617
		$textString = $text->getText();
618
 
619
		// Split text if needed
620
		if($width !== NULL) {
621
 
622
			$characters = floor($width / $this->getGDAverageWidth($font));
623
			$textString = wordwrap($textString, $characters, "\n", TRUE);
624
 
625
		}
626
 
627
		$color = $text->getColor();
628
		$rgb = $driver->getColor($color);
629
 
630
		imagettftext(
631
			$driver->resource,
632
			$font->getSize(),
633
			$text->getAngle(),
634
			$driver->x + $point->x + $textWidth * sin($text->getAngle() / 180 * M_PI),
635
			$driver->y + $point->y + $textHeight,
636
			$rgb,
637
			$filePath,
638
			$textString
639
		);
640
	}
641
 
642
	public function getTextWidth(awText $text, awDriver $driver) {
643
		switch ($driver->getDriverString()) {
644
			case 'gd':
645
				return $this->getGDTextWidth($text);
646
 
647
			default:
648
				awImage::drawError('Class FileFontDriver: Cannot get text width - incompatibility between driver and font');
649
				break;
650
		}
651
	}
652
 
653
	public function getTextHeight(awText $text, awDriver $driver) {
654
		switch ($driver->getDriverString()) {
655
			case 'gd':
656
				return $this->getGDTextHeight($text);
657
 
658
			default:
659
				awImage::drawError('Class FileFontDriver: Cannot get text height - incompatibility between driver and font');
660
				break;
661
		}
662
	}
663
 
664
	private function getGDTextWidth(awText $text) {
665
		$font = $text->getFont();
666
		if($font->getExtension() === NULL) {
667
			$font->setExtension('ttf');
668
		}
669
 
670
		$filePath = $font->getName().'.'.$font->getExtension();
671
 
672
		$box = imagettfbbox($font->getSize(), $text->getAngle(), $filePath, $text->getText());
673
 
674
		if($box === FALSE) {
675
			awImage::drawError("Class FileFontDriver: Unable to get font width (GD).");
676
		}
677
 
678
		list(, , $x2, , , , $x1, ) = $box;
679
 
680
		return abs($x2 - $x1);
681
	}
682
 
683
	private function getGDTextHeight(awText $text) {
684
		$font = $text->getFont();
685
		if($font->getExtension() === NULL) {
686
			$font->setExtension('ttf');
687
		}
688
 
689
		$filePath = $font->getName().'.'.$font->getExtension();
690
 
691
		$box = imagettfbbox($font->getSize(), $text->getAngle(), $filePath, $text->getText());
692
 
693
		if($box === FALSE) {
694
			awImage::drawError("Class FileFontDriver: Unable to get font height (GD).");
695
		}
696
 
697
		list(, , , $y2, , , , $y1) = $box;
698
 
699
		return abs($y2 - $y1);
700
	}
701
 
702
	private function getGDAverageWidth(awFileFont $font) {
703
 
704
		$text = "azertyuiopqsdfghjklmmmmmmmwxcvbbbn,;:!?.";
705
 
706
		$box = imagettfbbox($font->getSize(), 0, $font->getName().'.'.$font->getExtension(), $text);
707
 
708
		if($box === FALSE) {
709
			awImage::drawError("Class FileFontDriver: Unable to get font average width.");
710
		}
711
 
712
		list(, , $x2, $y2, , , $x1, $y1) = $box;
713
 
714
		return abs($x2 - $x1) / strlen($text);
715
 
716
	}
717
 
718
}
719
 
720
registerClass('FileFontDriver');
721
 
722
// Include ARTICHOW_DRIVER by default to preserve backward compatibility.
723
require_once dirname(__FILE__).'/drivers/'.ARTICHOW_DRIVER.'.class.php';
724
 
725
?>