PageRenderTime 88ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/include/html2pdf_v4.03/html2pdf.class.php

https://bitbucket.org/sleininger/stock_online
PHP | 6488 lines | 3863 code | 964 blank | 1661 comment | 732 complexity | cb436125a2986a184266a5b4e82cd42e MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0
  1. <?php
  2. /**
  3. * HTML2PDF Librairy - main class
  4. *
  5. * HTML => PDF convertor
  6. * distributed under the LGPL License
  7. *
  8. * @author Laurent MINGUET <webmaster@html2pdf.fr>
  9. * @version 4.03
  10. */
  11. if (!defined('__CLASS_HTML2PDF__')) {
  12. define('__CLASS_HTML2PDF__', '4.03');
  13. define('HTML2PDF_USED_TCPDF_VERSION', '5.0.002');
  14. require_once(dirname(__FILE__).'/_class/exception.class.php');
  15. require_once(dirname(__FILE__).'/_class/locale.class.php');
  16. require_once(dirname(__FILE__).'/_class/myPdf.class.php');
  17. require_once(dirname(__FILE__).'/_class/parsingHtml.class.php');
  18. require_once(dirname(__FILE__).'/_class/parsingCss.class.php');
  19. class HTML2PDF
  20. {
  21. /**
  22. * HTML2PDF_myPdf object, extends from TCPDF
  23. * @var HTML2PDF_myPdf
  24. */
  25. public $pdf = null;
  26. /**
  27. * CSS parsing
  28. * @var HTML2PDF_parsingCss
  29. */
  30. public $parsingCss = null;
  31. /**
  32. * HTML parsing
  33. * @var HTML2PDF_parsingHtml
  34. */
  35. public $parsingHtml = null;
  36. protected $_langue = 'fr'; // locale of the messages
  37. protected $_orientation = 'P'; // page orientation : Portrait ou Landscape
  38. protected $_format = 'A4'; // page format : A4, A3, ...
  39. protected $_encoding = ''; // charset encoding
  40. protected $_unicode = true; // means that the input text is unicode (default = true)
  41. protected $_testTdInOnepage = true; // test of TD that can not take more than one page
  42. protected $_testIsImage = true; // test if the images exist or not
  43. protected $_testIsDeprecated = false; // test the deprecated functions
  44. protected $_parsePos = 0; // position in the parsing
  45. protected $_tempPos = 0; // temporary position for complex table
  46. protected $_page = 0; // current page number
  47. protected $_subHtml = null; // sub html
  48. protected $_subPart = false; // sub HTML2PDF
  49. protected $_subHEADER = array(); // sub action to make the header
  50. protected $_subFOOTER = array(); // sub action to make the footer
  51. protected $_subSTATES = array(); // array to save some parameters
  52. protected $_isSubPart = false; // flag : in a sub html2pdf
  53. protected $_isInThead = false; // flag : in a thead
  54. protected $_isInTfoot = false; // flag : in a tfoot
  55. protected $_isInOverflow = false; // flag : in a overflow
  56. protected $_isInFooter = false; // flag : in a footer
  57. protected $_isInDraw = null; // flag : in a draw (svg)
  58. protected $_isAfterFloat = false; // flag : is just after a float
  59. protected $_isInForm = false; // flag : is in a float. false / action of the form
  60. protected $_isInLink = ''; // flag : is in a link. empty / href of the link
  61. protected $_isInParagraph = false; // flag : is in a paragraph
  62. protected $_isForOneLine = false; // flag : in a specific sub html2pdf to have the height of the next line
  63. protected $_maxX = 0; // maximum X of the current zone
  64. protected $_maxY = 0; // maximum Y of the current zone
  65. protected $_maxE = 0; // number of elements in the current zone
  66. protected $_maxH = 0; // maximum height of the line in the current zone
  67. protected $_maxSave = array(); // save the maximums of the current zone
  68. protected $_currentH = 0; // height of the current line
  69. protected $_defaultLeft = 0; // default marges of the page
  70. protected $_defaultTop = 0;
  71. protected $_defaultRight = 0;
  72. protected $_defaultBottom = 0;
  73. protected $_defaultFont = null; // default font to use, is the asked font does not exist
  74. protected $_margeLeft = 0; // current marges of the page
  75. protected $_margeTop = 0;
  76. protected $_margeRight = 0;
  77. protected $_margeBottom = 0;
  78. protected $_marges = array(); // save the different marges of the current page
  79. protected $_pageMarges = array(); // float marges of the current page
  80. protected $_background = array(); // background informations
  81. protected $_firstPage = true; // flag : first page
  82. protected $_defList = array(); // table to save the stats of the tags UL and OL
  83. protected $_lstAnchor = array(); // list of the anchors
  84. protected $_lstField = array(); // list of the fields
  85. protected $_lstSelect = array(); // list of the options of the current select
  86. protected $_previousCall = null; // last action called
  87. protected $_debugActif = false; // flag : mode debug is active
  88. protected $_debugOkUsage = false; // flag : the function memory_get_usage exist
  89. protected $_debugOkPeak = false; // flag : the function memory_get_peak_usage exist
  90. protected $_debugLevel = 0; // level in the debug
  91. protected $_debugStartTime = 0; // debug start time
  92. protected $_debugLastTime = 0; // debug stop time
  93. static protected $_subobj = null; // object html2pdf prepared in order to accelerate the creation of sub html2pdf
  94. static protected $_tables = array(); // static table to prepare the nested html tables
  95. /**
  96. * class constructor
  97. *
  98. * @access public
  99. * @param string $orientation page orientation, same as TCPDF
  100. * @param mixed $format The format used for pages, same as TCPDF
  101. * @param $tring $langue Langue : fr, en, it...
  102. * @param boolean $unicode TRUE means that the input text is unicode (default = true)
  103. * @param String $encoding charset encoding; default is UTF-8
  104. * @param array $marges Default marges (left, top, right, bottom)
  105. * @return HTML2PDF $this
  106. */
  107. public function __construct($orientation = 'P', $format = 'A4', $langue='fr', $unicode=true, $encoding='UTF-8', $marges = array(5, 5, 5, 8))
  108. {
  109. // init the page number
  110. $this->_page = 0;
  111. $this->_firstPage = true;
  112. // save the parameters
  113. $this->_orientation = $orientation;
  114. $this->_format = $format;
  115. $this->_langue = strtolower($langue);
  116. $this->_unicode = $unicode;
  117. $this->_encoding = $encoding;
  118. // load the Local
  119. HTML2PDF_locale::load($this->_langue);
  120. // create the HTML2PDF_myPdf object
  121. $this->pdf = new HTML2PDF_myPdf($orientation, 'mm', $format, $unicode, $encoding);
  122. // init the CSS parsing object
  123. $this->parsingCss = new HTML2PDF_parsingCss($this->pdf);
  124. $this->parsingCss->fontSet();
  125. $this->_defList = array();
  126. // init some tests
  127. $this->setTestTdInOnePage(true);
  128. $this->setTestIsImage(true);
  129. $this->setTestIsDeprecated(true);
  130. // init the default font
  131. $this->setDefaultFont(null);
  132. // init the HTML parsing object
  133. $this->parsingHtml = new HTML2PDF_parsingHtml($this->_encoding);
  134. $this->_subHtml = null;
  135. $this->_subPart = false;
  136. // init the marges of the page
  137. if (!is_array($marges)) $marges = array($marges, $marges, $marges, $marges);
  138. $this->_setDefaultMargins($marges[0], $marges[1], $marges[2], $marges[3]);
  139. $this->_setMargins();
  140. $this->_marges = array();
  141. // init the form's fields
  142. $this->_lstField = array();
  143. return $this;
  144. }
  145. /**
  146. * Destructor
  147. *
  148. * @access public
  149. * @return null
  150. */
  151. public function __destruct()
  152. {
  153. }
  154. /**
  155. * Clone to create a sub HTML2PDF from HTML2PDF::$_subobj
  156. *
  157. * @access public
  158. */
  159. public function __clone()
  160. {
  161. $this->pdf = clone $this->pdf;
  162. $this->parsingHtml = clone $this->parsingHtml;
  163. $this->parsingCss = clone $this->parsingCss;
  164. $this->parsingCss->setPdfParent($this->pdf);
  165. }
  166. /**
  167. * set the debug mode to On
  168. *
  169. * @access public
  170. * @return HTML2PDF $this
  171. */
  172. public function setModeDebug()
  173. {
  174. $time = microtime(true);
  175. $this->_debugActif = true;
  176. $this->_debugOkUsage = function_exists('memory_get_usage');
  177. $this->_debugOkPeak = function_exists('memory_get_peak_usage');
  178. $this->_debugStartTime = $time;
  179. $this->_debugLastTime = $time;
  180. $this->_DEBUG_stepline('step', 'time', 'delta', 'memory', 'peak');
  181. $this->_DEBUG_add('Init debug');
  182. return $this;
  183. }
  184. /**
  185. * Set the test of TD thdat can not take more than one page
  186. *
  187. * @access public
  188. * @param boolean $mode
  189. * @return HTML2PDF $this
  190. */
  191. public function setTestTdInOnePage($mode = true)
  192. {
  193. $this->_testTdInOnepage = $mode ? true : false;
  194. return $this;
  195. }
  196. /**
  197. * Set the test if the images exist or not
  198. *
  199. * @access public
  200. * @param boolean $mode
  201. * @return HTML2PDF $this
  202. */
  203. public function setTestIsImage($mode = true)
  204. {
  205. $this->_testIsImage = $mode ? true : false;
  206. return $this;
  207. }
  208. /**
  209. * Set the test on deprecated functions
  210. *
  211. * @access public
  212. * @param boolean $mode
  213. * @return HTML2PDF $this
  214. */
  215. public function setTestIsDeprecated($mode = true)
  216. {
  217. $this->_testIsDeprecated = $mode ? true : false;
  218. return $this;
  219. }
  220. /**
  221. * Set the default font to use, if no font is specify, or if the asked font does not exist
  222. *
  223. * @access public
  224. * @param string $default name of the default font to use. If null : Arial is no font is specify, and error if the asked font does not exist
  225. * @return HTML2PDF $this
  226. */
  227. public function setDefaultFont($default = null)
  228. {
  229. $this->_defaultFont = $default;
  230. $this->parsingCss->setDefaultFont($default);
  231. return $this;
  232. }
  233. /**
  234. * add a font, see TCPDF function addFont
  235. *
  236. * @access public
  237. * @param string $family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.
  238. * @param string $style Font style. Possible values are (case insensitive):<ul><li>empty string: regular (default)</li><li>B: bold</li><li>I: italic</li><li>BI or IB: bold italic</li></ul>
  239. * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
  240. * @return HTML2PDF $this
  241. * @see TCPDF::addFont
  242. */
  243. public function addFont($family, $style='', $file='')
  244. {
  245. $this->pdf->AddFont($family, $style, $file);
  246. return $this;
  247. }
  248. /**
  249. * display a automatic index, from the bookmarks
  250. *
  251. * @access public
  252. * @param string $titre index title
  253. * @param int $sizeTitle font size of the index title, in mm
  254. * @param int $sizeBookmark font size of the index, in mm
  255. * @param boolean $bookmarkTitle add a bookmark for the index, at his beginning
  256. * @param boolean $displayPage display the page numbers
  257. * @param int $onPage if null : at the end of the document on a new page, else on the $onPage page
  258. * @param string $fontName font name to use
  259. * @return null
  260. */
  261. public function createIndex($titre = 'Index', $sizeTitle = 20, $sizeBookmark = 15, $bookmarkTitle = true, $displayPage = true, $onPage = null, $fontName = 'helvetica')
  262. {
  263. $oldPage = $this->_INDEX_NewPage($onPage);
  264. $this->pdf->createIndex($this, $titre, $sizeTitle, $sizeBookmark, $bookmarkTitle, $displayPage, $onPage, $fontName);
  265. if ($oldPage) $this->pdf->setPage($oldPage);
  266. }
  267. /**
  268. * clean up the objects
  269. *
  270. * @access protected
  271. */
  272. protected function _cleanUp()
  273. {
  274. HTML2PDF::$_subobj = null;
  275. HTML2PDF::$_tables = array();
  276. }
  277. /**
  278. * Send the document to a given destination: string, local file or browser.
  279. * Dest can be :
  280. * I : send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.
  281. * D : send to the browser and force a file download with the name given by name.
  282. * F : save to a local server file with the name given by name.
  283. * S : return the document as a string. name is ignored.
  284. * FI: equivalent to F + I option
  285. * FD: equivalent to F + D option
  286. * true => I
  287. * false => S
  288. *
  289. * @param string $name The name of the file when saved.
  290. * @param string $dest Destination where to send the document.
  291. * @return string content of the PDF, if $dest=S
  292. * @see TCPDF::close
  293. * @access public
  294. */
  295. public function Output($name = '', $dest = false)
  296. {
  297. // close the pdf and clean up
  298. $this->_cleanUp();
  299. // if on debug mode
  300. if ($this->_debugActif) {
  301. $this->_DEBUG_add('Before output');
  302. $this->pdf->Close();
  303. exit;
  304. }
  305. // complete parameters
  306. if ($dest===false) $dest = 'I';
  307. if ($dest===true) $dest = 'S';
  308. if ($dest==='') $dest = 'I';
  309. if ($name=='') $name='document.pdf';
  310. // clean up the destination
  311. $dest = strtoupper($dest);
  312. if (!in_array($dest, array('I', 'D', 'F', 'S', 'FI','FD'))) $dest = 'I';
  313. // the name must be a PDF name
  314. if (strtolower(substr($name, -4))!='.pdf') {
  315. throw new HTML2PDF_exception(0, 'The output document name "'.$name.'" is not a PDF name');
  316. }
  317. // call the output of TCPDF
  318. return $this->pdf->Output($name, $dest);
  319. }
  320. /**
  321. * convert HTML to PDF
  322. *
  323. * @access public
  324. * @param string $html
  325. * @param boolean $debugVue enable the HTML debug vue
  326. * @return null
  327. */
  328. public function writeHTML($html, $debugVue = false)
  329. {
  330. // if it is a real html page, we have to convert it
  331. if (preg_match('/<body/isU', $html))
  332. $html = $this->getHtmlFromPage($html);
  333. $html = str_replace('[[date_y]]', date('Y'), $html);
  334. $html = str_replace('[[date_m]]', date('m'), $html);
  335. $html = str_replace('[[date_d]]', date('d'), $html);
  336. $html = str_replace('[[date_h]]', date('H'), $html);
  337. $html = str_replace('[[date_i]]', date('i'), $html);
  338. $html = str_replace('[[date_s]]', date('s'), $html);
  339. // If we are in HTML debug vue : display the HTML
  340. if ($debugVue) {
  341. return $this->_vueHTML($html);
  342. }
  343. // convert HTMl to PDF
  344. $this->parsingCss->readStyle($html);
  345. $this->parsingHtml->setHTML($html);
  346. $this->parsingHtml->parse();
  347. $this->_makeHTMLcode();
  348. }
  349. /**
  350. * convert the HTML of a real page, to a code adapted to HTML2PDF
  351. *
  352. * @access public
  353. * @param string HTML of a real page
  354. * @return string HTML adapted to HTML2PDF
  355. */
  356. public function getHtmlFromPage($html)
  357. {
  358. $html = str_replace('<BODY', '<body', $html);
  359. $html = str_replace('</BODY', '</body', $html);
  360. // extract the content
  361. $res = explode('<body', $html);
  362. if (count($res)<2) return $html;
  363. $content = '<page'.$res[1];
  364. $content = explode('</body', $content);
  365. $content = $content[0].'</page>';
  366. // extract the link tags
  367. preg_match_all('/<link([^>]*)>/isU', $html, $match);
  368. foreach ($match[0] as $src)
  369. $content = $src.'</link>'.$content;
  370. // extract the css style tags
  371. preg_match_all('/<style[^>]*>(.*)<\/style[^>]*>/isU', $html, $match);
  372. foreach ($match[0] as $src)
  373. $content = $src.$content;
  374. return $content;
  375. }
  376. /**
  377. * init a sub HTML2PDF. does not use it directly. Only the method createSubHTML must use it
  378. *
  379. * @access public
  380. * @param string $format
  381. * @param string $orientation
  382. * @param array $marge
  383. * @param integer $page
  384. * @param array $defLIST
  385. * @param integer $myLastPageGroup
  386. * @param integer $myLastPageGroupNb
  387. */
  388. public function initSubHtml($format, $orientation, $marge, $page, $defLIST, $myLastPageGroup, $myLastPageGroupNb)
  389. {
  390. $this->_isSubPart = true;
  391. $this->parsingCss->setOnlyLeft();
  392. $this->_setNewPage($format, $orientation, null, null, ($myLastPageGroup!==null));
  393. $this->_saveMargin(0, 0, $marge);
  394. $this->_defList = $defLIST;
  395. $this->_page = $page;
  396. $this->pdf->setMyLastPageGroup($myLastPageGroup);
  397. $this->pdf->setMyLastPageGroupNb($myLastPageGroupNb);
  398. $this->pdf->setXY(0, 0);
  399. $this->parsingCss->fontSet();
  400. }
  401. /**
  402. * display the content in HTML moden for debug
  403. *
  404. * @access protected
  405. * @param string $contenu
  406. */
  407. protected function _vueHTML($content)
  408. {
  409. $content = preg_replace('/<page_header([^>]*)>/isU', '<hr>'.HTML2PDF_locale::get('vue01').' : $1<hr><div$1>', $content);
  410. $content = preg_replace('/<page_footer([^>]*)>/isU', '<hr>'.HTML2PDF_locale::get('vue02').' : $1<hr><div$1>', $content);
  411. $content = preg_replace('/<page([^>]*)>/isU', '<hr>'.HTML2PDF_locale::get('vue03').' : $1<hr><div$1>', $content);
  412. $content = preg_replace('/<\/page([^>]*)>/isU', '</div><hr>', $content);
  413. $content = preg_replace('/<bookmark([^>]*)>/isU', '<hr>bookmark : $1<hr>', $content);
  414. $content = preg_replace('/<\/bookmark([^>]*)>/isU', '', $content);
  415. $content = preg_replace('/<barcode([^>]*)>/isU', '<hr>barcode : $1<hr>', $content);
  416. $content = preg_replace('/<\/barcode([^>]*)>/isU', '', $content);
  417. $content = preg_replace('/<qrcode([^>]*)>/isU', '<hr>qrcode : $1<hr>', $content);
  418. $content = preg_replace('/<\/qrcode([^>]*)>/isU', '', $content);
  419. echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  420. <html>
  421. <head>
  422. <title>'.HTML2PDF_locale::get('vue04').' HTML</title>
  423. <meta http-equiv="Content-Type" content="text/html; charset='.$this->_encoding.'" >
  424. </head>
  425. <body style="padding: 10px; font-size: 10pt;font-family: Verdana;">
  426. '.$content.'
  427. </body>
  428. </html>';
  429. exit;
  430. }
  431. /**
  432. * set the default margins of the page
  433. *
  434. * @access protected
  435. * @param int $left (mm, left margin)
  436. * @param int $top (mm, top margin)
  437. * @param int $right (mm, right margin, if null => left=right)
  438. * @param int $bottom (mm, bottom margin, if null => bottom=8mm)
  439. */
  440. protected function _setDefaultMargins($left, $top, $right = null, $bottom = null)
  441. {
  442. if ($right===null) $right = $left;
  443. if ($bottom===null) $bottom = 8;
  444. $this->_defaultLeft = $this->parsingCss->ConvertToMM($left.'mm');
  445. $this->_defaultTop = $this->parsingCss->ConvertToMM($top.'mm');
  446. $this->_defaultRight = $this->parsingCss->ConvertToMM($right.'mm');
  447. $this->_defaultBottom = $this->parsingCss->ConvertToMM($bottom.'mm');
  448. }
  449. /**
  450. * create a new page
  451. *
  452. * @access protected
  453. * @param mixed $format
  454. * @param string $orientation
  455. * @param array $background background information
  456. * @param integer $curr real position in the html parseur (if break line in the write of a text)
  457. * @param boolean $resetPageNumber
  458. */
  459. protected function _setNewPage($format = null, $orientation = '', $background = null, $curr = null, $resetPageNumber=false)
  460. {
  461. $this->_firstPage = false;
  462. $this->_format = $format ? $format : $this->_format;
  463. $this->_orientation = $orientation ? $orientation : $this->_orientation;
  464. $this->_background = $background!==null ? $background : $this->_background;
  465. $this->_maxY = 0;
  466. $this->_maxX = 0;
  467. $this->_maxH = 0;
  468. $this->_maxE = 0;
  469. $this->pdf->SetMargins($this->_defaultLeft, $this->_defaultTop, $this->_defaultRight);
  470. if ($resetPageNumber) {
  471. $this->pdf->startPageGroup();
  472. }
  473. $this->pdf->AddPage($this->_orientation, $this->_format);
  474. if ($resetPageNumber) {
  475. $this->pdf->myStartPageGroup();
  476. }
  477. $this->_page++;
  478. if (!$this->_subPart && !$this->_isSubPart) {
  479. if (is_array($this->_background)) {
  480. if (isset($this->_background['color']) && $this->_background['color']) {
  481. $this->pdf->setFillColorArray($this->_background['color']);
  482. $this->pdf->Rect(0, 0, $this->pdf->getW(), $this->pdf->getH(), 'F');
  483. }
  484. if (isset($this->_background['img']) && $this->_background['img'])
  485. $this->pdf->Image($this->_background['img'], $this->_background['posX'], $this->_background['posY'], $this->_background['width']);
  486. }
  487. $this->_setPageHeader();
  488. $this->_setPageFooter();
  489. }
  490. $this->_setMargins();
  491. $this->pdf->setY($this->_margeTop);
  492. $this->_setNewPositionForNewLine($curr);
  493. $this->_maxH = 0;
  494. }
  495. /**
  496. * set the real margin, using the default margins and the page margins
  497. *
  498. * @access protected
  499. */
  500. protected function _setMargins()
  501. {
  502. // prepare the margins
  503. $this->_margeLeft = $this->_defaultLeft + (isset($this->_background['left']) ? $this->_background['left'] : 0);
  504. $this->_margeRight = $this->_defaultRight + (isset($this->_background['right']) ? $this->_background['right'] : 0);
  505. $this->_margeTop = $this->_defaultTop + (isset($this->_background['top']) ? $this->_background['top'] : 0);
  506. $this->_margeBottom = $this->_defaultBottom + (isset($this->_background['bottom']) ? $this->_background['bottom'] : 0);
  507. // set the PDF margins
  508. $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
  509. $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
  510. // set the float Margins
  511. $this->_pageMarges = array();
  512. if ($this->_isInParagraph!==false) {
  513. $this->_pageMarges[floor($this->_margeTop*100)] = array($this->_isInParagraph[0], $this->pdf->getW()-$this->_isInParagraph[1]);
  514. } else {
  515. $this->_pageMarges[floor($this->_margeTop*100)] = array($this->_margeLeft, $this->pdf->getW()-$this->_margeRight);
  516. }
  517. }
  518. /**
  519. * add a debug step
  520. *
  521. * @access protected
  522. * @param string $name step name
  523. * @param boolean $level (true=up, false=down, null=nothing to do)
  524. * @return $this
  525. */
  526. protected function _DEBUG_add($name, $level=null)
  527. {
  528. // if true : UP
  529. if ($level===true) $this->_debugLevel++;
  530. $name = str_repeat(' ', $this->_debugLevel). $name.($level===true ? ' Begin' : ($level===false ? ' End' : ''));
  531. $time = microtime(true);
  532. $usage = ($this->_debugOkUsage ? memory_get_usage() : 0);
  533. $peak = ($this->_debugOkPeak ? memory_get_peak_usage() : 0);
  534. $this->_DEBUG_stepline(
  535. $name,
  536. number_format(($time - $this->_debugStartTime)*1000, 1, '.', ' ').' ms',
  537. number_format(($time - $this->_debugLastTime)*1000, 1, '.', ' ').' ms',
  538. number_format($usage/1024, 1, '.', ' ').' Ko',
  539. number_format($peak/1024, 1, '.', ' ').' Ko'
  540. );
  541. $this->_debugLastTime = $time;
  542. // it false : DOWN
  543. if ($level===false) $this->_debugLevel--;
  544. return $this;
  545. }
  546. /**
  547. * display a debug line
  548. *
  549. *
  550. * @access protected
  551. * @param string $name
  552. * @param string $timeTotal
  553. * @param string $timeStep
  554. * @param string $memoryUsage
  555. * @param string $memoryPeak
  556. */
  557. protected function _DEBUG_stepline($name, $timeTotal, $timeStep, $memoryUsage, $memoryPeak)
  558. {
  559. $txt = str_pad($name, 30, ' ', STR_PAD_RIGHT).
  560. str_pad($timeTotal, 12, ' ', STR_PAD_LEFT).
  561. str_pad($timeStep, 12, ' ', STR_PAD_LEFT).
  562. str_pad($memoryUsage, 15, ' ', STR_PAD_LEFT).
  563. str_pad($memoryPeak, 15, ' ', STR_PAD_LEFT);
  564. echo '<pre style="padding:0; margin:0">'.$txt.'</pre>';
  565. }
  566. /**
  567. * get the Min and Max X, for Y (use the float margins)
  568. *
  569. * @access protected
  570. * @param float $y
  571. * @return array(float, float)
  572. */
  573. protected function _getMargins($y)
  574. {
  575. $y = floor($y*100);
  576. $x = array($this->pdf->getlMargin(), $this->pdf->getW()-$this->pdf->getrMargin());
  577. foreach ($this->_pageMarges as $mY => $mX)
  578. if ($mY<=$y) $x = $mX;
  579. return $x;
  580. }
  581. /**
  582. * Add margins, for a float
  583. *
  584. * @access protected
  585. * @param string $float (left / right)
  586. * @param float $xLeft
  587. * @param float $yTop
  588. * @param float $xRight
  589. * @param float $yBottom
  590. */
  591. protected function _addMargins($float, $xLeft, $yTop, $xRight, $yBottom)
  592. {
  593. // get the current float margins, for top and bottom
  594. $oldTop = $this->_getMargins($yTop);
  595. $oldBottom = $this->_getMargins($yBottom);
  596. // update the top float margin
  597. if ($float=='left' && $oldTop[0]<$xRight) $oldTop[0] = $xRight;
  598. if ($float=='right' && $oldTop[1]>$xLeft) $oldTop[1] = $xLeft;
  599. $yTop = floor($yTop*100);
  600. $yBottom = floor($yBottom*100);
  601. // erase all the float margins that are smaller than the new one
  602. foreach ($this->_pageMarges as $mY => $mX) {
  603. if ($mY<$yTop) continue;
  604. if ($mY>$yBottom) break;
  605. if ($float=='left' && $this->_pageMarges[$mY][0]<$xRight) unset($this->_pageMarges[$mY]);
  606. if ($float=='right' && $this->_pageMarges[$mY][1]>$xLeft) unset($this->_pageMarges[$mY]);
  607. }
  608. // save the new Top and Bottom margins
  609. $this->_pageMarges[$yTop] = $oldTop;
  610. $this->_pageMarges[$yBottom] = $oldBottom;
  611. // sort the margins
  612. ksort($this->_pageMarges);
  613. // we are just after float
  614. $this->_isAfterFloat = true;
  615. }
  616. /**
  617. * Save old margins (push), and set new ones
  618. *
  619. * @access protected
  620. * @param float $ml left margin
  621. * @param float $mt top margin
  622. * @param float $mr right margin
  623. */
  624. protected function _saveMargin($ml, $mt, $mr)
  625. {
  626. // save old margins
  627. $this->_marges[] = array('l' => $this->pdf->getlMargin(), 't' => $this->pdf->gettMargin(), 'r' => $this->pdf->getrMargin(), 'page' => $this->_pageMarges);
  628. // set new ones
  629. $this->pdf->SetMargins($ml, $mt, $mr);
  630. // prepare for float margins
  631. $this->_pageMarges = array();
  632. $this->_pageMarges[floor($mt*100)] = array($ml, $this->pdf->getW()-$mr);
  633. }
  634. /**
  635. * load the last saved margins (pop)
  636. *
  637. * @access protected
  638. */
  639. protected function _loadMargin()
  640. {
  641. $old = array_pop($this->_marges);
  642. if ($old) {
  643. $ml = $old['l'];
  644. $mt = $old['t'];
  645. $mr = $old['r'];
  646. $mP = $old['page'];
  647. } else {
  648. $ml = $this->_margeLeft;
  649. $mt = 0;
  650. $mr = $this->_margeRight;
  651. $mP = array($mt => array($ml, $this->pdf->getW()-$mr));
  652. }
  653. $this->pdf->SetMargins($ml, $mt, $mr);
  654. $this->_pageMarges = $mP;
  655. }
  656. /**
  657. * save the current maxs (push)
  658. *
  659. * @access protected
  660. */
  661. protected function _saveMax()
  662. {
  663. $this->_maxSave[] = array($this->_maxX, $this->_maxY, $this->_maxH, $this->_maxE);
  664. }
  665. /**
  666. * load the last saved current maxs (pop)
  667. *
  668. * @access protected
  669. */
  670. protected function _loadMax()
  671. {
  672. $old = array_pop($this->_maxSave);
  673. if ($old) {
  674. $this->_maxX = $old[0];
  675. $this->_maxY = $old[1];
  676. $this->_maxH = $old[2];
  677. $this->_maxE = $old[3];
  678. } else {
  679. $this->_maxX = 0;
  680. $this->_maxY = 0;
  681. $this->_maxH = 0;
  682. $this->_maxE = 0;
  683. }
  684. }
  685. /**
  686. * draw the PDF header with the HTML in page_header
  687. *
  688. * @access protected
  689. */
  690. protected function _setPageHeader()
  691. {
  692. if (!count($this->_subHEADER)) return false;
  693. $oldParsePos = $this->_parsePos;
  694. $oldParseCode = $this->parsingHtml->code;
  695. $this->_parsePos = 0;
  696. $this->parsingHtml->code = $this->_subHEADER;
  697. $this->_makeHTMLcode();
  698. $this->_parsePos = $oldParsePos;
  699. $this->parsingHtml->code = $oldParseCode;
  700. }
  701. /**
  702. * draw the PDF footer with the HTML in page_footer
  703. *
  704. * @access protected
  705. */
  706. protected function _setPageFooter()
  707. {
  708. if (!count($this->_subFOOTER)) return false;
  709. $oldParsePos = $this->_parsePos;
  710. $oldParseCode = $this->parsingHtml->code;
  711. $this->_parsePos = 0;
  712. $this->parsingHtml->code = $this->_subFOOTER;
  713. $this->_isInFooter = true;
  714. $this->_makeHTMLcode();
  715. $this->_isInFooter = false;
  716. $this->_parsePos = $oldParsePos;
  717. $this->parsingHtml->code = $oldParseCode;
  718. }
  719. /**
  720. * new line, with a specific height
  721. *
  722. * @access protected
  723. * @param float $h
  724. * @param integer $curr real current position in the text, if new line in the write of a text
  725. */
  726. protected function _setNewLine($h, $curr = null)
  727. {
  728. $this->pdf->Ln($h);
  729. $this->_setNewPositionForNewLine($curr);
  730. }
  731. /**
  732. * calculate the start position of the next line, depending on the text-align
  733. *
  734. * @access protected
  735. * @param integer $curr real current position in the text, if new line in the write of a text
  736. */
  737. protected function _setNewPositionForNewLine($curr = null)
  738. {
  739. // get the margins for the current line
  740. list($lx, $rx) = $this->_getMargins($this->pdf->getY());
  741. $this->pdf->setX($lx);
  742. $wMax = $rx-$lx;
  743. $this->_currentH = 0;
  744. // if subPart => return because align left
  745. if ($this->_subPart || $this->_isSubPart || $this->_isForOneLine) {
  746. $this->pdf->setWordSpacing(0);
  747. return null;
  748. }
  749. // create the sub object
  750. $sub = null;
  751. $this->_createSubHTML($sub);
  752. $sub->_saveMargin(0, 0, $sub->pdf->getW()-$wMax);
  753. $sub->_isForOneLine = true;
  754. $sub->_parsePos = $this->_parsePos;
  755. $sub->parsingHtml->code = $this->parsingHtml->code;
  756. // if $curr => adapt the current position of the parsing
  757. if ($curr!==null && $sub->parsingHtml->code[$this->_parsePos]['name']=='write') {
  758. $txt = $sub->parsingHtml->code[$this->_parsePos]['param']['txt'];
  759. $txt = str_replace('[[page_cu]]', $sub->pdf->getMyNumPage($this->_page), $txt);
  760. $sub->parsingHtml->code[$this->_parsePos]['param']['txt'] = substr($txt, $curr+1);
  761. } else
  762. $sub->_parsePos++;
  763. // for each element of the parsing => load the action
  764. $res = null;
  765. for ($sub->_parsePos; $sub->_parsePos<count($sub->parsingHtml->code); $sub->_parsePos++) {
  766. $action = $sub->parsingHtml->code[$sub->_parsePos];
  767. $res = $sub->_executeAction($action);
  768. if (!$res) break;
  769. }
  770. $w = $sub->_maxX; // max width
  771. $h = $sub->_maxH; // max height
  772. $e = ($res===null ? $sub->_maxE : 0); // maxnumber of elemets on the line
  773. // destroy the sub HTML
  774. $this->_destroySubHTML($sub);
  775. // adapt the start of the line, depending on the text-align
  776. if ($this->parsingCss->value['text-align']=='center')
  777. $this->pdf->setX(($rx+$this->pdf->getX()-$w)*0.5-0.01);
  778. else if ($this->parsingCss->value['text-align']=='right')
  779. $this->pdf->setX($rx-$w-0.01);
  780. else
  781. $this->pdf->setX($lx);
  782. // set the height of the line
  783. $this->_currentH = $h;
  784. // if justify => set the word spacing
  785. if ($this->parsingCss->value['text-align']=='justify' && $e>1) {
  786. $this->pdf->setWordSpacing(($wMax-$w)/($e-1));
  787. } else {
  788. $this->pdf->setWordSpacing(0);
  789. }
  790. }
  791. /**
  792. * prepare HTML2PDF::$_subobj (used for create the sub HTML2PDF objects
  793. *
  794. * @access protected
  795. */
  796. protected function _prepareSubObj()
  797. {
  798. $pdf = null;
  799. // create the sub object
  800. HTML2PDF::$_subobj = new HTML2PDF(
  801. $this->_orientation,
  802. $this->_format,
  803. $this->_langue,
  804. $this->_unicode,
  805. $this->_encoding,
  806. array($this->_defaultLeft,$this->_defaultTop,$this->_defaultRight,$this->_defaultBottom)
  807. );
  808. // init
  809. HTML2PDF::$_subobj->setTestTdInOnePage($this->_testTdInOnepage);
  810. HTML2PDF::$_subobj->setTestIsImage($this->_testIsImage);
  811. HTML2PDF::$_subobj->setTestIsDeprecated($this->_testIsDeprecated);
  812. HTML2PDF::$_subobj->setDefaultFont($this->_defaultFont);
  813. HTML2PDF::$_subobj->parsingCss->css = &$this->parsingCss->css;
  814. HTML2PDF::$_subobj->parsingCss->cssKeys = &$this->parsingCss->cssKeys;
  815. // clone font from the original PDF
  816. HTML2PDF::$_subobj->pdf->cloneFontFrom($this->pdf);
  817. // remove the link to the parent
  818. HTML2PDF::$_subobj->parsingCss->setPdfParent($pdf);
  819. }
  820. /**
  821. * create a sub HTML2PDF, to calculate the multi-tables
  822. *
  823. * @access protected
  824. * @param &HTML2PDF $subHtml sub HTML2PDF to create
  825. * @param integer $cellmargin if in a TD : cellmargin of this td
  826. */
  827. protected function _createSubHTML(&$subHtml, $cellmargin=0)
  828. {
  829. // prepare the subObject, if never prepare before
  830. if (HTML2PDF::$_subobj===null) {
  831. $this->_prepareSubObj();
  832. }
  833. // calculate the width to use
  834. if ($this->parsingCss->value['width']) {
  835. $marge = $cellmargin*2;
  836. $marge+= $this->parsingCss->value['padding']['l'] + $this->parsingCss->value['padding']['r'];
  837. $marge+= $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['border']['r']['width'];
  838. $marge = $this->pdf->getW() - $this->parsingCss->value['width'] + $marge;
  839. } else {
  840. $marge = $this->_margeLeft+$this->_margeRight;
  841. }
  842. // BUGFIX : we have to call the method, because of a bug in php 5.1.6
  843. HTML2PDF::$_subobj->pdf->getPage();
  844. // clone the sub oject
  845. $subHtml = clone HTML2PDF::$_subobj;
  846. $subHtml->parsingCss->table = $this->parsingCss->table;
  847. $subHtml->parsingCss->value = $this->parsingCss->value;
  848. $subHtml->initSubHtml(
  849. $this->_format,
  850. $this->_orientation,
  851. $marge,
  852. $this->_page,
  853. $this->_defList,
  854. $this->pdf->getMyLastPageGroup(),
  855. $this->pdf->getMyLastPageGroupNb()
  856. );
  857. }
  858. /**
  859. * destroy a subHTML2PDF
  860. *
  861. * @access protected
  862. */
  863. protected function _destroySubHTML(&$subHtml)
  864. {
  865. unset($subHtml);
  866. $subHtml = null;
  867. }
  868. /**
  869. * Convert a arabic number in roman number
  870. *
  871. * @access protected
  872. * @param integer $nbArabic
  873. * @return string $nbRoman
  874. */
  875. protected function _listeArab2Rom($nbArabic)
  876. {
  877. $nbBaseTen = array('I','X','C','M');
  878. $nbBaseFive = array('V','L','D');
  879. $nbRoman = '';
  880. if ($nbArabic<1) return $nbArabic;
  881. if ($nbArabic>3999) return $nbArabic;
  882. for ($i=3; $i>=0 ; $i--) {
  883. $chiffre=floor($nbArabic/pow(10, $i));
  884. if ($chiffre>=1) {
  885. $nbArabic=$nbArabic-$chiffre*pow(10, $i);
  886. if ($chiffre<=3) {
  887. for ($j=$chiffre; $j>=1; $j--) {
  888. $nbRoman=$nbRoman.$nbBaseTen[$i];
  889. }
  890. } else if ($chiffre==9) {
  891. $nbRoman=$nbRoman.$nbBaseTen[$i].$nbBaseTen[$i+1];
  892. } else if ($chiffre==4) {
  893. $nbRoman=$nbRoman.$nbBaseTen[$i].$nbBaseFive[$i];
  894. } else {
  895. $nbRoman=$nbRoman.$nbBaseFive[$i];
  896. for ($j=$chiffre-5; $j>=1; $j--) {
  897. $nbRoman=$nbRoman.$nbBaseTen[$i];
  898. }
  899. }
  900. }
  901. }
  902. return $nbRoman;
  903. }
  904. /**
  905. * add a LI to the current level
  906. *
  907. * @access protected
  908. */
  909. protected function _listeAddLi()
  910. {
  911. $this->_defList[count($this->_defList)-1]['nb']++;
  912. }
  913. /**
  914. * get the width to use for the column of the list
  915. *
  916. * @access protected
  917. * @return string $width
  918. */
  919. protected function _listeGetWidth()
  920. {
  921. return '7mm';
  922. }
  923. /**
  924. * get the padding to use for the column of the list
  925. *
  926. * @access protected
  927. * @return string $padding
  928. */
  929. protected function _listeGetPadding()
  930. {
  931. return '1mm';
  932. }
  933. /**
  934. * get the information of the li on the current level
  935. *
  936. * @access protected
  937. * @return array(fontName, small size, string)
  938. */
  939. protected function _listeGetLi()
  940. {
  941. $im = $this->_defList[count($this->_defList)-1]['img'];
  942. $st = $this->_defList[count($this->_defList)-1]['style'];
  943. $nb = $this->_defList[count($this->_defList)-1]['nb'];
  944. $up = (substr($st, 0, 6)=='upper-');
  945. if ($im) return array(false, false, $im);
  946. switch($st)
  947. {
  948. case 'none':
  949. return array('helvetica', true, ' ');
  950. case 'upper-alpha':
  951. case 'lower-alpha':
  952. $str = '';
  953. while ($nb>26) {
  954. $str = chr(96+$nb%26).$str;
  955. $nb = floor($nb/26);
  956. }
  957. $str = chr(96+$nb).$str;
  958. return array('helvetica', false, ($up ? strtoupper($str) : $str).'.');
  959. case 'upper-roman':
  960. case 'lower-roman':
  961. $str = $this->_listeArab2Rom($nb);
  962. return array('helvetica', false, ($up ? strtoupper($str) : $str).'.');
  963. case 'decimal':
  964. return array('helvetica', false, $nb.'.');
  965. case 'square':
  966. return array('zapfdingbats', true, chr(110));
  967. case 'circle':
  968. return array('zapfdingbats', true, chr(109));
  969. case 'disc':
  970. default:
  971. return array('zapfdingbats', true, chr(108));
  972. }
  973. }
  974. /**
  975. * add a level to the list
  976. *
  977. * @access protected
  978. * @param string $type : ul, ol
  979. * @param string $style : lower-alpha, ...
  980. * @param string $img
  981. */
  982. protected function _listeAddLevel($type = 'ul', $style = '', $img = null)
  983. {
  984. // get the url of the image, if we want to use a image
  985. if ($img) {
  986. if (preg_match('/^url\(([^)]+)\)$/isU', trim($img), $match)) {
  987. $img = $match[1];
  988. } else {
  989. $img = null;
  990. }
  991. } else {
  992. $img = null;
  993. }
  994. // prepare the datas
  995. if (!in_array($type, array('ul', 'ol'))) $type = 'ul';
  996. if (!in_array($style, array('lower-alpha', 'upper-alpha', 'upper-roman', 'lower-roman', 'decimal', 'square', 'circle', 'disc', 'none'))) $style = '';
  997. if (!$style) {
  998. if ($type=='ul') $style = 'disc';
  999. else $style = 'decimal';
  1000. }
  1001. // add the new level
  1002. $this->_defList[count($this->_defList)] = array('style' => $style, 'nb' => 0, 'img' => $img);
  1003. }
  1004. /**
  1005. * remove a level to the list
  1006. *
  1007. * @access protected
  1008. */
  1009. protected function _listeDelLevel()
  1010. {
  1011. if (count($this->_defList)) {
  1012. unset($this->_defList[count($this->_defList)-1]);
  1013. $this->_defList = array_values($this->_defList);
  1014. }
  1015. }
  1016. /**
  1017. * execute the actions to convert the html
  1018. *
  1019. * @access protected
  1020. */
  1021. protected function _makeHTMLcode()
  1022. {
  1023. // foreach elements of the parsing
  1024. for ($this->_parsePos=0; $this->_parsePos<count($this->parsingHtml->code); $this->_parsePos++) {
  1025. // get the action to do
  1026. $action = $this->parsingHtml->code[$this->_parsePos];
  1027. // if it is a opening of table / ul / ol
  1028. if (in_array($action['name'], array('table', 'ul', 'ol')) && !$action['close']) {
  1029. // we will work as a sub HTML to calculate the size of the element
  1030. $this->_subPart = true;
  1031. // get the name of the opening tag
  1032. $tagOpen = $action['name'];
  1033. // save the actual pos on the parsing
  1034. $this->_tempPos = $this->_parsePos;
  1035. // foreach elements, while we are in the opened tag
  1036. while (isset($this->parsingHtml->code[$this->_tempPos]) && !($this->parsingHtml->code[$this->_tempPos]['name']==$tagOpen && $this->parsingHtml->code[$this->_tempPos]['close'])) {
  1037. // make the action
  1038. $this->_executeAction($this->parsingHtml->code[$this->_tempPos]);
  1039. $this->_tempPos++;
  1040. }
  1041. // execute the closure of the tag
  1042. if (isset($this->parsingHtml->code[$this->_tempPos])) {
  1043. $this->_executeAction($this->parsingHtml->code[$this->_tempPos]);
  1044. }
  1045. // end of the sub part
  1046. $this->_subPart = false;
  1047. }
  1048. // execute the action
  1049. $this->_executeAction($action);
  1050. }
  1051. }
  1052. /**
  1053. * execute the action from the parsing
  1054. *
  1055. * @access protected
  1056. * @param array $action
  1057. */
  1058. protected function _executeAction($action)
  1059. {
  1060. // name of the action
  1061. $fnc = ($action['close'] ? '_tag_close_' : '_tag_open_').strtoupper($action['name']);
  1062. // parameters of the action
  1063. $param = $action['param'];
  1064. // if it the first action of the first page, and if it is not a open tag of PAGE => create the new page
  1065. if ($fnc!='_tag_open_PAGE' && $this->_firstPage) {
  1066. $this->_setNewPage();
  1067. }
  1068. // the action must exist
  1069. if (!is_callable(array(&$this, $fnc))) {
  1070. throw new HTML2PDF_exception(1, strtoupper($action['name']), $this->parsingHtml->getHtmlErrorCode($action['html_pos']));
  1071. }
  1072. // lauch the action
  1073. $res = $this->{$fnc}($param);
  1074. // save the name of the action
  1075. $this->_previousCall = $fnc;
  1076. // return the result
  1077. return $res;
  1078. }
  1079. /**
  1080. * get the position of the element on the current line, depending on his height
  1081. *
  1082. * @access protected
  1083. * @param float $h
  1084. * @return float
  1085. */
  1086. protected function _getElementY($h)
  1087. {
  1088. if ($this->_subPart || $this->_isSubPart || !$this->_currentH || $this->_currentH<$h)
  1089. return 0;
  1090. return ($this->_currentH-$h)*0.8;
  1091. }
  1092. /**
  1093. * make a break line
  1094. *
  1095. * @access protected
  1096. * @param float $h current line height
  1097. * @param integer $curr real current position in the text, if new line in the write of a text
  1098. */
  1099. protected function _makeBreakLine($h, $curr = null)
  1100. {
  1101. if ($h) {
  1102. if (($this->pdf->getY()+$h<$this->pdf->getH() - $this->pdf->getbMargin()) || $this->_isInOverflow || $this->_isInFooter)
  1103. $this->_setNewLine($h, $curr);
  1104. else
  1105. $this->_setNewPage(null, '', null, $curr);
  1106. } else {
  1107. $this->_setNewPositionForNewLine($curr);
  1108. }
  1109. $this->_maxH = 0;
  1110. $this->_maxE = 0;
  1111. }
  1112. /**
  1113. * display a image
  1114. *
  1115. * @access protected
  1116. * @param string $src
  1117. * @param boolean $subLi if true=image of a list
  1118. * @return boolean depending on "isForOneLine"
  1119. */
  1120. protected function _drawImage($src, $subLi=false)
  1121. {
  1122. // get the size of the image
  1123. // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
  1124. $infos=@getimagesize($src);
  1125. // if the image does not exist, or can not be loaded
  1126. if (count($infos)<2) {
  1127. // if the test is activ => exception
  1128. if ($this->_testIsImage) {
  1129. throw new HTML2PDF_exception(6, $src);
  1130. }
  1131. // else, display a gray rectangle
  1132. $src = null;
  1133. $infos = array(16, 16);
  1134. }
  1135. // convert the size of the image in the unit of the PDF
  1136. $imageWidth = $infos[0]/$this->pdf->getK();
  1137. $imageHeight = $infos[1]/$this->pdf->getK();
  1138. // calculate the size from the css style
  1139. if ($this->parsingCss->value['width'] && $this->parsingCss->value['height']) {
  1140. $w = $this->parsingCss->value['width'];
  1141. $h = $this->parsingCss->value['height'];
  1142. } else if ($this->parsingCss->value['width']) {
  1143. $w = $this->parsingCss->value['width'];
  1144. $h = $imageHeight*$w/$imageWidth;
  1145. } else if ($this->parsingCss->value['height']) {
  1146. $h = $this->parsingCss->value['height'];
  1147. $w = $imageWidth*$h/$imageHeight;
  1148. } else {
  1149. // convert px to pt
  1150. $w = 72./96.*$imageWidth;
  1151. $h = 72./96.*$imageHeight;
  1152. }
  1153. // are we in a float
  1154. $float = $this->parsingCss->getFloat();
  1155. // if we are in a float, but if something else if on the line => Break Line
  1156. if ($float && $this->_maxH) {
  1157. // make the break line (false if we are in "_isForOneLine" mode)
  1158. if (!$this->_tag_open_BR(array())) {
  1159. return false;
  1160. }
  1161. }
  1162. // position of the image
  1163. $x = $this->pdf->getX();
  1164. $y = $this->pdf->getY();
  1165. // if the image can not be put on the current line => new line
  1166. if (!$float && ($x + $w>$this->pdf->getW() - $this->pdf->getrMargin()) && $this->_maxH) {
  1167. if ($this->_isForOneLine) {
  1168. return false;
  1169. }
  1170. // set the new line
  1171. $hnl = max($this->_maxH, $this->parsingCss->getLineHeight());
  1172. $this->_setNewLine($hnl);
  1173. // get the new position
  1174. $x = $this->pdf->getX();
  1175. $y = $this->pdf->getY();
  1176. }
  1177. // if the image can not be put on the current page
  1178. if (($y + $h>$this->pdf->getH() - $this->pdf->getbMargin()) && !$this->_isInOverflow) {
  1179. // new page
  1180. $this->_setNewPage();
  1181. // get the new position
  1182. $x = $this->pdf->getX();
  1183. $y = $this->pdf->getY();
  1184. }
  1185. // correction for display the image of a list
  1186. $hT = 0.80*$this->parsingCss->value['font-size'];
  1187. if ($subLi && $h<$hT) {
  1188. $y+=($hT-$h);
  1189. }
  1190. // add the margin top
  1191. $yc = $y-$this->parsingCss->value['margin']['t'];
  1192. // get the width and the position of the parent
  1193. $old = $this->parsingCss->getOldValues();
  1194. if ( $old['width']) {
  1195. $parentWidth = $old['width'];
  1196. $parentX = $x;
  1197. } else {
  1198. $parentWidth = $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  1199. $parentX = $this->pdf->getlMargin();
  1200. }
  1201. // if we are in a gloat => adapt the parent position and width
  1202. if ($float) {
  1203. list($lx, $rx) = $this->_getMargins($yc);
  1204. $parentX = $lx;
  1205. $parentWidth = $rx-$lx;
  1206. }
  1207. // calculate the position of the image, if align to the right
  1208. if ($parentWidth>$w && $float!='left') {
  1209. if ($float=='right' || $this->parsingCss->value['text-align']=='li_right') $x = $parentX + $parentWidth - $w-$this->parsingCss->value['margin']['r']-$this->parsingCss->value['margin']['l'];
  1210. }
  1211. // display the image
  1212. if (!$this->_subPart && !$this->_isSubPart) {
  1213. if ($src) {
  1214. $this->pdf->Image($src, $x, $y, $w, $h, '', $this->_isInLink);
  1215. } else {
  1216. // rectangle if the image can not be loaded
  1217. $this->pdf->setFillColorArray(array(240, 220, 220));
  1218. $this->pdf->Rect($x, $y, $w, $h, 'F');
  1219. }
  1220. }
  1221. // apply the margins
  1222. $x-= $this->parsingCss->value['margin']['l'];
  1223. $y-= $this->parsingCss->value['margin']['t'];
  1224. $w+= $this->parsingCss->value['margin']['l'] + $this->parsingCss->value['margin']['r'];
  1225. $h+= $this->parsingCss->value['margin']['t'] + $this->parsingCss->value['margin']['b'];
  1226. if ($float=='left') {
  1227. // save the current max
  1228. $this->_maxX = max($this->_maxX, $x+$w);
  1229. $this->_maxY = max($this->_maxY, $y+$h);
  1230. // add the image to the margins
  1231. $this->_addMargins($float, $x, $y, $x+$w, $y+$h);
  1232. // get the new position
  1233. list($lx, $rx) = $this->_getMargins($yc);
  1234. $this->pdf->setXY($lx, $yc);
  1235. } else if ($float=='right') {
  1236. // save the current max. We don't save the X because it is not the real max of the line
  1237. $this->_maxY = max($this->_maxY, $y+$h);
  1238. // add the image to the margins
  1239. $this->_addMargins($float, $x, $y, $x+$w, $y+$h);
  1240. // get the new position
  1241. list($lx, $rx) = $this->_getMargins($yc);
  1242. $this->pdf->setXY($lx, $yc);
  1243. } else {
  1244. // set the new position at the end of the image
  1245. $this->pdf->setX($x+$w);
  1246. // save the current max
  1247. $this->_maxX = max($this->_maxX, $x+$w);
  1248. $this->_maxY = max($this->_maxY, $y+$h);
  1249. $this->_maxH = max($this->_maxH, $h);
  1250. }
  1251. return true;
  1252. }
  1253. /**
  1254. * draw a rectangle
  1255. *
  1256. * @access protected
  1257. * @param float $x
  1258. * @param float $y
  1259. * @param float $w
  1260. * @param float $h
  1261. * @param array $border
  1262. * @param float $padding - internal marge of the rectanble => not used, but...
  1263. * @param float $margin - external marge of the rectanble
  1264. * @param array $background
  1265. * @return boolean
  1266. */
  1267. protected function _drawRectangle($x, $y, $w, $h, $border, $padding, $margin, $background)
  1268. {
  1269. // if we are in a subpart or if height is null => return false
  1270. if ($this->_subPart || $this->_isSubPart || $h===null) return false;
  1271. // add the margin
  1272. $x+= $margin;
  1273. $y+= $margin;
  1274. $w-= $margin*2;
  1275. $h-= $margin*2;
  1276. // get the radius of the border
  1277. $outTL = $border['radius']['tl'];
  1278. $outTR = $border['radius']['tr'];
  1279. $outBR = $border['radius']['br'];
  1280. $outBL = $border['radius']['bl'];
  1281. // prepare the out radius
  1282. $outTL = ($outTL[0] && $outTL[1]) ? $outTL : null;
  1283. $outTR = ($outTR[0] && $outTR[1]) ? $outTR : null;
  1284. $outBR = ($outBR[0] && $outBR[1]) ? $outBR : null;
  1285. $outBL = ($outBL[0] && $outBL[1]) ? $outBL : null;
  1286. // prepare the in radius
  1287. $inTL = $outTL;
  1288. $inTR = $outTR;
  1289. $inBR = $outBR;
  1290. $inBL = $outBL;
  1291. if (is_array($inTL)) {
  1292. $inTL[0]-= $border['l']['width'];
  1293. $inTL[1]-= $border['t']['width'];
  1294. }
  1295. if (is_array($inTR)) {
  1296. $inTR[0]-= $border['r']['width'];
  1297. $inTR[1]-= $border['t']['width'];
  1298. }
  1299. if (is_array($inBR)) {
  1300. $inBR[0]-= $border['r']['width'];
  1301. $inBR[1]-= $border['b']['width'];
  1302. }
  1303. if (is_array($inBL)) {
  1304. $inBL[0]-= $border['l']['width'];
  1305. $inBL[1]-= $border['b']['width'];
  1306. }
  1307. if ($inTL[0]<=0 || $inTL[1]<=0) $inTL = null;
  1308. if ($inTR[0]<=0 || $inTR[1]<=0) $inTR = null;
  1309. if ($inBR[0]<=0 || $inBR[1]<=0) $inBR = null;
  1310. if ($inBL[0]<=0 || $inBL[1]<=0) $inBL = null;
  1311. // prepare the background color
  1312. $pdfStyle = '';
  1313. if ($background['color']) {
  1314. $this->pdf->setFillColorArray($background['color']);
  1315. $pdfStyle.= 'F';
  1316. }
  1317. // if we have a background to fill => fill it with a path (because of the radius)
  1318. if ($pdfStyle) {
  1319. $this->pdf->clippingPathStart($x, $y, $w, $h, $outTL, $outTR, $outBL, $outBR);
  1320. $this->pdf->Rect($x, $y, $w, $h, $pdfStyle);
  1321. $this->pdf->clippingPathStop();
  1322. }
  1323. // prepare the background image
  1324. if ($background['image']) {
  1325. $iName = $background['image'];
  1326. $iPosition = $background['position']!==null ? $background['position'] : array(0, 0);
  1327. $iRepeat = $background['repeat']!==null ? $background['repeat'] : array(true, true);
  1328. // size of the background without the borders
  1329. $bX = $x;
  1330. $bY = $y;
  1331. $bW = $w;
  1332. $bH = $h;
  1333. if ($border['b']['width']) {
  1334. $bH-= $border['b']['width'];
  1335. }
  1336. if ($border['l']['width']) {
  1337. $bW-= $border['l']['width'];
  1338. $bX+= $border['l']['width'];
  1339. }
  1340. if ($border['t']['width']) {
  1341. $bH-= $border['t']['width'];
  1342. $bY+= $border['t']['width'];
  1343. }
  1344. if ($border['r']['width']) {
  1345. $bW-= $border['r']['width'];
  1346. }
  1347. // get the size of the image
  1348. // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
  1349. $imageInfos=@getimagesize($iName);
  1350. // if the image can not be loaded
  1351. if (count($imageInfos)<2) {
  1352. if ($this->_testIsImage) {
  1353. throw new HTML2PDF_exception(6, $iName);
  1354. }
  1355. } else {
  1356. // convert the size of the image from pixel to the unit of the PDF
  1357. $imageWidth = 72./96.*$imageInfos[0]/$this->pdf->getK();
  1358. $imageHeight = 72./96.*$imageInfos[1]/$this->pdf->getK();
  1359. // prepare the position of the backgroung
  1360. if ($iRepeat[0]) $iPosition[0] = $bX;
  1361. else if (preg_match('/^([-]?[0-9\.]+)%/isU', $iPosition[0], $match)) $iPosition[0] = $bX + $match[1]*($bW-$imageWidth)/100;
  1362. else $iPosition[0] = $bX+$iPosition[0];
  1363. if ($iRepeat[1]) $iPosition[1] = $bY;
  1364. else if (preg_match('/^([-]?[0-9\.]+)%/isU', $iPosition[1], $match)) $iPosition[1] = $bY + $match[1]*($bH-$imageHeight)/100;
  1365. else $iPosition[1] = $bY+$iPosition[1];
  1366. $imageXmin = $bX;
  1367. $imageXmax = $bX+$bW;
  1368. $imageYmin = $bY;
  1369. $imageYmax = $bY+$bH;
  1370. if (!$iRepeat[0] && !$iRepeat[1]) {
  1371. $imageXmin = $iPosition[0]; $imageXmax = $iPosition[0]+$imageWidth;
  1372. $imageYmin = $iPosition[1]; $imageYmax = $iPosition[1]+$imageHeight;
  1373. } else if ($iRepeat[0] && !$iRepeat[1]) {
  1374. $imageYmin = $iPosition[1]; $imageYmax = $iPosition[1]+$imageHeight;
  1375. } else if (!$iRepeat[0] && $iRepeat[1]) {
  1376. $imageXmin = $iPosition[0]; $imageXmax = $iPosition[0]+$imageWidth;
  1377. }
  1378. // build the path to display the image (because of radius)
  1379. $this->pdf->clippingPathStart($bX, $bY, $bW, $bH, $inTL, $inTR, $inBL, $inBR);
  1380. // repeat the image
  1381. for ($iY=$imageYmin; $iY<$imageYmax; $iY+=$imageHeight) {
  1382. for ($iX=$imageXmin; $iX<$imageXmax; $iX+=$imageWidth) {
  1383. $cX = null;
  1384. $cY = null;
  1385. $cW = $imageWidth;
  1386. $cH = $imageHeight;
  1387. if ($imageYmax-$iY<$imageHeight) {
  1388. $cX = $iX;
  1389. $cY = $iY;
  1390. $cH = $imageYmax-$iY;
  1391. }
  1392. if ($imageXmax-$iX<$imageWidth) {
  1393. $cX = $iX;
  1394. $cY = $iY;
  1395. $cW = $imageXmax-$iX;
  1396. }
  1397. $this->pdf->Image($iName, $iX, $iY, $imageWidth, $imageHeight, '', '');
  1398. }
  1399. }
  1400. // end of the path
  1401. $this->pdf->clippingPathStop();
  1402. }
  1403. }
  1404. // adding some loose (0.01mm)
  1405. $loose = 0.01;
  1406. $x-= $loose;
  1407. $y-= $loose;
  1408. $w+= 2.*$loose;
  1409. $h+= 2.*$loose;
  1410. if ($border['l']['width']) $border['l']['width']+= 2.*$loose;
  1411. if ($border['t']['width']) $border['t']['width']+= 2.*$loose;
  1412. if ($border['r']['width']) $border['r']['width']+= 2.*$loose;
  1413. if ($border['b']['width']) $border['b']['width']+= 2.*$loose;
  1414. // prepare the test on borders
  1415. $testBl = ($border['l']['width'] && $border['l']['color'][0]!==null);
  1416. $testBt = ($border['t']['width'] && $border['t']['color'][0]!==null);
  1417. $testBr = ($border['r']['width'] && $border['r']['color'][0]!==null);
  1418. $testBb = ($border['b']['width'] && $border['b']['color'][0]!==null);
  1419. // draw the radius bottom-left
  1420. if (is_array($outBL) && ($testBb || $testBl)) {
  1421. if ($inBL) {
  1422. $courbe = array();
  1423. $courbe[] = $x+$outBL[0]; $courbe[] = $y+$h;
  1424. $courbe[] = $x; $courbe[] = $y+$h-$outBL[1];
  1425. $courbe[] = $x+$outBL[0]; $courbe[] = $y+$h-$border['b']['width'];
  1426. $courbe[] = $x+$border['l']['width']; $courbe[] = $y+$h-$outBL[1];
  1427. $courbe[] = $x+$outBL[0]; $courbe[] = $y+$h-$outBL[1];
  1428. } else {
  1429. $courbe = array();
  1430. $courbe[] = $x+$outBL[0]; $courbe[] = $y+$h;
  1431. $courbe[] = $x; $courbe[] = $y+$h-$outBL[1];
  1432. $courbe[] = $x+$border['l']['width']; $courbe[] = $y+$h-$border['b']['width'];
  1433. $courbe[] = $x+$outBL[0]; $courbe[] = $y+$h-$outBL[1];
  1434. }
  1435. $this->_drawCurve($courbe, $border['l']['color']);
  1436. }
  1437. // draw the radius left-top
  1438. if (is_array($outTL) && ($testBt || $testBl)) {
  1439. if ($inTL) {
  1440. $courbe = array();
  1441. $courbe[] = $x; $courbe[] = $y+$outTL[1];
  1442. $courbe[] = $x+$outTL[0]; $courbe[] = $y;
  1443. $courbe[] = $x+$border['l']['width']; $courbe[] = $y+$outTL[1];
  1444. $courbe[] = $x+$outTL[0]; $courbe[] = $y+$border['t']['width'];
  1445. $courbe[] = $x+$outTL[0]; $courbe[] = $y+$outTL[1];
  1446. } else {
  1447. $courbe = array();
  1448. $courbe[] = $x; $courbe[] = $y+$outTL[1];
  1449. $courbe[] = $x+$outTL[0]; $courbe[] = $y;
  1450. $courbe[] = $x+$border['l']['width']; $courbe[] = $y+$border['t']['width'];
  1451. $courbe[] = $x+$outTL[0]; $courbe[] = $y+$outTL[1];
  1452. }
  1453. $this->_drawCurve($courbe, $border['t']['color']);
  1454. }
  1455. // draw the radius top-right
  1456. if (is_array($outTR) && ($testBt || $testBr)) {
  1457. if ($inTR) {
  1458. $courbe = array();
  1459. $courbe[] = $x+$w-$outTR[0]; $courbe[] = $y;
  1460. $courbe[] = $x+$w; $courbe[] = $y+$outTR[1];
  1461. $courbe[] = $x+$w-$outTR[0]; $courbe[] = $y+$border['t']['width'];
  1462. $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$outTR[1];
  1463. $courbe[] = $x+$w-$outTR[0]; $courbe[] = $y+$outTR[1];
  1464. } else {
  1465. $courbe = array();
  1466. $courbe[] = $x+$w-$outTR[0]; $courbe[] = $y;
  1467. $courbe[] = $x+$w; $courbe[] = $y+$outTR[1];
  1468. $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$border['t']['width'];
  1469. $courbe[] = $x+$w-$outTR[0]; $courbe[] = $y+$outTR[1];
  1470. }
  1471. $this->_drawCurve($courbe, $border['r']['color']);
  1472. }
  1473. // draw the radius right-bottom
  1474. if (is_array($outBR) && ($testBb || $testBr)) {
  1475. if ($inBR) {
  1476. $courbe = array();
  1477. $courbe[] = $x+$w; $courbe[] = $y+$h-$outBR[1];
  1478. $courbe[] = $x+$w-$outBR[0]; $courbe[] = $y+$h;
  1479. $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$h-$outBR[1];
  1480. $courbe[] = $x+$w-$outBR[0]; $courbe[] = $y+$h-$border['b']['width'];
  1481. $courbe[] = $x+$w-$outBR[0]; $courbe[] = $y+$h-$outBR[1];
  1482. } else {
  1483. $courbe = array();
  1484. $courbe[] = $x+$w; $courbe[] = $y+$h-$outBR[1];
  1485. $courbe[] = $x+$w-$outBR[0]; $courbe[] = $y+$h;
  1486. $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$h-$border['b']['width'];
  1487. $courbe[] = $x+$w-$outBR[0]; $courbe[] = $y+$h-$outBR[1];
  1488. }
  1489. $this->_drawCurve($courbe, $border['b']['color']);
  1490. }
  1491. // draw the left border
  1492. if ($testBl) {
  1493. $pt = array();
  1494. $pt[] = $x; $pt[] = $y+$h;
  1495. $pt[] = $x; $pt[] = $y+$h-$border['b']['width'];
  1496. $pt[] = $x; $pt[] = $y+$border['t']['width'];
  1497. $pt[] = $x; $pt[] = $y;
  1498. $pt[] = $x+$border['l']['width']; $pt[] = $y+$border['t']['width'];
  1499. $pt[] = $x+$border['l']['width']; $pt[] = $y+$h-$border['b']['width'];
  1500. $bord = 3;
  1501. if (is_array($outBL)) {
  1502. $bord-=1;
  1503. $pt[3] -= $outBL[1] - $border['b']['width'];
  1504. if ($inBL) $pt[11]-= $inBL[1];
  1505. unset($pt[0]);unset($pt[1]);
  1506. }
  1507. if (is_array($outTL)) {
  1508. $bord-=2;
  1509. $pt[5] += $outTL[1]-$border['t']['width'];
  1510. if ($inTL) $pt[9] += $inTL[1];
  1511. unset($pt[6]);unset($pt[7]);
  1512. }
  1513. $pt = array_values($pt);
  1514. $this->_drawLine($pt, $border['l']['color'], $border['l']['type'], $border['l']['width'], $bord);
  1515. }
  1516. // draw the top border
  1517. if ($testBt) {
  1518. $pt = array();
  1519. $pt[] = $x; $pt[] = $y;
  1520. $pt[] = $x+$border['l']['width']; $pt[] = $y;
  1521. $pt[] = $x+$w-$border['r']['width']; $pt[] = $y;
  1522. $pt[] = $x+$w; $pt[] = $y;
  1523. $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$border['t']['width'];
  1524. $pt[] = $x+$border['l']['width']; $pt[] = $y+$border['t']['width'];
  1525. $bord = 3;
  1526. if (is_array($outTL)) {
  1527. $bord-=1;
  1528. $pt[2] += $outTL[0] - $border['l']['width'];
  1529. if ($inTL) $pt[10]+= $inTL[0];
  1530. unset($pt[0]);unset($pt[1]);
  1531. }
  1532. if (is_array($outTR)) {
  1533. $bord-=2;
  1534. $pt[4] -= $outTR[0] - $border['r']['width'];
  1535. if ($inTR) $pt[8] -= $inTR[0];
  1536. unset($pt[6]);unset($pt[7]);
  1537. }
  1538. $pt = array_values($pt);
  1539. $this->_drawLine($pt, $border['t']['color'], $border['t']['type'], $border['t']['width'], $bord);
  1540. }
  1541. // draw the right border
  1542. if ($testBr) {
  1543. $pt = array();
  1544. $pt[] = $x+$w; $pt[] = $y;
  1545. $pt[] = $x+$w; $pt[] = $y+$border['t']['width'];
  1546. $pt[] = $x+$w; $pt[] = $y+$h-$border['b']['width'];
  1547. $pt[] = $x+$w; $pt[] = $y+$h;
  1548. $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h-$border['b']['width'];
  1549. $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$border['t']['width'];
  1550. $bord = 3;
  1551. if (is_array($outTR)) {
  1552. $bord-=1;
  1553. $pt[3] += $outTR[1] - $border['t']['width'];
  1554. if ($inTR) $pt[11]+= $inTR[1];
  1555. unset($pt[0]);unset($pt[1]);
  1556. }
  1557. if (is_array($outBR)) {
  1558. $bord-=2;
  1559. $pt[5] -= $outBR[1] - $border['b']['width'];
  1560. if ($inBR) $pt[9] -= $inBR[1];
  1561. unset($pt[6]);unset($pt[7]);
  1562. }
  1563. $pt = array_values($pt);
  1564. $this->_drawLine($pt, $border['r']['color'], $border['r']['type'], $border['r']['width'], $bord);
  1565. }
  1566. // draw the bottom border
  1567. if ($testBb) {
  1568. $pt = array();
  1569. $pt[] = $x+$w; $pt[] = $y+$h;
  1570. $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h;
  1571. $pt[] = $x+$border['l']['width']; $pt[] = $y+$h;
  1572. $pt[] = $x; $pt[] = $y+$h;
  1573. $pt[] = $x+$border['l']['width']; $pt[] = $y+$h-$border['b']['width'];
  1574. $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h-$border['b']['width'];
  1575. $bord = 3;
  1576. if (is_array($outBL)) {
  1577. $bord-=2;
  1578. $pt[4] += $outBL[0] - $border['l']['width'];
  1579. if ($inBL) $pt[8] += $inBL[0];
  1580. unset($pt[6]);unset($pt[7]);
  1581. }
  1582. if (is_array($outBR)) {
  1583. $bord-=1;
  1584. $pt[2] -= $outBR[0] - $border['r']['width'];
  1585. if ($inBR) $pt[10]-= $inBR[0];
  1586. unset($pt[0]);unset($pt[1]);
  1587. }
  1588. $pt = array_values($pt);
  1589. $this->_drawLine($pt, $border['b']['color'], $border['b']['type'], $border['b']['width'], $bord);
  1590. }
  1591. if ($background['color']) {
  1592. $this->pdf->setFillColorArray($background['color']);
  1593. }
  1594. return true;
  1595. }
  1596. /**
  1597. * draw a curve (for border radius)
  1598. *
  1599. * @access protected
  1600. * @param array $pt
  1601. * @param array $color
  1602. */
  1603. protected function _drawCurve($pt, $color)
  1604. {
  1605. $this->pdf->setFillColorArray($color);
  1606. if (count($pt)==10)
  1607. $this->pdf->drawCurve($pt[0], $pt[1], $pt[2], $pt[3], $pt[4], $pt[5], $pt[6], $pt[7], $pt[8], $pt[9]);
  1608. else
  1609. $this->pdf->drawCorner($pt[0], $pt[1], $pt[2], $pt[3], $pt[4], $pt[5], $pt[6], $pt[7]);
  1610. }
  1611. /**
  1612. * draw a ligne with a specific type, and specific start and end for radius
  1613. *
  1614. * @access protected
  1615. * @param array $pt
  1616. * @param float $color
  1617. * @param string $type (dashed, dotted, double, solid)
  1618. * @param float $width
  1619. * @param integer $radius (binary from 0 to 3 with 1=>start with a radius, 2=>end with a radius)
  1620. */
  1621. protected function _drawLine($pt, $color, $type, $width, $radius=3)
  1622. {
  1623. // set the fill color
  1624. $this->pdf->setFillColorArray($color);
  1625. // if dashed or dotted
  1626. if ($type=='dashed' || $type=='dotted') {
  1627. // clean the end of the line, if radius
  1628. if ($radius==1) {
  1629. $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
  1630. $this->pdf->Polygon($tmp, 'F');
  1631. $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
  1632. $pt = $tmp;
  1633. } else if ($radius==2) {
  1634. $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7];
  1635. $this->pdf->Polygon($tmp, 'F');
  1636. $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
  1637. $pt = $tmp;
  1638. } else if ($radius==3) {
  1639. $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[10]; $tmp[]=$pt[11];
  1640. $this->pdf->Polygon($tmp, 'F');
  1641. $tmp = array(); $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
  1642. $this->pdf->Polygon($tmp, 'F');
  1643. $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[8]; $tmp[]=$pt[9]; $tmp[]=$pt[10]; $tmp[]=$pt[11];
  1644. $pt = $tmp;
  1645. }
  1646. // horisontal or vertical line
  1647. if ($pt[2]==$pt[0]) {
  1648. $l = abs(($pt[3]-$pt[1])*0.5);
  1649. $px = 0;
  1650. $py = $width;
  1651. $x1 = $pt[0]; $y1 = ($pt[3]+$pt[1])*0.5;
  1652. $x2 = $pt[6]; $y2 = ($pt[7]+$pt[5])*0.5;
  1653. } else {
  1654. $l = abs(($pt[2]-$pt[0])*0.5);
  1655. $px = $width;
  1656. $py = 0;
  1657. $x1 = ($pt[2]+$pt[0])*0.5; $y1 = $pt[1];
  1658. $x2 = ($pt[6]+$pt[4])*0.5; $y2 = $pt[7];
  1659. }
  1660. // if dashed : 3x bigger than dotted
  1661. if ($type=='dashed') {
  1662. $px = $px*3.;
  1663. $py = $py*3.;
  1664. }
  1665. $mode = ($l/($px+$py)<.5);
  1666. // display the dotted/dashed line
  1667. for ($i=0; $l-($px+$py)*($i-0.5)>0; $i++) {
  1668. if (($i%2)==$mode) {
  1669. $j = $i-0.5;
  1670. $lx1 = $px*($j); if ($lx1<-$l) $lx1 =-$l;
  1671. $ly1 = $py*($j); if ($ly1<-$l) $ly1 =-$l;
  1672. $lx2 = $px*($j+1); if ($lx2>$l) $lx2 = $l;
  1673. $ly2 = $py*($j+1); if ($ly2>$l) $ly2 = $l;
  1674. $tmp = array();
  1675. $tmp[] = $x1+$lx1; $tmp[] = $y1+$ly1;
  1676. $tmp[] = $x1+$lx2; $tmp[] = $y1+$ly2;
  1677. $tmp[] = $x2+$lx2; $tmp[] = $y2+$ly2;
  1678. $tmp[] = $x2+$lx1; $tmp[] = $y2+$ly1;
  1679. $this->pdf->Polygon($tmp, 'F');
  1680. if ($j>0) {
  1681. $tmp = array();
  1682. $tmp[] = $x1-$lx1; $tmp[] = $y1-$ly1;
  1683. $tmp[] = $x1-$lx2; $tmp[] = $y1-$ly2;
  1684. $tmp[] = $x2-$lx2; $tmp[] = $y2-$ly2;
  1685. $tmp[] = $x2-$lx1; $tmp[] = $y2-$ly1;
  1686. $this->pdf->Polygon($tmp, 'F');
  1687. }
  1688. }
  1689. }
  1690. } else if ($type=='double') {
  1691. // if double, 2 lines : 0=>1/3 and 2/3=>1
  1692. $pt1 = $pt;
  1693. $pt2 = $pt;
  1694. if (count($pt)==12) {
  1695. // line 1
  1696. $pt1[0] = ($pt[0]-$pt[10])*0.33 + $pt[10];
  1697. $pt1[1] = ($pt[1]-$pt[11])*0.33 + $pt[11];
  1698. $pt1[2] = ($pt[2]-$pt[10])*0.33 + $pt[10];
  1699. $pt1[3] = ($pt[3]-$pt[11])*0.33 + $pt[11];
  1700. $pt1[4] = ($pt[4]-$pt[8])*0.33 + $pt[8];
  1701. $pt1[5] = ($pt[5]-$pt[9])*0.33 + $pt[9];
  1702. $pt1[6] = ($pt[6]-$pt[8])*0.33 + $pt[8];
  1703. $pt1[7] = ($pt[7]-$pt[9])*0.33 + $pt[9];
  1704. $pt2[10]= ($pt[10]-$pt[0])*0.33 + $pt[0];
  1705. $pt2[11]= ($pt[11]-$pt[1])*0.33 + $pt[1];
  1706. // line 2
  1707. $pt2[2] = ($pt[2] -$pt[0])*0.33 + $pt[0];
  1708. $pt2[3] = ($pt[3] -$pt[1])*0.33 + $pt[1];
  1709. $pt2[4] = ($pt[4] -$pt[6])*0.33 + $pt[6];
  1710. $pt2[5] = ($pt[5] -$pt[7])*0.33 + $pt[7];
  1711. $pt2[8] = ($pt[8] -$pt[6])*0.33 + $pt[6];
  1712. $pt2[9] = ($pt[9] -$pt[7])*0.33 + $pt[7];
  1713. } else {
  1714. // line 1
  1715. $pt1[0] = ($pt[0]-$pt[6])*0.33 + $pt[6];
  1716. $pt1[1] = ($pt[1]-$pt[7])*0.33 + $pt[7];
  1717. $pt1[2] = ($pt[2]-$pt[4])*0.33 + $pt[4];
  1718. $pt1[3] = ($pt[3]-$pt[5])*0.33 + $pt[5];
  1719. // line 2
  1720. $pt2[6] = ($pt[6]-$pt[0])*0.33 + $pt[0];
  1721. $pt2[7] = ($pt[7]-$pt[1])*0.33 + $pt[1];
  1722. $pt2[4] = ($pt[4]-$pt[2])*0.33 + $pt[2];
  1723. $pt2[5] = ($pt[5]-$pt[3])*0.33 + $pt[3];
  1724. }
  1725. $this->pdf->Polygon($pt1, 'F');
  1726. $this->pdf->Polygon($pt2, 'F');
  1727. } else if ($type=='solid') {
  1728. // solid line : draw directly the polygon
  1729. $this->pdf->Polygon($pt, 'F');
  1730. }
  1731. }
  1732. /**
  1733. * prepare a transform matrix, only for drawing a SVG graphic
  1734. *
  1735. * @access protected
  1736. * @param string $transform
  1737. * @return array $matrix
  1738. */
  1739. protected function _prepareTransform($transform)
  1740. {
  1741. // it can not be empty
  1742. if (!$transform) return null;
  1743. // sctions must be like scale(...)
  1744. if (!preg_match_all('/([a-z]+)\(([^\)]*)\)/isU', $transform, $match)) return null;
  1745. // prepare the list of the actions
  1746. $actions = array();
  1747. // for actions
  1748. for ($k=0; $k<count($match[0]); $k++) {
  1749. // get the name of the action
  1750. $name = strtolower($match[1][$k]);
  1751. // get the parameters of the action
  1752. $val = explode(',', trim($match[2][$k]));
  1753. foreach ($val as $i => $j) {
  1754. $val[$i] = trim($j);
  1755. }
  1756. // prepare the matrix, depending on the action
  1757. switch($name)
  1758. {
  1759. case 'scale':
  1760. if (!isset($val[0])) $val[0] = 1.; else $val[0] = 1.*$val[0];
  1761. if (!isset($val[1])) $val[1] = $val[0]; else $val[1] = 1.*$val[1];
  1762. $actions[] = array($val[0],0,0,$val[1],0,0);
  1763. break;
  1764. case 'translate':
  1765. if (!isset($val[0])) $val[0] = 0.; else $val[0] = $this->parsingCss->ConvertToMM($val[0], $this->_isInDraw['w']);
  1766. if (!isset($val[1])) $val[1] = 0.; else $val[1] = $this->parsingCss->ConvertToMM($val[1], $this->_isInDraw['h']);
  1767. $actions[] = array(1,0,0,1,$val[0],$val[1]);
  1768. break;
  1769. case 'rotate':
  1770. if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*M_PI/180.;
  1771. if (!isset($val[1])) $val[1] = 0.; else $val[1] = $this->parsingCss->ConvertToMM($val[1], $this->_isInDraw['w']);
  1772. if (!isset($val[2])) $val[2] = 0.; else $val[2] = $this->parsingCss->ConvertToMM($val[2], $this->_isInDraw['h']);
  1773. if ($val[1] || $val[2]) $actions[] = array(1,0,0,1,-$val[1],-$val[2]);
  1774. $actions[] = array(cos($val[0]),sin($val[0]),-sin($val[0]),cos($val[0]),0,0);
  1775. if ($val[1] || $val[2]) $actions[] = array(1,0,0,1,$val[1],$val[2]);
  1776. break;
  1777. case 'skewx':
  1778. if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*M_PI/180.;
  1779. $actions[] = array(1,0,tan($val[0]),1,0,0);
  1780. break;
  1781. case 'skewy':
  1782. if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*M_PI/180.;
  1783. $actions[] = array(1,tan($val[0]),0,1,0,0);
  1784. break;
  1785. case 'matrix':
  1786. if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*1.;
  1787. if (!isset($val[1])) $val[1] = 0.; else $val[1] = $val[1]*1.;
  1788. if (!isset($val[2])) $val[2] = 0.; else $val[2] = $val[2]*1.;
  1789. if (!isset($val[3])) $val[3] = 0.; else $val[3] = $val[3]*1.;
  1790. if (!isset($val[4])) $val[4] = 0.; else $val[4] = $this->parsingCss->ConvertToMM($val[4], $this->_isInDraw['w']);
  1791. if (!isset($val[5])) $val[5] = 0.; else $val[5] = $this->parsingCss->ConvertToMM($val[5], $this->_isInDraw['h']);
  1792. $actions[] =$val;
  1793. break;
  1794. }
  1795. }
  1796. // if ther is no actions => return
  1797. if (!$actions) return null;
  1798. // get the first matrix
  1799. $m = $actions[0]; unset($actions[0]);
  1800. // foreach matrix => multiply to the last matrix
  1801. foreach ($actions as $n) {
  1802. $m = array(
  1803. $m[0]*$n[0]+$m[2]*$n[1],
  1804. $m[1]*$n[0]+$m[3]*$n[1],
  1805. $m[0]*$n[2]+$m[2]*$n[3],
  1806. $m[1]*$n[2]+$m[3]*$n[3],
  1807. $m[0]*$n[4]+$m[2]*$n[5]+$m[4],
  1808. $m[1]*$n[4]+$m[3]*$n[5]+$m[5]
  1809. );
  1810. }
  1811. // return the matrix
  1812. return $m;
  1813. }
  1814. /**
  1815. * @access protected
  1816. * @param &array $cases
  1817. * @param &array $corr
  1818. */
  1819. protected function _calculateTableCellSize(&$cases, &$corr)
  1820. {
  1821. if (!isset($corr[0])) return true;
  1822. // for each cell without colspan, we get the max width for each column
  1823. $sw = array();
  1824. for ($x=0; $x<count($corr[0]); $x++) {
  1825. $m=0;
  1826. for ($y=0; $y<count($corr); $y++) {
  1827. if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][2]==1) {
  1828. $m = max($m, $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w']);
  1829. }
  1830. }
  1831. $sw[$x] = $m;
  1832. }
  1833. // for each cell with colspan, we adapt the width of each column
  1834. for ($x=0; $x<count($corr[0]); $x++) {
  1835. for ($y=0; $y<count($corr); $y++) {
  1836. if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][2]>1) {
  1837. // sum the max width of each column in colspan
  1838. $s = 0; for ($i=0; $i<$corr[$y][$x][2]; $i++) $s+= $sw[$x+$i];
  1839. // if the max width is < the width of the cell with colspan => we adapt the width of each max width
  1840. if ($s>0 && $s<$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w']) {
  1841. for ($i=0; $i<$corr[$y][$x][2]; $i++) {
  1842. $sw[$x+$i] = $sw[$x+$i]/$s*$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'];
  1843. }
  1844. }
  1845. }
  1846. }
  1847. }
  1848. // set the new width, for each cell
  1849. for ($x=0; $x<count($corr[0]); $x++) {
  1850. for ($y=0; $y<count($corr); $y++) {
  1851. if (isset($corr[$y][$x]) && is_array($corr[$y][$x])) {
  1852. // without colspan
  1853. if ($corr[$y][$x][2]==1) {
  1854. $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'] = $sw[$x];
  1855. // with colspan
  1856. } else {
  1857. $s = 0;
  1858. for ($i=0; $i<$corr[$y][$x][2]; $i++) {
  1859. $s+= $sw[$x+$i];
  1860. }
  1861. $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'] = $s;
  1862. }
  1863. }
  1864. }
  1865. }
  1866. // for each cell without rowspan, we get the max height for each line
  1867. $sh = array();
  1868. for ($y=0; $y<count($corr); $y++) {
  1869. $m=0;
  1870. for ($x=0; $x<count($corr[0]); $x++) {
  1871. if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][3]==1) {
  1872. $m = max($m, $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h']);
  1873. }
  1874. }
  1875. $sh[$y] = $m;
  1876. }
  1877. // for each cell with rowspan, we adapt the height of each line
  1878. for ($y=0; $y<count($corr); $y++) {
  1879. for ($x=0; $x<count($corr[0]); $x++) {
  1880. if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][3]>1) {
  1881. // sum the max height of each line in rowspan
  1882. $s = 0; for ($i=0; $i<$corr[$y][$x][3]; $i++) $s+= $sh[$y+$i];
  1883. // if the max height is < the height of the cell with rowspan => we adapt the height of each max height
  1884. if ($s>0 && $s<$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h']) {
  1885. for ($i=0; $i<$corr[$y][$x][3]; $i++) {
  1886. $sh[$y+$i] = $sh[$y+$i]/$s*$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'];
  1887. }
  1888. }
  1889. }
  1890. }
  1891. }
  1892. // set the new height, for each cell
  1893. for ($y=0; $y<count($corr); $y++) {
  1894. for ($x=0; $x<count($corr[0]); $x++) {
  1895. if (isset($corr[$y][$x]) && is_array($corr[$y][$x])) {
  1896. // without rowspan
  1897. if ($corr[$y][$x][3]==1) {
  1898. $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'] = $sh[$y];
  1899. // with rowspan
  1900. } else {
  1901. $s = 0;
  1902. for ($i=0; $i<$corr[$y][$x][3]; $i++) {
  1903. $s+= $sh[$y+$i];
  1904. }
  1905. $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'] = $s;
  1906. for ($j=1; $j<$corr[$y][$x][3]; $j++) {
  1907. $tx = $x+1;
  1908. $ty = $y+$j;
  1909. for (true; isset($corr[$ty][$tx]) && !is_array($corr[$ty][$tx]); $tx++);
  1910. if (isset($corr[$ty][$tx])) {
  1911. $cases[$corr[$ty][$tx][1]][$corr[$ty][$tx][0]]['dw']+= $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'];
  1912. }
  1913. }
  1914. }
  1915. }
  1916. }
  1917. }
  1918. }
  1919. /**
  1920. * tag : PAGE
  1921. * mode : OPEN
  1922. *
  1923. * @param array $param
  1924. * @return boolean
  1925. */
  1926. protected function _tag_open_PAGE($param)
  1927. {
  1928. if ($this->_isForOneLine) return false;
  1929. if ($this->_debugActif) $this->_DEBUG_add('PAGE '.($this->_page+1), true);
  1930. $newPageSet= (!isset($param['pageset']) || $param['pageset']!='old');
  1931. $resetPageNumber = (isset($param['pagegroup']) && $param['pagegroup']=='new');
  1932. $this->_maxH = 0;
  1933. // if new page set asked
  1934. if ($newPageSet) {
  1935. $this->_subHEADER = array();
  1936. $this->_subFOOTER = array();
  1937. // orientation
  1938. $orientation = '';
  1939. if (isset($param['orientation'])) {
  1940. $param['orientation'] = strtolower($param['orientation']);
  1941. if ($param['orientation']=='p') $orientation = 'P';
  1942. if ($param['orientation']=='portrait') $orientation = 'P';
  1943. if ($param['orientation']=='l') $orientation = 'L';
  1944. if ($param['orientation']=='paysage') $orientation = 'L';
  1945. if ($param['orientation']=='landscape') $orientation = 'L';
  1946. }
  1947. // format
  1948. $format = null;
  1949. if (isset($param['format'])) {
  1950. $format = strtolower($param['format']);
  1951. if (preg_match('/^([0-9]+)x([0-9]+)$/isU', $format, $match)) {
  1952. $format = array(intval($match[1]), intval($match[2]));
  1953. }
  1954. }
  1955. // background
  1956. $background = array();
  1957. if (isset($param['backimg'])) {
  1958. $background['img'] = isset($param['backimg']) ? $param['backimg'] : ''; // src of the image
  1959. $background['posX'] = isset($param['backimgx']) ? $param['backimgx'] : 'center'; // horizontale position of the image
  1960. $background['posY'] = isset($param['backimgy']) ? $param['backimgy'] : 'middle'; // vertical position of the image
  1961. $background['width'] = isset($param['backimgw']) ? $param['backimgw'] : '100%'; // width of the image (100% = page width)
  1962. // convert the src of the image, if parameters
  1963. $background['img'] = str_replace('&amp;', '&', $background['img']);
  1964. // convert the positions
  1965. if ($background['posX']=='left') $background['posX'] = '0%';
  1966. if ($background['posX']=='center') $background['posX'] = '50%';
  1967. if ($background['posX']=='right') $background['posX'] = '100%';
  1968. if ($background['posY']=='top') $background['posY'] = '0%';
  1969. if ($background['posY']=='middle') $background['posY'] = '50%';
  1970. if ($background['posY']=='bottom') $background['posY'] = '100%';
  1971. if ($background['img']) {
  1972. // get the size of the image
  1973. // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
  1974. $infos=@getimagesize($background['img']);
  1975. if (count($infos)>1) {
  1976. $imageWidth = $this->parsingCss->ConvertToMM($background['width'], $this->pdf->getW());
  1977. $imageHeight = $imageWidth*$infos[1]/$infos[0];
  1978. $background['width'] = $imageWidth;
  1979. $background['posX'] = $this->parsingCss->ConvertToMM($background['posX'], $this->pdf->getW() - $imageWidth);
  1980. $background['posY'] = $this->parsingCss->ConvertToMM($background['posY'], $this->pdf->getH() - $imageHeight);
  1981. } else {
  1982. $background = array();
  1983. }
  1984. } else {
  1985. $background = array();
  1986. }
  1987. }
  1988. // margins of the page
  1989. $background['top'] = isset($param['backtop']) ? $param['backtop'] : '0';
  1990. $background['bottom'] = isset($param['backbottom']) ? $param['backbottom'] : '0';
  1991. $background['left'] = isset($param['backleft']) ? $param['backleft'] : '0';
  1992. $background['right'] = isset($param['backright']) ? $param['backright'] : '0';
  1993. // if no unit => mm
  1994. if (preg_match('/^([0-9]*)$/isU', $background['top'])) $background['top'] .= 'mm';
  1995. if (preg_match('/^([0-9]*)$/isU', $background['bottom'])) $background['bottom'] .= 'mm';
  1996. if (preg_match('/^([0-9]*)$/isU', $background['left'])) $background['left'] .= 'mm';
  1997. if (preg_match('/^([0-9]*)$/isU', $background['right'])) $background['right'] .= 'mm';
  1998. // convert to mm
  1999. $background['top'] = $this->parsingCss->ConvertToMM($background['top'], $this->pdf->getH());
  2000. $background['bottom'] = $this->parsingCss->ConvertToMM($background['bottom'], $this->pdf->getH());
  2001. $background['left'] = $this->parsingCss->ConvertToMM($background['left'], $this->pdf->getW());
  2002. $background['right'] = $this->parsingCss->ConvertToMM($background['right'], $this->pdf->getW());
  2003. // get the background color
  2004. $res = false;
  2005. $background['color'] = isset($param['backcolor']) ? $this->parsingCss->convertToColor($param['backcolor'], $res) : null;
  2006. if (!$res) $background['color'] = null;
  2007. $this->parsingCss->save();
  2008. $this->parsingCss->analyse('PAGE', $param);
  2009. $this->parsingCss->setPosition();
  2010. $this->parsingCss->fontSet();
  2011. // new page
  2012. $this->_setNewPage($format, $orientation, $background, null, $resetPageNumber);
  2013. // automatic footer
  2014. if (isset($param['footer'])) {
  2015. $lst = explode(';', $param['footer']);
  2016. foreach ($lst as $key => $val) $lst[$key] = trim(strtolower($val));
  2017. $page = in_array('page', $lst);
  2018. $date = in_array('date', $lst);
  2019. $hour = in_array('heure', $lst);
  2020. $form = in_array('form', $lst);
  2021. } else {
  2022. $page = null;
  2023. $date = null;
  2024. $hour = null;
  2025. $form = null;
  2026. }
  2027. $this->pdf->SetMyFooter($page, $date, $hour, $form);
  2028. // else => we use the last page set used
  2029. } else {
  2030. $this->parsingCss->save();
  2031. $this->parsingCss->analyse('PAGE', $param);
  2032. $this->parsingCss->setPosition();
  2033. $this->parsingCss->fontSet();
  2034. $this->_setNewPage(null, null, null, null, $resetPageNumber);
  2035. }
  2036. return true;
  2037. }
  2038. /**
  2039. * tag : PAGE
  2040. * mode : CLOSE
  2041. *
  2042. * @param array $param
  2043. * @return boolean
  2044. */
  2045. protected function _tag_close_PAGE($param)
  2046. {
  2047. if ($this->_isForOneLine) return false;
  2048. $this->_maxH = 0;
  2049. $this->parsingCss->load();
  2050. $this->parsingCss->fontSet();
  2051. if ($this->_debugActif) $this->_DEBUG_add('PAGE '.$this->_page, false);
  2052. return true;
  2053. }
  2054. /**
  2055. * tag : PAGE_HEADER
  2056. * mode : OPEN
  2057. *
  2058. * @param array $param
  2059. * @return boolean
  2060. */
  2061. protected function _tag_open_PAGE_HEADER($param)
  2062. {
  2063. if ($this->_isForOneLine) return false;
  2064. $this->_subHEADER = array();
  2065. for ($this->_parsePos; $this->_parsePos<count($this->parsingHtml->code); $this->_parsePos++) {
  2066. $action = $this->parsingHtml->code[$this->_parsePos];
  2067. if ($action['name']=='page_header') $action['name']='page_header_sub';
  2068. $this->_subHEADER[] = $action;
  2069. if (strtolower($action['name'])=='page_header_sub' && $action['close']) break;
  2070. }
  2071. $this->_setPageHeader();
  2072. return true;
  2073. }
  2074. /**
  2075. * tag : PAGE_FOOTER
  2076. * mode : OPEN
  2077. *
  2078. * @param array $param
  2079. * @return boolean
  2080. */
  2081. protected function _tag_open_PAGE_FOOTER($param)
  2082. {
  2083. if ($this->_isForOneLine) return false;
  2084. $this->_subFOOTER = array();
  2085. for ($this->_parsePos; $this->_parsePos<count($this->parsingHtml->code); $this->_parsePos++) {
  2086. $action = $this->parsingHtml->code[$this->_parsePos];
  2087. if ($action['name']=='page_footer') $action['name']='page_footer_sub';
  2088. $this->_subFOOTER[] = $action;
  2089. if (strtolower($action['name'])=='page_footer_sub' && $action['close']) break;
  2090. }
  2091. $this->_setPageFooter();
  2092. return true;
  2093. }
  2094. /**
  2095. * It is not a real tag. Does not use it directly
  2096. *
  2097. * @param array $param
  2098. * @return boolean
  2099. */
  2100. protected function _tag_open_PAGE_HEADER_SUB($param)
  2101. {
  2102. if ($this->_isForOneLine) return false;
  2103. // save the current stat
  2104. $this->_subSTATES = array();
  2105. $this->_subSTATES['x'] = $this->pdf->getX();
  2106. $this->_subSTATES['y'] = $this->pdf->getY();
  2107. $this->_subSTATES['s'] = $this->parsingCss->value;
  2108. $this->_subSTATES['t'] = $this->parsingCss->table;
  2109. $this->_subSTATES['ml'] = $this->_margeLeft;
  2110. $this->_subSTATES['mr'] = $this->_margeRight;
  2111. $this->_subSTATES['mt'] = $this->_margeTop;
  2112. $this->_subSTATES['mb'] = $this->_margeBottom;
  2113. $this->_subSTATES['mp'] = $this->_pageMarges;
  2114. // new stat for the header
  2115. $this->_pageMarges = array();
  2116. $this->_margeLeft = $this->_defaultLeft;
  2117. $this->_margeRight = $this->_defaultRight;
  2118. $this->_margeTop = $this->_defaultTop;
  2119. $this->_margeBottom = $this->_defaultBottom;
  2120. $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
  2121. $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
  2122. $this->pdf->setXY($this->_defaultLeft, $this->_defaultTop);
  2123. $this->parsingCss->initStyle();
  2124. $this->parsingCss->resetStyle();
  2125. $this->parsingCss->value['width'] = $this->pdf->getW() - $this->_defaultLeft - $this->_defaultRight;
  2126. $this->parsingCss->table = array();
  2127. $this->parsingCss->save();
  2128. $this->parsingCss->analyse('page_header_sub', $param);
  2129. $this->parsingCss->setPosition();
  2130. $this->parsingCss->fontSet();
  2131. $this->_setNewPositionForNewLine();
  2132. return true;
  2133. }
  2134. /**
  2135. * It is not a real tag. Does not use it directly
  2136. *
  2137. * @param array $param
  2138. * @return boolean
  2139. */
  2140. protected function _tag_close_PAGE_HEADER_SUB($param)
  2141. {
  2142. if ($this->_isForOneLine) return false;
  2143. $this->parsingCss->load();
  2144. // restore the stat
  2145. $this->parsingCss->value = $this->_subSTATES['s'];
  2146. $this->parsingCss->table = $this->_subSTATES['t'];
  2147. $this->_pageMarges = $this->_subSTATES['mp'];
  2148. $this->_margeLeft = $this->_subSTATES['ml'];
  2149. $this->_margeRight = $this->_subSTATES['mr'];
  2150. $this->_margeTop = $this->_subSTATES['mt'];
  2151. $this->_margeBottom = $this->_subSTATES['mb'];
  2152. $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
  2153. $this->pdf->setbMargin($this->_margeBottom);
  2154. $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
  2155. $this->pdf->setXY($this->_subSTATES['x'], $this->_subSTATES['y']);
  2156. $this->parsingCss->fontSet();
  2157. $this->_maxH = 0;
  2158. return true;
  2159. }
  2160. /**
  2161. * It is not a real tag. Does not use it directly
  2162. *
  2163. * @param array $param
  2164. * @return boolean
  2165. */
  2166. protected function _tag_open_PAGE_FOOTER_SUB($param)
  2167. {
  2168. if ($this->_isForOneLine) return false;
  2169. // save the current stat
  2170. $this->_subSTATES = array();
  2171. $this->_subSTATES['x'] = $this->pdf->getX();
  2172. $this->_subSTATES['y'] = $this->pdf->getY();
  2173. $this->_subSTATES['s'] = $this->parsingCss->value;
  2174. $this->_subSTATES['t'] = $this->parsingCss->table;
  2175. $this->_subSTATES['ml'] = $this->_margeLeft;
  2176. $this->_subSTATES['mr'] = $this->_margeRight;
  2177. $this->_subSTATES['mt'] = $this->_margeTop;
  2178. $this->_subSTATES['mb'] = $this->_margeBottom;
  2179. $this->_subSTATES['mp'] = $this->_pageMarges;
  2180. // new stat for the footer
  2181. $this->_pageMarges = array();
  2182. $this->_margeLeft = $this->_defaultLeft;
  2183. $this->_margeRight = $this->_defaultRight;
  2184. $this->_margeTop = $this->_defaultTop;
  2185. $this->_margeBottom = $this->_defaultBottom;
  2186. $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
  2187. $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
  2188. $this->pdf->setXY($this->_defaultLeft, $this->_defaultTop);
  2189. $this->parsingCss->initStyle();
  2190. $this->parsingCss->resetStyle();
  2191. $this->parsingCss->value['width'] = $this->pdf->getW() - $this->_defaultLeft - $this->_defaultRight;
  2192. $this->parsingCss->table = array();
  2193. // we create a sub HTML2PFDF, and we execute on it the content of the footer, to get the height of it
  2194. $sub = null;
  2195. $this->_createSubHTML($sub);
  2196. $sub->parsingHtml->code = $this->parsingHtml->getLevel($this->_parsePos);
  2197. $sub->_makeHTMLcode();
  2198. $this->pdf->setY($this->pdf->getH() - $sub->_maxY - $this->_defaultBottom - 0.01);
  2199. $this->_destroySubHTML($sub);
  2200. $this->parsingCss->save();
  2201. $this->parsingCss->analyse('page_footer_sub', $param);
  2202. $this->parsingCss->setPosition();
  2203. $this->parsingCss->fontSet();
  2204. $this->_setNewPositionForNewLine();
  2205. return true;
  2206. }
  2207. /**
  2208. * It is not a real tag. Does not use it directly
  2209. *
  2210. * @param array $param
  2211. * @return boolean
  2212. */
  2213. protected function _tag_close_PAGE_FOOTER_SUB($param)
  2214. {
  2215. if ($this->_isForOneLine) return false;
  2216. $this->parsingCss->load();
  2217. $this->parsingCss->value = $this->_subSTATES['s'];
  2218. $this->parsingCss->table = $this->_subSTATES['t'];
  2219. $this->_pageMarges = $this->_subSTATES['mp'];
  2220. $this->_margeLeft = $this->_subSTATES['ml'];
  2221. $this->_margeRight = $this->_subSTATES['mr'];
  2222. $this->_margeTop = $this->_subSTATES['mt'];
  2223. $this->_margeBottom = $this->_subSTATES['mb'];
  2224. $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
  2225. $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
  2226. $this->pdf->setXY($this->_subSTATES['x'], $this->_subSTATES['y']);
  2227. $this->parsingCss->fontSet();
  2228. $this->_maxH = 0;
  2229. return true;
  2230. }
  2231. /**
  2232. * tag : NOBREAK
  2233. * mode : OPEN
  2234. *
  2235. * @param array $param
  2236. * @return boolean
  2237. */
  2238. protected function _tag_open_NOBREAK($param)
  2239. {
  2240. if ($this->_isForOneLine) return false;
  2241. $this->_maxH = 0;
  2242. // create a sub HTML2PDF to execute the content of the tag, to get the dimensions
  2243. $sub = null;
  2244. $this->_createSubHTML($sub);
  2245. $sub->parsingHtml->code = $this->parsingHtml->getLevel($this->_parsePos);
  2246. $sub->_makeHTMLcode();
  2247. $y = $this->pdf->getY();
  2248. // if the content does not fit on the page => new page
  2249. if (
  2250. $sub->_maxY < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin()) &&
  2251. $y + $sub->_maxY>=($this->pdf->getH() - $this->pdf->getbMargin())
  2252. ) {
  2253. $this->_setNewPage();
  2254. }
  2255. // destroy the sub HTML2PDF
  2256. $this->_destroySubHTML($sub);
  2257. return true;
  2258. }
  2259. /**
  2260. * tag : NOBREAK
  2261. * mode : CLOSE
  2262. *
  2263. * @param array $param
  2264. * @return boolean
  2265. */
  2266. protected function _tag_close_NOBREAK($param)
  2267. {
  2268. if ($this->_isForOneLine) return false;
  2269. $this->_maxH = 0;
  2270. return true;
  2271. }
  2272. /**
  2273. * tag : DIV
  2274. * mode : OPEN
  2275. *
  2276. * @param array $param
  2277. * @param string $other name of tag that used the div tag
  2278. * @return boolean
  2279. */
  2280. protected function _tag_open_DIV($param, $other = 'div')
  2281. {
  2282. if ($this->_isForOneLine) return false;
  2283. if ($this->_debugActif) $this->_DEBUG_add(strtoupper($other), true);
  2284. $this->parsingCss->save();
  2285. $this->parsingCss->analyse($other, $param);
  2286. $this->parsingCss->fontSet();
  2287. // for fieldset and legend
  2288. if (in_array($other, array('fieldset', 'legend'))) {
  2289. if (isset($param['moveTop'])) $this->parsingCss->value['margin']['t'] += $param['moveTop'];
  2290. if (isset($param['moveLeft'])) $this->parsingCss->value['margin']['l'] += $param['moveLeft'];
  2291. if (isset($param['moveDown'])) $this->parsingCss->value['margin']['b'] += $param['moveDown'];
  2292. }
  2293. $alignObject = null;
  2294. if ($this->parsingCss->value['margin-auto']) $alignObject = 'center';
  2295. $marge = array();
  2296. $marge['l'] = $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['padding']['l']+0.03;
  2297. $marge['r'] = $this->parsingCss->value['border']['r']['width'] + $this->parsingCss->value['padding']['r']+0.03;
  2298. $marge['t'] = $this->parsingCss->value['border']['t']['width'] + $this->parsingCss->value['padding']['t']+0.03;
  2299. $marge['b'] = $this->parsingCss->value['border']['b']['width'] + $this->parsingCss->value['padding']['b']+0.03;
  2300. // extract the content of the div
  2301. $level = $this->parsingHtml->getLevel($this->_parsePos);
  2302. // create a sub HTML2PDF to get the dimensions of the content of the div
  2303. $w = 0; $h = 0;
  2304. if (count($level)) {
  2305. $sub = null;
  2306. $this->_createSubHTML($sub);
  2307. $sub->parsingHtml->code = $level;
  2308. $sub->_makeHTMLcode();
  2309. $w = $sub->_maxX;
  2310. $h = $sub->_maxY;
  2311. $this->_destroySubHTML($sub);
  2312. }
  2313. $wReel = $w;
  2314. $hReel = $h;
  2315. $w+= $marge['l']+$marge['r']+0.001;
  2316. $h+= $marge['t']+$marge['b']+0.001;
  2317. if ($this->parsingCss->value['overflow']=='hidden') {
  2318. $overW = max($w, $this->parsingCss->value['width']);
  2319. $overH = max($h, $this->parsingCss->value['height']);
  2320. $overflow = true;
  2321. $this->parsingCss->value['old_maxX'] = $this->_maxX;
  2322. $this->parsingCss->value['old_maxY'] = $this->_maxY;
  2323. $this->parsingCss->value['old_maxH'] = $this->_maxH;
  2324. $this->parsingCss->value['old_overflow'] = $this->_isInOverflow;
  2325. $this->_isInOverflow = true;
  2326. } else {
  2327. $overW = null;
  2328. $overH = null;
  2329. $overflow = false;
  2330. $this->parsingCss->value['width'] = max($w, $this->parsingCss->value['width']);
  2331. $this->parsingCss->value['height'] = max($h, $this->parsingCss->value['height']);
  2332. }
  2333. switch($this->parsingCss->value['rotate'])
  2334. {
  2335. case 90:
  2336. $tmp = $overH; $overH = $overW; $overW = $tmp;
  2337. $tmp = $hReel; $hReel = $wReel; $wReel = $tmp;
  2338. unset($tmp);
  2339. $w = $this->parsingCss->value['height'];
  2340. $h = $this->parsingCss->value['width'];
  2341. $tX =-$h;
  2342. $tY = 0;
  2343. break;
  2344. case 180:
  2345. $w = $this->parsingCss->value['width'];
  2346. $h = $this->parsingCss->value['height'];
  2347. $tX = -$w;
  2348. $tY = -$h;
  2349. break;
  2350. case 270:
  2351. $tmp = $overH; $overH = $overW; $overW = $tmp;
  2352. $tmp = $hReel; $hReel = $wReel; $wReel = $tmp;
  2353. unset($tmp);
  2354. $w = $this->parsingCss->value['height'];
  2355. $h = $this->parsingCss->value['width'];
  2356. $tX = 0;
  2357. $tY =-$w;
  2358. break;
  2359. default:
  2360. $w = $this->parsingCss->value['width'];
  2361. $h = $this->parsingCss->value['height'];
  2362. $tX = 0;
  2363. $tY = 0;
  2364. break;
  2365. }
  2366. if (!$this->parsingCss->value['position']) {
  2367. if (
  2368. $w < ($this->pdf->getW() - $this->pdf->getlMargin()-$this->pdf->getrMargin()) &&
  2369. $this->pdf->getX() + $w>=($this->pdf->getW() - $this->pdf->getrMargin())
  2370. )
  2371. $this->_tag_open_BR(array());
  2372. if (
  2373. ($h < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin())) &&
  2374. ($this->pdf->getY() + $h>=($this->pdf->getH() - $this->pdf->getbMargin())) &&
  2375. !$this->_isInOverflow
  2376. )
  2377. $this->_setNewPage();
  2378. $old = $this->parsingCss->getOldValues();
  2379. $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  2380. if ($parentWidth>$w) {
  2381. if ($alignObject=='center') $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
  2382. else if ($alignObject=='right') $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
  2383. }
  2384. $this->parsingCss->setPosition();
  2385. } else {
  2386. $old = $this->parsingCss->getOldValues();
  2387. $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  2388. if ($parentWidth>$w) {
  2389. if ($alignObject=='center') $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
  2390. else if ($alignObject=='right') $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
  2391. }
  2392. $this->parsingCss->setPosition();
  2393. $this->_saveMax();
  2394. $this->_maxX = 0;
  2395. $this->_maxY = 0;
  2396. $this->_maxH = 0;
  2397. $this->_maxE = 0;
  2398. }
  2399. if ($this->parsingCss->value['rotate']) {
  2400. $this->pdf->startTransform();
  2401. $this->pdf->setRotation($this->parsingCss->value['rotate']);
  2402. $this->pdf->setTranslate($tX, $tY);
  2403. }
  2404. $this->_drawRectangle(
  2405. $this->parsingCss->value['x'],
  2406. $this->parsingCss->value['y'],
  2407. $this->parsingCss->value['width'],
  2408. $this->parsingCss->value['height'],
  2409. $this->parsingCss->value['border'],
  2410. $this->parsingCss->value['padding'],
  2411. 0,
  2412. $this->parsingCss->value['background']
  2413. );
  2414. $marge = array();
  2415. $marge['l'] = $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['padding']['l']+0.03;
  2416. $marge['r'] = $this->parsingCss->value['border']['r']['width'] + $this->parsingCss->value['padding']['r']+0.03;
  2417. $marge['t'] = $this->parsingCss->value['border']['t']['width'] + $this->parsingCss->value['padding']['t']+0.03;
  2418. $marge['b'] = $this->parsingCss->value['border']['b']['width'] + $this->parsingCss->value['padding']['b']+0.03;
  2419. $this->parsingCss->value['width'] -= $marge['l']+$marge['r'];
  2420. $this->parsingCss->value['height']-= $marge['t']+$marge['b'];
  2421. $xCorr = 0;
  2422. $yCorr = 0;
  2423. if (!$this->_subPart && !$this->_isSubPart) {
  2424. switch($this->parsingCss->value['text-align'])
  2425. {
  2426. case 'right':
  2427. $xCorr = ($this->parsingCss->value['width']-$wReel);
  2428. break;
  2429. case 'center':
  2430. $xCorr = ($this->parsingCss->value['width']-$wReel)*0.5;
  2431. break;
  2432. }
  2433. if ($xCorr>0) $xCorr=0;
  2434. switch($this->parsingCss->value['vertical-align'])
  2435. {
  2436. case 'bottom':
  2437. $yCorr = ($this->parsingCss->value['height']-$hReel);
  2438. break;
  2439. case 'middle':
  2440. $yCorr = ($this->parsingCss->value['height']-$hReel)*0.5;
  2441. break;
  2442. }
  2443. }
  2444. if ($overflow) {
  2445. $overW-= $marge['l']+$marge['r'];
  2446. $overH-= $marge['t']+$marge['b'];
  2447. $this->pdf->clippingPathStart(
  2448. $this->parsingCss->value['x']+$marge['l'],
  2449. $this->parsingCss->value['y']+$marge['t'],
  2450. $this->parsingCss->value['width'],
  2451. $this->parsingCss->value['height']
  2452. );
  2453. $this->parsingCss->value['x']+= $xCorr;
  2454. // marges from the dimension of the content
  2455. $mL = $this->parsingCss->value['x']+$marge['l'];
  2456. $mR = $this->pdf->getW() - $mL - $overW;
  2457. } else {
  2458. // marges from the dimension of the div
  2459. $mL = $this->parsingCss->value['x']+$marge['l'];
  2460. $mR = $this->pdf->getW() - $mL - $this->parsingCss->value['width'];
  2461. }
  2462. $x = $this->parsingCss->value['x']+$marge['l'];
  2463. $y = $this->parsingCss->value['y']+$marge['t']+$yCorr;
  2464. $this->_saveMargin($mL, 0, $mR);
  2465. $this->pdf->setXY($x, $y);
  2466. $this->_setNewPositionForNewLine();
  2467. return true;
  2468. }
  2469. /**
  2470. * tag : BLOCKQUOTE
  2471. * mode : OPEN
  2472. *
  2473. * @param array $param
  2474. * @return boolean
  2475. */
  2476. protected function _tag_open_BLOCKQUOTE($param)
  2477. {
  2478. return $this->_tag_open_DIV($param, 'blockquote');
  2479. }
  2480. /**
  2481. * tag : LEGEND
  2482. * mode : OPEN
  2483. *
  2484. * @param array $param
  2485. * @return boolean
  2486. */
  2487. protected function _tag_open_LEGEND($param)
  2488. {
  2489. return $this->_tag_open_DIV($param, 'legend');
  2490. }
  2491. /**
  2492. * tag : FIELDSET
  2493. * mode : OPEN
  2494. *
  2495. * @author Pavel Kochman
  2496. * @param array $param
  2497. * @return boolean
  2498. */
  2499. protected function _tag_open_FIELDSET($param)
  2500. {
  2501. $this->parsingCss->save();
  2502. $this->parsingCss->analyse('fieldset', $param);
  2503. // get height of LEGEND element and make fieldset corrections
  2504. for ($tempPos = $this->_parsePos + 1; $tempPos<count($this->parsingHtml->code); $tempPos++) {
  2505. $action = $this->parsingHtml->code[$tempPos];
  2506. if ($action['name'] == 'fieldset') break;
  2507. if ($action['name'] == 'legend' && !$action['close']) {
  2508. $legendOpenPos = $tempPos;
  2509. $sub = null;
  2510. $this->_createSubHTML($sub);
  2511. $sub->parsingHtml->code = $this->parsingHtml->getLevel($tempPos - 1);
  2512. $res = null;
  2513. for ($sub->_parsePos = 0; $sub->_parsePos<count($sub->parsingHtml->code); $sub->_parsePos++) {
  2514. $action = $sub->parsingHtml->code[$sub->_parsePos];
  2515. $sub->_executeAction($action);
  2516. if ($action['name'] == 'legend' && $action['close'])
  2517. break;
  2518. }
  2519. $legendH = $sub->_maxY;
  2520. $this->_destroySubHTML($sub);
  2521. $move = $this->parsingCss->value['padding']['t'] + $this->parsingCss->value['border']['t']['width'] + 0.03;
  2522. $param['moveTop'] = $legendH / 2;
  2523. $this->parsingHtml->code[$legendOpenPos]['param']['moveTop'] = - ($legendH / 2 + $move);
  2524. $this->parsingHtml->code[$legendOpenPos]['param']['moveLeft'] = 2 - $this->parsingCss->value['border']['l']['width'] - $this->parsingCss->value['padding']['l'];
  2525. $this->parsingHtml->code[$legendOpenPos]['param']['moveDown'] = $move;
  2526. break;
  2527. }
  2528. }
  2529. $this->parsingCss->load();
  2530. return $this->_tag_open_DIV($param, 'fieldset');
  2531. }
  2532. /**
  2533. * tag : DIV
  2534. * mode : CLOSE
  2535. *
  2536. * @param array $param
  2537. * @param string $other name of tag that used the div tag
  2538. * @return boolean
  2539. */
  2540. protected function _tag_close_DIV($param, $other='div')
  2541. {
  2542. if ($this->_isForOneLine) return false;
  2543. if ($this->parsingCss->value['overflow']=='hidden') {
  2544. $this->_maxX = $this->parsingCss->value['old_maxX'];
  2545. $this->_maxY = $this->parsingCss->value['old_maxY'];
  2546. $this->_maxH = $this->parsingCss->value['old_maxH'];
  2547. $this->_isInOverflow = $this->parsingCss->value['old_overflow'];
  2548. $this->pdf->clippingPathStop();
  2549. }
  2550. if ($this->parsingCss->value['rotate'])
  2551. $this->pdf->stopTransform();
  2552. $marge = array();
  2553. $marge['l'] = $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['padding']['l']+0.03;
  2554. $marge['r'] = $this->parsingCss->value['border']['r']['width'] + $this->parsingCss->value['padding']['r']+0.03;
  2555. $marge['t'] = $this->parsingCss->value['border']['t']['width'] + $this->parsingCss->value['padding']['t']+0.03;
  2556. $marge['b'] = $this->parsingCss->value['border']['b']['width'] + $this->parsingCss->value['padding']['b']+0.03;
  2557. $x = $this->parsingCss->value['x'];
  2558. $y = $this->parsingCss->value['y'];
  2559. $w = $this->parsingCss->value['width']+$marge['l']+$marge['r']+$this->parsingCss->value['margin']['r'];
  2560. $h = $this->parsingCss->value['height']+$marge['t']+$marge['b']+$this->parsingCss->value['margin']['b'];
  2561. switch($this->parsingCss->value['rotate'])
  2562. {
  2563. case 90:
  2564. $t = $w; $w = $h; $h = $t;
  2565. break;
  2566. case 270:
  2567. $t = $w; $w = $h; $h = $t;
  2568. break;
  2569. default:
  2570. break;
  2571. }
  2572. if ($this->parsingCss->value['position']!='absolute') {
  2573. $this->pdf->setXY($x+$w, $y);
  2574. $this->_maxX = max($this->_maxX, $x+$w);
  2575. $this->_maxY = max($this->_maxY, $y+$h);
  2576. $this->_maxH = max($this->_maxH, $h);
  2577. } else {
  2578. $this->pdf->setXY($this->parsingCss->value['xc'], $this->parsingCss->value['yc']);
  2579. $this->_loadMax();
  2580. }
  2581. $block = ($this->parsingCss->value['display']!='inline' && $this->parsingCss->value['position']!='absolute');
  2582. $this->parsingCss->load();
  2583. $this->parsingCss->fontSet();
  2584. $this->_loadMargin();
  2585. if ($block) $this->_tag_open_BR(array());
  2586. if ($this->_debugActif) $this->_DEBUG_add(strtoupper($other), false);
  2587. return true;
  2588. }
  2589. /**
  2590. * tag : BLOCKQUOTE
  2591. * mode : CLOSE
  2592. *
  2593. * @param array $param
  2594. * @return boolean
  2595. */
  2596. protected function _tag_close_BLOCKQUOTE($param)
  2597. {
  2598. return $this->_tag_close_DIV($param, 'blockquote');
  2599. }
  2600. /**
  2601. * tag : FIELDSET
  2602. * mode : CLOSE
  2603. *
  2604. * @param array $param
  2605. * @return boolean
  2606. */
  2607. protected function _tag_close_FIELDSET($param)
  2608. {
  2609. return $this->_tag_close_DIV($param, 'fieldset');
  2610. }
  2611. /**
  2612. * tag : LEGEND
  2613. * mode : CLOSE
  2614. *
  2615. * @param array $param
  2616. * @return boolean
  2617. */
  2618. protected function _tag_close_LEGEND($param)
  2619. {
  2620. return $this->_tag_close_DIV($param, 'legend');
  2621. }
  2622. /**
  2623. * tag : BARCODE
  2624. * mode : OPEN
  2625. *
  2626. * @param array $param
  2627. * @return boolean
  2628. */
  2629. protected function _tag_open_BARCODE($param)
  2630. {
  2631. // for compatibility with old versions < 3.29
  2632. $lstBarcode = array();
  2633. $lstBarcode['UPC_A'] = 'UPCA';
  2634. $lstBarcode['CODE39'] = 'C39';
  2635. if (!isset($param['type'])) $param['type'] = 'C39';
  2636. if (!isset($param['value'])) $param['value'] = 0;
  2637. if (!isset($param['label'])) $param['label'] = 'label';
  2638. if (!isset($param['style']['color'])) $param['style']['color'] = '#000000';
  2639. if ($this->_testIsDeprecated && (isset($param['bar_h']) || isset($param['bar_w'])))
  2640. throw new HTML2PDF_exception(9, array('BARCODE', 'bar_h, bar_w'));
  2641. $param['type'] = strtoupper($param['type']);
  2642. if (isset($lstBarcode[$param['type']])) $param['type'] = $lstBarcode[$param['type']];
  2643. $this->parsingCss->save();
  2644. $this->parsingCss->analyse('barcode', $param);
  2645. $this->parsingCss->setPosition();
  2646. $this->parsingCss->fontSet();
  2647. $x = $this->pdf->getX();
  2648. $y = $this->pdf->getY();
  2649. $w = $this->parsingCss->value['width']; if (!$w) $w = $this->parsingCss->ConvertToMM('50mm');
  2650. $h = $this->parsingCss->value['height']; if (!$h) $h = $this->parsingCss->ConvertToMM('10mm');
  2651. $txt = ($param['label']!=='none' ? $this->parsingCss->value['font-size'] : false);
  2652. $c = $this->parsingCss->value['color'];
  2653. $infos = $this->pdf->myBarcode($param['value'], $param['type'], $x, $y, $w, $h, $txt, $c);
  2654. $this->_maxX = max($this->_maxX, $x+$infos[0]);
  2655. $this->_maxY = max($this->_maxY, $y+$infos[1]);
  2656. $this->_maxH = max($this->_maxH, $infos[1]);
  2657. $this->_maxE++;
  2658. $this->pdf->setXY($x+$infos[0], $y);
  2659. $this->parsingCss->load();
  2660. $this->parsingCss->fontSet();
  2661. return true;
  2662. }
  2663. /**
  2664. * tag : BARCODE
  2665. * mode : CLOSE
  2666. *
  2667. * @param array $param
  2668. * @return boolean
  2669. */
  2670. protected function _tag_close_BARCODE($param)
  2671. {
  2672. // there is nothing to do here
  2673. return true;
  2674. }
  2675. /**
  2676. * tag : QRCODE
  2677. * mode : OPEN
  2678. *
  2679. * @param array $param
  2680. * @return boolean
  2681. */
  2682. protected function _tag_open_QRCODE($param)
  2683. {
  2684. if ($this->_testIsDeprecated && (isset($param['size']) || isset($param['noborder'])))
  2685. throw new HTML2PDF_exception(9, array('QRCODE', 'size, noborder'));
  2686. if ($this->_debugActif) $this->_DEBUG_add('QRCODE');
  2687. if (!isset($param['value'])) $param['value'] = '';
  2688. if (!isset($param['ec'])) $param['ec'] = 'H';
  2689. if (!isset($param['style']['color'])) $param['style']['color'] = '#000000';
  2690. if (!isset($param['style']['background-color'])) $param['style']['background-color'] = '#FFFFFF';
  2691. if (isset($param['style']['border'])) {
  2692. $borders = $param['style']['border']!='none';
  2693. unset($param['style']['border']);
  2694. } else {
  2695. $borders = true;
  2696. }
  2697. if ($param['value']==='') return true;
  2698. if (!in_array($param['ec'], array('L', 'M', 'Q', 'H'))) $param['ec'] = 'H';
  2699. $this->parsingCss->save();
  2700. $this->parsingCss->analyse('qrcode', $param);
  2701. $this->parsingCss->setPosition();
  2702. $this->parsingCss->fontSet();
  2703. $x = $this->pdf->getX();
  2704. $y = $this->pdf->getY();
  2705. $w = $this->parsingCss->value['width'];
  2706. $h = $this->parsingCss->value['height'];
  2707. $size = max($w, $h); if (!$size) $size = $this->parsingCss->ConvertToMM('50mm');
  2708. $style = array(
  2709. 'fgcolor' => $this->parsingCss->value['color'],
  2710. 'bgcolor' => $this->parsingCss->value['background']['color'],
  2711. );
  2712. if ($borders) {
  2713. $style['border'] = true;
  2714. $style['padding'] = 'auto';
  2715. } else {
  2716. $style['border'] = false;
  2717. $style['padding'] = 0;
  2718. }
  2719. if (!$this->_subPart && !$this->_isSubPart) {
  2720. $this->pdf->write2DBarcode($param['value'], 'QRCODE,'.$param['ec'], $x, $y, $size, $size, $style);
  2721. }
  2722. $this->_maxX = max($this->_maxX, $x+$size);
  2723. $this->_maxY = max($this->_maxY, $y+$size);
  2724. $this->_maxH = max($this->_maxH, $size);
  2725. $this->_maxE++;
  2726. $this->pdf->setX($x+$size);
  2727. $this->parsingCss->load();
  2728. $this->parsingCss->fontSet();
  2729. return true;
  2730. }
  2731. /**
  2732. * tag : QRCODE
  2733. * mode : CLOSE
  2734. *
  2735. * @param array $param
  2736. * @return boolean
  2737. */
  2738. protected function _tag_close_QRCODE($param)
  2739. {
  2740. // there is nothing to do here
  2741. return true;
  2742. }
  2743. /**
  2744. * tag : BOOKMARK
  2745. * mode : OPEN
  2746. *
  2747. * @param array $param
  2748. * @return boolean
  2749. */
  2750. protected function _tag_open_BOOKMARK($param)
  2751. {
  2752. $titre = isset($param['title']) ? trim($param['title']) : '';
  2753. $level = isset($param['level']) ? floor($param['level']) : 0;
  2754. if ($level<0) $level = 0;
  2755. if ($titre) $this->pdf->Bookmark($titre, $level, -1);
  2756. return true;
  2757. }
  2758. /**
  2759. * tag : BOOKMARK
  2760. * mode : CLOSE
  2761. *
  2762. * @param array $param
  2763. * @return boolean
  2764. */
  2765. protected function _tag_close_BOOKMARK($param)
  2766. {
  2767. // there is nothing to do here
  2768. return true;
  2769. }
  2770. /**
  2771. * this is not a real TAG, it is just to write texts
  2772. *
  2773. * @param array $param
  2774. * @return boolean
  2775. */
  2776. protected function _tag_open_WRITE($param)
  2777. {
  2778. $fill = ($this->parsingCss->value['background']['color']!==null && $this->parsingCss->value['background']['image']===null);
  2779. if (in_array($this->parsingCss->value['id_tag'], array('fieldset', 'legend', 'div', 'table', 'tr', 'td', 'th'))) {
  2780. $fill = false;
  2781. }
  2782. // get the text to write
  2783. $txt = $param['txt'];
  2784. if ($this->_isAfterFloat) {
  2785. $txt = ltrim($txt);
  2786. $this->_isAfterFloat = false;
  2787. }
  2788. $txt = str_replace('[[page_nb]]', $this->pdf->getMyAliasNbPages(), $txt);
  2789. $txt = str_replace('[[page_cu]]', $this->pdf->getMyNumPage($this->_page), $txt);
  2790. if ($this->parsingCss->value['text-transform']!='none') {
  2791. if ($this->parsingCss->value['text-transform']=='capitalize')
  2792. $txt = ucwords($txt);
  2793. else if ($this->parsingCss->value['text-transform']=='uppercase')
  2794. $txt = strtoupper($txt);
  2795. else if ($this->parsingCss->value['text-transform']=='lowercase')
  2796. $txt = strtolower($txt);
  2797. }
  2798. // size of the text
  2799. $h = 1.08*$this->parsingCss->value['font-size'];
  2800. $dh = $h*$this->parsingCss->value['mini-decal'];
  2801. $lh = $this->parsingCss->getLineHeight();
  2802. // identify the align
  2803. $align = 'L';
  2804. if ($this->parsingCss->value['text-align']=='li_right') {
  2805. $w = $this->parsingCss->value['width'];
  2806. $align = 'R';
  2807. }
  2808. // calculate the width of each words, and of all the sentence
  2809. $w = 0;
  2810. $words = explode(' ', $txt);
  2811. foreach ($words as $k => $word) {
  2812. $words[$k] = array($word, $this->pdf->GetStringWidth($word));
  2813. $w+= $words[$k][1];
  2814. }
  2815. $space = $this->pdf->GetStringWidth(' ');
  2816. $w+= $space*(count($words)-1);
  2817. // position in the text
  2818. $currPos = 0;
  2819. // the bigger width of the text, after automatic break line
  2820. $maxX = 0;
  2821. // position of the text
  2822. $x = $this->pdf->getX();
  2823. $y = $this->pdf->getY();
  2824. $dy = $this->_getElementY($lh);
  2825. // margins
  2826. list($left, $right) = $this->_getMargins($y);
  2827. // number of lines after automatic break line
  2828. $nb = 0;
  2829. // while we have words, and the text does not fit on the line => we cut the sentence
  2830. while ($x+$w>$right && $x<$right+$space && count($words)) {
  2831. // adding words 1 by 1 to fit on the line
  2832. $i=0;
  2833. $old = array('', 0);
  2834. $str = $words[0];
  2835. $add = false;
  2836. while (($x+$str[1])<$right) {
  2837. $i++;
  2838. $add = true;
  2839. array_shift($words);
  2840. $old = $str;
  2841. if (!count($words)) break;
  2842. $str[0].= ' '.$words[0][0];
  2843. $str[1]+= $space+$words[0][1];
  2844. }
  2845. $str = $old;
  2846. // if nothing fit on the line, and if the first word does not fit on the line => the word is too long, we put it
  2847. if ($i==0 && (($left+$words[0][1])>=$right)) {
  2848. $str = $words[0];
  2849. array_shift($words);
  2850. $i++;
  2851. $add = true;
  2852. }
  2853. $currPos+= ($currPos ? 1 : 0)+strlen($str[0]);
  2854. // write the extract sentence that fit on the page
  2855. $wc = ($align=='L' ? $str[1] : $this->parsingCss->value['width']);
  2856. if ($right - $left<$wc) $wc = $right - $left;
  2857. if (strlen($str[0])) {
  2858. $this->pdf->setXY($this->pdf->getX(), $y+$dh+$dy);
  2859. $this->pdf->Cell($wc, $h, $str[0], 0, 0, $align, $fill, $this->_isInLink);
  2860. $this->pdf->setXY($this->pdf->getX(), $y);
  2861. }
  2862. $this->_maxH = max($this->_maxH, $lh);
  2863. // max width
  2864. $maxX = max($maxX, $this->pdf->getX());
  2865. // new position and new width for the "while"
  2866. $w-= $str[1];
  2867. $y = $this->pdf->getY();
  2868. $x = $this->pdf->getX();
  2869. $dy = $this->_getElementY($lh);
  2870. // if we have again words to write
  2871. if (count($words)) {
  2872. // remove the space at the end
  2873. if ($add) $w-= $space;
  2874. // if we don't add any word, and if the first word is empty => useless space to skip
  2875. if (!$add && $words[0][0]==='') {
  2876. array_shift($words);
  2877. }
  2878. // if it is just to calculate for one line => adding the number of words
  2879. if ($this->_isForOneLine) {
  2880. $this->_maxE+= $i;
  2881. $this->_maxX = max($this->_maxX, $maxX);
  2882. return null;
  2883. }
  2884. // automatic line break
  2885. $this->_tag_open_BR(array('style' => ''), $currPos);
  2886. // new position
  2887. $y = $this->pdf->getY();
  2888. $x = $this->pdf->getX();
  2889. $dy = $this->_getElementY($lh);
  2890. // if the next line does not fit on the page => new page
  2891. if ($y + $h>=$this->pdf->getH() - $this->pdf->getbMargin()) {
  2892. if (!$this->_isInOverflow && !$this->_isInFooter) {
  2893. $this->_setNewPage(null, '', null, $currPos);
  2894. $y = $this->pdf->getY();
  2895. $x = $this->pdf->getX();
  2896. $dy = $this->_getElementY($lh);
  2897. }
  2898. }
  2899. // if more than 10000 line => error
  2900. $nb++;
  2901. if ($nb>10000) {
  2902. $txt = ''; foreach ($words as $k => $word) $txt.= ($k ? ' ' : '').$word[0];
  2903. throw new HTML2PDF_exception(2, array($txt, $right-$left, $w));
  2904. }
  2905. // new margins for the new line
  2906. list($left, $right) = $this->_getMargins($y);
  2907. }
  2908. }
  2909. // if we have words after automatic cut, it is because they fit on the line => we write the text
  2910. if (count($words)) {
  2911. $txt = ''; foreach ($words as $k => $word) $txt.= ($k ? ' ' : '').$word[0];
  2912. $w+= $this->pdf->getWordSpacing()*(count($words));
  2913. $this->pdf->setXY($this->pdf->getX(), $y+$dh+$dy);
  2914. $this->pdf->Cell(($align=='L' ? $w : $this->parsingCss->value['width']), $h, $txt, 0, 0, $align, $fill, $this->_isInLink);
  2915. $this->pdf->setXY($this->pdf->getX(), $y);
  2916. $this->_maxH = max($this->_maxH, $lh);
  2917. $this->_maxE+= count($words);
  2918. }
  2919. $maxX = max($maxX, $this->pdf->getX());
  2920. $maxY = $this->pdf->getY()+$h;
  2921. $this->_maxX = max($this->_maxX, $maxX);
  2922. $this->_maxY = max($this->_maxY, $maxY);
  2923. return true;
  2924. }
  2925. /**
  2926. * tag : BR
  2927. * mode : OPEN
  2928. *
  2929. * @param array $param
  2930. * @param integer $curr real position in the html parseur (if break line in the write of a text)
  2931. * @return boolean
  2932. */
  2933. protected function _tag_open_BR($param, $curr = null)
  2934. {
  2935. if ($this->_isForOneLine) return false;
  2936. $h = max($this->_maxH, $this->parsingCss->getLineHeight());
  2937. if ($this->_maxH==0) $this->_maxY = max($this->_maxY, $this->pdf->getY()+$h);
  2938. $this->_makeBreakLine($h, $curr);
  2939. $this->_maxH = 0;
  2940. $this->_maxE = 0;
  2941. return true;
  2942. }
  2943. /**
  2944. * tag : HR
  2945. * mode : OPEN
  2946. *
  2947. * @param array $param
  2948. * @return boolean
  2949. */
  2950. protected function _tag_open_HR($param)
  2951. {
  2952. if ($this->_isForOneLine) return false;
  2953. $oldAlign = $this->parsingCss->value['text-align'];
  2954. $this->parsingCss->value['text-align'] = 'left';
  2955. if ($this->_maxH) $this->_tag_open_BR($param);
  2956. $fontSize = $this->parsingCss->value['font-size'];
  2957. $this->parsingCss->value['font-size']=$fontSize*0.5; $this->_tag_open_BR($param);
  2958. $this->parsingCss->value['font-size']=0;
  2959. $param['style']['width'] = '100%';
  2960. $this->parsingCss->save();
  2961. $this->parsingCss->value['height']=$this->parsingCss->ConvertToMM('1mm');
  2962. $this->parsingCss->analyse('hr', $param);
  2963. $this->parsingCss->setPosition();
  2964. $this->parsingCss->fontSet();
  2965. $h = $this->parsingCss->value['height'];
  2966. if ($h) $h-= $this->parsingCss->value['border']['t']['width']+$this->parsingCss->value['border']['b']['width'];
  2967. if ($h<=0) $h = $this->parsingCss->value['border']['t']['width']+$this->parsingCss->value['border']['b']['width'];
  2968. $this->_drawRectangle($this->pdf->getX(), $this->pdf->getY(), $this->parsingCss->value['width'], $h, $this->parsingCss->value['border'], 0, 0, $this->parsingCss->value['background']);
  2969. $this->_maxH = $h;
  2970. $this->parsingCss->load();
  2971. $this->parsingCss->fontSet();
  2972. $this->_tag_open_BR($param);
  2973. $this->parsingCss->value['font-size']=$fontSize*0.5; $this->_tag_open_BR($param);
  2974. $this->parsingCss->value['font-size']=$fontSize;
  2975. $this->parsingCss->value['text-align'] = $oldAlign;
  2976. $this->_setNewPositionForNewLine();
  2977. return true;
  2978. }
  2979. /**
  2980. * tag : B
  2981. * mode : OPEN
  2982. *
  2983. * @param array $param
  2984. * @param string $other
  2985. * @return boolean
  2986. */
  2987. protected function _tag_open_B($param, $other = 'b')
  2988. {
  2989. $this->parsingCss->save();
  2990. $this->parsingCss->value['font-bold'] = true;
  2991. $this->parsingCss->analyse($other, $param);
  2992. $this->parsingCss->setPosition();
  2993. $this->parsingCss->fontSet();
  2994. return true;
  2995. }
  2996. /**
  2997. * tag : STRONG
  2998. * mode : OPEN
  2999. *
  3000. * @param array $param
  3001. * @return boolean
  3002. */
  3003. protected function _tag_open_STRONG($param)
  3004. {
  3005. return $this->_tag_open_B($param, 'strong');
  3006. }
  3007. /**
  3008. * tag : B
  3009. * mode : CLOSE
  3010. *
  3011. * @param array $param
  3012. * @return boolean
  3013. */
  3014. protected function _tag_close_B($param)
  3015. {
  3016. $this->parsingCss->load();
  3017. $this->parsingCss->fontSet();
  3018. return true;
  3019. }
  3020. /**
  3021. * tag : STRONG
  3022. * mode : CLOSE
  3023. *
  3024. * @param array $param
  3025. * @return boolean
  3026. */
  3027. protected function _tag_close_STRONG($param)
  3028. {
  3029. return $this->_tag_close_B($param);
  3030. }
  3031. /**
  3032. * tag : I
  3033. * mode : OPEN
  3034. *
  3035. * @param array $param
  3036. * @param string $other
  3037. * @return boolean
  3038. */
  3039. protected function _tag_open_I($param, $other = 'i')
  3040. {
  3041. $this->parsingCss->save();
  3042. $this->parsingCss->value['font-italic'] = true;
  3043. $this->parsingCss->analyse($other, $param);
  3044. $this->parsingCss->setPosition();
  3045. $this->parsingCss->fontSet();
  3046. return true;
  3047. }
  3048. /**
  3049. * tag : ADDRESS
  3050. * mode : OPEN
  3051. *
  3052. * @param array $param
  3053. * @return boolean
  3054. */
  3055. protected function _tag_open_ADDRESS($param)
  3056. {
  3057. return $this->_tag_open_I($param, 'address');
  3058. }
  3059. /**
  3060. * tag : CITE
  3061. * mode : OPEN
  3062. *
  3063. * @param array $param
  3064. * @return boolean
  3065. */
  3066. protected function _tag_open_CITE($param)
  3067. {
  3068. return $this->_tag_open_I($param, 'cite');
  3069. }
  3070. /**
  3071. * tag : EM
  3072. * mode : OPEN
  3073. *
  3074. * @param array $param
  3075. * @return boolean
  3076. */
  3077. protected function _tag_open_EM($param)
  3078. {
  3079. return $this->_tag_open_I($param, 'em');
  3080. }
  3081. /**
  3082. * tag : SAMP
  3083. * mode : OPEN
  3084. *
  3085. * @param array $param
  3086. * @return boolean
  3087. */
  3088. protected function _tag_open_SAMP($param)
  3089. {
  3090. return $this->_tag_open_I($param, 'samp');
  3091. }
  3092. /**
  3093. * tag : I
  3094. * mode : CLOSE
  3095. *
  3096. * @param array $param
  3097. * @return boolean
  3098. */
  3099. protected function _tag_close_I($param)
  3100. {
  3101. $this->parsingCss->load();
  3102. $this->parsingCss->fontSet();
  3103. return true;
  3104. }
  3105. /**
  3106. * tag : ADDRESS
  3107. * mode : CLOSE
  3108. *
  3109. * @param array $param
  3110. * @return boolean
  3111. */
  3112. protected function _tag_close_ADDRESS($param)
  3113. {
  3114. return $this->_tag_close_I($param);
  3115. }
  3116. /**
  3117. * tag : CITE
  3118. * mode : CLOSE
  3119. *
  3120. * @param array $param
  3121. * @return boolean
  3122. */
  3123. protected function _tag_close_CITE($param)
  3124. {
  3125. return $this->_tag_close_I($param);
  3126. }
  3127. /**
  3128. * tag : EM
  3129. * mode : CLOSE
  3130. *
  3131. * @param array $param
  3132. * @return boolean
  3133. */
  3134. protected function _tag_close_EM($param)
  3135. {
  3136. return $this->_tag_close_I($param);
  3137. }
  3138. /**
  3139. * tag : SAMP
  3140. * mode : CLOSE
  3141. *
  3142. * @param array $param
  3143. * @return boolean
  3144. */
  3145. protected function _tag_close_SAMP($param)
  3146. {
  3147. return $this->_tag_close_I($param);
  3148. }
  3149. /**
  3150. * tag : S
  3151. * mode : OPEN
  3152. *
  3153. * @param array $param
  3154. * @param string $other
  3155. * @return boolean
  3156. */
  3157. protected function _tag_open_S($param, $other = 's')
  3158. {
  3159. $this->parsingCss->save();
  3160. $this->parsingCss->value['font-linethrough'] = true;
  3161. $this->parsingCss->analyse($other, $param);
  3162. $this->parsingCss->setPosition();
  3163. $this->parsingCss->fontSet();
  3164. return true;
  3165. }
  3166. /**
  3167. * tag : DEL
  3168. * mode : OPEN
  3169. *
  3170. * @param array $param
  3171. * @return boolean
  3172. */
  3173. protected function _tag_open_DEL($param)
  3174. {
  3175. return $this->_tag_open_S($param, 'del');
  3176. }
  3177. /**
  3178. * tag : S
  3179. * mode : CLOSE
  3180. *
  3181. * @param array $param
  3182. * @return boolean
  3183. */
  3184. protected function _tag_close_S($param)
  3185. {
  3186. $this->parsingCss->load();
  3187. $this->parsingCss->fontSet();
  3188. return true;
  3189. }
  3190. /**
  3191. * tag : DEL
  3192. * mode : CLOSE
  3193. *
  3194. * @param array $param
  3195. * @return boolean
  3196. */
  3197. protected function _tag_close_DEL($param)
  3198. {
  3199. return $this->_tag_close_S($param);
  3200. }
  3201. /**
  3202. * tag : U
  3203. * mode : OPEN
  3204. *
  3205. * @param array $param
  3206. * @param string $other
  3207. * @return boolean
  3208. */
  3209. protected function _tag_open_U($param, $other='u')
  3210. {
  3211. $this->parsingCss->save();
  3212. $this->parsingCss->value['font-underline'] = true;
  3213. $this->parsingCss->analyse($other, $param);
  3214. $this->parsingCss->setPosition();
  3215. $this->parsingCss->fontSet();
  3216. return true;
  3217. }
  3218. /**
  3219. * tag : INS
  3220. * mode : OPEN
  3221. *
  3222. * @param array $param
  3223. * @return boolean
  3224. */
  3225. protected function _tag_open_INS($param)
  3226. {
  3227. return $this->_tag_open_U($param, 'ins');
  3228. }
  3229. /**
  3230. * tag : U
  3231. * mode : CLOSE
  3232. *
  3233. * @param array $param
  3234. * @return boolean
  3235. */
  3236. protected function _tag_close_U($param)
  3237. {
  3238. $this->parsingCss->load();
  3239. $this->parsingCss->fontSet();
  3240. return true;
  3241. }
  3242. /**
  3243. * tag : INS
  3244. * mode : CLOSE
  3245. *
  3246. * @param array $param
  3247. * @return boolean
  3248. */
  3249. protected function _tag_close_INS($param)
  3250. {
  3251. return $this->_tag_close_U($param);
  3252. }
  3253. /**
  3254. * tag : A
  3255. * mode : OPEN
  3256. *
  3257. * @param array $param
  3258. * @return boolean
  3259. */
  3260. protected function _tag_open_A($param)
  3261. {
  3262. $this->_isInLink = str_replace('&amp;', '&', isset($param['href']) ? $param['href'] : '');
  3263. if (isset($param['name'])) {
  3264. $name = $param['name'];
  3265. if (!isset($this->_lstAnchor[$name])) $this->_lstAnchor[$name] = array($this->pdf->AddLink(), false);
  3266. if (!$this->_lstAnchor[$name][1]) {
  3267. $this->_lstAnchor[$name][1] = true;
  3268. $this->pdf->SetLink($this->_lstAnchor[$name][0], -1, -1);
  3269. }
  3270. }
  3271. if (preg_match('/^#([^#]+)$/isU', $this->_isInLink, $match)) {
  3272. $name = $match[1];
  3273. if (!isset($this->_lstAnchor[$name])) $this->_lstAnchor[$name] = array($this->pdf->AddLink(), false);
  3274. $this->_isInLink = $this->_lstAnchor[$name][0];
  3275. }
  3276. $this->parsingCss->save();
  3277. $this->parsingCss->value['font-underline'] = true;
  3278. $this->parsingCss->value['color'] = array(20, 20, 250);
  3279. $this->parsingCss->analyse('a', $param);
  3280. $this->parsingCss->setPosition();
  3281. $this->parsingCss->fontSet();
  3282. return true;
  3283. }
  3284. /**
  3285. * tag : A
  3286. * mode : CLOSE
  3287. *
  3288. * @param array $param
  3289. * @return boolean
  3290. */
  3291. protected function _tag_close_A($param)
  3292. {
  3293. $this->_isInLink = '';
  3294. $this->parsingCss->load();
  3295. $this->parsingCss->fontSet();
  3296. return true;
  3297. }
  3298. /**
  3299. * tag : H1
  3300. * mode : OPEN
  3301. *
  3302. * @param array $param
  3303. * @param string $other
  3304. * @return boolean
  3305. */
  3306. protected function _tag_open_H1($param, $other = 'h1')
  3307. {
  3308. if ($this->_isForOneLine) return false;
  3309. if ($this->_maxH) $this->_tag_open_BR(array());
  3310. $this->parsingCss->save();
  3311. $this->parsingCss->value['font-bold'] = true;
  3312. $size = array('h1' => '28px', 'h2' => '24px', 'h3' => '20px', 'h4' => '16px', 'h5' => '12px', 'h6' => '9px');
  3313. $this->parsingCss->value['margin']['l'] = 0;
  3314. $this->parsingCss->value['margin']['r'] = 0;
  3315. $this->parsingCss->value['margin']['t'] = $this->parsingCss->ConvertToMM('16px');
  3316. $this->parsingCss->value['margin']['b'] = $this->parsingCss->ConvertToMM('16px');
  3317. $this->parsingCss->value['font-size'] = $this->parsingCss->ConvertToMM($size[$other]);
  3318. $this->parsingCss->analyse($other, $param);
  3319. $this->parsingCss->setPosition();
  3320. $this->parsingCss->fontSet();
  3321. $this->_setNewPositionForNewLine();
  3322. return true;
  3323. }
  3324. /**
  3325. * tag : H2
  3326. * mode : OPEN
  3327. *
  3328. * @param array $param
  3329. * @return boolean
  3330. */
  3331. protected function _tag_open_H2($param)
  3332. {
  3333. return $this->_tag_open_H1($param, 'h2');
  3334. }
  3335. /**
  3336. * tag : H3
  3337. * mode : OPEN
  3338. *
  3339. * @param array $param
  3340. * @return boolean
  3341. */
  3342. protected function _tag_open_H3($param)
  3343. {
  3344. return $this->_tag_open_H1($param, 'h3');
  3345. }
  3346. /**
  3347. * tag : H4
  3348. * mode : OPEN
  3349. *
  3350. * @param array $param
  3351. * @return boolean
  3352. */
  3353. protected function _tag_open_H4($param)
  3354. {
  3355. return $this->_tag_open_H1($param, 'h4');
  3356. }
  3357. /**
  3358. * tag : H5
  3359. * mode : OPEN
  3360. *
  3361. * @param array $param
  3362. * @return boolean
  3363. */
  3364. protected function _tag_open_H5($param)
  3365. {
  3366. return $this->_tag_open_H1($param, 'h5');
  3367. }
  3368. /**
  3369. * tag : H6
  3370. * mode : OPEN
  3371. *
  3372. * @param array $param
  3373. * @return boolean
  3374. */
  3375. protected function _tag_open_H6($param)
  3376. {
  3377. return $this->_tag_open_H1($param, 'h6');
  3378. }
  3379. /**
  3380. * tag : H1
  3381. * mode : CLOSE
  3382. *
  3383. * @param array $param
  3384. * @return boolean
  3385. */
  3386. protected function _tag_close_H1($param)
  3387. {
  3388. if ($this->_isForOneLine) return false;
  3389. $this->_maxH+= $this->parsingCss->value['margin']['b'];
  3390. $h = max($this->_maxH, $this->parsingCss->getLineHeight());
  3391. $this->parsingCss->load();
  3392. $this->parsingCss->fontSet();
  3393. $this->_makeBreakLine($h);
  3394. $this->_maxH = 0;
  3395. $this->_maxY = max($this->_maxY, $this->pdf->getY());
  3396. return true;
  3397. }
  3398. /**
  3399. * tag : H2
  3400. * mode : CLOSE
  3401. *
  3402. * @param array $param
  3403. * @return boolean
  3404. */
  3405. protected function _tag_close_H2($param)
  3406. {
  3407. return $this->_tag_close_H1($param);
  3408. }
  3409. /**
  3410. * tag : H3
  3411. * mode : CLOSE
  3412. *
  3413. * @param array $param
  3414. * @return boolean
  3415. */
  3416. protected function _tag_close_H3($param)
  3417. {
  3418. return $this->_tag_close_H1($param);
  3419. }
  3420. /**
  3421. * tag : H4
  3422. * mode : CLOSE
  3423. *
  3424. * @param array $param
  3425. * @return boolean
  3426. */
  3427. protected function _tag_close_H4($param)
  3428. {
  3429. return $this->_tag_close_H1($param);
  3430. }
  3431. /**
  3432. * tag : H5
  3433. * mode : CLOSE
  3434. *
  3435. * @param array $param
  3436. * @return boolean
  3437. */
  3438. protected function _tag_close_H5($param)
  3439. {
  3440. return $this->_tag_close_H1($param);
  3441. }
  3442. /**
  3443. * tag : H6
  3444. * mode : CLOSE
  3445. *
  3446. * @param array $param
  3447. * @return boolean
  3448. */
  3449. protected function _tag_close_H6($param)
  3450. {
  3451. return $this->_tag_close_H1($param);
  3452. }
  3453. /**
  3454. * tag : SPAN
  3455. * mode : OPEN
  3456. *
  3457. * @param array $param
  3458. * @param string $other
  3459. * @return boolean
  3460. */
  3461. protected function _tag_open_SPAN($param, $other = 'span')
  3462. {
  3463. $this->parsingCss->save();
  3464. $this->parsingCss->analyse($other, $param);
  3465. $this->parsingCss->setPosition();
  3466. $this->parsingCss->fontSet();
  3467. return true;
  3468. }
  3469. /**
  3470. * tag : FONT
  3471. * mode : OPEN
  3472. *
  3473. * @param array $param
  3474. * @return boolean
  3475. */
  3476. protected function _tag_open_FONT($param)
  3477. {
  3478. return $this->_tag_open_SPAN($param, 'font');
  3479. }
  3480. /**
  3481. * tag : LABEL
  3482. * mode : OPEN
  3483. *
  3484. * @param array $param
  3485. * @return boolean
  3486. */
  3487. protected function _tag_open_LABEL($param)
  3488. {
  3489. return $this->_tag_open_SPAN($param, 'label');
  3490. }
  3491. /**
  3492. * tag : SPAN
  3493. * mode : CLOSE
  3494. *
  3495. * @param array $param
  3496. * @return boolean
  3497. */
  3498. protected function _tag_close_SPAN($param)
  3499. {
  3500. $this->parsingCss->restorePosition();
  3501. $this->parsingCss->load();
  3502. $this->parsingCss->fontSet();
  3503. return true;
  3504. }
  3505. /**
  3506. * tag : FONT
  3507. * mode : CLOSE
  3508. *
  3509. * @param array $param
  3510. * @return boolean
  3511. */
  3512. protected function _tag_close_FONT($param)
  3513. {
  3514. return $this->_tag_close_SPAN($param);
  3515. }
  3516. /**
  3517. * tag : LABEL
  3518. * mode : CLOSE
  3519. *
  3520. * @param array $param
  3521. * @return boolean
  3522. */
  3523. protected function _tag_close_LABEL($param)
  3524. {
  3525. return $this->_tag_close_SPAN($param);
  3526. }
  3527. /**
  3528. * tag : P
  3529. * mode : OPEN
  3530. *
  3531. * @param array $param
  3532. * @return boolean
  3533. */
  3534. protected function _tag_open_P($param)
  3535. {
  3536. if ($this->_isForOneLine) return false;
  3537. if (!in_array($this->_previousCall, array('_tag_close_P', '_tag_close_UL'))) {
  3538. if ($this->_maxH) $this->_tag_open_BR(array());
  3539. }
  3540. $this->parsingCss->save();
  3541. $this->parsingCss->analyse('p', $param);
  3542. $this->parsingCss->setPosition();
  3543. $this->parsingCss->fontSet();
  3544. // cancel the effects of the setPosition
  3545. $this->pdf->setXY($this->pdf->getX()-$this->parsingCss->value['margin']['l'], $this->pdf->getY()-$this->parsingCss->value['margin']['t']);
  3546. list($mL, $mR) = $this->_getMargins($this->pdf->getY());
  3547. $mR = $this->pdf->getW()-$mR;
  3548. $mL+= $this->parsingCss->value['margin']['l']+$this->parsingCss->value['padding']['l'];
  3549. $mR+= $this->parsingCss->value['margin']['r']+$this->parsingCss->value['padding']['r'];
  3550. $this->_saveMargin($mL, 0, $mR);
  3551. if ($this->parsingCss->value['text-indent']>0) {
  3552. $y = $this->pdf->getY()+$this->parsingCss->value['margin']['t']+$this->parsingCss->value['padding']['t'];
  3553. $this->_pageMarges[floor($y*100)] = array($mL+$this->parsingCss->value['text-indent'], $this->pdf->getW()-$mR);
  3554. $y+= $this->parsingCss->getLineHeight()*0.1;
  3555. $this->_pageMarges[floor($y*100)] = array($mL, $this->pdf->getW()-$mR);
  3556. }
  3557. $this->_makeBreakLine($this->parsingCss->value['margin']['t']+$this->parsingCss->value['padding']['t']);
  3558. $this->_isInParagraph = array($mL, $mR);
  3559. return true;
  3560. }
  3561. /**
  3562. * tag : P
  3563. * mode : CLOSE
  3564. *
  3565. * @param array $param
  3566. * @return boolean
  3567. */
  3568. protected function _tag_close_P($param)
  3569. {
  3570. if ($this->_isForOneLine) return false;
  3571. if ($this->_maxH) $this->_tag_open_BR(array());
  3572. $this->_isInParagraph = false;
  3573. $this->_loadMargin();
  3574. $h = $this->parsingCss->value['margin']['b']+$this->parsingCss->value['padding']['b'];
  3575. $this->parsingCss->load();
  3576. $this->parsingCss->fontSet();
  3577. $this->_makeBreakLine($h);
  3578. return true;
  3579. }
  3580. /**
  3581. * tag : PRE
  3582. * mode : OPEN
  3583. *
  3584. * @param array $param
  3585. * @param string $other
  3586. * @return boolean
  3587. */
  3588. protected function _tag_open_PRE($param, $other = 'pre')
  3589. {
  3590. if ($other=='pre' && $this->_maxH) $this->_tag_open_BR(array());
  3591. $this->parsingCss->save();
  3592. $this->parsingCss->value['font-family'] = 'courier';
  3593. $this->parsingCss->analyse($other, $param);
  3594. $this->parsingCss->setPosition();
  3595. $this->parsingCss->fontSet();
  3596. if ($other=='pre') return $this->_tag_open_DIV($param, $other);
  3597. return true;
  3598. }
  3599. /**
  3600. * tag : CODE
  3601. * mode : OPEN
  3602. *
  3603. * @param array $param
  3604. * @param string $other
  3605. * @return boolean
  3606. */
  3607. protected function _tag_open_CODE($param)
  3608. {
  3609. return $this->_tag_open_PRE($param, 'code');
  3610. }
  3611. /**
  3612. * tag : PRE
  3613. * mode : CLOSE
  3614. *
  3615. * @param array $param
  3616. * @param string $other
  3617. * @return boolean
  3618. */
  3619. protected function _tag_close_PRE($param, $other = 'pre')
  3620. {
  3621. if ($other=='pre') {
  3622. if ($this->_isForOneLine) return false;
  3623. $this->_tag_close_DIV($param, $other);
  3624. $this->_tag_open_BR(array());
  3625. }
  3626. $this->parsingCss->load();
  3627. $this->parsingCss->fontSet();
  3628. return true;
  3629. }
  3630. /**
  3631. * tag : CODE
  3632. * mode : CLOSE
  3633. *
  3634. * @param array $param
  3635. * @return boolean
  3636. */
  3637. protected function _tag_close_CODE($param)
  3638. {
  3639. return $this->_tag_close_PRE($param, 'code');
  3640. }
  3641. /**
  3642. * tag : BIG
  3643. * mode : OPEN
  3644. *
  3645. * @param array $param
  3646. * @return boolean
  3647. */
  3648. protected function _tag_open_BIG($param)
  3649. {
  3650. $this->parsingCss->save();
  3651. $this->parsingCss->value['mini-decal']-= $this->parsingCss->value['mini-size']*0.12;
  3652. $this->parsingCss->value['mini-size'] *= 1.2;
  3653. $this->parsingCss->analyse('big', $param);
  3654. $this->parsingCss->setPosition();
  3655. $this->parsingCss->fontSet();
  3656. return true;
  3657. }
  3658. /**
  3659. * tag : BIG
  3660. * mode : CLOSE
  3661. *
  3662. * @param array $param
  3663. * @return boolean
  3664. */
  3665. protected function _tag_close_BIG($param)
  3666. {
  3667. $this->parsingCss->load();
  3668. $this->parsingCss->fontSet();
  3669. return true;
  3670. }
  3671. /**
  3672. * tag : SMALL
  3673. * mode : OPEN
  3674. *
  3675. * @param array $param
  3676. * @return boolean
  3677. */
  3678. protected function _tag_open_SMALL($param)
  3679. {
  3680. $this->parsingCss->save();
  3681. $this->parsingCss->value['mini-decal']+= $this->parsingCss->value['mini-size']*0.05;
  3682. $this->parsingCss->value['mini-size'] *= 0.82;
  3683. $this->parsingCss->analyse('small', $param);
  3684. $this->parsingCss->setPosition();
  3685. $this->parsingCss->fontSet();
  3686. return true;
  3687. }
  3688. /**
  3689. * tag : SMALL
  3690. * mode : CLOSE
  3691. *
  3692. * @param array $param
  3693. * @return boolean
  3694. */
  3695. protected function _tag_close_SMALL($param)
  3696. {
  3697. $this->parsingCss->load();
  3698. $this->parsingCss->fontSet();
  3699. return true;
  3700. }
  3701. /**
  3702. * tag : SUP
  3703. * mode : OPEN
  3704. *
  3705. * @param array $param
  3706. * @return boolean
  3707. */
  3708. protected function _tag_open_SUP($param)
  3709. {
  3710. $this->parsingCss->save();
  3711. $this->parsingCss->value['mini-decal']-= $this->parsingCss->value['mini-size']*0.15;
  3712. $this->parsingCss->value['mini-size'] *= 0.75;
  3713. $this->parsingCss->analyse('sup', $param);
  3714. $this->parsingCss->setPosition();
  3715. $this->parsingCss->fontSet();
  3716. return true;
  3717. }
  3718. /**
  3719. * tag : SUP
  3720. * mode : CLOSE
  3721. *
  3722. * @param array $param
  3723. * @return boolean
  3724. */
  3725. protected function _tag_close_SUP($param)
  3726. {
  3727. $this->parsingCss->load();
  3728. $this->parsingCss->fontSet();
  3729. return true;
  3730. }
  3731. /**
  3732. * tag : SUB
  3733. * mode : OPEN
  3734. *
  3735. * @param array $param
  3736. * @return boolean
  3737. */
  3738. protected function _tag_open_SUB($param)
  3739. {
  3740. $this->parsingCss->save();
  3741. $this->parsingCss->value['mini-decal']+= $this->parsingCss->value['mini-size']*0.15;
  3742. $this->parsingCss->value['mini-size'] *= 0.75;
  3743. $this->parsingCss->analyse('sub', $param);
  3744. $this->parsingCss->setPosition();
  3745. $this->parsingCss->fontSet();
  3746. return true;
  3747. }
  3748. /**
  3749. * tag : SUB
  3750. * mode : CLOSE
  3751. *
  3752. * @param array $param
  3753. * @return boolean
  3754. */
  3755. protected function _tag_close_SUB($param)
  3756. {
  3757. $this->parsingCss->load();
  3758. $this->parsingCss->fontSet();
  3759. return true;
  3760. }
  3761. /**
  3762. * tag : UL
  3763. * mode : OPEN
  3764. *
  3765. * @param array $param
  3766. * @param string $other
  3767. * @return boolean
  3768. */
  3769. protected function _tag_open_UL($param, $other = 'ul')
  3770. {
  3771. if ($this->_isForOneLine) return false;
  3772. if (!in_array($this->_previousCall, array('_tag_close_P', '_tag_close_UL'))) {
  3773. if ($this->_maxH) $this->_tag_open_BR(array());
  3774. if (!count($this->_defList)) $this->_tag_open_BR(array());
  3775. }
  3776. if (!isset($param['style']['width'])) $param['allwidth'] = true;
  3777. $param['cellspacing'] = 0;
  3778. // a list is like a table
  3779. $this->_tag_open_TABLE($param, $other);
  3780. // add a level of list
  3781. $this->_listeAddLevel($other, $this->parsingCss->value['list-style-type'], $this->parsingCss->value['list-style-image']);
  3782. return true;
  3783. }
  3784. /**
  3785. * tag : OL
  3786. * mode : OPEN
  3787. *
  3788. * @param array $param
  3789. * @return boolean
  3790. */
  3791. protected function _tag_open_OL($param)
  3792. {
  3793. return $this->_tag_open_UL($param, 'ol');
  3794. }
  3795. /**
  3796. * tag : UL
  3797. * mode : CLOSE
  3798. *
  3799. * @param array $param
  3800. * @return boolean
  3801. */
  3802. protected function _tag_close_UL($param)
  3803. {
  3804. if ($this->_isForOneLine) return false;
  3805. $this->_tag_close_TABLE($param);
  3806. $this->_listeDelLevel();
  3807. if (!$this->_subPart) {
  3808. if (!count($this->_defList)) $this->_tag_open_BR(array());
  3809. }
  3810. return true;
  3811. }
  3812. /**
  3813. * tag : OL
  3814. * mode : CLOSE
  3815. *
  3816. * @param array $param
  3817. * @return boolean
  3818. */
  3819. protected function _tag_close_OL($param)
  3820. {
  3821. return $this->_tag_close_UL($param);
  3822. }
  3823. /**
  3824. * tag : LI
  3825. * mode : OPEN
  3826. *
  3827. * @param array $param
  3828. * @return boolean
  3829. */
  3830. protected function _tag_open_LI($param)
  3831. {
  3832. if ($this->_isForOneLine) return false;
  3833. $this->_listeAddLi();
  3834. if (!isset($param['style']['width'])) $param['style']['width'] = '100%';
  3835. $paramPUCE = $param;
  3836. $inf = $this->_listeGetLi();
  3837. if ($inf[0]) {
  3838. $paramPUCE['style']['font-family'] = $inf[0];
  3839. $paramPUCE['style']['text-align'] = 'li_right';
  3840. $paramPUCE['style']['vertical-align'] = 'top';
  3841. $paramPUCE['style']['width'] = $this->_listeGetWidth();
  3842. $paramPUCE['style']['padding-right'] = $this->_listeGetPadding();
  3843. $paramPUCE['txt'] = $inf[2];
  3844. } else {
  3845. $paramPUCE['style']['text-align'] = 'li_right';
  3846. $paramPUCE['style']['vertical-align'] = 'top';
  3847. $paramPUCE['style']['width'] = $this->_listeGetWidth();
  3848. $paramPUCE['style']['padding-right'] = $this->_listeGetPadding();
  3849. $paramPUCE['src'] = $inf[2];
  3850. $paramPUCE['sub_li'] = true;
  3851. }
  3852. $this->_tag_open_TR($param, 'li');
  3853. $this->parsingCss->save();
  3854. // if small LI
  3855. if ($inf[1]) {
  3856. $this->parsingCss->value['mini-decal']+= $this->parsingCss->value['mini-size']*0.045;
  3857. $this->parsingCss->value['mini-size'] *= 0.75;
  3858. }
  3859. // if we are in a sub html => prepare. Else : display
  3860. if ($this->_subPart) {
  3861. // TD for the puce
  3862. $tmpPos = $this->_tempPos;
  3863. $tmpLst1 = $this->parsingHtml->code[$tmpPos+1];
  3864. $tmpLst2 = $this->parsingHtml->code[$tmpPos+2];
  3865. $this->parsingHtml->code[$tmpPos+1] = array();
  3866. $this->parsingHtml->code[$tmpPos+1]['name'] = (isset($paramPUCE['src'])) ? 'img' : 'write';
  3867. $this->parsingHtml->code[$tmpPos+1]['param'] = $paramPUCE; unset($this->parsingHtml->code[$tmpPos+1]['param']['style']['width']);
  3868. $this->parsingHtml->code[$tmpPos+1]['close'] = 0;
  3869. $this->parsingHtml->code[$tmpPos+2] = array();
  3870. $this->parsingHtml->code[$tmpPos+2]['name'] = 'li';
  3871. $this->parsingHtml->code[$tmpPos+2]['param'] = $paramPUCE;
  3872. $this->parsingHtml->code[$tmpPos+2]['close'] = 1;
  3873. $this->_tag_open_TD($paramPUCE, 'li_sub');
  3874. $this->_tag_close_TD($param);
  3875. $this->_tempPos = $tmpPos;
  3876. $this->parsingHtml->code[$tmpPos+1] = $tmpLst1;
  3877. $this->parsingHtml->code[$tmpPos+2] = $tmpLst2;
  3878. } else {
  3879. // TD for the puce
  3880. $this->_tag_open_TD($paramPUCE, 'li_sub');
  3881. unset($paramPUCE['style']['width']);
  3882. if (isset($paramPUCE['src'])) $this->_tag_open_IMG($paramPUCE);
  3883. else $this->_tag_open_WRITE($paramPUCE);
  3884. $this->_tag_close_TD($paramPUCE);
  3885. }
  3886. $this->parsingCss->load();
  3887. // TD for the content
  3888. $this->_tag_open_TD($param, 'li');
  3889. return true;
  3890. }
  3891. /**
  3892. * tag : LI
  3893. * mode : CLOSE
  3894. *
  3895. * @param array $param
  3896. * @return boolean
  3897. */
  3898. protected function _tag_close_LI($param)
  3899. {
  3900. if ($this->_isForOneLine) return false;
  3901. $this->_tag_close_TD($param);
  3902. $this->_tag_close_TR($param);
  3903. return true;
  3904. }
  3905. /**
  3906. * tag : TBODY
  3907. * mode : OPEN
  3908. *
  3909. * @param array $param
  3910. * @return boolean
  3911. */
  3912. protected function _tag_open_TBODY($param)
  3913. {
  3914. if ($this->_isForOneLine) return false;
  3915. $this->parsingCss->save();
  3916. $this->parsingCss->analyse('tbody', $param);
  3917. $this->parsingCss->setPosition();
  3918. $this->parsingCss->fontSet();
  3919. return true;
  3920. }
  3921. /**
  3922. * tag : TBODY
  3923. * mode : CLOSE
  3924. *
  3925. * @param array $param
  3926. * @return boolean
  3927. */
  3928. protected function _tag_close_TBODY($param)
  3929. {
  3930. if ($this->_isForOneLine) return false;
  3931. $this->parsingCss->load();
  3932. $this->parsingCss->fontSet();
  3933. return true;
  3934. }
  3935. /**
  3936. * tag : THEAD
  3937. * mode : OPEN
  3938. *
  3939. * @param array $param
  3940. * @return boolean
  3941. */
  3942. protected function _tag_open_THEAD($param)
  3943. {
  3944. if ($this->_isForOneLine) return false;
  3945. $this->parsingCss->save();
  3946. $this->parsingCss->analyse('thead', $param);
  3947. $this->parsingCss->setPosition();
  3948. $this->parsingCss->fontSet();
  3949. // if we are in a sub part, save the number of the first TR in the thead
  3950. if ($this->_subPart) {
  3951. HTML2PDF::$_tables[$param['num']]['thead']['tr'][0] = HTML2PDF::$_tables[$param['num']]['tr_curr'];
  3952. HTML2PDF::$_tables[$param['num']]['thead']['code'] = array();
  3953. for ($pos=$this->_tempPos; $pos<count($this->parsingHtml->code); $pos++) {
  3954. $action = $this->parsingHtml->code[$pos];
  3955. if (strtolower($action['name'])=='thead') $action['name'] = 'thead_sub';
  3956. HTML2PDF::$_tables[$param['num']]['thead']['code'][] = $action;
  3957. if (strtolower($action['name'])=='thead_sub' && $action['close']) break;
  3958. }
  3959. } else {
  3960. $level = $this->parsingHtml->getLevel($this->_parsePos);
  3961. $this->_parsePos+= count($level);
  3962. HTML2PDF::$_tables[$param['num']]['tr_curr']+= count(HTML2PDF::$_tables[$param['num']]['thead']['tr']);
  3963. }
  3964. return true;
  3965. }
  3966. /**
  3967. * tag : THEAD
  3968. * mode : CLOSE
  3969. *
  3970. * @param array $param
  3971. * @return boolean
  3972. */
  3973. protected function _tag_close_THEAD($param)
  3974. {
  3975. if ($this->_isForOneLine) return false;
  3976. $this->parsingCss->load();
  3977. $this->parsingCss->fontSet();
  3978. // if we are in a sub HTM, construct the list of the TR in the thead
  3979. if ($this->_subPart) {
  3980. $min = HTML2PDF::$_tables[$param['num']]['thead']['tr'][0];
  3981. $max = HTML2PDF::$_tables[$param['num']]['tr_curr']-1;
  3982. HTML2PDF::$_tables[$param['num']]['thead']['tr'] = range($min, $max);
  3983. }
  3984. return true;
  3985. }
  3986. /**
  3987. * tag : TFOOT
  3988. * mode : OPEN
  3989. *
  3990. * @param array $param
  3991. * @return boolean
  3992. */
  3993. protected function _tag_open_TFOOT($param)
  3994. {
  3995. if ($this->_isForOneLine) return false;
  3996. $this->parsingCss->save();
  3997. $this->parsingCss->analyse('tfoot', $param);
  3998. $this->parsingCss->setPosition();
  3999. $this->parsingCss->fontSet();
  4000. // if we are in a sub part, save the number of the first TR in the tfoot
  4001. if ($this->_subPart) {
  4002. HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0] = HTML2PDF::$_tables[$param['num']]['tr_curr'];
  4003. HTML2PDF::$_tables[$param['num']]['tfoot']['code'] = array();
  4004. for ($pos=$this->_tempPos; $pos<count($this->parsingHtml->code); $pos++) {
  4005. $action = $this->parsingHtml->code[$pos];
  4006. if (strtolower($action['name'])=='tfoot') $action['name'] = 'tfoot_sub';
  4007. HTML2PDF::$_tables[$param['num']]['tfoot']['code'][] = $action;
  4008. if (strtolower($action['name'])=='tfoot_sub' && $action['close']) break;
  4009. }
  4010. } else {
  4011. $level = $this->parsingHtml->getLevel($this->_parsePos);
  4012. $this->_parsePos+= count($level);
  4013. HTML2PDF::$_tables[$param['num']]['tr_curr']+= count(HTML2PDF::$_tables[$param['num']]['tfoot']['tr']);
  4014. }
  4015. return true;
  4016. }
  4017. /**
  4018. * tag : TFOOT
  4019. * mode : CLOSE
  4020. *
  4021. * @param array $param
  4022. * @return boolean
  4023. */
  4024. protected function _tag_close_TFOOT($param)
  4025. {
  4026. if ($this->_isForOneLine) return false;
  4027. $this->parsingCss->load();
  4028. $this->parsingCss->fontSet();
  4029. // if we are in a sub HTM, construct the list of the TR in the tfoot
  4030. if ($this->_subPart) {
  4031. $min = HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0];
  4032. $max = HTML2PDF::$_tables[$param['num']]['tr_curr']-1;
  4033. HTML2PDF::$_tables[$param['num']]['tfoot']['tr'] = range($min, $max);
  4034. }
  4035. return true;
  4036. }
  4037. /**
  4038. * It is not a real TAG, does not use it !
  4039. *
  4040. * @param array $param
  4041. * @return boolean
  4042. */
  4043. protected function _tag_open_THEAD_SUB($param)
  4044. {
  4045. if ($this->_isForOneLine) return false;
  4046. $this->parsingCss->save();
  4047. $this->parsingCss->analyse('thead', $param);
  4048. $this->parsingCss->setPosition();
  4049. $this->parsingCss->fontSet();
  4050. return true;
  4051. }
  4052. /**
  4053. * It is not a real TAG, does not use it !
  4054. *
  4055. * @param array $param
  4056. * @return boolean
  4057. */
  4058. protected function _tag_close_THEAD_SUB($param)
  4059. {
  4060. if ($this->_isForOneLine) return false;
  4061. $this->parsingCss->load();
  4062. $this->parsingCss->fontSet();
  4063. return true;
  4064. }
  4065. /**
  4066. * It is not a real TAG, does not use it !
  4067. *
  4068. * @param array $param
  4069. * @return boolean
  4070. */
  4071. protected function _tag_open_TFOOT_SUB($param)
  4072. {
  4073. if ($this->_isForOneLine) return false;
  4074. $this->parsingCss->save();
  4075. $this->parsingCss->analyse('tfoot', $param);
  4076. $this->parsingCss->setPosition();
  4077. $this->parsingCss->fontSet();
  4078. return true;
  4079. }
  4080. /**
  4081. * It is not a real TAG, does not use it !
  4082. *
  4083. * @param array $param
  4084. * @return boolean
  4085. */
  4086. protected function _tag_close_TFOOT_SUB($param)
  4087. {
  4088. if ($this->_isForOneLine) return false;
  4089. $this->parsingCss->load();
  4090. $this->parsingCss->fontSet();
  4091. return true;
  4092. }
  4093. /**
  4094. * tag : FORM
  4095. * mode : OPEN
  4096. *
  4097. * @param array $param
  4098. * @return boolean
  4099. */
  4100. protected function _tag_open_FORM($param)
  4101. {
  4102. $this->parsingCss->save();
  4103. $this->parsingCss->analyse('form', $param);
  4104. $this->parsingCss->setPosition();
  4105. $this->parsingCss->fontSet();
  4106. $this->pdf->setFormDefaultProp(
  4107. array(
  4108. 'lineWidth'=>1,
  4109. 'borderStyle'=>'solid',
  4110. 'fillColor'=>array(220, 220, 255),
  4111. 'strokeColor'=>array(128, 128, 200)
  4112. )
  4113. );
  4114. $this->_isInForm = isset($param['action']) ? $param['action'] : '';
  4115. return true;
  4116. }
  4117. /**
  4118. * tag : FORM
  4119. * mode : CLOSE
  4120. *
  4121. * @param array $param
  4122. * @return boolean
  4123. */
  4124. protected function _tag_close_FORM($param)
  4125. {
  4126. $this->_isInForm = false;
  4127. $this->parsingCss->load();
  4128. $this->parsingCss->fontSet();
  4129. return true;
  4130. }
  4131. /**
  4132. * tag : TABLE
  4133. * mode : OPEN
  4134. *
  4135. * @param array $param
  4136. * @return boolean
  4137. */
  4138. protected function _tag_open_TABLE($param, $other = 'table')
  4139. {
  4140. if ($this->_maxH) {
  4141. if ($this->_isForOneLine) return false;
  4142. $this->_tag_open_BR(array());
  4143. }
  4144. if ($this->_isForOneLine) {
  4145. $this->_maxX = $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  4146. return false;
  4147. }
  4148. $this->_maxH = 0;
  4149. $alignObject = isset($param['align']) ? strtolower($param['align']) : 'left';
  4150. if (isset($param['align'])) unset($param['align']);
  4151. if (!in_array($alignObject, array('left', 'center', 'right'))) $alignObject = 'left';
  4152. $this->parsingCss->save();
  4153. $this->parsingCss->analyse($other, $param);
  4154. $this->parsingCss->setPosition();
  4155. $this->parsingCss->fontSet();
  4156. if ($this->parsingCss->value['margin-auto']) $alignObject = 'center';
  4157. // collapse table ?
  4158. $collapse = false;
  4159. if ($other=='table') {
  4160. $collapse = isset($this->parsingCss->value['border']['collapse']) ? $this->parsingCss->value['border']['collapse'] : false;
  4161. }
  4162. // if collapse => no borders for the table, only for TD
  4163. if ($collapse) {
  4164. $param['style']['border'] = 'none';
  4165. $param['cellspacing'] = 0;
  4166. $none = $this->parsingCss->readBorder('none');
  4167. $this->parsingCss->value['border']['t'] = $none;
  4168. $this->parsingCss->value['border']['r'] = $none;
  4169. $this->parsingCss->value['border']['b'] = $none;
  4170. $this->parsingCss->value['border']['l'] = $none;
  4171. }
  4172. // if we are in a SUB html => prepare the properties of the table
  4173. if ($this->_subPart) {
  4174. if ($this->_debugActif) $this->_DEBUG_add('Table n'.$param['num'], true);
  4175. HTML2PDF::$_tables[$param['num']] = array();
  4176. HTML2PDF::$_tables[$param['num']]['border'] = isset($param['border']) ? $this->parsingCss->readBorder($param['border']) : null;
  4177. HTML2PDF::$_tables[$param['num']]['cellpadding'] = $this->parsingCss->ConvertToMM(isset($param['cellpadding']) ? $param['cellpadding'] : '1px');
  4178. HTML2PDF::$_tables[$param['num']]['cellspacing'] = $this->parsingCss->ConvertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
  4179. HTML2PDF::$_tables[$param['num']]['cases'] = array(); // properties of each TR/TD
  4180. HTML2PDF::$_tables[$param['num']]['corr'] = array(); // link between TR/TD and colspan/rowspan
  4181. HTML2PDF::$_tables[$param['num']]['corr_x'] = 0; // position in 'cases'
  4182. HTML2PDF::$_tables[$param['num']]['corr_y'] = 0; // position in 'cases'
  4183. HTML2PDF::$_tables[$param['num']]['td_curr'] = 0; // current column
  4184. HTML2PDF::$_tables[$param['num']]['tr_curr'] = 0; // current row
  4185. HTML2PDF::$_tables[$param['num']]['curr_x'] = $this->pdf->getX();
  4186. HTML2PDF::$_tables[$param['num']]['curr_y'] = $this->pdf->getY();
  4187. HTML2PDF::$_tables[$param['num']]['width'] = 0; // global width
  4188. HTML2PDF::$_tables[$param['num']]['height'] = 0; // global height
  4189. HTML2PDF::$_tables[$param['num']]['align'] = $alignObject;
  4190. HTML2PDF::$_tables[$param['num']]['marge'] = array();
  4191. HTML2PDF::$_tables[$param['num']]['marge']['t'] = $this->parsingCss->value['padding']['t']+$this->parsingCss->value['border']['t']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
  4192. HTML2PDF::$_tables[$param['num']]['marge']['r'] = $this->parsingCss->value['padding']['r']+$this->parsingCss->value['border']['r']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
  4193. HTML2PDF::$_tables[$param['num']]['marge']['b'] = $this->parsingCss->value['padding']['b']+$this->parsingCss->value['border']['b']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
  4194. HTML2PDF::$_tables[$param['num']]['marge']['l'] = $this->parsingCss->value['padding']['l']+$this->parsingCss->value['border']['l']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
  4195. HTML2PDF::$_tables[$param['num']]['page'] = 0; // number of pages
  4196. HTML2PDF::$_tables[$param['num']]['new_page'] = true; // flag : new page for the current TR
  4197. HTML2PDF::$_tables[$param['num']]['style_value'] = null; // CSS style of the table
  4198. HTML2PDF::$_tables[$param['num']]['thead'] = array(); // properties on the thead
  4199. HTML2PDF::$_tables[$param['num']]['tfoot'] = array(); // properties on the tfoot
  4200. HTML2PDF::$_tables[$param['num']]['thead']['tr'] = array(); // list of the TRs in the thead
  4201. HTML2PDF::$_tables[$param['num']]['tfoot']['tr'] = array(); // list of the TRs in the tfoot
  4202. HTML2PDF::$_tables[$param['num']]['thead']['height'] = 0; // thead height
  4203. HTML2PDF::$_tables[$param['num']]['tfoot']['height'] = 0; // tfoot height
  4204. HTML2PDF::$_tables[$param['num']]['thead']['code'] = array(); // HTML content of the thead
  4205. HTML2PDF::$_tables[$param['num']]['tfoot']['code'] = array(); // HTML content of the tfoot
  4206. HTML2PDF::$_tables[$param['num']]['cols'] = array(); // properties of the COLs
  4207. $this->_saveMargin($this->pdf->getlMargin(), $this->pdf->gettMargin(), $this->pdf->getrMargin());
  4208. $this->parsingCss->value['width']-= HTML2PDF::$_tables[$param['num']]['marge']['l'] + HTML2PDF::$_tables[$param['num']]['marge']['r'];
  4209. } else {
  4210. // we start from the first page and the first page of the table
  4211. HTML2PDF::$_tables[$param['num']]['page'] = 0;
  4212. HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
  4213. HTML2PDF::$_tables[$param['num']]['tr_curr'] = 0;
  4214. HTML2PDF::$_tables[$param['num']]['td_x'] = HTML2PDF::$_tables[$param['num']]['marge']['l']+HTML2PDF::$_tables[$param['num']]['curr_x'];
  4215. HTML2PDF::$_tables[$param['num']]['td_y'] = HTML2PDF::$_tables[$param['num']]['marge']['t']+HTML2PDF::$_tables[$param['num']]['curr_y'];
  4216. // draw the borders/background of the first page/part of the table
  4217. $this->_drawRectangle(
  4218. HTML2PDF::$_tables[$param['num']]['curr_x'],
  4219. HTML2PDF::$_tables[$param['num']]['curr_y'],
  4220. HTML2PDF::$_tables[$param['num']]['width'],
  4221. isset(HTML2PDF::$_tables[$param['num']]['height'][0]) ? HTML2PDF::$_tables[$param['num']]['height'][0] : null,
  4222. $this->parsingCss->value['border'],
  4223. $this->parsingCss->value['padding'],
  4224. 0,
  4225. $this->parsingCss->value['background']
  4226. );
  4227. HTML2PDF::$_tables[$param['num']]['style_value'] = $this->parsingCss->value;
  4228. }
  4229. return true;
  4230. }
  4231. /**
  4232. * tag : TABLE
  4233. * mode : CLOSE
  4234. *
  4235. * @param array $param
  4236. * @return boolean
  4237. */
  4238. protected function _tag_close_TABLE($param)
  4239. {
  4240. if ($this->_isForOneLine) return false;
  4241. $this->_maxH = 0;
  4242. // if we are in a sub HTML
  4243. if ($this->_subPart) {
  4244. // calculate the size of each case
  4245. $this->_calculateTableCellSize(HTML2PDF::$_tables[$param['num']]['cases'], HTML2PDF::$_tables[$param['num']]['corr']);
  4246. // calculate the height of the thead and the tfoot
  4247. $lst = array('thead', 'tfoot');
  4248. foreach ($lst as $mode) {
  4249. HTML2PDF::$_tables[$param['num']][$mode]['height'] = 0;
  4250. foreach (HTML2PDF::$_tables[$param['num']][$mode]['tr'] as $tr) {
  4251. // hauteur de la ligne tr
  4252. $h = 0;
  4253. for ($i=0; $i<count(HTML2PDF::$_tables[$param['num']]['cases'][$tr]); $i++)
  4254. if (HTML2PDF::$_tables[$param['num']]['cases'][$tr][$i]['rowspan']==1)
  4255. $h = max($h, HTML2PDF::$_tables[$param['num']]['cases'][$tr][$i]['h']);
  4256. HTML2PDF::$_tables[$param['num']][$mode]['height']+= $h;
  4257. }
  4258. }
  4259. // calculate the width of the table
  4260. HTML2PDF::$_tables[$param['num']]['width'] = HTML2PDF::$_tables[$param['num']]['marge']['l'] + HTML2PDF::$_tables[$param['num']]['marge']['r'];
  4261. if (isset(HTML2PDF::$_tables[$param['num']]['cases'][0])) {
  4262. foreach (HTML2PDF::$_tables[$param['num']]['cases'][0] as $case) {
  4263. HTML2PDF::$_tables[$param['num']]['width']+= $case['w'];
  4264. }
  4265. }
  4266. // X position of the table
  4267. $old = $this->parsingCss->getOldValues();
  4268. $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  4269. $x = HTML2PDF::$_tables[$param['num']]['curr_x'];
  4270. $w = HTML2PDF::$_tables[$param['num']]['width'];
  4271. if ($parentWidth>$w) {
  4272. if (HTML2PDF::$_tables[$param['num']]['align']=='center')
  4273. $x = $x + ($parentWidth-$w)*0.5;
  4274. else if (HTML2PDF::$_tables[$param['num']]['align']=='right')
  4275. $x = $x + $parentWidth-$w;
  4276. HTML2PDF::$_tables[$param['num']]['curr_x'] = $x;
  4277. }
  4278. // calculate the height of the table
  4279. HTML2PDF::$_tables[$param['num']]['height'] = array();
  4280. // minimum of the height because of margins, and of the thead and tfoot height
  4281. $h0 = HTML2PDF::$_tables[$param['num']]['marge']['t'] + HTML2PDF::$_tables[$param['num']]['marge']['b'];
  4282. $h0+= HTML2PDF::$_tables[$param['num']]['thead']['height'] + HTML2PDF::$_tables[$param['num']]['tfoot']['height'];
  4283. // max height of the page
  4284. $max = $this->pdf->getH() - $this->pdf->getbMargin();
  4285. // current position on the page
  4286. $y = HTML2PDF::$_tables[$param['num']]['curr_y'];
  4287. $height = $h0;
  4288. // we get the height of each line
  4289. for ($k=0; $k<count(HTML2PDF::$_tables[$param['num']]['cases']); $k++) {
  4290. // if it is a TR of the thead or of the tfoot => skip
  4291. if (in_array($k, HTML2PDF::$_tables[$param['num']]['thead']['tr'])) continue;
  4292. if (in_array($k, HTML2PDF::$_tables[$param['num']]['tfoot']['tr'])) continue;
  4293. // height of the line
  4294. $th = 0;
  4295. $h = 0;
  4296. for ($i=0; $i<count(HTML2PDF::$_tables[$param['num']]['cases'][$k]); $i++) {
  4297. $h = max($h, HTML2PDF::$_tables[$param['num']]['cases'][$k][$i]['h']);
  4298. if (HTML2PDF::$_tables[$param['num']]['cases'][$k][$i]['rowspan']==1)
  4299. $th = max($th, HTML2PDF::$_tables[$param['num']]['cases'][$k][$i]['h']);
  4300. }
  4301. // if the row does not fit on the page => new page
  4302. if ($y+$h+$height>$max) {
  4303. if ($height==$h0) $height = null;
  4304. HTML2PDF::$_tables[$param['num']]['height'][] = $height;
  4305. $height = $h0;
  4306. $y = $this->_margeTop;
  4307. }
  4308. $height+= $th;
  4309. }
  4310. // if ther is a height at the end, add it
  4311. if ($height!=$h0 || $k==0) HTML2PDF::$_tables[$param['num']]['height'][] = $height;
  4312. } else {
  4313. // if we have tfoor, draw it
  4314. if (count(HTML2PDF::$_tables[$param['num']]['tfoot']['code'])) {
  4315. $tmpTR = HTML2PDF::$_tables[$param['num']]['tr_curr'];
  4316. $tmpTD = HTML2PDF::$_tables[$param['num']]['td_curr'];
  4317. $oldParsePos = $this->_parsePos;
  4318. $oldParseCode = $this->parsingHtml->code;
  4319. HTML2PDF::$_tables[$param['num']]['tr_curr'] = HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0];
  4320. HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
  4321. $this->_parsePos = 0;
  4322. $this->parsingHtml->code = HTML2PDF::$_tables[$param['num']]['tfoot']['code'];
  4323. $this->_isInTfoot = true;
  4324. $this->_makeHTMLcode();
  4325. $this->_isInTfoot = false;
  4326. $this->_parsePos = $oldParsePos;
  4327. $this->parsingHtml->code = $oldParseCode;
  4328. HTML2PDF::$_tables[$param['num']]['tr_curr'] = $tmpTR;
  4329. HTML2PDF::$_tables[$param['num']]['td_curr'] = $tmpTD;
  4330. }
  4331. // get the positions of the end of the table
  4332. $x = HTML2PDF::$_tables[$param['num']]['curr_x'] + HTML2PDF::$_tables[$param['num']]['width'];
  4333. if (count(HTML2PDF::$_tables[$param['num']]['height'])>1)
  4334. $y = $this->_margeTop+HTML2PDF::$_tables[$param['num']]['height'][count(HTML2PDF::$_tables[$param['num']]['height'])-1];
  4335. else if (count(HTML2PDF::$_tables[$param['num']]['height'])==1)
  4336. $y = HTML2PDF::$_tables[$param['num']]['curr_y']+HTML2PDF::$_tables[$param['num']]['height'][count(HTML2PDF::$_tables[$param['num']]['height'])-1];
  4337. else
  4338. $y = HTML2PDF::$_tables[$param['num']]['curr_y'];
  4339. $this->_maxX = max($this->_maxX, $x);
  4340. $this->_maxY = max($this->_maxY, $y);
  4341. $this->pdf->setXY($this->pdf->getlMargin(), $y);
  4342. $this->_loadMargin();
  4343. if ($this->_debugActif) $this->_DEBUG_add('Table '.$param['num'], false);
  4344. }
  4345. $this->parsingCss->load();
  4346. $this->parsingCss->fontSet();
  4347. return true;
  4348. }
  4349. /**
  4350. * tag : COL
  4351. * mode : OPEN
  4352. *
  4353. * @param array $param
  4354. * @return boolean
  4355. */
  4356. protected function _tag_open_COL($param)
  4357. {
  4358. $span = isset($param['span']) ? $param['span'] : 1;
  4359. for ($k=0; $k<$span; $k++)
  4360. HTML2PDF::$_tables[$param['num']]['cols'][] = $param;
  4361. }
  4362. /**
  4363. * tag : COL
  4364. * mode : CLOSE
  4365. *
  4366. * @param array $param
  4367. * @return boolean
  4368. */
  4369. protected function _tag_close_COL($param)
  4370. {
  4371. // there is nothing to do here
  4372. return true;
  4373. }
  4374. /**
  4375. * tag : TR
  4376. * mode : OPEN
  4377. *
  4378. * @param array $param
  4379. * @return boolean
  4380. */
  4381. protected function _tag_open_TR($param, $other = 'tr')
  4382. {
  4383. if ($this->_isForOneLine) return false;
  4384. $this->_maxH = 0;
  4385. $this->parsingCss->save();
  4386. $this->parsingCss->analyse($other, $param);
  4387. $this->parsingCss->setPosition();
  4388. $this->parsingCss->fontSet();
  4389. // position in the table
  4390. HTML2PDF::$_tables[$param['num']]['tr_curr']++;
  4391. HTML2PDF::$_tables[$param['num']]['td_curr']= 0;
  4392. // if we are not in a sub html
  4393. if (!$this->_subPart) {
  4394. // Y after the row
  4395. $ty=null;
  4396. for ($ii=0; $ii<count(HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1]); $ii++) {
  4397. $ty = max($ty, HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][$ii]['h']);
  4398. }
  4399. // height of the tfoot
  4400. $hfoot = HTML2PDF::$_tables[$param['num']]['tfoot']['height'];
  4401. // if the line does not fit on the page => new page
  4402. if (!$this->_isInTfoot && HTML2PDF::$_tables[$param['num']]['td_y'] + HTML2PDF::$_tables[$param['num']]['marge']['b'] + $ty +$hfoot> $this->pdf->getH() - $this->pdf->getbMargin()) {
  4403. // fi ther is a tfoot => draw it
  4404. if (count(HTML2PDF::$_tables[$param['num']]['tfoot']['code'])) {
  4405. $tmpTR = HTML2PDF::$_tables[$param['num']]['tr_curr'];
  4406. $tmpTD = HTML2PDF::$_tables[$param['num']]['td_curr'];
  4407. $oldParsePos = $this->_parsePos;
  4408. $oldParseCode = $this->parsingHtml->code;
  4409. HTML2PDF::$_tables[$param['num']]['tr_curr'] = HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0];
  4410. HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
  4411. $this->_parsePos = 0;
  4412. $this->parsingHtml->code = HTML2PDF::$_tables[$param['num']]['tfoot']['code'];
  4413. $this->_isInTfoot = true;
  4414. $this->_makeHTMLcode();
  4415. $this->_isInTfoot = false;
  4416. $this->_parsePos = $oldParsePos;
  4417. $this->parsingHtml->code = $oldParseCode;
  4418. HTML2PDF::$_tables[$param['num']]['tr_curr'] = $tmpTR;
  4419. HTML2PDF::$_tables[$param['num']]['td_curr'] = $tmpTD;
  4420. }
  4421. // new page
  4422. HTML2PDF::$_tables[$param['num']]['new_page'] = true;
  4423. $this->_setNewPage();
  4424. // new position
  4425. HTML2PDF::$_tables[$param['num']]['page']++;
  4426. HTML2PDF::$_tables[$param['num']]['curr_y'] = $this->pdf->getY();
  4427. HTML2PDF::$_tables[$param['num']]['td_y'] = HTML2PDF::$_tables[$param['num']]['curr_y']+HTML2PDF::$_tables[$param['num']]['marge']['t'];
  4428. // if we have the height of the tbale on the page => draw borders and background
  4429. if (isset(HTML2PDF::$_tables[$param['num']]['height'][HTML2PDF::$_tables[$param['num']]['page']])) {
  4430. $old = $this->parsingCss->value;
  4431. $this->parsingCss->value = HTML2PDF::$_tables[$param['num']]['style_value'];
  4432. $this->_drawRectangle(
  4433. HTML2PDF::$_tables[$param['num']]['curr_x'],
  4434. HTML2PDF::$_tables[$param['num']]['curr_y'],
  4435. HTML2PDF::$_tables[$param['num']]['width'],
  4436. HTML2PDF::$_tables[$param['num']]['height'][HTML2PDF::$_tables[$param['num']]['page']],
  4437. $this->parsingCss->value['border'],
  4438. $this->parsingCss->value['padding'],
  4439. HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5,
  4440. $this->parsingCss->value['background']
  4441. );
  4442. $this->parsingCss->value = $old;
  4443. }
  4444. }
  4445. // if we are in a new page, and if we have a thead => draw it
  4446. if (HTML2PDF::$_tables[$param['num']]['new_page'] && count(HTML2PDF::$_tables[$param['num']]['thead']['code'])) {
  4447. HTML2PDF::$_tables[$param['num']]['new_page'] = false;
  4448. $tmpTR = HTML2PDF::$_tables[$param['num']]['tr_curr'];
  4449. $tmpTD = HTML2PDF::$_tables[$param['num']]['td_curr'];
  4450. $oldParsePos = $this->_parsePos;
  4451. $oldParseCode = $this->parsingHtml->code;
  4452. HTML2PDF::$_tables[$param['num']]['tr_curr'] = HTML2PDF::$_tables[$param['num']]['thead']['tr'][0];
  4453. HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
  4454. $this->_parsePos = 0;
  4455. $this->parsingHtml->code = HTML2PDF::$_tables[$param['num']]['thead']['code'];
  4456. $this->_isInThead = true;
  4457. $this->_makeHTMLcode();
  4458. $this->_isInThead = false;
  4459. $this->_parsePos = $oldParsePos;
  4460. $this->parsingHtml->code = $oldParseCode;
  4461. HTML2PDF::$_tables[$param['num']]['tr_curr'] = $tmpTR;
  4462. HTML2PDF::$_tables[$param['num']]['td_curr'] = $tmpTD;
  4463. HTML2PDF::$_tables[$param['num']]['new_page'] = true;
  4464. }
  4465. // else (in a sub HTML)
  4466. } else {
  4467. // prepare it
  4468. HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1] = array();
  4469. if (!isset(HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']]))
  4470. HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']] = array();
  4471. HTML2PDF::$_tables[$param['num']]['corr_x']=0;
  4472. while(isset(HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']][HTML2PDF::$_tables[$param['num']]['corr_x']]))
  4473. HTML2PDF::$_tables[$param['num']]['corr_x']++;
  4474. }
  4475. return true;
  4476. }
  4477. /**
  4478. * tag : TR
  4479. * mode : CLOSE
  4480. *
  4481. * @param array $param
  4482. * @return boolean
  4483. */
  4484. protected function _tag_close_TR($param)
  4485. {
  4486. if ($this->_isForOneLine) return false;
  4487. $this->_maxH = 0;
  4488. $this->parsingCss->load();
  4489. $this->parsingCss->fontSet();
  4490. // if we are not in a sub HTML
  4491. if (!$this->_subPart) {
  4492. // Y of the current line
  4493. $ty=null;
  4494. for ($ii=0; $ii<count(HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1]); $ii++) {
  4495. if (HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][$ii]['rowspan']==1) {
  4496. $ty = HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][$ii]['h'];
  4497. }
  4498. }
  4499. // new position
  4500. HTML2PDF::$_tables[$param['num']]['td_x'] = HTML2PDF::$_tables[$param['num']]['curr_x']+HTML2PDF::$_tables[$param['num']]['marge']['l'];
  4501. HTML2PDF::$_tables[$param['num']]['td_y']+= $ty;
  4502. HTML2PDF::$_tables[$param['num']]['new_page'] = false;
  4503. } else {
  4504. HTML2PDF::$_tables[$param['num']]['corr_y']++;
  4505. }
  4506. return true;
  4507. }
  4508. /**
  4509. * tag : TD
  4510. * mode : OPEN
  4511. *
  4512. * @param array $param
  4513. * @return boolean
  4514. */
  4515. protected function _tag_open_TD($param, $other = 'td')
  4516. {
  4517. if ($this->_isForOneLine) return false;
  4518. $this->_maxH = 0;
  4519. $param['cellpadding'] = HTML2PDF::$_tables[$param['num']]['cellpadding'].'mm';
  4520. $param['cellspacing'] = HTML2PDF::$_tables[$param['num']]['cellspacing'].'mm';
  4521. // specific style for LI
  4522. if ($other=='li') {
  4523. $specialLi = true;
  4524. } else {
  4525. $specialLi = false;
  4526. if ($other=='li_sub') {
  4527. $param['style']['border'] = 'none';
  4528. $param['style']['background-color'] = 'transparent';
  4529. $param['style']['background-image'] = 'none';
  4530. $param['style']['background-position'] = '';
  4531. $param['style']['background-repeat'] = '';
  4532. $other = 'li';
  4533. }
  4534. }
  4535. // get the properties of the TD
  4536. $x = HTML2PDF::$_tables[$param['num']]['td_curr'];
  4537. $y = HTML2PDF::$_tables[$param['num']]['tr_curr']-1;
  4538. $colspan = isset($param['colspan']) ? $param['colspan'] : 1;
  4539. $rowspan = isset($param['rowspan']) ? $param['rowspan'] : 1;
  4540. // flag for collapse table
  4541. $collapse = false;
  4542. // specific traitment for TD and TH
  4543. if (in_array($other, array('td', 'th'))) {
  4544. // id of the column
  4545. $numCol = isset(HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Xr']) ? HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Xr'] : HTML2PDF::$_tables[$param['num']]['corr_x'];
  4546. // we get the properties of the COL tag, if exist
  4547. if (isset(HTML2PDF::$_tables[$param['num']]['cols'][$numCol])) {
  4548. $colParam = HTML2PDF::$_tables[$param['num']]['cols'][$numCol];
  4549. // for colspans => we get all the neede widths
  4550. $colParam['style']['width'] = array();
  4551. for ($k=0; $k<$colspan; $k++) {
  4552. if (isset(HTML2PDF::$_tables[$param['num']]['cols'][$numCol+$k]['style']['width'])) {
  4553. $colParam['style']['width'][] = HTML2PDF::$_tables[$param['num']]['cols'][$numCol+$k]['style']['width'];
  4554. }
  4555. }
  4556. // calculate the total width of the column
  4557. $total = '';
  4558. $last = $this->parsingCss->getLastWidth();
  4559. if (count($colParam['style']['width'])) {
  4560. $total = $colParam['style']['width'][0]; unset($colParam['style']['width'][0]);
  4561. foreach ($colParam['style']['width'] as $width) {
  4562. if (substr($total, -1)=='%' && substr($width, -1)=='%')
  4563. $total = (str_replace('%', '', $total)+str_replace('%', '', $width)).'%';
  4564. else
  4565. $total = ($this->parsingCss->ConvertToMM($total, $last) + $this->parsingCss->ConvertToMM($width, $last)).'mm';
  4566. }
  4567. }
  4568. // get the final width
  4569. if ($total) {
  4570. $colParam['style']['width'] = $total;
  4571. } else {
  4572. unset($colParam['style']['width']);
  4573. }
  4574. // merge the styles of the COL and the TD
  4575. $param['style'] = array_merge($colParam['style'], $param['style']);
  4576. // merge the class of the COL and the TD
  4577. if (isset($colParam['class'])) {
  4578. $param['class'] = $colParam['class'].(isset($param['class']) ? ' '.$param['class'] : '');
  4579. }
  4580. }
  4581. $collapse = isset($this->parsingCss->value['border']['collapse']) ? $this->parsingCss->value['border']['collapse'] : false;
  4582. }
  4583. $this->parsingCss->save();
  4584. // legacy for TD and TH
  4585. $legacy = null;
  4586. if (in_array($other, array('td', 'th'))) {
  4587. $legacy = array();
  4588. $old = $this->parsingCss->getLastValue('background');
  4589. if ($old && ($old['color'] || $old['image']))
  4590. $legacy['background'] = $old;
  4591. if (HTML2PDF::$_tables[$param['num']]['border']) {
  4592. $legacy['border'] = array();
  4593. $legacy['border']['l'] = HTML2PDF::$_tables[$param['num']]['border'];
  4594. $legacy['border']['t'] = HTML2PDF::$_tables[$param['num']]['border'];
  4595. $legacy['border']['r'] = HTML2PDF::$_tables[$param['num']]['border'];
  4596. $legacy['border']['b'] = HTML2PDF::$_tables[$param['num']]['border'];
  4597. }
  4598. }
  4599. $return = $this->parsingCss->analyse($other, $param, $legacy);
  4600. if ($specialLi) {
  4601. $this->parsingCss->value['width']-= $this->parsingCss->ConvertToMM($this->_listeGetWidth());
  4602. $this->parsingCss->value['width']-= $this->parsingCss->ConvertToMM($this->_listeGetPadding());
  4603. }
  4604. $this->parsingCss->setPosition();
  4605. $this->parsingCss->fontSet();
  4606. // if tale collapse => modify the borders
  4607. if ($collapse) {
  4608. if (!$this->_subPart) {
  4609. if (
  4610. (HTML2PDF::$_tables[$param['num']]['tr_curr']>1 && !HTML2PDF::$_tables[$param['num']]['new_page']) ||
  4611. (!$this->_isInThead && count(HTML2PDF::$_tables[$param['num']]['thead']['code']))
  4612. ) {
  4613. $this->parsingCss->value['border']['t'] = $this->parsingCss->readBorder('none');
  4614. }
  4615. }
  4616. if (HTML2PDF::$_tables[$param['num']]['td_curr']>0) {
  4617. if (!$return) $this->parsingCss->value['width']+= $this->parsingCss->value['border']['l']['width'];
  4618. $this->parsingCss->value['border']['l'] = $this->parsingCss->readBorder('none');
  4619. }
  4620. }
  4621. // margins of the table
  4622. $marge = array();
  4623. $marge['t'] = $this->parsingCss->value['padding']['t']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['t']['width'];
  4624. $marge['r'] = $this->parsingCss->value['padding']['r']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['r']['width'];
  4625. $marge['b'] = $this->parsingCss->value['padding']['b']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['b']['width'];
  4626. $marge['l'] = $this->parsingCss->value['padding']['l']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['l']['width'];
  4627. // if we are in a sub HTML
  4628. if ($this->_subPart) {
  4629. // new position in the table
  4630. HTML2PDF::$_tables[$param['num']]['td_curr']++;
  4631. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x] = array();
  4632. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['w'] = 0;
  4633. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['h'] = 0;
  4634. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['dw'] = 0;
  4635. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['colspan'] = $colspan;
  4636. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['rowspan'] = $rowspan;
  4637. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Xr'] = HTML2PDF::$_tables[$param['num']]['corr_x'];
  4638. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Yr'] = HTML2PDF::$_tables[$param['num']]['corr_y'];
  4639. // prepare the mapping for rowspan and colspan
  4640. for ($j=0; $j<$rowspan; $j++) {
  4641. for ($i=0; $i<$colspan; $i++) {
  4642. HTML2PDF::$_tables[$param['num']]['corr']
  4643. [HTML2PDF::$_tables[$param['num']]['corr_y']+$j]
  4644. [HTML2PDF::$_tables[$param['num']]['corr_x']+$i] = ($i+$j>0) ? '' : array($x,$y,$colspan,$rowspan);
  4645. }
  4646. }
  4647. HTML2PDF::$_tables[$param['num']]['corr_x']+= $colspan;
  4648. while (isset(HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']][HTML2PDF::$_tables[$param['num']]['corr_x']])) {
  4649. HTML2PDF::$_tables[$param['num']]['corr_x']++;
  4650. }
  4651. // extract the content of the TD, and calculate his size
  4652. $level = $this->parsingHtml->getLevel($this->_tempPos);
  4653. $this->_createSubHTML($this->_subHtml);
  4654. $this->_subHtml->parsingHtml->code = $level;
  4655. $this->_subHtml->_makeHTMLcode();
  4656. $this->_tempPos+= count($level);
  4657. } else {
  4658. // new position in the table
  4659. HTML2PDF::$_tables[$param['num']]['td_curr']++;
  4660. HTML2PDF::$_tables[$param['num']]['td_x']+= HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['dw'];
  4661. // borders and background of the TD
  4662. $this->_drawRectangle(
  4663. HTML2PDF::$_tables[$param['num']]['td_x'],
  4664. HTML2PDF::$_tables[$param['num']]['td_y'],
  4665. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['w'],
  4666. HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['h'],
  4667. $this->parsingCss->value['border'],
  4668. $this->parsingCss->value['padding'],
  4669. HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5,
  4670. $this->parsingCss->value['background']
  4671. );
  4672. $this->parsingCss->value['width'] = HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['w'] - $marge['l'] - $marge['r'];
  4673. // marges = size of the TD
  4674. $mL = HTML2PDF::$_tables[$param['num']]['td_x']+$marge['l'];
  4675. $mR = $this->pdf->getW() - $mL - $this->parsingCss->value['width'];
  4676. $this->_saveMargin($mL, 0, $mR);
  4677. // position of the content, from vertical-align
  4678. $hCorr = HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['h'];
  4679. $hReel = HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['real_h'];
  4680. switch($this->parsingCss->value['vertical-align'])
  4681. {
  4682. case 'bottom':
  4683. $yCorr = $hCorr-$hReel;
  4684. break;
  4685. case 'middle':
  4686. $yCorr = ($hCorr-$hReel)*0.5;
  4687. break;
  4688. case 'top':
  4689. default:
  4690. $yCorr = 0;
  4691. break;
  4692. }
  4693. // position of the content
  4694. $x = HTML2PDF::$_tables[$param['num']]['td_x']+$marge['l'];
  4695. $y = HTML2PDF::$_tables[$param['num']]['td_y']+$marge['t']+$yCorr;
  4696. $this->pdf->setXY($x, $y);
  4697. $this->_setNewPositionForNewLine();
  4698. }
  4699. return true;
  4700. }
  4701. /**
  4702. * tag : TD
  4703. * mode : CLOSE
  4704. *
  4705. * @param array $param
  4706. * @return boolean
  4707. */
  4708. protected function _tag_close_TD($param)
  4709. {
  4710. if ($this->_isForOneLine) return false;
  4711. $this->_maxH = 0;
  4712. // get the margins
  4713. $marge = array();
  4714. $marge['t'] = $this->parsingCss->value['padding']['t']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['t']['width'];
  4715. $marge['r'] = $this->parsingCss->value['padding']['r']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['r']['width'];
  4716. $marge['b'] = $this->parsingCss->value['padding']['b']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['b']['width'];
  4717. $marge['l'] = $this->parsingCss->value['padding']['l']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['l']['width'];
  4718. $marge['t']+= 0.001;
  4719. $marge['r']+= 0.001;
  4720. $marge['b']+= 0.001;
  4721. $marge['l']+= 0.001;
  4722. // if we are in a sub HTML
  4723. if ($this->_subPart) {
  4724. // it msut take only one page
  4725. if ($this->_testTdInOnepage && $this->_subHtml->pdf->getPage()>1) {
  4726. throw new HTML2PDF_exception(7);
  4727. }
  4728. // size of the content of the TD
  4729. $w0 = $this->_subHtml->_maxX + $marge['l'] + $marge['r'];
  4730. $h0 = $this->_subHtml->_maxY + $marge['t'] + $marge['b'];
  4731. // size from the CSS style
  4732. $w2 = $this->parsingCss->value['width'] + $marge['l'] + $marge['r'];
  4733. $h2 = $this->parsingCss->value['height'] + $marge['t'] + $marge['b'];
  4734. // final size of the TD
  4735. HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['w'] = max(array($w0, $w2));
  4736. HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['h'] = max(array($h0, $h2));
  4737. // real position of the content
  4738. HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['real_w'] = $w0;
  4739. HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['real_h'] = $h0;
  4740. // destroy the sub HTML
  4741. $this->_destroySubHTML($this->_subHtml);
  4742. } else {
  4743. $this->_loadMargin();
  4744. HTML2PDF::$_tables[$param['num']]['td_x']+= HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['w'];
  4745. }
  4746. $this->parsingCss->load();
  4747. $this->parsingCss->fontSet();
  4748. return true;
  4749. }
  4750. /**
  4751. * tag : TH
  4752. * mode : OPEN
  4753. *
  4754. * @param array $param
  4755. * @return boolean
  4756. */
  4757. protected function _tag_open_TH($param)
  4758. {
  4759. if ($this->_isForOneLine) return false;
  4760. $this->parsingCss->save();
  4761. $this->parsingCss->value['font-bold'] = true;
  4762. $this->_tag_open_TD($param, 'th');
  4763. return true;
  4764. }
  4765. /**
  4766. * tag : TH
  4767. * mode : CLOSE
  4768. *
  4769. * @param array $param
  4770. * @return boolean
  4771. */
  4772. protected function _tag_close_TH($param)
  4773. {
  4774. if ($this->_isForOneLine) return false;
  4775. $this->_tag_close_TD($param);
  4776. $this->parsingCss->load();
  4777. return true;
  4778. }
  4779. /**
  4780. * tag : IMG
  4781. * mode : OPEN
  4782. *
  4783. * @param array $param
  4784. * @return boolean
  4785. */
  4786. protected function _tag_open_IMG($param)
  4787. {
  4788. $src = str_replace('&amp;', '&', $param['src']);
  4789. $this->parsingCss->save();
  4790. $this->parsingCss->value['width'] = 0;
  4791. $this->parsingCss->value['height'] = 0;
  4792. $this->parsingCss->value['border'] = array('type' => 'none', 'width' => 0, 'color' => array(0, 0, 0));
  4793. $this->parsingCss->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
  4794. $this->parsingCss->analyse('img', $param);
  4795. $this->parsingCss->setPosition();
  4796. $this->parsingCss->fontSet();
  4797. $res = $this->_drawImage($src, isset($param['sub_li']));
  4798. if (!$res) return $res;
  4799. $this->parsingCss->load();
  4800. $this->parsingCss->fontSet();
  4801. $this->_maxE++;
  4802. return true;
  4803. }
  4804. /**
  4805. * tag : SELECT
  4806. * mode : OPEN
  4807. *
  4808. * @param array $param
  4809. * @return boolean
  4810. */
  4811. protected function _tag_open_SELECT($param)
  4812. {
  4813. if (!isset($param['name'])) {
  4814. $param['name'] = 'champs_pdf_'.(count($this->_lstField)+1);
  4815. }
  4816. $param['name'] = strtolower($param['name']);
  4817. if (isset($this->_lstField[$param['name']])) {
  4818. $this->_lstField[$param['name']]++;
  4819. } else {
  4820. $this->_lstField[$param['name']] = 1;
  4821. }
  4822. $this->parsingCss->save();
  4823. $this->parsingCss->analyse('select', $param);
  4824. $this->parsingCss->setPosition();
  4825. $this->parsingCss->fontSet();
  4826. $this->_lstSelect = array();
  4827. $this->_lstSelect['name'] = $param['name'];
  4828. $this->_lstSelect['multi'] = isset($param['multiple']) ? true : false;
  4829. $this->_lstSelect['size'] = isset($param['size']) ? $param['size'] : 1;
  4830. $this->_lstSelect['options'] = array();
  4831. if ($this->_lstSelect['multi'] && $this->_lstSelect['size']<3) $this->_lstSelect['size'] = 3;
  4832. return true;
  4833. }
  4834. /**
  4835. * tag : OPTION
  4836. * mode : OPEN
  4837. *
  4838. * @param array $param
  4839. * @return boolean
  4840. */
  4841. protected function _tag_open_OPTION($param)
  4842. {
  4843. // get the content of the option : it is the text of the option
  4844. $level = $this->parsingHtml->getLevel($this->_parsePos);
  4845. $this->_parsePos+= count($level);
  4846. $value = isset($param['value']) ? $param['value'] : 'aut_tag_open_opt_'.(count($this->_lstSelect)+1);
  4847. $this->_lstSelect['options'][$value] = isset($level[0]['param']['txt']) ? $level[0]['param']['txt'] : '';
  4848. return true;
  4849. }
  4850. /**
  4851. * tag : OPTION
  4852. * mode : CLOSE
  4853. *
  4854. * @param array $param
  4855. * @return boolean
  4856. */
  4857. protected function _tag_close_OPTION($param)
  4858. {
  4859. // nothing to do here
  4860. return true;
  4861. }
  4862. /**
  4863. * tag : SELECT
  4864. * mode : CLOSE
  4865. *
  4866. * @param array $param
  4867. * @return boolean
  4868. */
  4869. protected function _tag_close_SELECT()
  4870. {
  4871. // position of the select
  4872. $x = $this->pdf->getX();
  4873. $y = $this->pdf->getY();
  4874. $f = 1.08*$this->parsingCss->value['font-size'];
  4875. // width
  4876. $w = $this->parsingCss->value['width']; if (!$w) $w = 50;
  4877. // height (automatic)
  4878. $h = ($f*1.07*$this->_lstSelect['size'] + 1);
  4879. $prop = $this->parsingCss->getFormStyle();
  4880. // multy select
  4881. if ($this->_lstSelect['multi']) {
  4882. $prop['multipleSelection'] = 'true';
  4883. }
  4884. // single or multi select
  4885. if ($this->_lstSelect['size']>1) {
  4886. $this->pdf->ListBox($this->_lstSelect['name'], $w, $h, $this->_lstSelect['options'], $prop);
  4887. } else {
  4888. $this->pdf->ComboBox($this->_lstSelect['name'], $w, $h, $this->_lstSelect['options'], $prop);
  4889. }
  4890. $this->_maxX = max($this->_maxX, $x+$w);
  4891. $this->_maxY = max($this->_maxY, $y+$h);
  4892. $this->_maxH = max($this->_maxH, $h);
  4893. $this->_maxE++;
  4894. $this->pdf->setX($x+$w);
  4895. $this->parsingCss->load();
  4896. $this->parsingCss->fontSet();
  4897. $this->_lstSelect = array();
  4898. return true;
  4899. }
  4900. /**
  4901. * tag : TEXTAREA
  4902. * mode : OPEN
  4903. *
  4904. * @param array $param
  4905. * @return boolean
  4906. */
  4907. protected function _tag_open_TEXTAREA($param)
  4908. {
  4909. if (!isset($param['name'])) {
  4910. $param['name'] = 'champs_pdf_'.(count($this->_lstField)+1);
  4911. }
  4912. $param['name'] = strtolower($param['name']);
  4913. if (isset($this->_lstField[$param['name']])) {
  4914. $this->_lstField[$param['name']]++;
  4915. } else {
  4916. $this->_lstField[$param['name']] = 1;
  4917. }
  4918. $this->parsingCss->save();
  4919. $this->parsingCss->analyse('textarea', $param);
  4920. $this->parsingCss->setPosition();
  4921. $this->parsingCss->fontSet();
  4922. $x = $this->pdf->getX();
  4923. $y = $this->pdf->getY();
  4924. $fx = 0.65*$this->parsingCss->value['font-size'];
  4925. $fy = 1.08*$this->parsingCss->value['font-size'];
  4926. // extract the content the textarea : value
  4927. $level = $this->parsingHtml->getLevel($this->_parsePos);
  4928. $this->_parsePos+= count($level);
  4929. // automatic size, from cols and rows properties
  4930. $w = $fx*(isset($param['cols']) ? $param['cols'] : 22)+1;
  4931. $h = $fy*1.07*(isset($param['rows']) ? $param['rows'] : 3)+3;
  4932. $prop = $this->parsingCss->getFormStyle();
  4933. $prop['multiline'] = true;
  4934. $prop['value'] = isset($level[0]['param']['txt']) ? $level[0]['param']['txt'] : '';
  4935. $this->pdf->TextField($param['name'], $w, $h, $prop, array(), $x, $y);
  4936. $this->_maxX = max($this->_maxX, $x+$w);
  4937. $this->_maxY = max($this->_maxY, $y+$h);
  4938. $this->_maxH = max($this->_maxH, $h);
  4939. $this->_maxE++;
  4940. $this->pdf->setX($x+$w);
  4941. return true;
  4942. }
  4943. /**
  4944. * tag : TEXTAREA
  4945. * mode : CLOSE
  4946. *
  4947. * @param array $param
  4948. * @return boolean
  4949. */
  4950. protected function _tag_close_TEXTAREA()
  4951. {
  4952. $this->parsingCss->load();
  4953. $this->parsingCss->fontSet();
  4954. return true;
  4955. }
  4956. /**
  4957. * tag : INPUT
  4958. * mode : OPEN
  4959. *
  4960. * @param array $param
  4961. * @return boolean
  4962. */
  4963. protected function _tag_open_INPUT($param)
  4964. {
  4965. if (!isset($param['name'])) $param['name'] = 'champs_pdf_'.(count($this->_lstField)+1);
  4966. if (!isset($param['value'])) $param['value'] = '';
  4967. if (!isset($param['type'])) $param['type'] = 'text';
  4968. $param['name'] = strtolower($param['name']);
  4969. $param['type'] = strtolower($param['type']);
  4970. // the type must be valid
  4971. if (!in_array($param['type'], array('text', 'checkbox', 'radio', 'hidden', 'submit', 'reset', 'button'))) {
  4972. $param['type'] = 'text';
  4973. }
  4974. if (isset($this->_lstField[$param['name']])) {
  4975. $this->_lstField[$param['name']]++;
  4976. } else {
  4977. $this->_lstField[$param['name']] = 1;
  4978. }
  4979. $this->parsingCss->save();
  4980. $this->parsingCss->analyse('input', $param);
  4981. $this->parsingCss->setPosition();
  4982. $this->parsingCss->fontSet();
  4983. $name = $param['name'];
  4984. $x = $this->pdf->getX();
  4985. $y = $this->pdf->getY();
  4986. $f = 1.08*$this->parsingCss->value['font-size'];
  4987. $prop = $this->parsingCss->getFormStyle();
  4988. switch($param['type'])
  4989. {
  4990. case 'checkbox':
  4991. $w = 3;
  4992. $h = $w;
  4993. if ($h<$f) $y+= ($f-$h)*0.5;
  4994. $checked = (isset($param['checked']) && $param['checked']=='checked');
  4995. $this->pdf->CheckBox($name, $w, $checked, $prop, array(), ($param['value'] ? $param['value'] : 'Yes'), $x, $y);
  4996. break;
  4997. case 'radio':
  4998. $w = 3;
  4999. $h = $w;
  5000. if ($h<$f) $y+= ($f-$h)*0.5;
  5001. $checked = (isset($param['checked']) && $param['checked']=='checked');
  5002. $this->pdf->RadioButton($name, $w, $prop, array(), ($param['value'] ? $param['value'] : 'On'), $checked, $x, $y);
  5003. break;
  5004. case 'hidden':
  5005. $w = 0;
  5006. $h = 0;
  5007. $prop['value'] = $param['value'];
  5008. $this->pdf->TextField($name, $w, $h, $prop, array(), $x, $y);
  5009. break;
  5010. case 'text':
  5011. $w = $this->parsingCss->value['width']; if (!$w) $w = 40;
  5012. $h = $f*1.3;
  5013. $prop['value'] = $param['value'];
  5014. $this->pdf->TextField($name, $w, $h, $prop, array(), $x, $y);
  5015. break;
  5016. case 'submit':
  5017. $w = $this->parsingCss->value['width']; if (!$w) $w = 40;
  5018. $h = $this->parsingCss->value['height']; if (!$h) $h = $f*1.3;
  5019. $action = array('S'=>'SubmitForm', 'F'=>$this->_isInForm, 'Flags'=>array('ExportFormat'));
  5020. $this->pdf->Button($name, $w, $h, $param['value'], $action, $prop, array(), $x, $y);
  5021. break;
  5022. case 'reset':
  5023. $w = $this->parsingCss->value['width']; if (!$w) $w = 40;
  5024. $h = $this->parsingCss->value['height']; if (!$h) $h = $f*1.3;
  5025. $action = array('S'=>'ResetForm');
  5026. $this->pdf->Button($name, $w, $h, $param['value'], $action, $prop, array(), $x, $y);
  5027. break;
  5028. case 'button':
  5029. $w = $this->parsingCss->value['width']; if (!$w) $w = 40;
  5030. $h = $this->parsingCss->value['height']; if (!$h) $h = $f*1.3;
  5031. $action = isset($param['onclick']) ? $param['onclick'] : '';
  5032. $this->pdf->Button($name, $w, $h, $param['value'], $action, $prop, array(), $x, $y);
  5033. break;
  5034. default:
  5035. $w = 0;
  5036. $h = 0;
  5037. break;
  5038. }
  5039. $this->_maxX = max($this->_maxX, $x+$w);
  5040. $this->_maxY = max($this->_maxY, $y+$h);
  5041. $this->_maxH = max($this->_maxH, $h);
  5042. $this->_maxE++;
  5043. $this->pdf->setX($x+$w);
  5044. $this->parsingCss->load();
  5045. $this->parsingCss->fontSet();
  5046. return true;
  5047. }
  5048. /**
  5049. * tag : DRAW
  5050. * mode : OPEN
  5051. *
  5052. * @param array $param
  5053. * @return boolean
  5054. */
  5055. protected function _tag_open_DRAW($param)
  5056. {
  5057. if ($this->_isForOneLine) return false;
  5058. if ($this->_debugActif) $this->_DEBUG_add('DRAW', true);
  5059. $this->parsingCss->save();
  5060. $this->parsingCss->analyse('draw', $param);
  5061. $this->parsingCss->fontSet();
  5062. $alignObject = null;
  5063. if ($this->parsingCss->value['margin-auto']) $alignObject = 'center';
  5064. $overW = $this->parsingCss->value['width'];
  5065. $overH = $this->parsingCss->value['height'];
  5066. $this->parsingCss->value['old_maxX'] = $this->_maxX;
  5067. $this->parsingCss->value['old_maxY'] = $this->_maxY;
  5068. $this->parsingCss->value['old_maxH'] = $this->_maxH;
  5069. $w = $this->parsingCss->value['width'];
  5070. $h = $this->parsingCss->value['height'];
  5071. if (!$this->parsingCss->value['position']) {
  5072. if (
  5073. $w < ($this->pdf->getW() - $this->pdf->getlMargin()-$this->pdf->getrMargin()) &&
  5074. $this->pdf->getX() + $w>=($this->pdf->getW() - $this->pdf->getrMargin())
  5075. )
  5076. $this->_tag_open_BR(array());
  5077. if (
  5078. ($h < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin())) &&
  5079. ($this->pdf->getY() + $h>=($this->pdf->getH() - $this->pdf->getbMargin())) &&
  5080. !$this->_isInOverflow
  5081. )
  5082. $this->_setNewPage();
  5083. $old = $this->parsingCss->getOldValues();
  5084. $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  5085. if ($parentWidth>$w) {
  5086. if ($alignObject=='center') $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
  5087. else if ($alignObject=='right') $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
  5088. }
  5089. $this->parsingCss->setPosition();
  5090. } else {
  5091. $old = $this->parsingCss->getOldValues();
  5092. $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
  5093. if ($parentWidth>$w) {
  5094. if ($alignObject=='center') $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
  5095. else if ($alignObject=='right') $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
  5096. }
  5097. $this->parsingCss->setPosition();
  5098. $this->_saveMax();
  5099. $this->_maxX = 0;
  5100. $this->_maxY = 0;
  5101. $this->_maxH = 0;
  5102. $this->_maxE = 0;
  5103. }
  5104. $this->_drawRectangle(
  5105. $this->parsingCss->value['x'],
  5106. $this->parsingCss->value['y'],
  5107. $this->parsingCss->value['width'],
  5108. $this->parsingCss->value['height'],
  5109. $this->parsingCss->value['border'],
  5110. $this->parsingCss->value['padding'],
  5111. 0,
  5112. $this->parsingCss->value['background']
  5113. );
  5114. $marge = array();
  5115. $marge['l'] = $this->parsingCss->value['border']['l']['width'];
  5116. $marge['r'] = $this->parsingCss->value['border']['r']['width'];
  5117. $marge['t'] = $this->parsingCss->value['border']['t']['width'];
  5118. $marge['b'] = $this->parsingCss->value['border']['b']['width'];
  5119. $this->parsingCss->value['width'] -= $marge['l']+$marge['r'];
  5120. $this->parsingCss->value['height']-= $marge['t']+$marge['b'];
  5121. $overW-= $marge['l']+$marge['r'];
  5122. $overH-= $marge['t']+$marge['b'];
  5123. // clipping to draw only in the size opf the DRAW tag
  5124. $this->pdf->clippingPathStart(
  5125. $this->parsingCss->value['x']+$marge['l'],
  5126. $this->parsingCss->value['y']+$marge['t'],
  5127. $this->parsingCss->value['width'],
  5128. $this->parsingCss->value['height']
  5129. );
  5130. // left and right of the DRAW tag
  5131. $mL = $this->parsingCss->value['x']+$marge['l'];
  5132. $mR = $this->pdf->getW() - $mL - $overW;
  5133. // position of the DRAW tag
  5134. $x = $this->parsingCss->value['x']+$marge['l'];
  5135. $y = $this->parsingCss->value['y']+$marge['t'];
  5136. // prepare the drawing area
  5137. $this->_saveMargin($mL, 0, $mR);
  5138. $this->pdf->setXY($x, $y);
  5139. // we are in a draw tag
  5140. $this->_isInDraw = array(
  5141. 'x' => $x,
  5142. 'y' => $y,
  5143. 'w' => $overW,
  5144. 'h' => $overH,
  5145. );
  5146. // init the translate matrix : (0,0) => ($x, $y)
  5147. $this->pdf->doTransform(array(1,0,0,1,$x,$y));
  5148. $this->pdf->SetAlpha(1.);
  5149. return true;
  5150. }
  5151. /**
  5152. * tag : DRAW
  5153. * mode : CLOSE
  5154. *
  5155. * @param array $param
  5156. * @return boolean
  5157. */
  5158. protected function _tag_close_DRAW($param)
  5159. {
  5160. if ($this->_isForOneLine) return false;
  5161. $this->pdf->SetAlpha(1.);
  5162. $this->pdf->undoTransform();
  5163. $this->pdf->clippingPathStop();
  5164. $this->_maxX = $this->parsingCss->value['old_maxX'];
  5165. $this->_maxY = $this->parsingCss->value['old_maxY'];
  5166. $this->_maxH = $this->parsingCss->value['old_maxH'];
  5167. $marge = array();
  5168. $marge['l'] = $this->parsingCss->value['border']['l']['width'];
  5169. $marge['r'] = $this->parsingCss->value['border']['r']['width'];
  5170. $marge['t'] = $this->parsingCss->value['border']['t']['width'];
  5171. $marge['b'] = $this->parsingCss->value['border']['b']['width'];
  5172. $x = $this->parsingCss->value['x'];
  5173. $y = $this->parsingCss->value['y'];
  5174. $w = $this->parsingCss->value['width']+$marge['l']+$marge['r'];
  5175. $h = $this->parsingCss->value['height']+$marge['t']+$marge['b'];
  5176. if ($this->parsingCss->value['position']!='absolute') {
  5177. $this->pdf->setXY($x+$w, $y);
  5178. $this->_maxX = max($this->_maxX, $x+$w);
  5179. $this->_maxY = max($this->_maxY, $y+$h);
  5180. $this->_maxH = max($this->_maxH, $h);
  5181. $this->_maxE++;
  5182. } else {
  5183. // position
  5184. $this->pdf->setXY($this->parsingCss->value['xc'], $this->parsingCss->value['yc']);
  5185. $this->_loadMax();
  5186. }
  5187. $block = ($this->parsingCss->value['display']!='inline' && $this->parsingCss->value['position']!='absolute');
  5188. $this->parsingCss->load();
  5189. $this->parsingCss->fontSet();
  5190. $this->_loadMargin();
  5191. if ($block) $this->_tag_open_BR(array());
  5192. if ($this->_debugActif) $this->_DEBUG_add('DRAW', false);
  5193. $this->_isInDraw = null;
  5194. return true;
  5195. }
  5196. /**
  5197. * tag : LINE
  5198. * mode : OPEN
  5199. *
  5200. * @param array $param
  5201. * @return boolean
  5202. */
  5203. protected function _tag_open_LINE($param)
  5204. {
  5205. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'LINE');
  5206. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5207. $this->parsingCss->save();
  5208. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5209. $styles['fill'] = null;
  5210. $style = $this->pdf->svgSetStyle($styles);
  5211. $x1 = isset($param['x1']) ? $this->parsingCss->ConvertToMM($param['x1'], $this->_isInDraw['w']) : 0.;
  5212. $y1 = isset($param['y1']) ? $this->parsingCss->ConvertToMM($param['y1'], $this->_isInDraw['h']) : 0.;
  5213. $x2 = isset($param['x2']) ? $this->parsingCss->ConvertToMM($param['x2'], $this->_isInDraw['w']) : 0.;
  5214. $y2 = isset($param['y2']) ? $this->parsingCss->ConvertToMM($param['y2'], $this->_isInDraw['h']) : 0.;
  5215. $this->pdf->svgLine($x1, $y1, $x2, $y2);
  5216. $this->pdf->undoTransform();
  5217. $this->parsingCss->load();
  5218. }
  5219. /**
  5220. * tag : RECT
  5221. * mode : OPEN
  5222. *
  5223. * @param array $param
  5224. * @return boolean
  5225. */
  5226. protected function _tag_open_RECT($param)
  5227. {
  5228. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'RECT');
  5229. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5230. $this->parsingCss->save();
  5231. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5232. $style = $this->pdf->svgSetStyle($styles);
  5233. $x = isset($param['x']) ? $this->parsingCss->ConvertToMM($param['x'], $this->_isInDraw['w']) : 0.;
  5234. $y = isset($param['y']) ? $this->parsingCss->ConvertToMM($param['y'], $this->_isInDraw['h']) : 0.;
  5235. $w = isset($param['w']) ? $this->parsingCss->ConvertToMM($param['w'], $this->_isInDraw['w']) : 0.;
  5236. $h = isset($param['h']) ? $this->parsingCss->ConvertToMM($param['h'], $this->_isInDraw['h']) : 0.;
  5237. $this->pdf->svgRect($x, $y, $w, $h, $style);
  5238. $this->pdf->undoTransform();
  5239. $this->parsingCss->load();
  5240. }
  5241. /**
  5242. * tag : CIRCLE
  5243. * mode : OPEN
  5244. *
  5245. * @param array $param
  5246. * @return boolean
  5247. */
  5248. protected function _tag_open_CIRCLE($param)
  5249. {
  5250. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'CIRCLE');
  5251. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5252. $this->parsingCss->save();
  5253. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5254. $style = $this->pdf->svgSetStyle($styles);
  5255. $cx = isset($param['cx']) ? $this->parsingCss->ConvertToMM($param['cx'], $this->_isInDraw['w']) : 0.;
  5256. $cy = isset($param['cy']) ? $this->parsingCss->ConvertToMM($param['cy'], $this->_isInDraw['h']) : 0.;
  5257. $r = isset($param['r']) ? $this->parsingCss->ConvertToMM($param['r'], $this->_isInDraw['w']) : 0.;
  5258. $this->pdf->svgEllipse($cx, $cy, $r, $r, $style);
  5259. $this->pdf->undoTransform();
  5260. $this->parsingCss->load();
  5261. }
  5262. /**
  5263. * tag : ELLIPSE
  5264. * mode : OPEN
  5265. *
  5266. * @param array $param
  5267. * @return boolean
  5268. */
  5269. protected function _tag_open_ELLIPSE($param)
  5270. {
  5271. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'ELLIPSE');
  5272. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5273. $this->parsingCss->save();
  5274. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5275. $style = $this->pdf->svgSetStyle($styles);
  5276. $cx = isset($param['cx']) ? $this->parsingCss->ConvertToMM($param['cx'], $this->_isInDraw['w']) : 0.;
  5277. $cy = isset($param['cy']) ? $this->parsingCss->ConvertToMM($param['cy'], $this->_isInDraw['h']) : 0.;
  5278. $rx = isset($param['ry']) ? $this->parsingCss->ConvertToMM($param['rx'], $this->_isInDraw['w']) : 0.;
  5279. $ry = isset($param['rx']) ? $this->parsingCss->ConvertToMM($param['ry'], $this->_isInDraw['h']) : 0.;
  5280. $this->pdf->svgEllipse($cx, $cy, $rx, $ry, $style);
  5281. $this->pdf->undoTransform();
  5282. $this->parsingCss->load();
  5283. }
  5284. /**
  5285. * tag : POLYLINE
  5286. * mode : OPEN
  5287. *
  5288. * @param array $param
  5289. * @return boolean
  5290. */
  5291. protected function _tag_open_POLYLINE($param)
  5292. {
  5293. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'POLYGON');
  5294. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5295. $this->parsingCss->save();
  5296. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5297. $style = $this->pdf->svgSetStyle($styles);
  5298. $path = isset($param['points']) ? $param['points'] : null;
  5299. if ($path) {
  5300. $path = str_replace(',', ' ', $path);
  5301. $path = preg_replace('/[\s]+/', ' ', trim($path));
  5302. // prepare the path
  5303. $path = explode(' ', $path);
  5304. foreach ($path as $k => $v) {
  5305. $path[$k] = trim($v);
  5306. if ($path[$k]==='') unset($path[$k]);
  5307. }
  5308. $path = array_values($path);
  5309. $actions = array();
  5310. for ($k=0; $k<count($path); $k+=2) {
  5311. $actions[] = array(
  5312. ($k ? 'L' : 'M') ,
  5313. $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']),
  5314. $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h'])
  5315. );
  5316. }
  5317. // drawing
  5318. $this->pdf->svgPolygone($actions, $style);
  5319. }
  5320. $this->pdf->undoTransform();
  5321. $this->parsingCss->load();
  5322. }
  5323. /**
  5324. * tag : POLYGON
  5325. * mode : OPEN
  5326. *
  5327. * @param array $param
  5328. * @return boolean
  5329. */
  5330. protected function _tag_open_POLYGON($param)
  5331. {
  5332. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'POLYGON');
  5333. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5334. $this->parsingCss->save();
  5335. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5336. $style = $this->pdf->svgSetStyle($styles);
  5337. $path = (isset($param['points']) ? $param['points'] : null);
  5338. if ($path) {
  5339. $path = str_replace(',', ' ', $path);
  5340. $path = preg_replace('/[\s]+/', ' ', trim($path));
  5341. // prepare the path
  5342. $path = explode(' ', $path);
  5343. foreach ($path as $k => $v) {
  5344. $path[$k] = trim($v);
  5345. if ($path[$k]==='') unset($path[$k]);
  5346. }
  5347. $path = array_values($path);
  5348. $actions = array();
  5349. for ($k=0; $k<count($path); $k+=2) {
  5350. $actions[] = array(
  5351. ($k ? 'L' : 'M') ,
  5352. $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']),
  5353. $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h'])
  5354. );
  5355. }
  5356. $actions[] = array('z');
  5357. // drawing
  5358. $this->pdf->svgPolygone($actions, $style);
  5359. }
  5360. $this->pdf->undoTransform();
  5361. $this->parsingCss->load();
  5362. }
  5363. /**
  5364. * tag : PATH
  5365. * mode : OPEN
  5366. *
  5367. * @param array $param
  5368. * @return boolean
  5369. */
  5370. protected function _tag_open_PATH($param)
  5371. {
  5372. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'PATH');
  5373. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5374. $this->parsingCss->save();
  5375. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5376. $style = $this->pdf->svgSetStyle($styles);
  5377. $path = isset($param['d']) ? $param['d'] : null;
  5378. if ($path) {
  5379. // prepare the path
  5380. $path = str_replace(',', ' ', $path);
  5381. $path = preg_replace('/([a-zA-Z])([0-9\.\-])/', '$1 $2', $path);
  5382. $path = preg_replace('/([0-9\.])([a-zA-Z])/', '$1 $2', $path);
  5383. $path = preg_replace('/[\s]+/', ' ', trim($path));
  5384. $path = preg_replace('/ ([a-z]{2})/', '$1', $path);
  5385. $path = explode(' ', $path);
  5386. foreach ($path as $k => $v) {
  5387. $path[$k] = trim($v);
  5388. if ($path[$k]==='') unset($path[$k]);
  5389. }
  5390. $path = array_values($path);
  5391. // read each actions in the path
  5392. $actions = array();
  5393. $action = array();
  5394. $lastAction = null; // last action found
  5395. for ($k=0; $k<count($path);true) {
  5396. // for this actions, we can not have multi coordonate
  5397. if (in_array($lastAction, array('z', 'Z'))) {
  5398. $lastAction = null;
  5399. }
  5400. // read the new action (forcing if no action before)
  5401. if (preg_match('/^[a-z]+$/i', $path[$k]) || $lastAction===null) {
  5402. $lastAction = $path[$k];
  5403. $k++;
  5404. }
  5405. // current action
  5406. $action = array();
  5407. $action[] = $lastAction;
  5408. switch($lastAction)
  5409. {
  5410. case 'C':
  5411. case 'c':
  5412. $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']); // x1
  5413. $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']); // y1
  5414. $action[] = $this->parsingCss->ConvertToMM($path[$k+2], $this->_isInDraw['w']); // x2
  5415. $action[] = $this->parsingCss->ConvertToMM($path[$k+3], $this->_isInDraw['h']); // y2
  5416. $action[] = $this->parsingCss->ConvertToMM($path[$k+4], $this->_isInDraw['w']); // x
  5417. $action[] = $this->parsingCss->ConvertToMM($path[$k+5], $this->_isInDraw['h']); // y
  5418. $k+= 6;
  5419. break;
  5420. case 'Q':
  5421. case 'S':
  5422. case 'q':
  5423. case 's':
  5424. $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']); // x2
  5425. $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']); // y2
  5426. $action[] = $this->parsingCss->ConvertToMM($path[$k+2], $this->_isInDraw['w']); // x
  5427. $action[] = $this->parsingCss->ConvertToMM($path[$k+3], $this->_isInDraw['h']); // y
  5428. $k+= 4;
  5429. break;
  5430. case 'A':
  5431. case 'a':
  5432. $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']); // rx
  5433. $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']); // ry
  5434. $action[] = 1.*$path[$k+2]; // angle de deviation de l'axe X
  5435. $action[] = ($path[$k+3]=='1') ? 1 : 0; // large-arc-flag
  5436. $action[] = ($path[$k+4]=='1') ? 1 : 0; // sweep-flag
  5437. $action[] = $this->parsingCss->ConvertToMM($path[$k+5], $this->_isInDraw['w']); // x
  5438. $action[] = $this->parsingCss->ConvertToMM($path[$k+6], $this->_isInDraw['h']); // y
  5439. $k+= 7;
  5440. break;
  5441. case 'M':
  5442. case 'L':
  5443. case 'T':
  5444. case 'm':
  5445. case 'l':
  5446. case 't':
  5447. $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']); // x
  5448. $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']); // y
  5449. $k+= 2;
  5450. break;
  5451. case 'H':
  5452. case 'h':
  5453. $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']); // x
  5454. $k+= 1;
  5455. break;
  5456. case 'V':
  5457. case 'v':
  5458. $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['h']); // y
  5459. $k+= 1;
  5460. break;
  5461. case 'z':
  5462. case 'Z':
  5463. default:
  5464. break;
  5465. }
  5466. // add the action
  5467. $actions[] = $action;
  5468. }
  5469. // drawing
  5470. $this->pdf->svgPolygone($actions, $style);
  5471. }
  5472. $this->pdf->undoTransform();
  5473. $this->parsingCss->load();
  5474. }
  5475. /**
  5476. * tag : G
  5477. * mode : OPEN
  5478. *
  5479. * @param array $param
  5480. * @return boolean
  5481. */
  5482. protected function _tag_open_G($param)
  5483. {
  5484. if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'G');
  5485. $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
  5486. $this->parsingCss->save();
  5487. $styles = $this->parsingCss->getSvgStyle('path', $param);
  5488. $style = $this->pdf->svgSetStyle($styles);
  5489. }
  5490. /**
  5491. * tag : G
  5492. * mode : CLOSE
  5493. *
  5494. * @param array $param
  5495. * @return boolean
  5496. */
  5497. protected function _tag_close_G($param)
  5498. {
  5499. $this->pdf->undoTransform();
  5500. $this->parsingCss->load();
  5501. }
  5502. /**
  5503. * new page for the automatic Index, does not use thie method. Only HTML2PDF_myPdf could use it !!!!
  5504. *
  5505. * @param &int $page
  5506. * @return integer $oldPage
  5507. */
  5508. public function _INDEX_NewPage(&$page)
  5509. {
  5510. if ($page) {
  5511. $oldPage = $this->pdf->getPage();
  5512. $this->pdf->setPage($page);
  5513. $this->pdf->setXY($this->_margeLeft, $this->_margeTop);
  5514. $this->_maxH = 0;
  5515. $page++;
  5516. return $oldPage;
  5517. } else {
  5518. $this->_setNewPage();
  5519. return null;
  5520. }
  5521. }
  5522. }
  5523. }