Subversion Repositories Sites.tela-botanica.org

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 david 1
<?php
2
/*=======================================================================
3
// File: 	JPGRAPH_CANVTOOLS.PHP
4
// Description:	Some utilities for text and shape drawing on a canvas
5
// Created: 	2002-08-23
6
// Author:	Johan Persson (johanp@aditus.nu)
7
// Ver:		$Id: jpgraph_canvtools.php,v 1.1 2004/06/15 10:13:19 jpm Exp $
8
//
9
// License:	This code is released under QPL
10
// Copyright (C) 2001,2002 Johan Persson
11
//========================================================================
12
*/
13
 
14
DEFINE('CORNER_TOPLEFT',0);
15
DEFINE('CORNER_TOPRIGHT',1);
16
DEFINE('CORNER_BOTTOMRIGHT',2);
17
DEFINE('CORNER_BOTTOMLEFT',3);
18
 
19
 
20
//===================================================
21
// CLASS CanvasScale
22
// Description: Define a scale for canvas so we
23
// can abstract away with absolute pixels
24
//===================================================
25
 
26
class CanvasScale {
27
    var $g;
28
    var $w,$h;
29
    var $ixmin=0,$ixmax=10,$iymin=0,$iymax=10;
30
 
31
    function CanvasScale(&$graph,$xmin=0,$xmax=10,$ymin=0,$ymax=10) {
32
	$this->g = &$graph;
33
	$this->w = $graph->img->width;
34
	$this->h = $graph->img->height;
35
	$this->ixmin = $xmin;
36
	$this->ixmax = $xmax;
37
	$this->iymin = $ymin;
38
	$this->iymax = $ymax;
39
    }
40
 
41
    function Set($xmin=0,$xmax=10,$ymin=0,$ymax=10) {
42
	$this->ixmin = $xmin;
43
	$this->ixmax = $xmax;
44
	$this->iymin = $ymin;
45
	$this->iymax = $ymax;
46
    }
47
 
48
    function Translate($x,$y) {
49
	$xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
50
	$yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
51
	return array($xp,$yp);
52
    }
53
 
54
    function TranslateX($x) {
55
	$xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
56
	return $xp;
57
    }
58
 
59
    function TranslateY($y) {
60
	$yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
61
	return $yp;
62
    }
63
 
64
}
65
 
66
 
67
//===================================================
68
// CLASS Shape
69
// Description: Methods to draw shapes on canvas
70
//===================================================
71
class Shape {
72
    var $img,$scale;
73
 
74
    function Shape(&$aGraph,&$scale) {
75
	$this->img = &$aGraph->img;
76
	$this->img->SetColor('black');
77
	$this->scale = &$scale;
78
    }
79
 
80
    function SetColor($aColor) {
81
	$this->img->SetColor($aColor);
82
    }
83
 
84
    function Line($x1,$y1,$x2,$y2) {
85
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
86
	list($x2,$y2) = $this->scale->Translate($x2,$y2);
87
	$this->img->Line($x1,$y1,$x2,$y2);
88
    }
89
 
90
    function Polygon($p,$aClosed=false) {
91
	$n=count($p);
92
	for($i=0; $i < $n; $i+=2 ) {
93
	   $p[$i]   = $this->scale->TranslateX($p[$i]);
94
	   $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
95
	}
96
	$this->img->Polygon($p,$aClosed);
97
    }
98
 
99
    function FilledPolygon($p) {
100
	$n=count($p);
101
	for($i=0; $i < $n; $i+=2 ) {
102
	   $p[$i]   = $this->scale->TranslateX($p[$i]);
103
	   $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
104
	}
105
	$this->img->FilledPolygon($p);
106
    }
107
 
108
 
109
    // Draw a bezier curve with defining points in the $aPnts array
110
    // using $aSteps steps.
111
    // 0=x0, 1=y0
112
    // 2=x1, 3=y1
113
    // 4=x2, 5=y2
114
    // 6=x3, 7=y3
115
    function Bezier($p,$aSteps=40) {
116
	$x0 = $p[0];
117
	$y0 = $p[1];
118
	// Calculate coefficients
119
	$cx = 3*($p[2]-$p[0]);
120
	$bx = 3*($p[4]-$p[2])-$cx;
121
	$ax = $p[6]-$p[0]-$cx-$bx;
122
	$cy = 3*($p[3]-$p[1]);
123
	$by = 3*($p[5]-$p[3])-$cy;
124
	$ay = $p[7]-$p[1]-$cy-$by;
125
 
126
	// Step size
127
	$delta = 1.0/$aSteps;
128
 
129
	$x_old = $x0;
130
	$y_old = $y0;
131
	for($t=$delta; $t<=1.0; $t+=$delta) {
132
	    $tt = $t*$t; $ttt=$tt*$t;
133
	    $x  = $ax*$ttt + $bx*$tt + $cx*$t + $x0;
134
	    $y = $ay*$ttt + $by*$tt + $cy*$t + $y0;
135
	    $this->Line($x_old,$y_old,$x,$y);
136
	    $x_old = $x;
137
	    $y_old = $y;
138
	}
139
	$this->Line($x_old,$y_old,$p[6],$p[7]);
140
    }
141
 
142
    function Rectangle($x1,$y1,$x2,$y2) {
143
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
144
	list($x2,$y2)   = $this->scale->Translate($x2,$y2);
145
	$this->img->Rectangle($x1,$y1,$x2,$y2);
146
    }
147
 
148
    function FilledRectangle($x1,$y1,$x2,$y2) {
149
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
150
	list($x2,$y2)   = $this->scale->Translate($x2,$y2);
151
	$this->img->FilledRectangle($x1,$y1,$x2,$y2);
152
    }
153
 
154
    function Circle($x1,$y1,$r) {
155
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
156
	if( $r >= 0 )
157
	    $r   = $this->scale->TranslateX($r);
158
	else
159
	    $r = -$r;
160
	$this->img->Circle($x1,$y1,$r);
161
    }
162
 
163
    function FilledCircle($x1,$y1,$r) {
164
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
165
	if( $r >= 0 )
166
	    $r   = $this->scale->TranslateX($r);
167
	else
168
	    $r = -$r;
169
	$this->img->FilledCircle($x1,$y1,$r);
170
    }
171
 
172
    function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) {
173
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
174
	list($x2,$y2)   = $this->scale->Translate($x2,$y2);
175
 
176
	if( $r == null )
177
	    $r = 5;
178
	elseif( $r >= 0 )
179
	    $r = $this->scale->TranslateX($r);
180
	else
181
	    $r = -$r;
182
	$this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r);
