Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

AOS_PDF_Templates/PDF_Lib/classes/cssmgr.php (13 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
class cssmgr {
4
5
var $mpdf = null;
6
7
var $tablecascadeCSS;
8
var $listcascadeCSS;
9
var $cascadeCSS;
10
var $CSS;
11
var $tbCSSlvl;
12
var $listCSSlvl;
13
14
15
function 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
26
function 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++)  {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
75
function ReadCSS($html) {
76
	preg_match_all('/<style[^>]*media=["\']([^"\'>]*)["\'].*?<\/style>/is',$html,$m);
77
	for($i=0; $i<count($m[0]); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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++)  {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
346
function 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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
369
function _fix_borderStr($bd) {
370
	preg_match_all("/\((.*?)\)/", $bd, $m);
371
	if (count($m[1])) { 
372
		for($i=0;$i<count($m[1]);$i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
417
function 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; }
0 ignored issues
show
Why assign $angle to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
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
711
function 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
746
function 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
774
function 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
830
function 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 --*/
849
function 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
930
function _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
941
function 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
965
function _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
1015
function 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
1022
function _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'
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
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
1035
function _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
1062
function 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
1486
function 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
?>