cssmgr

The Gravity PDF cssmgr class.

Defined (1)

The class is defined in the following location(s).

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