183
    }
184
 
185
    function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) {
186
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
187
	list($x2,$y2)   = $this->scale->Translate($x2,$y2);
188
 
189
	if( $r == null )
190
	    $r = 5;
191
	elseif( $r > 0 )
192
	    $r = $this->scale->TranslateX($r);
193
	else
194
	    $r = -$r;
195
	$this->img->FilledRoundedRectangle($x1,$y1,$x2,$y2,$r);
196
    }
197
 
198
    function ShadowRectangle($x1,$y1,$x2,$y2,$fcolor=false,$shadow_width=null,$shadow_color=array(102,102,102)) {
199
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
200
	list($x2,$y2) = $this->scale->Translate($x2,$y2);
201
	if( $shadow_width == null )
202
	    $shadow_width=4;
203
	else
204
	    $shadow_width=$this->scale->TranslateX($shadow_width);
205
	$this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color);
206
    }
207
 
208
    function SetTextAlign($halign,$valign="bottom") {
209
	$this->img->SetTextAlign($halign,$valign="bottom");
210
    }
211
 
212
    function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") {
213
	list($x1,$y1) = $this->scale->Translate($x1,$y1);
214
	$this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align);
215
    }
216
 
217
    // A rounded rectangle where one of the corner has been moved "into" the
218
    // rectangle 'iw' width and 'ih' height. Corners:
219
    // 0=Top left, 1=top right, 2=bottom right, 3=bottom left
220
    function IndentedRectangle($xt,$yt,$w,$h,$iw=0,$ih=0,$aCorner=3,$aFillColor="",$r=4) {
221
 
222
	list($xt,$yt) = $this->scale->Translate($xt,$yt);
223
	list($w,$h)   = $this->scale->Translate($w,$h);
224
	list($iw,$ih) = $this->scale->Translate($iw,$ih);
225
 
226
	$xr = $xt + $w - 0;
227
	$yl = $yt + $h - 0;
228
 
229
	switch( $aCorner ) {
230
	    case 0: // Upper left
231
 
232
		// Bottom line, left &  right arc
233
		$this->img->Line($xt+$r,$yl,$xr-$r,$yl);
234
		$this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
235
		$this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
236
 
237
		// Right line, Top right arc
238
		$this->img->Line($xr,$yt+$r,$xr,$yl-$r);
239
		$this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
240
 
241
		// Top line, Top left arc
242
		$this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt);
243
		$this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270);
244
 
245
		// Left line
246
		$this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r);
247
 
248
		// Indent horizontal, Lower left arc
249
		$this->img->Line($xt+$r,$yt+$ih,$xt+$iw-$r,$yt+$ih);
250
		$this->img->Arc($xt+$r,$yt+$ih+$r,$r*2,$r*2,180,270);
251
 
252
		// Indent vertical, Indent arc
253
		$this->img->Line($xt+$iw,$yt+$r,$xt+$iw,$yt+$ih-$r);
254
		$this->img->Arc($xt+$iw-$r,$yt+$ih-$r,$r*2,$r*2,0,90);
