PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / 1.7.8
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin v1.7.8
trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 All 71 releases
pdf-print / mpdf / classes / cssmgr.php

cssmgr.php in PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin 1.7.8, at mpdf/classes/cssmgr.php

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