Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
98.90% |
179 / 181 |
|
97.67% |
42 / 43 |
CRAP | |
0.00% |
0 / 1 |
Text | |
98.90% |
179 / 181 |
|
97.67% |
42 / 43 |
88 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
setString | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
setStrings | |
84.62% |
11 / 13 |
|
0.00% |
0 / 1 |
5.09 | |||
addStringWithOffset | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
getStringsWithOffset | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setSize | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setFillColor | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setStrokeColor | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setStroke | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
setRotation | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
setCharWrap | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
setLeading | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setAlignment | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setWrap | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setTextStream | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
escape | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
5 | |||
getString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStrings | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSize | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFillColor | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStrokeColor | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStroke | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getRotation | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getCharWrap | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getNumberOfWrappedLines | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getLeading | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getAlignment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getWrap | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTextStream | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasStrings | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasCharWrap | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasLeading | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasAlignment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasWrap | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasTextStream | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setTextParams | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
5 | |||
startStream | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
endStream | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStream | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPartialStream | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
9 | |||
getColorStream | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
9 | |||
calculateTextMatrix | |
100.00% |
36 / 36 |
|
100.00% |
1 / 1 |
10 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Pdf\Document\Page; |
15 | |
16 | use Pop\Color\Color; |
17 | use Pop\Color\Color\ColorInterface; |
18 | use OutOfRangeException; |
19 | |
20 | /** |
21 | * Pdf page text class |
22 | * |
23 | * @category Pop |
24 | * @package Pop\Pdf |
25 | * @author Nick Sagona, III <dev@nolainteractive.com> |
26 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
27 | * @license http://www.popphp.org/license New BSD License |
28 | * @version 5.0.0 |
29 | */ |
30 | class Text |
31 | { |
32 | |
33 | /** |
34 | * Text string value |
35 | * @var ?string |
36 | */ |
37 | protected ?string $string = null; |
38 | |
39 | /** |
40 | * Text strings as array for streaming |
41 | * @var array |
42 | */ |
43 | protected array $strings = []; |
44 | |
45 | /** |
46 | * Text strings with offset values |
47 | * @var array |
48 | */ |
49 | protected array $stringsWithOffsets = []; |
50 | |
51 | /** |
52 | * Text font size |
53 | * @var int|float |
54 | */ |
55 | protected int|float $size = 12; |
56 | |
57 | /** |
58 | * Text fill color |
59 | * @var ?ColorInterface |
60 | */ |
61 | protected ?ColorInterface $fillColor = null; |
62 | |
63 | /** |
64 | * Text stroke color |
65 | * @var ?ColorInterface |
66 | */ |
67 | protected ?ColorInterface$strokeColor = null; |
68 | |
69 | /** |
70 | * Text stroke |
71 | * @var array |
72 | */ |
73 | protected array $stroke = [ |
74 | 'width' => 0, |
75 | 'dashLength' => null, |
76 | 'dashGap' => null |
77 | ]; |
78 | |
79 | /** |
80 | * Basic wrap based on character length |
81 | * @var int |
82 | */ |
83 | protected int $charWrap = 0; |
84 | |
85 | /** |
86 | * Leading for the lines for a character wrap |
87 | * @var int |
88 | */ |
89 | protected int $leading = 0; |
90 | |
91 | /** |
92 | * Text alignment object |
93 | * @var ?Text\Alignment |
94 | */ |
95 | protected ?Text\Alignment $alignment = null; |
96 | |
97 | /** |
98 | * Text wrap object |
99 | * @var ?Text\Wrap |
100 | */ |
101 | protected ?Text\Wrap $wrap = null; |
102 | |
103 | /** |
104 | * Text stream object |
105 | * @var ?Text\Stream |
106 | */ |
107 | protected ?Text\Stream $stream = null; |
108 | |
109 | /** |
110 | * Text parameters |
111 | * @var array |
112 | */ |
113 | protected array $textParams = [ |
114 | 'c' => 0, |
115 | 'w' => 0, |
116 | 'h' => 100, |
117 | 'v' => 100, |
118 | 'rot' => 0, |
119 | 'rend' => 0 |
120 | ]; |
121 | |
122 | /** |
123 | * Constructor |
124 | * |
125 | * Instantiate a PDF text object. |
126 | * |
127 | * @param ?string $string |
128 | * @param ?string $size |
129 | */ |
130 | public function __construct(?string $string = null, ?string $size = null) |
131 | { |
132 | if ($string !== null) { |
133 | $this->setString($string); |
134 | } |
135 | if ($size !== null) { |
136 | $this->setSize($size); |
137 | } |
138 | } |
139 | |
140 | /** |
141 | * Set the text string |
142 | * |
143 | * @param string $string |
144 | * @return Text |
145 | */ |
146 | public function setString(string $string): Text |
147 | { |
148 | if (function_exists('mb_strlen')) { |
149 | if (mb_strlen($string, 'UTF-8') < strlen($string)) { |
150 | $string = mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string)); |
151 | } |
152 | } |
153 | $this->string = $string; |
154 | return $this; |
155 | } |
156 | |
157 | /** |
158 | * Set the text strings |
159 | * |
160 | * @param array $strings |
161 | * @return Text |
162 | */ |
163 | public function setStrings(array $strings): Text |
164 | { |
165 | if (function_exists('mb_strlen')) { |
166 | $strings = array_map(function($value) { |
167 | if ($value instanceof Text) { |
168 | $v = $value->getString(); |
169 | if (mb_strlen($v, 'UTF-8') < strlen($v)) { |
170 | return mb_convert_encoding($v, 'UTF-8', mb_detect_encoding($v)); |
171 | } |
172 | $value->setString($v); |
173 | } else if (mb_strlen($value, 'UTF-8') < strlen($value)) { |
174 | $value = mb_convert_encoding($value, 'UTF-8', mb_detect_encoding($value)); |
175 | } |
176 | return $value; |
177 | }, $strings); |
178 | |
179 | } |
180 | $this->strings = $strings; |
181 | return $this; |
182 | } |
183 | |
184 | /** |
185 | * Add a string with offset |
186 | * |
187 | * @param string $string |
188 | * @param int $offset |
189 | * @return Text |
190 | */ |
191 | public function addStringWithOffset(string $string, int $offset = 0): Text |
192 | { |
193 | if (function_exists('mb_strlen')) { |
194 | if (mb_strlen($string, 'UTF-8') < strlen($string)) { |
195 | $string = mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string)); |
196 | } |
197 | } |
198 | $this->stringsWithOffsets[] = [ |
199 | 'string' => $string, |
200 | 'offset' => $offset |
201 | ]; |
202 | return $this; |
203 | } |
204 | |
205 | /** |
206 | * Get strings with offset |
207 | * |
208 | * @return array |
209 | */ |
210 | public function getStringsWithOffset(): array |
211 | { |
212 | return $this->stringsWithOffsets; |
213 | } |
214 | |
215 | /** |
216 | * Set the text size |
217 | * |
218 | * @param int|float $size |
219 | * @return Text |
220 | */ |
221 | public function setSize(int|float $size): Text |
222 | { |
223 | $this->size = $size; |
224 | return $this; |
225 | } |
226 | |
227 | /** |
228 | * Set the text fill color |
229 | * |
230 | * @param ColorInterface $color |
231 | * @return Text |
232 | */ |
233 | public function setFillColor(ColorInterface $color): Text |
234 | { |
235 | $this->fillColor = $color; |
236 | return $this; |
237 | } |
238 | |
239 | /** |
240 | * Set the text stroke color |
241 | * |
242 | * @param ColorInterface $color |
243 | * @return Text |
244 | */ |
245 | public function setStrokeColor(ColorInterface $color): Text |
246 | { |
247 | $this->strokeColor = $color; |
248 | return $this; |
249 | } |
250 | |
251 | /** |
252 | * Set the text stroke properties |
253 | * |
254 | * @param int $width |
255 | * @param ?int $dashLength |
256 | * @param ?int $dashGap |
257 | * @return Text |
258 | */ |
259 | public function setStroke(int $width, ?int $dashLength = null, ?int $dashGap = null): Text |
260 | { |
261 | $this->stroke = [ |
262 | 'width' => $width, |
263 | 'dashLength' => $dashLength, |
264 | 'dashGap' => $dashGap |
265 | ]; |
266 | return $this; |
267 | } |
268 | |
269 | /** |
270 | * Method to set the rotation of the text |
271 | * |
272 | * @param int $rotation |
273 | * @throws OutOfRangeException |
274 | * @return Text |
275 | */ |
276 | public function setRotation(int $rotation): Text |
277 | { |
278 | if (abs($rotation) > 90) { |
279 | throw new OutOfRangeException('Error: The rotation parameter must be between -90 and 90 degrees.'); |
280 | } |
281 | $this->textParams['rot'] = $rotation; |
282 | return $this; |
283 | } |
284 | |
285 | /** |
286 | * Method to set the character wrap |
287 | * |
288 | * @param int $charWrap |
289 | * @param ?int $leading |
290 | * @return Text |
291 | */ |
292 | public function setCharWrap(int $charWrap, ?int $leading = null): Text |
293 | { |
294 | $this->charWrap = $charWrap; |
295 | if ($leading !== null) { |
296 | $this->setLeading($leading); |
297 | } |
298 | return $this; |
299 | } |
300 | |
301 | /** |
302 | * Method to set the character wrap leading |
303 | * |
304 | * @param int $leading |
305 | * @return Text |
306 | */ |
307 | public function setLeading(int $leading): Text |
308 | { |
309 | $this->leading = $leading; |
310 | return $this; |
311 | } |
312 | |
313 | /** |
314 | * Method to set the text alignment |
315 | * |
316 | * @param Text\Alignment $alignment |
317 | * @return Text |
318 | */ |
319 | public function setAlignment(Text\Alignment $alignment): Text |
320 | { |
321 | $this->alignment = $alignment; |
322 | return $this; |
323 | } |
324 | |
325 | /** |
326 | * Method to set the text wrap |
327 | * |
328 | * @param Text\Wrap $wrap |
329 | * @return Text |
330 | */ |
331 | public function setWrap(Text\Wrap $wrap): Text |
332 | { |
333 | $this->wrap = $wrap; |
334 | return $this; |
335 | } |
336 | |
337 | /** |
338 | * Method to set the text stream |
339 | * |
340 | * @param Text\Stream $stream |
341 | * @return Text |
342 | */ |
343 | public function setTextStream(Text\Stream $stream): Text |
344 | { |
345 | $this->stream = $stream; |
346 | return $this; |
347 | } |
348 | |
349 | /** |
350 | * Escape string |
351 | * |
352 | * @param mixed $search |
353 | * @param mixed $replace |
354 | * @return Text |
355 | */ |
356 | public function escape(mixed $search = null, mixed $replace = null): Text |
357 | { |
358 | $searchAry = ['(', ')']; |
359 | $replaceAry = ['\(', '\)']; |
360 | |
361 | if (($search !== null) && ($replace !== null)) { |
362 | if (!is_array($search)) { |
363 | $search = [$search]; |
364 | } |
365 | if (!is_array($replace)) { |
366 | $replace = [$replace]; |
367 | } |
368 | $searchAry = array_merge($searchAry, $search); |
369 | $replaceAry = array_merge($replaceAry, $replace); |
370 | } |
371 | |
372 | $this->string = str_replace($searchAry, $replaceAry, $this->string); |
373 | return $this; |
374 | } |
375 | |
376 | /** |
377 | * Get the text string |
378 | * |
379 | * @return ?string |
380 | */ |
381 | public function getString(): ?string |
382 | { |
383 | return $this->string; |
384 | } |
385 | |
386 | /** |
387 | * Get the text string array |
388 | * |
389 | * @return array |
390 | */ |
391 | public function getStrings(): array |
392 | { |
393 | return $this->strings; |
394 | } |
395 | |
396 | /** |
397 | * Get the text size |
398 | * |
399 | * @return int|float |
400 | */ |
401 | public function getSize(): int|float |
402 | { |
403 | return $this->size; |
404 | } |
405 | |
406 | /** |
407 | * Get the text fill color |
408 | * |
409 | * @return ?ColorInterface |
410 | */ |
411 | public function getFillColor(): ?ColorInterface |
412 | { |
413 | return $this->fillColor; |
414 | } |
415 | |
416 | /** |
417 | * Get the text stroke color |
418 | * |
419 | * @return ?ColorInterface |
420 | */ |
421 | public function getStrokeColor(): ?ColorInterface |
422 | { |
423 | return $this->strokeColor; |
424 | } |
425 | |
426 | /** |
427 | * Get the text stroke properties |
428 | * |
429 | * @return array |
430 | */ |
431 | public function getStroke(): array |
432 | { |
433 | return $this->stroke; |
434 | } |
435 | |
436 | /** |
437 | * Get the rotation of the text |
438 | * |
439 | * @return int |
440 | */ |
441 | public function getRotation(): int |
442 | { |
443 | return $this->textParams['rot']; |
444 | } |
445 | |
446 | /** |
447 | * Get character wrap |
448 | * |
449 | * @return int |
450 | */ |
451 | public function getCharWrap(): int |
452 | { |
453 | return $this->charWrap; |
454 | } |
455 | |
456 | /** |
457 | * Get number of wrapped lines from character wrap |
458 | * |
459 | * @return int |
460 | */ |
461 | public function getNumberOfWrappedLines(): int |
462 | { |
463 | return count(explode("\n", wordwrap($this->string, $this->charWrap, "\n"))); |
464 | } |
465 | |
466 | /** |
467 | * Get character wrap leading |
468 | * |
469 | * @return int |
470 | */ |
471 | public function getLeading(): int |
472 | { |
473 | return $this->leading; |
474 | } |
475 | |
476 | /** |
477 | * Get text alignment |
478 | * |
479 | * @return ?Text\Alignment |
480 | */ |
481 | public function getAlignment(): ?Text\Alignment |
482 | { |
483 | return $this->alignment; |
484 | } |
485 | |
486 | /** |
487 | * Get text wrap |
488 | * |
489 | * @return ?Text\Wrap |
490 | */ |
491 | public function getWrap(): ?Text\Wrap |
492 | { |
493 | return $this->wrap; |
494 | } |
495 | |
496 | /** |
497 | * Get text stream |
498 | * |
499 | * @return ?Text\Stream |
500 | */ |
501 | public function getTextStream(): ?Text\Stream |
502 | { |
503 | return $this->stream; |
504 | } |
505 | |
506 | /** |
507 | * Has text string |
508 | * |
509 | * @return bool |
510 | */ |
511 | public function hasString(): bool |
512 | { |
513 | return ($this->string !== null); |
514 | } |
515 | |
516 | /** |
517 | * Has text string array |
518 | * |
519 | * @return bool |
520 | */ |
521 | public function hasStrings(): bool |
522 | { |
523 | return !empty($this->strings); |
524 | } |
525 | |
526 | /** |
527 | * Has character wrap |
528 | * |
529 | * @return bool |
530 | */ |
531 | public function hasCharWrap(): bool |
532 | { |
533 | return ($this->charWrap > 0); |
534 | } |
535 | |
536 | /** |
537 | * Has character wrap leading |
538 | * |
539 | * @return bool |
540 | */ |
541 | public function hasLeading(): bool |
542 | { |
543 | return ($this->leading > 0); |
544 | } |
545 | |
546 | /** |
547 | * Has text alignment |
548 | * |
549 | * @return bool |
550 | */ |
551 | public function hasAlignment(): bool |
552 | { |
553 | return ($this->alignment !== null); |
554 | } |
555 | |
556 | /** |
557 | * Has text wrap |
558 | * |
559 | * @return bool |
560 | */ |
561 | public function hasWrap(): bool |
562 | { |
563 | return ($this->wrap !== null); |
564 | } |
565 | |
566 | /** |
567 | * Has text stream |
568 | * |
569 | * @return bool |
570 | */ |
571 | public function hasTextStream(): bool |
572 | { |
573 | return ($this->stream !== null); |
574 | } |
575 | |
576 | /** |
577 | * Set the text parameters for rendering text content |
578 | * |
579 | * @param int $c (character spacing) |
580 | * @param int $w (word spacing) |
581 | * @param int $h (horz stretch) |
582 | * @param int $v (vert stretch) |
583 | * @param int $rot (rotation, -90 - 90) |
584 | * @param int $rend (render flag, 0 - 7) |
585 | * @throws OutOfRangeException |
586 | * @return Text |
587 | */ |
588 | public function setTextParams(int $c = 0, int $w = 0, int $h = 100, int $v = 100, int $rot = 0, int $rend = 0): Text |
589 | { |
590 | // Check the rotation parameter. |
591 | if (abs($rot) > 90) { |
592 | throw new OutOfRangeException('Error: The rotation parameter must be between -90 and 90 degrees.'); |
593 | } |
594 | |
595 | // Check the render parameter. |
596 | if ((!is_int($rend)) || (($rend > 7) || ($rend < 0))) { |
597 | throw new OutOfRangeException('Error: The render parameter must be an integer between 0 and 7.'); |
598 | } |
599 | |
600 | // Set the text parameters. |
601 | $this->textParams['c'] = $c; |
602 | $this->textParams['w'] = $w; |
603 | $this->textParams['h'] = $h; |
604 | $this->textParams['v'] = $v; |
605 | $this->textParams['rot'] = $rot; |
606 | $this->textParams['rend'] = $rend; |
607 | |
608 | return $this; |
609 | } |
610 | |
611 | /** |
612 | * Start the text stream |
613 | * |
614 | * @param string $fontReference |
615 | * @param int $x |
616 | * @param int $y |
617 | * @return string |
618 | */ |
619 | public function startStream(string $fontReference, int $x, int $y): string |
620 | { |
621 | $stream = ''; |
622 | $fontReference = substr($fontReference, 0, strpos($fontReference, ' ')); |
623 | |
624 | $stream .= "\nBT\n {$fontReference} {$this->size} Tf\n " . $this->calculateTextMatrix() . |
625 | " {$x} {$y} Tm\n " . $this->textParams['c'] . " Tc " . $this->textParams['w'] . |
626 | " Tw " . $this->textParams['rend'] . " Tr\n"; |
627 | |
628 | return $stream; |
629 | } |
630 | |
631 | /** |
632 | * End the text stream |
633 | * |
634 | * @return string |
635 | */ |
636 | public function endStream(): string |
637 | { |
638 | return "ET\n"; |
639 | } |
640 | |
641 | /** |
642 | * Get the text stream |
643 | * |
644 | * @param string $fontReference |
645 | * @param int $x |
646 | * @param int $y |
647 | * @return string |
648 | */ |
649 | public function getStream(string $fontReference, int $x, int $y): string |
650 | { |
651 | return $this->startStream($fontReference, $x, $y) . $this->getPartialStream() . $this->endStream(); |
652 | } |
653 | |
654 | /** |
655 | * Get the partial text stream |
656 | * |
657 | * @param ?string $fontReference |
658 | * @return string |
659 | */ |
660 | public function getPartialStream(?string $fontReference = null): string |
661 | { |
662 | $stream = ''; |
663 | |
664 | if ($fontReference !== null) { |
665 | $fontReference = substr($fontReference, 0, strpos($fontReference, ' ')); |
666 | $stream .= " {$fontReference} {$this->size} Tf\n"; |
667 | } |
668 | |
669 | $stream .= $this->getColorStream(); |
670 | |
671 | if (count($this->stringsWithOffsets) > 0) { |
672 | $stream .= " [({$this->string})"; |
673 | foreach ($this->stringsWithOffsets as $string) { |
674 | $stream .= " " . (0 - $string['offset']) . " (" . $string['string'] . ")"; |
675 | } |
676 | $stream .= "]TJ\n"; |
677 | } else { |
678 | if (($this->hasCharWrap()) && (strlen($this->string) > $this->charWrap)) { |
679 | if ((int)$this->leading == 0) { |
680 | $this->leading = $this->size; |
681 | } |
682 | |
683 | $strings = explode("\n", wordwrap($this->string, $this->charWrap, "\n")); |
684 | |
685 | foreach ($strings as $i => $string) { |
686 | $stream .= " ({$string})Tj\n"; |
687 | if ($i < count($strings)) { |
688 | $stream .= " 0 -" . $this->leading . " Td\n"; |
689 | } |
690 | } |
691 | } else { |
692 | $stream .= " ({$this->string})Tj\n"; |
693 | } |
694 | } |
695 | |
696 | return $stream; |
697 | } |
698 | |
699 | /** |
700 | * Get the partial color stream |
701 | * |
702 | * @return string |
703 | */ |
704 | public function getColorStream(): string |
705 | { |
706 | $stream = ''; |
707 | |
708 | if ($this->fillColor !== null) { |
709 | if ($this->fillColor instanceof Color\Rgb) { |
710 | $stream .= ' ' . $this->fillColor->render(Color\Rgb::PERCENT) . " rg\n"; |
711 | } else if ($this->fillColor instanceof Color\Cmyk) { |
712 | $stream .= ' ' . $this->fillColor->render(Color\Cmyk::PERCENT) . " k\n"; |
713 | } else if ($this->fillColor instanceof Color\Grayscale) { |
714 | $stream .= ' ' . $this->fillColor->render(Color\Grayscale::PERCENT) . " g\n"; |
715 | } |
716 | } |
717 | if ($this->strokeColor !== null) { |
718 | if ($this->strokeColor instanceof Color\Rgb) { |
719 | $stream .= ' ' . $this->strokeColor->render(Color\Rgb::PERCENT) . " RG\n"; |
720 | } else if ($this->strokeColor instanceof Color\Cmyk) { |
721 | $stream .= ' ' . $this->strokeColor->render(Color\Cmyk::PERCENT) . " K\n"; |
722 | } else if ($this->strokeColor instanceof Color\Grayscale) { |
723 | $stream .= ' ' . $this->strokeColor->render(Color\Grayscale::PERCENT) . " G\n"; |
724 | } |
725 | } |
726 | |
727 | return $stream; |
728 | } |
729 | |
730 | /** |
731 | * Calculate text matrix |
732 | * |
733 | * @return string |
734 | */ |
735 | protected function calculateTextMatrix(): string |
736 | { |
737 | // Define some variables. |
738 | $a = ''; |
739 | $b = ''; |
740 | $c = ''; |
741 | $d = ''; |
742 | $neg = null; |
743 | |
744 | // Determine is the rotate parameter is negative or not. |
745 | $neg = ($this->textParams['rot'] < 0) ? true : false; |
746 | |
747 | // Calculate the text matrix parameters. |
748 | $rot = abs($this->textParams['rot']); |
749 | |
750 | if (($rot >= 0) && ($rot <= 45)) { |
751 | $factor = round(($rot / 45), 2); |
752 | if ($neg) { |
753 | $a = 1; |
754 | $b = '-' . $factor; |
755 | $c = $factor; |
756 | $d = 1; |
757 | } else { |
758 | $a = 1; |
759 | $b = $factor; |
760 | $c = '-' . $factor; |
761 | $d = 1; |
762 | } |
763 | } else if (($rot > 45) && ($rot <= 90)) { |
764 | $factor = round(((90 - $rot) / 45), 2); |
765 | if ($neg) { |
766 | $a = $factor; |
767 | $b = -1; |
768 | $c = 1; |
769 | $d = $factor; |
770 | } else { |
771 | $a = $factor; |
772 | $b = 1; |
773 | $c = -1; |
774 | $d = $factor; |
775 | } |
776 | } |
777 | |
778 | // Adjust the text matrix parameters according to the horizontal and vertical scale parameters. |
779 | if ($this->textParams['h'] != 100) { |
780 | $a = round(($a * ($this->textParams['h'] / 100)), 2); |
781 | $b = round(($b * ($this->textParams['h'] / 100)), 2); |
782 | } |
783 | |
784 | if ($this->textParams['v'] != 100) { |
785 | $c = round(($c * ($this->textParams['v'] / 100)), 2); |
786 | $d = round(($d * ($this->textParams['v'] / 100)), 2); |
787 | } |
788 | |
789 | // Return the text matrix. |
790 | return "{$a} {$b} {$c} {$d}"; |
791 | } |
792 | |
793 | } |