255
 
256
		if( $aFillColor != '' ) {
257
		    $bc = $this->img->current_color_name;
258
		    $this->img->PushColor($aFillColor);
259
		    $this->img->FillToBorder($xr-$r,$yl-$r,$bc);
260
		    $this->img->PopColor();
261
		}
262
 
263
		break;
264
 
265
	    case 1: // Upper right
266
 
267
		// Bottom line, left &  right arc
268
		$this->img->Line($xt+$r,$yl,$xr-$r,$yl);
269
		$this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
270
		$this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
271
 
272
		// Left line, Top left arc
273
		$this->img->Line($xt,$yt+$r,$xt,$yl-$r);
274
		$this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
275
 
276
		// Top line, Top right arc
277
		$this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt);
278
		$this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360);
279
 
280
		// Right line
281
		$this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r);
282
 
283
		// Indent horizontal, Lower right arc
284
		$this->img->Line($xr-$iw+$r,$yt+$ih,$xr-$r,$yt+$ih);
285
		$this->img->Arc($xr-$r,$yt+$ih+$r,$r*2,$r*2,270,360);
286
 
287
		// Indent vertical, Indent arc
288
		$this->img->Line($xr-$iw,$yt+$r,$xr-$iw,$yt+$ih-$r);
289
		$this->img->Arc($xr-$iw+$r,$yt+$ih-$r,$r*2,$r*2,90,180);
290
 
291
		if( $aFillColor != '' ) {
292
		    $bc = $this->img->current_color_name;
293
		    $this->img->PushColor($aFillColor);
294
		    $this->img->FillToBorder($xt+$r,$yl-$r,$bc);
295
		    $this->img->PopColor();
296
		}
297
 
298
		break;
299
 
300
	    case 2: // Lower right
301
		// Top line, Top left & Top right arc
302
		$this->img->Line($xt+$r,$yt,$xr-$r,$yt);
303
		$this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
304
		$this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
305
 
306
		// Left line, Bottom left arc
307
		$this->img->Line($xt,$yt+$r,$xt,$yl-$r);
308
		$this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
309
 
310
		// Bottom line, Bottom right arc
311
		$this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl);
312
		$this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90);
313
 
314
		// Right line
315
		$this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r);
316
 
317
		// Indent horizontal, Lower right arc
318
		$this->img->Line($xr-$r,$yl-$ih,$xr-$iw+$r,$yl-$ih);
319
		$this->img->Arc($xr-$r,$yl-$ih-$r,$r*2,$r*2,0,90);
320
 
321
		// Indent vertical, Indent arc
322
		$this->img->Line($xr-$iw,$yl-$r,$xr-$iw,$yl-$ih+$r);
323
		$this->img->Arc($xr-$iw+$r,$yl-$ih+$r,$r*2,$r*2,180,270);
324
 
325
		if( $aFillColor != '' ) {
326
		    $bc = $this->img->current_color_name;
327
		    $this->img->PushColor($aFillColor);
328
		    $this->img->FillToBorder($xt+$r,$yt+$r,$bc);
329
		    $this->img->PopColor();
330
		}
331
 
332
		break;
333
 
334
	    case 3: // Lower left
335
		// Top line, Top left & Top right arc
336
		$this->img->Line($xt+$r,$yt,$xr-$r,$yt);
337
		$this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
338
		$this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
339
 
340
		// Right line, Bottom right arc
341
		$this->img->Line($xr,$yt+$r,$xr,$yl-$r);
342
		$this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
343
 
344
		// Bottom line, Bottom left arc
345
		$this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl);
346
		$this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180);
347
 
348
		// Left line
349
		$this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r);
350
 
351
		// Indent horizontal, Lower left arc
352
		$this->img->Line($xt+$r,$yl-$ih,$xt+$iw-$r,$yl-$ih);
353
		$this->img->Arc($xt+$r,$yl-$ih-$r,$r*2,$r*2,90,180);
354
 
355
		// Indent vertical, Indent arc
356
		$this->img->Line($xt+$iw,$yl-$ih+$r,$xt+$iw,$yl-$r);
357
		$this->img->Arc($xt+$iw-$r,$yl-$ih+$r,$r*2,$r*2,270,360);
358
 
359
		if( $aFillColor != '' ) {
360
		    $bc = $this->img->current_color_name;
361
		    $this->img->PushColor($aFillColor);
362
		    $this->img->FillToBorder($xr-$r,$yt+$r,$bc);
363
		    $this->img->PopColor();
364
		}
365
 
366
		break;
367
	}
368
    }
369
}
370
 
371
 
