vendor/spipu/html2pdf/src/Html2Pdf.php line 5043

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