source: trunk/client/inc/hpdf403/html2pdf.class.php@ 394

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