372
//===================================================
373
// CLASS RectangleText
374
// Description: Draws a text paragraph inside a
375
// rounded, possible filled, rectangle.
376
//===================================================
377
class CanvasRectangleText {
378
    var $ix,$iy,$iw,$ih,$ir=4;
379
    var $iTxt,$iColor='black',$iFillColor='',$iFontColor='black';
380
    var $iParaAlign='center';
381
    var $iAutoBoxMargin=5;
382
    var $iShadowWidth=3,$iShadowColor='';
383
 
384
    function CanvasRectangleText($aTxt='',$xl=0,$yt=0,$w=0,$h=0) {
385
	$this->iTxt = new Text($aTxt);
386
	$this->ix = $xl;
387
	$this->iy = $yt;
388
	$this->iw = $w;
389
	$this->ih = $h;
390
    }
391
 
392
    function SetShadow($aColor='gray',$aWidth=3) {
393
	$this->iShadowColor = $aColor;
394
	$this->iShadowWidth = $aWidth;
395
    }
396
 
397
    function SetFont($FontFam,$aFontStyle,$aFontSize=12) {
398
	$this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize);
399
    }
400
 
401
    function SetTxt($aTxt) {
402
	$this->iTxt->Set($aTxt);
403
    }
404
 
405
    function ParagraphAlign($aParaAlign) {
406
	$this->iParaAlign = $aParaAlign;
407
    }
408
 
409
    function SetFillColor($aFillColor) {
410
	$this->iFillColor = $aFillColor;
411
    }
412
 
413
    function SetAutoMargin($aMargin) {
414
	$this->iAutoBoxMargin=$aMargin;
415
    }
416
 
417
    function SetColor($aColor) {
418
	$this->iColor = $aColor;
419
    }
420
 
421
    function SetFontColor($aColor) {
422
	$this->iFontColor = $aColor;
423
    }
424
 
425
    function SetPos($xl=0,$yt=0,$w=0,$h=0) {
426
	$this->ix = $xl;
427
	$this->iy = $yt;
428
	$this->iw = $w;
429
	$this->ih = $h;
430
    }
431
 
432
    function Pos($xl=0,$yt=0,$w=0,$h=0) {
433
	$this->ix = $xl;
434
	$this->iy = $yt;
435
	$this->iw = $w;
436
	$this->ih = $h;
437
    }
438
 
439
    function Set($aTxt,$xl,$yt,$w=0,$h=0) {
440
	$this->iTxt->Set($aTxt);
441
	$this->ix = $xl;
442
	$this->iy = $yt;
443
	$this->iw = $w;
444
	$this->ih = $h;
445
    }
446
 
447
    function SetCornerRadius($aRad=5) {
448
	$this->ir = $aRad;
449
    }
450
 
451
    function Stroke($aImg,$scale) {
452
 
453
	// If coordinates are specifed as negative this means we should
454
	// treat them as abolsute (pixels) coordinates
455
	if( $this->ix > 0 ) {
456
	    $this->ix = $scale->TranslateX($this->ix) ;
457
	}
458
	else {
459
	    $this->ix = -$this->ix;
460
	}
461
 
462
	if( $this->iy > 0 ) {
463
	    $this->iy = $scale->TranslateY($this->iy) ;
464
	}
465
	else {
466
	    $this->iy = -$this->iy;
467
	}
468
 
469
	list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ;
470
 
471
	if( $this->iw == 0 )
472
	    $this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin);
473
	if( $this->ih == 0 ) {
474
	    $this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin);
475
	}
476
 
477
	if( $this->iShadowColor != '' ) {
478
	    $aImg->PushColor($this->iShadowColor);
479
	    $aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth,
480
					  $this->iy+$this->iShadowWidth,
481
					  $this->ix+$this->iw-1+$this->iShadowWidth,
482
					  $this->iy+$this->ih-1+$this->iShadowWidth,
483
					  $this->ir);
484
	    $aImg->PopColor();
485
	}
486
 
487
	if( $this->iFillColor != '' ) {
488
	    $aImg->PushColor($this->iFillColor);
489
	    $aImg->FilledRoundedRectangle($this->ix,$this->iy,
490
					  $this->ix+$this->iw-1,
491
					  $this->iy+$this->ih-1,
492
					  $this->ir);
493
	    $aImg->PopColor();
494
	}
495
 
496
	if( $this->iColor != '' ) {
497
	    $aImg->PushColor($this->iColor);
498
	    $aImg->RoundedRectangle($this->ix,$this->iy,
499
				    $this->ix+$this->iw-1,
500
				    $this->iy+$this->ih-1,
501
				    $this->ir);
502
	    $aImg->PopColor();
503
	}
504
 
505
	$this->iTxt->Align('center','center');
506
	$this->iTxt->ParagraphAlign($this->iParaAlign);
507
	$this->iTxt->SetColor($this->iFontColor);
508
	$this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2);
509
 
510
	return array($this->iw, $this->ih);
511
 
512
    }
513
 
514
}
515
 
516
 
517
?>