aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/3rdparty/libraries/mpdf/classes/cssmgr.php
diff options
context:
space:
mode:
Diffstat (limited to 'inc/3rdparty/libraries/mpdf/classes/cssmgr.php')
-rw-r--r--inc/3rdparty/libraries/mpdf/classes/cssmgr.php1566
1 files changed, 1566 insertions, 0 deletions
diff --git a/inc/3rdparty/libraries/mpdf/classes/cssmgr.php b/inc/3rdparty/libraries/mpdf/classes/cssmgr.php
new file mode 100644
index 00000000..9bbbed9c
--- /dev/null
+++ b/inc/3rdparty/libraries/mpdf/classes/cssmgr.php
@@ -0,0 +1,1566 @@
1<?php
2
3class cssmgr {
4
5var $mpdf = null;
6
7var $tablecascadeCSS;
8var $listcascadeCSS;
9var $cascadeCSS;
10var $CSS;
11var $tbCSSlvl;
12var $listCSSlvl;
13
14
15function cssmgr(&$mpdf) {
16 $this->mpdf = $mpdf;
17 $this->tablecascadeCSS = array();
18 $this->listcascadeCSS = array();
19 $this->CSS=array();
20 $this->cascadeCSS = array();
21 $this->tbCSSlvl = 0;
22 $this->listCSSlvl = 0;
23}
24
25
26function ReadDefaultCSS($CSSstr) {
27 $CSS = array();
28 $CSSstr = preg_replace('|/\*.*?\*/|s',' ',$CSSstr);
29 $CSSstr = preg_replace('/[\s\n\r\t\f]/s',' ',$CSSstr);
30 $CSSstr = preg_replace('/(<\!\-\-|\-\->)/s',' ',$CSSstr);
31 if ($CSSstr ) {
32 preg_match_all('/(.*?)\{(.*?)\}/',$CSSstr,$styles);
33 for($i=0; $i < count($styles[1]) ; $i++) {
34 $stylestr= trim($styles[2][$i]);
35 $stylearr = explode(';',$stylestr);
36 foreach($stylearr AS $sta) {
37 if (trim($sta)) {
38 // Changed to allow style="background: url('http://www.bpm1.com/bg.jpg')"
39 list($property,$value) = explode(':',$sta,2);
40 $property = trim($property);
41 $value = preg_replace('/\s*!important/i','',$value);
42 $value = trim($value);
43 if ($property && ($value || $value==='0')) {
44 $classproperties[strtoupper($property)] = $value;
45 }
46 }
47 }
48 $classproperties = $this->fixCSS($classproperties);
49 $tagstr = strtoupper(trim($styles[1][$i]));
50 $tagarr = explode(',',$tagstr);
51 foreach($tagarr AS $tg) {
52 $tags = preg_split('/\s+/',trim($tg));
53 $level = count($tags);
54 if ($level == 1) { // e.g. p or .class or #id or p.class or p#id
55 $t = trim($tags[0]);
56 if ($t) {
57 $tag = '';
58 if (preg_match('/^('.$this->mpdf->allowedCSStags.')$/',$t)) { $tag= $t; }
59 if ($this->CSS[$tag] && $tag) { $CSS[$tag] = $this->array_merge_recursive_unique($CSS[$tag], $classproperties); }
60 else if ($tag) { $CSS[$tag] = $classproperties; }
61 }
62 }
63 }
64 $properties = array();
65 $values = array();
66 $classproperties = array();
67 }
68
69 } // end of if
70 return $CSS;
71}
72
73
74
75function ReadCSS($html) {
76 preg_match_all('/<style[^>]*media=["\']([^"\'>]*)["\'].*?<\/style>/is',$html,$m);
77 for($i=0; $i<count($m[0]); $i++) {
78 if ($this->mpdf->CSSselectMedia && !preg_match('/('.trim($this->mpdf->CSSselectMedia).'|all)/i',$m[1][$i])) {
79 $html = preg_replace('/'.preg_quote($m[0][$i],'/').'/','',$html);
80 }
81 }
82 preg_match_all('/<link[^>]*media=["\']([^"\'>]*)["\'].*?>/is',$html,$m);
83 for($i=0; $i<count($m[0]); $i++) {
84 if ($this->mpdf->CSSselectMedia && !preg_match('/('.trim($this->mpdf->CSSselectMedia).'|all)/i',$m[1][$i])) {
85 $html = preg_replace('/'.preg_quote($m[0][$i],'/').'/','',$html);
86 }
87 }
88
89 // mPDF 5.5.02
90 // Remove Comment tags <!-- ... --> inside CSS as <style> in HTML document
91 // Remove Comment tags /* ... */ inside CSS as <style> in HTML document
92 // But first, we replace upper and mixed case closing style tag with lower
93 // case so we can use str_replace later.
94 preg_replace('/<\/style>/i', '</style>', $html);
95 preg_match_all('/<style.*?>(.*?)<\/style>/si',$html,$m);
96 if (count($m[1])) {
97 for($i=0;$i<count($m[1]);$i++) {
98 // Remove comment tags
99 $sub = preg_replace('/(<\!\-\-|\-\->)/s',' ',$m[1][$i]);
100 $sub = '>'.preg_replace('|/\*.*?\*/|s',' ',$sub).'</style>';
101 $html = str_replace('>'.$m[1][$i].'</style>', $sub, $html);
102 }
103 }
104
105
106 $html = preg_replace('/<!--mpdf/i','',$html);
107 $html = preg_replace('/mpdf-->/i','',$html);
108 $html = preg_replace('/<\!\-\-.*?\-\->/s',' ',$html);
109
110 $match = 0; // no match for instance
111 $regexp = ''; // This helps debugging: showing what is the REAL string being processed
112 $CSSext = array();
113
114 //CSS inside external files
115 $regexp = '/<link[^>]*rel=["\']stylesheet["\'][^>]*href=["\']([^>"\']*)["\'].*?>/si';
116 $x = preg_match_all($regexp,$html,$cxt);
117 if ($x) {
118 $match += $x;
119 $CSSext = $cxt[1];
120 }
121
122 $regexp = '/<link[^>]*href=["\']([^>"\']*)["\'][^>]*?rel=["\']stylesheet["\'].*?>/si';
123 $x = preg_match_all($regexp,$html,$cxt);
124 if ($x) {
125 $match += $x;
126 $CSSext = array_merge($CSSext,$cxt[1]);
127 }
128
129 // look for @import stylesheets
130 //$regexp = '/@import url\([\'\"]{0,1}([^\)]*?\.css)[\'\"]{0,1}\)/si';
131 $regexp = '/@import url\([\'\"]{0,1}([^\)]*?\.css(\?\S+)?)[\'\"]{0,1}\)/si';
132 $x = preg_match_all($regexp,$html,$cxt);
133 if ($x) {
134 $match += $x;
135 $CSSext = array_merge($CSSext,$cxt[1]);
136 }
137
138 // look for @import without the url()
139 //$regexp = '/@import [\'\"]{0,1}([^;]*?\.css)[\'\"]{0,1}/si';
140 $regexp = '/@import [\'\"]{0,1}([^;]*?\.css(\?\S+)?)[\'\"]{0,1}/si';
141 $x = preg_match_all($regexp,$html,$cxt);
142 if ($x) {
143 $match += $x;
144 $CSSext = array_merge($CSSext,$cxt[1]);
145 }
146
147 $ind = 0;
148 $CSSstr = '';
149
150 if (!is_array($this->cascadeCSS)) $this->cascadeCSS = array();
151
152 while($match){
153 $path = $CSSext[$ind];
154 $this->mpdf->GetFullPath($path);
155 $CSSextblock = $this->mpdf->_get_file($path);
156 if ($CSSextblock) {
157 // look for embedded @import stylesheets in other stylesheets
158 // and fix url paths (including background-images) relative to stylesheet
159 //$regexpem = '/@import url\([\'\"]{0,1}(.*?\.css)[\'\"]{0,1}\)/si';
160 $regexpem = '/@import url\([\'\"]{0,1}(.*?\.css(\?\S+)?)[\'\"]{0,1}\)/si';
161 $xem = preg_match_all($regexpem,$CSSextblock,$cxtem);
162 $cssBasePath = preg_replace('/\/[^\/]*$/','',$path) . '/';
163 if ($xem) {
164 foreach($cxtem[1] AS $cxtembedded) {
165 // path is relative to original stlyesheet!!
166 $this->mpdf->GetFullPath($cxtembedded, $cssBasePath );
167 $match++;
168 $CSSext[] = $cxtembedded;
169 }
170 }
171 $regexpem = '/(background[^;]*url\s*\(\s*[\'\"]{0,1})([^\)\'\"]*)([\'\"]{0,1}\s*\))/si';
172 $xem = preg_match_all($regexpem,$CSSextblock,$cxtem);
173 if ($xem) {
174 for ($i=0;$i<count($cxtem[0]);$i++) {
175 // path is relative to original stlyesheet!!
176 $embedded = $cxtem[2][$i];
177 if (!preg_match('/^data:image/i', $embedded)) { // mPDF 5.5.13
178 $this->mpdf->GetFullPath($embedded, $cssBasePath );
179 $CSSextblock = preg_replace('/'.preg_quote($cxtem[0][$i],'/').'/', ($cxtem[1][$i].$embedded.$cxtem[3][$i]), $CSSextblock);
180 }
181 }
182 }
183 $CSSstr .= ' '.$CSSextblock;
184 }
185 $match--;
186 $ind++;
187 } //end of match
188
189 $match = 0; // reset value, if needed
190 // CSS as <style> in HTML document
191 $regexp = '/<style.*?>(.*?)<\/style>/si';
192 $match = preg_match_all($regexp,$html,$CSSblock);
193 if ($match) {
194 $tmpCSSstr = implode(' ',$CSSblock[1]);
195 $regexpem = '/(background[^;]*url\s*\(\s*[\'\"]{0,1})([^\)\'\"]*)([\'\"]{0,1}\s*\))/si';
196 $xem = preg_match_all($regexpem,$tmpCSSstr ,$cxtem);
197 if ($xem) {
198 for ($i=0;$i<count($cxtem[0]);$i++) {
199 $embedded = $cxtem[2][$i];
200 if (!preg_match('/^data:image/i', $embedded)) { // mPDF 5.5.13
201 $this->mpdf->GetFullPath($embedded);
202 $tmpCSSstr = preg_replace('/'.preg_quote($cxtem[0][$i],'/').'/', ($cxtem[1][$i].$embedded.$cxtem[3][$i]), $tmpCSSstr );
203 }
204 }
205 }
206 $CSSstr .= ' '.$tmpCSSstr;
207 }
208 // Remove comments
209 $CSSstr = preg_replace('|/\*.*?\*/|s',' ',$CSSstr);
210 $CSSstr = preg_replace('/[\s\n\r\t\f]/s',' ',$CSSstr);
211
212 if (preg_match('/@media/',$CSSstr)) {
213 preg_match_all('/@media(.*?)\{(([^\{\}]*\{[^\{\}]*\})+)\s*\}/is',$CSSstr,$m);
214 for($i=0; $i<count($m[0]); $i++) {
215 if ($this->mpdf->CSSselectMedia && !preg_match('/('.trim($this->mpdf->CSSselectMedia).'|all)/i',$m[1][$i])) {
216 $CSSstr = preg_replace('/'.preg_quote($m[0][$i],'/').'/','',$CSSstr);
217 }
218 else {
219 $CSSstr = preg_replace('/'.preg_quote($m[0][$i],'/').'/',' '.$m[2][$i].' ',$CSSstr);
220 }
221 }
222 }
223
224 // mPDF 5.5.13
225 // Replace any background: url(data:image... with temporary image file reference
226 preg_match_all("/(url\(data:image\/(jpeg|gif|png);base64,(.*)\))/si", $CSSstr, $idata);
227 if (count($idata[0])) {
228 for($i=0;$i<count($idata[0]);$i++) {
229 $file = _MPDF_TEMP_PATH.'_tempCSSidata'.RAND(1,10000).'_'.$i.'.'.$idata[2][$i];
230 //Save to local file
231 file_put_contents($file, base64_decode($idata[3][$i]));
232 // $this->mpdf->GetFullPath($file); // ? is this needed - NO mPDF 5.6.03
233 $CSSstr = str_replace($idata[0][$i], 'url("'.$file.'")', $CSSstr); // mPDF 5.5.17
234 }
235 }
236
237 $CSSstr = preg_replace('/(<\!\-\-|\-\->)/s',' ',$CSSstr);
238 if ($CSSstr ) {
239 preg_match_all('/(.*?)\{(.*?)\}/',$CSSstr,$styles);
240 for($i=0; $i < count($styles[1]) ; $i++) {
241 // SET array e.g. $classproperties['COLOR'] = '#ffffff';
242 $stylestr= trim($styles[2][$i]);
243 $stylearr = explode(';',$stylestr);
244 foreach($stylearr AS $sta) {
245 if (trim($sta)) {
246 // Changed to allow style="background: url('http://www.bpm1.com/bg.jpg')"
247 list($property,$value) = explode(':',$sta,2);
248 $property = trim($property);
249 $value = preg_replace('/\s*!important/i','',$value);
250 $value = trim($value);
251 if ($property && ($value || $value==='0')) {
252 // Ignores -webkit-gradient so doesn't override -moz-
253 if ((strtoupper($property)=='BACKGROUND-IMAGE' || strtoupper($property)=='BACKGROUND') && preg_match('/-webkit-gradient/i',$value)) {
254 continue;
255 }
256 $classproperties[strtoupper($property)] = $value;
257 }
258 }
259 }
260 $classproperties = $this->fixCSS($classproperties);
261 $tagstr = strtoupper(trim($styles[1][$i]));
262 $tagarr = explode(',',$tagstr);
263 $pageselectors = false; // used to turn on $this->mpdf->mirrorMargins
264 foreach($tagarr AS $tg) {
265 $tags = preg_split('/\s+/',trim($tg));
266 $level = count($tags);
267 $t = '';
268 $t2 = '';
269 $t3 = '';
270 if (trim($tags[0])=='@PAGE') {
271 if (isset($tags[0])) { $t = trim($tags[0]); }
272 if (isset($tags[1])) { $t2 = trim($tags[1]); }
273 if (isset($tags[2])) { $t3 = trim($tags[2]); }
274 $tag = '';
275 if ($level==1) { $tag = $t; }
276 else if ($level==2 && preg_match('/^[:](.*)$/',$t2,$m)) {
277 $tag = $t.'>>PSEUDO>>'.$m[1];
278 if ($m[1]=='LEFT' || $m[1]=='RIGHT') { $pageselectors = true; } // used to turn on $this->mpdf->mirrorMargins
279 }
280 else if ($level==2) { $tag = $t.'>>NAMED>>'.$t2; }
281 else if ($level==3 && preg_match('/^[:](.*)$/',$t3,$m)) {
282 $tag = $t.'>>NAMED>>'.$t2.'>>PSEUDO>>'.$m[1];
283 if ($m[1]=='LEFT' || $m[1]=='RIGHT') { $pageselectors = true; } // used to turn on $this->mpdf->mirrorMargins
284 }
285 if (isset($this->CSS[$tag]) && $tag) { $this->CSS[$tag] = $this->array_merge_recursive_unique($this->CSS[$tag], $classproperties); }
286 else if ($tag) { $this->CSS[$tag] = $classproperties; }
287 }
288
289 else if ($level == 1) { // e.g. p or .class or #id or p.class or p#id
290 if (isset($tags[0])) { $t = trim($tags[0]); }
291 if ($t) {
292 $tag = '';
293 if (preg_match('/^[.](.*)$/',$t,$m)) { $tag = 'CLASS>>'.$m[1]; }
294 else if (preg_match('/^[#](.*)$/',$t,$m)) { $tag = 'ID>>'.$m[1]; }
295 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[.](.*)$/',$t,$m)) { $tag = $m[1].'>>CLASS>>'.$m[2]; }
296 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')\s*:NTH-CHILD\((.*)\)$/',$t,$m)) { $tag = $m[1].'>>SELECTORNTHCHILD>>'.$m[2]; }
297 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[#](.*)$/',$t,$m)) { $tag = $m[1].'>>ID>>'.$m[2]; }
298 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')$/',$t)) { $tag= $t; }
299 if (isset($this->CSS[$tag]) && $tag) { $this->CSS[$tag] = $this->array_merge_recursive_unique($this->CSS[$tag], $classproperties); }
300 else if ($tag) { $this->CSS[$tag] = $classproperties; }
301 }
302 }
303 else {
304 $tmp = array();
305 for($n=0;$n<$level;$n++) {
306 if (isset($tags[$n])) { $t = trim($tags[$n]); }
307 else { $t = ''; }
308 if ($t) {
309 $tag = '';
310 if (preg_match('/^[.](.*)$/',$t,$m)) { $tag = 'CLASS>>'.$m[1]; }
311 else if (preg_match('/^[#](.*)$/',$t,$m)) { $tag = 'ID>>'.$m[1]; }
312 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[.](.*)$/',$t,$m)) { $tag = $m[1].'>>CLASS>>'.$m[2]; }
313 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')\s*:NTH-CHILD\((.*)\)$/',$t,$m)) { $tag = $m[1].'>>SELECTORNTHCHILD>>'.$m[2]; }
314 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')[#](.*)$/',$t,$m)) { $tag = $m[1].'>>ID>>'.$m[2]; }
315 else if (preg_match('/^('.$this->mpdf->allowedCSStags.')$/',$t)) { $tag= $t; }
316
317 if ($tag) $tmp[] = $tag;
318 else { break; }
319 }
320 }
321
322 if ($tag) {
323 $x = &$this->cascadeCSS;
324 foreach($tmp AS $tp) { $x = &$x[$tp]; }
325 $x = $this->array_merge_recursive_unique($x, $classproperties);
326 $x['depth'] = $level;
327 }
328 }
329 }
330 if ($pageselectors) { $this->mpdf->mirrorMargins = true; }
331 $properties = array();
332 $values = array();
333 $classproperties = array();
334 }
335 } // end of if
336 //Remove CSS (tags and content), if any
337 $regexp = '/<style.*?>(.*?)<\/style>/si'; // it can be <style> or <style type="txt/css">
338 $html = preg_replace($regexp,'',$html);
339//print_r($this->CSS); exit;
340//print_r($this->cascadeCSS); exit;
341 return $html;
342}
343
344
345
346function readInlineCSS($html) {
347 //Fix incomplete CSS code
348 $size = strlen($html)-1;
349 if (substr($html,$size,1) != ';') $html .= ';';
350 //Make CSS[Name-of-the-class] = array(key => value)
351 $regexp = '|\\s*?(\\S+?):(.+?);|i';
352 preg_match_all( $regexp, $html, $styleinfo);
353 $properties = $styleinfo[1];
354 $values = $styleinfo[2];
355 //Array-properties and Array-values must have the SAME SIZE!
356 $classproperties = array();
357 for($i = 0; $i < count($properties) ; $i++) {
358 // Ignores -webkit-gradient so doesn't override -moz-
359 if ((strtoupper($properties[$i])=='BACKGROUND-IMAGE' || strtoupper($properties[$i])=='BACKGROUND') && preg_match('/-webkit-gradient/i',$values[$i])) {
360 continue;
361 }
362 $classproperties[strtoupper($properties[$i])] = trim($values[$i]);
363 }
364 return $this->fixCSS($classproperties);
365}
366
367
368
369function _fix_borderStr($bd) {
370 preg_match_all("/\((.*?)\)/", $bd, $m);
371 if (count($m[1])) {
372 for($i=0;$i<count($m[1]);$i++) {
373 $sub = preg_replace("/ /", "", $m[1][$i]);
374 $bd = preg_replace('/'.preg_quote($m[1][$i], '/').'/si', $sub, $bd);
375 }
376 }
377
378 $prop = preg_split('/\s+/',trim($bd));
379 $w = 'medium';
380 $c = '#000000';
381 $s = 'none';
382
383 if ( count($prop) == 1 ) {
384 // solid
385 if (in_array($prop[0],$this->mpdf->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $s = $prop[0]; }
386 // #000000
387 else if (is_array($this->mpdf->ConvertColor($prop[0]))) { $c = $prop[0]; }
388 // 1px
389 else { $w = $prop[0]; }
390 }
391 else if (count($prop) == 2 ) {
392 // 1px solid
393 if (in_array($prop[1],$this->mpdf->borderstyles) || $prop[1] == 'none' || $prop[1] == 'hidden' ) { $w = $prop[0]; $s = $prop[1]; }
394 // solid #000000
395 else if (in_array($prop[0],$this->mpdf->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $s = $prop[0]; $c = $prop[1]; }
396 // 1px #000000
397 else { $w = $prop[0]; $c = $prop[1]; }
398 }
399 else if ( count($prop) == 3 ) {
400 // Change #000000 1px solid to 1px solid #000000 (proper)
401 if (substr($prop[0],0,1) == '#') { $c = $prop[0]; $w = $prop[1]; $s = $prop[2]; }
402 // Change solid #000000 1px to 1px solid #000000 (proper)
403 else if (substr($prop[0],1,1) == '#') { $s = $prop[0]; $c = $prop[1]; $w = $prop[2]; }
404 // Change solid 1px #000000 to 1px solid #000000 (proper)
405 else if (in_array($prop[0],$this->mpdf->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) {
406 $s = $prop[0]; $w = $prop[1]; $c = $prop[2];
407 }
408 else { $w = $prop[0]; $s = $prop[1]; $c = $prop[2]; }
409 }
410 else { return ''; }
411 $s = strtolower($s);
412 return $w.' '.$s.' '.$c;
413}
414
415
416
417function fixCSS($prop) {
418 if (!is_array($prop) || (count($prop)==0)) return array();
419 $newprop = array();
420 foreach($prop AS $k => $v) {
421 if ($k != 'BACKGROUND-IMAGE' && $k != 'BACKGROUND' && $k != 'ODD-HEADER-NAME' && $k != 'EVEN-HEADER-NAME' && $k != 'ODD-FOOTER-NAME' && $k != 'EVEN-FOOTER-NAME' && $k != 'HEADER' && $k != 'FOOTER') {
422 $v = strtolower($v);
423 }
424
425 if ($k == 'FONT') {
426 $s = trim($v);
427 preg_match_all('/\"(.*?)\"/',$s,$ff);
428 if (count($ff[1])) {
429 foreach($ff[1] AS $ffp) {
430 $w = preg_split('/\s+/',$ffp);
431 $s = preg_replace('/\"'.$ffp.'\"/',$w[0],$s);
432 }
433 }
434 preg_match_all('/\'(.*?)\'/',$s,$ff);
435 if (count($ff[1])) {
436 foreach($ff[1] AS $ffp) {
437 $w = preg_split('/\s+/',$ffp);
438 $s = preg_replace('/\''.$ffp.'\'/',$w[0],$s);
439 }
440 }
441 $s = preg_replace('/\s*,\s*/',',',$s);
442 $bits = preg_split('/\s+/',$s);
443 if (count($bits)>1) {
444 $k = 'FONT-FAMILY'; $v = $bits[(count($bits)-1)];
445 $fs = $bits[(count($bits)-2)];
446 if (preg_match('/(.*?)\/(.*)/',$fs, $fsp)) {
447 $newprop['FONT-SIZE'] = $fsp[1];
448 $newprop['LINE-HEIGHT'] = $fsp[2];
449 }
450 else { $newprop['FONT-SIZE'] = $fs; }
451 if (preg_match('/(italic|oblique)/i',$s)) { $newprop['FONT-STYLE'] = 'italic'; }
452 else { $newprop['FONT-STYLE'] = 'normal'; }
453 if (preg_match('/bold/i',$s)) { $newprop['FONT-WEIGHT'] = 'bold'; }
454 else { $newprop['FONT-WEIGHT'] = 'normal'; }
455 if (preg_match('/small-caps/i',$s)) { $newprop['TEXT-TRANSFORM'] = 'uppercase'; }
456 }
457 }
458 if ($k == 'FONT-FAMILY') {
459 $aux_fontlist = explode(",",$v);
460 $found = 0;
461 foreach($aux_fontlist AS $f) {
462 $fonttype = trim($f);
463 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
464 $fonttype = preg_replace('/ /','',$fonttype);
465 $v = strtolower(trim($fonttype));
466 if (isset($this->mpdf->fonttrans[$v]) && $this->mpdf->fonttrans[$v]) { $v = $this->mpdf->fonttrans[$v]; }
467 if ((!$this->mpdf->onlyCoreFonts && in_array($v,$this->mpdf->available_unifonts)) ||
468 in_array($v,array('ccourier','ctimes','chelvetica')) ||
469 ($this->mpdf->onlyCoreFonts && in_array($v,array('courier','times','helvetica','arial'))) ||
470 in_array($v, array('sjis','uhc','big5','gb'))) {
471 $newprop[$k] = $v;
472 $found = 1;
473 break;
474 }
475 }
476 if (!$found) {
477 foreach($aux_fontlist AS $f) {
478 $fonttype = trim($f);
479 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
480 $fonttype = preg_replace('/ /','',$fonttype);
481 $v = strtolower(trim($fonttype));
482 if (isset($this->mpdf->fonttrans[$v]) && $this->mpdf->fonttrans[$v]) { $v = $this->mpdf->fonttrans[$v]; }
483 if (in_array($v,$this->mpdf->sans_fonts) || in_array($v,$this->mpdf->serif_fonts) || in_array($v,$this->mpdf->mono_fonts) ) {
484 $newprop[$k] = $v;
485 break;
486 }
487 }
488 }
489 }
490 else if ($k == 'MARGIN') {
491 $tmp = $this->expand24($v);
492 $newprop['MARGIN-TOP'] = $tmp['T'];
493 $newprop['MARGIN-RIGHT'] = $tmp['R'];
494 $newprop['MARGIN-BOTTOM'] = $tmp['B'];
495 $newprop['MARGIN-LEFT'] = $tmp['L'];
496 }
497/*-- BORDER-RADIUS --*/
498 else if ($k == 'BORDER-RADIUS' || $k == 'BORDER-TOP-LEFT-RADIUS' || $k == 'BORDER-TOP-RIGHT-RADIUS' || $k == 'BORDER-BOTTOM-LEFT-RADIUS' || $k == 'BORDER-BOTTOM-RIGHT-RADIUS') {
499 $tmp = $this->border_radius_expand($v,$k);
500 if (isset($tmp['TL-H'])) $newprop['BORDER-TOP-LEFT-RADIUS-H'] = $tmp['TL-H'];
501 if (isset($tmp['TL-V'])) $newprop['BORDER-TOP-LEFT-RADIUS-V'] = $tmp['TL-V'];
502 if (isset($tmp['TR-H'])) $newprop['BORDER-TOP-RIGHT-RADIUS-H'] = $tmp['TR-H'];
503 if (isset($tmp['TR-V'])) $newprop['BORDER-TOP-RIGHT-RADIUS-V'] = $tmp['TR-V'];
504 if (isset($tmp['BL-H'])) $newprop['BORDER-BOTTOM-LEFT-RADIUS-H'] = $tmp['BL-H'];
505 if (isset($tmp['BL-V'])) $newprop['BORDER-BOTTOM-LEFT-RADIUS-V'] = $tmp['BL-V'];
506 if (isset($tmp['BR-H'])) $newprop['BORDER-BOTTOM-RIGHT-RADIUS-H'] = $tmp['BR-H'];
507 if (isset($tmp['BR-V'])) $newprop['BORDER-BOTTOM-RIGHT-RADIUS-V'] = $tmp['BR-V'];
508 }
509/*-- END BORDER-RADIUS --*/
510 else if ($k == 'PADDING') {
511 $tmp = $this->expand24($v);
512 $newprop['PADDING-TOP'] = $tmp['T'];
513 $newprop['PADDING-RIGHT'] = $tmp['R'];
514 $newprop['PADDING-BOTTOM'] = $tmp['B'];
515 $newprop['PADDING-LEFT'] = $tmp['L'];
516 }
517 else if ($k == 'BORDER') {
518 if ($v == '1') { $v = '1px solid #000000'; }
519 else { $v = $this->_fix_borderStr($v); }
520 $newprop['BORDER-TOP'] = $v;
521 $newprop['BORDER-RIGHT'] = $v;
522 $newprop['BORDER-BOTTOM'] = $v;
523 $newprop['BORDER-LEFT'] = $v;
524 }
525 else if ($k == 'BORDER-TOP') {
526 $newprop['BORDER-TOP'] = $this->_fix_borderStr($v);
527 }
528 else if ($k == 'BORDER-RIGHT') {
529 $newprop['BORDER-RIGHT'] = $this->_fix_borderStr($v);
530 }
531 else if ($k == 'BORDER-BOTTOM') {
532 $newprop['BORDER-BOTTOM'] = $this->_fix_borderStr($v);
533 }
534 else if ($k == 'BORDER-LEFT') {
535 $newprop['BORDER-LEFT'] = $this->_fix_borderStr($v);
536 }
537 else if ($k == 'BORDER-STYLE') {
538 $e = $this->expand24($v);
539 $newprop['BORDER-TOP-STYLE'] = $e['T'];
540 $newprop['BORDER-RIGHT-STYLE'] = $e['R'];
541 $newprop['BORDER-BOTTOM-STYLE'] = $e['B'];
542 $newprop['BORDER-LEFT-STYLE'] = $e['L'];
543 }
544 else if ($k == 'BORDER-WIDTH') {
545 $e = $this->expand24($v);
546 $newprop['BORDER-TOP-WIDTH'] = $e['T'];
547 $newprop['BORDER-RIGHT-WIDTH'] = $e['R'];
548 $newprop['BORDER-BOTTOM-WIDTH'] = $e['B'];
549 $newprop['BORDER-LEFT-WIDTH'] = $e['L'];
550 }
551 else if ($k == 'BORDER-COLOR') {
552 $e = $this->expand24($v);
553 $newprop['BORDER-TOP-COLOR'] = $e['T'];
554 $newprop['BORDER-RIGHT-COLOR'] = $e['R'];
555 $newprop['BORDER-BOTTOM-COLOR'] = $e['B'];
556 $newprop['BORDER-LEFT-COLOR'] = $e['L'];
557 }
558
559 else if ($k == 'BORDER-SPACING') {
560 $prop = preg_split('/\s+/',trim($v));
561 if (count($prop) == 1 ) {
562 $newprop['BORDER-SPACING-H'] = $prop[0];
563 $newprop['BORDER-SPACING-V'] = $prop[0];
564 }
565 else if (count($prop) == 2 ) {
566 $newprop['BORDER-SPACING-H'] = $prop[0];
567 $newprop['BORDER-SPACING-V'] = $prop[1];
568 }
569 }
570 else if ($k == 'TEXT-OUTLINE') { // mPDF 5.6.07
571 $prop = preg_split('/\s+/',trim($v));
572 if (trim(strtolower($v)) == 'none' ) {
573 $newprop['TEXT-OUTLINE'] = 'none';
574 }
575 else if (count($prop) == 2 ) {
576 $newprop['TEXT-OUTLINE-WIDTH'] = $prop[0];
577 $newprop['TEXT-OUTLINE-COLOR'] = $prop[1];
578 }
579 else if (count($prop) == 3 ) {
580 $newprop['TEXT-OUTLINE-WIDTH'] = $prop[0];
581 $newprop['TEXT-OUTLINE-COLOR'] = $prop[2];
582 }
583 }
584 else if ($k == 'SIZE') {
585 $prop = preg_split('/\s+/',trim($v));
586 if (preg_match('/(auto|portrait|landscape)/',$prop[0])) {
587 $newprop['SIZE'] = strtoupper($prop[0]);
588 }
589 else if (count($prop) == 1 ) {
590 $newprop['SIZE']['W'] = $this->mpdf->ConvertSize($prop[0]);
591 $newprop['SIZE']['H'] = $this->mpdf->ConvertSize($prop[0]);
592 }
593 else if (count($prop) == 2 ) {
594 $newprop['SIZE']['W'] = $this->mpdf->ConvertSize($prop[0]);
595 $newprop['SIZE']['H'] = $this->mpdf->ConvertSize($prop[1]);
596 }
597 }
598 else if ($k == 'SHEET-SIZE') {
599 $prop = preg_split('/\s+/',trim($v));
600 if (count($prop) == 2 ) {
601 $newprop['SHEET-SIZE'] = array($this->mpdf->ConvertSize($prop[0]), $this->mpdf->ConvertSize($prop[1]));
602 }
603 else {
604 if(preg_match('/([0-9a-zA-Z]*)-L/i',$v,$m)) { // e.g. A4-L = A$ landscape
605 $ft = $this->mpdf->_getPageFormat($m[1]);
606 $format = array($ft[1],$ft[0]);
607 }
608 else { $format = $this->mpdf->_getPageFormat($v); }
609 if ($format) { $newprop['SHEET-SIZE'] = array($format[0]/_MPDFK, $format[1]/_MPDFK); }
610 }
611 }
612 else if ($k == 'BACKGROUND') {
613 $bg = $this->parseCSSbackground($v);
614 if ($bg['c']) { $newprop['BACKGROUND-COLOR'] = $bg['c']; }
615 else { $newprop['BACKGROUND-COLOR'] = 'transparent'; }
616/*-- BACKGROUNDS --*/
617 if ($bg['i']) {
618 $newprop['BACKGROUND-IMAGE'] = $bg['i'];
619 if ($bg['r']) { $newprop['BACKGROUND-REPEAT'] = $bg['r']; }
620 if ($bg['p']) { $newprop['BACKGROUND-POSITION'] = $bg['p']; }
621 }
622 else { $newprop['BACKGROUND-IMAGE'] = ''; }
623/*-- END BACKGROUNDS --*/
624 }
625/*-- BACKGROUNDS --*/
626 else if ($k == 'BACKGROUND-IMAGE') {
627 if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient\(.*\)/i',$v,$m)) {
628 $newprop['BACKGROUND-IMAGE'] = $m[0];
629 continue;
630 }
631 if (preg_match('/url\([\'\"]{0,1}(.*?)[\'\"]{0,1}\)/i',$v,$m)) {
632 $newprop['BACKGROUND-IMAGE'] = $m[1];
633 }
634
635 else if (strtolower($v)=='none') { $newprop['BACKGROUND-IMAGE'] = ''; }
636
637 }
638 else if ($k == 'BACKGROUND-REPEAT') {
639 if (preg_match('/(repeat-x|repeat-y|no-repeat|repeat)/i',$v,$m)) {
640 $newprop['BACKGROUND-REPEAT'] = strtolower($m[1]);
641 }
642 }
643 else if ($k == 'BACKGROUND-POSITION') {
644 $s = $v;
645 $bits = preg_split('/\s+/',trim($s));
646 // These should be Position x1 or x2
647 if (count($bits)==1) {
648 if (preg_match('/bottom/',$bits[0])) { $bg['p'] = '50% 100%'; }
649 else if (preg_match('/top/',$bits[0])) { $bg['p'] = '50% 0%'; }
650 else { $bg['p'] = $bits[0] . ' 50%'; }
651 }
652 else if (count($bits)==2) {
653 // Can be either right center or center right
654 if (preg_match('/(top|bottom)/',$bits[0]) || preg_match('/(left|right)/',$bits[1])) {
655 $bg['p'] = $bits[1] . ' '.$bits[0];
656 }
657 else {
658 $bg['p'] = $bits[0] . ' '.$bits[1];
659 }
660 }
661 if ($bg['p']) {
662 $bg['p'] = preg_replace('/(left|top)/','0%',$bg['p']);
663 $bg['p'] = preg_replace('/(right|bottom)/','100%',$bg['p']);
664 $bg['p'] = preg_replace('/(center)/','50%',$bg['p']);
665 if (!preg_match('/[\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)* [\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)*/',$bg['p'])) {
666 $bg['p'] = false;
667 }
668 }
669 if ($bg['p']) { $newprop['BACKGROUND-POSITION'] = $bg['p']; }
670 }
671/*-- END BACKGROUNDS --*/
672 else if ($k == 'IMAGE-ORIENTATION') {
673 if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$v,$m)) {
674 $angle = $m[1] + 0;
675 if (strtolower($m[2])=='deg') { $angle = $angle; }
676 else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
677 else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
678 while($angle < 0) { $angle += 360; }
679 $angle = ($angle % 360);
680 $angle /= 90;
681 $angle = round($angle) * 90;
682 $newprop['IMAGE-ORIENTATION'] = $angle;
683 }
684 }
685 // mPDF 5.6.13
686 else if ($k == 'TEXT-ALIGN') {
687 if (preg_match('/["\'](.){1}["\']/i',$v,$m)) {
688 $d = array_search($m[1],$this->mpdf->decimal_align);
689 if ($d !== false) { $newprop['TEXT-ALIGN'] = $d; }
690 if (preg_match('/(center|left|right)/i',$v,$m)) { $newprop['TEXT-ALIGN'] .= strtoupper(substr($m[1],0,1)); }
691 else { $newprop['TEXT-ALIGN'] .= 'R'; } // default = R
692 }
693 else if (preg_match('/["\'](\\\[a-fA-F0-9]{1,6})["\']/i',$v,$m)) {
694 $utf8 = codeHex2utf(substr($m[1],1,6));
695 $d = array_search($utf8,$this->mpdf->decimal_align);
696 if ($d !== false) { $newprop['TEXT-ALIGN'] = $d; }
697 if (preg_match('/(center|left|right)/i',$v,$m)) { $newprop['TEXT-ALIGN'] .= strtoupper(substr($m[1],0,1)); }
698 else { $newprop['TEXT-ALIGN'] .= 'R'; } // default = R
699 }
700 else { $newprop[$k] = $v; }
701 }
702
703 else {
704 $newprop[$k] = $v;
705 }
706 }
707
708 return $newprop;
709}
710
711function setCSSboxshadow($v) {
712 $sh = array();
713 $c = preg_match_all('/(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl)\(.*?\)/',$v,$x); // mPDF 5.6.05
714 for($i=0; $i<$c; $i++) {
715 $col = preg_replace('/,/','*',$x[0][$i]);
716 $v = preg_replace('/'.preg_quote($x[0][$i],'/').'/',$col,$v);
717 }
718 $ss = explode(',',$v);
719 foreach ($ss AS $s) {
720 $new = array('inset'=>false, 'blur'=>0, 'spread'=>0);
721 if (preg_match('/inset/i',$s)) { $new['inset'] = true; $s = preg_replace('/\s*inset\s*/','',$s); }
722 $p = explode(' ',trim($s));
723 if (isset($p[0])) { $new['x'] = $this->mpdf->ConvertSize(trim($p[0]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
724 if (isset($p[1])) { $new['y'] = $this->mpdf->ConvertSize(trim($p[1]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
725 if (isset($p[2])) {
726 if (preg_match('/^\s*[\.\-0-9]/',$p[2])) {
727 $new['blur'] = $this->mpdf->ConvertSize(trim($p[2]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false);
728 }
729 else { $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[2])); }
730 if (isset($p[3])) {
731 if (preg_match('/^\s*[\.\-0-9]/',$p[3])) {
732 $new['spread'] = $this->mpdf->ConvertSize(trim($p[3]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false);
733 }
734 else { $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[3])); }
735 if (isset($p[4])) {
736 $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[4]));
737 }
738 }
739 }
740 if (!$new['col']) { $new['col'] = $this->mpdf->ConvertColor('#888888'); }
741 if (isset($new['y'])) { array_unshift($sh, $new); }
742 }
743 return $sh;
744}
745
746function setCSStextshadow($v) {
747 $sh = array();
748 $c = preg_match_all('/(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl)\(.*?\)/',$v,$x); // mPDF 5.6.05
749 for($i=0; $i<$c; $i++) {
750 $col = preg_replace('/,/','*',$x[0][$i]);
751 $v = preg_replace('/'.preg_quote($x[0][$i],'/').'/',$col,$v);
752 }
753 $ss = explode(',',$v);
754 foreach ($ss AS $s) {
755 $new = array('blur'=>0);
756 $p = explode(' ',trim($s));
757 if (isset($p[0])) { $new['x'] = $this->mpdf->ConvertSize(trim($p[0]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
758 if (isset($p[1])) { $new['y'] = $this->mpdf->ConvertSize(trim($p[1]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false); }
759 if (isset($p[2])) {
760 if (preg_match('/^\s*[\.\-0-9]/',$p[2])) {
761 $new['blur'] = $this->mpdf->ConvertSize(trim($p[2]),$this->mpdf->blk[$this->mpdf->blklvl-1]['inner_width'],$this->mpdf->FontSize,false);
762 }
763 else { $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[2])); }
764 if (isset($p[3])) {
765 $new['col'] = $this->mpdf->ConvertColor(preg_replace('/\*/',',',$p[3]));
766 }
767 }
768 if (!$new['col']) { $new['col'] = $this->mpdf->ConvertColor('#888888'); }
769 if (isset($new['y'])) { array_unshift($sh, $new); }
770 }
771 return $sh;
772}
773
774function parseCSSbackground($s) {
775 $bg = array('c'=>false, 'i'=>false, 'r'=>false, 'p'=>false, );
776/*-- BACKGROUNDS --*/
777 if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient\(.*\)/i',$s,$m)) {
778 $bg['i'] = $m[0];
779 }
780 else
781/*-- END BACKGROUNDS --*/
782 if (preg_match('/url\(/i',$s)) {
783 // If color, set and strip it off
784 // mPDF 5.6.05
785 if (preg_match('/^\s*(#[0-9a-fA-F]{3,6}|(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl|spot)\(.*?\)|[a-zA-Z]{3,})\s+(url\(.*)/i',$s,$m)) {
786 $bg['c'] = strtolower($m[1]);
787 $s = $m[3];
788 }
789/*-- BACKGROUNDS --*/
790 if (preg_match('/url\([\'\"]{0,1}(.*?)[\'\"]{0,1}\)\s*(.*)/i',$s,$m)) {
791 $bg['i'] = $m[1];
792 $s = strtolower($m[2]);
793 if (preg_match('/(repeat-x|repeat-y|no-repeat|repeat)/',$s,$m)) {
794 $bg['r'] = $m[1];
795 }
796 // Remove repeat, attachment (discarded) and also any inherit
797 $s = preg_replace('/(repeat-x|repeat-y|no-repeat|repeat|scroll|fixed|inherit)/','',$s);
798 $bits = preg_split('/\s+/',trim($s));
799 // These should be Position x1 or x2
800 if (count($bits)==1) {
801 if (preg_match('/bottom/',$bits[0])) { $bg['p'] = '50% 100%'; }
802 else if (preg_match('/top/',$bits[0])) { $bg['p'] = '50% 0%'; }
803 else { $bg['p'] = $bits[0] . ' 50%'; }
804 }
805 else if (count($bits)==2) {
806 // Can be either right center or center right
807 if (preg_match('/(top|bottom)/',$bits[0]) || preg_match('/(left|right)/',$bits[1])) {
808 $bg['p'] = $bits[1] . ' '.$bits[0];
809 }
810 else {
811 $bg['p'] = $bits[0] . ' '.$bits[1];
812 }
813 }
814 if ($bg['p']) {
815 $bg['p'] = preg_replace('/(left|top)/','0%',$bg['p']);
816 $bg['p'] = preg_replace('/(right|bottom)/','100%',$bg['p']);
817 $bg['p'] = preg_replace('/(center)/','50%',$bg['p']);
818 if (!preg_match('/[\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)* [\-]{0,1}\d+(in|cm|mm|pt|pc|em|ex|px|%)*/',$bg['p'])) {
819 $bg['p'] = false;
820 }
821 }
822 }
823/*-- END BACKGROUNDS --*/
824 }
825 else if (preg_match('/^\s*(#[0-9a-fA-F]{3,6}|(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl|spot)\(.*?\)|[a-zA-Z]{3,})/i',$s,$m)) { $bg['c'] = strtolower($m[1]); } // mPDF 5.6.05
826 return ($bg);
827}
828
829
830function expand24($mp) {
831 $prop = preg_split('/\s+/',trim($mp));
832 if (count($prop) == 1 ) {
833 return array('T' => $prop[0], 'R' => $prop[0], 'B' => $prop[0], 'L'=> $prop[0]);
834 }
835 if (count($prop) == 2 ) {
836 return array('T' => $prop[0], 'R' => $prop[1], 'B' => $prop[0], 'L'=> $prop[1]);
837 }
838
839 if (count($prop) == 3 ) {
840 return array('T' => $prop[0], 'R' => $prop[1], 'B' => $prop[2], 'L'=> $prop[1]);
841 }
842 if (count($prop) == 4 ) {
843 return array('T' => $prop[0], 'R' => $prop[1], 'B' => $prop[2], 'L'=> $prop[3]);
844 }
845 return array();
846}
847
848/*-- BORDER-RADIUS --*/
849function border_radius_expand($val,$k) {
850 $b = array();
851 if ($k == 'BORDER-RADIUS') {
852 $hv = explode('/',trim($val));
853 $prop = preg_split('/\s+/',trim($hv[0]));
854 if (count($prop)==1) {
855 $b['TL-H'] = $b['TR-H'] = $b['BR-H'] = $b['BL-H'] = $prop[0];
856 }
857 else if (count($prop)==2) {
858 $b['TL-H'] = $b['BR-H'] = $prop[0];
859 $b['TR-H'] = $b['BL-H'] = $prop[1];
860 }
861 else if (count($prop)==3) {
862 $b['TL-H'] = $prop[0];
863 $b['TR-H'] = $b['BL-H'] = $prop[1];
864 $b['BR-H'] = $prop[2];
865 }
866 else if (count($prop)==4) {
867 $b['TL-H'] = $prop[0];
868 $b['TR-H'] = $prop[1];
869 $b['BR-H'] = $prop[2];
870 $b['BL-H'] = $prop[3];
871 }
872 if (count($hv)==2) {
873 $prop = preg_split('/\s+/',trim($hv[1]));
874 if (count($prop)==1) {
875 $b['TL-V'] = $b['TR-V'] = $b['BR-V'] = $b['BL-V'] = $prop[0];
876 }
877 else if (count($prop)==2) {
878 $b['TL-V'] = $b['BR-V'] = $prop[0];
879 $b['TR-V'] = $b['BL-V'] = $prop[1];
880 }
881 else if (count($prop)==3) {
882 $b['TL-V'] = $prop[0];
883 $b['TR-V'] = $b['BL-V'] = $prop[1];
884 $b['BR-V'] = $prop[2];
885 }
886 else if (count($prop)==4) {
887 $b['TL-V'] = $prop[0];
888 $b['TR-V'] = $prop[1];
889 $b['BR-V'] = $prop[2];
890 $b['BL-V'] = $prop[3];
891 }
892 }
893 else {
894 $b['TL-V'] = $b['TL-H'];
895 $b['TR-V'] = $b['TR-H'];
896 $b['BL-V'] = $b['BL-H'];
897 $b['BR-V'] = $b['BR-H'];
898 }
899 return $b;
900 }
901
902 // Parse 2
903 $h = 0;
904 $v = 0;
905 $prop = preg_split('/\s+/',trim($val));
906 if (count($prop)==1) { $h = $v = $val; }
907 else { $h = $prop[0]; $v = $prop[1]; }
908 if ($h==0 || $v==0) { $h = $v = 0; }
909 if ($k == 'BORDER-TOP-LEFT-RADIUS') {
910 $b['TL-H'] = $h;
911 $b['TL-V'] = $v;
912 }
913 else if ($k == 'BORDER-TOP-RIGHT-RADIUS') {
914 $b['TR-H'] = $h;
915 $b['TR-V'] = $v;
916 }
917 else if ($k == 'BORDER-BOTTOM-LEFT-RADIUS') {
918 $b['BL-H'] = $h;
919 $b['BL-V'] = $v;
920 }
921 else if ($k == 'BORDER-BOTTOM-RIGHT-RADIUS') {
922 $b['BR-H'] = $h;
923 $b['BR-V'] = $v;
924 }
925 return $b;
926
927}
928/*-- END BORDER-RADIUS --*/
929
930function _mergeCSS($p, &$t) {
931 // Save Cascading CSS e.g. "div.topic p" at this block level
932 if (isset($p) && $p) {
933 if ($t) {
934 $t = $this->array_merge_recursive_unique($t, $p);
935 }
936 else { $t = $p; }
937 }
938}
939
940// for CSS handling
941function array_merge_recursive_unique($array1, $array2) {
942 $arrays = func_get_args();
943 $narrays = count($arrays);
944 $ret = $arrays[0];
945 for ($i = 1; $i < $narrays; $i ++) {
946 foreach ($arrays[$i] as $key => $value) {
947 if (((string) $key) === ((string) intval($key))) { // integer or string as integer key - append
948 $ret[] = $value;
949 }
950 else { // string key - merge
951 if (is_array($value) && isset($ret[$key])) {
952 $ret[$key] = $this->array_merge_recursive_unique($ret[$key], $value);
953 }
954 else {
955 $ret[$key] = $value;
956 }
957 }
958 }
959 }
960 return $ret;
961}
962
963
964
965function _mergeFullCSS($p, &$t, $tag, $classes, $id) {
966 $this->_mergeCSS($p[$tag], $t);
967 // STYLESHEET CLASS e.g. .smallone{} .redletter{}
968 foreach($classes AS $class) {
969 $this->_mergeCSS($p['CLASS>>'.$class], $t);
970 }
971 // STYLESHEET nth-child SELECTOR e.g. tr:nth-child(odd) td:nth-child(2n+1)
972 if ($tag=='TR' && isset($p) && $p) {
973 foreach($p AS $k=>$val) {
974 if (preg_match('/'.$tag.'>>SELECTORNTHCHILD>>(.*)/',$k, $m)) {
975 $select = false;
976 if ($tag=='TR') {
977 $row = $this->mpdf->row;
978 $thnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) : 0);
979 $tfnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) : 0);
980 if ($this->mpdf->tabletfoot) { $row -= $thnr; }
981 else if (!$this->mpdf->tablethead) { $row -= ($thnr + $tfnr); }
982 if ($m[1]=='ODD' && ($row % 2) == 0) { $select = true; }
983 else if ($m[1]=='EVEN' && ($row % 2) == 1) { $select = true; }
984 else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
985 if ((($row + 1) % $a[1]) == $a[2]) { $select = true; }
986 }
987 }
988 else if ($tag=='TD' || $tag=='TH') {
989 if ($m[1]=='ODD' && ($this->mpdf->col % 2) == 0) { $select = true; }
990 else if ($m[1]=='EVEN' && ($this->mpdf->col % 2) == 1) { $select = true; }
991 else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
992 if ((($this->mpdf->col + 1) % $a[1]) == $a[2]) { $select = true; }
993 }
994 }
995 if ($select) {
996 $this->_mergeCSS($p[$tag.'>>SELECTORNTHCHILD>>'.$m[1]], $t);
997 }
998 }
999 }
1000 }
1001 // STYLESHEET CLASS e.g. #smallone{} #redletter{}
1002 if (isset($id) && $id) {
1003 $this->_mergeCSS($p['ID>>'.$id], $t);
1004 }
1005 // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1006 foreach($classes AS $class) {
1007 $this->_mergeCSS($p[$tag.'>>CLASS>>'.$class], $t);
1008 }
1009 // STYLESHEET CLASS e.g. #smallone{} #redletter{}
1010 if (isset($id)) {
1011 $this->_mergeCSS($p[$tag.'>>ID>>'.$id], $t);
1012 }
1013}
1014
1015function setBorderDominance($prop, $val) {
1016 if (isset($prop['BORDER-LEFT']) && $prop['BORDER-LEFT']) { $this->cell_border_dominance_L = $val; }
1017 if (isset($prop['BORDER-RIGHT']) && $prop['BORDER-RIGHT']) { $this->cell_border_dominance_R = $val; }
1018 if (isset($prop['BORDER-TOP']) && $prop['BORDER-TOP']) { $this->cell_border_dominance_T = $val; }
1019 if (isset($prop['BORDER-BOTTOM']) && $prop['BORDER-BOTTOM']) { $this->cell_border_dominance_B = $val; }
1020}
1021
1022function _set_mergedCSS(&$m, &$p, $d=true, $bd=false) {
1023 if (isset($m)) {
1024 if ((isset($m['depth']) && $m['depth']>1) || $d==false) { // include check for 'depth'
1025 if ($bd) { $this->setBorderDominance($m, $bd); } // *TABLES*
1026 if (is_array($m)) {
1027 $p = array_merge($p,$m);
1028 $this->_mergeBorders($p,$m);
1029 }
1030 }
1031 }
1032}
1033
1034
1035function _mergeBorders(&$b, &$a) { // Merges $a['BORDER-TOP-STYLE'] to $b['BORDER-TOP'] etc.
1036 foreach(array('TOP','RIGHT','BOTTOM','LEFT') AS $side) {
1037 foreach(array('STYLE','WIDTH','COLOR') AS $el) {
1038 if (isset($a['BORDER-'.$side.'-'.$el])) { // e.g. $b['BORDER-TOP-STYLE']
1039 $s = trim($a['BORDER-'.$side.'-'.$el]);
1040 if (isset($b['BORDER-'.$side])) { // e.g. $b['BORDER-TOP']
1041 $p = trim($b['BORDER-'.$side]);
1042 }
1043 else { $p = ''; }
1044 if ($el=='STYLE') {
1045 if ($p) { $b['BORDER-'.$side] = preg_replace('/(\S+)\s+(\S+)\s+(\S+)/', '\\1 '.$s.' \\3', $p); }
1046 else { $b['BORDER-'.$side] = '0px '.$s.' #000000'; }
1047 }
1048 else if ($el=='WIDTH') {
1049 if ($p) { $b['BORDER-'.$side] = preg_replace('/(\S+)\s+(\S+)\s+(\S+)/', $s.' \\2 \\3', $p); }
1050 else { $b['BORDER-'.$side] = $s.' none #000000'; }
1051 }
1052 else if ($el=='COLOR') {
1053 if ($p) { $b['BORDER-'.$side] = preg_replace('/(\S+)\s+(\S+)\s+(\S+)/', '\\1 \\2 '.$s, $p); }
1054 else { $b['BORDER-'.$side] = '0px none '.$s; }
1055 }
1056 }
1057 }
1058 }
1059}
1060
1061
1062function MergeCSS($inherit,$tag,$attr) {
1063 $p = array();
1064 $zp = array();
1065
1066 $classes = array();
1067 if (isset($attr['CLASS'])) {
1068 $classes = preg_split('/\s+/',$attr['CLASS']);
1069 }
1070 if (!isset($attr['ID'])) { $attr['ID']=''; }
1071 //===============================================
1072/*-- TABLES --*/
1073 // Set Inherited properties
1074 if ($inherit == 'TOPTABLE') { // $tag = TABLE
1075 //===============================================
1076 // Save Cascading CSS e.g. "div.topic p" at this block level
1077
1078 if (isset($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'])) {
1079 $this->tablecascadeCSS[0] = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1080 }
1081 else {
1082 $this->tablecascadeCSS[0] = $this->cascadeCSS;
1083 }
1084 }
1085 //===============================================
1086 // Set Inherited properties
1087 if ($inherit == 'TOPTABLE' || $inherit == 'TABLE') {
1088 //Cascade everything from last level that is not an actual property, or defined by current tag/attributes
1089 if (isset($this->tablecascadeCSS[$this->tbCSSlvl-1]) && is_array($this->tablecascadeCSS[$this->tbCSSlvl-1])) {
1090 foreach($this->tablecascadeCSS[$this->tbCSSlvl-1] AS $k=>$v) {
1091 $this->tablecascadeCSS[$this->tbCSSlvl][$k] = $v;
1092 }
1093 }
1094 $this->_mergeFullCSS($this->cascadeCSS, $this->tablecascadeCSS[$this->tbCSSlvl], $tag, $classes, $attr['ID']);
1095 //===============================================
1096 // Cascading forward CSS e.g. "table.topic td" for this table in $this->tablecascadeCSS
1097 //===============================================
1098 // STYLESHEET TAG e.g. table
1099 $this->_mergeFullCSS($this->tablecascadeCSS[$this->tbCSSlvl-1], $this->tablecascadeCSS[$this->tbCSSlvl], $tag, $classes, $attr['ID']);
1100 //===============================================
1101 }
1102/*-- END TABLES --*/
1103 //===============================================
1104/*-- LISTS --*/
1105 // Set Inherited properties
1106 if ($inherit == 'TOPLIST') { // $tag = UL,OL
1107 //===============================================
1108 // Save Cascading CSS e.g. "div.topic p" at this block level
1109 if (isset($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'])) {
1110 $this->listcascadeCSS[0] = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1111 }
1112 else {
1113 $this->listcascadeCSS[0] = $this->cascadeCSS;
1114 }
1115 }
1116 //===============================================
1117 // Set Inherited properties
1118 if ($inherit == 'TOPLIST' || $inherit == 'LIST') {
1119 //Cascade everything from last level that is not an actual property, or defined by current tag/attributes
1120 if (isset($this->listcascadeCSS[$this->listCSSlvl-1]) && is_array($this->listcascadeCSS[$this->listCSSlvl-1])) {
1121 foreach($this->listcascadeCSS[$this->listCSSlvl-1] AS $k=>$v) {
1122 $this->listcascadeCSS[$this->listCSSlvl][$k] = $v;
1123 }
1124 }
1125 $this->_mergeFullCSS($this->cascadeCSS, $this->listcascadeCSS[$this->listCSSlvl], $tag, $classes, $attr['ID']);
1126 //===============================================
1127 // Cascading forward CSS e.g. "table.topic td" for this list in $this->listcascadeCSS
1128 //===============================================
1129 // STYLESHEET TAG e.g. table
1130 $this->_mergeFullCSS($this->listcascadeCSS[$this->listCSSlvl-1], $this->listcascadeCSS[$this->listCSSlvl], $tag, $classes, $attr['ID']);
1131 //===============================================
1132 }
1133/*-- END LISTS --*/
1134 //===============================================
1135 // Set Inherited properties
1136 if ($inherit == 'BLOCK') {
1137 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS']) && is_array($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'])) {
1138 foreach($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'] AS $k=>$v) {
1139 $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$k] = $v;
1140
1141 }
1142 }
1143
1144 //===============================================
1145 // Save Cascading CSS e.g. "div.topic p" at this block level
1146 $this->_mergeFullCSS($this->cascadeCSS, $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'], $tag, $classes, $attr['ID']);
1147 //===============================================
1148 // Cascading forward CSS
1149 //===============================================
1150 $this->_mergeFullCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'], $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'], $tag, $classes, $attr['ID']);
1151 //===============================================
1152 // Block properties
1153 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['margin_collapse']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['margin_collapse']) { $p['MARGIN-COLLAPSE'] = 'COLLAPSE'; } // custom tag, but follows CSS principle that border-collapse is inherited
1154 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['line_height']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['line_height']) { $p['LINE-HEIGHT'] = $this->mpdf->blk[$this->mpdf->blklvl-1]['line_height']; }
1155
1156 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['direction']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['direction']) { $p['DIRECTION'] = $this->mpdf->blk[$this->mpdf->blklvl-1]['direction']; }
1157
1158 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['align']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['align']) {
1159 if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'L') { $p['TEXT-ALIGN'] = 'left'; }
1160 else if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'J') { $p['TEXT-ALIGN'] = 'justify'; }
1161 else if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'R') { $p['TEXT-ALIGN'] = 'right'; }
1162 else if ($this->mpdf->blk[$this->mpdf->blklvl-1]['align'] == 'C') { $p['TEXT-ALIGN'] = 'center'; }
1163 }
1164 if ($this->mpdf->ColActive || $this->mpdf->keep_block_together) {
1165 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['bgcolor']) && $this->mpdf->blk[$this->mpdf->blklvl-1]['bgcolor']) { // Doesn't officially inherit, but default value is transparent (?=inherited)
1166 $cor = $this->mpdf->blk[$this->mpdf->blklvl-1]['bgcolorarray' ];
1167 $p['BACKGROUND-COLOR'] = $this->mpdf->_colAtoString($cor);
1168 }
1169 }
1170
1171 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent']) && ($this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent'] || $this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent']===0)) { $p['TEXT-INDENT'] = $this->mpdf->blk[$this->mpdf->blklvl-1]['text_indent']; }
1172 if (isset($this->mpdf->blk[$this->mpdf->blklvl-1]['InlineProperties'])) {
1173 $biilp = $this->mpdf->blk[$this->mpdf->blklvl-1]['InlineProperties'];
1174 }
1175 else { $biilp = null; }
1176 if (isset($biilp[ 'family' ]) && $biilp[ 'family' ]) { $p['FONT-FAMILY'] = $biilp[ 'family' ]; }
1177 if (isset($biilp[ 'I' ]) && $biilp[ 'I' ]) { $p['FONT-STYLE'] = 'italic'; }
1178 if (isset($biilp[ 'sizePt' ]) && $biilp[ 'sizePt' ]) { $p['FONT-SIZE'] = $biilp[ 'sizePt' ] . 'pt'; }
1179 if (isset($biilp[ 'B' ]) && $biilp[ 'B' ]) { $p['FONT-WEIGHT'] = 'bold'; }
1180 if (isset($biilp[ 'colorarray' ]) && $biilp[ 'colorarray' ]) {
1181 $cor = $biilp[ 'colorarray' ];
1182 $p['COLOR'] = $this->mpdf->_colAtoString($cor);
1183 }
1184 if (isset($biilp[ 'fontkerning' ])) {
1185 if ($biilp[ 'fontkerning' ]) { $p['FONT-KERNING'] = 'normal'; }
1186 else { $p['FONT-KERNING'] = 'none'; }
1187 }
1188 if (isset($biilp[ 'lSpacingCSS' ]) && $biilp[ 'lSpacingCSS' ]) { $p['LETTER-SPACING'] = $biilp[ 'lSpacingCSS' ]; }
1189 if (isset($biilp[ 'wSpacingCSS' ]) && $biilp[ 'wSpacingCSS' ]) { $p['WORD-SPACING'] = $biilp[ 'wSpacingCSS' ]; }
1190 if (isset($biilp[ 'toupper' ]) && $biilp[ 'toupper' ]) { $p['TEXT-TRANSFORM'] = 'uppercase'; }
1191 else if (isset($biilp[ 'tolower' ]) && $biilp[ 'tolower' ]) { $p['TEXT-TRANSFORM'] = 'lowercase'; }
1192 else if (isset($biilp[ 'capitalize' ]) && $biilp[ 'capitalize' ]) { $p['TEXT-TRANSFORM'] = 'capitalize'; }
1193 // CSS says text-decoration is not inherited, but IE7 does??
1194 if (isset($biilp[ 'underline' ]) && $biilp[ 'underline' ]) { $p['TEXT-DECORATION'] = 'underline'; }
1195 if (isset($biilp[ 'smCaps' ]) && $biilp[ 'smCaps' ]) { $p['FONT-VARIANT'] = 'small-caps'; }
1196
1197 }
1198 //===============================================
1199 //===============================================
1200/*-- LISTS --*/
1201 // Set Inherited properties
1202 if ($inherit == 'TOPLIST') {
1203 if ($this->listCSSlvl == 1) {
1204 $bilp = $this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties'];
1205 if (isset($bilp[ 'family' ]) && $bilp[ 'family' ]) { $p['FONT-FAMILY'] = $bilp[ 'family' ]; }
1206 if (isset($bilp[ 'I' ]) && $bilp[ 'I' ]) { $p['FONT-STYLE'] = 'italic'; }
1207 if (isset($bilp[ 'sizePt' ]) && $bilp[ 'sizePt' ]) { $p['FONT-SIZE'] = $bilp[ 'sizePt' ] . 'pt'; }
1208 if (isset($bilp[ 'B' ]) && $bilp[ 'B' ]) { $p['FONT-WEIGHT'] = 'bold'; }
1209 if (isset($bilp[ 'colorarray' ]) && $bilp[ 'colorarray' ]) {
1210 $cor = $bilp[ 'colorarray' ];
1211 $p['COLOR'] = $this->mpdf->_colAtoString($cor);
1212 }
1213 if (isset($bilp[ 'toupper' ]) && $bilp[ 'toupper' ]) { $p['TEXT-TRANSFORM'] = 'uppercase'; }
1214 else if (isset($bilp[ 'tolower' ]) && $bilp[ 'tolower' ]) { $p['TEXT-TRANSFORM'] = 'lowercase'; }
1215 else if (isset($bilp[ 'capitalize' ]) && $bilp[ 'capitalize' ]) { $p['TEXT-TRANSFORM'] = 'capitalize'; }
1216 if (isset($bilp[ 'fontkerning' ])) {
1217 if ($bilp[ 'fontkerning' ]) { $p['FONT-KERNING'] = 'normal'; }
1218 else { $p['FONT-KERNING'] = 'none'; }
1219 }
1220 if (isset($bilp[ 'lSpacingCSS' ]) && $bilp[ 'lSpacingCSS' ]) { $p['LETTER-SPACING'] = $bilp[ 'lSpacingCSS' ]; }
1221 if (isset($bilp[ 'wSpacingCSS' ]) && $bilp[ 'wSpacingCSS' ]) { $p['WORD-SPACING'] = $bilp[ 'wSpacingCSS' ]; }
1222 // CSS says text-decoration is not inherited, but IE7 does??
1223 if (isset($bilp[ 'underline' ]) && $bilp[ 'underline' ]) { $p['TEXT-DECORATION'] = 'underline'; }
1224 if (isset($bilp[ 'smCaps' ]) && $bilp[ 'smCaps' ]) { $p['FONT-VARIANT'] = 'small-caps'; }
1225 if ($tag=='LI') {
1226 // Note to self - this should never work, as TOPLIST is not called when LI (see code removed in v5.3)
1227 $this->mpdf->Error("If you see this message, please report this as a bug to the mPDF Forum.");
1228 }
1229 }
1230 }
1231/*-- END LISTS --*/
1232 //===============================================
1233 //===============================================
1234 // DEFAULT for this TAG set in DefaultCSS
1235 if (isset($this->mpdf->defaultCSS[$tag])) {
1236 $zp = $this->fixCSS($this->mpdf->defaultCSS[$tag]);
1237 if (is_array($zp)) { // Default overwrites Inherited
1238 $p = array_merge($p,$zp); // !! Note other way round !!
1239 $this->_mergeBorders($p,$zp);
1240 }
1241 }
1242 //===============================================
1243/*-- TABLES --*/
1244 // cellPadding overwrites TD/TH default but not specific CSS set on cell
1245 if (($tag=='TD' || $tag=='TH') && isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding']) && ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'] || $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding']===0)) {
1246 $p['PADDING-LEFT'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1247 $p['PADDING-RIGHT'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1248 $p['PADDING-TOP'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1249 $p['PADDING-BOTTOM'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cell_padding'];
1250 }
1251/*-- END TABLES --*/
1252 //===============================================
1253 // STYLESHEET TAG e.g. h1 p div table
1254 if (isset($this->CSS[$tag]) && $this->CSS[$tag]) {
1255 $zp = $this->CSS[$tag];
1256 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1257 if (is_array($zp)) {
1258 $p = array_merge($p,$zp);
1259 $this->_mergeBorders($p,$zp);
1260 }
1261 }
1262 //===============================================
1263 // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1264 foreach($classes AS $class) {
1265 $zp = array();
1266 if (isset($this->CSS['CLASS>>'.$class]) && $this->CSS['CLASS>>'.$class]) { $zp = $this->CSS['CLASS>>'.$class]; }
1267 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1268 if (is_array($zp)) {
1269 $p = array_merge($p,$zp);
1270 $this->_mergeBorders($p,$zp);
1271 }
1272 }
1273 //===============================================
1274/*-- TABLES --*/
1275 // STYLESHEET nth-child SELECTOR e.g. tr:nth-child(odd) td:nth-child(2n+1)
1276 if ($tag=='TR' || $tag=='TD' || $tag=='TH') {
1277 foreach($this->CSS AS $k=>$val) {
1278 if (preg_match('/'.$tag.'>>SELECTORNTHCHILD>>(.*)/',$k, $m)) {
1279 $select = false;
1280 if ($tag=='TR') {
1281 $row = $this->mpdf->row;
1282 $thnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) : 0);
1283 $tfnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) : 0);
1284 if ($this->mpdf->tabletfoot) { $row -= $thnr; }
1285 else if (!$this->mpdf->tablethead) { $row -= ($thnr + $tfnr); }
1286 if ($m[1]=='ODD' && ($row % 2) == 0) { $select = true; }
1287 else if ($m[1]=='EVEN' && ($row % 2) == 1) { $select = true; }
1288 else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1289 if ((($row + 1) % $a[1]) == $a[2]) { $select = true; }
1290 }
1291 }
1292 else if ($tag=='TD' || $tag=='TH') {
1293 if ($m[1]=='ODD' && ($this->mpdf->col % 2) == 0) { $select = true; }
1294 else if ($m[1]=='EVEN' && ($this->mpdf->col % 2) == 1) { $select = true; }
1295 else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1296 if ((($this->mpdf->col+1) % $a[1]) == $a[2]) { $select = true; }
1297 }
1298 }
1299 if ($select) {
1300 $zp = $this->CSS[$tag.'>>SELECTORNTHCHILD>>'.$m[1]];
1301 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); }
1302 if (is_array($zp)) {
1303 $p = array_merge($p,$zp);
1304 $this->_mergeBorders($p,$zp);
1305 }
1306 }
1307 }
1308 }
1309 }
1310/*-- END TABLES --*/
1311 //===============================================
1312 // STYLESHEET ID e.g. #smallone{} #redletter{}
1313 if (isset($attr['ID']) && isset($this->CSS['ID>>'.$attr['ID']]) && $this->CSS['ID>>'.$attr['ID']]) {
1314 $zp = $this->CSS['ID>>'.$attr['ID']];
1315 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1316 if (is_array($zp)) {
1317 $p = array_merge($p,$zp);
1318 $this->_mergeBorders($p,$zp);
1319 }
1320 }
1321 //===============================================
1322 // STYLESHEET CLASS e.g. p.smallone{} div.redletter{}
1323 foreach($classes AS $class) {
1324 $zp = array();
1325 if (isset($this->CSS[$tag.'>>CLASS>>'.$class]) && $this->CSS[$tag.'>>CLASS>>'.$class]) { $zp = $this->CSS[$tag.'>>CLASS>>'.$class]; }
1326 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1327 if (is_array($zp)) {
1328 $p = array_merge($p,$zp);
1329 $this->_mergeBorders($p,$zp);
1330 }
1331 }
1332 //===============================================
1333 // STYLESHEET CLASS e.g. p#smallone{} div#redletter{}
1334 if (isset($attr['ID']) && isset($this->CSS[$tag.'>>ID>>'.$attr['ID']]) && $this->CSS[$tag.'>>ID>>'.$attr['ID']]) {
1335 $zp = $this->CSS[$tag.'>>ID>>'.$attr['ID']];
1336 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1337 if (is_array($zp)) {
1338 $p = array_merge($p,$zp);
1339 $this->_mergeBorders($p,$zp);
1340 }
1341 }
1342 //===============================================
1343 // Cascaded e.g. div.class p only works for block level
1344 if ($inherit == 'BLOCK') {
1345 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'][$tag], $p);
1346 foreach($classes AS $class) {
1347 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS']['CLASS>>'.$class], $p);
1348 }
1349 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS']['ID>>'.$attr['ID']], $p);
1350 foreach($classes AS $class) {
1351 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'][$tag.'>>CLASS>>'.$class], $p);
1352 }
1353 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl-1]['cascadeCSS'][$tag.'>>ID>>'.$attr['ID']], $p);
1354 }
1355 else if ($inherit == 'INLINE') {
1356 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$tag], $p);
1357 foreach($classes AS $class) {
1358 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS']['CLASS>>'.$class], $p);
1359 }
1360 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS']['ID>>'.$attr['ID']], $p);
1361 foreach($classes AS $class) {
1362 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$tag.'>>CLASS>>'.$class], $p);
1363 }
1364 $this->_set_mergedCSS($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'][$tag.'>>ID>>'.$attr['ID']], $p);
1365 }
1366/*-- TABLES --*/
1367 else if ($inherit == 'TOPTABLE' || $inherit == 'TABLE') { // NB looks at $this->tablecascadeCSS-1 for cascading CSS
1368 // false, 9 = don't check for 'depth' and do set border dominance
1369 $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag], $p, false, 9);
1370 foreach($classes AS $class) {
1371 $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1]['CLASS>>'.$class], $p, false, 9);
1372 }
1373 // STYLESHEET nth-child SELECTOR e.g. tr:nth-child(odd) td:nth-child(2n+1)
1374 if ($tag=='TR' || $tag=='TD' || $tag=='TH') {
1375 foreach($this->tablecascadeCSS[$this->tbCSSlvl-1] AS $k=>$val) {
1376 if (preg_match('/'.$tag.'>>SELECTORNTHCHILD>>(.*)/',$k, $m)) {
1377 $select = false;
1378 if ($tag=='TR') {
1379 $row = $this->mpdf->row;
1380 $thnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead']) : 0);
1381 $tfnr = (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) ? count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) : 0);
1382 if ($this->mpdf->tabletfoot) { $row -= $thnr; }
1383 else if (!$this->mpdf->tablethead) { $row -= ($thnr + $tfnr); }
1384 if ($m[1]=='ODD' && ($row % 2) == 0) { $select = true; }
1385 else if ($m[1]=='EVEN' && ($row % 2) == 1) { $select = true; }
1386 else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1387 if ((($row + 1) % $a[1]) == $a[2]) { $select = true; }
1388 }
1389 }
1390 else if ($tag=='TD' || $tag=='TH') {
1391 if ($m[1]=='ODD' && ($this->mpdf->col % 2) == 0) { $select = true; }
1392 else if ($m[1]=='EVEN' && ($this->mpdf->col % 2) == 1) { $select = true; }
1393 else if (preg_match('/(\d+)N\+(\d+)/',$m[1],$a)) {
1394 if ((($this->mpdf->col + 1) % $a[1]) == $a[2]) { $select = true; }
1395 }
1396 }
1397 if ($select) {
1398 $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag.'>>SELECTORNTHCHILD>>'.$m[1]], $p, false, 9);
1399 }
1400 }
1401 }
1402 }
1403 $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1]['ID>>'.$attr['ID']], $p, false, 9);
1404 foreach($classes AS $class) {
1405 $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag.'>>CLASS>>'.$class], $p, false, 9);
1406 }
1407 $this->_set_mergedCSS($this->tablecascadeCSS[$this->tbCSSlvl-1][$tag.'>>ID>>'.$attr['ID']], $p, false, 9);
1408 }
1409/*-- END TABLES --*/
1410 //===============================================
1411/*-- LISTS --*/
1412 else if ($inherit == 'TOPLIST' || $inherit == 'LIST') { // NB looks at $this->listcascadeCSS-1 for cascading CSS
1413 // false = don't check for 'depth'
1414 $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1][$tag], $p, false);
1415 foreach($classes AS $class) {
1416 $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1]['CLASS>>'.$class], $p, false);
1417 }
1418 $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1]['ID>>'.$attr['ID']], $p, false);
1419 foreach($classes AS $class) {
1420 $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1][$tag.'>>CLASS>>'.$class], $p, false);
1421 }
1422 $this->_set_mergedCSS($this->listcascadeCSS[$this->listCSSlvl-1][$tag.'>>ID>>'.$attr['ID']], $p, false);
1423 }
1424/*-- END LISTS --*/
1425 //===============================================
1426 //===============================================
1427 // INLINE STYLE e.g. style="CSS:property"
1428 if (isset($attr['STYLE'])) {
1429 $zp = $this->readInlineCSS($attr['STYLE']);
1430 if ($tag=='TD' || $tag=='TH') { $this->setBorderDominance($zp, 9); } // *TABLES* // *TABLES-ADVANCED-BORDERS*
1431 if (is_array($zp)) {
1432 $p = array_merge($p,$zp);
1433 $this->_mergeBorders($p,$zp);
1434 }
1435 }
1436 //===============================================
1437 //===============================================
1438 // INLINE ATTRIBUTES e.g. .. ALIGN="CENTER">
1439 if (isset($attr['LANG']) and $attr['LANG']!='') {
1440 $p['LANG'] = $attr['LANG'];
1441 }
1442 if (isset($attr['COLOR']) and $attr['COLOR']!='') {
1443 $p['COLOR'] = $attr['COLOR'];
1444 }
1445 if ($tag != 'INPUT') {
1446 if (isset($attr['WIDTH']) and $attr['WIDTH']!='') {
1447 $p['WIDTH'] = $attr['WIDTH'];
1448 }
1449 if (isset($attr['HEIGHT']) and $attr['HEIGHT']!='') {
1450 $p['HEIGHT'] = $attr['HEIGHT'];
1451 }
1452 }
1453 if ($tag == 'FONT') {
1454 if (isset($attr['FACE'])) {
1455 $p['FONT-FAMILY'] = $attr['FACE'];
1456 }
1457 if (isset($attr['SIZE']) and $attr['SIZE']!='') {
1458 $s = '';
1459 if ($attr['SIZE'] === '+1') { $s = '120%'; }
1460 else if ($attr['SIZE'] === '-1') { $s = '86%'; }
1461 else if ($attr['SIZE'] === '1') { $s = 'XX-SMALL'; }
1462 else if ($attr['SIZE'] == '2') { $s = 'X-SMALL'; }
1463 else if ($attr['SIZE'] == '3') { $s = 'SMALL'; }
1464 else if ($attr['SIZE'] == '4') { $s = 'MEDIUM'; }
1465 else if ($attr['SIZE'] == '5') { $s = 'LARGE'; }
1466 else if ($attr['SIZE'] == '6') { $s = 'X-LARGE'; }
1467 else if ($attr['SIZE'] == '7') { $s = 'XX-LARGE'; }
1468 if ($s) $p['FONT-SIZE'] = $s;
1469 }
1470 }
1471 if (isset($attr['VALIGN']) and $attr['VALIGN']!='') {
1472 $p['VERTICAL-ALIGN'] = $attr['VALIGN'];
1473 }
1474 if (isset($attr['VSPACE']) and $attr['VSPACE']!='') {
1475 $p['MARGIN-TOP'] = $attr['VSPACE'];
1476 $p['MARGIN-BOTTOM'] = $attr['VSPACE'];
1477 }
1478 if (isset($attr['HSPACE']) and $attr['HSPACE']!='') {
1479 $p['MARGIN-LEFT'] = $attr['HSPACE'];
1480 $p['MARGIN-RIGHT'] = $attr['HSPACE'];
1481 }
1482 //===============================================
1483 return $p;
1484}
1485
1486function PreviewBlockCSS($tag,$attr) {
1487 // Looks ahead from current block level to a new level
1488 $p = array();
1489 $zp = array();
1490 $oldcascadeCSS = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1491 $classes = array();
1492 if (isset($attr['CLASS'])) { $classes = preg_split('/\s+/',$attr['CLASS']); }
1493 //===============================================
1494 // DEFAULT for this TAG set in DefaultCSS
1495 if (isset($this->mpdf->defaultCSS[$tag])) {
1496 $zp = $this->fixCSS($this->mpdf->defaultCSS[$tag]);
1497 if (is_array($zp)) { $p = array_merge($zp,$p); } // Inherited overwrites default
1498 }
1499 // STYLESHEET TAG e.g. h1 p div table
1500 if (isset($this->CSS[$tag])) {
1501 $zp = $this->CSS[$tag];
1502 if (is_array($zp)) { $p = array_merge($p,$zp); }
1503 }
1504 // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1505 foreach($classes AS $class) {
1506 $zp = array();
1507 if (isset($this->CSS['CLASS>>'.$class])) { $zp = $this->CSS['CLASS>>'.$class]; }
1508 if (is_array($zp)) { $p = array_merge($p,$zp); }
1509 }
1510 // STYLESHEET ID e.g. #smallone{} #redletter{}
1511 if (isset($attr['ID']) && isset($this->CSS['ID>>'.$attr['ID']])) {
1512 $zp = $this->CSS['ID>>'.$attr['ID']];
1513 if (is_array($zp)) { $p = array_merge($p,$zp); }
1514 }
1515 // STYLESHEET CLASS e.g. p.smallone{} div.redletter{}
1516 foreach($classes AS $class) {
1517 $zp = array();
1518 if (isset($this->CSS[$tag.'>>CLASS>>'.$class])) { $zp = $this->CSS[$tag.'>>CLASS>>'.$class]; }
1519 if (is_array($zp)) { $p = array_merge($p,$zp); }
1520 }
1521 // STYLESHEET CLASS e.g. p#smallone{} div#redletter{}
1522 if (isset($attr['ID']) && isset($this->CSS[$tag.'>>ID>>'.$attr['ID']])) {
1523 $zp = $this->CSS[$tag.'>>ID>>'.$attr['ID']];
1524 if (is_array($zp)) { $p = array_merge($p,$zp); }
1525 }
1526 //===============================================
1527 // STYLESHEET TAG e.g. div h1 div p
1528
1529 $this->_set_mergedCSS($oldcascadeCSS[$tag], $p);
1530 // STYLESHEET CLASS e.g. .smallone{} .redletter{}
1531 foreach($classes AS $class) {
1532
1533 $this->_set_mergedCSS($oldcascadeCSS['CLASS>>'.$class], $p);
1534 }
1535 // STYLESHEET CLASS e.g. #smallone{} #redletter{}
1536 if (isset($attr['ID'])) {
1537
1538 $this->_set_mergedCSS($oldcascadeCSS['ID>>'.$attr['ID']], $p);
1539 }
1540 // STYLESHEET CLASS e.g. div.smallone{} p.redletter{}
1541 foreach($classes AS $class) {
1542
1543 $this->_set_mergedCSS($oldcascadeCSS[$tag.'>>CLASS>>'.$class], $p);
1544 }
1545 // STYLESHEET CLASS e.g. div#smallone{} p#redletter{}
1546 if (isset($attr['ID'])) {
1547
1548 $this->_set_mergedCSS($oldcascadeCSS[$tag.'>>ID>>'.$attr['ID']], $p);
1549 }
1550 //===============================================
1551 // INLINE STYLE e.g. style="CSS:property"
1552 if (isset($attr['STYLE'])) {
1553 $zp = $this->readInlineCSS($attr['STYLE']);
1554 if (is_array($zp)) { $p = array_merge($p,$zp); }
1555 }
1556 //===============================================
1557 return $p;
1558}
1559
1560
1561
1562
1563
1564} // end of class
1565
1566?> \ No newline at end of file