PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.3
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.3
2.4.3 2.4.4 2.4.2 2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 All 60 releases
easy-invoice / vendor / dompdf / php-svg-lib / src / Svg / Style.php

Style.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.3, at vendor/dompdf/php-svg-lib/src/Svg/Style.php

576 lines 19.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package php-svg-lib
4 * @link http://github.com/dompdf/php-svg-lib
5 * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
6 */
7
8 namespace Svg;
9
10 use Svg\Tag\AbstractTag;
11
12 class Style
13 {
14 const TYPE_COLOR = 1;
15 const TYPE_LENGTH = 2;
16 const TYPE_NAME = 3;
17 const TYPE_ANGLE = 4;
18 const TYPE_NUMBER = 5;
19
20 private $_document;
21 private $_parentStyle;
22
23 public $color;
24 public $opacity;
25 public $display;
26
27 public $fill;
28 public $fillOpacity;
29 public $fillRule;
30
31 public $stroke;
32 public $strokeOpacity;
33 public $strokeLinecap;
34 public $strokeLinejoin;
35 public $strokeMiterlimit;
36 public $strokeWidth;
37 public $strokeDasharray;
38 public $strokeDashoffset;
39
40 public $fontFamily = 'serif';
41 public $fontSize = 12;
42 public $fontWeight = 'normal';
43 public $fontStyle = 'normal';
44 public $textAnchor = 'start';
45
46 public function __construct($document = null) {
47 if ($document !== null) {
48 $this->_document = $document;
49 }
50 }
51
52 protected function getStyleMap()
53 {
54 return array(
55 'color' => array('color', self::TYPE_COLOR),
56 'opacity' => array('opacity', self::TYPE_NUMBER),
57 'display' => array('display', self::TYPE_NAME),
58
59 'fill' => array('fill', self::TYPE_COLOR),
60 'fill-opacity' => array('fillOpacity', self::TYPE_NUMBER),
61 'fill-rule' => array('fillRule', self::TYPE_NAME),
62
63 'stroke' => array('stroke', self::TYPE_COLOR),
64 'stroke-dasharray' => array('strokeDasharray', self::TYPE_NAME),
65 'stroke-dashoffset' => array('strokeDashoffset', self::TYPE_NUMBER),
66 'stroke-linecap' => array('strokeLinecap', self::TYPE_NAME),
67 'stroke-linejoin' => array('strokeLinejoin', self::TYPE_NAME),
68 'stroke-miterlimit' => array('strokeMiterlimit', self::TYPE_NUMBER),
69 'stroke-opacity' => array('strokeOpacity', self::TYPE_NUMBER),
70 'stroke-width' => array('strokeWidth', self::TYPE_NUMBER),
71
72 'font-family' => array('fontFamily', self::TYPE_NAME),
73 'font-size' => array('fontSize', self::TYPE_NUMBER),
74 'font-weight' => array('fontWeight', self::TYPE_NAME),
75 'font-style' => array('fontStyle', self::TYPE_NAME),
76 'text-anchor' => array('textAnchor', self::TYPE_NAME),
77 );
78 }
79
80 /**
81 * @param $attributes
82 *
83 * @return Style
84 */
85 public function fromAttributes($attributes)
86 {
87 $this->fillStyles($attributes);
88
89 if (isset($attributes["style"])) {
90 $styles = self::parseCssStyle($attributes["style"]);
91 $this->fillStyles($styles);
92 }
93 }
94
95 public function inherit(AbstractTag $tag) {
96 $group = $tag->getParentGroup();
97 if ($group) {
98 $parent_style = $group->getStyle();
99 $this->_parentStyle = $parent_style;
100 foreach ($parent_style as $_key => $_value) {
101 if ($_value !== null) {
102 $this->$_key = $_value;
103 }
104 }
105 }
106 }
107
108 public function fromStyleSheets(AbstractTag $tag, $attributes) {
109 $class = isset($attributes["class"]) ? preg_split('/\s+/', trim($attributes["class"])) : null;
110
111 $stylesheets = $tag->getDocument()->getStyleSheets();
112 $outputFormat = \Sabberworm\CSS\OutputFormat::createCompact();
113
114 $styles = array();
115
116 foreach ($stylesheets as $_sc) {
117
118 /** @var \Sabberworm\CSS\RuleSet\DeclarationBlock $_decl */
119 foreach ($_sc->getAllDeclarationBlocks() as $_decl) {
120
121 /** @var \Sabberworm\CSS\Property\Selector $_selector */
122 foreach ($_decl->getSelectors() as $_selector) {
123 $_selector = $_selector->getSelector();
124
125 // Match class name
126 if ($class !== null) {
127 foreach ($class as $_class) {
128 if ($_selector === ".$_class") {
129 /** @var \Sabberworm\CSS\Rule\Rule $_rule */
130 foreach ($_decl->getRules() as $_rule) {
131 $value = $_rule->getValue();
132 if ($value instanceof \Sabberworm\CSS\Value\Value) {
133 $styles[$_rule->getRule()] = $value->render($outputFormat) . "";
134 } else {
135 $styles[$_rule->getRule()] = $value . "";
136 }
137 }
138
139 break 2;
140 }
141 }
142 }
143
144 // Match tag name
145 if ($_selector === $tag->tagName) {
146 /** @var \Sabberworm\CSS\Rule\Rule $_rule */
147 foreach ($_decl->getRules() as $_rule) {
148 $value = $_rule->getValue();
149 if ($value instanceof \Sabberworm\CSS\Value\Value) {
150 $styles[$_rule->getRule()] = $value->render($outputFormat) . "";
151 } else {
152 $styles[$_rule->getRule()] = $value . "";
153 }
154 }
155
156 break;
157 }
158 }
159 }
160 }
161
162 $this->fillStyles($styles);
163 }
164
165 protected function fillStyles($styles)
166 {
167 $style_map = $this->getStyleMap();
168 foreach ($style_map as $from => $spec) {
169 if (isset($styles[$from])) {
170 list($to, $type) = $spec;
171 $value = null;
172 switch ($type) {
173 case self::TYPE_COLOR:
174 $value = self::parseColor($styles[$from]);
175 if ($value === "currentcolor") {
176 if ($type === "color") {
177 $value = $this->_parentStyle->color;
178 } else {
179 $value = $this->color;
180 }
181 }
182 if (is_array($value) && $value[3] !== 1.0 && array_key_exists("{$from}-opacity", $style_map) === true) {
183 $styles["{$from}-opacity"] = $value[3];
184 }
185 break;
186
187 case self::TYPE_NUMBER:
188 $value = ($styles[$from] === null) ? null : (float)$styles[$from];
189 break;
190
191 default:
192 $value = $styles[$from];
193 }
194
195 if ($from === "font-family") {
196 $scheme = \strtolower(parse_url($value, PHP_URL_SCHEME) ?: "");
197 if (
198 $scheme === "phar" || \strtolower(\substr($value, 0, 7)) === "phar://"
199 || ($this->_document !== null && $this->_document->allowExternalReferences === false && $scheme !== "data")
200 ) {
201 continue;
202 }
203 }
204
205 if ($value !== null) {
206 $this->$to = $value;
207 }
208 }
209 }
210 }
211
212 static function parseColor($color)
213 {
214 $color = strtolower(trim($color));
215
216 $parts = preg_split('/[^,]\s+/', $color, 2);
217
218 if (count($parts) == 2) {
219 $color = $parts[1];
220 } else {
221 $color = $parts[0];
222 }
223
224 if ($color === "none") {
225 return "none";
226 }
227
228 if ($color === "currentcolor") {
229 return "currentcolor";
230 }
231
232 if ($color === "transparent") {
233 return [0.0, 0.0, 0.0, 0.0];
234 }
235
236 // SVG color name
237 if (isset(self::$colorNames[$color])) {
238 return self::parseHexColor(self::$colorNames[$color]);
239 }
240
241 // Hex color
242 if ($color[0] === "#") {
243 return self::parseHexColor($color);
244 }
245
246 // RGB color
247 if (strpos($color, "rgb") !== false) {
248 return self::getQuad($color);
249 }
250
251 // HSL color
252 if (strpos($color, "hsl") !== false) {
253 $quad = self::getQuad($color, true);
254
255 if ($quad == null) {
256 return null;
257 }
258
259 list($h, $s, $l, $a) = $quad;
260
261 $r = $l;
262 $g = $l;
263 $b = $l;
264 $v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
265 if ($v > 0) {
266 $m = $l + $l - $v;
267 $sv = ($v - $m) / $v;
268 $h *= 6.0;
269 $sextant = floor($h);
270 $fract = $h - $sextant;
271 $vsf = $v * $sv * $fract;
272 $mid1 = $m + $vsf;
273 $mid2 = $v - $vsf;
274
275 switch ($sextant) {
276 case 0:
277 $r = $v;
278 $g = $mid1;
279 $b = $m;
280 break;
281 case 1:
282 $r = $mid2;
283 $g = $v;
284 $b = $m;
285 break;
286 case 2:
287 $r = $m;
288 $g = $v;
289 $b = $mid1;
290 break;
291 case 3:
292 $r = $m;
293 $g = $mid2;
294 $b = $v;
295 break;
296 case 4:
297 $r = $mid1;
298 $g = $m;
299 $b = $v;
300 break;
301 case 5:
302 $r = $v;
303 $g = $m;
304 $b = $mid2;
305 break;
306 }
307 }
308 $a = $a * 255;
309
310 return array(
311 $r * 255.0,
312 $g * 255.0,
313 $b * 255.0,
314 $a
315 );
316 }
317
318 // Gradient
319 if (strpos($color, "url(#") !== false) {
320 $i = strpos($color, "(");
321 $j = strpos($color, ")");
322
323 // Bad url format
324 if ($i === false || $j === false) {
325 return null;
326 }
327
328 //FIXME: gradients not supported?
329 return null; // trim(substr($color, $i + 1, $j - $i - 1));
330 }
331
332 return null;
333 }
334
335 static function getQuad($color, $percent = false) {
336 $i = strpos($color, "(");
337 $j = strpos($color, ")");
338
339 // Bad color value
340 if ($i === false || $j === false) {
341 return null;
342 }
343
344 $quad = preg_split("/\\s*[,\\/]\\s*/", trim(substr($color, $i + 1, $j - $i - 1)));
345 if (!isset($quad[3])) {
346 $quad[3] = "1";
347 }
348
349 if (count($quad) != 3 && count($quad) != 4) {
350 return null;
351 }
352
353 foreach (array_keys($quad) as $c) {
354 $quad[$c] = trim($quad[$c]);
355
356 if ($percent) {
357 if ($quad[$c][strlen($quad[$c]) - 1] === "%") {
358 $quad[$c] = floatval($quad[$c]) / 100;
359 } else {
360 $quad[$c] = floatval($quad[$c]) / 255;
361 }
362 } else {
363 if ($quad[$c][strlen($quad[$c]) - 1] === "%") {
364 $quad[$c] = floatval($quad[$c]) * 2.55;
365 } else {
366 $quad[$c] = floatval($quad[$c]);
367 }
368 }
369 }
370
371 return $quad;
372 }
373
374 static function parseHexColor($hex)
375 {
376 $c = array(0.0, 0.0, 0.0, 1.0);
377
378 // #FFFFFF
379 if (isset($hex[6])) {
380 $c[0] = hexdec(substr($hex, 1, 2));
381 $c[1] = hexdec(substr($hex, 3, 2));
382 $c[2] = hexdec(substr($hex, 5, 2));
383
384 if (isset($hex[7])) {
385 $alpha = substr($hex, 7, 2);
386 if (ctype_xdigit($alpha)) {
387 $c[3] = round(hexdec($alpha)/255, 2);
388 }
389 }
390 } else {
391 $c[0] = hexdec($hex[1] . $hex[1]);
392 $c[1] = hexdec($hex[2] . $hex[2]);
393 $c[2] = hexdec($hex[3] . $hex[3]);
394
395 if (isset($hex[4])) {
396 if (ctype_xdigit($hex[4])) {
397 $c[3] = round(hexdec($hex[4] . $hex[4])/255, 2);
398 }
399 }
400 }
401
402 return $c;
403 }
404
405 /**
406 * Simple CSS parser
407 *
408 * @param $style
409 *
410 * @return array
411 */
412 static function parseCssStyle($style)
413 {
414 $matches = array();
415 preg_match_all("/([a-z-]+)\\s*:\\s*([^;$]+)/si", $style, $matches, PREG_SET_ORDER);
416
417 $styles = array();
418 foreach ($matches as $match) {
419 $styles[$match[1]] = $match[2];
420 }
421
422 return $styles;
423 }
424
425 static $colorNames = array(
426 'antiquewhite' => '#FAEBD7',
427 'aqua' => '#00FFFF',
428 'aquamarine' => '#7FFFD4',
429 'beige' => '#F5F5DC',
430 'black' => '#000000',
431 'blue' => '#0000FF',
432 'brown' => '#A52A2A',
433 'cadetblue' => '#5F9EA0',
434 'chocolate' => '#D2691E',
435 'cornflowerblue' => '#6495ED',
436 'crimson' => '#DC143C',
437 'darkblue' => '#00008B',
438 'darkgoldenrod' => '#B8860B',
439 'darkgreen' => '#006400',
440 'darkmagenta' => '#8B008B',
441 'darkorange' => '#FF8C00',
442 'darkred' => '#8B0000',
443 'darkseagreen' => '#8FBC8F',
444 'darkslategray' => '#2F4F4F',
445 'darkviolet' => '#9400D3',
446 'deepskyblue' => '#00BFFF',
447 'dodgerblue' => '#1E90FF',
448 'firebrick' => '#B22222',
449 'forestgreen' => '#228B22',
450 'fuchsia' => '#FF00FF',
451 'gainsboro' => '#DCDCDC',
452 'gold' => '#FFD700',
453 'gray' => '#808080',
454 'green' => '#008000',
455 'greenyellow' => '#ADFF2F',
456 'hotpink' => '#FF69B4',
457 'indigo' => '#4B0082',
458 'khaki' => '#F0E68C',
459 'lavenderblush' => '#FFF0F5',
460 'lemonchiffon' => '#FFFACD',
461 'lightcoral' => '#F08080',
462 'lightgoldenrodyellow' => '#FAFAD2',
463 'lightgreen' => '#90EE90',
464 'lightsalmon' => '#FFA07A',
465 'lightskyblue' => '#87CEFA',
466 'lightslategray' => '#778899',
467 'lightyellow' => '#FFFFE0',
468 'lime' => '#00FF00',
469 'limegreen' => '#32CD32',
470 'magenta' => '#FF00FF',
471 'maroon' => '#800000',
472 'mediumaquamarine' => '#66CDAA',
473 'mediumorchid' => '#BA55D3',
474 'mediumseagreen' => '#3CB371',
475 'mediumspringgreen' => '#00FA9A',
476 'mediumvioletred' => '#C71585',
477 'midnightblue' => '#191970',
478 'mintcream' => '#F5FFFA',
479 'moccasin' => '#FFE4B5',
480 'navy' => '#000080',
481 'olive' => '#808000',
482 'orange' => '#FFA500',
483 'orchid' => '#DA70D6',
484 'palegreen' => '#98FB98',
485 'palevioletred' => '#D87093',
486 'peachpuff' => '#FFDAB9',
487 'pink' => '#FFC0CB',
488 'powderblue' => '#B0E0E6',
489 'purple' => '#800080',
490 'red' => '#FF0000',
491 'royalblue' => '#4169E1',
492 'salmon' => '#FA8072',
493 'seagreen' => '#2E8B57',
494 'sienna' => '#A0522D',
495 'silver' => '#C0C0C0',
496 'skyblue' => '#87CEEB',
497 'slategray' => '#708090',
498 'springgreen' => '#00FF7F',
499 'steelblue' => '#4682B4',
500 'tan' => '#D2B48C',
501 'teal' => '#008080',
502 'thistle' => '#D8BFD8',
503 'turquoise' => '#40E0D0',
504 'violetred' => '#D02090',
505 'white' => '#FFFFFF',
506 'yellow' => '#FFFF00',
507 'aliceblue' => '#f0f8ff',
508 'azure' => '#f0ffff',
509 'bisque' => '#ffe4c4',
510 'blanchedalmond' => '#ffebcd',
511 'blueviolet' => '#8a2be2',
512 'burlywood' => '#deb887',
513 'chartreuse' => '#7fff00',
514 'coral' => '#ff7f50',
515 'cornsilk' => '#fff8dc',
516 'cyan' => '#00ffff',
517 'darkcyan' => '#008b8b',
518 'darkgray' => '#a9a9a9',
519 'darkgrey' => '#a9a9a9',
520 'darkkhaki' => '#bdb76b',
521 'darkolivegreen' => '#556b2f',
522 'darkorchid' => '#9932cc',
523 'darksalmon' => '#e9967a',
524 'darkslateblue' => '#483d8b',
525 'darkslategrey' => '#2f4f4f',
526 'darkturquoise' => '#00ced1',
527 'deeppink' => '#ff1493',
528 'dimgray' => '#696969',
529 'dimgrey' => '#696969',
530 'floralwhite' => '#fffaf0',
531 'ghostwhite' => '#f8f8ff',
532 'goldenrod' => '#daa520',
533 'grey' => '#808080',
534 'honeydew' => '#f0fff0',
535 'indianred' => '#cd5c5c',
536 'ivory' => '#fffff0',
537 'lavender' => '#e6e6fa',
538 'lawngreen' => '#7cfc00',
539 'lightblue' => '#add8e6',
540 'lightcyan' => '#e0ffff',
541 'lightgray' => '#d3d3d3',
542 'lightgrey' => '#d3d3d3',
543 'lightpink' => '#ffb6c1',
544 'lightseagreen' => '#20b2aa',
545 'lightslategrey' => '#778899',
546 'lightsteelblue' => '#b0c4de',
547 'linen' => '#faf0e6',
548 'mediumblue' => '#0000cd',
549 'mediumpurple' => '#9370db',
550 'mediumslateblue' => '#7b68ee',
551 'mediumturquoise' => '#48d1cc',
552 'mistyrose' => '#ffe4e1',
553 'navajowhite' => '#ffdead',
554 'oldlace' => '#fdf5e6',
555 'olivedrab' => '#6b8e23',
556 'orangered' => '#ff4500',
557 'palegoldenrod' => '#eee8aa',
558 'paleturquoise' => '#afeeee',
559 'papayawhip' => '#ffefd5',
560 'peru' => '#cd853f',
561 'plum' => '#dda0dd',
562 'rosybrown' => '#bc8f8f',
563 'saddlebrown' => '#8b4513',
564 'sandybrown' => '#f4a460',
565 'seashell' => '#fff5ee',
566 'slateblue' => '#6a5acd',
567 'slategrey' => '#708090',
568 'snow' => '#fffafa',
569 'tomato' => '#ff6347',
570 'violet' => '#ee82ee',
571 'wheat' => '#f5deb3',
572 'whitesmoke' => '#f5f5f5',
573 'yellowgreen' => '#9acd32',
574 );
575 }
576