/include/html2pdf/html2pdf.class.php

https://bitbucket.org/sleininger/stock_online · PHP · 6125 lines · 4031 code · 857 blank · 1237 comment · 664 complexity · 2c96e3ec10ad42db995aacb6c834a163 MD5 · raw file

Large files are truncated click here to view the full file

  1. <?php
  2. /**
  3. * Logiciel : HTML2PDF
  4. *
  5. * Convertisseur HTML => PDF, utilise TCPDF
  6. * Distribuי sous la licence LGPL.
  7. *
  8. * @author Laurent MINGUET <webmaster@html2pdf.fr>
  9. * @version 4.01
  10. */
  11. if (!defined('__CLASS_HTML2PDF__'))
  12. {
  13. define('__CLASS_HTML2PDF__', '4.01');
  14. require_once(dirname(__FILE__).'/_mypdf/mypdf.class.php'); // classe mypdf
  15. require_once(dirname(__FILE__).'/parsingHTML.class.php'); // classe de parsing HTML
  16. require_once(dirname(__FILE__).'/styleHTML.class.php'); // classe de gestion des styles
  17. class HTML2PDF
  18. {
  19. public $pdf = null; // objet PDF
  20. public $style = null; // objet de style
  21. public $parsing = null; // objet de parsing
  22. protected $langue = 'fr'; // langue des messages
  23. protected $sens = 'P'; // sens d'affichage Portrait ou Landscape
  24. protected $format = 'A4'; // format de la page : A4, A3, ...
  25. protected $encoding = ''; // charset encoding
  26. protected $unicode = true; // means that the input text is unicode (default = true)
  27. protected $background = array(); // informations sur le background
  28. protected $testTDin1page = true; // activer le test de TD ne devant pas depasser une page
  29. protected $testIsImage = true; // test si les images existes ou non
  30. protected $testIsDeprecated = false; // test si certaines fonctions sont deprecated
  31. protected $isSubPart = false; // indique que le convertisseur courant est un sous html
  32. protected $parse_pos = 0; // position du parsing
  33. protected $temp_pos = 0; // position temporaire pour multi tableau
  34. protected $page = 0; // numero de la page courante
  35. protected $sub_html = null; // sous html
  36. protected $sub_part = false; // indicateur de sous html
  37. protected $maxX = 0; // zone maxi X
  38. protected $maxY = 0; // zone maxi Y
  39. protected $maxE = 0; // nomre d'elements dans la zone
  40. protected $maxH = 0; // plus grande hauteur dans la ligne, pour saut de ligne א corriger
  41. protected $maxSave = array(); // tableau de sauvegarde des maximaux
  42. protected $currentH = 0; // hauteur de la ligne courante
  43. protected $firstPage = true; // premier page
  44. protected $defaultLeft = 0; // marges par default de la page
  45. protected $defaultTop = 0;
  46. protected $defaultRight = 0;
  47. protected $defaultBottom = 0;
  48. protected $margeLeft = 0; //marges rיelles de la page
  49. protected $margeTop = 0;
  50. protected $margeRight = 0;
  51. protected $margeBottom = 0;
  52. protected $marges = array(); // tableau de sauvegarde des differents etats des marges de la page courante
  53. protected $inLink = ''; // indique si on est א l'interieur d'un lien
  54. protected $lstAncre = array(); // liste des ancres dיtectיes ou crייes
  55. protected $subHEADER = array(); // tableau des sous commandes pour faire l'HEADER
  56. protected $subFOOTER = array(); // tableau des sous commandes pour faire le FOOTER
  57. protected $subSTATES = array(); // tableau de sauvegarde de certains paramטtres
  58. protected $defLIST = array(); // tableau de sauvegarde de l'etat des UL et OL
  59. protected $lstChamps = array(); // liste des champs
  60. protected $lstSelect = array(); // options du select en cours
  61. protected $previousCall = null; // dernier appel
  62. protected $pageMarges = array(); // marges spיcifiques dues aux floats
  63. protected $isInThead = false; // indique si on est dans un thead
  64. protected $isInTfoot = false; // indique si on est dans un tfoot
  65. protected $isInOverflow = false; // indique si on est dans une div overflow
  66. protected $isInFooter = false; // indique si on est dans un footer ou non
  67. protected $isInDraw = null; // indique si on est en mode dessin
  68. protected $isAfterFloat = false; // indique si on est apres un float
  69. protected $forOneLine = false; // indique si on est dans un sous HTML ne servant qu'a calculer la taille de la prochaine ligne
  70. protected $isInForm = false; // indique si on est dans un formulaire. Contient dans ce cas lא l'action de celui-ci
  71. protected $DEBUG_actif = false; // indique si on est en mode debug
  72. protected $DEBUG_ok_usage = false; // indique l'existance de la fonction memory_get_usage
  73. protected $DEBUG_ok_peak = false; // indique l'existance de la fonction memory_get_peak_usage
  74. protected $DEBUG_level = 0; // niveau du debug
  75. protected $DEBUG_start_time = 0; //
  76. protected $DEBUG_last_time = 0; //
  77. protected $defaultFont = null; // fonte par dיfaut si la fonte demandיe n'existe pas
  78. static protected $SUBOBJ = null; // sous objet HTML2PDF prיparי en cas de besoin
  79. static protected $TABLES = array(); // tableau global necessaire א la gestion des tables imbriquיes
  80. static protected $TEXTES = array(); // tableau comprennant le fichier de langue
  81. /**
  82. * Constructeur
  83. *
  84. * @param string sens portrait ou landscape
  85. * @param string format A4, A5, ...
  86. * @param string langue : fr, en, it...
  87. * @param boolean $unicode TRUE means that the input text is unicode (default = true)
  88. * @param String $encoding charset encoding; default is UTF-8
  89. * @param array marges par defaut, dans l'ordre (left, top, right, bottom)
  90. * @return null
  91. */
  92. public function __construct($sens = 'P', $format = 'A4', $langue='fr', $unicode=true, $encoding='UTF-8', $marges = array(5, 5, 5, 8))
  93. {
  94. // sauvegarde des paramטtres
  95. $this->page = 0;
  96. $this->sens = $sens;
  97. $this->format = $format;
  98. $this->unicode = $unicode;
  99. $this->encoding = $encoding;
  100. $this->firstPage = true;
  101. $this->langue = strtolower($langue);
  102. // chargement du fichier de langue
  103. HTML2PDF::textLOAD($this->langue);
  104. // crיation de l' objet PDF
  105. $this->pdf = new MyPDF($sens, 'mm', $format, $unicode, $encoding);
  106. // initialisation des styles
  107. $this->style = new styleHTML($this->pdf);
  108. $this->style->FontSet();
  109. $this->defLIST = array();
  110. // initialisations diverses
  111. $this->setTestTdInOnePage(true);
  112. $this->setTestIsImage(true);
  113. $this->setTestIsDeprecated(true);
  114. $this->setDefaultFont(null);
  115. // initialisation du parsing
  116. $this->parsing = new parsingHTML($this->encoding);
  117. $this->sub_html = null;
  118. $this->sub_part = false;
  119. // initialisation des marges
  120. if (!is_array($marges)) $marges = array($marges, $marges, $marges, $marges);
  121. $this->setDefaultMargins($marges[0], $marges[1], $marges[2], $marges[3]);
  122. $this->setMargins();
  123. $this->marges = array();
  124. // initialisation des champs de formulaire
  125. $this->lstChamps = array();
  126. }
  127. /**
  128. * Destructeur
  129. *
  130. * @return null
  131. */
  132. public function __destruct()
  133. {
  134. }
  135. /**
  136. * activer le debug mode
  137. *
  138. * @return null
  139. */
  140. public function setModeDebug()
  141. {
  142. list($usec, $sec) = explode(' ', microtime());
  143. $this->DEBUG_actif = true;
  144. $this->DEBUG_ok_usage = function_exists('memory_get_usage');
  145. $this->DEBUG_ok_peak = function_exists('memory_get_peak_usage');
  146. $this->DEBUG_start_time = (float)$sec + (float)$usec;
  147. $this->DEBUG_last_time = (float)$sec + (float)$usec;
  148. $this->DEBUG_stepline('step', 'time', 'delta', 'memory', 'peak');
  149. $this->DEBUG_add('Init debug');
  150. }
  151. /**
  152. * rajouter une ligne de debug
  153. *
  154. * @param string nom de l'etape
  155. * @param boolean true=monter d'un niveau, false=descendre d'un niveau, null : ne rien faire
  156. * @return null
  157. */
  158. protected function DEBUG_add($nom, $level=null)
  159. {
  160. list($usec, $sec) = explode(' ', microtime());
  161. if ($level===true) $this->DEBUG_level++;
  162. $nom = str_repeat(' ',$this->DEBUG_level). $nom.($level===true ? ' Begin' : ($level===false ? ' End' : ''));
  163. $time = (float)$sec + (float)$usec;
  164. $usage = ($this->DEBUG_ok_usage ? memory_get_usage() : 0);
  165. $peak = ($this->DEBUG_ok_peak ? memory_get_peak_usage() : 0);
  166. $this->DEBUG_stepline(
  167. $nom,
  168. number_format(($time - $this->DEBUG_start_time)*1000, 1, '.', ' ').' ms',
  169. number_format(($time - $this->DEBUG_last_time)*1000, 1, '.', ' ').' ms',
  170. number_format($usage/1024, 1, '.', ' ').' Ko',
  171. number_format($peak/1024, 1, '.', ' ').' Ko');
  172. $this->DEBUG_last_time = $time;
  173. if ($level===false) $this->DEBUG_level--;
  174. return true;
  175. }
  176. /**
  177. * affiche une ligne de debug
  178. *
  179. * @param string nom de l'etape
  180. * @param string valeur 1
  181. * @param string valeur 2
  182. * @param string valeur 3
  183. * @param string valeur 4
  184. * @return null
  185. */
  186. protected function DEBUG_stepline($nom, $val1, $val2, $val3, $val4)
  187. {
  188. $txt = str_pad($nom, 30, ' ', STR_PAD_RIGHT).
  189. str_pad($val1, 12, ' ', STR_PAD_LEFT).
  190. str_pad($val2, 12, ' ', STR_PAD_LEFT).
  191. str_pad($val3, 15, ' ', STR_PAD_LEFT).
  192. str_pad($val4, 15, ' ', STR_PAD_LEFT);
  193. echo '<pre style="padding:0; margin:0">'.$txt.'</pre>';
  194. }
  195. /**
  196. * activer ou desactiver le test de TD ne devant pas depasser une page
  197. *
  198. * @param boolean nouvel etat
  199. * @return boolean ancien etat
  200. */
  201. public function setTestTdInOnePage($mode = true)
  202. {
  203. $old = $this->testTDin1page;
  204. $this->testTDin1page = $mode ? true : false;
  205. return $old;
  206. }
  207. /**
  208. * activer ou desactiver le test sur la prיsence des images
  209. *
  210. * @param boolean nouvel etat
  211. * @return boolean ancien etat
  212. */
  213. public function setTestIsImage($mode = true)
  214. {
  215. $old = $this->testIsImage;
  216. $this->testIsImage = $mode ? true : false;
  217. return $old;
  218. }
  219. /**
  220. * activer ou desactiver le test sur les fonctions deprecated
  221. *
  222. * @param boolean nouvel etat
  223. * @return boolean ancien etat
  224. */
  225. public function setTestIsDeprecated($mode = true)
  226. {
  227. $old = $this->testIsDeprecated;
  228. $this->testIsDeprecated = $mode ? true : false;
  229. return $old;
  230. }
  231. /**
  232. * dיfinit la fonte par dיfaut si aucun fonte n'est spיcifiיe, ou si la fonte demandיe n'existe pas
  233. *
  234. * @param string nom de la fonte par defaut. si null : Arial pour fonte non spיcifiיe, et erreur pour fonte non existante
  235. * @return string nom de l'ancienne fonte par defaut
  236. */
  237. public function setDefaultFont($default = null)
  238. {
  239. $old = $this->defaultFont;
  240. $this->defaultFont = $default;
  241. $this->style->setDefaultFont($default);
  242. return $old;
  243. }
  244. /**
  245. * dיfinir les marges par dיfault
  246. *
  247. * @param int en mm, marge left
  248. * @param int en mm, marge top
  249. * @param int en mm, marge right. si null, left=right
  250. * @param int en mm, marge bottom. si null, bottom=8
  251. * @return null
  252. */
  253. protected function setDefaultMargins($left, $top, $right = null, $bottom = null)
  254. {
  255. if ($right===null) $right = $left;
  256. if ($bottom===null) $bottom = 8;
  257. $this->defaultLeft = $this->style->ConvertToMM($left.'mm');
  258. $this->defaultTop = $this->style->ConvertToMM($top.'mm');
  259. $this->defaultRight = $this->style->ConvertToMM($right.'mm');
  260. $this->defaultBottom = $this->style->ConvertToMM($bottom.'mm');
  261. }
  262. /**
  263. * dיfinir les marges rיelles, fonctions de la balise page
  264. *
  265. * @return null
  266. */
  267. protected function setMargins()
  268. {
  269. $this->margeLeft = $this->defaultLeft + (isset($this->background['left']) ? $this->background['left'] : 0);
  270. $this->margeRight = $this->defaultRight + (isset($this->background['right']) ? $this->background['right'] : 0);
  271. $this->margeTop = $this->defaultTop + (isset($this->background['top']) ? $this->background['top'] : 0);
  272. $this->margeBottom = $this->defaultBottom + (isset($this->background['bottom']) ? $this->background['bottom'] : 0);
  273. $this->pdf->SetMargins($this->margeLeft, $this->margeTop, $this->margeRight);
  274. $this->pdf->setcMargin(0);
  275. $this->pdf->SetAutoPageBreak(false, $this->margeBottom);
  276. $this->pageMarges = array();
  277. $this->pageMarges[floor($this->margeTop*100)] = array($this->margeLeft, $this->pdf->getW()-$this->margeRight);
  278. }
  279. /**
  280. * recuperer les positions x minimales et maximales en fonction d'une hauteur
  281. *
  282. * @param float y
  283. * @return array(float, float)
  284. */
  285. protected function getMargins($y)
  286. {
  287. $y = floor($y*100);
  288. $x = array($this->pdf->getlMargin(), $this->pdf->getW()-$this->pdf->getrMargin());
  289. foreach($this->pageMarges as $m_y => $m_x)
  290. if ($m_y<=$y) $x = $m_x;
  291. return $x;
  292. }
  293. /**
  294. * ajouter une marge suite a un float
  295. *
  296. * @param string left ou right
  297. * @param float x1
  298. * @param float y1
  299. * @param float x2
  300. * @param float y2
  301. * @return null
  302. */
  303. protected function addMargins($float, $x1, $y1, $x2, $y2)
  304. {
  305. $old1 = $this->getMargins($y1);
  306. $old2 = $this->getMargins($y2);
  307. if ($float=='left') $old1[0] = $x2;
  308. if ($float=='right') $old1[1] = $x1;
  309. $y1 = floor($y1*100);
  310. $y2 = floor($y2*100);
  311. foreach($this->pageMarges as $m_y => $m_x)
  312. {
  313. if ($m_y<$y1) continue;
  314. if ($m_y>$y2) break;
  315. if ($float=='left' && $this->pageMarges[$m_y][0]<$x2) unset($this->pageMarges[$m_y]);
  316. if ($float=='right' && $this->pageMarges[$m_y][1]>$x1) unset($this->pageMarges[$m_y]);
  317. }
  318. $this->pageMarges[$y1] = $old1;
  319. $this->pageMarges[$y2] = $old2;
  320. ksort($this->pageMarges);
  321. $this->isAfterFloat = true;
  322. }
  323. /**
  324. * dיfinir des nouvelles marges et sauvegarder les anciennes
  325. *
  326. * @param float marge left
  327. * @param float marge top
  328. * @param float marge right
  329. * @return null
  330. */
  331. protected function saveMargin($ml, $mt, $mr)
  332. {
  333. $this->marges[] = array('l' => $this->pdf->getlMargin(), 't' => $this->pdf->gettMargin(), 'r' => $this->pdf->getrMargin(), 'page' => $this->pageMarges);
  334. $this->pdf->SetMargins($ml, $mt, $mr);
  335. $this->pageMarges = array();
  336. $this->pageMarges[floor($mt*100)] = array($ml, $this->pdf->getW()-$mr);
  337. }
  338. /**
  339. * rיcuperer les derniטres marches sauvיes
  340. *
  341. * @return null
  342. */
  343. protected function loadMargin()
  344. {
  345. $old = array_pop($this->marges);
  346. if ($old)
  347. {
  348. $ml = $old['l'];
  349. $mt = $old['t'];
  350. $mr = $old['r'];
  351. $mP = $old['page'];
  352. }
  353. else
  354. {
  355. $ml = $this->margeLeft;
  356. $mt = 0;
  357. $mr = $this->margeRight;
  358. $mP = array($mt => array($ml, $this->pdf->getW()-$mr));
  359. }
  360. $this->pdf->SetMargins($ml, $mt, $mr);
  361. $this->pageMarges = $mP;
  362. }
  363. /**
  364. * permet d'ajouter une fonte.
  365. *
  366. * @param string nom de la fonte
  367. * @param string style de la fonte
  368. * @param string fichier de la fonte
  369. * @return null
  370. */
  371. public function addFont($family, $style='', $file='')
  372. {
  373. $this->pdf->AddFont($family, $style, $file);
  374. }
  375. /**
  376. * sauvegarder l'יtat actuelle des maximums
  377. *
  378. * @return null
  379. */
  380. protected function saveMax()
  381. {
  382. $this->maxSave[] = array($this->maxX, $this->maxY, $this->maxH, $this->maxE);
  383. }
  384. /**
  385. * charger le dernier יtat sauvי des maximums
  386. *
  387. * @return null
  388. */
  389. protected function loadMax()
  390. {
  391. $old = array_pop($this->maxSave);
  392. if ($old)
  393. {
  394. $this->maxX = $old[0];
  395. $this->maxY = $old[1];
  396. $this->maxH = $old[2];
  397. $this->maxE = $old[3];
  398. }
  399. else
  400. {
  401. $this->maxX = 0;
  402. $this->maxY = 0;
  403. $this->maxH = 0;
  404. $this->maxE = 0;
  405. }
  406. }
  407. /**
  408. * afficher l'header contenu dans page_header
  409. *
  410. * @return null
  411. */
  412. protected function setPageHeader()
  413. {
  414. if (!count($this->subHEADER)) return false;
  415. $OLD_parse_pos = $this->parse_pos;
  416. $OLD_parse_code = $this->parsing->code;
  417. $this->parse_pos = 0;
  418. $this->parsing->code = $this->subHEADER;
  419. $this->makeHTMLcode();
  420. $this->parse_pos = $OLD_parse_pos;
  421. $this->parsing->code = $OLD_parse_code;
  422. }
  423. /**
  424. * afficher le footer contenu dans page_footer
  425. *
  426. * @return null
  427. */
  428. protected function setPageFooter()
  429. {
  430. if (!count($this->subFOOTER)) return false;
  431. $OLD_parse_pos = $this->parse_pos;
  432. $OLD_parse_code = $this->parsing->code;
  433. $this->parse_pos = 0;
  434. $this->parsing->code = $this->subFOOTER;
  435. $this->isInFooter = true;
  436. $this->makeHTMLcode();
  437. $this->isInFooter = false;
  438. $this->parse_pos = $OLD_parse_pos;
  439. $this->parsing->code = $OLD_parse_code;
  440. }
  441. /**
  442. * saut de ligne avec une hauteur spיcifique
  443. *
  444. * @param float hauteur de la ligne
  445. * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
  446. * @return null
  447. */
  448. protected function setNewLine($h, $curr = null)
  449. {
  450. $this->pdf->Ln($h);
  451. $this->setNewPositionForNewLine($curr);
  452. }
  453. /**
  454. * crיation d'une nouvelle page avec le format et l'orientation spיcifies
  455. *
  456. * @param mixed format de la page : A5, A4, array(width, height)
  457. * @param string sens P=portrait ou L=landscape
  458. * @param array tableau des propriיtיs du fond de la page
  459. * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
  460. * @return null
  461. */
  462. public function setNewPage($format = null, $orientation = '', $background = null, $curr = null)
  463. {
  464. $this->firstPage = false;
  465. $this->format = $format ? $format : $this->format;
  466. $this->sens = $orientation ? $orientation : $this->sens;
  467. $this->background = $background!==null ? $background : $this->background;
  468. $this->maxY = 0;
  469. $this->maxX = 0;
  470. $this->maxH = 0;
  471. $this->pdf->SetMargins($this->defaultLeft, $this->defaultTop, $this->defaultRight);
  472. $this->pdf->AddPage($this->sens, $this->format);
  473. $this->page++;
  474. if (!$this->sub_part && !$this->isSubPart)
  475. {
  476. if (is_array($this->background))
  477. {
  478. if (isset($this->background['color']) && $this->background['color'])
  479. {
  480. $this->pdf->setFillColorArray($this->background['color']);
  481. $this->pdf->Rect(0, 0, $this->pdf->getW(), $this->pdf->getH(), 'F');
  482. }
  483. if (isset($this->background['img']) && $this->background['img'])
  484. $this->pdf->Image($this->background['img'], $this->background['posX'], $this->background['posY'], $this->background['width']);
  485. }
  486. $this->setPageHeader();
  487. $this->setPageFooter();
  488. }
  489. $this->setMargins();
  490. $this->pdf->setY($this->margeTop);
  491. $this->setNewPositionForNewLine($curr);
  492. $this->maxH = 0;
  493. }
  494. /**
  495. * calcul de la position de debut de la prochaine ligne en fonction de l'alignement voulu
  496. *
  497. * @param integer position reelle courante si saut de ligne pendant l'ecriture d'un texte
  498. * @return null
  499. */
  500. protected function setNewPositionForNewLine($curr = null)
  501. {
  502. list($lx, $rx) = $this->getMargins($this->pdf->getY());
  503. $this->pdf->setX($lx);
  504. $wMax = $rx-$lx;
  505. $this->currentH = 0;
  506. if ($this->sub_part || $this->isSubPart || $this->forOneLine)
  507. {
  508. // $this->pdf->setWordSpacing(0);
  509. return null;
  510. }
  511. /*
  512. if (
  513. $this->style->value['text-align']!='right' &&
  514. $this->style->value['text-align']!='center' &&
  515. $this->style->value['text-align']!='justify'
  516. )
  517. {
  518. // $this->pdf->setWordSpacing(0);
  519. return null;
  520. }
  521. */
  522. $sub = null;
  523. $this->createSubHTML($sub);
  524. $sub->saveMargin(0, 0, $sub->pdf->getW()-$wMax);
  525. $sub->forOneLine = true;
  526. $sub->parse_pos = $this->parse_pos;
  527. $sub->parsing->code = $this->parsing->code;
  528. if ($curr!==null && $sub->parsing->code[$this->parse_pos]['name']=='write')
  529. {
  530. $txt = $sub->parsing->code[$this->parse_pos]['param']['txt'];
  531. $txt = str_replace('[[page_cu]]', $sub->page, $txt);
  532. $sub->parsing->code[$this->parse_pos]['param']['txt'] = substr($txt, $curr);
  533. }
  534. else
  535. $sub->parse_pos++;
  536. // pour chaque element identifiי par le parsing
  537. $res = null;
  538. for($sub->parse_pos; $sub->parse_pos<count($sub->parsing->code); $sub->parse_pos++)
  539. {
  540. $todo = $sub->parsing->code[$sub->parse_pos];
  541. $res = $sub->loadAction($todo);
  542. if (!$res) break;
  543. }
  544. $w = $sub->maxX; // largeur maximale
  545. $h = $sub->maxH; // hauteur maximale
  546. $e = ($res===null ? $sub->maxE : 0); // nombre d'יlיments maximal
  547. $this->destroySubHTML($sub);
  548. if ($this->style->value['text-align']=='center')
  549. $this->pdf->setX(($rx+$this->pdf->getX()-$w)*0.5-0.01);
  550. elseif ($this->style->value['text-align']=='right')
  551. $this->pdf->setX($rx-$w-0.01);
  552. else
  553. $this->pdf->setX($lx);
  554. $this->currentH = $h;
  555. /*
  556. if ($this->style->value['text-align']=='justify' && $e>1)
  557. $this->pdf->setWordSpacing(($wMax-$w)/($e-1));
  558. else
  559. $this->pdf->setWordSpacing(0);
  560. */
  561. }
  562. /**
  563. * rיcupיration du PDF
  564. *
  565. * @param string nom du fichier PDF
  566. * @param boolean destination
  567. * @return string contenu יventuel du pdf
  568. *
  569. *
  570. * Destination oש envoyer le document. Le paramטtre peut prendre les valeurs suivantes :
  571. * true : equivalent א I
  572. * false : equivalent א S
  573. * I : envoyer en inline au navigateur. Le plug-in est utilisי s'il est installי. Le nom indiquי dans name est utilisי lorsque l'on sיlectionne "Enregistrer sous" sur le lien gיnיrant le PDF.
  574. * D : envoyer au navigateur en forחant le tיlיchargement, avec le nom indiquי dans name.
  575. * F : sauver dans un fichier local, avec le nom indiquי dans name (peut inclure un rיpertoire).
  576. * S : renvoyer le document sous forme de chaמne. name est ignorי.
  577. */
  578. public function Output($name = '', $dest = false)
  579. {
  580. // nettoyage
  581. HTML2PDF::$TABLES = array();
  582. if ($this->DEBUG_actif)
  583. {
  584. $this->DEBUG_add('Before output');
  585. $this->pdf->Close();
  586. exit;
  587. }
  588. // interpretation des paramטtres
  589. if ($dest===false) $dest = 'I';
  590. if ($dest===true) $dest = 'S';
  591. if ($dest==='') $dest = 'I';
  592. if ($name=='') $name='document.pdf';
  593. // verification de la destination
  594. $dest = strtoupper($dest);
  595. if (!in_array($dest, array('I', 'D', 'F', 'S'))) $dest = 'I';
  596. // verification du nom
  597. if (strtolower(substr($name, -4))!='.pdf')
  598. {
  599. echo 'ERROR : The output document name "'.$name.'" is not a PDF name';
  600. exit;
  601. }
  602. return $this->pdf->Output($name, $dest);
  603. }
  604. /**
  605. * preparation de HTML2PDF::$SUBOBJ utilisי pour la crיation des sous HTML2PDF
  606. *
  607. * @return null
  608. */
  609. protected function prepareSubObj()
  610. {
  611. $pdf = null;
  612. HTML2PDF::$SUBOBJ = new HTML2PDF(
  613. $this->sens,
  614. $this->format,
  615. $this->langue,
  616. $this->unicode,
  617. $this->encoding,
  618. array($this->defaultLeft,$this->defaultTop,$this->defaultRight,$this->defaultBottom)
  619. );
  620. // initialisation
  621. HTML2PDF::$SUBOBJ->setIsSubPart();
  622. HTML2PDF::$SUBOBJ->setTestTdInOnePage($this->testTDin1page);
  623. HTML2PDF::$SUBOBJ->setTestIsImage($this->testIsImage);
  624. HTML2PDF::$SUBOBJ->setTestIsDeprecated($this->testIsDeprecated);
  625. HTML2PDF::$SUBOBJ->setDefaultFont($this->defaultFont);
  626. HTML2PDF::$SUBOBJ->style->css = &$this->style->css;
  627. HTML2PDF::$SUBOBJ->style->css_keys = &$this->style->css_keys;
  628. HTML2PDF::$SUBOBJ->pdf->cloneFontFrom($this->pdf);
  629. HTML2PDF::$SUBOBJ->style->setPdfParent($pdf);
  630. }
  631. /**
  632. * fonction de clonage pour la creation d'un sous HTML2PDF א partir de HTML2PDF::$SUBOBJ
  633. *
  634. * @return null
  635. */
  636. public function __clone()
  637. {
  638. $this->pdf = clone $this->pdf;
  639. $this->parsing = clone $this->parsing;
  640. $this->style = clone $this->style;
  641. $this->style->setPdfParent($this->pdf);
  642. }
  643. /**
  644. * crיation d'un sous HTML2PDF pour la gestion des tableaux imbriquיs
  645. *
  646. * @param HTML2PDF futur sous HTML2PDF passי en rיfיrence pour crיation
  647. * @param integer marge eventuelle de l'objet si simulation d'un TD
  648. * @return null
  649. */
  650. protected function createSubHTML(&$sub_html, $cellmargin=0)
  651. {
  652. if (!HTML2PDF::$SUBOBJ) $this->prepareSubObj();
  653. // calcul de la largueur
  654. if ($this->style->value['width'])
  655. {
  656. $marge = $cellmargin*2;
  657. $marge+= $this->style->value['padding']['l'] + $this->style->value['padding']['r'];
  658. $marge+= $this->style->value['border']['l']['width'] + $this->style->value['border']['r']['width'];
  659. $marge = $this->pdf->getW() - $this->style->value['width'] + $marge;
  660. }
  661. else
  662. $marge = $this->margeLeft+$this->margeRight;
  663. //clonage
  664. $sub_html = clone HTML2PDF::$SUBOBJ;
  665. $sub_html->style->table = $this->style->table;
  666. $sub_html->style->value = $this->style->value;
  667. $sub_html->style->setOnlyLeft();
  668. $sub_html->setNewPage($this->format, $this->sens);
  669. $sub_html->initSubHtml($marge, $this->page, $this->defLIST);
  670. }
  671. /**
  672. * initialise le sous HTML2PDF. Ne pas utiliser directement. seul la fonction createSubHTML doit l'utiliser
  673. *
  674. * @return null
  675. */
  676. public function initSubHtml($marge, $page, $defLIST)
  677. {
  678. $this->saveMargin(0, 0, $marge);
  679. $this->defLIST = $defLIST;
  680. $this->page = $page;
  681. $this->pdf->setXY(0, 0);
  682. $this->style->FontSet();
  683. }
  684. public function setIsSubPart()
  685. {
  686. $this->isSubPart = true;
  687. }
  688. /**
  689. * destruction d'un sous HTML2PDF pour la gestion des tableaux imbriquיs
  690. *
  691. * @return null
  692. */
  693. protected function destroySubHTML(&$sub_html)
  694. {
  695. unset($sub_html);
  696. $sub_html = null;
  697. }
  698. /**
  699. * Convertir un nombre arabe en nombre romain
  700. *
  701. * @param integer nombre א convertir
  702. * @return string nombre converti
  703. */
  704. protected function listeArab2Rom($nb_ar)
  705. {
  706. $nb_b10 = array('I','X','C','M');
  707. $nb_b5 = array('V','L','D');
  708. $nb_ro = '';
  709. if ($nb_ar<1) return $nb_ar;
  710. if ($nb_ar>3999) return $nb_ar;
  711. for($i=3; $i>=0 ; $i--)
  712. {
  713. $chiffre=floor($nb_ar/pow(10,$i));
  714. if($chiffre>=1)
  715. {
  716. $nb_ar=$nb_ar-$chiffre*pow(10,$i);
  717. if($chiffre<=3)
  718. {
  719. for($j=$chiffre; $j>=1; $j--)
  720. {
  721. $nb_ro=$nb_ro.$nb_b10[$i];
  722. }
  723. }
  724. else if($chiffre==9)
  725. {
  726. $nb_ro=$nb_ro.$nb_b10[$i].$nb_b10[$i+1];
  727. }
  728. elseif($chiffre==4)
  729. {
  730. $nb_ro=$nb_ro.$nb_b10[$i].$nb_b5[$i];
  731. }
  732. else
  733. {
  734. $nb_ro=$nb_ro.$nb_b5[$i];
  735. for($j=$chiffre-5; $j>=1; $j--)
  736. {
  737. $nb_ro=$nb_ro.$nb_b10[$i];
  738. }
  739. }
  740. }
  741. }
  742. return $nb_ro;
  743. }
  744. /**
  745. * Ajouter un LI au niveau actuel
  746. *
  747. * @return null
  748. */
  749. protected function listeAddLi()
  750. {
  751. $this->defLIST[count($this->defLIST)-1]['nb']++;
  752. }
  753. protected function listeGetWidth() { return '7mm'; }
  754. protected function listeGetPadding() { return '1mm'; }
  755. /**
  756. * Recuperer le LI du niveau actuel
  757. *
  758. * @return string chaine א afficher
  759. */
  760. protected function listeGetLi()
  761. {
  762. $im = $this->defLIST[count($this->defLIST)-1]['img'];
  763. $st = $this->defLIST[count($this->defLIST)-1]['style'];
  764. $nb = $this->defLIST[count($this->defLIST)-1]['nb'];
  765. $up = (substr($st, 0, 6)=='upper-');
  766. if ($im) return array(false, false, $im);
  767. switch($st)
  768. {
  769. case 'none':
  770. return array('helvetica', true, ' ');
  771. case 'upper-alpha':
  772. case 'lower-alpha':
  773. $str = '';
  774. while($nb>26)
  775. {
  776. $str = chr(96+$nb%26).$str;
  777. $nb = floor($nb/26);
  778. }
  779. $str = chr(96+$nb).$str;
  780. return array('helvetica', false, ($up ? strtoupper($str) : $str).'.');
  781. case 'upper-roman':
  782. case 'lower-roman':
  783. $str = $this->listeArab2Rom($nb);
  784. return array('helvetica', false, ($up ? strtoupper($str) : $str).'.');
  785. case 'decimal':
  786. return array('helvetica', false, $nb.'.');
  787. case 'square':
  788. return array('zapfdingbats', true, chr(110));
  789. case 'circle':
  790. return array('zapfdingbats', true, chr(109));
  791. case 'disc':
  792. default:
  793. return array('zapfdingbats', true, chr(108));
  794. }
  795. }
  796. /**
  797. * Ajouter un niveau de liste
  798. *
  799. * @param string type de liste : ul, ol
  800. * @param string style de la liste
  801. * @return null
  802. */
  803. protected function listeAddLevel($type = 'ul', $style = '', $img = null)
  804. {
  805. if ($img)
  806. {
  807. if (preg_match('/^url\(([^)]+)\)$/isU', trim($img), $match))
  808. $img = $match[1];
  809. else
  810. $img = null;
  811. }
  812. else
  813. $img = null;
  814. if (!in_array($type, array('ul', 'ol'))) $type = 'ul';
  815. if (!in_array($style, array('lower-alpha', 'upper-alpha', 'upper-roman', 'lower-roman', 'decimal', 'square', 'circle', 'disc', 'none'))) $style = '';
  816. if (!$style)
  817. {
  818. if ($type=='ul') $style = 'disc';
  819. else $style = 'decimal';
  820. }
  821. $this->defLIST[count($this->defLIST)] = array('style' => $style, 'nb' => 0, 'img' => $img);
  822. }
  823. /**
  824. * Supprimer un niveau de liste
  825. *
  826. * @return null
  827. */
  828. protected function listeDelLevel()
  829. {
  830. if (count($this->defLIST))
  831. {
  832. unset($this->defLIST[count($this->defLIST)-1]);
  833. $this->defLIST = array_values($this->defLIST);
  834. }
  835. }
  836. /**
  837. * traitement d'un code HTML fait pour HTML2PDF
  838. *
  839. * @param string code HTML א convertir
  840. * @param boolean afficher en pdf (false) ou en html adaptי (true)
  841. * @return null
  842. */
  843. public function writeHTML($html, $vue = false)
  844. {
  845. // si c'est une vrai page HTML, une conversion s'impose
  846. if (preg_match('/<body/isU', $html))
  847. $html = $this->getHtmlFromPage($html);
  848. $html = str_replace('[[page_nb]]', '{nb}', $html);
  849. $html = str_replace('[[date_y]]', date('Y'), $html);
  850. $html = str_replace('[[date_m]]', date('m'), $html);
  851. $html = str_replace('[[date_d]]', date('d'), $html);
  852. $html = str_replace('[[date_h]]', date('H'), $html);
  853. $html = str_replace('[[date_i]]', date('i'), $html);
  854. $html = str_replace('[[date_s]]', date('s'), $html);
  855. // si on veut voir le rיsultat en HTML => on appelle la fonction
  856. if ($vue) $this->vueHTML($html);
  857. // sinon, traitement pour conversion en PDF :
  858. // parsing
  859. $this->sub_pdf = false;
  860. $this->style->readStyle($html);
  861. $this->parsing->setHTML($html);
  862. $this->parsing->parse();
  863. $this->makeHTMLcode();
  864. }
  865. /**
  866. * traitement du code d'une vrai page HTML pour l'adapter א HTML2PDF
  867. *
  868. * @param string code HTML א adapter
  869. * @return string code HTML adaptי
  870. */
  871. public function getHtmlFromPage($html)
  872. {
  873. $html = str_replace('<BODY', '<body', $html);
  874. $html = str_replace('</BODY', '</body', $html);
  875. // extraction du contenu
  876. $res = explode('<body', $html);
  877. if (count($res)<2) return $html;
  878. $content = '<page'.$res[1];
  879. $content = explode('</body', $content);
  880. $content = $content[0].'</page>';
  881. // extraction des balises link
  882. preg_match_all('/<link([^>]*)>/isU', $html, $match);
  883. foreach($match[0] as $src)
  884. $content = $src.'</link>'.$content;
  885. // extraction des balises style
  886. preg_match_all('/<style[^>]*>(.*)<\/style[^>]*>/isU', $html, $match);
  887. foreach($match[0] as $src)
  888. $content = $src.$content;
  889. return $content;
  890. }
  891. /**
  892. * execute les diffיrentes actions du code HTML
  893. *
  894. * @return null
  895. */
  896. protected function makeHTMLcode()
  897. {
  898. // pour chaque element identifiי par le parsing
  899. for($this->parse_pos=0; $this->parse_pos<count($this->parsing->code); $this->parse_pos++)
  900. {
  901. // rיcupיration de l'יlיment
  902. $todo = $this->parsing->code[$this->parse_pos];
  903. // si c'est une ouverture de tableau
  904. if (in_array($todo['name'], array('table', 'ul', 'ol')) && !$todo['close'])
  905. {
  906. // on va crיer un sous HTML, et on va travailler sur une position temporaire
  907. $tag_open = $todo['name'];
  908. $this->sub_part = true;
  909. $this->temp_pos = $this->parse_pos;
  910. // pour tous les יlיments jusqu'א la fermeture de la table afin de prיparer les dimensions
  911. while(isset($this->parsing->code[$this->temp_pos]) && !($this->parsing->code[$this->temp_pos]['name']==$tag_open && $this->parsing->code[$this->temp_pos]['close']))
  912. {
  913. $this->loadAction($this->parsing->code[$this->temp_pos]);
  914. $this->temp_pos++;
  915. }
  916. if (isset($this->parsing->code[$this->temp_pos])) $this->loadAction($this->parsing->code[$this->temp_pos]);
  917. $this->sub_part = false;
  918. }
  919. // chargement de l'action correspondant א l'יlיment
  920. $this->loadAction($todo);
  921. }
  922. }
  923. /**
  924. * affichage en mode HTML du contenu
  925. *
  926. * @param string contenu
  927. * @return null
  928. */
  929. protected function vueHTML($content)
  930. {
  931. $content = preg_replace('/<page_header([^>]*)>/isU', '<hr>'.HTML2PDF::textGET('vue01').' : $1<hr><div$1>', $content);
  932. $content = preg_replace('/<page_footer([^>]*)>/isU', '<hr>'.HTML2PDF::textGET('vue02').' : $1<hr><div$1>', $content);
  933. $content = preg_replace('/<page([^>]*)>/isU', '<hr>'.HTML2PDF::textGET('vue03').' : $1<hr><div$1>', $content);
  934. $content = preg_replace('/<\/page([^>]*)>/isU', '</div><hr>', $content);
  935. $content = preg_replace('/<bookmark([^>]*)>/isU', '<hr>bookmark : $1<hr>', $content);
  936. $content = preg_replace('/<\/bookmark([^>]*)>/isU', '', $content);
  937. $content = preg_replace('/<barcode([^>]*)>/isU', '<hr>barcode : $1<hr>', $content);
  938. $content = preg_replace('/<\/barcode([^>]*)>/isU', '', $content);
  939. $content = preg_replace('/<qrcode([^>]*)>/isU', '<hr>qrcode : $1<hr>', $content);
  940. $content = preg_replace('/<\/qrcode([^>]*)>/isU', '', $content);
  941. echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  942. <html>
  943. <head>
  944. <title>'.HTML2PDF::textGET('vue04').' HTML</title>
  945. <meta http-equiv="Content-Type" content="text/html; charset='.$this->encoding.'" >
  946. </head>
  947. <body style="padding: 10px; font-size: 10pt;font-family: Verdana;">
  948. '.$content.'
  949. </body>
  950. </html>';
  951. exit;
  952. }
  953. /**
  954. * chargement de l'action correspondante א un element de parsing
  955. *
  956. * @param array יlיment de parsing
  957. * @return null
  958. */
  959. protected function loadAction($row)
  960. {
  961. // nom de l'action
  962. $fnc = ($row['close'] ? 'c_' : 'o_').strtoupper($row['name']);
  963. // parametres de l'action
  964. $param = $row['param'];
  965. // si aucune page n'est crיי, on la crיי
  966. if ($fnc!='o_PAGE' && $this->firstPage)
  967. {
  968. $this->setNewPage();
  969. }
  970. // lancement de l'action
  971. if (is_callable(array(&$this, $fnc)))
  972. {
  973. $res = $this->{$fnc}($param);
  974. $this->previousCall = $fnc;
  975. return $res;
  976. }
  977. else
  978. throw new HTML2PDF_exception(1, strtoupper($row['name']), $this->parsing->getHtmlErrorCode($row['html_pos']));
  979. }
  980. /**
  981. * balise : PAGE
  982. * mode : OUVERTURE
  983. *
  984. * @param array paramטtres de l'יlיment de parsing
  985. * @return null
  986. */
  987. protected function o_PAGE($param)
  988. {
  989. if ($this->forOneLine) return false;
  990. if ($this->DEBUG_actif) $this->DEBUG_add('PAGE n°'.($this->page+1), true);
  991. $newPageSet= (!isset($param['pageset']) || $param['pageset']!='old');
  992. $this->maxH = 0;
  993. if ($newPageSet)
  994. {
  995. $this->subHEADER = array();
  996. $this->subFOOTER = array();
  997. // identification de l'orientation demandיe
  998. $orientation = '';
  999. if (isset($param['orientation']))
  1000. {
  1001. $param['orientation'] = strtolower($param['orientation']);
  1002. if ($param['orientation']=='p') $orientation = 'P';
  1003. if ($param['orientation']=='portrait') $orientation = 'P';
  1004. if ($param['orientation']=='l') $orientation = 'L';
  1005. if ($param['orientation']=='paysage') $orientation = 'L';
  1006. if ($param['orientation']=='landscape') $orientation = 'L';
  1007. }
  1008. // identification de l'orientation demandיe
  1009. $format = null;
  1010. if (isset($param['format']))
  1011. {
  1012. $format = strtolower($param['format']);
  1013. if (preg_match('/^([0-9]+)x([0-9]+)$/isU', $format, $match))
  1014. {
  1015. $format = array(intval($match[1]), intval($match[2]));
  1016. }
  1017. }
  1018. // identification des propriיtיs du background
  1019. $background = array();
  1020. if (isset($param['backimg']))
  1021. {
  1022. $background['img'] = isset($param['backimg']) ? $param['backimg'] : ''; // nom de l'image
  1023. $background['posX'] = isset($param['backimgx']) ? $param['backimgx'] : 'center'; // position horizontale de l'image
  1024. $background['posY'] = isset($param['backimgy']) ? $param['backimgy'] : 'middle'; // position verticale de l'image
  1025. $background['width'] = isset($param['backimgw']) ? $param['backimgw'] : '100%'; // taille de l'image (100% = largueur de la feuille)
  1026. // conversion du nom de l'image, en cas de paramטtres en _GET
  1027. $background['img'] = str_replace('&amp;', '&', $background['img']);
  1028. // conversion des positions
  1029. if ($background['posX']=='left') $background['posX'] = '0%';
  1030. if ($background['posX']=='center') $background['posX'] = '50%';
  1031. if ($background['posX']=='right') $background['posX'] = '100%';
  1032. if ($background['posY']=='top') $background['posY'] = '0%';
  1033. if ($background['posY']=='middle') $background['posY'] = '50%';
  1034. if ($background['posY']=='bottom') $background['posY'] = '100%';
  1035. // si il y a une image de prיcisי
  1036. if ($background['img'])
  1037. {
  1038. // est-ce que c'est une image ?
  1039. $infos=@GetImageSize($background['img']);
  1040. if (count($infos)>1)
  1041. {
  1042. // taille de l'image, en fonction de la taille spיcifiיe.
  1043. $Wi = $this->style->ConvertToMM($background['width'], $this->pdf->getW());
  1044. $Hi = $Wi*$infos[1]/$infos[0];
  1045. // rיcupיration des dimensions et positions de l'image
  1046. $background['width'] = $Wi;
  1047. $background['posX'] = $this->style->ConvertToMM($background['posX'], $this->pdf->getW() - $Wi);
  1048. $background['posY'] = $this->style->ConvertToMM($background['posY'], $this->pdf->getH() - $Hi);
  1049. }
  1050. else
  1051. $background = array();
  1052. }
  1053. else
  1054. $background = array();
  1055. }
  1056. // marges TOP et BOTTOM pour le texte.
  1057. $background['top'] = isset($param['backtop']) ? $param['backtop'] : '0';
  1058. $background['bottom'] = isset($param['backbottom']) ? $param['backbottom'] : '0';
  1059. $background['left'] = isset($param['backleft']) ? $param['backleft'] : '0';
  1060. $background['right'] = isset($param['backright']) ? $param['backright'] : '0';
  1061. if (preg_match('/^([0-9]*)$/isU', $background['top'])) $background['top'] .= 'mm';
  1062. if (preg_match('/^([0-9]*)$/isU', $background['bottom'])) $background['bottom'] .= 'mm';
  1063. if (preg_match('/^([0-9]*)$/isU', $background['left'])) $background['left'] .= 'mm';
  1064. if (preg_match('/^([0-9]*)$/isU', $background['right'])) $background['right'] .= 'mm';
  1065. $background['top'] = $this->style->ConvertToMM($background['top'], $this->pdf->getH());
  1066. $background['bottom'] = $this->style->ConvertToMM($background['bottom'], $this->pdf->getH());
  1067. $background['left'] = $this->style->ConvertToMM($background['left'], $this->pdf->getW());
  1068. $background['right'] = $this->style->ConvertToMM($background['right'], $this->pdf->getW());
  1069. $res = false;
  1070. $background['color'] = isset($param['backcolor']) ? $this->style->ConvertToColor($param['backcolor'], $res) : null;
  1071. if (!$res) $background['color'] = null;
  1072. $this->style->save();
  1073. $this->style->analyse('PAGE', $param);
  1074. $this->style->setPosition();
  1075. $this->style->FontSet();
  1076. // nouvelle page
  1077. $this->setNewPage($format, $orientation, $background);
  1078. // footer automatique
  1079. if (isset($param['footer']))
  1080. {
  1081. $lst = explode(';', $param['footer']);
  1082. foreach($lst as $key => $val) $lst[$key] = trim(strtolower($val));
  1083. $page = in_array('page', $lst);
  1084. $date = in_array('date', $lst);
  1085. $heure = in_array('heure', $lst);
  1086. $form = in_array('form', $lst);
  1087. }
  1088. else
  1089. {
  1090. $page = null;
  1091. $date = null;
  1092. $heure = null;
  1093. $form = null;
  1094. }
  1095. $this->pdf->SetMyFooter($page, $date, $heure, $form);
  1096. }
  1097. else
  1098. {
  1099. $this->style->save();
  1100. $this->style->analyse('PAGE', $param);
  1101. $this->style->setPosition();
  1102. $this->style->FontSet();
  1103. $this->setNewPage();
  1104. }
  1105. return true;
  1106. }
  1107. /**
  1108. * balise : PAGE
  1109. * mode : FERMETURE
  1110. *
  1111. * @param array paramטtres de l'יlיment de parsing
  1112. * @return null
  1113. */
  1114. protected function c_PAGE($param)
  1115. {
  1116. if ($this->forOneLine) return false;
  1117. $this->maxH = 0;
  1118. $this->style->load();
  1119. $this->style->FontSet();
  1120. if ($this->DEBUG_actif) $this->DEBUG_add('PAGE n°'.$this->page, false);
  1121. return true;
  1122. }
  1123. protected function o_PAGE_HEADER($param)
  1124. {
  1125. if ($this->forOneLine) return false;
  1126. $this->subHEADER = array();
  1127. for($this->parse_pos; $this->parse_pos<count($this->parsing->code); $this->parse_pos++)
  1128. {
  1129. $todo = $this->parsing->code[$this->parse_pos];
  1130. if ($todo['name']=='page_header') $todo['name']='page_header_sub';
  1131. $this->subHEADER[] = $todo;
  1132. if (strtolower($todo['name'])=='page_header_sub' && $todo['close']) break;
  1133. }
  1134. $this->setPageHeader();
  1135. return true;
  1136. }
  1137. protected function o_PAGE_FOOTER($param)
  1138. {
  1139. if ($this->forOneLine) return false;
  1140. $this->subFOOTER = array();
  1141. for($this->parse_pos; $this->parse_pos<count($this->parsing->code); $this->parse_pos++)
  1142. {
  1143. $todo = $this->parsing->code[$this->parse_pos];
  1144. if ($todo['name']=='page_footer') $todo['name']='page_footer_sub';
  1145. $this->subFOOTER[] = $todo;
  1146. if (strtolower($todo['name'])=='page_footer_sub' && $todo['close']) break;
  1147. }
  1148. $this->setPageFooter();
  1149. return true;
  1150. }
  1151. protected function o_PAGE_HEADER_SUB($param)
  1152. {
  1153. if ($this->forOneLine) return false;
  1154. // sauvegarde de l'יtat
  1155. $this->subSTATES = array();
  1156. $this->subSTATES['x'] = $this->pdf->getX();
  1157. $this->subSTATES['y'] = $this->pdf->getY();
  1158. $this->subSTATES['s'] = $this->style->value;
  1159. $this->subSTATES['t'] = $this->style->table;
  1160. $this->subSTATES['ml'] = $this->margeLeft;
  1161. $this->subSTATES['mr'] = $this->margeRight;
  1162. $this->subSTATES['mt'] = $this->margeTop;
  1163. $this->subSTATES['mb'] = $this->margeBottom;
  1164. $this->subSTATES['mp'] = $this->pageMarges;
  1165. // nouvel etat pour le footer
  1166. $this->pageMarges = array();
  1167. $this->margeLeft = $this->defaultLeft;
  1168. $this->margeRight = $this->defaultRight;
  1169. $this->margeTop = $this->defaultTop;
  1170. $this->margeBottom = $this->defaultBottom;
  1171. $this->pdf->SetMargins($this->margeLeft, $this->margeTop, $this->margeRight);
  1172. $this->pdf->SetAutoPageBreak(false, $this->margeBottom);
  1173. $this->pdf->setXY($this->defaultLeft, $this->defaultTop);
  1174. $this->style->initStyle();
  1175. $this->style->resetStyle();
  1176. $this->style->value['width'] = $this->pdf->getW() - $this->defaultLeft - $this->defaultRight;
  1177. $this->style->table = array();
  1178. $this->style->save();
  1179. $this->style->analyse('page_header_sub', $param);
  1180. $this->style->setPosition();
  1181. $this->style->FontSet();
  1182. $this->setNewPositionForNewLine();
  1183. return true;
  1184. }
  1185. protected function c_PAGE_HEADER_SUB($param)
  1186. {
  1187. if ($this->forOneLine) return false;
  1188. $this->style->load();
  1189. // retablissement de l'etat
  1190. $this->style->value = $this->subSTATES['s'];
  1191. $this->style->table = $this->subSTATES['t'];
  1192. $this->pageMarges = $this->subSTATES['mp'];
  1193. $this->margeLeft = $this->subSTATES['ml'];
  1194. $this->margeRight = $this->subSTATES['mr'];
  1195. $this->margeTop = $this->subSTATES['mt'];
  1196. $this->margeBottom = $this->subSTATES['mb'];
  1197. $this->pdf->SetMargins($this->margeLeft, $this->margeTop, $this->margeRight);
  1198. $this->pdf->setbMargin($this->margeBottom);
  1199. $this->pdf->SetAutoPageBreak(false, $this->margeBottom);
  1200. $this->pdf->setXY($this->subSTATES['x'], $this->subSTATES['y']);
  1201. $this->style->FontSet();
  1202. $this->maxH = 0;
  1203. return true;
  1204. }
  1205. protected function o_PAGE_FOOTER_SUB($param)
  1206. {
  1207. if ($this->forOneLine) return false;
  1208. $this->subSTATES = array();
  1209. $this->subSTATES['x'] = $this->pdf->getX();
  1210. $this->subSTATES['y'] = $this->pdf->getY();
  1211. $this->subSTATES['s'] = $this->style->value;
  1212. $this->subSTATES['t'] = $this->style->table;
  1213. $this->subSTATES['ml'] = $this->margeLeft;
  1214. $this->subSTATES['mr'] = $this->margeRight;
  1215. $this->subSTATES['mt'] = $this->margeTop;
  1216. $this->subSTATES['mb'] = $this->margeBottom;
  1217. $this->subSTATES['mp'] = $this->pageMarges;
  1218. // nouvel etat pour le footer
  1219. $this->pageMarges = array();
  1220. $this->margeLeft = $this->defaultLeft;
  1221. $this->margeRight = $this->defaultRight;
  1222. $this->margeTop = $this->defaultTop;
  1223. $this->margeBottom = $this->defaultBottom;
  1224. $this->pdf->SetMargins($this->margeLeft, $this->margeTop, $this->margeRight);
  1225. $this->pdf->SetAutoPageBreak(false, $this->margeBottom);
  1226. $this->pdf->setXY($this->defaultLeft, $this->defaultTop);
  1227. $this->style->initStyle();
  1228. $this->style->resetStyle();
  1229. $this->style->value['width'] = $this->pdf->getW() - $this->defaultLeft - $this->defaultRight;
  1230. $this->style->table = array();
  1231. // on en crיי un sous HTML que l'on transforme en PDF
  1232. // pour rיcupיrer la hauteur
  1233. // on extrait tout ce qui est contenu dans le FOOTER
  1234. $sub = null;
  1235. $this->CreateSubHTML($sub);
  1236. $sub->parsing->code = $this->parsing->getLevel($this->parse_pos);
  1237. $sub->MakeHTMLcode();
  1238. $this->pdf->setY($this->pdf->getH() - $sub->maxY - $this->defaultBottom - 0.01);
  1239. $this->destroySubHTML($sub);
  1240. $this->style->save();
  1241. $this->style->analyse('page_footer_sub', $param);
  1242. $this->style->setPosition();
  1243. $this->style->FontSet();
  1244. $this->setNewPositionForNewLine();
  1245. return true;
  1246. }
  1247. protected function c_PAGE_FOOTER_SUB($param)
  1248. {
  1249. if ($this->forOneLine) return false;
  1250. $this->style->load();
  1251. $this->style->value = $this->subSTATES['s'];
  1252. $this->style->table = $this->subSTATES['t'];
  1253. $this->pageMarges = $this->subSTATES['mp'];
  1254. $this->margeLeft = $this->subSTATES['ml'];
  1255. $this->margeRight = $this->subSTATES['mr'];
  1256. $this->margeTop = $this->subSTATES['mt'];
  1257. $this->margeBottom = $this->subSTATES['mb'];
  1258. $this->pdf->SetMargins($this->margeLeft, $this->margeTop, $this->margeRight);
  1259. $this->pdf->SetAutoPageBreak(false, $this->margeBottom);
  1260. $this->pdf->setXY($this->subSTATES['x'], $this->subSTATES['y']);
  1261. $this->style->FontSet();
  1262. $this->maxH = 0;
  1263. return true;
  1264. }
  1265. /**
  1266. * balise : NOBREAK
  1267. * mode : OUVERTURE
  1268. *
  1269. * @param array paramטtres de l'יlיment de parsing
  1270. * @return null
  1271. */
  1272. protected function o_NOBREAK($param)
  1273. {
  1274. if ($this->forOneLine) return false;
  1275. $this->maxH = 0;
  1276. // on en crיי un sous HTML que l'on transforme en PDF
  1277. // pour analyse les dimensions
  1278. // et voir si ca rentre
  1279. $sub = null;
  1280. $this->CreateSubHTML($sub);
  1281. $sub->parsing->code = $this->parsing->getLevel($this->parse_pos);
  1282. $sub->MakeHTMLcode();
  1283. $y = $this->pdf->getY();
  1284. if (
  1285. $sub->maxY < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin()) &&
  1286. $y + $sub->maxY>=($this->pdf->getH() - $this->pdf->getbMargin())
  1287. )
  1288. $this->setNewPage();
  1289. $this->destroySubHTML($sub);
  1290. return true;
  1291. }
  1292. /**
  1293. * balise : NOBREAK
  1294. * mode : FERMETURE
  1295. *
  1296. * @param array paramטtres de l'יlיment de parsing
  1297. * @return null
  1298. */
  1299. protected function c_NOBREAK($param)
  1300. {
  1301. if ($this->forOneLine) return false;
  1302. $this->maxH = 0;
  1303. return true;
  1304. }
  1305. /**
  1306. * balise : DIV
  1307. * mode : OUVERTURE
  1308. *
  1309. * @param array paramטtres de l'יlיment de parsing
  1310. * @return null
  1311. */
  1312. protected function o_DIV($param, $other = 'div')
  1313. {
  1314. if ($this->forOneLine) return false;
  1315. if ($this->DEBUG_actif) $this->DEBUG_add(strtoupper($other), true);
  1316. $this->style->save();
  1317. $this->style->analyse($other, $param);
  1318. $this->style->FontSet();
  1319. // gestion specifique a la balise legend pour l'afficher au bon endroit
  1320. if (in_array($other, array('fieldset', 'legend')))
  1321. {
  1322. if (isset($param['moveTop'])) $this->style->value['margin']['t'] += $param['moveTop'];
  1323. if (isset($param['moveLeft'])) $this->style->value['margin']['l'] += $param['moveLeft'];
  1324. if (isset($param['moveDown'])) $this->style->value['margin']['b'] += $param['moveDown'];
  1325. }
  1326. $align_object = null;
  1327. if ($this->style->value['margin-auto']) $align_object = 'center';
  1328. $marge = array();
  1329. $marge['l'] = $this->style->value['border']['l']['width'] + $this->style->value['padding']['l']+0.03;
  1330. $marge['r'] = $this->style->value['border']['r']['width'] + $this->style->value['padding']['r']+0.03;
  1331. $marge['t'] = $this->style->value['border']['t']['width'] + $this->style->value['padding']['t']+0.03;
  1332. $marge['b'] = $this->style->value['border']['b']['width'] + $this->style->value['padding']['b']+0.03;
  1333. // on extrait tout ce qui est contenu dans la DIV
  1334. $level = $this->parsing->getLevel($this->parse_pos);
  1335. // on en crיי un sous HTML que l'on transforme en PDF
  1336. // pour analyse les dimensions
  1337. $w = 0; $h = 0;
  1338. if (count($level))
  1339. {
  1340. $sub = null;
  1341. $this->CreateSubHTML($sub);
  1342. $sub->parsing->code = $level;
  1343. $sub->MakeHTMLcode();
  1344. $w = $sub->maxX;
  1345. $h = $sub->maxY;
  1346. $this->destroySubHTML($sub);
  1347. }