[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 12 if (!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('&', '&', $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('&', '&', 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); 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('&', '&', $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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |