|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* JPGraph v4.0.3 |
|
5
|
|
|
*/ |
|
6
|
|
|
|
|
7
|
|
|
namespace Amenadiel\JpGraph\Text; |
|
8
|
|
|
|
|
9
|
|
|
//use Amenadiel\JpGraph\Graph\Graph; |
|
10
|
|
|
use Amenadiel\JpGraph\Util; |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* File: JPGRAPH_TEXT.INC.PHP |
|
14
|
|
|
* // Description: Class to handle text as object in the graph. |
|
15
|
|
|
* // The low level text layout engine is handled by the GD class |
|
16
|
|
|
* // Created: 2001-01-08 (Refactored to separate file 2008-08-01) |
|
17
|
|
|
* // Ver: $Id: jpgraph_text.inc.php 1844 2009-09-26 17:05:31Z ljp $ |
|
18
|
|
|
* // |
|
19
|
|
|
* // Copyright (c) Asial Corporation. All rights reserved. |
|
20
|
|
|
*/ |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* @class Text |
|
24
|
|
|
* // Description: Arbitrary text object that can be added to the graph |
|
25
|
|
|
*/ |
|
26
|
|
|
class Text //extends Graph |
|
27
|
|
|
{ |
|
28
|
|
|
public $t; |
|
29
|
|
|
public $x = 0; |
|
30
|
|
|
public $y = 0; |
|
31
|
|
|
public $halign = 'left'; |
|
32
|
|
|
public $valign = 'top'; |
|
33
|
|
|
public $color = [0, 0, 0]; |
|
34
|
|
|
public $hide = false; |
|
35
|
|
|
public $dir = 0; |
|
36
|
|
|
public $iScalePosY; |
|
37
|
|
|
public $iScalePosX; |
|
38
|
|
|
public $iWordwrap = 0; |
|
39
|
|
|
public $font_family = FF_DEFAULT; |
|
40
|
|
|
public $font_style = FS_NORMAL; // old. FF_FONT1 |
|
41
|
|
|
public $boxed = false; // Should the text be boxed |
|
42
|
|
|
protected $paragraph_align = 'left'; |
|
43
|
|
|
protected $icornerradius = 0; |
|
44
|
|
|
protected $ishadowwidth = 3; |
|
45
|
|
|
protected $fcolor = 'white'; |
|
46
|
|
|
protected $bcolor = 'black'; |
|
47
|
|
|
protected $shadow = false; |
|
48
|
|
|
protected $iCSIMarea = ''; |
|
49
|
|
|
protected $iCSIMalt = ''; |
|
50
|
|
|
protected $iCSIMtarget = ''; |
|
51
|
|
|
protected $iCSIMWinTarget = ''; |
|
52
|
|
|
private $iBoxType = 1; // Which variant of filled box around text we want |
|
53
|
|
|
|
|
54
|
|
|
// for __get, __set |
|
55
|
|
|
private $_margin; |
|
56
|
|
|
private $_font_size = 8; // old. 12 |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* CONSTRUCTOR. |
|
60
|
|
|
* |
|
61
|
|
|
* @param mixed $aTxt |
|
62
|
|
|
* @param mixed $aXAbsPos |
|
63
|
|
|
* @param mixed $aYAbsPos |
|
64
|
|
|
*/ |
|
65
|
|
|
// Create new text at absolute pixel coordinates |
|
66
|
21 |
|
public function __construct($aTxt = '', $aXAbsPos = 0, $aYAbsPos = 0) |
|
67
|
|
|
{ |
|
68
|
21 |
|
if (!is_string($aTxt)) { |
|
69
|
|
|
Util\JpGraphError::RaiseL(25050); //('First argument to Text::Text() must be s atring.'); |
|
70
|
|
|
} |
|
71
|
21 |
|
$this->t = $aTxt; |
|
72
|
21 |
|
$this->x = round($aXAbsPos); |
|
73
|
21 |
|
$this->y = round($aYAbsPos); |
|
74
|
21 |
|
$this->margin = 0; |
|
75
|
21 |
|
} |
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* PUBLIC METHODS. |
|
79
|
|
|
* |
|
80
|
|
|
* @param mixed $aTxt |
|
81
|
|
|
*/ |
|
82
|
|
|
// Set the string in the text object |
|
83
|
19 |
|
public function Set($aTxt) |
|
84
|
|
|
{ |
|
85
|
19 |
|
$this->t = $aTxt; |
|
86
|
19 |
|
} |
|
87
|
|
|
|
|
88
|
|
|
// Alias for Pos() |
|
89
|
21 |
|
public function SetPos($aXAbsPos = 0, $aYAbsPos = 0, $aHAlign = 'left', $aVAlign = 'top') |
|
90
|
|
|
{ |
|
91
|
|
|
//$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign); |
|
92
|
21 |
|
$this->x = $aXAbsPos; |
|
93
|
21 |
|
$this->y = $aYAbsPos; |
|
94
|
21 |
|
$this->halign = $aHAlign; |
|
95
|
21 |
|
$this->valign = $aVAlign; |
|
96
|
21 |
|
} |
|
97
|
|
|
|
|
98
|
|
|
public function SetScalePos($aX, $aY) |
|
99
|
|
|
{ |
|
100
|
|
|
$this->iScalePosX = $aX; |
|
101
|
|
|
$this->iScalePosY = $aY; |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
// Specify alignment for the text |
|
105
|
21 |
|
public function Align($aHAlign, $aVAlign = 'top', $aParagraphAlign = '') |
|
106
|
|
|
{ |
|
107
|
21 |
|
$this->halign = $aHAlign; |
|
108
|
21 |
|
$this->valign = $aVAlign; |
|
109
|
21 |
|
if ($aParagraphAlign != '') { |
|
110
|
|
|
$this->paragraph_align = $aParagraphAlign; |
|
111
|
|
|
} |
|
112
|
21 |
|
} |
|
113
|
|
|
|
|
114
|
|
|
// Alias |
|
115
|
21 |
|
public function SetAlign($aHAlign, $aVAlign = 'top', $aParagraphAlign = '') |
|
116
|
|
|
{ |
|
117
|
21 |
|
$this->Align($aHAlign, $aVAlign, $aParagraphAlign); |
|
118
|
21 |
|
} |
|
119
|
|
|
|
|
120
|
|
|
// Specifies the alignment for a multi line text |
|
121
|
21 |
|
public function ParagraphAlign($aAlign) |
|
122
|
|
|
{ |
|
123
|
21 |
|
$this->paragraph_align = $aAlign; |
|
124
|
21 |
|
} |
|
125
|
|
|
|
|
126
|
|
|
// Specifies the alignment for a multi line text |
|
127
|
|
|
public function SetParagraphAlign($aAlign) |
|
128
|
|
|
{ |
|
129
|
|
|
$this->paragraph_align = $aAlign; |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
public function SetShadow($aShadowColor = 'gray', $aShadowWidth = 3) |
|
133
|
|
|
{ |
|
134
|
|
|
$this->ishadowwidth = $aShadowWidth; |
|
135
|
|
|
$this->shadow = $aShadowColor; |
|
136
|
|
|
$this->boxed = true; |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
public function SetWordWrap($aCol) |
|
140
|
|
|
{ |
|
141
|
|
|
$this->iWordwrap = $aCol; |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
// Specify that the text should be boxed. fcolor=frame color, bcolor=border color, |
|
145
|
|
|
// $shadow=drop shadow should be added around the text. |
|
146
|
|
|
public function SetBox($aFrameColor = [255, 255, 255], $aBorderColor = [0, 0, 0], $aShadowColor = false, $aCornerRadius = 4, $aShadowWidth = 3) |
|
147
|
|
|
{ |
|
148
|
|
|
if ($aFrameColor === false) { |
|
149
|
|
|
$this->boxed = false; |
|
150
|
|
|
} else { |
|
151
|
|
|
$this->boxed = true; |
|
152
|
|
|
} |
|
153
|
|
|
$this->fcolor = $aFrameColor; |
|
154
|
|
|
$this->bcolor = $aBorderColor; |
|
155
|
|
|
// For backwards compatibility when shadow was just true or false |
|
156
|
|
|
if ($aShadowColor === true) { |
|
157
|
|
|
$aShadowColor = 'gray'; |
|
158
|
|
|
} |
|
159
|
|
|
$this->shadow = $aShadowColor; |
|
160
|
|
|
$this->icornerradius = $aCornerRadius; |
|
161
|
|
|
$this->ishadowwidth = $aShadowWidth; |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
public function SetBox2($aFrameColor = [255, 255, 255], $aBorderColor = [0, 0, 0], $aShadowColor = false, $aCornerRadius = 4, $aShadowWidth = 3) |
|
165
|
|
|
{ |
|
166
|
|
|
$this->iBoxType = 2; |
|
167
|
|
|
$this->SetBox($aFrameColor, $aBorderColor, $aShadowColor, $aCornerRadius, $aShadowWidth); |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
// Hide the text |
|
171
|
16 |
|
public function Hide($aHide = true) |
|
172
|
|
|
{ |
|
173
|
16 |
|
$this->hide = $aHide; |
|
174
|
16 |
|
} |
|
175
|
|
|
|
|
176
|
|
|
// This looks ugly since it's not a very orthogonal design |
|
177
|
|
|
// but I added this "inverse" of Hide() to harmonize |
|
178
|
|
|
// with some classes which I designed more recently (especially) |
|
179
|
|
|
// jpgraph_gantt |
|
180
|
|
|
public function Show($aShow = true) |
|
181
|
|
|
{ |
|
182
|
|
|
$this->hide = !$aShow; |
|
183
|
|
|
} |
|
184
|
|
|
|
|
185
|
|
|
// Specify font |
|
186
|
21 |
|
public function SetFont($aFamily, $aStyle = FS_NORMAL, $aSize = 10) |
|
187
|
|
|
{ |
|
188
|
21 |
|
$this->font_family = $aFamily; |
|
189
|
21 |
|
$this->font_style = $aStyle; |
|
190
|
21 |
|
$this->font_size = $aSize; |
|
191
|
21 |
|
} |
|
192
|
|
|
|
|
193
|
|
|
// Center the text between $left and $right coordinates |
|
194
|
21 |
|
public function Center($aLeft, $aRight, $aYAbsPos = false) |
|
195
|
|
|
{ |
|
196
|
21 |
|
$this->x = $aLeft + ($aRight - $aLeft) / 2; |
|
197
|
21 |
|
$this->halign = 'center'; |
|
198
|
21 |
|
if (is_numeric($aYAbsPos)) { |
|
199
|
21 |
|
$this->y = $aYAbsPos; |
|
200
|
|
|
} |
|
201
|
21 |
|
} |
|
202
|
|
|
|
|
203
|
|
|
// Set text color |
|
204
|
21 |
|
public function SetColor($aColor) |
|
205
|
|
|
{ |
|
206
|
21 |
|
$this->color = $aColor; |
|
207
|
21 |
|
} |
|
208
|
|
|
|
|
209
|
1 |
|
public function SetAngle($aAngle) |
|
210
|
|
|
{ |
|
211
|
1 |
|
$this->SetOrientation($aAngle); |
|
212
|
1 |
|
} |
|
213
|
|
|
|
|
214
|
|
|
// Orientation of text. Note only TTF fonts can have an arbitrary angle |
|
215
|
21 |
|
public function SetOrientation($aDirection = 0) |
|
216
|
|
|
{ |
|
217
|
21 |
|
if (is_numeric($aDirection)) { |
|
218
|
21 |
|
$this->dir = $aDirection; |
|
219
|
|
|
} elseif ($aDirection == 'h') { |
|
220
|
|
|
$this->dir = 0; |
|
221
|
|
|
} elseif ($aDirection == 'v') { |
|
222
|
|
|
$this->dir = 90; |
|
223
|
|
|
} else { |
|
224
|
|
|
Util\JpGraphError::RaiseL(25051); |
|
225
|
|
|
} |
|
226
|
|
|
//(" Invalid direction specified for text."); |
|
227
|
21 |
|
} |
|
228
|
|
|
|
|
229
|
|
|
// Total width of text |
|
230
|
5 |
|
public function GetWidth($aImg) |
|
231
|
|
|
{ |
|
232
|
5 |
|
$aImg->SetFont($this->font_family, $this->font_style, $this->raw_font_size); |
|
233
|
5 |
|
$w = $aImg->GetTextWidth($this->t, $this->dir); |
|
234
|
|
|
|
|
235
|
5 |
|
return $w; |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
// Hight of font |
|
239
|
3 |
|
public function GetFontHeight($aImg) |
|
240
|
|
|
{ |
|
241
|
3 |
|
$aImg->SetFont($this->font_family, $this->font_style, $this->raw_font_size); |
|
242
|
3 |
|
$h = $aImg->GetFontHeight(); |
|
243
|
|
|
|
|
244
|
3 |
|
return $h; |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
21 |
|
public function GetTextHeight($aImg) |
|
248
|
|
|
{ |
|
249
|
21 |
|
$aImg->SetFont($this->font_family, $this->font_style, $this->raw_font_size); |
|
250
|
21 |
|
$h = $aImg->GetTextHeight($this->t, $this->dir); |
|
251
|
|
|
|
|
252
|
21 |
|
return $h; |
|
253
|
|
|
} |
|
254
|
|
|
|
|
255
|
|
|
public function GetHeight($aImg) |
|
256
|
|
|
{ |
|
257
|
|
|
// Synonym for GetTextHeight() |
|
258
|
|
|
$aImg->SetFont($this->font_family, $this->font_style, $this->raw_font_size); |
|
259
|
|
|
$h = $aImg->GetTextHeight($this->t, $this->dir); |
|
260
|
|
|
|
|
261
|
|
|
return $h; |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
// Set the margin which will be interpretated differently depending |
|
265
|
|
|
// on the context. |
|
266
|
21 |
|
public function SetMargin($aMarg) |
|
267
|
|
|
{ |
|
268
|
21 |
|
$this->margin = $aMarg; |
|
269
|
21 |
|
} |
|
270
|
|
|
|
|
271
|
1 |
|
public function StrokeWithScale($aImg, $axscale, $ayscale) |
|
272
|
|
|
{ |
|
273
|
1 |
|
if ($this->iScalePosX === null || $this->iScalePosY === null) { |
|
274
|
1 |
|
$this->Stroke($aImg); |
|
275
|
|
|
} else { |
|
276
|
|
|
$this->Stroke( |
|
277
|
|
|
$aImg, |
|
278
|
|
|
round($axscale->Translate($this->iScalePosX)), |
|
279
|
|
|
round($ayscale->Translate($this->iScalePosY)) |
|
280
|
|
|
); |
|
281
|
|
|
} |
|
282
|
1 |
|
} |
|
283
|
|
|
|
|
284
|
|
|
public function SetCSIMTarget($aURITarget, $aAlt = '', $aWinTarget = '') |
|
285
|
|
|
{ |
|
286
|
|
|
$this->iCSIMtarget = $aURITarget; |
|
287
|
|
|
$this->iCSIMalt = $aAlt; |
|
288
|
|
|
$this->iCSIMWinTarget = $aWinTarget; |
|
289
|
|
|
} |
|
290
|
|
|
|
|
291
|
|
|
public function GetCSIMareas() |
|
292
|
|
|
{ |
|
293
|
|
|
if ($this->iCSIMtarget !== '') { |
|
294
|
|
|
return $this->iCSIMarea; |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
return ''; |
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
|
|
// Display text in image |
|
301
|
21 |
|
public function Stroke($aImg, $x = null, $y = null) |
|
302
|
|
|
{ |
|
303
|
21 |
|
if (is_numeric($x)) { |
|
304
|
21 |
|
$this->x = round($x); |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
21 |
|
if (is_numeric($y)) { |
|
308
|
21 |
|
$this->y = round($y); |
|
309
|
|
|
} |
|
310
|
|
|
|
|
311
|
|
|
// Insert newlines |
|
312
|
21 |
|
if ($this->iWordwrap > 0) { |
|
313
|
|
|
$this->t = wordwrap($this->t, $this->iWordwrap, "\n"); |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
// If position been given as a fraction of the image size |
|
317
|
|
|
// calculate the absolute position |
|
318
|
21 |
|
if ($this->x < 1 && $this->x > 0) { |
|
319
|
|
|
$this->x *= $aImg->width; |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
21 |
|
if ($this->y < 1 && $this->y > 0) { |
|
323
|
|
|
$this->y *= $aImg->height; |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
21 |
|
$aImg->PushColor($this->color); |
|
327
|
21 |
|
$aImg->SetFont($this->font_family, $this->font_style, $this->raw_font_size); |
|
328
|
21 |
|
$aImg->SetTextAlign($this->halign, $this->valign); |
|
329
|
|
|
|
|
330
|
21 |
|
if ($this->boxed) { |
|
331
|
|
|
if ($this->fcolor == 'nofill') { |
|
332
|
|
|
$this->fcolor = false; |
|
333
|
|
|
} |
|
334
|
|
|
|
|
335
|
|
|
$oldweight = $aImg->SetLineWeight(1); |
|
336
|
|
|
|
|
337
|
|
|
if ($this->iBoxType == 2 && $this->font_family > FF_FONT2 + 2) { |
|
338
|
|
|
$bbox = $aImg->StrokeBoxedText2( |
|
339
|
|
|
$this->x, |
|
340
|
|
|
$this->y, |
|
341
|
|
|
$this->t, |
|
342
|
|
|
$this->dir, |
|
343
|
|
|
$this->fcolor, |
|
344
|
|
|
$this->bcolor, |
|
345
|
|
|
$this->shadow, |
|
346
|
|
|
$this->paragraph_align, |
|
347
|
|
|
2, |
|
348
|
|
|
4, |
|
349
|
|
|
$this->icornerradius, |
|
350
|
|
|
$this->ishadowwidth |
|
351
|
|
|
); |
|
352
|
|
|
} else { |
|
353
|
|
|
$bbox = $aImg->StrokeBoxedText( |
|
354
|
|
|
$this->x, |
|
355
|
|
|
$this->y, |
|
356
|
|
|
$this->t, |
|
357
|
|
|
$this->dir, |
|
358
|
|
|
$this->fcolor, |
|
359
|
|
|
$this->bcolor, |
|
360
|
|
|
$this->shadow, |
|
361
|
|
|
$this->paragraph_align, |
|
362
|
|
|
3, |
|
363
|
|
|
3, |
|
364
|
|
|
$this->icornerradius, |
|
365
|
|
|
$this->ishadowwidth |
|
366
|
|
|
); |
|
367
|
|
|
} |
|
368
|
|
|
|
|
369
|
|
|
$aImg->SetLineWeight($oldweight); |
|
370
|
|
|
} else { |
|
371
|
21 |
|
$debug = false; |
|
372
|
21 |
|
$bbox = $aImg->StrokeText($this->x, $this->y, $this->t, $this->dir, $this->paragraph_align, $debug); |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
// Create CSIM targets |
|
376
|
21 |
|
$coords = implode(',', [ |
|
377
|
21 |
|
$bbox[0], $bbox[1], $bbox[2], $bbox[3], $bbox[4], $bbox[5], $bbox[6], $bbox[7], |
|
378
|
|
|
]); |
|
379
|
21 |
|
$this->iCSIMarea = "<area shape=\"poly\" coords=\"${coords}\" href=\""; |
|
380
|
21 |
|
$this->iCSIMarea .= htmlentities($this->iCSIMtarget) . '" '; |
|
381
|
21 |
|
if (trim($this->iCSIMalt) != '') { |
|
382
|
|
|
$this->iCSIMarea .= ' alt="' . $this->iCSIMalt . '" '; |
|
383
|
|
|
$this->iCSIMarea .= ' title="' . $this->iCSIMalt . '" '; |
|
384
|
|
|
} |
|
385
|
21 |
|
if (trim($this->iCSIMWinTarget) != '') { |
|
386
|
|
|
$this->iCSIMarea .= ' target="' . $this->iCSIMWinTarget . '" '; |
|
387
|
|
|
} |
|
388
|
21 |
|
$this->iCSIMarea .= " />\n"; |
|
389
|
|
|
|
|
390
|
21 |
|
$aImg->PopColor($this->color); |
|
391
|
21 |
|
} |
|
392
|
|
|
|
|
393
|
21 |
|
public function __get($name) |
|
394
|
|
|
{ |
|
395
|
21 |
|
if (strpos($name, 'raw_') !== false) { |
|
396
|
|
|
// if $name == 'raw_left_margin' , return $this->_left_margin; |
|
397
|
21 |
|
$variable_name = '_' . str_replace('raw_', '', $name); |
|
398
|
|
|
|
|
399
|
21 |
|
return $this->{$variable_name}; |
|
400
|
|
|
} |
|
401
|
|
|
|
|
402
|
21 |
|
$variable_name = '_' . $name; |
|
403
|
|
|
|
|
404
|
21 |
|
if (isset($this->{$variable_name})) { |
|
405
|
21 |
|
return $this->{$variable_name} * SUPERSAMPLING_SCALE; |
|
406
|
|
|
} |
|
407
|
|
|
Util\JpGraphError::RaiseL('25132', $name); |
|
408
|
|
|
} |
|
409
|
|
|
|
|
410
|
21 |
|
public function __set($name, $value) |
|
411
|
|
|
{ |
|
412
|
21 |
|
$this->{'_' . $name} = $value; |
|
413
|
21 |
|
} |
|
414
|
|
|
} // @class |
|
415
|
|
|
|