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