PageRenderTime 64ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/common/libraries/plugin/html2pdf/styleHTML.class.php

https://bitbucket.org/chamilo/chamilo/
PHP | 1712 lines | 1353 code | 193 blank | 166 comment | 257 complexity | e36a905856b230ac16c4d328165983e0 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Logiciel : HTML2PDF - classe styleHTML
  4. *
  5. * Convertisseur HTML => PDF, utilise TCPDF
  6. * Distribué sous la licence LGPL.
  7. *
  8. * @author Laurent MINGUET <webmaster@html2pdf.fr>
  9. * @version 4.00
  10. */
  11. class styleHTML
  12. {
  13. protected $pdf = null; // référence au PDF parent
  14. protected $htmlColor = array(); // liste des couleurs HTML
  15. protected $onlyLeft = false; // indique si on est dans un sous HTML et qu'on bloque ? gauche
  16. protected $defaultFont = null; // fonte par défaut si la fonte demandée n'existe pas
  17. public $value = array(); // valeurs actuelles
  18. public $css = array(); // tableau des CSS
  19. public $css_keys = array(); // tableau des clefs CSS, pour l'ordre d'execution
  20. public $table = array(); // tableau d'empilement pour historisation des niveaux
  21. /**
  22. * Constructeur
  23. *
  24. * @param &pdf référence ? l'objet HTML2PDF parent
  25. * @return null
  26. */
  27. public function __construct(&$pdf)
  28. {
  29. $this->init(); // initialisation
  30. $this->setPdfParent($pdf);
  31. }
  32. public function setPdfParent(&$pdf)
  33. {
  34. $this->pdf = &$pdf;
  35. }
  36. public function setOnlyLeft()
  37. {
  38. $this->value['text-align'] = 'left';
  39. $this->onlyLeft = true;
  40. }
  41. public function getOldValues()
  42. {
  43. return isset($this->table[count($this->table)-1]) ? $this->table[count($this->table)-1] : $this->value;
  44. }
  45. /**
  46. * définit la fonte par défaut si aucun fonte n'est spécifiée, ou si la fonte demandée n'existe pas
  47. *
  48. * @param string nom de la fonte par defaut. si null : Arial pour fonte non spécifiée, et erreur pour fonte non existante
  49. * @return string nom de l'ancienne fonte par defaut
  50. */
  51. public function setDefaultFont($default = null)
  52. {
  53. $old = $this->defaultFont;
  54. $this->defaultFont = $default;
  55. if ($default) $this->value['font-family'] = $default;
  56. return $old;
  57. }
  58. /**
  59. * Initialisation du style
  60. *
  61. * @return null
  62. */
  63. protected function init()
  64. {
  65. $color = array();
  66. $color['AliceBlue'] = '#F0F8FF';
  67. $color['AntiqueWhite'] = '#FAEBD7';
  68. $color['Aqua'] = '#00FFFF';
  69. $color['Aquamarine'] = '#7FFFD4';
  70. $color['Azure'] = '#F0FFFF';
  71. $color['Beige'] = '#F5F5DC';
  72. $color['Bisque'] = '#FFE4C4';
  73. $color['Black'] = '#000000';
  74. $color['BlanchedAlmond'] = '#FFEBCD';
  75. $color['Blue'] = '#0000FF';
  76. $color['BlueViolet'] = '#8A2BE2';
  77. $color['Brown'] = '#A52A2A';
  78. $color['BurlyWood'] = '#DEB887';
  79. $color['CadetBlue'] = '#5F9EA0';
  80. $color['Chartreuse'] = '#7FFF00';
  81. $color['Chocolate'] = '#D2691E';
  82. $color['Coral'] = '#FF7F50';
  83. $color['CornflowerBlue'] = '#6495ED';
  84. $color['Cornsilk'] = '#FFF8DC';
  85. $color['Crimson'] = '#DC143C';
  86. $color['Cyan'] = '#00FFFF';
  87. $color['DarkBlue'] = '#00008B';
  88. $color['DarkCyan'] = '#008B8B';
  89. $color['DarkGoldenRod'] = '#B8860B';
  90. $color['DarkGray'] = '#A9A9A9';
  91. $color['DarkGrey'] = '#A9A9A9';
  92. $color['DarkGreen'] = '#006400';
  93. $color['DarkKhaki'] = '#BDB76B';
  94. $color['DarkMagenta'] = '#8B008B';
  95. $color['DarkOliveGreen'] = '#556B2F';
  96. $color['Darkorange'] = '#FF8C00';
  97. $color['DarkOrchid'] = '#9932CC';
  98. $color['DarkRed'] = '#8B0000';
  99. $color['DarkSalmon'] = '#E9967A';
  100. $color['DarkSeaGreen'] = '#8FBC8F';
  101. $color['DarkSlateBlue'] = '#483D8B';
  102. $color['DarkSlateGray'] = '#2F4F4F';
  103. $color['DarkSlateGrey'] = '#2F4F4F';
  104. $color['DarkTurquoise'] = '#00CED1';
  105. $color['DarkViolet'] = '#9400D3';
  106. $color['DeepPink'] = '#FF1493';
  107. $color['DeepSkyBlue'] = '#00BFFF';
  108. $color['DimGray'] = '#696969';
  109. $color['DimGrey'] = '#696969';
  110. $color['DodgerBlue'] = '#1E90FF';
  111. $color['FireBrick'] = '#B22222';
  112. $color['FloralWhite'] = '#FFFAF0';
  113. $color['ForestGreen'] = '#228B22';
  114. $color['Fuchsia'] = '#FF00FF';
  115. $color['Gainsboro'] = '#DCDCDC';
  116. $color['GhostWhite'] = '#F8F8FF';
  117. $color['Gold'] = '#FFD700';
  118. $color['GoldenRod'] = '#DAA520';
  119. $color['Gray'] = '#808080';
  120. $color['Grey'] = '#808080';
  121. $color['Green'] = '#008000';
  122. $color['GreenYellow'] = '#ADFF2F';
  123. $color['HoneyDew'] = '#F0FFF0';
  124. $color['HotPink'] = '#FF69B4';
  125. $color['IndianRed'] = '#CD5C5C';
  126. $color['Indigo'] = '#4B0082';
  127. $color['Ivory'] = '#FFFFF0';
  128. $color['Khaki'] = '#F0E68C';
  129. $color['Lavender'] = '#E6E6FA';
  130. $color['LavenderBlush'] = '#FFF0F5';
  131. $color['LawnGreen'] = '#7CFC00';
  132. $color['LemonChiffon'] = '#FFFACD';
  133. $color['LightBlue'] = '#ADD8E6';
  134. $color['LightCoral'] = '#F08080';
  135. $color['LightCyan'] = '#E0FFFF';
  136. $color['LightGoldenRodYellow'] = '#FAFAD2';
  137. $color['LightGray'] = '#D3D3D3';
  138. $color['LightGrey'] = '#D3D3D3';
  139. $color['LightGreen'] = '#90EE90';
  140. $color['LightPink'] = '#FFB6C1';
  141. $color['LightSalmon'] = '#FFA07A';
  142. $color['LightSeaGreen'] = '#20B2AA';
  143. $color['LightSkyBlue'] = '#87CEFA';
  144. $color['LightSlateGray'] = '#778899';
  145. $color['LightSlateGrey'] = '#778899';
  146. $color['LightSteelBlue'] = '#B0C4DE';
  147. $color['LightYellow'] = '#FFFFE0';
  148. $color['Lime'] = '#00FF00';
  149. $color['LimeGreen'] = '#32CD32';
  150. $color['Linen'] = '#FAF0E6';
  151. $color['Magenta'] = '#FF00FF';
  152. $color['Maroon'] = '#800000';
  153. $color['MediumAquaMarine'] = '#66CDAA';
  154. $color['MediumBlue'] = '#0000CD';
  155. $color['MediumOrchid'] = '#BA55D3';
  156. $color['MediumPurple'] = '#9370D8';
  157. $color['MediumSeaGreen'] = '#3CB371';
  158. $color['MediumSlateBlue'] = '#7B68EE';
  159. $color['MediumSpringGreen'] = '#00FA9A';
  160. $color['MediumTurquoise'] = '#48D1CC';
  161. $color['MediumVioletRed'] = '#C71585';
  162. $color['MidnightBlue'] = '#191970';
  163. $color['MintCream'] = '#F5FFFA';
  164. $color['MistyRose'] = '#FFE4E1';
  165. $color['Moccasin'] = '#FFE4B5';
  166. $color['NavajoWhite'] = '#FFDEAD';
  167. $color['Navy'] = '#000080';
  168. $color['OldLace'] = '#FDF5E6';
  169. $color['Olive'] = '#808000';
  170. $color['OliveDrab'] = '#6B8E23';
  171. $color['Orange'] = '#FFA500';
  172. $color['OrangeRed'] = '#FF4500';
  173. $color['Orchid'] = '#DA70D6';
  174. $color['PaleGoldenRod'] = '#EEE8AA';
  175. $color['PaleGreen'] = '#98FB98';
  176. $color['PaleTurquoise'] = '#AFEEEE';
  177. $color['PaleVioletRed'] = '#D87093';
  178. $color['PapayaWhip'] = '#FFEFD5';
  179. $color['PeachPuff'] = '#FFDAB9';
  180. $color['Peru'] = '#CD853F';
  181. $color['Pink'] = '#FFC0CB';
  182. $color['Plum'] = '#DDA0DD';
  183. $color['PowderBlue'] = '#B0E0E6';
  184. $color['Purple'] = '#800080';
  185. $color['Red'] = '#FF0000';
  186. $color['RosyBrown'] = '#BC8F8F';
  187. $color['RoyalBlue'] = '#4169E1';
  188. $color['SaddleBrown'] = '#8B4513';
  189. $color['Salmon'] = '#FA8072';
  190. $color['SandyBrown'] = '#F4A460';
  191. $color['SeaGreen'] = '#2E8B57';
  192. $color['SeaShell'] = '#FFF5EE';
  193. $color['Sienna'] = '#A0522D';
  194. $color['Silver'] = '#C0C0C0';
  195. $color['SkyBlue'] = '#87CEEB';
  196. $color['SlateBlue'] = '#6A5ACD';
  197. $color['SlateGray'] = '#708090';
  198. $color['SlateGrey'] = '#708090';
  199. $color['Snow'] = '#FFFAFA';
  200. $color['SpringGreen'] = '#00FF7F';
  201. $color['SteelBlue'] = '#4682B4';
  202. $color['Tan'] = '#D2B48C';
  203. $color['Teal'] = '#008080';
  204. $color['Thistle'] = '#D8BFD8';
  205. $color['Tomato'] = '#FF6347';
  206. $color['Turquoise'] = '#40E0D0';
  207. $color['Violet'] = '#EE82EE';
  208. $color['Wheat'] = '#F5DEB3';
  209. $color['White'] = '#FFFFFF';
  210. $color['WhiteSmoke'] = '#F5F5F5';
  211. $color['Yellow'] = '#FFFF00';
  212. $color['YellowGreen'] = '#9ACD32';
  213. $this->htmlColor = array();
  214. foreach($color as $key => $val) $this->htmlColor[strtolower($key)] = $val;
  215. unset($color);
  216. $this->table = array();
  217. $this->value = array();
  218. $this->initStyle();
  219. // initialisation des styles sans héritages
  220. $this->resetStyle();
  221. }
  222. public function initStyle()
  223. {
  224. $this->value['id_balise'] = 'body'; // balise
  225. $this->value['id_name'] = null; // name
  226. $this->value['id_id'] = null; // id
  227. $this->value['id_class'] = null; // class
  228. $this->value['id_lst'] = array('*'); // lst de dependance
  229. $this->value['mini-size'] = 1.; // rapport de taille spécifique aux sup, sub
  230. $this->value['mini-decal'] = 0; // rapport de position spécifique aux sup, sub
  231. $this->value['font-family'] = 'Arial';
  232. $this->value['font-bold'] = false;
  233. $this->value['font-italic'] = false;
  234. $this->value['font-underline'] = false;
  235. $this->value['font-overline'] = false;
  236. $this->value['font-linethrough'] = false;
  237. $this->value['text-transform'] = 'none';
  238. $this->value['font-size'] = $this->ConvertToMM('10pt');
  239. $this->value['text-indent'] = 0;
  240. $this->value['text-align'] = 'left';
  241. $this->value['vertical-align'] = 'middle';
  242. $this->value['line-height'] = 'normal';
  243. $this->value['position'] = null;
  244. $this->value['x'] = null;
  245. $this->value['y'] = null;
  246. $this->value['width'] = 0;
  247. $this->value['height'] = 0;
  248. $this->value['top'] = null;
  249. $this->value['right'] = null;
  250. $this->value['bottom'] = null;
  251. $this->value['left'] = null;
  252. $this->value['float'] = null;
  253. $this->value['display'] = null;
  254. $this->value['rotate'] = null;
  255. $this->value['overflow'] = 'visible';
  256. $this->value['color'] = array(0, 0, 0);
  257. $this->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
  258. $this->value['border'] = array();
  259. $this->value['padding'] = array();
  260. $this->value['margin'] = array();
  261. $this->value['margin-auto'] = false;
  262. $this->value['list-style-type'] = '';
  263. $this->value['list-style-image'] = '';
  264. $this->value['xc'] = null;
  265. $this->value['yc'] = null;
  266. }
  267. /**
  268. * Initialisation des styles sans héritages
  269. *
  270. * @param string balise HTML
  271. * @return null
  272. */
  273. public function resetStyle($balise = '')
  274. {
  275. $collapse = isset($this->value['border']['collapse']) ? $this->value['border']['collapse'] : false;
  276. if (!in_array($balise, array('tr', 'td', 'th', 'thead', 'tbody', 'tfoot'))) $collapse = false;
  277. $this->value['position'] = null;
  278. $this->value['x'] = null;
  279. $this->value['y'] = null;
  280. $this->value['width'] = 0;
  281. $this->value['height'] = 0;
  282. $this->value['top'] = null;
  283. $this->value['right'] = null;
  284. $this->value['bottom'] = null;
  285. $this->value['left'] = null;
  286. $this->value['float'] = null;
  287. $this->value['display'] = null;
  288. $this->value['rotate'] = null;
  289. $this->value['overflow'] = 'visible';
  290. $this->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
  291. $this->value['border'] = array(
  292. 't' => $this->readBorder('none'),
  293. 'r' => $this->readBorder('none'),
  294. 'b' => $this->readBorder('none'),
  295. 'l' => $this->readBorder('none'),
  296. 'radius' => array(
  297. 'tl' => array(0, 0),
  298. 'tr' => array(0, 0),
  299. 'br' => array(0, 0),
  300. 'bl' => array(0, 0)
  301. ),
  302. 'collapse' => $collapse,
  303. );
  304. if (!in_array($balise, array('h1', 'h2', 'h3', 'h4', 'h5', 'h6')))
  305. $this->value['margin'] = array('t'=>0,'r'=>0,'b'=>0,'l'=>0);
  306. if ($balise=='p')
  307. {
  308. $this->value['margin']['t'] = null;
  309. $this->value['margin']['b'] = null;
  310. }
  311. $this->value['margin-auto'] = false;
  312. if (in_array($balise, array('div')))
  313. $this->value['vertical-align'] = 'top';
  314. if (in_array($balise, array('ul', 'li')))
  315. {
  316. $this->value['list-style-type'] = '';
  317. $this->value['list-style-image'] = '';
  318. }
  319. if (!in_array($balise, array('tr', 'td')))
  320. {
  321. $this->value['padding'] = array(
  322. 't' => 0,
  323. 'r' => 0,
  324. 'b' => 0,
  325. 'l' => 0
  326. );
  327. }
  328. else
  329. {
  330. $this->value['padding'] = array(
  331. 't' => $this->ConvertToMM('1px'),
  332. 'r' => $this->ConvertToMM('1px'),
  333. 'b' => $this->ConvertToMM('1px'),
  334. 'l' => $this->ConvertToMM('1px')
  335. );
  336. }
  337. if ($balise=='hr')
  338. {
  339. $this->value['border'] = array(
  340. 't' => $this->readBorder('solid 1px #000000'),
  341. 'r' => $this->readBorder('solid 1px #000000'),
  342. 'b' => $this->readBorder('solid 1px #000000'),
  343. 'l' => $this->readBorder('solid 1px #000000'),
  344. 'radius' => array(
  345. 'tl' => array(0, 0),
  346. 'tr' => array(0, 0),
  347. 'br' => array(0, 0),
  348. 'bl' => array(0, 0)
  349. ),
  350. 'collapse' => false,
  351. );
  352. $this->ConvertBackground('#FFFFFF', $this->value['background']);
  353. }
  354. $this->value['xc'] = null;
  355. $this->value['yc'] = null;
  356. }
  357. /**
  358. * Initialisation de la font PDF
  359. *
  360. * @return null
  361. */
  362. public function FontSet()
  363. {
  364. $family = strtolower($this->value['font-family']);
  365. $b = ($this->value['font-bold'] ? 'B' : '');
  366. $i = ($this->value['font-italic'] ? 'I' : '');
  367. $u = ($this->value['font-underline'] ? 'U' : '');
  368. $d = ($this->value['font-linethrough'] ? 'D' : '');
  369. if ($this->defaultFont)
  370. {
  371. $style = $b.$i;
  372. if($family=='arial')
  373. $family='helvetica';
  374. elseif($family=='symbol' || $family=='zapfdingbats')
  375. $style='';
  376. $fontkey = $family.$style;
  377. if (!$this->pdf->isLoadedFont($fontkey))
  378. $family = $this->defaultFont;
  379. }
  380. if($family=='arial')
  381. $family='helvetica';
  382. elseif($family=='symbol' || $family=='zapfdingbats')
  383. $style='';
  384. // taille en mm, ? ramener en pt
  385. $size = $this->value['font-size'];
  386. $size = 72 * $size / 25.4;
  387. $this->pdf->setOverline($this->value['font-overline']);
  388. // application de la fonte
  389. $this->pdf->SetFont($family, $b.$i.$u.$d, $this->value['mini-size']*$size);
  390. $this->pdf->setTextColorArray($this->value['color']);
  391. if ($this->value['background']['color'])
  392. $this->pdf->setFillColorArray($this->value['background']['color']);
  393. else
  394. $this->pdf->setFillColor(255);
  395. }
  396. /**
  397. * Monter d'un niveau dans l'historisation
  398. *
  399. * @return null
  400. */
  401. public function save()
  402. {
  403. $this->table[count($this->table)] = $this->value;
  404. }
  405. /**
  406. * Descendre d'un niveau dans l'historisation
  407. *
  408. * @return null
  409. */
  410. public function load()
  411. {
  412. if (count($this->table))
  413. {
  414. $this->value = $this->table[count($this->table)-1];
  415. unset($this->table[count($this->table)-1]);
  416. }
  417. }
  418. public function restorePosition()
  419. {
  420. if ($this->value['y']==$this->pdf->getY()) $this->pdf->setY($this->value['yc'], false);
  421. }
  422. public function setPosition()
  423. {
  424. $current_x = $this->pdf->getX();
  425. $current_y = $this->pdf->getY();
  426. $this->value['xc'] = $current_x;
  427. $this->value['yc'] = $current_y;
  428. if ($this->value['position']=='relative' || $this->value['position']=='absolute')
  429. {
  430. if ($this->value['right']!==null)
  431. {
  432. $x = $this->getLastWidth(true) - $this->value['right'] - $this->value['width'];
  433. if ($this->value['margin']['r']) $x-= $this->value['margin']['r'];
  434. }
  435. else
  436. {
  437. $x = $this->value['left'];
  438. if ($this->value['margin']['l']) $x+= $this->value['margin']['l'];
  439. }
  440. if ($this->value['bottom']!==null)
  441. {
  442. $y = $this->getLastHeight(true) - $this->value['bottom'] - $this->value['height'];
  443. if ($this->value['margin']['b']) $y-= $this->value['margin']['b'];
  444. }
  445. else
  446. {
  447. $y = $this->value['top'];
  448. if ($this->value['margin']['t']) $y+= $this->value['margin']['t'];
  449. }
  450. if ($this->value['position']=='relative')
  451. {
  452. $this->value['x'] = $current_x + $x;
  453. $this->value['y'] = $current_y + $y;
  454. }
  455. else
  456. {
  457. $this->value['x'] = $this->getLastAbsoluteX()+$x;
  458. $this->value['y'] = $this->getLastAbsoluteY()+$y;
  459. }
  460. }
  461. else
  462. {
  463. $this->value['x'] = $current_x;
  464. $this->value['y'] = $current_y;
  465. if ($this->value['margin']['l']) $this->value['x']+= $this->value['margin']['l'];
  466. if ($this->value['margin']['t']) $this->value['y']+= $this->value['margin']['t'];
  467. }
  468. $this->pdf->setXY($this->value['x'], $this->value['y']);
  469. }
  470. /**
  471. * Analyse un tableau de style provenant du parseurHTML
  472. *
  473. * @param string nom de la balise
  474. * @param array tableau de style
  475. * @return null
  476. */
  477. public function getSvgStyle($balise, &$param)
  478. {
  479. // preparation
  480. $balise = strtolower($balise);
  481. $id = isset($param['id']) ? strtolower(trim($param['id'])) : null; if (!$id) $id = null;
  482. $name = isset($param['name']) ? strtolower(trim($param['name'])) : null; if (!$name) $name = null;
  483. // lecture de la propriete classe
  484. $class = array();
  485. $tmp = isset($param['class']) ? strtolower(trim($param['class'])) : '';
  486. $tmp = explode(' ', $tmp);
  487. foreach($tmp as $k => $v)
  488. {
  489. $v = trim($v);
  490. if ($v) $class[] = $v;
  491. }
  492. // identification de la balise et des styles direct qui pourraient lui ?tre appliqués
  493. $this->value['id_balise'] = $balise;
  494. $this->value['id_name'] = $name;
  495. $this->value['id_id'] = $id;
  496. $this->value['id_class'] = $class;
  497. $this->value['id_lst'] = array();
  498. $this->value['id_lst'][] = '*';
  499. $this->value['id_lst'][] = $balise;
  500. if (!isset($this->value['svg']))
  501. {
  502. $this->value['svg'] = array(
  503. 'stroke' => null,
  504. 'stroke-width' => $this->ConvertToMM('1pt'),
  505. 'fill' => null,
  506. 'fill-opacity' => null,
  507. );
  508. }
  509. if (count($class))
  510. {
  511. foreach($class as $v)
  512. {
  513. $this->value['id_lst'][] = '*.'.$v;
  514. $this->value['id_lst'][] = '.'.$v;
  515. $this->value['id_lst'][] = $balise.'.'.$v;
  516. }
  517. }
  518. if ($id)
  519. {
  520. $this->value['id_lst'][] = '*#'.$id;
  521. $this->value['id_lst'][] = '#'.$id;
  522. $this->value['id_lst'][] = $balise.'#'.$id;
  523. }
  524. // style CSS
  525. $styles = $this->getFromCSS();
  526. // on ajoute le style propre ? la balise
  527. $styles = array_merge($styles, $param['style']);
  528. if (isset($styles['stroke'])) $this->value['svg']['stroke'] = $this->ConvertToColor($styles['stroke'], $res);
  529. if (isset($styles['stroke-width'])) $this->value['svg']['stroke-width'] = $this->ConvertToMM($styles['stroke-width']);
  530. if (isset($styles['fill'])) $this->value['svg']['fill'] = $this->ConvertToColor($styles['fill'], $res);
  531. if (isset($styles['fill-opacity'])) $this->value['svg']['fill-opacity'] = 1.*$styles['fill-opacity'];
  532. return $this->value['svg'];
  533. }
  534. /**
  535. * Analyse un tableau de style provenant du parseurHTML
  536. *
  537. * @param string nom de la balise
  538. * @param array tableau de style
  539. * @param array tableau initialisant des styles
  540. * @return null
  541. */
  542. public function analyse($balise, &$param, $heritage = null)
  543. {
  544. // preparation
  545. $balise = strtolower($balise);
  546. $id = isset($param['id']) ? strtolower(trim($param['id'])) : null; if (!$id) $id = null;
  547. $name = isset($param['name']) ? strtolower(trim($param['name'])) : null; if (!$name) $name = null;
  548. // lecture de la propriete classe
  549. $class = array();
  550. $tmp = isset($param['class']) ? strtolower(trim($param['class'])) : '';
  551. $tmp = explode(' ', $tmp);
  552. foreach($tmp as $k => $v)
  553. {
  554. $v = trim($v);
  555. if ($v) $class[] = $v;
  556. }
  557. // identification de la balise et des styles direct qui pourraient lui ?tre appliqués
  558. $this->value['id_balise'] = $balise;
  559. $this->value['id_name'] = $name;
  560. $this->value['id_id'] = $id;
  561. $this->value['id_class'] = $class;
  562. $this->value['id_lst'] = array();
  563. $this->value['id_lst'][] = '*';
  564. $this->value['id_lst'][] = $balise;
  565. if (count($class))
  566. {
  567. foreach($class as $v)
  568. {
  569. $this->value['id_lst'][] = '*.'.$v;
  570. $this->value['id_lst'][] = '.'.$v;
  571. $this->value['id_lst'][] = $balise.'.'.$v;
  572. }
  573. }
  574. if ($id)
  575. {
  576. $this->value['id_lst'][] = '*#'.$id;
  577. $this->value['id_lst'][] = '#'.$id;
  578. $this->value['id_lst'][] = $balise.'#'.$id;
  579. }
  580. // style CSS
  581. $styles = $this->getFromCSS();
  582. // on ajoute le style propre ? la balise
  583. $styles = array_merge($styles, $param['style']);
  584. if (isset($param['allwidth']) && !isset($styles['width'])) $styles['width'] = '100%';
  585. // mise ? zero des styles non hérités
  586. $this->resetStyle($balise);
  587. if ($heritage)
  588. {
  589. foreach($heritage as $he_nom => $he_val)
  590. {
  591. if (is_array($he_val))
  592. {
  593. foreach($he_val as $he2_nom => $he2_val)
  594. $this->value[$he_nom][$he2_nom] = $he2_val;
  595. }
  596. else
  597. $this->value[$he_nom] = $he_val;
  598. }
  599. }
  600. // interpreration des nouvelles valeurs
  601. $correct_width = false;
  602. $no_width = true;
  603. foreach($styles as $nom => $val)
  604. {
  605. switch($nom)
  606. {
  607. case 'font-family':
  608. $val = explode(',', $val);
  609. $val = trim($val[0]);
  610. if ($val) $this->value['font-family'] = $val;
  611. break;
  612. case 'font-weight':
  613. $this->value['font-bold'] = ($val=='bold');
  614. break;
  615. case 'font-style':
  616. $this->value['font-italic'] = ($val=='italic');
  617. break;
  618. case 'text-decoration':
  619. $val = explode(' ', $val);
  620. $this->value['font-underline'] = (in_array('underline', $val));
  621. $this->value['font-overline'] = (in_array('overline', $val));
  622. $this->value['font-linethrough'] = (in_array('line-through', $val));
  623. break;
  624. case 'text-indent':
  625. $this->value['text-indent'] = $this->ConvertToMM($val);
  626. break;
  627. case 'text-transform':
  628. if (!in_array($val, array('none', 'capitalize', 'uppercase', 'lowercase'))) $val = 'none';
  629. $this->value['text-transform'] = $val;
  630. break;
  631. case 'font-size':
  632. $val = $this->ConvertToMM($val, $this->value['font-size']);
  633. if ($val) $this->value['font-size'] = $val;
  634. break;
  635. case 'color':
  636. $res = null;
  637. $this->value['color'] = $this->ConvertToColor($val, $res);
  638. if ($balise=='hr')
  639. {
  640. $this->value['border']['l']['color'] = $this->value['color'];
  641. $this->value['border']['t']['color'] = $this->value['color'];
  642. $this->value['border']['r']['color'] = $this->value['color'];
  643. $this->value['border']['b']['color'] = $this->value['color'];
  644. }
  645. break;
  646. case 'text-align':
  647. $val = strtolower($val);
  648. if (!in_array($val, array('left', 'right', 'center', 'justify', 'li_right'))) $val = 'left';
  649. $this->value['text-align'] = $val;
  650. break;
  651. case 'vertical-align':
  652. $this->value['vertical-align'] = $val;
  653. break;
  654. case 'width':
  655. $this->value['width'] = $this->ConvertToMM($val, $this->getLastWidth());
  656. if ($this->value['width'] && substr($val, -1)=='%') $correct_width=true;
  657. $no_width = false;
  658. break;
  659. case 'height':
  660. $this->value['height'] = $this->ConvertToMM($val, $this->getLastHeight());
  661. break;
  662. case 'line-height':
  663. if (preg_match('/^[0-9\.]+$/isU', $val)) $val = floor($val*100).'%';
  664. $this->value['line-height'] = $val;
  665. break;
  666. case 'rotate':
  667. if (!in_array($val, array(0, -90, 90, 180, 270, -180, -270))) $val = null;
  668. if ($val<0) $val+= 360;
  669. $this->value['rotate'] = $val;
  670. break;
  671. case 'overflow':
  672. if (!in_array($val, array('visible', 'hidden'))) $val = 'visible';
  673. $this->value['overflow'] = $val;
  674. break;
  675. case 'padding':
  676. $val = explode(' ', $val);
  677. foreach($val as $k => $v)
  678. {
  679. $v = trim($v);
  680. if ($v!='') $val[$k] = $v;
  681. else unset($val[$k]);
  682. }
  683. $val = array_values($val);
  684. if (count($val)!=4)
  685. {
  686. $val = $this->ConvertToMM($val[0], 0);
  687. $this->value['padding']['t'] = $val;
  688. $this->value['padding']['r'] = $val;
  689. $this->value['padding']['b'] = $val;
  690. $this->value['padding']['l'] = $val;
  691. }
  692. else
  693. {
  694. $this->value['padding']['t'] = $this->ConvertToMM($val[0], 0);
  695. $this->value['padding']['r'] = $this->ConvertToMM($val[1], 0);
  696. $this->value['padding']['b'] = $this->ConvertToMM($val[2], 0);
  697. $this->value['padding']['l'] = $this->ConvertToMM($val[3], 0);
  698. }
  699. break;
  700. case 'padding-top':
  701. $this->value['padding']['t'] = $this->ConvertToMM($val, 0);
  702. break;
  703. case 'padding-right':
  704. $this->value['padding']['r'] = $this->ConvertToMM($val, 0);
  705. break;
  706. case 'padding-bottom':
  707. $this->value['padding']['b'] = $this->ConvertToMM($val, 0);
  708. break;
  709. case 'padding-left':
  710. $this->value['padding']['l'] = $this->ConvertToMM($val, 0);
  711. break;
  712. case 'margin':
  713. if ($val=='auto')
  714. {
  715. $this->value['margin-auto'] = true;
  716. break;
  717. }
  718. $val = explode(' ', $val);
  719. foreach($val as $k => $v)
  720. {
  721. $v = trim($v);
  722. if ($v!='') $val[$k] = $v;
  723. else unset($val[$k]);
  724. }
  725. $val = array_values($val);
  726. if (count($val)!=4)
  727. {
  728. $val = $this->ConvertToMM($val[0], 0);
  729. $this->value['margin']['t'] = $val;
  730. $this->value['margin']['r'] = $val;
  731. $this->value['margin']['b'] = $val;
  732. $this->value['margin']['l'] = $val;
  733. }
  734. else
  735. {
  736. $this->value['margin']['t'] = $this->ConvertToMM($val[0], 0);
  737. $this->value['margin']['r'] = $this->ConvertToMM($val[1], 0);
  738. $this->value['margin']['b'] = $this->ConvertToMM($val[2], 0);
  739. $this->value['margin']['l'] = $this->ConvertToMM($val[3], 0);
  740. }
  741. break;
  742. case 'margin-top':
  743. $this->value['margin']['t'] = $this->ConvertToMM($val, 0);
  744. break;
  745. case 'margin-right':
  746. $this->value['margin']['r'] = $this->ConvertToMM($val, 0);
  747. break;
  748. case 'margin-bottom':
  749. $this->value['margin']['b'] = $this->ConvertToMM($val, 0);
  750. break;
  751. case 'margin-left':
  752. $this->value['margin']['l'] = $this->ConvertToMM($val, 0);
  753. break;
  754. case 'border':
  755. $val = $this->readBorder($val);
  756. $this->value['border']['t'] = $val;
  757. $this->value['border']['r'] = $val;
  758. $this->value['border']['b'] = $val;
  759. $this->value['border']['l'] = $val;
  760. break;
  761. case 'border-style':
  762. $val = explode(' ', $val);
  763. foreach($val as $val_k => $val_v)
  764. if (!in_array($val_v, array('solid', 'dotted', 'dashed')))
  765. $val[$val_k] = null;
  766. $this->duplicateBorder($val);
  767. if ($val[0]) $this->value['border']['t']['type'] = $val[0];
  768. if ($val[1]) $this->value['border']['r']['type'] = $val[1];
  769. if ($val[2]) $this->value['border']['b']['type'] = $val[2];
  770. if ($val[3]) $this->value['border']['l']['type'] = $val[3];
  771. break;
  772. case 'border-top-style':
  773. if (in_array($val, array('solid', 'dotted', 'dashed')))
  774. $this->value['border']['t']['type'] = $val;
  775. break;
  776. case 'border-right-style':
  777. if (in_array($val, array('solid', 'dotted', 'dashed')))
  778. $this->value['border']['r']['type'] = $val;
  779. break;
  780. case 'border-bottom-style':
  781. if (in_array($val, array('solid', 'dotted', 'dashed')))
  782. $this->value['border']['b']['type'] = $val;
  783. break;
  784. case 'border-left-style':
  785. if (in_array($val, array('solid', 'dotted', 'dashed')))
  786. $this->value['border']['l']['type'] = $val;
  787. break;
  788. case 'border-color':
  789. $res = false;
  790. $val = preg_replace('/,[\s]+/', ',', $val);
  791. $val = explode(' ', $val);
  792. foreach($val as $val_k => $val_v)
  793. {
  794. $val[$val_k] = $this->ConvertToColor($val_v, $res);
  795. if (!$res) $val[$val_k] = null;
  796. }
  797. $this->duplicateBorder($val);
  798. if (is_array($val[0])) $this->value['border']['t']['color'] = $val[0];
  799. if (is_array($val[1])) $this->value['border']['r']['color'] = $val[1];
  800. if (is_array($val[2])) $this->value['border']['b']['color'] = $val[2];
  801. if (is_array($val[3])) $this->value['border']['l']['color'] = $val[3];
  802. break;
  803. case 'border-top-color':
  804. $res = false;
  805. $val = $this->ConvertToColor($val, $res);
  806. if ($res) $this->value['border']['t']['color'] = $val;
  807. break;
  808. case 'border-right-color':
  809. $res = false;
  810. $val = $this->ConvertToColor($val, $res);
  811. if ($res) $this->value['border']['r']['color'] = $val;
  812. break;
  813. case 'border-bottom-color':
  814. $res = false;
  815. $val = $this->ConvertToColor($val, $res);
  816. if ($res) $this->value['border']['b']['color'] = $val;
  817. break;
  818. case 'border-left-color':
  819. $res = false;
  820. $val = $this->ConvertToColor($val, $res);
  821. if ($res) $this->value['border']['l']['color'] = $val;
  822. break;
  823. case 'border-width':
  824. $val = explode(' ', $val);
  825. foreach($val as $val_k => $val_v)
  826. {
  827. $val[$val_k] = $this->ConvertToMM($val_v, 0);
  828. }
  829. $this->duplicateBorder($val);
  830. if ($val[0]) $this->value['border']['t']['width'] = $val[0];
  831. if ($val[1]) $this->value['border']['r']['width'] = $val[1];
  832. if ($val[2]) $this->value['border']['b']['width'] = $val[2];
  833. if ($val[3]) $this->value['border']['l']['width'] = $val[3];
  834. break;
  835. case 'border-top-width':
  836. $val = $this->ConvertToMM($val, 0);;
  837. if ($val) $this->value['border']['t']['width'] = $val;
  838. break;
  839. case 'border-right-width':
  840. $val = $this->ConvertToMM($val, 0);;
  841. if ($val) $this->value['border']['r']['width'] = $val;
  842. break;
  843. case 'border-bottom-width':
  844. $val = $this->ConvertToMM($val, 0);;
  845. if ($val) $this->value['border']['b']['width'] = $val;
  846. break;
  847. case 'border-left-width':
  848. $val = $this->ConvertToMM($val, 0);;
  849. if ($val) $this->value['border']['l']['width'] = $val;
  850. break;
  851. case 'border-collapse':
  852. if ($balise=='table') $this->value['border']['collapse'] = ($val=='collapse');
  853. break;
  854. case 'border-radius':
  855. $val = explode('/', $val); if (count($val)>2) break;
  856. $val_h = $this->ConvertToRadius(trim($val[0]));
  857. if (count($val_h)<1 || count($val_h)>4) break;
  858. if (!isset($val_h[1])) $val_h[1] = $val_h[0];
  859. if (!isset($val_h[2])) $val_h = array($val_h[0], $val_h[0], $val_h[1], $val_h[1]);
  860. if (!isset($val_h[3])) $val_h[3] = $val_h[1];
  861. if (isset($val[1]))
  862. {
  863. $val_v = $this->ConvertToRadius(trim($val[1]));
  864. if (count($val_v)<1 || count($val_v)>4) break;
  865. if (!isset($val_v[1])) $val_v[1] = $val_v[0];
  866. if (!isset($val_v[2])) $val_v = array($val_v[0], $val_v[0], $val_v[1], $val_v[1]);
  867. if (!isset($val_v[3])) $val_v[3] = $val_v[1];
  868. }
  869. else
  870. $val_v = $val_h;
  871. $this->value['border']['radius'] = array(
  872. 'tl' => array($val_h[0], $val_v[0]),
  873. 'tr' => array($val_h[1], $val_v[1]),
  874. 'br' => array($val_h[2], $val_v[2]),
  875. 'bl' => array($val_h[3], $val_v[3])
  876. );
  877. break;
  878. case 'border-top-left-radius':
  879. $val = $this->ConvertToRadius($val);
  880. if (count($val)<1 || count($val)>2) break;
  881. $this->value['border']['radius']['tl'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
  882. break;
  883. case 'border-top-right-radius':
  884. $val = $this->ConvertToRadius($val);
  885. if (count($val)<1 || count($val)>2) break;
  886. $this->value['border']['radius']['tr'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
  887. break;
  888. case 'border-bottom-right-radius':
  889. $val = $this->ConvertToRadius($val);
  890. if (count($val)<1 || count($val)>2) break;
  891. $this->value['border']['radius']['br'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
  892. break;
  893. case 'border-bottom-left-radius':
  894. $val = $this->ConvertToRadius($val);
  895. if (count($val)<1 || count($val)>2) break;
  896. $this->value['border']['radius']['bl'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
  897. break;
  898. case 'border-top':
  899. $this->value['border']['t'] = $this->readBorder($val);
  900. break;
  901. case 'border-right':
  902. $this->value['border']['r'] = $this->readBorder($val);
  903. break;
  904. case 'border-bottom':
  905. $this->value['border']['b'] = $this->readBorder($val);
  906. break;
  907. case 'border-left':
  908. $this->value['border']['l'] = $this->readBorder($val);
  909. break;
  910. case 'background-color':
  911. $this->value['background']['color'] = $this->ConvertBackgroundColor($val);
  912. break;
  913. case 'background-image':
  914. $this->value['background']['image'] = $this->ConvertBackgroundImage($val);
  915. break;
  916. case 'background-position':
  917. $res = null;
  918. $this->value['background']['position'] = $this->ConvertBackgroundPosition($val, $res);
  919. break;
  920. case 'background-repeat':
  921. $this->value['background']['repeat'] = $this->ConvertBackgroundRepeat($val);
  922. break;
  923. case 'background':
  924. $this->ConvertBackground($val, $this->value['background']);
  925. break;
  926. case 'position':
  927. if ($val=='absolute') $this->value['position'] = 'absolute';
  928. else if ($val=='relative') $this->value['position'] = 'relative';
  929. else $this->value['position'] = null;
  930. break;
  931. case 'float':
  932. if ($val=='left') $this->value['float'] = 'left';
  933. else if ($val=='right') $this->value['float'] = 'right';
  934. else $this->value['float'] = null;
  935. break;
  936. case 'display':
  937. if ($val=='inline') $this->value['display'] = 'inline';
  938. else if ($val=='block') $this->value['display'] = 'block';
  939. else if ($val=='none') $this->value['display'] = 'none';
  940. else $this->value['display'] = null;
  941. break;
  942. case 'top':
  943. case 'bottom':
  944. case 'left':
  945. case 'right':
  946. $this->value[$nom] = $val;
  947. break;
  948. case 'list-style':
  949. case 'list-style-type':
  950. case 'list-style-image':
  951. if ($nom=='list-style') $nom = 'list-style-type';
  952. $this->value[$nom] = $val;
  953. break;
  954. default:
  955. break;
  956. }
  957. }
  958. if ($this->value['margin']['t']===null) $this->value['margin']['t'] = $this->value['font-size'];
  959. if ($this->value['margin']['b']===null) $this->value['margin']['b'] = $this->value['font-size'];
  960. if ($this->onlyLeft) $this->value['text-align'] = 'left';
  961. // correction de la largeur pour correspondre au mod?le de boite quick
  962. if ($no_width && in_array($balise, array('div')) && $this->value['position']!='absolute')
  963. {
  964. $this->value['width'] = $this->getLastWidth();
  965. $this->value['width']-= $this->value['margin']['l'] + $this->value['margin']['r'];
  966. }
  967. else
  968. {
  969. if ($correct_width)
  970. {
  971. if (!in_array($balise, array('table', 'div', 'hr')))
  972. {
  973. $this->value['width']-= $this->value['padding']['l'] + $this->value['padding']['r'];
  974. $this->value['width']-= $this->value['border']['l']['width'] + $this->value['border']['r']['width'];
  975. }
  976. if (in_array($balise, array('th', 'td')))
  977. {
  978. $this->value['width']-= $this->ConvertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
  979. }
  980. if ($this->value['width']<0) $this->value['width']=0;
  981. }
  982. else
  983. {
  984. if ($this->value['width'])
  985. {
  986. if ($this->value['border']['l']['width']) $this->value['width'] += $this->value['border']['l']['width'];
  987. if ($this->value['border']['r']['width']) $this->value['width'] += $this->value['border']['r']['width'];
  988. if ($this->value['padding']['l']) $this->value['width'] += $this->value['padding']['l'];
  989. if ($this->value['padding']['r']) $this->value['width'] += $this->value['padding']['r'];
  990. }
  991. }
  992. }
  993. if ($this->value['height'])
  994. {
  995. if ($this->value['border']['b']['width']) { $this->value['height'] += $this->value['border']['b']['width']; }
  996. if ($this->value['border']['t']['width']) { $this->value['height'] += $this->value['border']['t']['width']; }
  997. if ($this->value['padding']['b']) $this->value['height'] += $this->value['padding']['b'];
  998. if ($this->value['padding']['t']) $this->value['height'] += $this->value['padding']['t'];
  999. }
  1000. if ($this->value['top']!=null) $this->value['top'] = $this->ConvertToMM($this->value['top'], $this->getLastHeight(true));
  1001. if ($this->value['bottom']!=null) $this->value['bottom'] = $this->ConvertToMM($this->value['bottom'], $this->getLastHeight(true));
  1002. if ($this->value['left']!=null) $this->value['left'] = $this->ConvertToMM($this->value['left'], $this->getLastWidth(true));
  1003. if ($this->value['right']!=null) $this->value['right'] = $this->ConvertToMM($this->value['right'], $this->getLastWidth(true));
  1004. if ($this->value['top'] && $this->value['bottom'] && $this->value['height']) $this->value['bottom'] = null;
  1005. if ($this->value['left'] && $this->value['right'] && $this->value['width']) $this->value['right'] = null;
  1006. }
  1007. /**
  1008. * Récupération de la hauteur de ligne courante
  1009. *
  1010. * @return float hauteur en mm
  1011. */
  1012. public function getLineHeight()
  1013. {
  1014. $val = $this->value['line-height'];
  1015. if ($val=='normal') $val = '108%';
  1016. return $this->ConvertToMM($val, $this->value['font-size']);
  1017. }
  1018. /**
  1019. * Récupération de la largeur de l'objet parent
  1020. *
  1021. * @return float largeur
  1022. */
  1023. public function getLastWidth($mode = false)
  1024. {
  1025. for($k=count($this->table); $k>0; $k--)
  1026. {
  1027. if ($this->table[$k-1]['width'])
  1028. {
  1029. $w = $this->table[$k-1]['width'];
  1030. if ($mode)
  1031. {
  1032. $w+= $this->table[$k-1]['border']['l']['width'] + $this->table[$k-1]['padding']['l']+0.02;
  1033. $w+= $this->table[$k-1]['border']['r']['width'] + $this->table[$k-1]['padding']['r']+0.02;
  1034. }
  1035. return $w;
  1036. }
  1037. }
  1038. return $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  1039. }
  1040. /**
  1041. * Récupération de la hauteur de l'objet parent
  1042. *
  1043. * @return float hauteur
  1044. */
  1045. public function getLastHeight($mode = false)
  1046. {
  1047. for($k=count($this->table); $k>0; $k--)
  1048. {
  1049. if ($this->table[$k-1]['height'])
  1050. {
  1051. $h = $this->table[$k-1]['height'];
  1052. if ($mode)
  1053. {
  1054. $h+= $this->table[$k-1]['border']['t']['width'] + $this->table[$k-1]['padding']['t']+0.02;
  1055. $h+= $this->table[$k-1]['border']['b']['width'] + $this->table[$k-1]['padding']['b']+0.02;
  1056. }
  1057. return $h;
  1058. }
  1059. }
  1060. return $this->pdf->getH() - $this->pdf->gettMargin() - $this->pdf->getbMargin();
  1061. }
  1062. public function getFloat()
  1063. {
  1064. if ($this->value['float']=='left') return 'left';
  1065. if ($this->value['float']=='right') return 'right';
  1066. return null;
  1067. }
  1068. public function getLastValue($key)
  1069. {
  1070. $nb = count($this->table);
  1071. if ($nb>0)
  1072. return $this->table[$nb-1][$key];
  1073. return null;
  1074. }
  1075. protected function getLastAbsoluteX()
  1076. {
  1077. for($k=count($this->table); $k>0; $k--)
  1078. {
  1079. if ($this->table[$k-1]['x'] && $this->table[$k-1]['position']) return $this->table[$k-1]['x'];
  1080. }
  1081. return $this->pdf->getlMargin();
  1082. }
  1083. protected function getLastAbsoluteY()
  1084. {
  1085. for($k=count($this->table); $k>0; $k--)
  1086. {
  1087. if ($this->table[$k-1]['y'] && $this->table[$k-1]['position']) return $this->table[$k-1]['y'];
  1088. }
  1089. return $this->pdf->gettMargin();
  1090. }
  1091. /**
  1092. * Récupération des propriétés CSS de la balise en cours
  1093. *
  1094. * @return array() tableau des propriétés CSS
  1095. */
  1096. protected function getFromCSS()
  1097. {
  1098. $styles = array(); // style ? appliquer
  1099. $getit = array(); // styles ? récuperer
  1100. // identification des styles direct, et ceux des parents
  1101. $lst = array();
  1102. $lst[] = $this->value['id_lst'];
  1103. for($i=count($this->table)-1; $i>=0; $i--) $lst[] = $this->table[$i]['id_lst'];
  1104. // identification des styles ? récuperer
  1105. foreach($this->css_keys as $key => $num)
  1106. if ($this->getReccursiveStyle($key, $lst))
  1107. $getit[$key] = $num;
  1108. // si des styles sont ? recuperer
  1109. if (count($getit))
  1110. {
  1111. // on les récup?re, mais dans l'odre de définition, afin de garder les priorités
  1112. asort($getit);
  1113. foreach($getit as $key => $val) $styles = array_merge($styles, $this->css[$key]);
  1114. }
  1115. return $styles;
  1116. }
  1117. /**
  1118. * Identification des styles ? récuperer, en fonction de la balise et de ses parents
  1119. *
  1120. * @param string clef CSS ? analyser
  1121. * @param array() tableau des styles direct, et ceux des parents
  1122. * @param string prochaine etape
  1123. * @return boolean clef autorisée ou non
  1124. */
  1125. protected function getReccursiveStyle($key, $lst, $next = null)
  1126. {
  1127. // si propchaine etape, on construit les valeurs
  1128. if ($next!==null)
  1129. {
  1130. if ($next) $key = trim(substr($key, 0, -strlen($next))); // on el?ve cette etape
  1131. unset($lst[0]);
  1132. if (!count($lst)) return false; // pas d'etape possible
  1133. $lst = array_values($lst);
  1134. }
  1135. // pour chaque style direct possible de l'etape en cours
  1136. foreach($lst[0] as $nom)
  1137. {
  1138. if ($key==$nom) return true; // si la clef conrrespond => ok
  1139. if (substr($key, -strlen(' '.$nom))==' '.$nom && $this->getReccursiveStyle($key, $lst, $nom)) return true; // si la clef est la fin, on analyse ce qui préc?de
  1140. }
  1141. // si on est pas ? la premiere etape, on doit analyse toutes les sous etapes
  1142. if ($next!==null && $this->getReccursiveStyle($key, $lst, '')) return true;
  1143. // aucun style trouvé
  1144. return false;
  1145. }
  1146. /**
  1147. * Analyse d'une propriété Border
  1148. *
  1149. * @param string propriété border
  1150. * @return array() propriété décodée
  1151. */
  1152. public function readBorder($val)
  1153. {
  1154. $none = array('type' => 'none', 'width' => 0, 'color' => array(0, 0, 0));
  1155. // valeurs par défault
  1156. $type = 'solid';
  1157. $width = $this->ConvertToMM('1pt');
  1158. $color = array(0, 0, 0);
  1159. // nettoyage des valeurs
  1160. $val = explode(' ', $val);
  1161. foreach($val as $k => $v)
  1162. {
  1163. $v = trim($v);
  1164. if ($v) $val[$k] = $v;
  1165. else unset($val[$k]);
  1166. }
  1167. $val = array_values($val);
  1168. // identification des valeurs
  1169. $res = null;
  1170. foreach($val as $key)
  1171. {
  1172. if ($key=='none' || $key=='hidden') return $none;
  1173. if ($this->ConvertToMM($key)!==null)
  1174. $width = $this->ConvertToMM($key);
  1175. else if (in_array($key, array('solid', 'dotted', 'dashed', 'double')))
  1176. $type = $key;
  1177. else
  1178. {
  1179. $tmp = $this->ConvertToColor($key, $res);
  1180. if ($res) $color = $tmp;
  1181. }
  1182. }
  1183. if (!$width) return $none;
  1184. return array('type' => $type, 'width' => $width, 'color' => $color);
  1185. }
  1186. protected function duplicateBorder(&$val)
  1187. {
  1188. if (count($val)==1)
  1189. {
  1190. $val[1] = $val[0];
  1191. $val[2] = $val[0];
  1192. $val[3] = $val[0];
  1193. }
  1194. else if (count($val)==2)
  1195. {
  1196. $val[2] = $val[0];
  1197. $val[3] = $val[1];
  1198. }
  1199. else if (count($val)==3)
  1200. {
  1201. $val[3] = $val[1];
  1202. }
  1203. }
  1204. public function ConvertBackground($stl, &$res)
  1205. {
  1206. // Image
  1207. $text = '/url\(([^)]*)\)/isU';
  1208. if (preg_match($text, $stl, $match))
  1209. {
  1210. $res['image'] = $this->ConvertBackgroundImage($match[0]);
  1211. $stl = preg_replace($text, '', $stl);
  1212. $stl = preg_replace('/[\s]+/', ' ', $stl);
  1213. }
  1214. // protection des espaces
  1215. $stl = preg_replace('/,[\s]+/', ',', $stl);
  1216. $lst = explode(' ', $stl);
  1217. $pos = '';
  1218. foreach($lst as $val)
  1219. {
  1220. $ok = false;
  1221. $color = $this->ConvertToColor($val, $ok);
  1222. if ($ok)
  1223. {
  1224. $res['color'] = $color;
  1225. }
  1226. else if ($val=='transparent')
  1227. {
  1228. $res['color'] = null;
  1229. }
  1230. else
  1231. {
  1232. $repeat = $this->ConvertBackgroundRepeat($val);
  1233. if ($repeat)
  1234. {
  1235. $res['repeat'] = $repeat;
  1236. }
  1237. else
  1238. {
  1239. $pos.= ($pos ? ' ' : '').$val;
  1240. }
  1241. }
  1242. }
  1243. if ($pos)
  1244. {
  1245. $pos = $this->ConvertBackgroundPosition($pos, $ok);
  1246. if ($ok) $res['position'] = $pos;
  1247. }
  1248. }
  1249. public function ConvertBackgroundColor($val)
  1250. {
  1251. $res = null;
  1252. if ($val=='transparent') return null;
  1253. else return $this->ConvertToColor($val, $res);
  1254. }
  1255. public function ConvertBackgroundImage($val)
  1256. {
  1257. if ($val=='none')
  1258. return null;
  1259. else if (preg_match('/^url\(([^)]*)\)$/isU', $val, $match))
  1260. return $match[1];
  1261. else
  1262. return null;
  1263. }
  1264. public function ConvertBackgroundPosition($val, &$res)
  1265. {
  1266. $val = explode(' ', $val);
  1267. if (count($val)<2)
  1268. {
  1269. if (!$val[0]) return null;
  1270. $val[1] = 'center';
  1271. }
  1272. if (count($val)>2) return null;
  1273. $x = 0;
  1274. $y = 0;
  1275. $res = true;
  1276. if ($val[0]=='left') $x = '0%';
  1277. else if ($val[0]=='center') $x = '50%';
  1278. else if ($val[0]=='right') $x = '100%';
  1279. else if ($val[0]=='top') $y = '0%';
  1280. else if ($val[0]=='bottom') $y = '100%';
  1281. else if (preg_match('/^[-]?[0-9\.]+%$/isU', $val[0])) $x = $val[0];
  1282. else if ($this->ConvertToMM($val[0])) $x = $this->ConvertToMM($val[0]);
  1283. else $res = false;
  1284. if ($val[1]=='left') $x = '0%';
  1285. else if ($val[1]=='right') $x = '100%';
  1286. else if ($val[1]=='top') $y = '0%';
  1287. else if ($val[1]=='center') $y = '50%';
  1288. else if ($val[1]=='bottom') $y = '100%';
  1289. else if (preg_match('/^[-]?[0-9\.]+%$/isU', $val[1])) $y = $val[1];
  1290. else if ($this->ConvertToMM($val[1])) $y = $this->ConvertToMM($val[1]);
  1291. else $res = false;
  1292. $val[0] = $x;
  1293. $val[1] = $y;
  1294. return $val;
  1295. }
  1296. public function ConvertBackgroundRepeat($val)
  1297. {
  1298. switch($val)
  1299. {
  1300. case 'repeat':
  1301. return array(true, true);
  1302. case 'repeat-x':
  1303. return array(true, false);
  1304. case 'repeat-y':
  1305. return array(false, true);
  1306. case 'no-repeat':
  1307. return array(false, false);
  1308. }
  1309. return null;
  1310. }
  1311. /**
  1312. * Convertir une longueur en mm
  1313. *
  1314. * @param string longueur, avec unité, ? convertir
  1315. * @param float longueur du parent
  1316. * @return float longueur exprimée en mm
  1317. */
  1318. public function ConvertToMM($val, $old=0.)
  1319. {
  1320. $val = trim($val);
  1321. if (preg_match('/^[0-9\.\-]+$/isU', $val)) $val.= 'px';
  1322. if (preg_match('/^[0-9\.\-]+px$/isU', $val)) $val = 25.4/96. * str_replace('px', '', $val);
  1323. else if (preg_match('/^[0-9\.\-]+pt$/isU', $val)) $val = 25.4/72. * str_replace('pt', '', $val);
  1324. else if (preg_match('/^[0-9\.\-]+in$/isU', $val)) $val = 25.4 * str_replace('in', '', $val);
  1325. else if (preg_match('/^[0-9\.\-]+mm$/isU', $val)) $val = 1.*str_replace('mm', '', $val);
  1326. else if (preg_match('/^[0-9\.\-]+%$/isU', $val)) $val = 1.*$old*str_replace('%', '', $val)/100.;
  1327. else $val = null;
  1328. return $val;
  1329. }
  1330. public function ConvertToRadius($val)
  1331. {
  1332. $val = explode(' ', $val);
  1333. foreach($val as $k => $v)
  1334. {
  1335. $v = trim($v);
  1336. if ($v)
  1337. {
  1338. $v = $this->ConvertToMM($v, 0);
  1339. if ($v!==null)
  1340. $val[$k] = $v;
  1341. else
  1342. unset($val[$k]);
  1343. }
  1344. else unset($val[$k]);
  1345. }
  1346. return array_values($val);
  1347. }
  1348. /**
  1349. * Décomposition d'un code couleur HTML
  1350. *
  1351. * @param string couleur au format CSS
  1352. * @return array(r, v, b) couleur exprimé par ses comporantes R, V, B, de 0 ? 255.
  1353. */
  1354. public function ConvertToColor($val, &$res)
  1355. {
  1356. $val = trim($val);
  1357. $res = true;
  1358. if (strtolower($val)=='transparent') return array(null, null, null);
  1359. if (isset($this->htmlColor[strtolower($val)])) $val = $this->htmlColor[strtolower($val)];
  1360. if (preg_match('/^#[0-9A-Fa-f]{6}$/isU', $val))
  1361. {
  1362. $r = floatVal(hexdec(substr($val, 1, 2)));
  1363. $v = floatVal(hexdec(substr($val, 3, 2)));
  1364. $b = floatVal(hexdec(substr($val, 5, 2)));
  1365. $col = array($r, $v, $b);
  1366. }
  1367. elseif (preg_match('/^#[0-9A-F]{3}$/isU', $val))
  1368. {
  1369. $r = floatVal(hexdec(substr($val, 1, 1).substr($val, 1, 1)));
  1370. $v = floatVal(hexdec(substr($val, 2, 1).substr($val, 2, 1)));
  1371. $b = floatVal(hexdec(substr($val, 3, 1).substr($val, 3, 1)));
  1372. $col = array($r, $v, $b);
  1373. }
  1374. elseif (preg_match('/rgb\([\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*\)/isU', $val, $match))
  1375. {
  1376. $r = $this->ConvertSubColor($match[1])*255.;
  1377. $v = $this->ConvertSubColor($match[2])*255.;
  1378. $b = $this->ConvertSubColor($match[3])*255.;
  1379. $col = array($r, $v, $b);
  1380. }
  1381. elseif (preg_match('/cmyk\([\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*\)/isU', $val, $match))
  1382. {
  1383. $c = $this->ConvertSubColor($match[1])*100.;
  1384. $m = $this->ConvertSubColor($match[2])*100.;
  1385. $y = $this->ConvertSubColor($match[3])*100.;
  1386. $k = $this->ConvertSubColor($match[4])*100.;
  1387. $col = array($c, $m, $y, $k);
  1388. }
  1389. else
  1390. {
  1391. $col = array(0., 0., 0.);
  1392. $res = false;
  1393. }
  1394. return $col;
  1395. }
  1396. protected function ConvertSubColor($c)
  1397. {
  1398. if (substr($c, -1)=='%') $c = floatVal(substr($c, 0, -1))/100.;
  1399. else
  1400. {
  1401. $c = floatVal($c);
  1402. if ($c>1) $c = $c/255.;
  1403. }
  1404. return $c;
  1405. }
  1406. /**
  1407. * Analyser une feuille de style
  1408. *
  1409. * @param string code CSS
  1410. * @return null
  1411. */
  1412. protected function analyseStyle(&$code)
  1413. {
  1414. // on remplace tous les espaces, tab, \r, \n, par des espaces uniques
  1415. $code = preg_replace('/[\s]+/', ' ', $code);
  1416. // on enl?ve les commentaires
  1417. $code = preg_replace('/\/\*.*?\*\//s', '', $code);
  1418. // on analyse chaque style
  1419. preg_match_all('/([^{}]+){([^}]*)}/isU', $code, $match);
  1420. for($k=0; $k<count($match[0]); $k++)
  1421. {
  1422. // noms
  1423. $noms = strtolower(trim($match[1][$k]));
  1424. // style, séparé par des; => on remplie le tableau correspondant
  1425. $styles = trim($match[2][$k]);
  1426. $styles = explode(';', $styles);
  1427. $stl = array();
  1428. foreach($styles as $style)
  1429. {
  1430. $tmp = explode(':', $style);
  1431. if (count($tmp)>1)
  1432. {
  1433. $cod = $tmp[0]; unset($tmp[0]); $tmp = implode(':', $tmp);
  1434. $stl[trim(strtolower($cod))] = trim($tmp);
  1435. }
  1436. }
  1437. // décomposition des noms par les ,
  1438. $noms = explode(',', $noms);
  1439. foreach($noms as $nom)
  1440. {
  1441. $nom = trim($nom);
  1442. // Si il a une fonction spécifique, comme :hover => on zap
  1443. if (strpos($nom, ':')!==false) cont

Large files files are truncated, but you can click here to view the full file