source: trunk/client/inc/hpdf5/spipu/html2pdf/src/CssConverter.php@ 424

Last change on this file since 424 was 347, checked in by roby, 4 years ago

Aggiornamento per compatibilità con php7.4

File size: 10.7 KB
RevLine 
[347]1<?php
2/**
3 * Html2Pdf Library
4 *
5 * HTML => PDF converter
6 * distributed under the OSL-3.0 License
7 *
8 * @package Html2pdf
9 * @author Laurent MINGUET <webmaster@html2pdf.fr>
10 * @copyright 2017 Laurent MINGUET
11 */
12namespace Spipu\Html2Pdf;
13
14/**
15 * Class CssConverter
16 */
17class CssConverter
18{
19 private $htmlColor = array(); // list of the HTML colors
20
21 /**
22 * fontsize ratios
23 * @var float[]
24 */
25 private $fontSizeRatio = [
26 'smaller' => 0.8,
27 'larger' => 1.25,
28 'xx-small' => 0.512,
29 'x-small' => 0.64,
30 'small' => 0.8,
31 'medium' => 1.,
32 'large' => 1.25,
33 'x-large' => 1.5625,
34 'xx-large' => 1.953125,
35 ];
36
37 public function __construct()
38 {
39 $this->htmlColor = \TCPDF_COLORS::$webcolor;
40 }
41
42 /**
43 * convert a distance to mm
44 *
45 * @param string $css distance to convert
46 * @param float $old parent distance
47 *
48 * @return float
49 */
50 public function convertToMM($css, $old = 0.)
51 {
52 $css = trim($css);
53 if (preg_match('/^[0-9\.\-]+$/isU', $css)) {
54 $css.= 'px';
55 }
56 if (preg_match('/^[0-9\.\-]+px$/isU', $css)) {
57 $css = 25.4/96. * str_replace('px', '', $css);
58 } elseif (preg_match('/^[0-9\.\-]+pt$/isU', $css)) {
59 $css = 25.4/72. * str_replace('pt', '', $css);
60 } elseif (preg_match('/^[0-9\.\-]+in$/isU', $css)) {
61 $css = 25.4 * str_replace('in', '', $css);
62 } elseif (preg_match('/^[0-9\.\-]+mm$/isU', $css)) {
63 $css = 1.*str_replace('mm', '', $css);
64 } elseif (preg_match('/^[0-9\.\-]+%$/isU', $css)) {
65 $css = 1.*$old*str_replace('%', '', $css)/100.;
66 } else {
67 $css = null;
68 }
69
70 return $css;
71 }
72
73 /**
74 * @param string $css font size to convert
75 * @param float $parent parent font size
76 * @return float
77 */
78 public function convertFontSize($css, $parent = 0.)
79 {
80 $css = trim($css);
81 if (array_key_exists($css, $this->fontSizeRatio)) {
82 $css = ($this->fontSizeRatio[$css] * $parent).'mm';
83 }
84
85 return $this->convertToMM($css, $parent);
86 }
87
88 /**
89 * convert a css radius
90 *
91 * @access public
92 * @param string $css
93 * @return float $value
94 */
95 public function convertToRadius($css)
96 {
97 // explode the value
98 $css = explode(' ', $css);
99
100 foreach ($css as $k => $v) {
101 $v = trim($v);
102 if ($v !== '') {
103 $v = $this->convertToMM($v, 0);
104 if ($v !== null) {
105 $css[$k] = $v;
106 } else {
107 unset($css[$k]);
108 }
109 } else {
110 unset($css[$k]);
111 }
112 }
113
114 return array_values($css);
115 }
116
117 /**
118 * convert a css color to an RGB array
119 *
120 * @param string $css
121 * @param &boolean $res
122 *
123 * @return array (r, g, b)
124 */
125 public function convertToColor($css, &$res)
126 {
127 // prepare the value
128 $css = trim($css);
129 $res = true;
130
131 // if transparent => return null
132 if (strtolower($css) === 'transparent') {
133 return array(null, null, null);
134 }
135
136 // HTML color
137 if (isset($this->htmlColor[strtolower($css)])) {
138 $css = $this->htmlColor[strtolower($css)];
139 $r = floatVal(hexdec(substr($css, 0, 2)));
140 $g = floatVal(hexdec(substr($css, 2, 2)));
141 $b = floatVal(hexdec(substr($css, 4, 2)));
142 return array($r, $g, $b);
143 }
144
145 // like #FFFFFF
146 if (preg_match('/^#[0-9A-Fa-f]{6}$/isU', $css)) {
147 $r = floatVal(hexdec(substr($css, 1, 2)));
148 $g = floatVal(hexdec(substr($css, 3, 2)));
149 $b = floatVal(hexdec(substr($css, 5, 2)));
150 return array($r, $g, $b);
151 }
152
153 // like #FFF
154 if (preg_match('/^#[0-9A-F]{3}$/isU', $css)) {
155 $r = floatVal(hexdec(substr($css, 1, 1).substr($css, 1, 1)));
156 $g = floatVal(hexdec(substr($css, 2, 1).substr($css, 2, 1)));
157 $b = floatVal(hexdec(substr($css, 3, 1).substr($css, 3, 1)));
158 return array($r, $g, $b);
159 }
160
161 // like rgb(100, 100, 100)
162 $sub = '[\s]*([0-9%\.]+)[\s]*';
163 if (preg_match('/rgb\('.$sub.','.$sub.','.$sub.'\)/isU', $css, $match)) {
164 $r = $this->convertSubColor($match[1]);
165 $g = $this->convertSubColor($match[2]);
166 $b = $this->convertSubColor($match[3]);
167 return array($r * 255., $g * 255., $b * 255.);
168 }
169
170 // like cmyk(100, 100, 100, 100)
171 $sub = '[\s]*([0-9%\.]+)[\s]*';
172 if (preg_match('/cmyk\('.$sub.','.$sub.','.$sub.','.$sub.'\)/isU', $css, $match)) {
173 $c = $this->convertSubColor($match[1]);
174 $m = $this->convertSubColor($match[2]);
175 $y = $this->convertSubColor($match[3]);
176 $k = $this->convertSubColor($match[4]);
177 return array($c * 100., $m * 100., $y * 100., $k * 100.);
178 }
179
180 $res = false;
181 return array(0., 0., 0.);
182 }
183
184 /**
185 * color value to convert
186 *
187 * @access protected
188 * @param string $c
189 * @return float $c 0.->1.
190 */
191 protected function convertSubColor($c)
192 {
193 if (substr($c, -1) === '%') {
194 $c = floatVal(substr($c, 0, -1)) / 100.;
195 } else {
196 $c = floatVal($c);
197 if ($c > 1) {
198 $c = $c / 255.;
199 }
200 }
201
202 return $c;
203 }
204
205
206 /**
207 * Analyse a background
208 *
209 * @param string $css css background properties
210 * @param &array $value parsed values (by reference, because, ther is a legacy of the parent CSS properties)
211 *
212 * @return void
213 */
214 public function convertBackground($css, &$value)
215 {
216 // is there a image ?
217 $text = '/url\(([^)]*)\)/isU';
218 if (preg_match($text, $css, $match)) {
219 // get the image
220 $value['image'] = $this->convertBackgroundImage($match[0]);
221
222 // remove if from the css properties
223 $css = preg_replace($text, '', $css);
224 $css = preg_replace('/[\s]+/', ' ', $css);
225 }
226
227 // protect some spaces
228 $css = preg_replace('/,[\s]+/', ',', $css);
229
230 // explode the values
231 $css = explode(' ', $css);
232
233 // background position to parse
234 $pos = '';
235
236 // foreach value
237 foreach ($css as $val) {
238 // try to parse the value as a color
239 $ok = false;
240 $color = $this->convertToColor($val, $ok);
241
242 // if ok => it is a color
243 if ($ok) {
244 $value['color'] = $color;
245 // else if transparent => no coloàr
246 } elseif ($val === 'transparent') {
247 $value['color'] = null;
248 // else
249 } else {
250 // try to parse the value as a repeat
251 $repeat = $this->convertBackgroundRepeat($val);
252
253 // if ok => it is repeat
254 if ($repeat) {
255 $value['repeat'] = $repeat;
256 // else => it could only be a position
257 } else {
258 $pos.= ($pos ? ' ' : '').$val;
259 }
260 }
261 }
262
263 // if we have a position to parse
264 if ($pos) {
265 // try to read it
266 $pos = $this->convertBackgroundPosition($pos, $ok);
267 if ($ok) {
268 $value['position'] = $pos;
269 }
270 }
271 }
272
273 /**
274 * Parse a background color
275 *
276 * @param string $css
277 *
278 * @return string|null $value
279 */
280 public function convertBackgroundColor($css)
281 {
282 $res = null;
283 if ($css === 'transparent') {
284 return null;
285 }
286
287 return $this->convertToColor($css, $res);
288 }
289
290 /**
291 * Parse a background image
292 *
293 * @param string $css
294 *
295 * @return string|null $value
296 */
297 public function convertBackgroundImage($css)
298 {
299 if ($css === 'none') {
300 return null;
301 }
302
303 if (preg_match('/^url\(([^)]*)\)$/isU', $css, $match)) {
304 return $match[1];
305 }
306
307 return null;
308 }
309
310 /**
311 * Parse a background position
312 *
313 * @param string $css
314 * @param boolean &$res flag if convert is ok or not
315 *
316 * @return array (x, y)
317 */
318 public function convertBackgroundPosition($css, &$res)
319 {
320 // init the res
321 $res = false;
322
323 // explode the value
324 $css = explode(' ', $css);
325
326 // we must have 2 values. if 0 or >2 : error. if 1 => put center for 2
327 if (count($css)<2) {
328 if (!$css[0]) {
329 return null;
330 }
331 $css[1] = 'center';
332 }
333 if (count($css)>2) {
334 return null;
335 }
336
337 // prepare the values
338 $x = 0;
339 $y = 0;
340 $res = true;
341
342 // convert the first value
343 if ($css[0] === 'left') {
344 $x = '0%';
345 } elseif ($css[0] === 'center') {
346 $x = '50%';
347 } elseif ($css[0] === 'right') {
348 $x = '100%';
349 } elseif ($css[0] === 'top') {
350 $y = '0%';
351 } elseif ($css[0] === 'bottom') {
352 $y = '100%';
353 } elseif (preg_match('/^[-]?[0-9\.]+%$/isU', $css[0])) {
354 $x = $css[0];
355 } elseif ($this->convertToMM($css[0])) {
356 $x = $this->convertToMM($css[0]);
357 } else {
358 $res = false;
359 }
360
361 // convert the second value
362 if ($css[1] === 'left') {
363 $x = '0%';
364 } elseif ($css[1] === 'right') {
365 $x = '100%';
366 } elseif ($css[1] === 'top') {
367 $y = '0%';
368 } elseif ($css[1] === 'center') {
369 $y = '50%';
370 } elseif ($css[1] === 'bottom') {
371 $y = '100%';
372 } elseif (preg_match('/^[-]?[0-9\.]+%$/isU', $css[1])) {
373 $y = $css[1];
374 } elseif ($this->convertToMM($css[1])) {
375 $y = $this->convertToMM($css[1]);
376 } else {
377 $res = false;
378 }
379
380 // return the values
381 return array($x, $y);
382 }
383
384 /**
385 * Parse a background repeat
386 *
387 * @param string $css
388 *
389 * @return array|null background repeat as array
390 */
391 public function convertBackgroundRepeat($css)
392 {
393 switch ($css) {
394 case 'repeat':
395 return array(true, true);
396 case 'repeat-x':
397 return array(true, false);
398 case 'repeat-y':
399 return array(false, true);
400 case 'no-repeat':
401 return array(false, false);
402 }
403 return null;
404 }
405}
Note: See TracBrowser for help on using the repository browser.