File: html2pdf.class.php - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

0001: <?php
0002: /**
0003:  * HTML2PDF Librairy - main class
0004:  *
0005:  * HTML => PDF convertor
0006:  * distributed under the LGPL License
0007:  *
0008:  * @author  Laurent MINGUET <webmaster@html2pdf.fr>
0009:  * @version 4.03
0010:  */
0011: 
0012: if (!defined('__CLASS_HTML2PDF__')) {
0013: 
0014:     define('__CLASS_HTML2PDF__', '4.03');
0015:     define('HTML2PDF_USED_TCPDF_VERSION', '5.0.002');
0016: 
0017:     require_once(dirname(__FILE__).'/_class/exception.class.php');
0018:     require_once(dirname(__FILE__).'/_class/locale.class.php');
0019:     require_once(dirname(__FILE__).'/_class/myPdf.class.php');
0020:     require_once(dirname(__FILE__).'/_class/parsingHtml.class.php');
0021:     require_once(dirname(__FILE__).'/_class/parsingCss.class.php');
0022: 
0023:     class HTML2PDF
0024:     {
0025:         /**
0026:          * HTML2PDF_myPdf object, extends from TCPDF
0027:          * @var HTML2PDF_myPdf
0028:          */
0029:         public $pdf = null;
0030: 
0031:         /**
0032:          * CSS parsing
0033:          * @var HTML2PDF_parsingCss
0034:          */
0035:         public $parsingCss = null;
0036: 
0037:         /**
0038:          * HTML parsing
0039:          * @var HTML2PDF_parsingHtml
0040:          */
0041:         public $parsingHtml = null;
0042: 
0043:         protected $_langue           = 'fr';        // locale of the messages
0044:         protected $_orientation      = 'P';         // page orientation : Portrait ou Landscape
0045:         protected $_format           = 'A4';        // page format : A4, A3, ...
0046:         protected $_encoding         = '';          // charset encoding
0047:         protected $_unicode          = true;        // means that the input text is unicode (default = true)
0048: 
0049:         protected $_testTdInOnepage  = true;        // test of TD that can not take more than one page
0050:         protected $_testIsImage      = true;        // test if the images exist or not
0051:         protected $_testIsDeprecated = false;       // test the deprecated functions
0052: 
0053:         protected $_parsePos         = 0;           // position in the parsing
0054:         protected $_tempPos          = 0;           // temporary position for complex table
0055:         protected $_page             = 0;           // current page number
0056: 
0057:         protected $_subHtml          = null;        // sub html
0058:         protected $_subPart          = false;       // sub HTML2PDF
0059:         protected $_subHEADER        = array();     // sub action to make the header
0060:         protected $_subFOOTER        = array();     // sub action to make the footer
0061:         protected $_subSTATES        = array();     // array to save some parameters
0062: 
0063:         protected $_isSubPart        = false;       // flag : in a sub html2pdf
0064:         protected $_isInThead        = false;       // flag : in a thead
0065:         protected $_isInTfoot        = false;       // flag : in a tfoot
0066:         protected $_isInOverflow     = false;       // flag : in a overflow
0067:         protected $_isInFooter       = false;       // flag : in a footer
0068:         protected $_isInDraw         = null;        // flag : in a draw (svg)
0069:         protected $_isAfterFloat     = false;       // flag : is just after a float
0070:         protected $_isInForm         = false;       // flag : is in a float. false / action of the form
0071:         protected $_isInLink         = '';          // flag : is in a link. empty / href of the link
0072:         protected $_isInParagraph    = false;       // flag : is in a paragraph
0073:         protected $_isForOneLine     = false;       // flag : in a specific sub html2pdf to have the height of the next line
0074: 
0075:         protected $_maxX             = 0;           // maximum X of the current zone
0076:         protected $_maxY             = 0;           // maximum Y of the current zone
0077:         protected $_maxE             = 0;           // number of elements in the current zone
0078:         protected $_maxH             = 0;           // maximum height of the line in the current zone
0079:         protected $_maxSave          = array();     // save the maximums of the current zone
0080:         protected $_currentH         = 0;           // height of the current line
0081: 
0082:         protected $_defaultLeft      = 0;           // default marges of the page
0083:         protected $_defaultTop       = 0;
0084:         protected $_defaultRight     = 0;
0085:         protected $_defaultBottom    = 0;
0086:         protected $_defaultFont      = null;        // default font to use, is the asked font does not exist
0087: 
0088:         protected $_margeLeft        = 0;           // current marges of the page
0089:         protected $_margeTop         = 0;
0090:         protected $_margeRight       = 0;
0091:         protected $_margeBottom      = 0;
0092:         protected $_marges           = array();     // save the different marges of the current page
0093:         protected $_pageMarges       = array();     // float marges of the current page
0094:         protected $_background       = array();     // background informations
0095: 
0096: 
0097:         protected $_firstPage        = true;        // flag : first page
0098:         protected $_defList          = array();     // table to save the stats of the tags UL and OL
0099: 
0100:         protected $_lstAnchor        = array();     // list of the anchors
0101:         protected $_lstField         = array();     // list of the fields
0102:         protected $_lstSelect        = array();     // list of the options of the current select
0103:         protected $_previousCall     = null;        // last action called
0104: 
0105:         protected $_debugActif       = false;       // flag : mode debug is active
0106:         protected $_debugOkUsage     = false;       // flag : the function memory_get_usage exist
0107:         protected $_debugOkPeak      = false;       // flag : the function memory_get_peak_usage exist
0108:         protected $_debugLevel       = 0;           // level in the debug
0109:         protected $_debugStartTime   = 0;           // debug start time
0110:         protected $_debugLastTime    = 0;           // debug stop time
0111: 
0112:         static protected $_subobj    = null;        // object html2pdf prepared in order to accelerate the creation of sub html2pdf
0113:         static protected $_tables    = array();     // static table to prepare the nested html tables
0114: 
0115:         /**
0116:          * class constructor
0117:          *
0118:          * @access public
0119:          * @param  string   $orientation page orientation, same as TCPDF
0120:          * @param  mixed    $format      The format used for pages, same as TCPDF
0121:          * @param  $tring   $langue      Langue : fr, en, it...
0122:          * @param  boolean  $unicode     TRUE means that the input text is unicode (default = true)
0123:          * @param  String   $encoding    charset encoding; default is UTF-8
0124:          * @param  array    $marges      Default marges (left, top, right, bottom)
0125:          * @return HTML2PDF $this
0126:          */
0127:         public function __construct($orientation = 'P', $format = 'A4', $langue='fr', $unicode=true, $encoding='UTF-8', $marges = array(5, 5, 5, 8))
0128:         {
0129:             // init the page number
0130:             $this->_page         = 0;
0131:             $this->_firstPage    = true;
0132: 
0133:             // save the parameters
0134:             $this->_orientation  = $orientation;
0135:             $this->_format       = $format;
0136:             $this->_langue       = strtolower($langue);
0137:             $this->_unicode      = $unicode;
0138:             $this->_encoding     = $encoding;
0139: 
0140:             // load the Local
0141:             HTML2PDF_locale::load($this->_langue);
0142: 
0143:             // create the  HTML2PDF_myPdf object
0144:             $this->pdf = new HTML2PDF_myPdf($orientation, 'mm', $format, $unicode, $encoding);
0145: 
0146:             // init the CSS parsing object
0147:             $this->parsingCss = new HTML2PDF_parsingCss($this->pdf);
0148:             $this->parsingCss->fontSet();
0149:             $this->_defList = array();
0150: 
0151:             // init some tests
0152:             $this->setTestTdInOnePage(true);
0153:             $this->setTestIsImage(true);
0154:             $this->setTestIsDeprecated(true);
0155: 
0156:             // init the default font
0157:             $this->setDefaultFont(null);
0158: 
0159:             // init the HTML parsing object
0160:             $this->parsingHtml = new HTML2PDF_parsingHtml($this->_encoding);
0161:             $this->_subHtml = null;
0162:             $this->_subPart = false;
0163: 
0164:             // init the marges of the page
0165:             if (!is_array($marges)) $marges = array($marges, $marges, $marges, $marges);
0166:             $this->_setDefaultMargins($marges[0], $marges[1], $marges[2], $marges[3]);
0167:             $this->_setMargins();
0168:             $this->_marges = array();
0169: 
0170:             // init the form's fields
0171:             $this->_lstField = array();
0172: 
0173:             return $this;
0174:         }
0175: 
0176:         /**
0177:          * Destructor
0178:          *
0179:          * @access public
0180:          * @return null
0181:          */
0182:         public function __destruct()
0183:         {
0184: 
0185:         }
0186: 
0187:         /**
0188:          * Clone to create a sub HTML2PDF from HTML2PDF::$_subobj
0189:          *
0190:          * @access public
0191:          */
0192:         public function __clone()
0193:         {
0194:             $this->pdf = clone $this->pdf;
0195:             $this->parsingHtml = clone $this->parsingHtml;
0196:             $this->parsingCss = clone $this->parsingCss;
0197:             $this->parsingCss->setPdfParent($this->pdf);
0198:         }
0199: 
0200:         /**
0201:          * set the debug mode to On
0202:          *
0203:          * @access public
0204:          * @return HTML2PDF $this
0205:          */
0206:         public function setModeDebug()
0207:         {
0208:             $time = microtime(true);
0209: 
0210:             $this->_debugActif     = true;
0211:             $this->_debugOkUsage   = function_exists('memory_get_usage');
0212:             $this->_debugOkPeak    = function_exists('memory_get_peak_usage');
0213:             $this->_debugStartTime = $time;
0214:             $this->_debugLastTime  = $time;
0215: 
0216:             $this->_DEBUG_stepline('step', 'time', 'delta', 'memory', 'peak');
0217:             $this->_DEBUG_add('Init debug');
0218: 
0219:             return $this;
0220:         }
0221: 
0222:         /**
0223:          * Set the test of TD thdat can not take more than one page
0224:          *
0225:          * @access public
0226:          * @param  boolean  $mode
0227:          * @return HTML2PDF $this
0228:          */
0229:         public function setTestTdInOnePage($mode = true)
0230:         {
0231:             $this->_testTdInOnepage = $mode ? true : false;
0232: 
0233:             return $this;
0234:         }
0235: 
0236:         /**
0237:          * Set the test if the images exist or not
0238:          *
0239:          * @access public
0240:          * @param  boolean  $mode
0241:          * @return HTML2PDF $this
0242:          */
0243:         public function setTestIsImage($mode = true)
0244:         {
0245:             $this->_testIsImage = $mode ? true : false;
0246: 
0247:             return $this;
0248:         }
0249: 
0250:         /**
0251:          * Set the test on deprecated functions
0252:          *
0253:          * @access public
0254:          * @param  boolean  $mode
0255:          * @return HTML2PDF $this
0256:          */
0257:         public function setTestIsDeprecated($mode = true)
0258:         {
0259:             $this->_testIsDeprecated = $mode ? true : false;
0260: 
0261:             return $this;
0262:         }
0263: 
0264:         /**
0265:          * Set the default font to use, if no font is specify, or if the asked font does not exist
0266:          *
0267:          * @access public
0268:          * @param  string   $default name of the default font to use. If null : Arial is no font is specify, and error if the asked font does not exist
0269:          * @return HTML2PDF $this
0270:          */
0271:         public function setDefaultFont($default = null)
0272:         {
0273:             $this->_defaultFont = $default;
0274:             $this->parsingCss->setDefaultFont($default);
0275: 
0276:             return $this;
0277:         }
0278: 
0279:         /**
0280:          * add a font, see TCPDF function addFont
0281:          *
0282:          * @access public
0283:          * @param string $family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.
0284:          * @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>
0285:          * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces.
0286:          * @return HTML2PDF $this
0287:          * @see TCPDF::addFont
0288:          */
0289:         public function addFont($family, $style='', $file='')
0290:         {
0291:             $this->pdf->AddFont($family, $style, $file);
0292: 
0293:             return $this;
0294:         }
0295: 
0296:         /**
0297:          * display a automatic index, from the bookmarks
0298:          *
0299:          * @access public
0300:          * @param  string  $titre         index title
0301:          * @param  int     $sizeTitle     font size of the index title, in mm
0302:          * @param  int     $sizeBookmark  font size of the index, in mm
0303:          * @param  boolean $bookmarkTitle add a bookmark for the index, at his beginning
0304:          * @param  boolean $displayPage   display the page numbers
0305:          * @param  int     $onPage        if null : at the end of the document on a new page, else on the $onPage page
0306:          * @param  string  $fontName      font name to use
0307:          * @return null
0308:          */
0309:         public function createIndex($titre = 'Index', $sizeTitle = 20, $sizeBookmark = 15, $bookmarkTitle = true, $displayPage = true, $onPage = null, $fontName = 'helvetica')
0310:         {
0311:             $oldPage = $this->_INDEX_NewPage($onPage);
0312:             $this->pdf->createIndex($this, $titre, $sizeTitle, $sizeBookmark, $bookmarkTitle, $displayPage, $onPage, $fontName);
0313:             if ($oldPage) $this->pdf->setPage($oldPage);
0314:         }
0315: 
0316:         /**
0317:          * clean up the objects
0318:          *
0319:          * @access protected
0320:          */
0321:         protected function _cleanUp()
0322:         {
0323:             HTML2PDF::$_subobj = null;
0324:             HTML2PDF::$_tables = array();
0325:         }
0326: 
0327:         /**
0328:          * Send the document to a given destination: string, local file or browser.
0329:          * Dest can be :
0330:          *  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.
0331:          *  D : send to the browser and force a file download with the name given by name.
0332:          *  F : save to a local server file with the name given by name.
0333:          *  S : return the document as a string. name is ignored.
0334:          *  FI: equivalent to F + I option
0335:          *  FD: equivalent to F + D option
0336:          *  true  => I
0337:          *  false => S
0338:          *
0339:          * @param  string $name The name of the file when saved.
0340:          * @param  string $dest Destination where to send the document.
0341:          * @return string content of the PDF, if $dest=S
0342:          * @see TCPDF::close
0343:          * @access public
0344: 
0345:          */
0346:         public function Output($name = '', $dest = false)
0347:         {
0348:             // close the pdf and clean up
0349:             $this->_cleanUp();
0350: 
0351:             // if on debug mode
0352:             if ($this->_debugActif) {
0353:                 $this->_DEBUG_add('Before output');
0354:                 $this->pdf->Close();
0355:                 exit;
0356:             }
0357: 
0358:             // complete parameters
0359:             if ($dest===false) $dest = 'I';
0360:             if ($dest===true)  $dest = 'S';
0361:             if ($dest==='')    $dest = 'I';
0362:             if ($name=='')     $name='document.pdf';
0363: 
0364:             // clean up the destination
0365:             $dest = strtoupper($dest);
0366:             if (!in_array($dest, array('I', 'D', 'F', 'S', 'FI','FD'))) $dest = 'I';
0367: 
0368:             // the name must be a PDF name
0369:             if (strtolower(substr($name, -4))!='.pdf') {
0370:                 throw new HTML2PDF_exception(0, 'The output document name "'.$name.'" is not a PDF name');
0371:             }
0372: 
0373:             // call the output of TCPDF
0374:             return $this->pdf->Output($name, $dest);
0375:         }
0376: 
0377:         /**
0378:          * convert HTML to PDF
0379:          *
0380:          * @access public
0381:          * @param  string   $html
0382:          * @param  boolean  $debugVue  enable the HTML debug vue
0383:          * @return null
0384:          */
0385:         public function writeHTML($html, $debugVue = false)
0386:         {
0387:             // if it is a real html page, we have to convert it
0388:             if (preg_match('/<body/isU', $html))
0389:                 $html = $this->getHtmlFromPage($html);
0390: 
0391:             $html = str_replace('[[date_y]]', date('Y'), $html);
0392:             $html = str_replace('[[date_m]]', date('m'), $html);
0393:             $html = str_replace('[[date_d]]', date('d'), $html);
0394: 
0395:             $html = str_replace('[[date_h]]', date('H'), $html);
0396:             $html = str_replace('[[date_i]]', date('i'), $html);
0397:             $html = str_replace('[[date_s]]', date('s'), $html);
0398: 
0399:             // If we are in HTML debug vue : display the HTML
0400:             if ($debugVue) {
0401:                 return $this->_vueHTML($html);
0402:             }
0403: 
0404:             // convert HTMl to PDF
0405:             $this->parsingCss->readStyle($html);
0406:             $this->parsingHtml->setHTML($html);
0407:             $this->parsingHtml->parse();
0408:             $this->_makeHTMLcode();
0409:         }
0410: 
0411:         /**
0412:          * convert the HTML of a real page, to a code adapted to HTML2PDF
0413:          *
0414:          * @access public
0415:          * @param  string HTML of a real page
0416:          * @return string HTML adapted to HTML2PDF
0417:          */
0418:         public function getHtmlFromPage($html)
0419:         {
0420:             $html = str_replace('<BODY', '<body', $html);
0421:             $html = str_replace('</BODY', '</body', $html);
0422: 
0423:             // extract the content
0424:             $res = explode('<body', $html);
0425:             if (count($res)<2) return $html;
0426:             $content = '<page'.$res[1];
0427:             $content = explode('</body', $content);
0428:             $content = $content[0].'</page>';
0429: 
0430:             // extract the link tags
0431:             preg_match_all('/<link([^>]*)>/isU', $html, $match);
0432:             foreach ($match[0] as $src)
0433:                 $content = $src.'</link>'.$content;
0434: 
0435:             // extract the css style tags
0436:             preg_match_all('/<style[^>]*>(.*)<\/style[^>]*>/isU', $html, $match);
0437:             foreach ($match[0] as $src)
0438:                 $content = $src.$content;
0439: 
0440:             return $content;
0441:         }
0442: 
0443:         /**
0444:          * init a sub HTML2PDF. does not use it directly. Only the method createSubHTML must use it
0445:          *
0446:          * @access public
0447:          * @param  string  $format
0448:          * @param  string  $orientation
0449:          * @param  array   $marge
0450:          * @param  integer $page
0451:          * @param  array   $defLIST
0452:          * @param  integer $myLastPageGroup
0453:          * @param  integer $myLastPageGroupNb
0454:          */
0455:         public function initSubHtml($format, $orientation, $marge, $page, $defLIST, $myLastPageGroup, $myLastPageGroupNb)
0456:         {
0457:             $this->_isSubPart = true;
0458: 
0459:             $this->parsingCss->setOnlyLeft();
0460: 
0461:             $this->_setNewPage($format, $orientation, null, null, ($myLastPageGroup!==null));
0462: 
0463:             $this->_saveMargin(0, 0, $marge);
0464:             $this->_defList = $defLIST;
0465: 
0466:             $this->_page = $page;
0467:             $this->pdf->setMyLastPageGroup($myLastPageGroup);
0468:             $this->pdf->setMyLastPageGroupNb($myLastPageGroupNb);
0469:             $this->pdf->setXY(0, 0);
0470:             $this->parsingCss->fontSet();
0471:         }
0472: 
0473:         /**
0474:          * display the content in HTML moden for debug
0475:          *
0476:          * @access protected
0477:          * @param  string $contenu
0478:          */
0479:         protected function _vueHTML($content)
0480:         {
0481:             $content = preg_replace('/<page_header([^>]*)>/isU', '<hr>'.HTML2PDF_locale::get('vue01').' : $1<hr><div$1>', $content);
0482:             $content = preg_replace('/<page_footer([^>]*)>/isU', '<hr>'.HTML2PDF_locale::get('vue02').' : $1<hr><div$1>', $content);
0483:             $content = preg_replace('/<page([^>]*)>/isU', '<hr>'.HTML2PDF_locale::get('vue03').' : $1<hr><div$1>', $content);
0484:             $content = preg_replace('/<\/page([^>]*)>/isU', '</div><hr>', $content);
0485:             $content = preg_replace('/<bookmark([^>]*)>/isU', '<hr>bookmark : $1<hr>', $content);
0486:             $content = preg_replace('/<\/bookmark([^>]*)>/isU', '', $content);
0487:             $content = preg_replace('/<barcode([^>]*)>/isU', '<hr>barcode : $1<hr>', $content);
0488:             $content = preg_replace('/<\/barcode([^>]*)>/isU', '', $content);
0489:             $content = preg_replace('/<qrcode([^>]*)>/isU', '<hr>qrcode : $1<hr>', $content);
0490:             $content = preg_replace('/<\/qrcode([^>]*)>/isU', '', $content);
0491: 
0492:             echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
0493: <html>
0494:     <head>
0495:         <title>'.HTML2PDF_locale::get('vue04').' HTML</title>
0496:         <meta http-equiv="Content-Type" content="text/html; charset='.$this->_encoding.'" >
0497:     </head>
0498:     <body style="padding: 10px; font-size: 10pt;font-family:    Verdana;">
0499: '.$content.'
0500:     </body>
0501: </html>';
0502:             exit;
0503:         }
0504: 
0505:         /**
0506:          * set the default margins of the page
0507:          *
0508:          * @access protected
0509:          * @param  int $left   (mm, left margin)
0510:          * @param  int $top    (mm, top margin)
0511:          * @param  int $right  (mm, right margin, if null => left=right)
0512:          * @param  int $bottom (mm, bottom margin, if null => bottom=8mm)
0513:          */
0514:         protected function _setDefaultMargins($left, $top, $right = null, $bottom = null)
0515:         {
0516:             if ($right===null)  $right = $left;
0517:             if ($bottom===null) $bottom = 8;
0518: 
0519:             $this->_defaultLeft   = $this->parsingCss->ConvertToMM($left.'mm');
0520:             $this->_defaultTop    = $this->parsingCss->ConvertToMM($top.'mm');
0521:             $this->_defaultRight  = $this->parsingCss->ConvertToMM($right.'mm');
0522:             $this->_defaultBottom = $this->parsingCss->ConvertToMM($bottom.'mm');
0523:         }
0524: 
0525:         /**
0526:          * create a new page
0527:          *
0528:          * @access protected
0529:          * @param  mixed   $format
0530:          * @param  string  $orientation
0531:          * @param  array   $background background information
0532:          * @param  integer $curr real position in the html parseur (if break line in the write of a text)
0533:          * @param  boolean $resetPageNumber
0534:          */
0535:         protected function _setNewPage($format = null, $orientation = '', $background = null, $curr = null, $resetPageNumber=false)
0536:         {
0537:             $this->_firstPage = false;
0538: 
0539:             $this->_format = $format ? $format : $this->_format;
0540:             $this->_orientation = $orientation ? $orientation : $this->_orientation;
0541:             $this->_background = $background!==null ? $background : $this->_background;
0542:             $this->_maxY = 0;
0543:             $this->_maxX = 0;
0544:             $this->_maxH = 0;
0545:             $this->_maxE = 0;
0546: 
0547:             $this->pdf->SetMargins($this->_defaultLeft, $this->_defaultTop, $this->_defaultRight);
0548: 
0549:             if ($resetPageNumber) {
0550:                 $this->pdf->startPageGroup();
0551:             }
0552: 
0553:             $this->pdf->AddPage($this->_orientation, $this->_format);
0554: 
0555:             if ($resetPageNumber) {
0556:                 $this->pdf->myStartPageGroup();
0557:             }
0558: 
0559:             $this->_page++;
0560: 
0561:             if (!$this->_subPart && !$this->_isSubPart) {
0562:                 if (is_array($this->_background)) {
0563:                     if (isset($this->_background['color']) && $this->_background['color']) {
0564:                         $this->pdf->setFillColorArray($this->_background['color']);
0565:                         $this->pdf->Rect(0, 0, $this->pdf->getW(), $this->pdf->getH(), 'F');
0566:                     }
0567: 
0568:                     if (isset($this->_background['img']) && $this->_background['img'])
0569:                         $this->pdf->Image($this->_background['img'], $this->_background['posX'], $this->_background['posY'], $this->_background['width']);
0570:                 }
0571: 
0572:                 $this->_setPageHeader();
0573:                 $this->_setPageFooter();
0574:             }
0575: 
0576:             $this->_setMargins();
0577:             $this->pdf->setY($this->_margeTop);
0578: 
0579:             $this->_setNewPositionForNewLine($curr);
0580:             $this->_maxH = 0;
0581:         }
0582: 
0583:         /**
0584:          * set the real margin, using the default margins and the page margins
0585:          *
0586:          * @access protected
0587:          */
0588:         protected function _setMargins()
0589:         {
0590:             // prepare the margins
0591:             $this->_margeLeft   = $this->_defaultLeft   + (isset($this->_background['left'])   ? $this->_background['left']   : 0);
0592:             $this->_margeRight  = $this->_defaultRight  + (isset($this->_background['right'])  ? $this->_background['right']  : 0);
0593:             $this->_margeTop    = $this->_defaultTop    + (isset($this->_background['top'])    ? $this->_background['top']    : 0);
0594:             $this->_margeBottom = $this->_defaultBottom + (isset($this->_background['bottom']) ? $this->_background['bottom'] : 0);
0595: 
0596:             // set the PDF margins
0597:             $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
0598:             $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
0599: 
0600:             // set the float Margins
0601:             $this->_pageMarges = array();
0602:             if ($this->_isInParagraph!==false) {
0603:                 $this->_pageMarges[floor($this->_margeTop*100)] = array($this->_isInParagraph[0], $this->pdf->getW()-$this->_isInParagraph[1]);
0604:             } else {
0605:                 $this->_pageMarges[floor($this->_margeTop*100)] = array($this->_margeLeft, $this->pdf->getW()-$this->_margeRight);
0606:             }
0607:         }
0608: 
0609:         /**
0610:          * add a debug step
0611:          *
0612:          * @access protected
0613:          * @param  string  $name step name
0614:          * @param  boolean $level (true=up, false=down, null=nothing to do)
0615:          * @return $this
0616:          */
0617:         protected function _DEBUG_add($name, $level=null)
0618:         {
0619:             // if true : UP
0620:             if ($level===true) $this->_debugLevel++;
0621: 
0622:             $name   = str_repeat('  ', $this->_debugLevel). $name.($level===true ? ' Begin' : ($level===false ? ' End' : ''));
0623:             $time  = microtime(true);
0624:             $usage = ($this->_debugOkUsage ? memory_get_usage() : 0);
0625:             $peak  = ($this->_debugOkPeak ? memory_get_peak_usage() : 0);
0626: 
0627:             $this->_DEBUG_stepline(
0628:                 $name,
0629:                 number_format(($time - $this->_debugStartTime)*1000, 1, '.', ' ').' ms',
0630:                 number_format(($time - $this->_debugLastTime)*1000, 1, '.', ' ').' ms',
0631:                 number_format($usage/1024, 1, '.', ' ').' Ko',
0632:                 number_format($peak/1024, 1, '.', ' ').' Ko'
0633:             );
0634: 
0635:             $this->_debugLastTime = $time;
0636: 
0637:             // it false : DOWN
0638:             if ($level===false) $this->_debugLevel--;
0639: 
0640:             return $this;
0641:         }
0642: 
0643:         /**
0644:          * display a debug line
0645:          *
0646:          *
0647:          * @access protected
0648:          * @param  string $name
0649:          * @param  string $timeTotal
0650:          * @param  string $timeStep
0651:          * @param  string $memoryUsage
0652:          * @param  string $memoryPeak
0653:          */
0654:         protected function _DEBUG_stepline($name, $timeTotal, $timeStep, $memoryUsage, $memoryPeak)
0655:         {
0656:             $txt = str_pad($name, 30, ' ', STR_PAD_RIGHT).
0657:                     str_pad($timeTotal, 12, ' ', STR_PAD_LEFT).
0658:                     str_pad($timeStep, 12, ' ', STR_PAD_LEFT).
0659:                     str_pad($memoryUsage, 15, ' ', STR_PAD_LEFT).
0660:                     str_pad($memoryPeak, 15, ' ', STR_PAD_LEFT);
0661: 
0662:             echo '<pre style="padding:0; margin:0">'.$txt.'</pre>';
0663:         }
0664: 
0665:         /**
0666:          * get the Min and Max X, for Y (use the float margins)
0667:          *
0668:          * @access protected
0669:          * @param  float $y
0670:          * @return array(float, float)
0671:          */
0672:         protected function _getMargins($y)
0673:         {
0674:             $y = floor($y*100);
0675:             $x = array($this->pdf->getlMargin(), $this->pdf->getW()-$this->pdf->getrMargin());
0676: 
0677:             foreach ($this->_pageMarges as $mY => $mX)
0678:                 if ($mY<=$y) $x = $mX;
0679: 
0680:             return $x;
0681:         }
0682: 
0683:         /**
0684:          * Add margins, for a float
0685:          *
0686:          * @access protected
0687:          * @param  string $float (left / right)
0688:          * @param  float  $xLeft
0689:          * @param  float  $yTop
0690:          * @param  float  $xRight
0691:          * @param  float  $yBottom
0692:          */
0693:         protected function _addMargins($float, $xLeft, $yTop, $xRight, $yBottom)
0694:         {
0695:             // get the current float margins, for top and bottom
0696:             $oldTop    = $this->_getMargins($yTop);
0697:             $oldBottom = $this->_getMargins($yBottom);
0698: 
0699:             // update the top float margin
0700:             if ($float=='left'  && $oldTop[0]<$xRight) $oldTop[0] = $xRight;
0701:             if ($float=='right' && $oldTop[1]>$xLeft)  $oldTop[1] = $xLeft;
0702: 
0703:             $yTop = floor($yTop*100);
0704:             $yBottom = floor($yBottom*100);
0705: 
0706:             // erase all the float margins that are smaller than the new one
0707:             foreach ($this->_pageMarges as $mY => $mX) {
0708:                 if ($mY<$yTop) continue;
0709:                 if ($mY>$yBottom) break;
0710:                 if ($float=='left' && $this->_pageMarges[$mY][0]<$xRight)  unset($this->_pageMarges[$mY]);
0711:                 if ($float=='right' && $this->_pageMarges[$mY][1]>$xLeft) unset($this->_pageMarges[$mY]);
0712:             }
0713: 
0714:             // save the new Top and Bottom margins
0715:             $this->_pageMarges[$yTop] = $oldTop;
0716:             $this->_pageMarges[$yBottom] = $oldBottom;
0717: 
0718:             // sort the margins
0719:             ksort($this->_pageMarges);
0720: 
0721:             // we are just after float
0722:             $this->_isAfterFloat = true;
0723:         }
0724: 
0725:         /**
0726:          * Save old margins (push), and set new ones
0727:          *
0728:          * @access protected
0729:          * @param  float  $ml left margin
0730:          * @param  float  $mt top margin
0731:          * @param  float  $mr right margin
0732:          */
0733:         protected function _saveMargin($ml, $mt, $mr)
0734:         {
0735:             // save old margins
0736:             $this->_marges[] = array('l' => $this->pdf->getlMargin(), 't' => $this->pdf->gettMargin(), 'r' => $this->pdf->getrMargin(), 'page' => $this->_pageMarges);
0737: 
0738:             // set new ones
0739:             $this->pdf->SetMargins($ml, $mt, $mr);
0740: 
0741:             // prepare for float margins
0742:             $this->_pageMarges = array();
0743:             $this->_pageMarges[floor($mt*100)] = array($ml, $this->pdf->getW()-$mr);
0744:         }
0745: 
0746:         /**
0747:          * load the last saved margins (pop)
0748:          *
0749:          * @access protected
0750:          */
0751:         protected function _loadMargin()
0752:         {
0753:             $old = array_pop($this->_marges);
0754:             if ($old) {
0755:                 $ml = $old['l'];
0756:                 $mt = $old['t'];
0757:                 $mr = $old['r'];
0758:                 $mP = $old['page'];
0759:             } else {
0760:                 $ml = $this->_margeLeft;
0761:                 $mt = 0;
0762:                 $mr = $this->_margeRight;
0763:                 $mP = array($mt => array($ml, $this->pdf->getW()-$mr));
0764:             }
0765: 
0766:             $this->pdf->SetMargins($ml, $mt, $mr);
0767:             $this->_pageMarges = $mP;
0768:         }
0769: 
0770:         /**
0771:          * save the current maxs (push)
0772:          *
0773:          * @access protected
0774:          */
0775:         protected function _saveMax()
0776:         {
0777:             $this->_maxSave[] = array($this->_maxX, $this->_maxY, $this->_maxH, $this->_maxE);
0778:         }
0779: 
0780:         /**
0781:          * load the last saved current maxs (pop)
0782:          *
0783:          * @access protected
0784:          */
0785:         protected function _loadMax()
0786:         {
0787:             $old = array_pop($this->_maxSave);
0788: 
0789:             if ($old) {
0790:                 $this->_maxX = $old[0];
0791:                 $this->_maxY = $old[1];
0792:                 $this->_maxH = $old[2];
0793:                 $this->_maxE = $old[3];
0794:             } else {
0795:                 $this->_maxX = 0;
0796:                 $this->_maxY = 0;
0797:                 $this->_maxH = 0;
0798:                 $this->_maxE = 0;
0799:             }
0800:         }
0801: 
0802:         /**
0803:          * draw the PDF header with the HTML in page_header
0804:          *
0805:          * @access protected
0806:          */
0807:         protected function _setPageHeader()
0808:         {
0809:             if (!count($this->_subHEADER)) return false;
0810: 
0811:             $oldParsePos = $this->_parsePos;
0812:             $oldParseCode = $this->parsingHtml->code;
0813: 
0814:             $this->_parsePos = 0;
0815:             $this->parsingHtml->code = $this->_subHEADER;
0816:             $this->_makeHTMLcode();
0817: 
0818:             $this->_parsePos = $oldParsePos;
0819:             $this->parsingHtml->code = $oldParseCode;
0820:         }
0821: 
0822:         /**
0823:          * draw the PDF footer with the HTML in page_footer
0824:          *
0825:          * @access protected
0826:          */
0827:         protected function _setPageFooter()
0828:         {
0829:             if (!count($this->_subFOOTER)) return false;
0830: 
0831:             $oldParsePos = $this->_parsePos;
0832:             $oldParseCode = $this->parsingHtml->code;
0833: 
0834:             $this->_parsePos = 0;
0835:             $this->parsingHtml->code = $this->_subFOOTER;
0836:             $this->_isInFooter = true;
0837:             $this->_makeHTMLcode();
0838:             $this->_isInFooter = false;
0839: 
0840:             $this->_parsePos = $oldParsePos;
0841:             $this->parsingHtml->code = $oldParseCode;
0842:         }
0843: 
0844:         /**
0845:          * new line, with a specific height
0846:          *
0847:          * @access protected
0848:          * @param float   $h
0849:          * @param integer $curr real current position in the text, if new line in the write of a text
0850:          */
0851:         protected function _setNewLine($h, $curr = null)
0852:         {
0853:             $this->pdf->Ln($h);
0854:             $this->_setNewPositionForNewLine($curr);
0855:         }
0856: 
0857:         /**
0858:          * calculate the start position of the next line,  depending on the text-align
0859:          *
0860:          * @access protected
0861:          * @param  integer $curr real current position in the text, if new line in the write of a text
0862:          */
0863:         protected function _setNewPositionForNewLine($curr = null)
0864:         {
0865:             // get the margins for the current line
0866:             list($lx, $rx) = $this->_getMargins($this->pdf->getY());
0867:             $this->pdf->setX($lx);
0868:             $wMax = $rx-$lx;
0869:             $this->_currentH = 0;
0870: 
0871:             // if subPart => return because align left
0872:             if ($this->_subPart || $this->_isSubPart || $this->_isForOneLine) {
0873:                 $this->pdf->setWordSpacing(0);
0874:                 return null;
0875:             }
0876: 
0877:             // create the sub object
0878:             $sub = null;
0879:             $this->_createSubHTML($sub);
0880:             $sub->_saveMargin(0, 0, $sub->pdf->getW()-$wMax);
0881:             $sub->_isForOneLine = true;
0882:             $sub->_parsePos = $this->_parsePos;
0883:             $sub->parsingHtml->code = $this->parsingHtml->code;
0884: 
0885:             // if $curr => adapt the current position of the parsing
0886:             if ($curr!==null && $sub->parsingHtml->code[$this->_parsePos]['name']=='write') {
0887:                 $txt = $sub->parsingHtml->code[$this->_parsePos]['param']['txt'];
0888:                 $txt = str_replace('[[page_cu]]', $sub->pdf->getMyNumPage($this->_page), $txt);
0889:                 $sub->parsingHtml->code[$this->_parsePos]['param']['txt'] = substr($txt, $curr+1);
0890:             } else
0891:                 $sub->_parsePos++;
0892: 
0893:             // for each element of the parsing => load the action
0894:             $res = null;
0895:             for ($sub->_parsePos; $sub->_parsePos<count($sub->parsingHtml->code); $sub->_parsePos++) {
0896:                 $action = $sub->parsingHtml->code[$sub->_parsePos];
0897:                 $res = $sub->_executeAction($action);
0898:                 if (!$res) break;
0899:             }
0900: 
0901:             $w = $sub->_maxX; // max width
0902:             $h = $sub->_maxH; // max height
0903:             $e = ($res===null ? $sub->_maxE : 0); // maxnumber of elemets on the line
0904: 
0905:             // destroy the sub HTML
0906:             $this->_destroySubHTML($sub);
0907: 
0908:             // adapt the start of the line, depending on the text-align
0909:             if ($this->parsingCss->value['text-align']=='center')
0910:                 $this->pdf->setX(($rx+$this->pdf->getX()-$w)*0.5-0.01);
0911:             else if ($this->parsingCss->value['text-align']=='right')
0912:                 $this->pdf->setX($rx-$w-0.01);
0913:             else
0914:                 $this->pdf->setX($lx);
0915: 
0916:             // set the height of the line
0917:             $this->_currentH = $h;
0918: 
0919:             // if justify => set the word spacing
0920:             if ($this->parsingCss->value['text-align']=='justify' && $e>1) {
0921:                 $this->pdf->setWordSpacing(($wMax-$w)/($e-1));
0922:             } else {
0923:                 $this->pdf->setWordSpacing(0);
0924:             }
0925:         }
0926: 
0927:         /**
0928:          * prepare HTML2PDF::$_subobj (used for create the sub HTML2PDF objects
0929:          *
0930:          * @access protected
0931:          */
0932:         protected function _prepareSubObj()
0933:         {
0934:             $pdf = null;
0935: 
0936:             // create the sub object
0937:             HTML2PDF::$_subobj = new HTML2PDF(
0938:                                         $this->_orientation,
0939:                                         $this->_format,
0940:                                         $this->_langue,
0941:                                         $this->_unicode,
0942:                                         $this->_encoding,
0943:                                         array($this->_defaultLeft,$this->_defaultTop,$this->_defaultRight,$this->_defaultBottom)
0944:                                     );
0945: 
0946:             // init
0947:             HTML2PDF::$_subobj->setTestTdInOnePage($this->_testTdInOnepage);
0948:             HTML2PDF::$_subobj->setTestIsImage($this->_testIsImage);
0949:             HTML2PDF::$_subobj->setTestIsDeprecated($this->_testIsDeprecated);
0950:             HTML2PDF::$_subobj->setDefaultFont($this->_defaultFont);
0951:             HTML2PDF::$_subobj->parsingCss->css            = &$this->parsingCss->css;
0952:             HTML2PDF::$_subobj->parsingCss->cssKeys        = &$this->parsingCss->cssKeys;
0953: 
0954:             // clone font from the original PDF
0955:             HTML2PDF::$_subobj->pdf->cloneFontFrom($this->pdf);
0956: 
0957:             // remove the link to the parent
0958:             HTML2PDF::$_subobj->parsingCss->setPdfParent($pdf);
0959:         }
0960: 
0961:         /**
0962:          * create a sub HTML2PDF, to calculate the multi-tables
0963:          *
0964:          * @access protected
0965:          * @param  &HTML2PDF $subHtml sub HTML2PDF to create
0966:          * @param  integer   $cellmargin if in a TD : cellmargin of this td
0967:          */
0968:         protected function _createSubHTML(&$subHtml, $cellmargin=0)
0969:         {
0970:             // prepare the subObject, if never prepare before
0971:             if (HTML2PDF::$_subobj===null) {
0972:                 $this->_prepareSubObj();
0973:             }
0974: 
0975:             // calculate the width to use
0976:             if ($this->parsingCss->value['width']) {
0977:                 $marge = $cellmargin*2;
0978:                 $marge+= $this->parsingCss->value['padding']['l'] + $this->parsingCss->value['padding']['r'];
0979:                 $marge+= $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['border']['r']['width'];
0980:                 $marge = $this->pdf->getW() - $this->parsingCss->value['width'] + $marge;
0981:             } else {
0982:                 $marge = $this->_margeLeft+$this->_margeRight;
0983:             }
0984: 
0985:             // BUGFIX : we have to call the method, because of a bug in php 5.1.6
0986:             HTML2PDF::$_subobj->pdf->getPage();
0987: 
0988:             // clone the sub oject
0989:             $subHtml = clone HTML2PDF::$_subobj;
0990:             $subHtml->parsingCss->table = $this->parsingCss->table;
0991:             $subHtml->parsingCss->value = $this->parsingCss->value;
0992:             $subHtml->initSubHtml(
0993:                 $this->_format,
0994:                 $this->_orientation,
0995:                 $marge,
0996:                 $this->_page,
0997:                 $this->_defList,
0998:                 $this->pdf->getMyLastPageGroup(),
0999:                 $this->pdf->getMyLastPageGroupNb()
1000:             );
1001:         }
1002: 
1003:         /**
1004:          * destroy a subHTML2PDF
1005:          *
1006:          * @access protected
1007:          */
1008:         protected function _destroySubHTML(&$subHtml)
1009:         {
1010:             unset($subHtml);
1011:             $subHtml = null;
1012:         }
1013: 
1014:         /**
1015:          * Convert a arabic number in roman number
1016:          *
1017:          * @access protected
1018:          * @param  integer $nbArabic
1019:          * @return string  $nbRoman
1020:          */
1021:         protected function _listeArab2Rom($nbArabic)
1022:         {
1023:             $nbBaseTen    = array('I','X','C','M');
1024:             $nbBaseFive    = array('V','L','D');
1025:             $nbRoman    = '';
1026: 
1027:             if ($nbArabic<1)    return $nbArabic;
1028:             if ($nbArabic>3999) return $nbArabic;
1029: 
1030:             for ($i=3; $i>=0 ; $i--) {
1031:                 $chiffre=floor($nbArabic/pow(10, $i));
1032:                 if ($chiffre>=1) {
1033:                     $nbArabic=$nbArabic-$chiffre*pow(10, $i);
1034:                     if ($chiffre<=3) {
1035:                         for ($j=$chiffre; $j>=1; $j--) {
1036:                             $nbRoman=$nbRoman.$nbBaseTen[$i];
1037:                         }
1038:                     } else if ($chiffre==9) {
1039:                         $nbRoman=$nbRoman.$nbBaseTen[$i].$nbBaseTen[$i+1];
1040:                     } else if ($chiffre==4) {
1041:                     $nbRoman=$nbRoman.$nbBaseTen[$i].$nbBaseFive[$i];
1042:                     } else {
1043:                         $nbRoman=$nbRoman.$nbBaseFive[$i];
1044:                         for ($j=$chiffre-5; $j>=1; $j--) {
1045:                             $nbRoman=$nbRoman.$nbBaseTen[$i];
1046:                         }
1047:                     }
1048:                 }
1049:             }
1050:             return $nbRoman;
1051:         }
1052: 
1053:         /**
1054:          * add a LI to the current level
1055:          *
1056:          * @access protected
1057:          */
1058:         protected function _listeAddLi()
1059:         {
1060:             $this->_defList[count($this->_defList)-1]['nb']++;
1061:         }
1062: 
1063:         /**
1064:          * get the width to use for the column of the list
1065:          *
1066:          * @access protected
1067:          * @return string $width
1068:          */
1069:         protected function _listeGetWidth()
1070:         {
1071:             return '7mm';
1072:         }
1073: 
1074:         /**
1075:          * get the padding to use for the column of the list
1076:          *
1077:          * @access protected
1078:          * @return string $padding
1079:          */
1080:         protected function _listeGetPadding()
1081:         {
1082:             return '1mm';
1083:         }
1084: 
1085:         /**
1086:          * get the information of the li on the current level
1087:          *
1088:          * @access protected
1089:          * @return array(fontName, small size, string)
1090:          */
1091:         protected function _listeGetLi()
1092:         {
1093:             $im = $this->_defList[count($this->_defList)-1]['img'];
1094:             $st = $this->_defList[count($this->_defList)-1]['style'];
1095:             $nb = $this->_defList[count($this->_defList)-1]['nb'];
1096:             $up = (substr($st, 0, 6)=='upper-');
1097: 
1098:             if ($im) return array(false, false, $im);
1099: 
1100:             switch($st)
1101:             {
1102:                 case 'none':
1103:                     return array('helvetica', true, ' ');
1104: 
1105:                 case 'upper-alpha':
1106:                 case 'lower-alpha':
1107:                     $str = '';
1108:                     while ($nb>26) {
1109:                         $str = chr(96+$nb%26).$str;
1110:                         $nb = floor($nb/26);
1111:                     }
1112:                     $str = chr(96+$nb).$str;
1113: 
1114:                     return array('helvetica', false, ($up ? strtoupper($str) : $str).'.');
1115: 
1116:                 case 'upper-roman':
1117:                 case 'lower-roman':
1118:                     $str = $this->_listeArab2Rom($nb);
1119: 
1120:                     return array('helvetica', false, ($up ? strtoupper($str) : $str).'.');
1121: 
1122:                 case 'decimal':
1123:                     return array('helvetica', false, $nb.'.');
1124: 
1125:                 case 'square':
1126:                     return array('zapfdingbats', true, chr(110));
1127: 
1128:                 case 'circle':
1129:                     return array('zapfdingbats', true, chr(109));
1130: 
1131:                 case 'disc':
1132:                 default:
1133:                     return array('zapfdingbats', true, chr(108));
1134:             }
1135:         }
1136: 
1137:         /**
1138:          * add a level to the list
1139:          *
1140:          * @access protected
1141:          * @param  string $type  : ul, ol
1142:          * @param  string $style : lower-alpha, ...
1143:          * @param  string $img
1144:          */
1145:         protected function _listeAddLevel($type = 'ul', $style = '', $img = null)
1146:         {
1147:             // get the url of the image, if we want to use a image
1148:             if ($img) {
1149:                 if (preg_match('/^url\(([^)]+)\)$/isU', trim($img), $match)) {
1150:                     $img = $match[1];
1151:                 } else {
1152:                     $img = null;
1153:                 }
1154:             } else {
1155:                 $img = null;
1156:             }
1157: 
1158:             // prepare the datas
1159:             if (!in_array($type, array('ul', 'ol'))) $type = 'ul';
1160:             if (!in_array($style, array('lower-alpha', 'upper-alpha', 'upper-roman', 'lower-roman', 'decimal', 'square', 'circle', 'disc', 'none'))) $style = '';
1161: 
1162:             if (!$style) {
1163:                 if ($type=='ul')    $style = 'disc';
1164:                 else                $style = 'decimal';
1165:             }
1166: 
1167:             // add the new level
1168:             $this->_defList[count($this->_defList)] = array('style' => $style, 'nb' => 0, 'img' => $img);
1169:         }
1170: 
1171:         /**
1172:          * remove a level to the list
1173:          *
1174:          * @access protected
1175:          */
1176:         protected function _listeDelLevel()
1177:         {
1178:             if (count($this->_defList)) {
1179:                 unset($this->_defList[count($this->_defList)-1]);
1180:                 $this->_defList = array_values($this->_defList);
1181:             }
1182:         }
1183: 
1184:         /**
1185:          * execute the actions to convert the html
1186:          *
1187:          * @access protected
1188:          */
1189:         protected function _makeHTMLcode()
1190:         {
1191:             // foreach elements of the parsing
1192:             for ($this->_parsePos=0; $this->_parsePos<count($this->parsingHtml->code); $this->_parsePos++) {
1193: 
1194:                 // get the action to do
1195:                 $action = $this->parsingHtml->code[$this->_parsePos];
1196: 
1197:                 // if it is a opening of table / ul / ol
1198:                 if (in_array($action['name'], array('table', 'ul', 'ol')) && !$action['close']) {
1199: 
1200:                     //  we will work as a sub HTML to calculate the size of the element
1201:                     $this->_subPart = true;
1202: 
1203:                     // get the name of the opening tag
1204:                     $tagOpen = $action['name'];
1205: 
1206:                     // save the actual pos on the parsing
1207:                     $this->_tempPos = $this->_parsePos;
1208: 
1209:                     // foreach elements, while we are in the opened tag
1210:                     while (isset($this->parsingHtml->code[$this->_tempPos]) && !($this->parsingHtml->code[$this->_tempPos]['name']==$tagOpen && $this->parsingHtml->code[$this->_tempPos]['close'])) {
1211:                         // make the action
1212:                         $this->_executeAction($this->parsingHtml->code[$this->_tempPos]);
1213:                         $this->_tempPos++;
1214:                     }
1215: 
1216:                     // execute the closure of the tag
1217:                     if (isset($this->parsingHtml->code[$this->_tempPos])) {
1218:                         $this->_executeAction($this->parsingHtml->code[$this->_tempPos]);
1219:                     }
1220: 
1221:                     // end of the sub part
1222:                     $this->_subPart = false;
1223:                 }
1224: 
1225:                 // execute the action
1226:                 $this->_executeAction($action);
1227:             }
1228:         }
1229: 
1230:         /**
1231:          * execute the action from the parsing
1232:          *
1233:          * @access protected
1234:          * @param  array $action
1235:          */
1236:         protected function _executeAction($action)
1237:         {
1238:             // name of the action
1239:             $fnc = ($action['close'] ? '_tag_close_' : '_tag_open_').strtoupper($action['name']);
1240: 
1241:             // parameters of the action
1242:             $param = $action['param'];
1243: 
1244:             // if it the first action of the first page, and if it is not a open tag of PAGE => create the new page
1245:             if ($fnc!='_tag_open_PAGE' && $this->_firstPage) {
1246:                 $this->_setNewPage();
1247:             }
1248: 
1249:             // the action must exist
1250:             if (!is_callable(array(&$this, $fnc))) {
1251:                 throw new HTML2PDF_exception(1, strtoupper($action['name']), $this->parsingHtml->getHtmlErrorCode($action['html_pos']));
1252:             }
1253: 
1254:             // lauch the action
1255:             $res = $this->{$fnc}($param);
1256: 
1257:             // save the name of the action
1258:             $this->_previousCall = $fnc;
1259: 
1260:             // return the result
1261:             return $res;
1262:         }
1263: 
1264:         /**
1265:          * get the position of the element on the current line, depending on his height
1266:          *
1267:          * @access protected
1268:          * @param  float $h
1269:          * @return float
1270:          */
1271:         protected function _getElementY($h)
1272:         {
1273:             if ($this->_subPart || $this->_isSubPart || !$this->_currentH || $this->_currentH<$h)
1274:                 return 0;
1275: 
1276:             return ($this->_currentH-$h)*0.8;
1277:         }
1278: 
1279:         /**
1280:          * make a break line
1281:          *
1282:          * @access protected
1283:          * @param  float $h current line height
1284:          * @param  integer $curr real current position in the text, if new line in the write of a text
1285:          */
1286:         protected function _makeBreakLine($h, $curr = null)
1287:         {
1288:             if ($h) {
1289:                 if (($this->pdf->getY()+$h<$this->pdf->getH() - $this->pdf->getbMargin()) || $this->_isInOverflow || $this->_isInFooter)
1290:                     $this->_setNewLine($h, $curr);
1291:                 else
1292:                     $this->_setNewPage(null, '', null, $curr);
1293:             } else {
1294:                 $this->_setNewPositionForNewLine($curr);
1295:             }
1296: 
1297:             $this->_maxH = 0;
1298:             $this->_maxE = 0;
1299:         }
1300: 
1301:         /**
1302:          * display a image
1303:          *
1304:          * @access protected
1305:          * @param  string $src
1306:          * @param  boolean $subLi if true=image of a list
1307:          * @return boolean depending on "isForOneLine"
1308:          */
1309:         protected function _drawImage($src, $subLi=false)
1310:         {
1311:             // get the size of the image
1312:             // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
1313:             $infos=@getimagesize($src);
1314: 
1315:             // if the image does not exist, or can not be loaded
1316:             if (count($infos)<2) {
1317:                 // if the test is activ => exception
1318:                 if ($this->_testIsImage) {
1319:                     throw new HTML2PDF_exception(6, $src);
1320:                 }
1321: 
1322:                 // else, display a gray rectangle
1323:                 $src = null;
1324:                 $infos = array(16, 16);
1325:             }
1326: 
1327:             // convert the size of the image in the unit of the PDF
1328:             $imageWidth = $infos[0]/$this->pdf->getK();
1329:             $imageHeight = $infos[1]/$this->pdf->getK();
1330: 
1331:             // calculate the size from the css style
1332:             if ($this->parsingCss->value['width'] && $this->parsingCss->value['height']) {
1333:                 $w = $this->parsingCss->value['width'];
1334:                 $h = $this->parsingCss->value['height'];
1335:             } else if ($this->parsingCss->value['width']) {
1336:                 $w = $this->parsingCss->value['width'];
1337:                 $h = $imageHeight*$w/$imageWidth;
1338:             } else if ($this->parsingCss->value['height']) {
1339:                 $h = $this->parsingCss->value['height'];
1340:                 $w = $imageWidth*$h/$imageHeight;
1341:             } else {
1342:                 // convert px to pt
1343:                 $w = 72./96.*$imageWidth;
1344:                 $h = 72./96.*$imageHeight;
1345:             }
1346: 
1347:             // are we in a float
1348:             $float = $this->parsingCss->getFloat();
1349: 
1350:             // if we are in a float, but if something else if on the line => Break Line
1351:             if ($float && $this->_maxH) {
1352:                 // make the break line (false if we are in "_isForOneLine" mode)
1353:                 if (!$this->_tag_open_BR(array())) {
1354:                     return false;
1355:                 }
1356:             }
1357: 
1358:             // position of the image
1359:             $x = $this->pdf->getX();
1360:             $y = $this->pdf->getY();
1361: 
1362:             // if the image can not be put on the current line => new line
1363:             if (!$float && ($x + $w>$this->pdf->getW() - $this->pdf->getrMargin()) && $this->_maxH) {
1364:                 if ($this->_isForOneLine) {
1365:                     return false;
1366:                 }
1367: 
1368:                 // set the new line
1369:                 $hnl = max($this->_maxH, $this->parsingCss->getLineHeight());
1370:                 $this->_setNewLine($hnl);
1371: 
1372:                 // get the new position
1373:                 $x = $this->pdf->getX();
1374:                 $y = $this->pdf->getY();
1375:             }
1376: 
1377:             // if the image can not be put on the current page
1378:             if (($y + $h>$this->pdf->getH() - $this->pdf->getbMargin()) && !$this->_isInOverflow) {
1379:                 // new page
1380:                 $this->_setNewPage();
1381: 
1382:                 // get the new position
1383:                 $x = $this->pdf->getX();
1384:                 $y = $this->pdf->getY();
1385:             }
1386: 
1387:             // correction for display the image of a list
1388:             $hT = 0.80*$this->parsingCss->value['font-size'];
1389:             if ($subLi && $h<$hT) {
1390:                 $y+=($hT-$h);
1391:             }
1392: 
1393:             // add the margin top
1394:             $yc = $y-$this->parsingCss->value['margin']['t'];
1395: 
1396:             // get the width and the position of the parent
1397:             $old = $this->parsingCss->getOldValues();
1398:             if ( $old['width']) {
1399:                 $parentWidth = $old['width'];
1400:                 $parentX = $x;
1401:             } else {
1402:                 $parentWidth = $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
1403:                 $parentX = $this->pdf->getlMargin();
1404:             }
1405: 
1406:             // if we are in a gloat => adapt the parent position and width
1407:             if ($float) {
1408:                 list($lx, $rx) = $this->_getMargins($yc);
1409:                 $parentX = $lx;
1410:                 $parentWidth = $rx-$lx;
1411:             }
1412: 
1413:             // calculate the position of the image, if align to the right
1414:             if ($parentWidth>$w && $float!='left') {
1415:                 if ($float=='right' || $this->parsingCss->value['text-align']=='li_right')    $x = $parentX + $parentWidth - $w-$this->parsingCss->value['margin']['r']-$this->parsingCss->value['margin']['l'];
1416:             }
1417: 
1418:             // display the image
1419:             if (!$this->_subPart && !$this->_isSubPart) {
1420:                 if ($src) {
1421:                     $this->pdf->Image($src, $x, $y, $w, $h, '', $this->_isInLink);
1422:                 } else {
1423:                     // rectangle if the image can not be loaded
1424:                     $this->pdf->setFillColorArray(array(240, 220, 220));
1425:                     $this->pdf->Rect($x, $y, $w, $h, 'F');
1426:                 }
1427:             }
1428: 
1429:             // apply the margins
1430:             $x-= $this->parsingCss->value['margin']['l'];
1431:             $y-= $this->parsingCss->value['margin']['t'];
1432:             $w+= $this->parsingCss->value['margin']['l'] + $this->parsingCss->value['margin']['r'];
1433:             $h+= $this->parsingCss->value['margin']['t'] + $this->parsingCss->value['margin']['b'];
1434: 
1435:             if ($float=='left') {
1436:                 // save the current max
1437:                 $this->_maxX = max($this->_maxX, $x+$w);
1438:                 $this->_maxY = max($this->_maxY, $y+$h);
1439: 
1440:                 // add the image to the margins
1441:                 $this->_addMargins($float, $x, $y, $x+$w, $y+$h);
1442: 
1443:                 // get the new position
1444:                 list($lx, $rx) = $this->_getMargins($yc);
1445:                 $this->pdf->setXY($lx, $yc);
1446:             } else if ($float=='right') {
1447:                 // save the current max. We don't save the X because it is not the real max of the line
1448:                 $this->_maxY = max($this->_maxY, $y+$h);
1449: 
1450:                 // add the image to the margins
1451:                 $this->_addMargins($float, $x, $y, $x+$w, $y+$h);
1452: 
1453:                 // get the new position
1454:                 list($lx, $rx) = $this->_getMargins($yc);
1455:                 $this->pdf->setXY($lx, $yc);
1456:             } else {
1457:                 // set the new position at the end of the image
1458:                 $this->pdf->setX($x+$w);
1459: 
1460:                 // save the current max
1461:                 $this->_maxX = max($this->_maxX, $x+$w);
1462:                 $this->_maxY = max($this->_maxY, $y+$h);
1463:                 $this->_maxH = max($this->_maxH, $h);
1464:             }
1465: 
1466:             return true;
1467:         }
1468: 
1469:         /**
1470:          * draw a rectangle
1471:          *
1472:          * @access protected
1473:          * @param  float $x
1474:          * @param  float $y
1475:          * @param  float $w
1476:          * @param  float $h
1477:          * @param  array $border
1478:          * @param  float $padding - internal marge of the rectanble => not used, but...
1479:          * @param  float $margin  - external marge of the rectanble
1480:          * @param  array $background
1481:          * @return boolean
1482:          */
1483:         protected function _drawRectangle($x, $y, $w, $h, $border, $padding, $margin, $background)
1484:         {
1485:             // if we are in a subpart or if height is null => return false
1486:             if ($this->_subPart || $this->_isSubPart || $h===null) return false;
1487: 
1488:             // add the margin
1489:             $x+= $margin;
1490:             $y+= $margin;
1491:             $w-= $margin*2;
1492:             $h-= $margin*2;
1493: 
1494:             // get the radius of the border
1495:             $outTL = $border['radius']['tl'];
1496:             $outTR = $border['radius']['tr'];
1497:             $outBR = $border['radius']['br'];
1498:             $outBL = $border['radius']['bl'];
1499: 
1500:             // prepare the out radius
1501:             $outTL = ($outTL[0] && $outTL[1]) ? $outTL : null;
1502:             $outTR = ($outTR[0] && $outTR[1]) ? $outTR : null;
1503:             $outBR = ($outBR[0] && $outBR[1]) ? $outBR : null;
1504:             $outBL = ($outBL[0] && $outBL[1]) ? $outBL : null;
1505: 
1506:             // prepare the in radius
1507:             $inTL = $outTL;
1508:             $inTR = $outTR;
1509:             $inBR = $outBR;
1510:             $inBL = $outBL;
1511: 
1512:             if (is_array($inTL)) {
1513:                 $inTL[0]-= $border['l']['width'];
1514:                 $inTL[1]-= $border['t']['width'];
1515:             }
1516:             if (is_array($inTR)) {
1517:                 $inTR[0]-= $border['r']['width'];
1518:                 $inTR[1]-= $border['t']['width'];
1519:             }
1520:             if (is_array($inBR)) {
1521:                 $inBR[0]-= $border['r']['width'];
1522:                 $inBR[1]-= $border['b']['width'];
1523:             }
1524:             if (is_array($inBL)) {
1525:                 $inBL[0]-= $border['l']['width'];
1526:                 $inBL[1]-= $border['b']['width'];
1527:             }
1528: 
1529:             if ($inTL[0]<=0 || $inTL[1]<=0) $inTL = null;
1530:             if ($inTR[0]<=0 || $inTR[1]<=0) $inTR = null;
1531:             if ($inBR[0]<=0 || $inBR[1]<=0) $inBR = null;
1532:             if ($inBL[0]<=0 || $inBL[1]<=0) $inBL = null;
1533: 
1534:             // prepare the background color
1535:             $pdfStyle = '';
1536:             if ($background['color']) {
1537:                 $this->pdf->setFillColorArray($background['color']);
1538:                 $pdfStyle.= 'F';
1539:             }
1540:            
1541:             if ($background['transparency']) {
1542:                 $this->pdf->SetAlpha($background['transparency']);
1543:             }
1544:             else
1545:             {
1546:                 $this->pdf->SetAlpha(1);
1547:             }
1548: 
1549:             // if we have a background to fill => fill it with a path (because of the radius)
1550:             if ($pdfStyle) {
1551:                 $this->pdf->clippingPathStart($x, $y, $w, $h, $outTL, $outTR, $outBL, $outBR);
1552:                 $this->pdf->Rect($x, $y, $w, $h, $pdfStyle);
1553:                 $this->pdf->clippingPathStop();
1554:             }
1555: 
1556:             // prepare the background image
1557:             if ($background['image']) {
1558:                 $iName      = $background['image'];
1559:                 $iPosition  = $background['position']!==null ? $background['position'] : array(0, 0);
1560:                 $iRepeat    = $background['repeat']!==null   ? $background['repeat']   : array(true, true);
1561: 
1562:                 // size of the background without the borders
1563:                 $bX = $x;
1564:                 $bY = $y;
1565:                 $bW = $w;
1566:                 $bH = $h;
1567: 
1568:                 if ($border['b']['width']) {
1569:                     $bH-= $border['b']['width'];
1570:                 }
1571:                 if ($border['l']['width']) {
1572:                     $bW-= $border['l']['width'];
1573:                     $bX+= $border['l']['width'];
1574:                 }
1575:                 if ($border['t']['width']) {
1576:                     $bH-= $border['t']['width'];
1577:                     $bY+= $border['t']['width'];
1578:                 }
1579:                 if ($border['r']['width']) {
1580:                     $bW-= $border['r']['width'];
1581:                 }
1582: 
1583:                 // get the size of the image
1584:                 // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
1585:                 $imageInfos=@getimagesize($iName);
1586: 
1587:                 // if the image can not be loaded
1588:                 if (count($imageInfos)<2) {
1589:                     if ($this->_testIsImage) {
1590:                         throw new HTML2PDF_exception(6, $iName);
1591:                     }
1592:                 } else {
1593:                     // convert the size of the image from pixel to the unit of the PDF
1594:                     $imageWidth    = 72./96.*$imageInfos[0]/$this->pdf->getK();
1595:                     $imageHeight    = 72./96.*$imageInfos[1]/$this->pdf->getK();
1596: 
1597:                     // prepare the position of the backgroung
1598:                     if ($iRepeat[0]) $iPosition[0] = $bX;
1599:                     else if (preg_match('/^([-]?[0-9\.]+)%/isU', $iPosition[0], $match)) $iPosition[0] = $bX + $match[1]*($bW-$imageWidth)/100;
1600:                     else $iPosition[0] = $bX+$iPosition[0];
1601: 
1602:                     if ($iRepeat[1]) $iPosition[1] = $bY;
1603:                     else if (preg_match('/^([-]?[0-9\.]+)%/isU', $iPosition[1], $match)) $iPosition[1] = $bY + $match[1]*($bH-$imageHeight)/100;
1604:                     else $iPosition[1] = $bY+$iPosition[1];
1605: 
1606:                     $imageXmin = $bX;
1607:                     $imageXmax = $bX+$bW;
1608:                     $imageYmin = $bY;
1609:                     $imageYmax = $bY+$bH;
1610: 
1611:                     if (!$iRepeat[0] && !$iRepeat[1]) {
1612:                         $imageXmin =     $iPosition[0]; $imageXmax =     $iPosition[0]+$imageWidth;
1613:                         $imageYmin =     $iPosition[1]; $imageYmax =     $iPosition[1]+$imageHeight;
1614:                     } else if ($iRepeat[0] && !$iRepeat[1]) {
1615:                         $imageYmin =     $iPosition[1]; $imageYmax =     $iPosition[1]+$imageHeight;
1616:                     } else if (!$iRepeat[0] && $iRepeat[1]) {
1617:                         $imageXmin =     $iPosition[0]; $imageXmax =     $iPosition[0]+$imageWidth;
1618:                     }
1619: 
1620:                     // build the path to display the image (because of radius)
1621:                     $this->pdf->clippingPathStart($bX, $bY, $bW, $bH, $inTL, $inTR, $inBL, $inBR);
1622: 
1623:                     // repeat the image
1624:                     for ($iY=$imageYmin; $iY<$imageYmax; $iY+=$imageHeight) {
1625:                         for ($iX=$imageXmin; $iX<$imageXmax; $iX+=$imageWidth) {
1626:                             $cX = null;
1627:                             $cY = null;
1628:                             $cW = $imageWidth;
1629:                             $cH = $imageHeight;
1630:                             if ($imageYmax-$iY<$imageHeight) {
1631:                                 $cX = $iX;
1632:                                 $cY = $iY;
1633:                                 $cH = $imageYmax-$iY;
1634:                             }
1635:                             if ($imageXmax-$iX<$imageWidth) {
1636:                                 $cX = $iX;
1637:                                 $cY = $iY;
1638:                                 $cW = $imageXmax-$iX;
1639:                             }
1640: 
1641:                             $this->pdf->Image($iName, $iX, $iY, $imageWidth, $imageHeight, '', '');
1642:                         }
1643:                     }
1644: 
1645:                     // end of the path
1646:                     $this->pdf->clippingPathStop();
1647:                 }
1648:             }
1649: 
1650:             // adding some loose (0.01mm)
1651:             $loose = 0.01;
1652:             $x-= $loose;
1653:             $y-= $loose;
1654:             $w+= 2.*$loose;
1655:             $h+= 2.*$loose;
1656:             if ($border['l']['width']) $border['l']['width']+= 2.*$loose;
1657:             if ($border['t']['width']) $border['t']['width']+= 2.*$loose;
1658:             if ($border['r']['width']) $border['r']['width']+= 2.*$loose;
1659:             if ($border['b']['width']) $border['b']['width']+= 2.*$loose;
1660: 
1661:             // prepare the test on borders
1662:             $testBl = ($border['l']['width'] && $border['l']['color'][0]!==null);
1663:             $testBt = ($border['t']['width'] && $border['t']['color'][0]!==null);
1664:             $testBr = ($border['r']['width'] && $border['r']['color'][0]!==null);
1665:             $testBb = ($border['b']['width'] && $border['b']['color'][0]!==null);
1666: 
1667:             // draw the radius bottom-left
1668:             if (is_array($outBL) && ($testBb || $testBl)) {
1669:                 if ($inBL) {
1670:                     $courbe = array();
1671:                     $courbe[] = $x+$outBL[0];              $courbe[] = $y+$h;
1672:                     $courbe[] = $x;                        $courbe[] = $y+$h-$outBL[1];
1673:                     $courbe[] = $x+$outBL[0];              $courbe[] = $y+$h-$border['b']['width'];
1674:                     $courbe[] = $x+$border['l']['width'];  $courbe[] = $y+$h-$outBL[1];
1675:                     $courbe[] = $x+$outBL[0];              $courbe[] = $y+$h-$outBL[1];
1676:                 } else {
1677:                     $courbe = array();
1678:                     $courbe[] = $x+$outBL[0];              $courbe[] = $y+$h;
1679:                     $courbe[] = $x;                        $courbe[] = $y+$h-$outBL[1];
1680:                     $courbe[] = $x+$border['l']['width'];  $courbe[] = $y+$h-$border['b']['width'];
1681:                     $courbe[] = $x+$outBL[0];              $courbe[] = $y+$h-$outBL[1];
1682:                 }
1683:                 $this->_drawCurve($courbe, $border['l']['color']);
1684:             }
1685: 
1686:             // draw the radius left-top
1687:             if (is_array($outTL) && ($testBt || $testBl)) {
1688:                 if ($inTL) {
1689:                     $courbe = array();
1690:                     $courbe[] = $x;                        $courbe[] = $y+$outTL[1];
1691:                     $courbe[] = $x+$outTL[0];              $courbe[] = $y;
1692:                     $courbe[] = $x+$border['l']['width'];  $courbe[] = $y+$outTL[1];
1693:                     $courbe[] = $x+$outTL[0];              $courbe[] = $y+$border['t']['width'];
1694:                     $courbe[] = $x+$outTL[0];              $courbe[] = $y+$outTL[1];
1695:                 } else {
1696:                     $courbe = array();
1697:                     $courbe[] = $x;                        $courbe[] = $y+$outTL[1];
1698:                     $courbe[] = $x+$outTL[0];              $courbe[] = $y;
1699:                     $courbe[] = $x+$border['l']['width'];  $courbe[] = $y+$border['t']['width'];
1700:                     $courbe[] = $x+$outTL[0];              $courbe[] = $y+$outTL[1];
1701:                 }
1702:                 $this->_drawCurve($courbe, $border['t']['color']);
1703:             }
1704: 
1705:             // draw the radius top-right
1706:             if (is_array($outTR) && ($testBt || $testBr)) {
1707:                 if ($inTR) {
1708:                     $courbe = array();
1709:                     $courbe[] = $x+$w-$outTR[0];             $courbe[] = $y;
1710:                     $courbe[] = $x+$w;                       $courbe[] = $y+$outTR[1];
1711:                     $courbe[] = $x+$w-$outTR[0];             $courbe[] = $y+$border['t']['width'];
1712:                     $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$outTR[1];
1713:                     $courbe[] = $x+$w-$outTR[0];             $courbe[] = $y+$outTR[1];
1714:                 } else {
1715:                     $courbe = array();
1716:                     $courbe[] = $x+$w-$outTR[0];             $courbe[] = $y;
1717:                     $courbe[] = $x+$w;                       $courbe[] = $y+$outTR[1];
1718:                     $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$border['t']['width'];
1719:                     $courbe[] = $x+$w-$outTR[0];             $courbe[] = $y+$outTR[1];
1720:                 }
1721:                 $this->_drawCurve($courbe, $border['r']['color']);
1722:             }
1723: 
1724:             // draw the radius right-bottom
1725:             if (is_array($outBR) && ($testBb || $testBr)) {
1726:                 if ($inBR) {
1727:                     $courbe = array();
1728:                     $courbe[] = $x+$w;                       $courbe[] = $y+$h-$outBR[1];
1729:                     $courbe[] = $x+$w-$outBR[0];             $courbe[] = $y+$h;
1730:                     $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$h-$outBR[1];
1731:                     $courbe[] = $x+$w-$outBR[0];             $courbe[] = $y+$h-$border['b']['width'];
1732:                     $courbe[] = $x+$w-$outBR[0];             $courbe[] = $y+$h-$outBR[1];
1733:                 } else {
1734:                     $courbe = array();
1735:                     $courbe[] = $x+$w;                       $courbe[] = $y+$h-$outBR[1];
1736:                     $courbe[] = $x+$w-$outBR[0];             $courbe[] = $y+$h;
1737:                     $courbe[] = $x+$w-$border['r']['width']; $courbe[] = $y+$h-$border['b']['width'];
1738:                     $courbe[] = $x+$w-$outBR[0];             $courbe[] = $y+$h-$outBR[1];
1739:                 }
1740:                 $this->_drawCurve($courbe, $border['b']['color']);
1741:             }
1742: 
1743:             // draw the left border
1744:             if ($testBl) {
1745:                 $pt = array();
1746:                 $pt[] = $x;                       $pt[] = $y+$h;
1747:                 $pt[] = $x;                       $pt[] = $y+$h-$border['b']['width'];
1748:                 $pt[] = $x;                       $pt[] = $y+$border['t']['width'];
1749:                 $pt[] = $x;                       $pt[] = $y;
1750:                 $pt[] = $x+$border['l']['width']; $pt[] = $y+$border['t']['width'];
1751:                 $pt[] = $x+$border['l']['width']; $pt[] = $y+$h-$border['b']['width'];
1752: 
1753:                 $bord = 3;
1754:                 if (is_array($outBL)) {
1755:                     $bord-=1;
1756:                     $pt[3] -= $outBL[1] - $border['b']['width'];
1757:                     if ($inBL) $pt[11]-= $inBL[1];
1758:                     unset($pt[0]);unset($pt[1]);
1759:                 }
1760:                 if (is_array($outTL)) {
1761:                     $bord-=2;
1762:                     $pt[5] += $outTL[1]-$border['t']['width'];
1763:                     if ($inTL) $pt[9] += $inTL[1];
1764:                     unset($pt[6]);unset($pt[7]);
1765:                 }
1766: 
1767:                 $pt = array_values($pt);
1768:                 $this->_drawLine($pt, $border['l']['color'], $border['l']['type'], $border['l']['width'], $bord);
1769:             }
1770: 
1771:             // draw the top border
1772:             if ($testBt) {
1773:                 $pt = array();
1774:                 $pt[] = $x;                          $pt[] = $y;
1775:                 $pt[] = $x+$border['l']['width'];    $pt[] = $y;
1776:                 $pt[] = $x+$w-$border['r']['width']; $pt[] = $y;
1777:                 $pt[] = $x+$w;                       $pt[] = $y;
1778:                 $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$border['t']['width'];
1779:                 $pt[] = $x+$border['l']['width'];    $pt[] = $y+$border['t']['width'];
1780: 
1781:                 $bord = 3;
1782:                 if (is_array($outTL)) {
1783:                     $bord-=1;
1784:                     $pt[2] += $outTL[0] - $border['l']['width'];
1785:                     if ($inTL) $pt[10]+= $inTL[0];
1786:                     unset($pt[0]);unset($pt[1]);
1787:                 }
1788:                 if (is_array($outTR)) {
1789:                     $bord-=2;
1790:                     $pt[4] -= $outTR[0] - $border['r']['width'];
1791:                     if ($inTR) $pt[8] -= $inTR[0];
1792:                     unset($pt[6]);unset($pt[7]);
1793:                 }
1794: 
1795:                 $pt = array_values($pt);
1796:                 $this->_drawLine($pt, $border['t']['color'], $border['t']['type'], $border['t']['width'], $bord);
1797:             }
1798: 
1799:             // draw the right border
1800:             if ($testBr) {
1801:                 $pt = array();
1802:                 $pt[] = $x+$w;                       $pt[] = $y;
1803:                 $pt[] = $x+$w;                       $pt[] = $y+$border['t']['width'];
1804:                 $pt[] = $x+$w;                       $pt[] = $y+$h-$border['b']['width'];
1805:                 $pt[] = $x+$w;                       $pt[] = $y+$h;
1806:                 $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h-$border['b']['width'];
1807:                 $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$border['t']['width'];
1808: 
1809:                 $bord = 3;
1810:                 if (is_array($outTR)) {
1811:                     $bord-=1;
1812:                     $pt[3] += $outTR[1] - $border['t']['width'];
1813:                     if ($inTR) $pt[11]+= $inTR[1];
1814:                     unset($pt[0]);unset($pt[1]);
1815:                 }
1816:                 if (is_array($outBR)) {
1817:                     $bord-=2;
1818:                     $pt[5] -= $outBR[1] - $border['b']['width'];
1819:                     if ($inBR) $pt[9] -= $inBR[1];
1820:                     unset($pt[6]);unset($pt[7]);
1821:                 }
1822: 
1823:                 $pt = array_values($pt);
1824:                 $this->_drawLine($pt, $border['r']['color'], $border['r']['type'], $border['r']['width'], $bord);
1825:             }
1826: 
1827:             // draw the bottom border
1828:             if ($testBb) {
1829:                 $pt = array();
1830:                 $pt[] = $x+$w;                       $pt[] = $y+$h;
1831:                 $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h;
1832:                 $pt[] = $x+$border['l']['width'];    $pt[] = $y+$h;
1833:                 $pt[] = $x;                          $pt[] = $y+$h;
1834:                 $pt[] = $x+$border['l']['width'];    $pt[] = $y+$h-$border['b']['width'];
1835:                 $pt[] = $x+$w-$border['r']['width']; $pt[] = $y+$h-$border['b']['width'];
1836: 
1837:                 $bord = 3;
1838:                 if (is_array($outBL)) {
1839:                     $bord-=2;
1840:                     $pt[4] += $outBL[0] - $border['l']['width'];
1841:                     if ($inBL) $pt[8] += $inBL[0];
1842:                     unset($pt[6]);unset($pt[7]);
1843:                 }
1844:                 if (is_array($outBR)) {
1845:                     $bord-=1;
1846:                     $pt[2] -= $outBR[0] - $border['r']['width'];
1847:                     if ($inBR) $pt[10]-= $inBR[0];
1848:                     unset($pt[0]);unset($pt[1]);
1849: 
1850:                 }
1851: 
1852:                 $pt = array_values($pt);
1853:                 $this->_drawLine($pt, $border['b']['color'], $border['b']['type'], $border['b']['width'], $bord);
1854:             }
1855: 
1856:             if ($background['color']) {
1857:                 $this->pdf->setFillColorArray($background['color']);
1858:             }
1859: 
1860:             return true;
1861:         }
1862: 
1863:         /**
1864:          * draw a curve (for border radius)
1865:          *
1866:          * @access protected
1867:          * @param  array $pt
1868:          * @param  array $color
1869:          */
1870:         protected function _drawCurve($pt, $color)
1871:         {
1872:             $this->pdf->setFillColorArray($color);
1873: 
1874:             if (count($pt)==10)
1875:                 $this->pdf->drawCurve($pt[0], $pt[1], $pt[2], $pt[3], $pt[4], $pt[5], $pt[6], $pt[7], $pt[8], $pt[9]);
1876:             else
1877:                 $this->pdf->drawCorner($pt[0], $pt[1], $pt[2], $pt[3], $pt[4], $pt[5], $pt[6], $pt[7]);
1878:         }
1879: 
1880:         /**
1881:          * draw a ligne with a specific type, and specific start and end for radius
1882:          *
1883:          * @access protected
1884:          * @param  array   $pt
1885:          * @param  float   $color
1886:          * @param  string  $type (dashed, dotted, double, solid)
1887:          * @param  float   $width
1888:          * @param  integer $radius (binary from 0 to 3 with 1=>start with a radius, 2=>end with a radius)
1889:          */
1890:         protected function _drawLine($pt, $color, $type, $width, $radius=3)
1891:         {
1892:             // set the fill color
1893:             $this->pdf->setFillColorArray($color);
1894: 
1895:             // if dashed or dotted
1896:             if ($type=='dashed' || $type=='dotted') {
1897: 
1898:                 // clean the end of the line, if radius
1899:                 if ($radius==1) {
1900:                     $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
1901:                     $this->pdf->Polygon($tmp, 'F');
1902: 
1903:                     $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
1904:                     $pt = $tmp;
1905:                 } else if ($radius==2) {
1906:                     $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7];
1907:                     $this->pdf->Polygon($tmp, 'F');
1908: 
1909:                     $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
1910:                     $pt = $tmp;
1911:                 } else if ($radius==3) {
1912:                     $tmp = array(); $tmp[]=$pt[0]; $tmp[]=$pt[1]; $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[10]; $tmp[]=$pt[11];
1913:                     $this->pdf->Polygon($tmp, 'F');
1914: 
1915:                     $tmp = array(); $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[6]; $tmp[]=$pt[7]; $tmp[]=$pt[8]; $tmp[]=$pt[9];
1916:                     $this->pdf->Polygon($tmp, 'F');
1917: 
1918:                     $tmp = array(); $tmp[]=$pt[2]; $tmp[]=$pt[3]; $tmp[]=$pt[4]; $tmp[]=$pt[5]; $tmp[]=$pt[8]; $tmp[]=$pt[9]; $tmp[]=$pt[10]; $tmp[]=$pt[11];
1919:                     $pt = $tmp;
1920:                 }
1921: 
1922:                 // horisontal or vertical line
1923:                 if ($pt[2]==$pt[0]) {
1924:                     $l = abs(($pt[3]-$pt[1])*0.5);
1925:                     $px = 0;
1926:                     $py = $width;
1927:                     $x1 = $pt[0]; $y1 = ($pt[3]+$pt[1])*0.5;
1928:                     $x2 = $pt[6]; $y2 = ($pt[7]+$pt[5])*0.5;
1929:                 } else {
1930:                     $l = abs(($pt[2]-$pt[0])*0.5);
1931:                     $px = $width;
1932:                     $py = 0;
1933:                     $x1 = ($pt[2]+$pt[0])*0.5; $y1 = $pt[1];
1934:                     $x2 = ($pt[6]+$pt[4])*0.5; $y2 = $pt[7];
1935:                 }
1936: 
1937:                 // if dashed : 3x bigger than dotted
1938:                 if ($type=='dashed') {
1939:                     $px = $px*3.;
1940:                     $py = $py*3.;
1941:                 }
1942:                 $mode = ($l/($px+$py)<.5);
1943: 
1944:                 // display the dotted/dashed line
1945:                 for ($i=0; $l-($px+$py)*($i-0.5)>0; $i++) {
1946:                     if (($i%2)==$mode) {
1947:                         $j = $i-0.5;
1948:                         $lx1 = $px*($j);   if ($lx1<-$l) $lx1 =-$l;
1949:                         $ly1 = $py*($j);   if ($ly1<-$l) $ly1 =-$l;
1950:                         $lx2 = $px*($j+1); if ($lx2>$l)  $lx2 = $l;
1951:                         $ly2 = $py*($j+1); if ($ly2>$l)  $ly2 = $l;
1952: 
1953:                         $tmp = array();
1954:                         $tmp[] = $x1+$lx1; $tmp[] = $y1+$ly1;
1955:                         $tmp[] = $x1+$lx2; $tmp[] = $y1+$ly2;
1956:                         $tmp[] = $x2+$lx2; $tmp[] = $y2+$ly2;
1957:                         $tmp[] = $x2+$lx1; $tmp[] = $y2+$ly1;
1958:                         $this->pdf->Polygon($tmp, 'F');
1959: 
1960:                         if ($j>0) {
1961:                             $tmp = array();
1962:                             $tmp[] = $x1-$lx1; $tmp[] = $y1-$ly1;
1963:                             $tmp[] = $x1-$lx2; $tmp[] = $y1-$ly2;
1964:                             $tmp[] = $x2-$lx2; $tmp[] = $y2-$ly2;
1965:                             $tmp[] = $x2-$lx1; $tmp[] = $y2-$ly1;
1966:                             $this->pdf->Polygon($tmp, 'F');
1967:                         }
1968:                     }
1969:                 }
1970:             } else if ($type=='double') {
1971: 
1972:                 // if double, 2 lines : 0=>1/3 and 2/3=>1
1973:                 $pt1 = $pt;
1974:                 $pt2 = $pt;
1975: 
1976:                 if (count($pt)==12) {
1977:                     // line 1
1978:                     $pt1[0] = ($pt[0]-$pt[10])*0.33 + $pt[10];
1979:                     $pt1[1] = ($pt[1]-$pt[11])*0.33 + $pt[11];
1980:                     $pt1[2] = ($pt[2]-$pt[10])*0.33 + $pt[10];
1981:                     $pt1[3] = ($pt[3]-$pt[11])*0.33 + $pt[11];
1982:                     $pt1[4] = ($pt[4]-$pt[8])*0.33 + $pt[8];
1983:                     $pt1[5] = ($pt[5]-$pt[9])*0.33 + $pt[9];
1984:                     $pt1[6] = ($pt[6]-$pt[8])*0.33 + $pt[8];
1985:                     $pt1[7] = ($pt[7]-$pt[9])*0.33 + $pt[9];
1986:                     $pt2[10]= ($pt[10]-$pt[0])*0.33 + $pt[0];
1987:                     $pt2[11]= ($pt[11]-$pt[1])*0.33 + $pt[1];
1988: 
1989:                     // line 2
1990:                     $pt2[2] = ($pt[2] -$pt[0])*0.33 + $pt[0];
1991:                     $pt2[3] = ($pt[3] -$pt[1])*0.33 + $pt[1];
1992:                     $pt2[4] = ($pt[4] -$pt[6])*0.33 + $pt[6];
1993:                     $pt2[5] = ($pt[5] -$pt[7])*0.33 + $pt[7];
1994:                     $pt2[8] = ($pt[8] -$pt[6])*0.33 + $pt[6];
1995:                     $pt2[9] = ($pt[9] -$pt[7])*0.33 + $pt[7];
1996:                 } else {
1997:                     // line 1
1998:                     $pt1[0] = ($pt[0]-$pt[6])*0.33 + $pt[6];
1999:                     $pt1[1] = ($pt[1]-$pt[7])*0.33 + $pt[7];
2000:                     $pt1[2] = ($pt[2]-$pt[4])*0.33 + $pt[4];
2001:                     $pt1[3] = ($pt[3]-$pt[5])*0.33 + $pt[5];
2002: 
2003:                     // line 2
2004:                     $pt2[6] = ($pt[6]-$pt[0])*0.33 + $pt[0];
2005:                     $pt2[7] = ($pt[7]-$pt[1])*0.33 + $pt[1];
2006:                     $pt2[4] = ($pt[4]-$pt[2])*0.33 + $pt[2];
2007:                     $pt2[5] = ($pt[5]-$pt[3])*0.33 + $pt[3];
2008:                 }
2009:                 $this->pdf->Polygon($pt1, 'F');
2010:                 $this->pdf->Polygon($pt2, 'F');
2011:             } else if ($type=='solid') {
2012:                 // solid line : draw directly the polygon
2013:                 $this->pdf->Polygon($pt, 'F');
2014:             }
2015:         }
2016: 
2017:         /**
2018:          * prepare a transform matrix, only for drawing a SVG graphic
2019:          *
2020:          * @access protected
2021:          * @param  string $transform
2022:          * @return array  $matrix
2023:          */
2024:         protected function _prepareTransform($transform)
2025:         {
2026:             // it can not be  empty
2027:             if (!$transform) return null;
2028: 
2029:             // sctions must be like scale(...)
2030:             if (!preg_match_all('/([a-z]+)\(([^\)]*)\)/isU', $transform, $match)) return null;
2031: 
2032:             // prepare the list of the actions
2033:             $actions = array();
2034: 
2035:             // for actions
2036:             for ($k=0; $k<count($match[0]); $k++) {
2037: 
2038:                 // get the name of the action
2039:                 $name = strtolower($match[1][$k]);
2040: 
2041:                 // get the parameters of the action
2042:                 $val = explode(',', trim($match[2][$k]));
2043:                 foreach ($val as $i => $j) {
2044:                     $val[$i] = trim($j);
2045:                 }
2046: 
2047:                 // prepare the matrix, depending on the action
2048:                 switch($name)
2049:                 {
2050:                     case 'scale':
2051:                         if (!isset($val[0])) $val[0] = 1.;      else $val[0] = 1.*$val[0];
2052:                         if (!isset($val[1])) $val[1] = $val[0]; else $val[1] = 1.*$val[1];
2053:                         $actions[] = array($val[0],0,0,$val[1],0,0);
2054:                         break;
2055: 
2056:                     case 'translate':
2057:                         if (!isset($val[0])) $val[0] = 0.; else $val[0] = $this->parsingCss->ConvertToMM($val[0], $this->_isInDraw['w']);
2058:                         if (!isset($val[1])) $val[1] = 0.; else $val[1] = $this->parsingCss->ConvertToMM($val[1], $this->_isInDraw['h']);
2059:                         $actions[] = array(1,0,0,1,$val[0],$val[1]);
2060:                         break;
2061: 
2062:                     case 'rotate':
2063:                         if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*M_PI/180.;
2064:                         if (!isset($val[1])) $val[1] = 0.; else $val[1] = $this->parsingCss->ConvertToMM($val[1], $this->_isInDraw['w']);
2065:                         if (!isset($val[2])) $val[2] = 0.; else $val[2] = $this->parsingCss->ConvertToMM($val[2], $this->_isInDraw['h']);
2066:                         if ($val[1] || $val[2]) $actions[] = array(1,0,0,1,-$val[1],-$val[2]);
2067:                         $actions[] = array(cos($val[0]),sin($val[0]),-sin($val[0]),cos($val[0]),0,0);
2068:                         if ($val[1] || $val[2]) $actions[] = array(1,0,0,1,$val[1],$val[2]);
2069:                         break;
2070: 
2071:                     case 'skewx':
2072:                         if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*M_PI/180.;
2073:                         $actions[] = array(1,0,tan($val[0]),1,0,0);
2074:                         break;
2075: 
2076:                     case 'skewy':
2077:                         if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*M_PI/180.;
2078:                         $actions[] = array(1,tan($val[0]),0,1,0,0);
2079:                         break;
2080:                     case 'matrix':
2081:                         if (!isset($val[0])) $val[0] = 0.; else $val[0] = $val[0]*1.;
2082:                         if (!isset($val[1])) $val[1] = 0.; else $val[1] = $val[1]*1.;
2083:                         if (!isset($val[2])) $val[2] = 0.; else $val[2] = $val[2]*1.;
2084:                         if (!isset($val[3])) $val[3] = 0.; else $val[3] = $val[3]*1.;
2085:                         if (!isset($val[4])) $val[4] = 0.; else $val[4] = $this->parsingCss->ConvertToMM($val[4], $this->_isInDraw['w']);
2086:                         if (!isset($val[5])) $val[5] = 0.; else $val[5] = $this->parsingCss->ConvertToMM($val[5], $this->_isInDraw['h']);
2087:                         $actions[] =$val;
2088:                         break;
2089:                 }
2090:             }
2091: 
2092:             // if ther is no actions => return
2093:             if (!$actions) return null;
2094: 
2095:             // get the first matrix
2096:             $m = $actions[0]; unset($actions[0]);
2097: 
2098:             // foreach matrix => multiply to the last matrix
2099:             foreach ($actions as $n) {
2100:                 $m = array(
2101:                     $m[0]*$n[0]+$m[2]*$n[1],
2102:                     $m[1]*$n[0]+$m[3]*$n[1],
2103:                     $m[0]*$n[2]+$m[2]*$n[3],
2104:                     $m[1]*$n[2]+$m[3]*$n[3],
2105:                     $m[0]*$n[4]+$m[2]*$n[5]+$m[4],
2106:                     $m[1]*$n[4]+$m[3]*$n[5]+$m[5]
2107:                 );
2108:             }
2109: 
2110:             // return the matrix
2111:             return $m;
2112:         }
2113: 
2114:         /**
2115:          * @access protected
2116:          * @param  &array $cases
2117:          * @param  &array $corr
2118:          */
2119:         protected function _calculateTableCellSize(&$cases, &$corr)
2120:         {
2121:             if (!isset($corr[0])) return true;
2122: 
2123:             // for each cell without colspan, we get the max width for each column
2124:             $sw = array();
2125:             for ($x=0; $x<count($corr[0]); $x++) {
2126:                 $m=0;
2127:                 for ($y=0; $y<count($corr); $y++) {
2128:                     if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][2]==1) {
2129:                         $m = max($m, $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w']);
2130:                     }
2131:                 }
2132:                 $sw[$x] = $m;
2133:             }
2134: 
2135:             // for each cell with colspan, we adapt the width of each column
2136:             for ($x=0; $x<count($corr[0]); $x++) {
2137:                 for ($y=0; $y<count($corr); $y++) {
2138:                     if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][2]>1) {
2139: 
2140:                         // sum the max width of each column in colspan
2141:                         $s = 0; for ($i=0; $i<$corr[$y][$x][2]; $i++) $s+= $sw[$x+$i];
2142: 
2143:                         // if the max width is < the width of the cell with colspan => we adapt the width of each max width
2144:                         if ($s>0 && $s<$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w']) {
2145:                             for ($i=0; $i<$corr[$y][$x][2]; $i++) {
2146:                                 $sw[$x+$i] = $sw[$x+$i]/$s*$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'];
2147:                             }
2148:                         }
2149:                     }
2150:                 }
2151:             }
2152: 
2153:             // set the new width, for each cell
2154:             for ($x=0; $x<count($corr[0]); $x++) {
2155:                 for ($y=0; $y<count($corr); $y++) {
2156:                     if (isset($corr[$y][$x]) && is_array($corr[$y][$x])) {
2157:                         // without colspan
2158:                         if ($corr[$y][$x][2]==1) {
2159:                             $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'] = $sw[$x];
2160:                         // with colspan
2161:                         } else {
2162:                             $s = 0;
2163:                             for ($i=0; $i<$corr[$y][$x][2]; $i++) {
2164:                                 $s+= $sw[$x+$i];
2165:                             }
2166:                             $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'] = $s;
2167:                         }
2168:                     }
2169:                 }
2170:             }
2171: 
2172:             // for each cell without rowspan, we get the max height for each line
2173:             $sh = array();
2174:             for ($y=0; $y<count($corr); $y++) {
2175:                 $m=0;
2176:                 for ($x=0; $x<count($corr[0]); $x++) {
2177:                     if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][3]==1) {
2178:                         $m = max($m, $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h']);
2179:                     }
2180:                 }
2181:                 $sh[$y] = $m;
2182:             }
2183: 
2184:             // for each cell with rowspan, we adapt the height of each line
2185:             for ($y=0; $y<count($corr); $y++) {
2186:                 for ($x=0; $x<count($corr[0]); $x++) {
2187:                     if (isset($corr[$y][$x]) && is_array($corr[$y][$x]) && $corr[$y][$x][3]>1) {
2188: 
2189:                         // sum the max height of each line in rowspan
2190:                         $s = 0; for ($i=0; $i<$corr[$y][$x][3]; $i++) $s+= $sh[$y+$i];
2191: 
2192:                         // if the max height is < the height of the cell with rowspan => we adapt the height of each max height
2193:                         if ($s>0 && $s<$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h']) {
2194:                             for ($i=0; $i<$corr[$y][$x][3]; $i++) {
2195:                                 $sh[$y+$i] = $sh[$y+$i]/$s*$cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'];
2196:                             }
2197:                         }
2198:                     }
2199:                 }
2200:             }
2201: 
2202:             // set the new height, for each cell
2203:             for ($y=0; $y<count($corr); $y++) {
2204:                 for ($x=0; $x<count($corr[0]); $x++) {
2205:                     if (isset($corr[$y][$x]) && is_array($corr[$y][$x])) {
2206:                         // without rowspan
2207:                         if ($corr[$y][$x][3]==1) {
2208:                             $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'] = $sh[$y];
2209:                         // with rowspan
2210:                         } else {
2211:                             $s = 0;
2212:                             for ($i=0; $i<$corr[$y][$x][3]; $i++) {
2213:                                 $s+= $sh[$y+$i];
2214:                             }
2215:                             $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['h'] = $s;
2216: 
2217:                             for ($j=1; $j<$corr[$y][$x][3]; $j++) {
2218:                                 $tx = $x+1;
2219:                                 $ty = $y+$j;
2220:                                 for (true; isset($corr[$ty][$tx]) && !is_array($corr[$ty][$tx]); $tx++);
2221:                                 if (isset($corr[$ty][$tx])) {
2222:                                     $cases[$corr[$ty][$tx][1]][$corr[$ty][$tx][0]]['dw']+= $cases[$corr[$y][$x][1]][$corr[$y][$x][0]]['w'];
2223:                                 }
2224:                             }
2225:                         }
2226:                     }
2227:                 }
2228:             }
2229:         }
2230: 
2231:         /**
2232:          * tag : PAGE
2233:          * mode : OPEN
2234:          *
2235:          * @param  array $param
2236:          * @return boolean
2237:          */
2238:         protected function _tag_open_PAGE($param)
2239:         {
2240:             if ($this->_isForOneLine) return false;
2241:             if ($this->_debugActif) $this->_DEBUG_add('PAGE '.($this->_page+1), true);
2242: 
2243:             $newPageSet= (!isset($param['pageset']) || $param['pageset']!='old');
2244: 
2245:             $resetPageNumber = (isset($param['pagegroup']) && $param['pagegroup']=='new');
2246: 
2247:             $this->_maxH = 0;
2248: 
2249:             // if new page set asked
2250:             if ($newPageSet) {
2251:                 $this->_subHEADER = array();
2252:                 $this->_subFOOTER = array();
2253: 
2254:                 // orientation
2255:                 $orientation = '';
2256:                 if (isset($param['orientation'])) {
2257:                     $param['orientation'] = strtolower($param['orientation']);
2258:                     if ($param['orientation']=='p')         $orientation = 'P';
2259:                     if ($param['orientation']=='portrait')  $orientation = 'P';
2260: 
2261:                     if ($param['orientation']=='l')         $orientation = 'L';
2262:                     if ($param['orientation']=='paysage')   $orientation = 'L';
2263:                     if ($param['orientation']=='landscape') $orientation = 'L';
2264:                 }
2265: 
2266:                 // format
2267:                 $format = null;
2268:                 if (isset($param['format'])) {
2269:                     $format = strtolower($param['format']);
2270:                     if (preg_match('/^([0-9]+)x([0-9]+)$/isU', $format, $match)) {
2271:                         $format = array(intval($match[1]), intval($match[2]));
2272:                     }
2273:                 }
2274: 
2275:                 // background
2276:                 $background = array();
2277:                 if (isset($param['backimg'])) {
2278:                     $background['img']    = isset($param['backimg'])  ? $param['backimg']  : '';       // src of the image
2279:                     $background['posX']   = isset($param['backimgx']) ? $param['backimgx'] : 'center'; // horizontale position of the image
2280:                     $background['posY']   = isset($param['backimgy']) ? $param['backimgy'] : 'middle'; // vertical position of the image
2281:                     $background['width']  = isset($param['backimgw']) ? $param['backimgw'] : '100%';   // width of the image (100% = page width)
2282: 
2283:                     // convert the src of the image, if parameters
2284:                     $background['img'] = str_replace('&amp;', '&', $background['img']);
2285: 
2286:                     // convert the positions
2287:                     if ($background['posX']=='left')    $background['posX'] = '0%';
2288:                     if ($background['posX']=='center')  $background['posX'] = '50%';
2289:                     if ($background['posX']=='right')   $background['posX'] = '100%';
2290:                     if ($background['posY']=='top')     $background['posY'] = '0%';
2291:                     if ($background['posY']=='middle')  $background['posY'] = '50%';
2292:                     if ($background['posY']=='bottom')  $background['posY'] = '100%';
2293: 
2294:                     if ($background['img']) {
2295:                         // get the size of the image
2296:                         // WARNING : if URL, "allow_url_fopen" must turned to "on" in php.ini
2297:                         $infos=@getimagesize($background['img']);
2298:                         if (count($infos)>1) {
2299:                             $imageWidth = $this->parsingCss->ConvertToMM($background['width'], $this->pdf->getW());
2300:                             $imageHeight = $imageWidth*$infos[1]/$infos[0];
2301: 
2302:                             $background['width'] = $imageWidth;
2303:                             $background['posX']  = $this->parsingCss->ConvertToMM($background['posX'], $this->pdf->getW() - $imageWidth);
2304:                             $background['posY']  = $this->parsingCss->ConvertToMM($background['posY'], $this->pdf->getH() - $imageHeight);
2305:                         } else {
2306:                             $background = array();
2307:                         }
2308:                     } else {
2309:                         $background = array();
2310:                     }
2311:                 }
2312: 
2313:                 // margins of the page
2314:                 $background['top']    = isset($param['backtop'])    ? $param['backtop']    : '0';
2315:                 $background['bottom'] = isset($param['backbottom']) ? $param['backbottom'] : '0';
2316:                 $background['left']   = isset($param['backleft'])   ? $param['backleft']   : '0';
2317:                 $background['right']  = isset($param['backright'])  ? $param['backright']  : '0';
2318: 
2319:                 // if no unit => mm
2320:                 if (preg_match('/^([0-9]*)$/isU', $background['top']))    $background['top']    .= 'mm';
2321:                 if (preg_match('/^([0-9]*)$/isU', $background['bottom'])) $background['bottom'] .= 'mm';
2322:                 if (preg_match('/^([0-9]*)$/isU', $background['left']))   $background['left']   .= 'mm';
2323:                 if (preg_match('/^([0-9]*)$/isU', $background['right']))  $background['right']  .= 'mm';
2324: 
2325:                 // convert to mm
2326:                 $background['top']    = $this->parsingCss->ConvertToMM($background['top'], $this->pdf->getH());
2327:                 $background['bottom'] = $this->parsingCss->ConvertToMM($background['bottom'], $this->pdf->getH());
2328:                 $background['left']   = $this->parsingCss->ConvertToMM($background['left'], $this->pdf->getW());
2329:                 $background['right']  = $this->parsingCss->ConvertToMM($background['right'], $this->pdf->getW());
2330: 
2331:                 // get the background color
2332:                 $res = false;
2333:                 $background['color']    = isset($param['backcolor'])    ? $this->parsingCss->convertToColor($param['backcolor'], $res) : null;
2334:                 if (!$res) $background['color'] = null;
2335: 
2336:                 $this->parsingCss->save();
2337:                 $this->parsingCss->analyse('PAGE', $param);
2338:                 $this->parsingCss->setPosition();
2339:                 $this->parsingCss->fontSet();
2340: 
2341:                 // new page
2342:                 $this->_setNewPage($format, $orientation, $background, null, $resetPageNumber);
2343: 
2344:                 // automatic footer
2345:                 if (isset($param['footer'])) {
2346:                     $lst = explode(';', $param['footer']);
2347:                     foreach ($lst as $key => $val) $lst[$key] = trim(strtolower($val));
2348:                     $page    = in_array('page', $lst);
2349:                     $date    = in_array('date', $lst);
2350:                     $hour    = in_array('heure', $lst);
2351:                     $form    = in_array('form', $lst);
2352:                 } else {
2353:                     $page    = null;
2354:                     $date    = null;
2355:                     $hour    = null;
2356:                     $form    = null;
2357:                 }
2358:                 $this->pdf->SetMyFooter($page, $date, $hour, $form);
2359:             // else => we use the last page set used
2360:             } else {
2361:                 $this->parsingCss->save();
2362:                 $this->parsingCss->analyse('PAGE', $param);
2363:                 $this->parsingCss->setPosition();
2364:                 $this->parsingCss->fontSet();
2365: 
2366:                 $this->_setNewPage(null, null, null, null, $resetPageNumber);
2367:             }
2368: 
2369:             return true;
2370:         }
2371: 
2372:         /**
2373:          * tag : PAGE
2374:          * mode : CLOSE
2375:          *
2376:          * @param  array $param
2377:          * @return boolean
2378:          */
2379:         protected function _tag_close_PAGE($param)
2380:         {
2381:             if ($this->_isForOneLine) return false;
2382: 
2383:             $this->_maxH = 0;
2384: 
2385:             $this->parsingCss->load();
2386:             $this->parsingCss->fontSet();
2387: 
2388:             if ($this->_debugActif) $this->_DEBUG_add('PAGE '.$this->_page, false);
2389: 
2390:             return true;
2391:         }
2392: 
2393:         /**
2394:          * tag : PAGE_HEADER
2395:          * mode : OPEN
2396:          *
2397:          * @param  array $param
2398:          * @return boolean
2399:          */
2400:         protected function _tag_open_PAGE_HEADER($param)
2401:         {
2402:             if ($this->_isForOneLine) return false;
2403: 
2404:             $this->_subHEADER = array();
2405:             for ($this->_parsePos; $this->_parsePos<count($this->parsingHtml->code); $this->_parsePos++) {
2406:                 $action = $this->parsingHtml->code[$this->_parsePos];
2407:                 if ($action['name']=='page_header') $action['name']='page_header_sub';
2408:                 $this->_subHEADER[] = $action;
2409:                 if (strtolower($action['name'])=='page_header_sub' && $action['close']) break;
2410:             }
2411: 
2412:             $this->_setPageHeader();
2413: 
2414:             return true;
2415:         }
2416: 
2417:         /**
2418:          * tag : PAGE_FOOTER
2419:          * mode : OPEN
2420:          *
2421:          * @param  array $param
2422:          * @return boolean
2423:          */
2424:         protected function _tag_open_PAGE_FOOTER($param)
2425:         {
2426:             if ($this->_isForOneLine) return false;
2427: 
2428:             $this->_subFOOTER = array();
2429:             for ($this->_parsePos; $this->_parsePos<count($this->parsingHtml->code); $this->_parsePos++) {
2430:                 $action = $this->parsingHtml->code[$this->_parsePos];
2431:                 if ($action['name']=='page_footer') $action['name']='page_footer_sub';
2432:                 $this->_subFOOTER[] = $action;
2433:                 if (strtolower($action['name'])=='page_footer_sub' && $action['close']) break;
2434:             }
2435: 
2436:             $this->_setPageFooter();
2437: 
2438:             return true;
2439:         }
2440: 
2441:         /**
2442:          * It is not a real tag. Does not use it directly
2443:          *
2444:          * @param  array $param
2445:          * @return boolean
2446:          */
2447:         protected function _tag_open_PAGE_HEADER_SUB($param)
2448:         {
2449:             if ($this->_isForOneLine) return false;
2450: 
2451:             // save the current stat
2452:             $this->_subSTATES = array();
2453:             $this->_subSTATES['x']  = $this->pdf->getX();
2454:             $this->_subSTATES['y']  = $this->pdf->getY();
2455:             $this->_subSTATES['s']  = $this->parsingCss->value;
2456:             $this->_subSTATES['t']  = $this->parsingCss->table;
2457:             $this->_subSTATES['ml'] = $this->_margeLeft;
2458:             $this->_subSTATES['mr'] = $this->_margeRight;
2459:             $this->_subSTATES['mt'] = $this->_margeTop;
2460:             $this->_subSTATES['mb'] = $this->_margeBottom;
2461:             $this->_subSTATES['mp'] = $this->_pageMarges;
2462: 
2463:             // new stat for the header
2464:             $this->_pageMarges = array();
2465:             $this->_margeLeft    = $this->_defaultLeft;
2466:             $this->_margeRight   = $this->_defaultRight;
2467:             $this->_margeTop     = $this->_defaultTop;
2468:             $this->_margeBottom  = $this->_defaultBottom;
2469:             $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
2470:             $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
2471:             $this->pdf->setXY($this->_defaultLeft, $this->_defaultTop);
2472: 
2473:             $this->parsingCss->initStyle();
2474:             $this->parsingCss->resetStyle();
2475:             $this->parsingCss->value['width'] = $this->pdf->getW() - $this->_defaultLeft - $this->_defaultRight;
2476:             $this->parsingCss->table = array();
2477: 
2478:             $this->parsingCss->save();
2479:             $this->parsingCss->analyse('page_header_sub', $param);
2480:             $this->parsingCss->setPosition();
2481:             $this->parsingCss->fontSet();
2482:             $this->_setNewPositionForNewLine();
2483:             return true;
2484:         }
2485: 
2486:         /**
2487:          * It is not a real tag. Does not use it directly
2488:          *
2489:          * @param  array $param
2490:          * @return boolean
2491:          */
2492:         protected function _tag_close_PAGE_HEADER_SUB($param)
2493:         {
2494:             if ($this->_isForOneLine) return false;
2495: 
2496:             $this->parsingCss->load();
2497: 
2498:             // restore the stat
2499:             $this->parsingCss->value = $this->_subSTATES['s'];
2500:             $this->parsingCss->table = $this->_subSTATES['t'];
2501:             $this->_pageMarges       = $this->_subSTATES['mp'];
2502:             $this->_margeLeft        = $this->_subSTATES['ml'];
2503:             $this->_margeRight       = $this->_subSTATES['mr'];
2504:             $this->_margeTop         = $this->_subSTATES['mt'];
2505:             $this->_margeBottom      = $this->_subSTATES['mb'];
2506:             $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
2507:             $this->pdf->setbMargin($this->_margeBottom);
2508:             $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
2509:             $this->pdf->setXY($this->_subSTATES['x'], $this->_subSTATES['y']);
2510: 
2511:             $this->parsingCss->fontSet();
2512:             $this->_maxH = 0;
2513: 
2514:             return true;
2515:         }
2516: 
2517:         /**
2518:          * It is not a real tag. Does not use it directly
2519:          *
2520:          * @param  array $param
2521:          * @return boolean
2522:          */
2523:         protected function _tag_open_PAGE_FOOTER_SUB($param)
2524:         {
2525:             if ($this->_isForOneLine) return false;
2526: 
2527:             // save the current stat
2528:             $this->_subSTATES = array();
2529:             $this->_subSTATES['x']    = $this->pdf->getX();
2530:             $this->_subSTATES['y']    = $this->pdf->getY();
2531:             $this->_subSTATES['s']    = $this->parsingCss->value;
2532:             $this->_subSTATES['t']    = $this->parsingCss->table;
2533:             $this->_subSTATES['ml']    = $this->_margeLeft;
2534:             $this->_subSTATES['mr']    = $this->_margeRight;
2535:             $this->_subSTATES['mt']    = $this->_margeTop;
2536:             $this->_subSTATES['mb']    = $this->_margeBottom;
2537:             $this->_subSTATES['mp']    = $this->_pageMarges;
2538: 
2539:             // new stat for the footer
2540:             $this->_pageMarges  = array();
2541:             $this->_margeLeft   = $this->_defaultLeft;
2542:             $this->_margeRight  = $this->_defaultRight;
2543:             $this->_margeTop    = $this->_defaultTop;
2544:             $this->_margeBottom = $this->_defaultBottom;
2545:             $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
2546:             $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
2547:             $this->pdf->setXY($this->_defaultLeft, $this->_defaultTop);
2548: 
2549:             $this->parsingCss->initStyle();
2550:             $this->parsingCss->resetStyle();
2551:             $this->parsingCss->value['width']    = $this->pdf->getW() - $this->_defaultLeft - $this->_defaultRight;
2552:             $this->parsingCss->table                = array();
2553: 
2554:             // we create a sub HTML2PFDF, and we execute on it the content of the footer, to get the height of it
2555:             $sub = null;
2556:             $this->_createSubHTML($sub);
2557:             $sub->parsingHtml->code = $this->parsingHtml->getLevel($this->_parsePos);
2558:             $sub->_makeHTMLcode();
2559:             $this->pdf->setY($this->pdf->getH() - $sub->_maxY - $this->_defaultBottom - 0.01);
2560:             $this->_destroySubHTML($sub);
2561: 
2562:             $this->parsingCss->save();
2563:             $this->parsingCss->analyse('page_footer_sub', $param);
2564:             $this->parsingCss->setPosition();
2565:             $this->parsingCss->fontSet();
2566:             $this->_setNewPositionForNewLine();
2567: 
2568:             return true;
2569:         }
2570: 
2571:         /**
2572:          * It is not a real tag. Does not use it directly
2573:          *
2574:          * @param  array $param
2575:          * @return boolean
2576:          */
2577:         protected function _tag_close_PAGE_FOOTER_SUB($param)
2578:         {
2579:             if ($this->_isForOneLine) return false;
2580: 
2581:             $this->parsingCss->load();
2582: 
2583:             $this->parsingCss->value                = $this->_subSTATES['s'];
2584:             $this->parsingCss->table                = $this->_subSTATES['t'];
2585:             $this->_pageMarges                 = $this->_subSTATES['mp'];
2586:             $this->_margeLeft                = $this->_subSTATES['ml'];
2587:             $this->_margeRight                = $this->_subSTATES['mr'];
2588:             $this->_margeTop                    = $this->_subSTATES['mt'];
2589:             $this->_margeBottom                = $this->_subSTATES['mb'];
2590:             $this->pdf->SetMargins($this->_margeLeft, $this->_margeTop, $this->_margeRight);
2591:             $this->pdf->SetAutoPageBreak(false, $this->_margeBottom);
2592:             $this->pdf->setXY($this->_subSTATES['x'], $this->_subSTATES['y']);
2593: 
2594:             $this->parsingCss->fontSet();
2595:             $this->_maxH = 0;
2596: 
2597:             return true;
2598:         }
2599: 
2600:         /**
2601:          * tag : NOBREAK
2602:          * mode : OPEN
2603:          *
2604:          * @param  array $param
2605:          * @return boolean
2606:          */
2607:         protected function _tag_open_NOBREAK($param)
2608:         {
2609:             if ($this->_isForOneLine) return false;
2610: 
2611:             $this->_maxH = 0;
2612: 
2613:             // create a sub HTML2PDF to execute the content of the tag, to get the dimensions
2614:             $sub = null;
2615:             $this->_createSubHTML($sub);
2616:             $sub->parsingHtml->code = $this->parsingHtml->getLevel($this->_parsePos);
2617:             $sub->_makeHTMLcode();
2618:             $y = $this->pdf->getY();
2619: 
2620:             // if the content does not fit on the page => new page
2621:             if (
2622:                 $sub->_maxY < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin()) &&
2623:                 $y + $sub->_maxY>=($this->pdf->getH() - $this->pdf->getbMargin())
2624:             ) {
2625:                 $this->_setNewPage();
2626:             }
2627: 
2628:             // destroy the sub HTML2PDF
2629:             $this->_destroySubHTML($sub);
2630: 
2631:             return true;
2632:         }
2633: 
2634: 
2635:         /**
2636:          * tag : NOBREAK
2637:          * mode : CLOSE
2638:          *
2639:          * @param  array $param
2640:          * @return boolean
2641:          */
2642:         protected function _tag_close_NOBREAK($param)
2643:         {
2644:             if ($this->_isForOneLine) return false;
2645: 
2646:             $this->_maxH = 0;
2647: 
2648:             return true;
2649:         }
2650: 
2651:         /**
2652:          * tag : DIV
2653:          * mode : OPEN
2654:          *
2655:          * @param  array $param
2656:          * @param  string $other name of tag that used the div tag
2657:          * @return boolean
2658:          */
2659:         protected function _tag_open_DIV($param, $other = 'div')
2660:         {
2661:             if ($this->_isForOneLine) return false;
2662:             if ($this->_debugActif) $this->_DEBUG_add(strtoupper($other), true);
2663: 
2664:             $this->parsingCss->save();
2665:             $this->parsingCss->analyse($other, $param);
2666:             $this->parsingCss->fontSet();
2667: 
2668:             // for fieldset and legend
2669:             if (in_array($other, array('fieldset', 'legend'))) {
2670:                 if (isset($param['moveTop']))  $this->parsingCss->value['margin']['t']    += $param['moveTop'];
2671:                 if (isset($param['moveLeft'])) $this->parsingCss->value['margin']['l']    += $param['moveLeft'];
2672:                 if (isset($param['moveDown'])) $this->parsingCss->value['margin']['b']    += $param['moveDown'];
2673:             }
2674: 
2675:             $alignObject = null;
2676:             if ($this->parsingCss->value['margin-auto']) $alignObject = 'center';
2677: 
2678:             $marge = array();
2679:             $marge['l'] = $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['padding']['l']+0.03;
2680:             $marge['r'] = $this->parsingCss->value['border']['r']['width'] + $this->parsingCss->value['padding']['r']+0.03;
2681:             $marge['t'] = $this->parsingCss->value['border']['t']['width'] + $this->parsingCss->value['padding']['t']+0.03;
2682:             $marge['b'] = $this->parsingCss->value['border']['b']['width'] + $this->parsingCss->value['padding']['b']+0.03;
2683: 
2684:             // extract the content of the div
2685:             $level = $this->parsingHtml->getLevel($this->_parsePos);
2686: 
2687:             // create a sub HTML2PDF to get the dimensions of the content of the div
2688:             $w = 0; $h = 0;
2689:             if (count($level)) {
2690:                 $sub = null;
2691:                 $this->_createSubHTML($sub);
2692:                 $sub->parsingHtml->code = $level;
2693:                 $sub->_makeHTMLcode();
2694:                 $w = $sub->_maxX;
2695:                 $h = $sub->_maxY;
2696:                 $this->_destroySubHTML($sub);
2697:             }
2698:             $wReel = $w;
2699:             $hReel = $h;
2700: 
2701:             $w+= $marge['l']+$marge['r']+0.001;
2702:             $h+= $marge['t']+$marge['b']+0.001;
2703: 
2704:             if ($this->parsingCss->value['overflow']=='hidden') {
2705:                 $overW = max($w, $this->parsingCss->value['width']);
2706:                 $overH = max($h, $this->parsingCss->value['height']);
2707:                 $overflow = true;
2708:                 $this->parsingCss->value['old_maxX'] = $this->_maxX;
2709:                 $this->parsingCss->value['old_maxY'] = $this->_maxY;
2710:                 $this->parsingCss->value['old_maxH'] = $this->_maxH;
2711:                 $this->parsingCss->value['old_overflow'] = $this->_isInOverflow;
2712:                 $this->_isInOverflow = true;
2713:             } else {
2714:                 $overW = null;
2715:                 $overH = null;
2716:                 $overflow = false;
2717:                 $this->parsingCss->value['width']    = max($w, $this->parsingCss->value['width']);
2718:                 $this->parsingCss->value['height']    = max($h, $this->parsingCss->value['height']);
2719:             }
2720: 
2721:             switch($this->parsingCss->value['rotate'])
2722:             {
2723:                 case 90:
2724:                     $tmp = $overH; $overH = $overW; $overW = $tmp;
2725:                     $tmp = $hReel; $hReel = $wReel; $wReel = $tmp;
2726:                     unset($tmp);
2727:                     $w = $this->parsingCss->value['height'];
2728:                     $h = $this->parsingCss->value['width'];
2729:                     $tX =-$h;
2730:                     $tY = 0;
2731:                     break;
2732: 
2733:                 case 180:
2734:                     $w = $this->parsingCss->value['width'];
2735:                     $h = $this->parsingCss->value['height'];
2736:                     $tX = -$w;
2737:                     $tY = -$h;
2738:                     break;
2739: 
2740:                 case 270:
2741:                     $tmp = $overH; $overH = $overW; $overW = $tmp;
2742:                     $tmp = $hReel; $hReel = $wReel; $wReel = $tmp;
2743:                     unset($tmp);
2744:                     $w = $this->parsingCss->value['height'];
2745:                     $h = $this->parsingCss->value['width'];
2746:                     $tX = 0;
2747:                     $tY =-$w;
2748:                     break;
2749: 
2750:                 default:
2751:                     $w = $this->parsingCss->value['width'];
2752:                     $h = $this->parsingCss->value['height'];
2753:                     $tX = 0;
2754:                     $tY = 0;
2755:                     break;
2756:             }
2757: 
2758:             if (!$this->parsingCss->value['position']) {
2759:                 if (
2760:                     $w < ($this->pdf->getW() - $this->pdf->getlMargin()-$this->pdf->getrMargin()) &&
2761:                     $this->pdf->getX() + $w>=($this->pdf->getW() - $this->pdf->getrMargin())
2762:                     )
2763:                     $this->_tag_open_BR(array());
2764: 
2765:                 if (
2766:                         ($h < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin())) &&
2767:                         ($this->pdf->getY() + $h>=($this->pdf->getH() - $this->pdf->getbMargin())) &&
2768:                         !$this->_isInOverflow
2769:                     )
2770:                     $this->_setNewPage();
2771: 
2772:                 $old = $this->parsingCss->getOldValues();
2773:                 $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
2774: 
2775:                 if ($parentWidth>$w) {
2776:                     if ($alignObject=='center')        $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
2777:                     else if ($alignObject=='right')    $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
2778:                 }
2779: 
2780:                 $this->parsingCss->setPosition();
2781:             } else {
2782:                 $old = $this->parsingCss->getOldValues();
2783:                 $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
2784: 
2785:                 if ($parentWidth>$w) {
2786:                     if ($alignObject=='center')        $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
2787:                     else if ($alignObject=='right')    $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
2788:                 }
2789: 
2790:                 $this->parsingCss->setPosition();
2791:                 $this->_saveMax();
2792:                 $this->_maxX = 0;
2793:                 $this->_maxY = 0;
2794:                 $this->_maxH = 0;
2795:                 $this->_maxE = 0;
2796:             }
2797: 
2798:             if ($this->parsingCss->value['rotate']) {
2799:                 $this->pdf->startTransform();
2800:                 $this->pdf->setRotation($this->parsingCss->value['rotate']);
2801:                 $this->pdf->setTranslate($tX, $tY);
2802:             }
2803: 
2804:             $this->_drawRectangle(
2805:                 $this->parsingCss->value['x'],
2806:                 $this->parsingCss->value['y'],
2807:                 $this->parsingCss->value['width'],
2808:                 $this->parsingCss->value['height'],
2809:                 $this->parsingCss->value['border'],
2810:                 $this->parsingCss->value['padding'],
2811:                 0,
2812:                 $this->parsingCss->value['background']
2813:             );
2814: 
2815:             $marge = array();
2816:             $marge['l'] = $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['padding']['l']+0.03;
2817:             $marge['r'] = $this->parsingCss->value['border']['r']['width'] + $this->parsingCss->value['padding']['r']+0.03;
2818:             $marge['t'] = $this->parsingCss->value['border']['t']['width'] + $this->parsingCss->value['padding']['t']+0.03;
2819:             $marge['b'] = $this->parsingCss->value['border']['b']['width'] + $this->parsingCss->value['padding']['b']+0.03;
2820: 
2821:             $this->parsingCss->value['width'] -= $marge['l']+$marge['r'];
2822:             $this->parsingCss->value['height']-= $marge['t']+$marge['b'];
2823: 
2824:             $xCorr = 0;
2825:             $yCorr = 0;
2826:             if (!$this->_subPart && !$this->_isSubPart) {
2827:                 switch($this->parsingCss->value['text-align'])
2828:                 {
2829:                     case 'right':
2830:                         $xCorr = ($this->parsingCss->value['width']-$wReel);
2831:                         break;
2832:                     case 'center':
2833:                         $xCorr = ($this->parsingCss->value['width']-$wReel)*0.5;
2834:                         break;
2835:                 }
2836:                 if ($xCorr>0) $xCorr=0;
2837:                 switch($this->parsingCss->value['vertical-align'])
2838:                 {
2839:                     case 'bottom':
2840:                         $yCorr = ($this->parsingCss->value['height']-$hReel);
2841:                         break;
2842:                     case 'middle':
2843:                         $yCorr = ($this->parsingCss->value['height']-$hReel)*0.5;
2844:                         break;
2845:                 }
2846:             }
2847: 
2848:             if ($overflow) {
2849:                 $overW-= $marge['l']+$marge['r'];
2850:                 $overH-= $marge['t']+$marge['b'];
2851:                 $this->pdf->clippingPathStart(
2852:                     $this->parsingCss->value['x']+$marge['l'],
2853:                     $this->parsingCss->value['y']+$marge['t'],
2854:                     $this->parsingCss->value['width'],
2855:                     $this->parsingCss->value['height']
2856:                 );
2857: 
2858:                 $this->parsingCss->value['x']+= $xCorr;
2859: 
2860:                 // marges from the dimension of the content
2861:                 $mL = $this->parsingCss->value['x']+$marge['l'];
2862:                 $mR = $this->pdf->getW() - $mL - $overW;
2863:             } else {
2864:                 // marges from the dimension of the div
2865:                 $mL = $this->parsingCss->value['x']+$marge['l'];
2866:                 $mR = $this->pdf->getW() - $mL - $this->parsingCss->value['width'];
2867:             }
2868: 
2869:             $x = $this->parsingCss->value['x']+$marge['l'];
2870:             $y = $this->parsingCss->value['y']+$marge['t']+$yCorr;
2871:             $this->_saveMargin($mL, 0, $mR);
2872:             $this->pdf->setXY($x, $y);
2873: 
2874:             $this->_setNewPositionForNewLine();
2875: 
2876:             return true;
2877:         }
2878: 
2879:         /**
2880:          * tag : BLOCKQUOTE
2881:          * mode : OPEN
2882:          *
2883:          * @param  array $param
2884:          * @return boolean
2885:          */
2886:         protected function _tag_open_BLOCKQUOTE($param)
2887:         {
2888:             return $this->_tag_open_DIV($param, 'blockquote');
2889:         }
2890: 
2891:         /**
2892:          * tag : LEGEND
2893:          * mode : OPEN
2894:          *
2895:          * @param  array $param
2896:          * @return boolean
2897:          */
2898:         protected function _tag_open_LEGEND($param)
2899:         {
2900:             return $this->_tag_open_DIV($param, 'legend');
2901:         }
2902: 
2903:         /**
2904:          * tag : FIELDSET
2905:          * mode : OPEN
2906:          *
2907:          * @author Pavel Kochman
2908:          * @param  array $param
2909:          * @return boolean
2910:          */
2911:         protected function _tag_open_FIELDSET($param)
2912:         {
2913: 
2914:             $this->parsingCss->save();
2915:             $this->parsingCss->analyse('fieldset', $param);
2916: 
2917:             // get height of LEGEND element and make fieldset corrections
2918:             for ($tempPos = $this->_parsePos + 1; $tempPos<count($this->parsingHtml->code); $tempPos++) {
2919:                 $action = $this->parsingHtml->code[$tempPos];
2920:                 if ($action['name'] == 'fieldset') break;
2921:                 if ($action['name'] == 'legend' && !$action['close']) {
2922:                     $legendOpenPos = $tempPos;
2923: 
2924:                     $sub = null;
2925:                     $this->_createSubHTML($sub);
2926:                     $sub->parsingHtml->code = $this->parsingHtml->getLevel($tempPos - 1);
2927: 
2928:                     $res = null;
2929:                     for ($sub->_parsePos = 0; $sub->_parsePos<count($sub->parsingHtml->code); $sub->_parsePos++) {
2930:                         $action = $sub->parsingHtml->code[$sub->_parsePos];
2931:                         $sub->_executeAction($action);
2932: 
2933:                         if ($action['name'] == 'legend' && $action['close'])
2934:                             break;
2935:                     }
2936: 
2937:                     $legendH = $sub->_maxY;
2938:                     $this->_destroySubHTML($sub);
2939: 
2940:                     $move = $this->parsingCss->value['padding']['t'] + $this->parsingCss->value['border']['t']['width'] + 0.03;
2941: 
2942:                     $param['moveTop'] = $legendH / 2;
2943: 
2944:                     $this->parsingHtml->code[$legendOpenPos]['param']['moveTop'] = - ($legendH / 2 + $move);
2945:                     $this->parsingHtml->code[$legendOpenPos]['param']['moveLeft'] = 2 - $this->parsingCss->value['border']['l']['width'] - $this->parsingCss->value['padding']['l'];
2946:                     $this->parsingHtml->code[$legendOpenPos]['param']['moveDown'] = $move;
2947:                     break;
2948:                 }
2949:             }
2950:             $this->parsingCss->load();
2951: 
2952:             return $this->_tag_open_DIV($param, 'fieldset');
2953:         }
2954: 
2955:         /**
2956:          * tag : DIV
2957:          * mode : CLOSE
2958:          *
2959:          * @param  array $param
2960:          * @param  string $other name of tag that used the div tag
2961:          * @return boolean
2962:          */
2963:         protected function _tag_close_DIV($param, $other='div')
2964:         {
2965:             if ($this->_isForOneLine) return false;
2966: 
2967:             if ($this->parsingCss->value['overflow']=='hidden') {
2968:                 $this->_maxX = $this->parsingCss->value['old_maxX'];
2969:                 $this->_maxY = $this->parsingCss->value['old_maxY'];
2970:                 $this->_maxH = $this->parsingCss->value['old_maxH'];
2971:                 $this->_isInOverflow = $this->parsingCss->value['old_overflow'];
2972:                 $this->pdf->clippingPathStop();
2973:             }
2974: 
2975:             if ($this->parsingCss->value['rotate'])
2976:                 $this->pdf->stopTransform();
2977: 
2978:             $marge = array();
2979:             $marge['l'] = $this->parsingCss->value['border']['l']['width'] + $this->parsingCss->value['padding']['l']+0.03;
2980:             $marge['r'] = $this->parsingCss->value['border']['r']['width'] + $this->parsingCss->value['padding']['r']+0.03;
2981:             $marge['t'] = $this->parsingCss->value['border']['t']['width'] + $this->parsingCss->value['padding']['t']+0.03;
2982:             $marge['b'] = $this->parsingCss->value['border']['b']['width'] + $this->parsingCss->value['padding']['b']+0.03;
2983: 
2984:             $x = $this->parsingCss->value['x'];
2985:             $y = $this->parsingCss->value['y'];
2986:             $w = $this->parsingCss->value['width']+$marge['l']+$marge['r']+$this->parsingCss->value['margin']['r'];
2987:             $h = $this->parsingCss->value['height']+$marge['t']+$marge['b']+$this->parsingCss->value['margin']['b'];
2988: 
2989:             switch($this->parsingCss->value['rotate'])
2990:             {
2991:                 case 90:
2992:                     $t = $w; $w = $h; $h = $t;
2993:                     break;
2994: 
2995:                 case 270:
2996:                     $t = $w; $w = $h; $h = $t;
2997:                     break;
2998: 
2999:                 default:
3000:                     break;
3001:             }
3002: 
3003: 
3004:             if ($this->parsingCss->value['position']!='absolute') {
3005:                 $this->pdf->setXY($x+$w, $y);
3006: 
3007:                 $this->_maxX = max($this->_maxX, $x+$w);
3008:                 $this->_maxY = max($this->_maxY, $y+$h);
3009:                 $this->_maxH = max($this->_maxH, $h);
3010:             } else {
3011:                 $this->pdf->setXY($this->parsingCss->value['xc'], $this->parsingCss->value['yc']);
3012: 
3013:                 $this->_loadMax();
3014:             }
3015: 
3016:             $block = ($this->parsingCss->value['display']!='inline' && $this->parsingCss->value['position']!='absolute');
3017: 
3018:             $this->parsingCss->load();
3019:             $this->parsingCss->fontSet();
3020:             $this->_loadMargin();
3021: 
3022:             if ($block) $this->_tag_open_BR(array());
3023:             if ($this->_debugActif) $this->_DEBUG_add(strtoupper($other), false);
3024: 
3025:             return true;
3026:         }
3027: 
3028:         /**
3029:          * tag : BLOCKQUOTE
3030:          * mode : CLOSE
3031:          *
3032:          * @param  array $param
3033:          * @return boolean
3034:          */
3035:         protected function _tag_close_BLOCKQUOTE($param)
3036:         {
3037:             return $this->_tag_close_DIV($param, 'blockquote');
3038:         }
3039: 
3040:         /**
3041:          * tag : FIELDSET
3042:          * mode : CLOSE
3043:          *
3044:          * @param  array $param
3045:          * @return boolean
3046:          */
3047:         protected function _tag_close_FIELDSET($param)
3048:         {
3049:             return $this->_tag_close_DIV($param, 'fieldset');
3050:         }
3051: 
3052:         /**
3053:          * tag : LEGEND
3054:          * mode : CLOSE
3055:          *
3056:          * @param  array $param
3057:          * @return boolean
3058:          */
3059:         protected function _tag_close_LEGEND($param)
3060:         {
3061:             return $this->_tag_close_DIV($param, 'legend');
3062:         }
3063: 
3064:         /**
3065:          * tag : BARCODE
3066:          * mode : OPEN
3067:          *
3068:          * @param  array $param
3069:          * @return boolean
3070:          */
3071:         protected function _tag_open_BARCODE($param)
3072:         {
3073:             // for  compatibility with old versions < 3.29
3074:             $lstBarcode = array();
3075:             $lstBarcode['UPC_A']  =    'UPCA';
3076:             $lstBarcode['CODE39'] =    'C39';
3077: 
3078:             if (!isset($param['type']))     $param['type'] = 'C39';
3079:             if (!isset($param['value']))    $param['value']    = 0;
3080:             if (!isset($param['label']))    $param['label']    = 'label';
3081:             if (!isset($param['style']['color'])) $param['style']['color'] = '#000000';
3082: 
3083:             if ($this->_testIsDeprecated && (isset($param['bar_h']) || isset($param['bar_w'])))
3084:                 throw new HTML2PDF_exception(9, array('BARCODE', 'bar_h, bar_w'));
3085: 
3086:             $param['type'] = strtoupper($param['type']);
3087:             if (isset($lstBarcode[$param['type']])) $param['type'] = $lstBarcode[$param['type']];
3088: 
3089:             $this->parsingCss->save();
3090:             $this->parsingCss->analyse('barcode', $param);
3091:             $this->parsingCss->setPosition();
3092:             $this->parsingCss->fontSet();
3093: 
3094:             $x = $this->pdf->getX();
3095:             $y = $this->pdf->getY();
3096:             $w = $this->parsingCss->value['width'];    if (!$w) $w = $this->parsingCss->ConvertToMM('50mm');
3097:             $h = $this->parsingCss->value['height'];    if (!$h) $h = $this->parsingCss->ConvertToMM('10mm');
3098:             $txt = ($param['label']!=='none' ? $this->parsingCss->value['font-size'] : false);
3099:             $c = $this->parsingCss->value['color'];
3100:             $infos = $this->pdf->myBarcode($param['value'], $param['type'], $x, $y, $w, $h, $txt, $c);
3101: 
3102:             $this->_maxX = max($this->_maxX, $x+$infos[0]);
3103:             $this->_maxY = max($this->_maxY, $y+$infos[1]);
3104:             $this->_maxH = max($this->_maxH, $infos[1]);
3105:             $this->_maxE++;
3106: 
3107:             $this->pdf->setXY($x+$infos[0], $y);
3108: 
3109:             $this->parsingCss->load();
3110:             $this->parsingCss->fontSet();
3111: 
3112:             return true;
3113:         }
3114: 
3115:         /**
3116:          * tag : BARCODE
3117:          * mode : CLOSE
3118:          *
3119:          * @param  array $param
3120:          * @return boolean
3121:          */
3122:         protected function _tag_close_BARCODE($param)
3123:         {
3124:             // there is nothing to do here
3125: 
3126:             return true;
3127:         }
3128: 
3129:         /**
3130:          * tag : QRCODE
3131:          * mode : OPEN
3132:          *
3133:          * @param  array $param
3134:          * @return boolean
3135:          */
3136:         protected function _tag_open_QRCODE($param)
3137:         {
3138:             if ($this->_testIsDeprecated && (isset($param['size']) || isset($param['noborder'])))
3139:                 throw new HTML2PDF_exception(9, array('QRCODE', 'size, noborder'));
3140: 
3141:             if ($this->_debugActif) $this->_DEBUG_add('QRCODE');
3142: 
3143:             if (!isset($param['value']))                     $param['value'] = '';
3144:             if (!isset($param['ec']))                        $param['ec'] = 'H';
3145:             if (!isset($param['style']['color']))            $param['style']['color'] = '#000000';
3146:             if (!isset($param['style']['background-color'])) $param['style']['background-color'] = '#FFFFFF';
3147:             if (isset($param['style']['border'])) {
3148:                 $borders = $param['style']['border']!='none';
3149:                 unset($param['style']['border']);
3150:             } else {
3151:                 $borders = true;
3152:             }
3153: 
3154:             if ($param['value']==='') return true;
3155:             if (!in_array($param['ec'], array('L', 'M', 'Q', 'H'))) $param['ec'] = 'H';
3156: 
3157:             $this->parsingCss->save();
3158:             $this->parsingCss->analyse('qrcode', $param);
3159:             $this->parsingCss->setPosition();
3160:             $this->parsingCss->fontSet();
3161: 
3162:             $x = $this->pdf->getX();
3163:             $y = $this->pdf->getY();
3164:             $w = $this->parsingCss->value['width'];
3165:             $h = $this->parsingCss->value['height'];
3166:             $size = max($w, $h); if (!$size) $size = $this->parsingCss->ConvertToMM('50mm');
3167: 
3168:             $style = array(
3169:                     'fgcolor' => $this->parsingCss->value['color'],
3170:                     'bgcolor' => $this->parsingCss->value['background']['color'],
3171:                 );
3172: 
3173:             if ($borders) {
3174:                 $style['border'] = true;
3175:                 $style['padding'] = 'auto';
3176:             } else {
3177:                 $style['border'] = false;
3178:                 $style['padding'] = 0;
3179:             }
3180: 
3181:             if (!$this->_subPart && !$this->_isSubPart) {
3182:                 $this->pdf->write2DBarcode($param['value'], 'QRCODE,'.$param['ec'], $x, $y, $size, $size, $style);
3183:             }
3184: 
3185:             $this->_maxX = max($this->_maxX, $x+$size);
3186:             $this->_maxY = max($this->_maxY, $y+$size);
3187:             $this->_maxH = max($this->_maxH, $size);
3188:             $this->_maxE++;
3189: 
3190:             $this->pdf->setX($x+$size);
3191: 
3192:             $this->parsingCss->load();
3193:             $this->parsingCss->fontSet();
3194: 
3195:             return true;
3196:         }
3197: 
3198:         /**
3199:          * tag : QRCODE
3200:          * mode : CLOSE
3201:          *
3202:          * @param  array $param
3203:          * @return boolean
3204:          */
3205:         protected function _tag_close_QRCODE($param)
3206:         {
3207:             // there is nothing to do here
3208: 
3209:             return true;
3210:         }
3211: 
3212:         /**
3213:          * tag : BOOKMARK
3214:          * mode : OPEN
3215:          *
3216:          * @param  array $param
3217:          * @return boolean
3218:          */
3219:         protected function _tag_open_BOOKMARK($param)
3220:         {
3221:             $titre = isset($param['title']) ? trim($param['title']) : '';
3222:             $level = isset($param['level']) ? floor($param['level']) : 0;
3223: 
3224:             if ($level<0) $level = 0;
3225:             if ($titre) $this->pdf->Bookmark($titre, $level, -1);
3226: 
3227:             return true;
3228:         }
3229: 
3230:         /**
3231:          * tag : BOOKMARK
3232:          * mode : CLOSE
3233:          *
3234:          * @param  array $param
3235:          * @return boolean
3236:          */
3237:         protected function _tag_close_BOOKMARK($param)
3238:         {
3239:             // there is nothing to do here
3240: 
3241:             return true;
3242:         }
3243: 
3244:         /**
3245:          * this is not a real TAG, it is just to write texts
3246:          *
3247:          * @param  array $param
3248:          * @return boolean
3249:          */
3250:         protected function _tag_open_WRITE($param)
3251:         {
3252:             $fill = ($this->parsingCss->value['background']['color']!==null && $this->parsingCss->value['background']['image']===null);
3253:             if (in_array($this->parsingCss->value['id_tag'], array('fieldset', 'legend', 'div', 'table', 'tr', 'td', 'th'))) {
3254:                 $fill = false;
3255:             }
3256: 
3257:             // get the text to write
3258:             $txt = $param['txt'];
3259: 
3260:             if ($this->_isAfterFloat) {
3261:                 $txt = ltrim($txt);
3262:                 $this->_isAfterFloat = false;
3263:             }
3264: 
3265:             $txt = str_replace('[[page_nb]]', $this->pdf->getMyAliasNbPages(), $txt);
3266:             $txt = str_replace('[[page_cu]]', $this->pdf->getMyNumPage($this->_page), $txt);
3267: 
3268:             if ($this->parsingCss->value['text-transform']!='none') {
3269:                 if ($this->parsingCss->value['text-transform']=='capitalize')
3270:                     $txt = ucwords($txt);
3271:                 else if ($this->parsingCss->value['text-transform']=='uppercase')
3272:                     $txt = strtoupper($txt);
3273:                 else if ($this->parsingCss->value['text-transform']=='lowercase')
3274:                     $txt = strtolower($txt);
3275:             }
3276: 
3277:             // size of the text
3278:             $h  = 1.08*$this->parsingCss->value['font-size'];
3279:             $dh = $h*$this->parsingCss->value['mini-decal'];
3280:             $lh = $this->parsingCss->getLineHeight();
3281: 
3282:             // identify the align
3283:             $align = 'L';
3284:             if ($this->parsingCss->value['text-align']=='li_right') {
3285:                 $w = $this->parsingCss->value['width'];
3286:                 $align = 'R';
3287:             }
3288: 
3289:             // calculate the width of each words, and of all the sentence
3290:             $w = 0;
3291:             $words = explode(' ', $txt);
3292:             foreach ($words as $k => $word) {
3293:                 $words[$k] = array($word, $this->pdf->GetStringWidth($word));
3294:                 $w+= $words[$k][1];
3295:             }
3296:             $space = $this->pdf->GetStringWidth(' ');
3297:             $w+= $space*(count($words)-1);
3298: 
3299:             // position in the text
3300:             $currPos = 0;
3301: 
3302:             // the bigger width of the text, after automatic break line
3303:             $maxX = 0;
3304: 
3305:             // position of the text
3306:             $x = $this->pdf->getX();
3307:             $y = $this->pdf->getY();
3308:             $dy = $this->_getElementY($lh);
3309: 
3310:             // margins
3311:             list($left, $right) = $this->_getMargins($y);
3312: 
3313:             // number of lines after automatic break line
3314:             $nb = 0;
3315: 
3316:             // while we have words, and the text does not fit on the line => we cut the sentence
3317:             while ($x+$w>$right && $x<$right+$space && count($words)) {
3318:                 // adding words 1 by 1 to fit on the line
3319:                 $i=0;
3320:                 $old = array('', 0);
3321:                 $str = $words[0];
3322:                 $add = false;
3323:                 while (($x+$str[1])<$right) {
3324:                     $i++;
3325:                     $add = true;
3326: 
3327:                     array_shift($words);
3328:                     $old = $str;
3329: 
3330:                     if (!count($words)) break;
3331:                     $str[0].= ' '.$words[0][0];
3332:                     $str[1]+= $space+$words[0][1];
3333:                 }
3334:                 $str = $old;
3335: 
3336:                 // if  nothing fit on the line, and if the first word does not fit on the line => the word is too long, we put it
3337:                 if ($i==0 && (($left+$words[0][1])>=$right)) {
3338:                     $str = $words[0];
3339:                     array_shift($words);
3340:                     $i++;
3341:                     $add = true;
3342:                 }
3343:                 $currPos+= ($currPos ? 1 : 0)+strlen($str[0]);
3344: 
3345:                 // write the extract sentence that fit on the page
3346:                 $wc = ($align=='L' ? $str[1] : $this->parsingCss->value['width']);
3347:                 if ($right - $left<$wc) $wc = $right - $left;
3348: 
3349:                 if (strlen($str[0])) {
3350:                     $this->pdf->setXY($this->pdf->getX(), $y+$dh+$dy);
3351:                     $this->pdf->Cell($wc, $h, $str[0], 0, 0, $align, $fill, $this->_isInLink);
3352:                     $this->pdf->setXY($this->pdf->getX(), $y);
3353:                 }
3354:                 $this->_maxH = max($this->_maxH, $lh);
3355: 
3356:                 // max width
3357:                 $maxX = max($maxX, $this->pdf->getX());
3358: 
3359:                 // new position and new width for the "while"
3360:                 $w-= $str[1];
3361:                 $y = $this->pdf->getY();
3362:                 $x = $this->pdf->getX();
3363:                 $dy = $this->_getElementY($lh);
3364: 
3365:                 // if we have again words to write
3366:                 if (count($words)) {
3367:                     // remove the space at the end
3368:                     if ($add) $w-= $space;
3369: 
3370:                     // if we don't add any word, and if the first word is empty => useless space to skip
3371:                     if (!$add && $words[0][0]==='') {
3372:                         array_shift($words);
3373:                     }
3374: 
3375:                     // if it is just to calculate for one line => adding the number of words
3376:                     if ($this->_isForOneLine) {
3377:                         $this->_maxE+= $i;
3378:                         $this->_maxX = max($this->_maxX, $maxX);
3379:                         return null;
3380:                     }
3381: 
3382:                     // automatic line break
3383:                     $this->_tag_open_BR(array('style' => ''), $currPos);
3384: 
3385:                     // new position
3386:                     $y = $this->pdf->getY();
3387:                     $x = $this->pdf->getX();
3388:                     $dy = $this->_getElementY($lh);
3389: 
3390:                     // if the next line does  not fit on the page => new page
3391:                     if ($y + $h>=$this->pdf->getH() - $this->pdf->getbMargin()) {
3392:                         if (!$this->_isInOverflow && !$this->_isInFooter) {
3393:                             $this->_setNewPage(null, '', null, $currPos);
3394:                             $y = $this->pdf->getY();
3395:                             $x = $this->pdf->getX();
3396:                             $dy = $this->_getElementY($lh);
3397:                         }
3398:                     }
3399: 
3400:                     // if more than 10000 line => error
3401:                     $nb++;
3402:                     if ($nb>10000) {
3403:                         $txt = ''; foreach ($words as $k => $word) $txt.= ($k ? ' ' : '').$word[0];
3404:                         throw new HTML2PDF_exception(2, array($txt, $right-$left, $w));
3405:                     }
3406: 
3407:                     // new margins for the new line
3408:                     list($left, $right) = $this->_getMargins($y);
3409:                 }
3410:             }
3411: 
3412:             // if we have words after automatic cut, it is because they fit on the line => we write the text
3413:             if (count($words)) {
3414:                 $txt = ''; foreach ($words as $k => $word) $txt.= ($k ? ' ' : '').$word[0];
3415:                 $w+= $this->pdf->getWordSpacing()*(count($words));
3416:                 $this->pdf->setXY($this->pdf->getX(), $y+$dh+$dy);
3417:                 $this->pdf->Cell(($align=='L' ? $w : $this->parsingCss->value['width']), $h, $txt, 0, 0, $align, $fill, $this->_isInLink);
3418:                 $this->pdf->setXY($this->pdf->getX(), $y);
3419:                 $this->_maxH = max($this->_maxH, $lh);
3420:                 $this->_maxE+= count($words);
3421:             }
3422: 
3423:             $maxX = max($maxX, $this->pdf->getX());
3424:             $maxY = $this->pdf->getY()+$h;
3425: 
3426:             $this->_maxX = max($this->_maxX, $maxX);
3427:             $this->_maxY = max($this->_maxY, $maxY);
3428: 
3429:             return true;
3430:         }
3431: 
3432:         /**
3433:          * tag : BR
3434:          * mode : OPEN
3435:          *
3436:          * @param  array   $param
3437:          * @param  integer $curr real position in the html parseur (if break line in the write of a text)
3438:          * @return boolean
3439:          */
3440:         protected function _tag_open_BR($param, $curr = null)
3441:         {
3442:             if ($this->_isForOneLine) return false;
3443: 
3444:             $h = max($this->_maxH, $this->parsingCss->getLineHeight());
3445: 
3446:             if ($this->_maxH==0) $this->_maxY = max($this->_maxY, $this->pdf->getY()+$h);
3447: 
3448:             $this->_makeBreakLine($h, $curr);
3449: 
3450:             $this->_maxH = 0;
3451:             $this->_maxE = 0;
3452: 
3453:             return true;
3454:         }
3455: 
3456:         /**
3457:          * tag : HR
3458:          * mode : OPEN
3459:          *
3460:          * @param  array $param
3461:          * @return boolean
3462:          */
3463:         protected function _tag_open_HR($param)
3464:         {
3465:             if ($this->_isForOneLine) return false;
3466:             $oldAlign = $this->parsingCss->value['text-align'];
3467:             $this->parsingCss->value['text-align'] = 'left';
3468: 
3469:             if ($this->_maxH) $this->_tag_open_BR($param);
3470: 
3471:             $fontSize = $this->parsingCss->value['font-size'];
3472:             $this->parsingCss->value['font-size']=$fontSize*0.5; $this->_tag_open_BR($param);
3473:             $this->parsingCss->value['font-size']=0;
3474: 
3475:             $param['style']['width'] = '100%';
3476: 
3477:             $this->parsingCss->save();
3478:             $this->parsingCss->value['height']=$this->parsingCss->ConvertToMM('1mm');
3479: 
3480:             $this->parsingCss->analyse('hr', $param);
3481:             $this->parsingCss->setPosition();
3482:             $this->parsingCss->fontSet();
3483: 
3484:             $h = $this->parsingCss->value['height'];
3485:             if ($h)    $h-= $this->parsingCss->value['border']['t']['width']+$this->parsingCss->value['border']['b']['width'];
3486:             if ($h<=0) $h = $this->parsingCss->value['border']['t']['width']+$this->parsingCss->value['border']['b']['width'];
3487: 
3488:             $this->_drawRectangle($this->pdf->getX(), $this->pdf->getY(), $this->parsingCss->value['width'], $h, $this->parsingCss->value['border'], 0, 0, $this->parsingCss->value['background']);
3489:             $this->_maxH = $h;
3490: 
3491:             $this->parsingCss->load();
3492:             $this->parsingCss->fontSet();
3493: 
3494:             $this->_tag_open_BR($param);
3495: 
3496:             $this->parsingCss->value['font-size']=$fontSize*0.5; $this->_tag_open_BR($param);
3497:             $this->parsingCss->value['font-size']=$fontSize;
3498: 
3499:             $this->parsingCss->value['text-align'] = $oldAlign;
3500:             $this->_setNewPositionForNewLine();
3501: 
3502:             return true;
3503:         }
3504: 
3505:         /**
3506:          * tag : B
3507:          * mode : OPEN
3508:          *
3509:          * @param  array $param
3510:          * @param  string $other
3511:          * @return boolean
3512:          */
3513:         protected function _tag_open_B($param, $other = 'b')
3514:         {
3515:             $this->parsingCss->save();
3516:             $this->parsingCss->value['font-bold'] = true;
3517:             $this->parsingCss->analyse($other, $param);
3518:             $this->parsingCss->setPosition();
3519:             $this->parsingCss->fontSet();
3520: 
3521:             return true;
3522:         }
3523: 
3524:         /**
3525:          * tag : STRONG
3526:          * mode : OPEN
3527:          *
3528:          * @param  array $param
3529:          * @return boolean
3530:          */
3531:         protected function _tag_open_STRONG($param)
3532:         {
3533:             return $this->_tag_open_B($param, 'strong');
3534:         }
3535: 
3536:         /**
3537:          * tag : B
3538:          * mode : CLOSE
3539:          *
3540:          * @param    array $param
3541:          * @return boolean
3542:          */
3543:         protected function _tag_close_B($param)
3544:         {
3545:             $this->parsingCss->load();
3546:             $this->parsingCss->fontSet();
3547: 
3548:             return true;
3549:         }
3550: 
3551:         /**
3552:          * tag : STRONG
3553:          * mode : CLOSE
3554:          *
3555:          * @param  array $param
3556:          * @return boolean
3557:          */
3558:         protected function _tag_close_STRONG($param)
3559:         {
3560:             return $this->_tag_close_B($param);
3561:         }
3562: 
3563:         /**
3564:          * tag : I
3565:          * mode : OPEN
3566:          *
3567:          * @param  array $param
3568:          * @param  string $other
3569:          * @return boolean
3570:          */
3571:         protected function _tag_open_I($param, $other = 'i')
3572:         {
3573:             $this->parsingCss->save();
3574:             $this->parsingCss->value['font-italic'] = true;
3575:             $this->parsingCss->analyse($other, $param);
3576:             $this->parsingCss->setPosition();
3577:             $this->parsingCss->fontSet();
3578: 
3579:             return true;
3580:         }
3581: 
3582:         /**
3583:          * tag : ADDRESS
3584:          * mode : OPEN
3585:          *
3586:          * @param  array $param
3587:          * @return boolean
3588:          */
3589:         protected function _tag_open_ADDRESS($param)
3590:         {
3591:             return $this->_tag_open_I($param, 'address');
3592:         }
3593: 
3594:         /**
3595:          * tag : CITE
3596:          * mode : OPEN
3597:          *
3598:          * @param  array $param
3599:          * @return boolean
3600:          */
3601:         protected function _tag_open_CITE($param)
3602:         {
3603:             return $this->_tag_open_I($param, 'cite');
3604:         }
3605: 
3606:         /**
3607:          * tag : EM
3608:          * mode : OPEN
3609:          *
3610:          * @param  array $param
3611:          * @return boolean
3612:          */
3613:         protected function _tag_open_EM($param)
3614:         {
3615:             return $this->_tag_open_I($param, 'em');
3616:         }
3617: 
3618:         /**
3619:          * tag : SAMP
3620:          * mode : OPEN
3621:          *
3622:          * @param  array $param
3623:          * @return boolean
3624:          */
3625:         protected function _tag_open_SAMP($param)
3626:         {
3627:             return $this->_tag_open_I($param, 'samp');
3628:         }
3629: 
3630:         /**
3631:          * tag : I
3632:          * mode : CLOSE
3633:          *
3634:          * @param  array $param
3635:          * @return boolean
3636:          */
3637:         protected function _tag_close_I($param)
3638:         {
3639:             $this->parsingCss->load();
3640:             $this->parsingCss->fontSet();
3641: 
3642:             return true;
3643:         }
3644: 
3645:         /**
3646:          * tag : ADDRESS
3647:          * mode : CLOSE
3648:          *
3649:          * @param  array $param
3650:          * @return boolean
3651:          */
3652:         protected function _tag_close_ADDRESS($param)
3653:         {
3654:             return $this->_tag_close_I($param);
3655:         }
3656: 
3657:         /**
3658:          * tag : CITE
3659:          * mode : CLOSE
3660:          *
3661:          * @param  array $param
3662:          * @return boolean
3663:          */
3664:         protected function _tag_close_CITE($param)
3665:         {
3666:             return $this->_tag_close_I($param);
3667:         }
3668: 
3669:         /**
3670:          * tag : EM
3671:          * mode : CLOSE
3672:          *
3673:          * @param  array $param
3674:          * @return boolean
3675:          */
3676:         protected function _tag_close_EM($param)
3677:         {
3678:             return $this->_tag_close_I($param);
3679:         }
3680: 
3681:         /**
3682:          * tag : SAMP
3683:          * mode : CLOSE
3684:          *
3685:          * @param  array $param
3686:          * @return boolean
3687:          */
3688:         protected function _tag_close_SAMP($param)
3689:         {
3690:             return $this->_tag_close_I($param);
3691:         }
3692: 
3693:         /**
3694:          * tag : S
3695:          * mode : OPEN
3696:          *
3697:          * @param  array $param
3698:          * @param  string $other
3699:          * @return boolean
3700:          */
3701:         protected function _tag_open_S($param, $other = 's')
3702:         {
3703:             $this->parsingCss->save();
3704:             $this->parsingCss->value['font-linethrough'] = true;
3705:             $this->parsingCss->analyse($other, $param);
3706:             $this->parsingCss->setPosition();
3707:             $this->parsingCss->fontSet();
3708: 
3709:             return true;
3710:         }
3711: 
3712:         /**
3713:          * tag : DEL
3714:          * mode : OPEN
3715:          *
3716:          * @param  array $param
3717:          * @return boolean
3718:          */
3719:         protected function _tag_open_DEL($param)
3720:         {
3721:             return $this->_tag_open_S($param, 'del');
3722:         }
3723: 
3724:         /**
3725:          * tag : S
3726:          * mode : CLOSE
3727:          *
3728:          * @param    array $param
3729:          * @return boolean
3730:          */
3731:         protected function _tag_close_S($param)
3732:         {
3733:             $this->parsingCss->load();
3734:             $this->parsingCss->fontSet();
3735: 
3736:             return true;
3737:         }
3738: 
3739:         /**
3740:          * tag : DEL
3741:          * mode : CLOSE
3742:          *
3743:          * @param  array $param
3744:          * @return boolean
3745:          */
3746:         protected function _tag_close_DEL($param)
3747:         {
3748:             return $this->_tag_close_S($param);
3749:         }
3750: 
3751:         /**
3752:          * tag : U
3753:          * mode : OPEN
3754:          *
3755:          * @param  array $param
3756:          * @param  string $other
3757:          * @return boolean
3758:          */
3759:         protected function _tag_open_U($param, $other='u')
3760:         {
3761:             $this->parsingCss->save();
3762:             $this->parsingCss->value['font-underline'] = true;
3763:             $this->parsingCss->analyse($other, $param);
3764:             $this->parsingCss->setPosition();
3765:             $this->parsingCss->fontSet();
3766: 
3767:             return true;
3768:         }
3769: 
3770:         /**
3771:          * tag : INS
3772:          * mode : OPEN
3773:          *
3774:          * @param  array $param
3775:          * @return boolean
3776:          */
3777:         protected function _tag_open_INS($param)
3778:         {
3779:             return $this->_tag_open_U($param, 'ins');
3780:         }
3781: 
3782:         /**
3783:          * tag : U
3784:          * mode : CLOSE
3785:          *
3786:          * @param    array $param
3787:          * @return boolean
3788:          */
3789:         protected function _tag_close_U($param)
3790:         {
3791:             $this->parsingCss->load();
3792:             $this->parsingCss->fontSet();
3793: 
3794:             return true;
3795:         }
3796: 
3797:         /**
3798:          * tag : INS
3799:          * mode : CLOSE
3800:          *
3801:          * @param  array $param
3802:          * @return boolean
3803:          */
3804:         protected function _tag_close_INS($param)
3805:         {
3806:             return $this->_tag_close_U($param);
3807:         }
3808: 
3809:         /**
3810:          * tag : A
3811:          * mode : OPEN
3812:          *
3813:          * @param  array $param
3814:          * @return boolean
3815:          */
3816:         protected function _tag_open_A($param)
3817:         {
3818:             $this->_isInLink = str_replace('&amp;', '&', isset($param['href']) ? $param['href'] : '');
3819: 
3820:             if (isset($param['name'])) {
3821:                 $name =     $param['name'];
3822:                 if (!isset($this->_lstAnchor[$name])) $this->_lstAnchor[$name] = array($this->pdf->AddLink(), false);
3823: 
3824:                 if (!$this->_lstAnchor[$name][1]) {
3825:                     $this->_lstAnchor[$name][1] = true;
3826:                     $this->pdf->SetLink($this->_lstAnchor[$name][0], -1, -1);
3827:                 }
3828:             }
3829: 
3830:             if (preg_match('/^#([^#]+)$/isU', $this->_isInLink, $match)) {
3831:                 $name = $match[1];
3832:                 if (!isset($this->_lstAnchor[$name])) $this->_lstAnchor[$name] = array($this->pdf->AddLink(), false);
3833: 
3834:                 $this->_isInLink = $this->_lstAnchor[$name][0];
3835:             }
3836: 
3837:             $this->parsingCss->save();
3838:             $this->parsingCss->value['font-underline'] = true;
3839:             $this->parsingCss->value['color'] = array(20, 20, 250);
3840:             $this->parsingCss->analyse('a', $param);
3841:             $this->parsingCss->setPosition();
3842:             $this->parsingCss->fontSet();
3843: 
3844:             return true;
3845:         }
3846: 
3847:         /**
3848:          * tag : A
3849:          * mode : CLOSE
3850:          *
3851:          * @param  array $param
3852:          * @return boolean
3853:          */
3854:         protected function _tag_close_A($param)
3855:         {
3856:             $this->_isInLink    = '';
3857:             $this->parsingCss->load();
3858:             $this->parsingCss->fontSet();
3859: 
3860:             return true;
3861:         }
3862: 
3863:         /**
3864:          * tag : H1
3865:          * mode : OPEN
3866:          *
3867:          * @param  array $param
3868:          * @param  string $other
3869:          * @return boolean
3870:          */
3871:         protected function _tag_open_H1($param, $other = 'h1')
3872:         {
3873:             if ($this->_isForOneLine) return false;
3874: 
3875:             if ($this->_maxH) $this->_tag_open_BR(array());
3876:             $this->parsingCss->save();
3877:             $this->parsingCss->value['font-bold'] = true;
3878: 
3879:             $size = array('h1' => '28px', 'h2' => '24px', 'h3' => '20px', 'h4' => '16px', 'h5' => '12px', 'h6' => '9px');
3880:             $this->parsingCss->value['margin']['l'] = 0;
3881:             $this->parsingCss->value['margin']['r'] = 0;
3882:             $this->parsingCss->value['margin']['t'] = $this->parsingCss->ConvertToMM('16px');
3883:             $this->parsingCss->value['margin']['b'] = $this->parsingCss->ConvertToMM('16px');
3884:             $this->parsingCss->value['font-size'] = $this->parsingCss->ConvertToMM($size[$other]);
3885: 
3886:             $this->parsingCss->analyse($other, $param);
3887:             $this->parsingCss->setPosition();
3888:             $this->parsingCss->fontSet();
3889:             $this->_setNewPositionForNewLine();
3890: 
3891:             return true;
3892:         }
3893: 
3894:         /**
3895:          * tag : H2
3896:          * mode : OPEN
3897:          *
3898:          * @param  array $param
3899:          * @return boolean
3900:          */
3901:         protected function _tag_open_H2($param)
3902:         {
3903:             return $this->_tag_open_H1($param, 'h2');
3904:         }
3905: 
3906:         /**
3907:          * tag : H3
3908:          * mode : OPEN
3909:          *
3910:          * @param  array $param
3911:          * @return boolean
3912:          */
3913:         protected function _tag_open_H3($param)
3914:         {
3915:             return $this->_tag_open_H1($param, 'h3');
3916:         }
3917: 
3918:         /**
3919:          * tag : H4
3920:          * mode : OPEN
3921:          *
3922:          * @param  array $param
3923:          * @return boolean
3924:          */
3925:         protected function _tag_open_H4($param)
3926:         {
3927:             return $this->_tag_open_H1($param, 'h4');
3928:         }
3929: 
3930:         /**
3931:          * tag : H5
3932:          * mode : OPEN
3933:          *
3934:          * @param  array $param
3935:          * @return boolean
3936:          */
3937:         protected function _tag_open_H5($param)
3938:         {
3939:             return $this->_tag_open_H1($param, 'h5');
3940:         }
3941: 
3942:         /**
3943:          * tag : H6
3944:          * mode : OPEN
3945:          *
3946:          * @param  array $param
3947:          * @return boolean
3948:          */
3949:         protected function _tag_open_H6($param)
3950:         {
3951:             return $this->_tag_open_H1($param, 'h6');
3952:         }
3953: 
3954:         /**
3955:          * tag : H1
3956:          * mode : CLOSE
3957:          *
3958:          * @param  array $param
3959:          * @return boolean
3960:          */
3961:         protected function _tag_close_H1($param)
3962:         {
3963:             if ($this->_isForOneLine) return false;
3964: 
3965:             $this->_maxH+= $this->parsingCss->value['margin']['b'];
3966:             $h = max($this->_maxH, $this->parsingCss->getLineHeight());
3967: 
3968:             $this->parsingCss->load();
3969:             $this->parsingCss->fontSet();
3970: 
3971:             $this->_makeBreakLine($h);
3972:             $this->_maxH = 0;
3973: 
3974:             $this->_maxY = max($this->_maxY, $this->pdf->getY());
3975: 
3976:             return true;
3977:         }
3978: 
3979:         /**
3980:          * tag : H2
3981:          * mode : CLOSE
3982:          *
3983:          * @param  array $param
3984:          * @return boolean
3985:          */
3986:         protected function _tag_close_H2($param)
3987:         {
3988:             return $this->_tag_close_H1($param);
3989:         }
3990: 
3991:         /**
3992:          * tag : H3
3993:          * mode : CLOSE
3994:          *
3995:          * @param  array $param
3996:          * @return boolean
3997:          */
3998:         protected function _tag_close_H3($param)
3999:         {
4000:             return $this->_tag_close_H1($param);
4001:         }
4002: 
4003:         /**
4004:          * tag : H4
4005:          * mode : CLOSE
4006:          *
4007:          * @param  array $param
4008:          * @return boolean
4009:          */
4010:         protected function _tag_close_H4($param)
4011:         {
4012:             return $this->_tag_close_H1($param);
4013:         }
4014: 
4015:         /**
4016:          * tag : H5
4017:          * mode : CLOSE
4018:          *
4019:          * @param  array $param
4020:          * @return boolean
4021:          */
4022:         protected function _tag_close_H5($param)
4023:         {
4024:             return $this->_tag_close_H1($param);
4025:         }
4026: 
4027:         /**
4028:          * tag : H6
4029:          * mode : CLOSE
4030:          *
4031:          * @param  array $param
4032:          * @return boolean
4033:          */
4034:         protected function _tag_close_H6($param)
4035:         {
4036:             return $this->_tag_close_H1($param);
4037:         }
4038: 
4039:         /**
4040:          * tag : SPAN
4041:          * mode : OPEN
4042:          *
4043:          * @param  array $param
4044:          * @param  string $other
4045:          * @return boolean
4046:          */
4047:         protected function _tag_open_SPAN($param, $other = 'span')
4048:         {
4049:             $this->parsingCss->save();
4050:             $this->parsingCss->analyse($other, $param);
4051:             $this->parsingCss->setPosition();
4052:             $this->parsingCss->fontSet();
4053: 
4054:             return true;
4055:         }
4056: 
4057:         /**
4058:          * tag : FONT
4059:          * mode : OPEN
4060:          *
4061:          * @param  array $param
4062:          * @return boolean
4063:          */
4064:         protected function _tag_open_FONT($param)
4065:         {
4066:             return $this->_tag_open_SPAN($param, 'font');
4067:         }
4068: 
4069:         /**
4070:          * tag : LABEL
4071:          * mode : OPEN
4072:          *
4073:          * @param  array $param
4074:          * @return boolean
4075:          */
4076:         protected function _tag_open_LABEL($param)
4077:         {
4078:             return $this->_tag_open_SPAN($param, 'label');
4079:         }
4080: 
4081:         /**
4082:          * tag : SPAN
4083:          * mode : CLOSE
4084:          *
4085:          * @param  array $param
4086:          * @return boolean
4087:          */
4088:         protected function _tag_close_SPAN($param)
4089:         {
4090:             $this->parsingCss->restorePosition();
4091:             $this->parsingCss->load();
4092:             $this->parsingCss->fontSet();
4093: 
4094:             return true;
4095:         }
4096: 
4097:         /**
4098:          * tag : FONT
4099:          * mode : CLOSE
4100:          *
4101:          * @param  array $param
4102:          * @return boolean
4103:          */
4104:         protected function _tag_close_FONT($param)
4105:         {
4106:             return $this->_tag_close_SPAN($param);
4107:         }
4108: 
4109:         /**
4110:          * tag : LABEL
4111:          * mode : CLOSE
4112:          *
4113:          * @param  array $param
4114:          * @return boolean
4115:          */
4116:         protected function _tag_close_LABEL($param)
4117:         {
4118:             return $this->_tag_close_SPAN($param);
4119:         }
4120: 
4121:         /**
4122:          * tag : P
4123:          * mode : OPEN
4124:          *
4125:          * @param    array $param
4126:          * @return boolean
4127:          */
4128:         protected function _tag_open_P($param)
4129:         {
4130:             if ($this->_isForOneLine) return false;
4131: 
4132:             if (!in_array($this->_previousCall, array('_tag_close_P', '_tag_close_UL'))) {
4133:                 if ($this->_maxH) $this->_tag_open_BR(array());
4134:             }
4135: 
4136:             $this->parsingCss->save();
4137:             $this->parsingCss->analyse('p', $param);
4138:             $this->parsingCss->setPosition();
4139:             $this->parsingCss->fontSet();
4140: 
4141:              // cancel the effects of the setPosition
4142:             $this->pdf->setXY($this->pdf->getX()-$this->parsingCss->value['margin']['l'], $this->pdf->getY()-$this->parsingCss->value['margin']['t']);
4143: 
4144:             list($mL, $mR) = $this->_getMargins($this->pdf->getY());
4145:             $mR = $this->pdf->getW()-$mR;
4146:             $mL+= $this->parsingCss->value['margin']['l']+$this->parsingCss->value['padding']['l'];
4147:             $mR+= $this->parsingCss->value['margin']['r']+$this->parsingCss->value['padding']['r'];
4148:             $this->_saveMargin($mL, 0, $mR);
4149: 
4150:             if ($this->parsingCss->value['text-indent']>0) {
4151:                 $y = $this->pdf->getY()+$this->parsingCss->value['margin']['t']+$this->parsingCss->value['padding']['t'];
4152:                 $this->_pageMarges[floor($y*100)] = array($mL+$this->parsingCss->value['text-indent'], $this->pdf->getW()-$mR);
4153:                 $y+= $this->parsingCss->getLineHeight()*0.1;
4154:                 $this->_pageMarges[floor($y*100)] = array($mL, $this->pdf->getW()-$mR);
4155:             }
4156:             $this->_makeBreakLine($this->parsingCss->value['margin']['t']+$this->parsingCss->value['padding']['t']);
4157:             $this->_isInParagraph = array($mL, $mR);
4158:             return true;
4159:         }
4160: 
4161:         /**
4162:          * tag : P
4163:          * mode : CLOSE
4164:          *
4165:          * @param  array $param
4166:          * @return boolean
4167:          */
4168:         protected function _tag_close_P($param)
4169:         {
4170:             if ($this->_isForOneLine) return false;
4171: 
4172:             if ($this->_maxH) $this->_tag_open_BR(array());
4173:             $this->_isInParagraph = false;
4174:             $this->_loadMargin();
4175:             $h = $this->parsingCss->value['margin']['b']+$this->parsingCss->value['padding']['b'];
4176: 
4177:             $this->parsingCss->load();
4178:             $this->parsingCss->fontSet();
4179:             $this->_makeBreakLine($h);
4180: 
4181:             return true;
4182:         }
4183: 
4184:         /**
4185:          * tag : PRE
4186:          * mode : OPEN
4187:          *
4188:          * @param  array $param
4189:          * @param  string $other
4190:          * @return boolean
4191:          */
4192:         protected function _tag_open_PRE($param, $other = 'pre')
4193:         {
4194:             if ($other=='pre' && $this->_maxH) $this->_tag_open_BR(array());
4195: 
4196:             $this->parsingCss->save();
4197:             $this->parsingCss->value['font-family'] = 'courier';
4198:             $this->parsingCss->analyse($other, $param);
4199:             $this->parsingCss->setPosition();
4200:             $this->parsingCss->fontSet();
4201: 
4202:             if ($other=='pre') return $this->_tag_open_DIV($param, $other);
4203: 
4204:             return true;
4205:         }
4206: 
4207:         /**
4208:          * tag : CODE
4209:          * mode : OPEN
4210:          *
4211:          * @param  array $param
4212:          * @param  string $other
4213:          * @return boolean
4214:          */
4215:         protected function _tag_open_CODE($param)
4216:         {
4217:             return $this->_tag_open_PRE($param, 'code');
4218:         }
4219: 
4220:         /**
4221:          * tag : PRE
4222:          * mode : CLOSE
4223:          *
4224:          * @param  array $param
4225:          * @param  string $other
4226:          * @return boolean
4227:          */
4228:         protected function _tag_close_PRE($param, $other = 'pre')
4229:         {
4230:             if ($other=='pre') {
4231:                 if ($this->_isForOneLine) return false;
4232: 
4233:                 $this->_tag_close_DIV($param, $other);
4234:                 $this->_tag_open_BR(array());
4235:             }
4236:             $this->parsingCss->load();
4237:             $this->parsingCss->fontSet();
4238: 
4239:             return true;
4240:         }
4241: 
4242:         /**
4243:          * tag : CODE
4244:          * mode : CLOSE
4245:          *
4246:          * @param  array $param
4247:          * @return boolean
4248:          */
4249:         protected function _tag_close_CODE($param)
4250:         {
4251:             return $this->_tag_close_PRE($param, 'code');
4252:         }
4253: 
4254:         /**
4255:          * tag : BIG
4256:          * mode : OPEN
4257:          *
4258:          * @param    array $param
4259:          * @return boolean
4260:          */
4261:         protected function _tag_open_BIG($param)
4262:         {
4263:             $this->parsingCss->save();
4264:             $this->parsingCss->value['mini-decal']-= $this->parsingCss->value['mini-size']*0.12;
4265:             $this->parsingCss->value['mini-size'] *= 1.2;
4266:             $this->parsingCss->analyse('big', $param);
4267:             $this->parsingCss->setPosition();
4268:             $this->parsingCss->fontSet();
4269:             return true;
4270:         }
4271: 
4272:         /**
4273:          * tag : BIG
4274:          * mode : CLOSE
4275:          *
4276:          * @param    array $param
4277:          * @return boolean
4278:          */
4279:         protected function _tag_close_BIG($param)
4280:         {
4281:             $this->parsingCss->load();
4282:             $this->parsingCss->fontSet();
4283: 
4284:             return true;
4285:         }
4286: 
4287:         /**
4288:          * tag : SMALL
4289:          * mode : OPEN
4290:          *
4291:          * @param    array $param
4292:          * @return boolean
4293:          */
4294:         protected function _tag_open_SMALL($param)
4295:         {
4296:             $this->parsingCss->save();
4297:             $this->parsingCss->value['mini-decal']+= $this->parsingCss->value['mini-size']*0.05;
4298:             $this->parsingCss->value['mini-size'] *= 0.82;
4299:             $this->parsingCss->analyse('small', $param);
4300:             $this->parsingCss->setPosition();
4301:             $this->parsingCss->fontSet();
4302:             return true;
4303:         }
4304: 
4305:         /**
4306:          * tag : SMALL
4307:          * mode : CLOSE
4308:          *
4309:          * @param    array $param
4310:          * @return boolean
4311:          */
4312:         protected function _tag_close_SMALL($param)
4313:         {
4314:             $this->parsingCss->load();
4315:             $this->parsingCss->fontSet();
4316: 
4317:             return true;
4318:         }
4319: 
4320:         /**
4321:          * tag : SUP
4322:          * mode : OPEN
4323:          *
4324:          * @param    array $param
4325:          * @return boolean
4326:          */
4327:         protected function _tag_open_SUP($param)
4328:         {
4329:             $this->parsingCss->save();
4330:             $this->parsingCss->value['mini-decal']-= $this->parsingCss->value['mini-size']*0.15;
4331:             $this->parsingCss->value['mini-size'] *= 0.75;
4332:             $this->parsingCss->analyse('sup', $param);
4333:             $this->parsingCss->setPosition();
4334:             $this->parsingCss->fontSet();
4335: 
4336:             return true;
4337:         }
4338: 
4339:         /**
4340:          * tag : SUP
4341:          * mode : CLOSE
4342:          *
4343:          * @param    array $param
4344:          * @return boolean
4345:          */
4346:         protected function _tag_close_SUP($param)
4347:         {
4348:             $this->parsingCss->load();
4349:             $this->parsingCss->fontSet();
4350: 
4351:             return true;
4352:         }
4353: 
4354:         /**
4355:          * tag : SUB
4356:          * mode : OPEN
4357:          *
4358:          * @param    array $param
4359:          * @return boolean
4360:          */
4361:         protected function _tag_open_SUB($param)
4362:         {
4363:             $this->parsingCss->save();
4364:             $this->parsingCss->value['mini-decal']+= $this->parsingCss->value['mini-size']*0.15;
4365:             $this->parsingCss->value['mini-size'] *= 0.75;
4366:             $this->parsingCss->analyse('sub', $param);
4367:             $this->parsingCss->setPosition();
4368:             $this->parsingCss->fontSet();
4369:             return true;
4370:         }
4371: 
4372:         /**
4373:          * tag : SUB
4374:          * mode : CLOSE
4375:          *
4376:          * @param    array $param
4377:          * @return boolean
4378:          */
4379:         protected function _tag_close_SUB($param)
4380:         {
4381:             $this->parsingCss->load();
4382:             $this->parsingCss->fontSet();
4383: 
4384:             return true;
4385:         }
4386: 
4387:         /**
4388:          * tag : UL
4389:          * mode : OPEN
4390:          *
4391:          * @param  array $param
4392:          * @param  string $other
4393:          * @return boolean
4394:          */
4395:         protected function _tag_open_UL($param, $other = 'ul')
4396:         {
4397:             if ($this->_isForOneLine) return false;
4398: 
4399:             if (!in_array($this->_previousCall, array('_tag_close_P', '_tag_close_UL'))) {
4400:                 if ($this->_maxH) $this->_tag_open_BR(array());
4401:                 if (!count($this->_defList)) $this->_tag_open_BR(array());
4402:             }
4403: 
4404:             if (!isset($param['style']['width'])) $param['allwidth'] = true;
4405:             $param['cellspacing'] = 0;
4406: 
4407:             // a list is like a table
4408:             $this->_tag_open_TABLE($param, $other);
4409: 
4410:             // add a level of list
4411:             $this->_listeAddLevel($other, $this->parsingCss->value['list-style-type'], $this->parsingCss->value['list-style-image']);
4412: 
4413:             return true;
4414:         }
4415: 
4416:         /**
4417:          * tag : OL
4418:          * mode : OPEN
4419:          *
4420:          * @param  array $param
4421:          * @return boolean
4422:          */
4423:         protected function _tag_open_OL($param)
4424:         {
4425:             return $this->_tag_open_UL($param, 'ol');
4426:         }
4427: 
4428:         /**
4429:          * tag : UL
4430:          * mode : CLOSE
4431:          *
4432:          * @param  array $param
4433:          * @return boolean
4434:          */
4435:         protected function _tag_close_UL($param)
4436:         {
4437:             if ($this->_isForOneLine) return false;
4438: 
4439:             $this->_tag_close_TABLE($param);
4440: 
4441:             $this->_listeDelLevel();
4442: 
4443:             if (!$this->_subPart) {
4444:                 if (!count($this->_defList)) $this->_tag_open_BR(array());
4445:             }
4446: 
4447:             return true;
4448:         }
4449: 
4450:         /**
4451:          * tag : OL
4452:          * mode : CLOSE
4453:          *
4454:          * @param  array $param
4455:          * @return boolean
4456:          */
4457:         protected function _tag_close_OL($param)
4458:         {
4459:             return $this->_tag_close_UL($param);
4460:         }
4461: 
4462:         /**
4463:          * tag : LI
4464:          * mode : OPEN
4465:          *
4466:          * @param  array $param
4467:          * @return boolean
4468:          */
4469:         protected function _tag_open_LI($param)
4470:         {
4471:             if ($this->_isForOneLine) return false;
4472: 
4473:             $this->_listeAddLi();
4474: 
4475:             if (!isset($param['style']['width'])) $param['style']['width'] = '100%';
4476: 
4477:             $paramPUCE = $param;
4478: 
4479:             $inf = $this->_listeGetLi();
4480:             if ($inf[0]) {
4481:                 $paramPUCE['style']['font-family']     = $inf[0];
4482:                 $paramPUCE['style']['text-align']      = 'li_right';
4483:                 $paramPUCE['style']['vertical-align']  = 'top';
4484:                 $paramPUCE['style']['width']           = $this->_listeGetWidth();
4485:                 $paramPUCE['style']['padding-right']   = $this->_listeGetPadding();
4486:                 $paramPUCE['txt'] = $inf[2];
4487:             } else {
4488:                 $paramPUCE['style']['text-align']      = 'li_right';
4489:                 $paramPUCE['style']['vertical-align']  = 'top';
4490:                 $paramPUCE['style']['width']           = $this->_listeGetWidth();
4491:                 $paramPUCE['style']['padding-right']   = $this->_listeGetPadding();
4492:                 $paramPUCE['src'] = $inf[2];
4493:                 $paramPUCE['sub_li'] = true;
4494:             }
4495: 
4496:             $this->_tag_open_TR($param, 'li');
4497: 
4498:             $this->parsingCss->save();
4499: 
4500:             // if small LI
4501:             if ($inf[1]) {
4502:                 $this->parsingCss->value['mini-decal']+= $this->parsingCss->value['mini-size']*0.045;
4503:                 $this->parsingCss->value['mini-size'] *= 0.75;
4504:             }
4505: 
4506:             // if we are in a sub html => prepare. Else : display
4507:             if ($this->_subPart) {
4508:                 // TD for the puce
4509:                 $tmpPos = $this->_tempPos;
4510:                 $tmpLst1 = $this->parsingHtml->code[$tmpPos+1];
4511:                 $tmpLst2 = $this->parsingHtml->code[$tmpPos+2];
4512:                 $this->parsingHtml->code[$tmpPos+1] = array();
4513:                 $this->parsingHtml->code[$tmpPos+1]['name']    = (isset($paramPUCE['src'])) ? 'img' : 'write';
4514:                 $this->parsingHtml->code[$tmpPos+1]['param']    = $paramPUCE; unset($this->parsingHtml->code[$tmpPos+1]['param']['style']['width']);
4515:                 $this->parsingHtml->code[$tmpPos+1]['close']    = 0;
4516:                 $this->parsingHtml->code[$tmpPos+2] = array();
4517:                 $this->parsingHtml->code[$tmpPos+2]['name']    = 'li';
4518:                 $this->parsingHtml->code[$tmpPos+2]['param']    = $paramPUCE;
4519:                 $this->parsingHtml->code[$tmpPos+2]['close']    = 1;
4520:                 $this->_tag_open_TD($paramPUCE, 'li_sub');
4521:                 $this->_tag_close_TD($param);
4522:                 $this->_tempPos = $tmpPos;
4523:                 $this->parsingHtml->code[$tmpPos+1] = $tmpLst1;
4524:                 $this->parsingHtml->code[$tmpPos+2] = $tmpLst2;
4525:             } else {
4526:                 // TD for the puce
4527:                 $this->_tag_open_TD($paramPUCE, 'li_sub');
4528:                 unset($paramPUCE['style']['width']);
4529:                 if (isset($paramPUCE['src']))    $this->_tag_open_IMG($paramPUCE);
4530:                 else                            $this->_tag_open_WRITE($paramPUCE);
4531:                 $this->_tag_close_TD($paramPUCE);
4532:             }
4533:             $this->parsingCss->load();
4534: 
4535: 
4536:             // TD for the content
4537:             $this->_tag_open_TD($param, 'li');
4538: 
4539:             return true;
4540:         }
4541: 
4542:         /**
4543:          * tag : LI
4544:          * mode : CLOSE
4545:          *
4546:          * @param  array $param
4547:          * @return boolean
4548:          */
4549:         protected function _tag_close_LI($param)
4550:         {
4551:             if ($this->_isForOneLine) return false;
4552: 
4553:             $this->_tag_close_TD($param);
4554: 
4555:             $this->_tag_close_TR($param);
4556: 
4557:             return true;
4558:         }
4559: 
4560:         /**
4561:          * tag : TBODY
4562:          * mode : OPEN
4563:          *
4564:          * @param  array $param
4565:          * @return boolean
4566:          */
4567:         protected function _tag_open_TBODY($param)
4568:         {
4569:             if ($this->_isForOneLine) return false;
4570: 
4571:             $this->parsingCss->save();
4572:             $this->parsingCss->analyse('tbody', $param);
4573:             $this->parsingCss->setPosition();
4574:             $this->parsingCss->fontSet();
4575: 
4576:             return true;
4577:         }
4578: 
4579:         /**
4580:          * tag : TBODY
4581:          * mode : CLOSE
4582:          *
4583:          * @param  array $param
4584:          * @return boolean
4585:          */
4586:         protected function _tag_close_TBODY($param)
4587:         {
4588:             if ($this->_isForOneLine) return false;
4589: 
4590:             $this->parsingCss->load();
4591:             $this->parsingCss->fontSet();
4592: 
4593:             return true;
4594:         }
4595: 
4596:         /**
4597:          * tag : THEAD
4598:          * mode : OPEN
4599:          *
4600:          * @param  array $param
4601:          * @return boolean
4602:          */
4603:         protected function _tag_open_THEAD($param)
4604:         {
4605:             if ($this->_isForOneLine) return false;
4606: 
4607:             $this->parsingCss->save();
4608:             $this->parsingCss->analyse('thead', $param);
4609:             $this->parsingCss->setPosition();
4610:             $this->parsingCss->fontSet();
4611: 
4612:             // if we are in a sub part, save the number of the first TR in the thead
4613:             if ($this->_subPart) {
4614:                 HTML2PDF::$_tables[$param['num']]['thead']['tr'][0] = HTML2PDF::$_tables[$param['num']]['tr_curr'];
4615:                 HTML2PDF::$_tables[$param['num']]['thead']['code'] = array();
4616:                 for ($pos=$this->_tempPos; $pos<count($this->parsingHtml->code); $pos++) {
4617:                     $action = $this->parsingHtml->code[$pos];
4618:                     if (strtolower($action['name'])=='thead') $action['name'] = 'thead_sub';
4619:                     HTML2PDF::$_tables[$param['num']]['thead']['code'][] = $action;
4620:                     if (strtolower($action['name'])=='thead_sub' && $action['close']) break;
4621:                 }
4622:             } else {
4623:                 $level = $this->parsingHtml->getLevel($this->_parsePos);
4624:                 $this->_parsePos+= count($level);
4625:                 HTML2PDF::$_tables[$param['num']]['tr_curr']+= count(HTML2PDF::$_tables[$param['num']]['thead']['tr']);
4626:             }
4627: 
4628:             return true;
4629:         }
4630: 
4631:         /**
4632:          * tag : THEAD
4633:          * mode : CLOSE
4634:          *
4635:          * @param  array $param
4636:          * @return boolean
4637:          */
4638:         protected function _tag_close_THEAD($param)
4639:         {
4640:             if ($this->_isForOneLine) return false;
4641: 
4642:             $this->parsingCss->load();
4643:             $this->parsingCss->fontSet();
4644: 
4645:             // if we are in a sub HTM, construct the list of the TR in the thead
4646:             if ($this->_subPart) {
4647:                 $min = HTML2PDF::$_tables[$param['num']]['thead']['tr'][0];
4648:                 $max = HTML2PDF::$_tables[$param['num']]['tr_curr']-1;
4649:                 HTML2PDF::$_tables[$param['num']]['thead']['tr'] = range($min, $max);
4650:             }
4651: 
4652:             return true;
4653:         }
4654: 
4655:         /**
4656:          * tag : TFOOT
4657:          * mode : OPEN
4658:          *
4659:          * @param  array $param
4660:          * @return boolean
4661:          */
4662:         protected function _tag_open_TFOOT($param)
4663:         {
4664:             if ($this->_isForOneLine) return false;
4665: 
4666:             $this->parsingCss->save();
4667:             $this->parsingCss->analyse('tfoot', $param);
4668:             $this->parsingCss->setPosition();
4669:             $this->parsingCss->fontSet();
4670: 
4671:             // if we are in a sub part, save the number of the first TR in the tfoot
4672:             if ($this->_subPart) {
4673:                 HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0] = HTML2PDF::$_tables[$param['num']]['tr_curr'];
4674:                 HTML2PDF::$_tables[$param['num']]['tfoot']['code'] = array();
4675:                 for ($pos=$this->_tempPos; $pos<count($this->parsingHtml->code); $pos++) {
4676:                     $action = $this->parsingHtml->code[$pos];
4677:                     if (strtolower($action['name'])=='tfoot') $action['name'] = 'tfoot_sub';
4678:                     HTML2PDF::$_tables[$param['num']]['tfoot']['code'][] = $action;
4679:                     if (strtolower($action['name'])=='tfoot_sub' && $action['close']) break;
4680:                 }
4681:             } else {
4682:                 $level = $this->parsingHtml->getLevel($this->_parsePos);
4683:                 $this->_parsePos+= count($level);
4684:                 HTML2PDF::$_tables[$param['num']]['tr_curr']+= count(HTML2PDF::$_tables[$param['num']]['tfoot']['tr']);
4685:             }
4686: 
4687:             return true;
4688:         }
4689: 
4690:         /**
4691:          * tag : TFOOT
4692:          * mode : CLOSE
4693:          *
4694:          * @param  array $param
4695:          * @return boolean
4696:          */
4697:         protected function _tag_close_TFOOT($param)
4698:         {
4699:             if ($this->_isForOneLine) return false;
4700: 
4701:             $this->parsingCss->load();
4702:             $this->parsingCss->fontSet();
4703: 
4704:             // if we are in a sub HTM, construct the list of the TR in the tfoot
4705:             if ($this->_subPart) {
4706:                 $min = HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0];
4707:                 $max = HTML2PDF::$_tables[$param['num']]['tr_curr']-1;
4708:                 HTML2PDF::$_tables[$param['num']]['tfoot']['tr'] = range($min, $max);
4709:             }
4710: 
4711:             return true;
4712:         }
4713: 
4714:         /**
4715:          * It is not a real TAG, does not use it !
4716:          *
4717:          * @param  array $param
4718:          * @return boolean
4719:          */
4720:         protected function _tag_open_THEAD_SUB($param)
4721:         {
4722:             if ($this->_isForOneLine) return false;
4723: 
4724:             $this->parsingCss->save();
4725:             $this->parsingCss->analyse('thead', $param);
4726:             $this->parsingCss->setPosition();
4727:             $this->parsingCss->fontSet();
4728: 
4729:             return true;
4730:         }
4731: 
4732:         /**
4733:          * It is not a real TAG, does not use it !
4734:          *
4735:          * @param  array $param
4736:          * @return boolean
4737:          */
4738:         protected function _tag_close_THEAD_SUB($param)
4739:         {
4740:             if ($this->_isForOneLine) return false;
4741: 
4742:             $this->parsingCss->load();
4743:             $this->parsingCss->fontSet();
4744: 
4745:             return true;
4746:         }
4747: 
4748:         /**
4749:          * It is not a real TAG, does not use it !
4750:          *
4751:          * @param    array $param
4752:          * @return boolean
4753:          */
4754:         protected function _tag_open_TFOOT_SUB($param)
4755:         {
4756:             if ($this->_isForOneLine) return false;
4757: 
4758:             $this->parsingCss->save();
4759:             $this->parsingCss->analyse('tfoot', $param);
4760:             $this->parsingCss->setPosition();
4761:             $this->parsingCss->fontSet();
4762: 
4763:             return true;
4764:         }
4765: 
4766:         /**
4767:          * It is not a real TAG, does not use it !
4768:          *
4769:          * @param  array $param
4770:          * @return boolean
4771:          */
4772:         protected function _tag_close_TFOOT_SUB($param)
4773:         {
4774:             if ($this->_isForOneLine) return false;
4775: 
4776:             $this->parsingCss->load();
4777:             $this->parsingCss->fontSet();
4778: 
4779:             return true;
4780:         }
4781: 
4782:         /**
4783:          * tag : FORM
4784:          * mode : OPEN
4785:          *
4786:          * @param  array $param
4787:          * @return boolean
4788:          */
4789:         protected function _tag_open_FORM($param)
4790:         {
4791:             $this->parsingCss->save();
4792:             $this->parsingCss->analyse('form', $param);
4793:             $this->parsingCss->setPosition();
4794:             $this->parsingCss->fontSet();
4795: 
4796:             $this->pdf->setFormDefaultProp(
4797:                 array(
4798:                     'lineWidth'=>1,
4799:                     'borderStyle'=>'solid',
4800:                     'fillColor'=>array(220, 220, 255),
4801:                     'strokeColor'=>array(128, 128, 200)
4802:                 )
4803:             );
4804: 
4805:             $this->_isInForm = isset($param['action']) ? $param['action'] : '';
4806: 
4807:             return true;
4808:         }
4809: 
4810:         /**
4811:          * tag : FORM
4812:          * mode : CLOSE
4813:          *
4814:          * @param  array $param
4815:          * @return boolean
4816:          */
4817:         protected function _tag_close_FORM($param)
4818:         {
4819:             $this->_isInForm = false;
4820:             $this->parsingCss->load();
4821:             $this->parsingCss->fontSet();
4822: 
4823:             return true;
4824:         }
4825: 
4826:         /**
4827:          * tag : TABLE
4828:          * mode : OPEN
4829:          *
4830:          * @param  array $param
4831:          * @return boolean
4832:          */
4833:         protected function _tag_open_TABLE($param, $other = 'table')
4834:         {
4835:             if ($this->_maxH) {
4836:                 if ($this->_isForOneLine) return false;
4837:                 $this->_tag_open_BR(array());
4838:             }
4839: 
4840:             if ($this->_isForOneLine) {
4841:                 $this->_maxX = $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
4842:                 return false;
4843:             }
4844: 
4845:             $this->_maxH = 0;
4846: 
4847:             $alignObject = isset($param['align']) ? strtolower($param['align']) : 'left';
4848:             if (isset($param['align'])) unset($param['align']);
4849:             if (!in_array($alignObject, array('left', 'center', 'right'))) $alignObject = 'left';
4850: 
4851:             $this->parsingCss->save();
4852:             $this->parsingCss->analyse($other, $param);
4853:             $this->parsingCss->setPosition();
4854:             $this->parsingCss->fontSet();
4855: 
4856:             if ($this->parsingCss->value['margin-auto']) $alignObject = 'center';
4857: 
4858:             // collapse table ?
4859:             $collapse = false;
4860:             if ($other=='table') {
4861:                 $collapse = isset($this->parsingCss->value['border']['collapse']) ? $this->parsingCss->value['border']['collapse'] : false;
4862:             }
4863: 
4864:             // if collapse => no borders for the table, only for TD
4865:             if ($collapse) {
4866:                 $param['style']['border'] = 'none';
4867:                 $param['cellspacing'] = 0;
4868:                 $none = $this->parsingCss->readBorder('none');
4869:                 $this->parsingCss->value['border']['t'] = $none;
4870:                 $this->parsingCss->value['border']['r'] = $none;
4871:                 $this->parsingCss->value['border']['b'] = $none;
4872:                 $this->parsingCss->value['border']['l'] = $none;
4873:             }
4874: 
4875:             // if we are in a SUB html => prepare the properties of the table
4876:             if ($this->_subPart) {
4877:                 if ($this->_debugActif) $this->_DEBUG_add('Table n'.$param['num'], true);
4878:                 HTML2PDF::$_tables[$param['num']] = array();
4879:                 HTML2PDF::$_tables[$param['num']]['border']          = isset($param['border']) ? $this->parsingCss->readBorder($param['border']) : null;
4880:                 HTML2PDF::$_tables[$param['num']]['cellpadding']     = $this->parsingCss->ConvertToMM(isset($param['cellpadding']) ? $param['cellpadding'] : '1px');
4881:                 HTML2PDF::$_tables[$param['num']]['cellspacing']     = $this->parsingCss->ConvertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
4882:                 HTML2PDF::$_tables[$param['num']]['cases']           = array();          // properties of each TR/TD
4883:                 HTML2PDF::$_tables[$param['num']]['corr']            = array();          // link between TR/TD and colspan/rowspan
4884:                 HTML2PDF::$_tables[$param['num']]['corr_x']          = 0;                // position in 'cases'
4885:                 HTML2PDF::$_tables[$param['num']]['corr_y']          = 0;                // position in 'cases'
4886:                 HTML2PDF::$_tables[$param['num']]['td_curr']         = 0;                // current column
4887:                 HTML2PDF::$_tables[$param['num']]['tr_curr']         = 0;                // current row
4888:                 HTML2PDF::$_tables[$param['num']]['curr_x']          = $this->pdf->getX();
4889:                 HTML2PDF::$_tables[$param['num']]['curr_y']          = $this->pdf->getY();
4890:                 HTML2PDF::$_tables[$param['num']]['width']           = 0;                // global width
4891:                 HTML2PDF::$_tables[$param['num']]['height']          = 0;                // global height
4892:                 HTML2PDF::$_tables[$param['num']]['align']           = $alignObject;
4893:                 HTML2PDF::$_tables[$param['num']]['marge']           = array();
4894:                 HTML2PDF::$_tables[$param['num']]['marge']['t']      = $this->parsingCss->value['padding']['t']+$this->parsingCss->value['border']['t']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
4895:                 HTML2PDF::$_tables[$param['num']]['marge']['r']      = $this->parsingCss->value['padding']['r']+$this->parsingCss->value['border']['r']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
4896:                 HTML2PDF::$_tables[$param['num']]['marge']['b']      = $this->parsingCss->value['padding']['b']+$this->parsingCss->value['border']['b']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
4897:                 HTML2PDF::$_tables[$param['num']]['marge']['l']      = $this->parsingCss->value['padding']['l']+$this->parsingCss->value['border']['l']['width']+HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5;
4898:                 HTML2PDF::$_tables[$param['num']]['page']            = 0;                // number of pages
4899:                 HTML2PDF::$_tables[$param['num']]['new_page']        = true;             // flag : new page for the current TR
4900:                 HTML2PDF::$_tables[$param['num']]['style_value']     = null;             // CSS style of the table
4901:                 HTML2PDF::$_tables[$param['num']]['thead']           = array();          // properties on the thead
4902:                 HTML2PDF::$_tables[$param['num']]['tfoot']           = array();          // properties on the tfoot
4903:                 HTML2PDF::$_tables[$param['num']]['thead']['tr']     = array();          // list of the TRs in the thead
4904:                 HTML2PDF::$_tables[$param['num']]['tfoot']['tr']     = array();          // list of the TRs in the tfoot
4905:                 HTML2PDF::$_tables[$param['num']]['thead']['height']    = 0;             // thead height
4906:                 HTML2PDF::$_tables[$param['num']]['tfoot']['height']    = 0;             // tfoot height
4907:                 HTML2PDF::$_tables[$param['num']]['thead']['code'] = array();            // HTML content of the thead
4908:                 HTML2PDF::$_tables[$param['num']]['tfoot']['code'] = array();            // HTML content of the tfoot
4909:                 HTML2PDF::$_tables[$param['num']]['cols']        = array();              // properties of the COLs
4910: 
4911:                 $this->_saveMargin($this->pdf->getlMargin(), $this->pdf->gettMargin(), $this->pdf->getrMargin());
4912: 
4913:                 $this->parsingCss->value['width']-= HTML2PDF::$_tables[$param['num']]['marge']['l'] + HTML2PDF::$_tables[$param['num']]['marge']['r'];
4914:             } else {
4915:                 // we start from the first page and the first page of the table
4916:                 HTML2PDF::$_tables[$param['num']]['page'] = 0;
4917:                 HTML2PDF::$_tables[$param['num']]['td_curr']    = 0;
4918:                 HTML2PDF::$_tables[$param['num']]['tr_curr']    = 0;
4919:                 HTML2PDF::$_tables[$param['num']]['td_x']        = HTML2PDF::$_tables[$param['num']]['marge']['l']+HTML2PDF::$_tables[$param['num']]['curr_x'];
4920:                 HTML2PDF::$_tables[$param['num']]['td_y']        = HTML2PDF::$_tables[$param['num']]['marge']['t']+HTML2PDF::$_tables[$param['num']]['curr_y'];
4921: 
4922:                 // draw the borders/background of the first page/part of the table
4923:                 $this->_drawRectangle(
4924:                     HTML2PDF::$_tables[$param['num']]['curr_x'],
4925:                     HTML2PDF::$_tables[$param['num']]['curr_y'],
4926:                     HTML2PDF::$_tables[$param['num']]['width'],
4927:                     isset(HTML2PDF::$_tables[$param['num']]['height'][0]) ? HTML2PDF::$_tables[$param['num']]['height'][0] : null,
4928:                     $this->parsingCss->value['border'],
4929:                     $this->parsingCss->value['padding'],
4930:                     0,
4931:                     $this->parsingCss->value['background']
4932:                 );
4933: 
4934:                 HTML2PDF::$_tables[$param['num']]['style_value'] = $this->parsingCss->value;
4935:             }
4936: 
4937:             return true;
4938:         }
4939: 
4940:         /**
4941:          * tag : TABLE
4942:          * mode : CLOSE
4943:          *
4944:          * @param  array $param
4945:          * @return boolean
4946:          */
4947:         protected function _tag_close_TABLE($param)
4948:         {
4949:             if ($this->_isForOneLine) return false;
4950: 
4951:             $this->_maxH = 0;
4952: 
4953:             // if we are in a sub HTML
4954:             if ($this->_subPart) {
4955:                 // calculate the size of each case
4956:                 $this->_calculateTableCellSize(HTML2PDF::$_tables[$param['num']]['cases'], HTML2PDF::$_tables[$param['num']]['corr']);
4957: 
4958:                 // calculate the height of the thead and the tfoot
4959:                 $lst = array('thead', 'tfoot');
4960:                 foreach ($lst as $mode) {
4961:                     HTML2PDF::$_tables[$param['num']][$mode]['height'] = 0;
4962:                     foreach (HTML2PDF::$_tables[$param['num']][$mode]['tr'] as $tr) {
4963:                         // hauteur de la ligne tr
4964:                         $h = 0;
4965:                         for ($i=0; $i<count(HTML2PDF::$_tables[$param['num']]['cases'][$tr]); $i++)
4966:                             if (HTML2PDF::$_tables[$param['num']]['cases'][$tr][$i]['rowspan']==1)
4967:                                 $h = max($h, HTML2PDF::$_tables[$param['num']]['cases'][$tr][$i]['h']);
4968:                         HTML2PDF::$_tables[$param['num']][$mode]['height']+= $h;
4969:                     }
4970:                 }
4971: 
4972:                 // calculate the width of the table
4973:                 HTML2PDF::$_tables[$param['num']]['width'] = HTML2PDF::$_tables[$param['num']]['marge']['l'] + HTML2PDF::$_tables[$param['num']]['marge']['r'];
4974:                 if (isset(HTML2PDF::$_tables[$param['num']]['cases'][0])) {
4975:                     foreach (HTML2PDF::$_tables[$param['num']]['cases'][0] as $case) {
4976:                         HTML2PDF::$_tables[$param['num']]['width']+= $case['w'];
4977:                     }
4978:                 }
4979: 
4980:                 // X position of the table
4981:                 $old = $this->parsingCss->getOldValues();
4982:                 $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
4983:                 $x = HTML2PDF::$_tables[$param['num']]['curr_x'];
4984:                 $w = HTML2PDF::$_tables[$param['num']]['width'];
4985:                 if ($parentWidth>$w) {
4986:                     if (HTML2PDF::$_tables[$param['num']]['align']=='center')
4987:                         $x = $x + ($parentWidth-$w)*0.5;
4988:                     else if (HTML2PDF::$_tables[$param['num']]['align']=='right')
4989:                         $x = $x + $parentWidth-$w;
4990: 
4991:                     HTML2PDF::$_tables[$param['num']]['curr_x'] = $x;
4992:                 }
4993: 
4994:                 // calculate the height of the table
4995:                 HTML2PDF::$_tables[$param['num']]['height'] = array();
4996: 
4997:                 // minimum of the height because of margins, and of the thead and tfoot height
4998:                 $h0 = HTML2PDF::$_tables[$param['num']]['marge']['t'] + HTML2PDF::$_tables[$param['num']]['marge']['b'];
4999:                 $h0+= HTML2PDF::$_tables[$param['num']]['thead']['height'] + HTML2PDF::$_tables[$param['num']]['tfoot']['height'];
5000: 
5001:                 // max height of the page
5002:                 $max = $this->pdf->getH() - $this->pdf->getbMargin();
5003: 
5004:                 // current position on the page
5005:                 $y = HTML2PDF::$_tables[$param['num']]['curr_y'];
5006:                 $height = $h0;
5007: 
5008:                 // we get the height of each line
5009:                 for ($k=0; $k<count(HTML2PDF::$_tables[$param['num']]['cases']); $k++) {
5010: 
5011:                     // if it is a TR of the thead or of the tfoot => skip
5012:                     if (in_array($k, HTML2PDF::$_tables[$param['num']]['thead']['tr'])) continue;
5013:                     if (in_array($k, HTML2PDF::$_tables[$param['num']]['tfoot']['tr'])) continue;
5014: 
5015:                     // height of the line
5016:                     $th = 0;
5017:                     $h = 0;
5018:                     for ($i=0; $i<count(HTML2PDF::$_tables[$param['num']]['cases'][$k]); $i++) {
5019:                         $h = max($h, HTML2PDF::$_tables[$param['num']]['cases'][$k][$i]['h']);
5020: 
5021:                         if (HTML2PDF::$_tables[$param['num']]['cases'][$k][$i]['rowspan']==1)
5022:                             $th = max($th, HTML2PDF::$_tables[$param['num']]['cases'][$k][$i]['h']);
5023:                     }
5024: 
5025:                     // if the row does not fit on the page => new page
5026:                     if ($y+$h+$height>$max) {
5027:                         if ($height==$h0) $height = null;
5028:                         HTML2PDF::$_tables[$param['num']]['height'][] = $height;
5029:                         $height = $h0;
5030:                         $y = $this->_margeTop;
5031:                     }
5032:                     $height+= $th;
5033:                 }
5034: 
5035:                 // if ther is a height at the end, add it
5036:                 if ($height!=$h0 || $k==0) HTML2PDF::$_tables[$param['num']]['height'][] = $height;
5037:             } else {
5038:                 // if we have tfoor, draw it
5039:                 if (count(HTML2PDF::$_tables[$param['num']]['tfoot']['code'])) {
5040:                     $tmpTR = HTML2PDF::$_tables[$param['num']]['tr_curr'];
5041:                     $tmpTD = HTML2PDF::$_tables[$param['num']]['td_curr'];
5042:                     $oldParsePos = $this->_parsePos;
5043:                     $oldParseCode = $this->parsingHtml->code;
5044: 
5045:                     HTML2PDF::$_tables[$param['num']]['tr_curr'] = HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0];
5046:                     HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
5047:                     $this->_parsePos = 0;
5048:                     $this->parsingHtml->code = HTML2PDF::$_tables[$param['num']]['tfoot']['code'];
5049:                     $this->_isInTfoot = true;
5050:                     $this->_makeHTMLcode();
5051:                     $this->_isInTfoot = false;
5052: 
5053:                     $this->_parsePos =     $oldParsePos;
5054:                     $this->parsingHtml->code = $oldParseCode;
5055:                     HTML2PDF::$_tables[$param['num']]['tr_curr'] = $tmpTR;
5056:                     HTML2PDF::$_tables[$param['num']]['td_curr'] = $tmpTD;
5057:                 }
5058: 
5059:                 // get the positions of the end of the table
5060:                 $x = HTML2PDF::$_tables[$param['num']]['curr_x'] + HTML2PDF::$_tables[$param['num']]['width'];
5061:                 if (count(HTML2PDF::$_tables[$param['num']]['height'])>1)
5062:                     $y = $this->_margeTop+HTML2PDF::$_tables[$param['num']]['height'][count(HTML2PDF::$_tables[$param['num']]['height'])-1];
5063:                 else if (count(HTML2PDF::$_tables[$param['num']]['height'])==1)
5064:                     $y = HTML2PDF::$_tables[$param['num']]['curr_y']+HTML2PDF::$_tables[$param['num']]['height'][count(HTML2PDF::$_tables[$param['num']]['height'])-1];
5065:                 else
5066:                     $y = HTML2PDF::$_tables[$param['num']]['curr_y'];
5067: 
5068:                 $this->_maxX = max($this->_maxX, $x);
5069:                 $this->_maxY = max($this->_maxY, $y);
5070: 
5071:                 $this->pdf->setXY($this->pdf->getlMargin(), $y);
5072: 
5073:                 $this->_loadMargin();
5074: 
5075:                 if ($this->_debugActif) $this->_DEBUG_add('Table '.$param['num'], false);
5076:             }
5077: 
5078:             $this->parsingCss->load();
5079:             $this->parsingCss->fontSet();
5080: 
5081: 
5082:             return true;
5083:         }
5084: 
5085:         /**
5086:          * tag : COL
5087:          * mode : OPEN
5088:          *
5089:          * @param  array $param
5090:          * @return boolean
5091:          */
5092:         protected function _tag_open_COL($param)
5093:         {
5094:             $span = isset($param['span']) ? $param['span'] : 1;
5095:             for ($k=0; $k<$span; $k++)
5096:                 HTML2PDF::$_tables[$param['num']]['cols'][] = $param;
5097:         }
5098: 
5099:         /**
5100:          * tag : COL
5101:          * mode : CLOSE
5102:          *
5103:          * @param  array $param
5104:          * @return boolean
5105:          */
5106:         protected function _tag_close_COL($param)
5107:         {
5108:             // there is nothing to do here
5109: 
5110:             return true;
5111:         }
5112: 
5113:         /**
5114:          * tag : TR
5115:          * mode : OPEN
5116:          *
5117:          * @param  array $param
5118:          * @return boolean
5119:          */
5120:         protected function _tag_open_TR($param, $other = 'tr')
5121:         {
5122:             if ($this->_isForOneLine) return false;
5123: 
5124:             $this->_maxH = 0;
5125: 
5126:             $this->parsingCss->save();
5127:             $this->parsingCss->analyse($other, $param);
5128:             $this->parsingCss->setPosition();
5129:             $this->parsingCss->fontSet();
5130: 
5131:             // position in the table
5132:             HTML2PDF::$_tables[$param['num']]['tr_curr']++;
5133:             HTML2PDF::$_tables[$param['num']]['td_curr']= 0;
5134: 
5135:             // if we are not in a sub html
5136:             if (!$this->_subPart) {
5137: 
5138:                 // Y after the row
5139:                 $ty=null;
5140:                 for ($ii=0; $ii<count(HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1]); $ii++) {
5141:                     $ty = max($ty, HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][$ii]['h']);
5142:                 }
5143: 
5144:                 // height of the tfoot
5145:                 $hfoot = HTML2PDF::$_tables[$param['num']]['tfoot']['height'];
5146: 
5147:                 // if the line does not fit on the page => new page
5148:                 if (!$this->_isInTfoot && HTML2PDF::$_tables[$param['num']]['td_y'] + HTML2PDF::$_tables[$param['num']]['marge']['b'] + $ty +$hfoot> $this->pdf->getH() - $this->pdf->getbMargin()) {
5149: 
5150:                     // fi ther is a tfoot => draw it
5151:                     if (count(HTML2PDF::$_tables[$param['num']]['tfoot']['code'])) {
5152:                         $tmpTR = HTML2PDF::$_tables[$param['num']]['tr_curr'];
5153:                         $tmpTD = HTML2PDF::$_tables[$param['num']]['td_curr'];
5154:                         $oldParsePos = $this->_parsePos;
5155:                         $oldParseCode = $this->parsingHtml->code;
5156: 
5157:                         HTML2PDF::$_tables[$param['num']]['tr_curr'] = HTML2PDF::$_tables[$param['num']]['tfoot']['tr'][0];
5158:                         HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
5159:                         $this->_parsePos = 0;
5160:                         $this->parsingHtml->code = HTML2PDF::$_tables[$param['num']]['tfoot']['code'];
5161:                         $this->_isInTfoot = true;
5162:                         $this->_makeHTMLcode();
5163:                         $this->_isInTfoot = false;
5164: 
5165:                         $this->_parsePos =     $oldParsePos;
5166:                         $this->parsingHtml->code = $oldParseCode;
5167:                         HTML2PDF::$_tables[$param['num']]['tr_curr'] = $tmpTR;
5168:                         HTML2PDF::$_tables[$param['num']]['td_curr'] = $tmpTD;
5169:                     }
5170: 
5171:                     // new page
5172:                     HTML2PDF::$_tables[$param['num']]['new_page'] = true;
5173:                     $this->_setNewPage();
5174: 
5175:                     // new position
5176:                     HTML2PDF::$_tables[$param['num']]['page']++;
5177:                     HTML2PDF::$_tables[$param['num']]['curr_y'] = $this->pdf->getY();
5178:                     HTML2PDF::$_tables[$param['num']]['td_y'] = HTML2PDF::$_tables[$param['num']]['curr_y']+HTML2PDF::$_tables[$param['num']]['marge']['t'];
5179: 
5180:                     // if we have the height of the tbale on the page => draw borders and background
5181:                     if (isset(HTML2PDF::$_tables[$param['num']]['height'][HTML2PDF::$_tables[$param['num']]['page']])) {
5182:                         $old = $this->parsingCss->value;
5183:                         $this->parsingCss->value = HTML2PDF::$_tables[$param['num']]['style_value'];
5184: 
5185:                         $this->_drawRectangle(
5186:                             HTML2PDF::$_tables[$param['num']]['curr_x'],
5187:                             HTML2PDF::$_tables[$param['num']]['curr_y'],
5188:                             HTML2PDF::$_tables[$param['num']]['width'],
5189:                             HTML2PDF::$_tables[$param['num']]['height'][HTML2PDF::$_tables[$param['num']]['page']],
5190:                             $this->parsingCss->value['border'],
5191:                             $this->parsingCss->value['padding'],
5192:                             HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5,
5193:                             $this->parsingCss->value['background']
5194:                         );
5195: 
5196:                         $this->parsingCss->value = $old;
5197:                     }
5198:                 }
5199: 
5200:                 // if we are in a new page, and if we have a thead => draw it
5201:                 if (HTML2PDF::$_tables[$param['num']]['new_page'] && count(HTML2PDF::$_tables[$param['num']]['thead']['code'])) {
5202:                     HTML2PDF::$_tables[$param['num']]['new_page'] = false;
5203:                     $tmpTR = HTML2PDF::$_tables[$param['num']]['tr_curr'];
5204:                     $tmpTD = HTML2PDF::$_tables[$param['num']]['td_curr'];
5205:                     $oldParsePos = $this->_parsePos;
5206:                     $oldParseCode = $this->parsingHtml->code;
5207: 
5208:                     HTML2PDF::$_tables[$param['num']]['tr_curr'] = HTML2PDF::$_tables[$param['num']]['thead']['tr'][0];
5209:                     HTML2PDF::$_tables[$param['num']]['td_curr'] = 0;
5210:                     $this->_parsePos = 0;
5211:                     $this->parsingHtml->code = HTML2PDF::$_tables[$param['num']]['thead']['code'];
5212:                     $this->_isInThead = true;
5213:                     $this->_makeHTMLcode();
5214:                     $this->_isInThead = false;
5215: 
5216:                     $this->_parsePos =     $oldParsePos;
5217:                     $this->parsingHtml->code = $oldParseCode;
5218:                     HTML2PDF::$_tables[$param['num']]['tr_curr'] = $tmpTR;
5219:                     HTML2PDF::$_tables[$param['num']]['td_curr'] = $tmpTD;
5220:                     HTML2PDF::$_tables[$param['num']]['new_page'] = true;
5221:                 }
5222:             // else (in a sub HTML)
5223:             } else {
5224:                 // prepare it
5225:                 HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1] = array();
5226:                 if (!isset(HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']]))
5227:                     HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']] = array();
5228: 
5229:                 HTML2PDF::$_tables[$param['num']]['corr_x']=0;
5230:                 while(isset(HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']][HTML2PDF::$_tables[$param['num']]['corr_x']]))
5231:                     HTML2PDF::$_tables[$param['num']]['corr_x']++;
5232:             }
5233: 
5234:             return true;
5235:         }
5236: 
5237:         /**
5238:          * tag : TR
5239:          * mode : CLOSE
5240:          *
5241:          * @param  array $param
5242:          * @return boolean
5243:          */
5244:         protected function _tag_close_TR($param)
5245:         {
5246:             if ($this->_isForOneLine) return false;
5247: 
5248:             $this->_maxH = 0;
5249: 
5250:             $this->parsingCss->load();
5251:             $this->parsingCss->fontSet();
5252: 
5253:             // if we are not in a sub HTML
5254:             if (!$this->_subPart) {
5255: 
5256:                 // Y of the current line
5257:                 $ty=null;
5258:                 for ($ii=0; $ii<count(HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1]); $ii++) {
5259:                     if (HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][$ii]['rowspan']==1) {
5260:                         $ty = HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][$ii]['h'];
5261:                     }
5262:                 }
5263: 
5264:                 // new position
5265:                 HTML2PDF::$_tables[$param['num']]['td_x'] = HTML2PDF::$_tables[$param['num']]['curr_x']+HTML2PDF::$_tables[$param['num']]['marge']['l'];
5266:                 HTML2PDF::$_tables[$param['num']]['td_y']+= $ty;
5267:                 HTML2PDF::$_tables[$param['num']]['new_page'] = false;
5268:             } else {
5269:                 HTML2PDF::$_tables[$param['num']]['corr_y']++;
5270:             }
5271: 
5272:             return true;
5273:         }
5274: 
5275:         /**
5276:          * tag : TD
5277:          * mode : OPEN
5278:          *
5279:          * @param  array $param
5280:          * @return boolean
5281:          */
5282:         protected function _tag_open_TD($param, $other = 'td')
5283:         {
5284:             if ($this->_isForOneLine) return false;
5285: 
5286:             $this->_maxH = 0;
5287: 
5288:             $param['cellpadding'] = HTML2PDF::$_tables[$param['num']]['cellpadding'].'mm';
5289:             $param['cellspacing'] = HTML2PDF::$_tables[$param['num']]['cellspacing'].'mm';
5290: 
5291:             // specific style for LI
5292:             if ($other=='li') {
5293:                 $specialLi = true;
5294:             } else {
5295:                 $specialLi = false;
5296:                 if ($other=='li_sub') {
5297:                     $param['style']['border'] = 'none';
5298:                     $param['style']['background-color']    = 'transparent';
5299:                     $param['style']['background-image']    = 'none';
5300:                     $param['style']['background-position'] = '';
5301:                     $param['style']['background-repeat']   = '';
5302:                     $other = 'li';
5303:                 }
5304:             }
5305: 
5306:             // get the properties of the TD
5307:             $x = HTML2PDF::$_tables[$param['num']]['td_curr'];
5308:             $y = HTML2PDF::$_tables[$param['num']]['tr_curr']-1;
5309:             $colspan = isset($param['colspan']) ? $param['colspan'] : 1;
5310:             $rowspan = isset($param['rowspan']) ? $param['rowspan'] : 1;
5311: 
5312:             // flag for collapse table
5313:             $collapse = false;
5314: 
5315:             // specific traitment for TD and TH
5316:             if (in_array($other, array('td', 'th'))) {
5317:                 // id of the column
5318:                 $numCol = isset(HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Xr']) ? HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Xr'] : HTML2PDF::$_tables[$param['num']]['corr_x'];
5319: 
5320:                 // we get the properties of the COL tag, if exist
5321:                 if (isset(HTML2PDF::$_tables[$param['num']]['cols'][$numCol])) {
5322: 
5323:                     $colParam = HTML2PDF::$_tables[$param['num']]['cols'][$numCol];
5324: 
5325:                     // for colspans => we get all the neede widths
5326:                     $colParam['style']['width'] = array();
5327:                     for ($k=0; $k<$colspan; $k++) {
5328:                         if (isset(HTML2PDF::$_tables[$param['num']]['cols'][$numCol+$k]['style']['width'])) {
5329:                             $colParam['style']['width'][] = HTML2PDF::$_tables[$param['num']]['cols'][$numCol+$k]['style']['width'];
5330:                         }
5331:                     }
5332: 
5333:                     // calculate the total width of the column
5334:                     $total = '';
5335:                     $last = $this->parsingCss->getLastWidth();
5336:                     if (count($colParam['style']['width'])) {
5337:                         $total = $colParam['style']['width'][0]; unset($colParam['style']['width'][0]);
5338:                         foreach ($colParam['style']['width'] as $width) {
5339:                             if (substr($total, -1)=='%' && substr($width, -1)=='%')
5340:                                 $total = (str_replace('%', '', $total)+str_replace('%', '', $width)).'%';
5341:                             else
5342:                                 $total = ($this->parsingCss->ConvertToMM($total, $last) + $this->parsingCss->ConvertToMM($width, $last)).'mm';
5343:                         }
5344:                     }
5345: 
5346:                     // get the final width
5347:                     if ($total) {
5348:                         $colParam['style']['width'] = $total;
5349:                     } else {
5350:                         unset($colParam['style']['width']);
5351:                     }
5352: 
5353: 
5354:                     // merge the styles of the COL and the TD
5355:                     $param['style'] = array_merge($colParam['style'], $param['style']);
5356: 
5357:                     // merge the class of the COL and the TD
5358:                     if (isset($colParam['class'])) {
5359:                         $param['class'] = $colParam['class'].(isset($param['class']) ? ' '.$param['class'] : '');
5360:                     }
5361:                 }
5362: 
5363:                 $collapse = isset($this->parsingCss->value['border']['collapse']) ? $this->parsingCss->value['border']['collapse'] : false;
5364:             }
5365: 
5366:             $this->parsingCss->save();
5367: 
5368:             // legacy for TD and TH
5369:             $legacy = null;
5370:             if (in_array($other, array('td', 'th'))) {
5371:                 $legacy = array();
5372: 
5373:                 $old = $this->parsingCss->getLastValue('background');
5374:                 if ($old && ($old['color'] || $old['image']))
5375:                     $legacy['background'] = $old;
5376: 
5377:                 if (HTML2PDF::$_tables[$param['num']]['border']) {
5378:                     $legacy['border'] = array();
5379:                     $legacy['border']['l'] = HTML2PDF::$_tables[$param['num']]['border'];
5380:                     $legacy['border']['t'] = HTML2PDF::$_tables[$param['num']]['border'];
5381:                     $legacy['border']['r'] = HTML2PDF::$_tables[$param['num']]['border'];
5382:                     $legacy['border']['b'] = HTML2PDF::$_tables[$param['num']]['border'];
5383:                 }
5384:             }
5385:             $return = $this->parsingCss->analyse($other, $param, $legacy);
5386: 
5387:             if ($specialLi) {
5388:                 $this->parsingCss->value['width']-= $this->parsingCss->ConvertToMM($this->_listeGetWidth());
5389:                 $this->parsingCss->value['width']-= $this->parsingCss->ConvertToMM($this->_listeGetPadding());
5390:             }
5391:             $this->parsingCss->setPosition();
5392:             $this->parsingCss->fontSet();
5393: 
5394:             // if tale collapse => modify the borders
5395:             if ($collapse) {
5396:                 if (!$this->_subPart) {
5397:                     if (
5398:                         (HTML2PDF::$_tables[$param['num']]['tr_curr']>1 && !HTML2PDF::$_tables[$param['num']]['new_page']) ||
5399:                         (!$this->_isInThead && count(HTML2PDF::$_tables[$param['num']]['thead']['code']))
5400:                     ) {
5401:                         $this->parsingCss->value['border']['t'] = $this->parsingCss->readBorder('none');
5402:                     }
5403:                 }
5404: 
5405:                 if (HTML2PDF::$_tables[$param['num']]['td_curr']>0) {
5406:                     if (!$return) $this->parsingCss->value['width']+= $this->parsingCss->value['border']['l']['width'];
5407:                     $this->parsingCss->value['border']['l'] = $this->parsingCss->readBorder('none');
5408:                 }
5409:             }
5410: 
5411:             // margins of the table
5412:             $marge = array();
5413:             $marge['t'] = $this->parsingCss->value['padding']['t']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['t']['width'];
5414:             $marge['r'] = $this->parsingCss->value['padding']['r']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['r']['width'];
5415:             $marge['b'] = $this->parsingCss->value['padding']['b']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['b']['width'];
5416:             $marge['l'] = $this->parsingCss->value['padding']['l']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['l']['width'];
5417: 
5418:             // if we are in a sub HTML
5419:             if ($this->_subPart) {
5420:                 // new position in the table
5421:                 HTML2PDF::$_tables[$param['num']]['td_curr']++;
5422:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x] = array();
5423:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['w'] = 0;
5424:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['h'] = 0;
5425:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['dw'] = 0;
5426:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['colspan'] = $colspan;
5427:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['rowspan'] = $rowspan;
5428:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Xr'] = HTML2PDF::$_tables[$param['num']]['corr_x'];
5429:                 HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['Yr'] = HTML2PDF::$_tables[$param['num']]['corr_y'];
5430: 
5431:                 // prepare the mapping for rowspan and colspan
5432:                 for ($j=0; $j<$rowspan; $j++) {
5433:                     for ($i=0; $i<$colspan; $i++) {
5434:                         HTML2PDF::$_tables[$param['num']]['corr']
5435:                             [HTML2PDF::$_tables[$param['num']]['corr_y']+$j]
5436:                             [HTML2PDF::$_tables[$param['num']]['corr_x']+$i] = ($i+$j>0) ? '' : array($x,$y,$colspan,$rowspan);
5437:                     }
5438:                 }
5439:                 HTML2PDF::$_tables[$param['num']]['corr_x']+= $colspan;
5440:                 while (isset(HTML2PDF::$_tables[$param['num']]['corr'][HTML2PDF::$_tables[$param['num']]['corr_y']][HTML2PDF::$_tables[$param['num']]['corr_x']])) {
5441:                     HTML2PDF::$_tables[$param['num']]['corr_x']++;
5442:                 }
5443: 
5444:                 // extract the content of the TD, and calculate his size
5445:                 $level = $this->parsingHtml->getLevel($this->_tempPos);
5446:                 $this->_createSubHTML($this->_subHtml);
5447:                 $this->_subHtml->parsingHtml->code = $level;
5448:                 $this->_subHtml->_makeHTMLcode();
5449:                 $this->_tempPos+= count($level);
5450:             } else {
5451:                 // new position in the table
5452:                 HTML2PDF::$_tables[$param['num']]['td_curr']++;
5453:                 HTML2PDF::$_tables[$param['num']]['td_x']+= HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['dw'];
5454: 
5455:                 // borders and background of the TD
5456:                 $this->_drawRectangle(
5457:                     HTML2PDF::$_tables[$param['num']]['td_x'],
5458:                     HTML2PDF::$_tables[$param['num']]['td_y'],
5459:                     HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['w'],
5460:                     HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['h'],
5461:                     $this->parsingCss->value['border'],
5462:                     $this->parsingCss->value['padding'],
5463:                     HTML2PDF::$_tables[$param['num']]['cellspacing']*0.5,
5464:                     $this->parsingCss->value['background']
5465:                 );
5466: 
5467:                 $this->parsingCss->value['width'] = HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['w'] - $marge['l'] - $marge['r'];
5468: 
5469:                 // marges = size of the TD
5470:                 $mL = HTML2PDF::$_tables[$param['num']]['td_x']+$marge['l'];
5471:                 $mR = $this->pdf->getW() - $mL - $this->parsingCss->value['width'];
5472:                 $this->_saveMargin($mL, 0, $mR);
5473: 
5474:                 // position of the content, from vertical-align
5475:                 $hCorr = HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['h'];
5476:                 $hReel = HTML2PDF::$_tables[$param['num']]['cases'][$y][$x]['real_h'];
5477:                 switch($this->parsingCss->value['vertical-align'])
5478:                 {
5479:                     case 'bottom':
5480:                         $yCorr = $hCorr-$hReel;
5481:                         break;
5482: 
5483:                     case 'middle':
5484:                         $yCorr = ($hCorr-$hReel)*0.5;
5485:                         break;
5486: 
5487:                     case 'top':
5488:                     default:
5489:                         $yCorr = 0;
5490:                         break;
5491:                 }
5492: 
5493:                 //  position of the content
5494:                 $x = HTML2PDF::$_tables[$param['num']]['td_x']+$marge['l'];
5495:                 $y = HTML2PDF::$_tables[$param['num']]['td_y']+$marge['t']+$yCorr;
5496:                 $this->pdf->setXY($x, $y);
5497:                 $this->_setNewPositionForNewLine();
5498:             }
5499: 
5500:             return true;
5501:         }
5502: 
5503:         /**
5504:          * tag : TD
5505:          * mode : CLOSE
5506:          *
5507:          * @param    array $param
5508:          * @return boolean
5509:          */
5510:         protected function _tag_close_TD($param)
5511:         {
5512:             if ($this->_isForOneLine) return false;
5513: 
5514:             $this->_maxH = 0;
5515: 
5516:             // get the margins
5517:             $marge = array();
5518:             $marge['t'] = $this->parsingCss->value['padding']['t']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['t']['width'];
5519:             $marge['r'] = $this->parsingCss->value['padding']['r']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['r']['width'];
5520:             $marge['b'] = $this->parsingCss->value['padding']['b']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['b']['width'];
5521:             $marge['l'] = $this->parsingCss->value['padding']['l']+0.5*HTML2PDF::$_tables[$param['num']]['cellspacing']+$this->parsingCss->value['border']['l']['width'];
5522:             $marge['t']+= 0.001;
5523:             $marge['r']+= 0.001;
5524:             $marge['b']+= 0.001;
5525:             $marge['l']+= 0.001;
5526: 
5527:             // if we are in a sub HTML
5528:             if ($this->_subPart) {
5529: 
5530:                 // it msut take only one page
5531:                 if ($this->_testTdInOnepage && $this->_subHtml->pdf->getPage()>1) {
5532:                     throw new HTML2PDF_exception(7);
5533:                 }
5534: 
5535:                 // size of the content of the TD
5536:                 $w0 = $this->_subHtml->_maxX + $marge['l'] + $marge['r'];
5537:                 $h0 = $this->_subHtml->_maxY + $marge['t'] + $marge['b'];
5538: 
5539:                 // size from the CSS style
5540:                 $w2 = $this->parsingCss->value['width'] + $marge['l'] + $marge['r'];
5541:                 $h2 = $this->parsingCss->value['height'] + $marge['t'] + $marge['b'];
5542: 
5543:                 // final size of the TD
5544:                 HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['w'] = max(array($w0, $w2));
5545:                 HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['h'] = max(array($h0, $h2));
5546: 
5547:                 // real position of the content
5548:                 HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['real_w'] = $w0;
5549:                 HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['real_h'] = $h0;
5550: 
5551:                 // destroy the sub HTML
5552:                 $this->_destroySubHTML($this->_subHtml);
5553:             } else {
5554:                 $this->_loadMargin();
5555: 
5556:                 HTML2PDF::$_tables[$param['num']]['td_x']+= HTML2PDF::$_tables[$param['num']]['cases'][HTML2PDF::$_tables[$param['num']]['tr_curr']-1][HTML2PDF::$_tables[$param['num']]['td_curr']-1]['w'];
5557:             }
5558: 
5559:             $this->parsingCss->load();
5560:             $this->parsingCss->fontSet();
5561: 
5562:             return true;
5563:         }
5564: 
5565: 
5566:         /**
5567:          * tag : TH
5568:          * mode : OPEN
5569:          *
5570:          * @param  array $param
5571:          * @return boolean
5572:          */
5573:         protected function _tag_open_TH($param)
5574:         {
5575:             if ($this->_isForOneLine) return false;
5576: 
5577:             $this->parsingCss->save();
5578:             $this->parsingCss->value['font-bold'] = true;
5579: 
5580:             $this->_tag_open_TD($param, 'th');
5581: 
5582:             return true;
5583:         }
5584: 
5585:         /**
5586:          * tag : TH
5587:          * mode : CLOSE
5588:          *
5589:          * @param  array $param
5590:          * @return boolean
5591:          */
5592:         protected function _tag_close_TH($param)
5593:         {
5594:             if ($this->_isForOneLine) return false;
5595: 
5596:             $this->_tag_close_TD($param);
5597: 
5598:             $this->parsingCss->load();
5599: 
5600:             return true;
5601:         }
5602: 
5603:         /**
5604:          * tag : IMG
5605:          * mode : OPEN
5606:          *
5607:          * @param  array $param
5608:          * @return boolean
5609:          */
5610:         protected function _tag_open_IMG($param)
5611:         {
5612:             $src    = str_replace('&amp;', '&', $param['src']);
5613: 
5614:             $this->parsingCss->save();
5615:             $this->parsingCss->value['width']    = 0;
5616:             $this->parsingCss->value['height']    = 0;
5617:             $this->parsingCss->value['border']    = array('type' => 'none', 'width' => 0, 'color' => array(0, 0, 0));
5618:             $this->parsingCss->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
5619:             $this->parsingCss->analyse('img', $param);
5620:             $this->parsingCss->setPosition();
5621:             $this->parsingCss->fontSet();
5622: 
5623:             $res = $this->_drawImage($src, isset($param['sub_li']));
5624:             if (!$res) return $res;
5625: 
5626:             $this->parsingCss->load();
5627:             $this->parsingCss->fontSet();
5628:             $this->_maxE++;
5629: 
5630:             return true;
5631:         }
5632: 
5633:         /**
5634:          * tag : SELECT
5635:          * mode : OPEN
5636:          *
5637:          * @param  array $param
5638:          * @return boolean
5639:          */
5640:         protected function _tag_open_SELECT($param)
5641:         {
5642:             if (!isset($param['name'])) {
5643:                 $param['name'] = 'champs_pdf_'.(count($this->_lstField)+1);
5644:             }
5645: 
5646:             $param['name'] = strtolower($param['name']);
5647: 
5648:             if (isset($this->_lstField[$param['name']])) {
5649:                 $this->_lstField[$param['name']]++;
5650:             } else {
5651:                 $this->_lstField[$param['name']] = 1;
5652:             }
5653: 
5654:             $this->parsingCss->save();
5655:             $this->parsingCss->analyse('select', $param);
5656:             $this->parsingCss->setPosition();
5657:             $this->parsingCss->fontSet();
5658: 
5659:             $this->_lstSelect = array();
5660:             $this->_lstSelect['name']    = $param['name'];
5661:             $this->_lstSelect['multi']    = isset($param['multiple']) ? true : false;
5662:             $this->_lstSelect['size']    = isset($param['size']) ? $param['size'] : 1;
5663:             $this->_lstSelect['options']    = array();
5664: 
5665:             if ($this->_lstSelect['multi'] && $this->_lstSelect['size']<3) $this->_lstSelect['size'] = 3;
5666: 
5667:             return true;
5668:         }
5669: 
5670:         /**
5671:          * tag : OPTION
5672:          * mode : OPEN
5673:          *
5674:          * @param    array $param
5675:          * @return boolean
5676:          */
5677:         protected function _tag_open_OPTION($param)
5678:         {
5679:             // get the content of the option : it is the text of the option
5680:             $level = $this->parsingHtml->getLevel($this->_parsePos);
5681:             $this->_parsePos+= count($level);
5682:             $value = isset($param['value']) ? $param['value'] : 'aut_tag_open_opt_'.(count($this->_lstSelect)+1);
5683: 
5684:             $this->_lstSelect['options'][$value] = isset($level[0]['param']['txt']) ? $level[0]['param']['txt'] : '';
5685: 
5686:             return true;
5687:         }
5688: 
5689:         /**
5690:          * tag : OPTION
5691:          * mode : CLOSE
5692:          *
5693:          * @param    array $param
5694:          * @return boolean
5695:          */
5696:         protected function _tag_close_OPTION($param)
5697:         {
5698:             // nothing to do here
5699: 
5700:             return true;
5701:         }
5702: 
5703:         /**
5704:          * tag : SELECT
5705:          * mode : CLOSE
5706:          *
5707:          * @param  array $param
5708:          * @return boolean
5709:          */
5710:         protected function _tag_close_SELECT()
5711:         {
5712:             // position of the select
5713:             $x = $this->pdf->getX();
5714:             $y = $this->pdf->getY();
5715:             $f = 1.08*$this->parsingCss->value['font-size'];
5716: 
5717:             // width
5718:             $w = $this->parsingCss->value['width']; if (!$w) $w = 50;
5719: 
5720:             // height (automatic)
5721:             $h = ($f*1.07*$this->_lstSelect['size'] + 1);
5722: 
5723:             $prop = $this->parsingCss->getFormStyle();
5724: 
5725:             // multy select
5726:             if ($this->_lstSelect['multi']) {
5727:                 $prop['multipleSelection'] = 'true';
5728:             }
5729: 
5730: 
5731:             // single or multi select
5732:             if ($this->_lstSelect['size']>1) {
5733:                 $this->pdf->ListBox($this->_lstSelect['name'], $w, $h, $this->_lstSelect['options'], $prop);
5734:             } else {
5735:                 $this->pdf->ComboBox($this->_lstSelect['name'], $w, $h, $this->_lstSelect['options'], $prop);
5736:             }
5737: 
5738:             $this->_maxX = max($this->_maxX, $x+$w);
5739:             $this->_maxY = max($this->_maxY, $y+$h);
5740:             $this->_maxH = max($this->_maxH, $h);
5741:             $this->_maxE++;
5742:             $this->pdf->setX($x+$w);
5743: 
5744:             $this->parsingCss->load();
5745:             $this->parsingCss->fontSet();
5746: 
5747:             $this->_lstSelect = array();
5748: 
5749:             return true;
5750:         }
5751: 
5752:         /**
5753:          * tag : TEXTAREA
5754:          * mode : OPEN
5755:          *
5756:          * @param    array $param
5757:          * @return boolean
5758:          */
5759:         protected function _tag_open_TEXTAREA($param)
5760:         {
5761:             if (!isset($param['name'])) {
5762:                 $param['name'] = 'champs_pdf_'.(count($this->_lstField)+1);
5763:             }
5764: 
5765:             $param['name'] = strtolower($param['name']);
5766: 
5767:             if (isset($this->_lstField[$param['name']])) {
5768:                 $this->_lstField[$param['name']]++;
5769:             } else {
5770:                 $this->_lstField[$param['name']] = 1;
5771:             }
5772: 
5773:             $this->parsingCss->save();
5774:             $this->parsingCss->analyse('textarea', $param);
5775:             $this->parsingCss->setPosition();
5776:             $this->parsingCss->fontSet();
5777: 
5778:             $x = $this->pdf->getX();
5779:             $y = $this->pdf->getY();
5780:             $fx = 0.65*$this->parsingCss->value['font-size'];
5781:             $fy = 1.08*$this->parsingCss->value['font-size'];
5782: 
5783:             // extract the content the textarea : value
5784:             $level = $this->parsingHtml->getLevel($this->_parsePos);
5785:             $this->_parsePos+= count($level);
5786: 
5787:             // automatic size, from cols and rows properties
5788:             $w = $fx*(isset($param['cols']) ? $param['cols'] : 22)+1;
5789:             $h = $fy*1.07*(isset($param['rows']) ? $param['rows'] : 3)+3;
5790: 
5791:             $prop = $this->parsingCss->getFormStyle();
5792: 
5793:             $prop['multiline'] = true;
5794:             $prop['value'] = isset($level[0]['param']['txt']) ? $level[0]['param']['txt'] : '';
5795: 
5796:             $this->pdf->TextField($param['name'], $w, $h, $prop, array(), $x, $y);
5797: 
5798:             $this->_maxX = max($this->_maxX, $x+$w);
5799:             $this->_maxY = max($this->_maxY, $y+$h);
5800:             $this->_maxH = max($this->_maxH, $h);
5801:             $this->_maxE++;
5802:             $this->pdf->setX($x+$w);
5803: 
5804:             return true;
5805:         }
5806: 
5807:         /**
5808:          * tag : TEXTAREA
5809:          * mode : CLOSE
5810:          *
5811:          * @param  array $param
5812:          * @return boolean
5813:          */
5814:         protected function _tag_close_TEXTAREA()
5815:         {
5816:             $this->parsingCss->load();
5817:             $this->parsingCss->fontSet();
5818: 
5819:             return true;
5820:         }
5821: 
5822:         /**
5823:          * tag : INPUT
5824:          * mode : OPEN
5825:          *
5826:          * @param  array $param
5827:          * @return boolean
5828:          */
5829:         protected function _tag_open_INPUT($param)
5830:         {
5831:             if (!isset($param['name']))  $param['name']  = 'champs_pdf_'.(count($this->_lstField)+1);
5832:             if (!isset($param['value'])) $param['value'] = '';
5833:             if (!isset($param['type']))  $param['type']  = 'text';
5834: 
5835:             $param['name'] = strtolower($param['name']);
5836:             $param['type'] = strtolower($param['type']);
5837: 
5838:             // the type must be valid
5839:             if (!in_array($param['type'], array('text', 'checkbox', 'radio', 'hidden', 'submit', 'reset', 'button'))) {
5840:                 $param['type'] = 'text';
5841:             }
5842: 
5843:             if (isset($this->_lstField[$param['name']])) {
5844:                 $this->_lstField[$param['name']]++;
5845:             } else {
5846:                 $this->_lstField[$param['name']] = 1;
5847:             }
5848: 
5849:             $this->parsingCss->save();
5850:             $this->parsingCss->analyse('input', $param);
5851:             $this->parsingCss->setPosition();
5852:             $this->parsingCss->fontSet();
5853: 
5854:             $name = $param['name'];
5855: 
5856:             $x = $this->pdf->getX();
5857:             $y = $this->pdf->getY();
5858:             $f = 1.08*$this->parsingCss->value['font-size'];
5859: 
5860:             $prop = $this->parsingCss->getFormStyle();
5861: 
5862:             switch($param['type'])
5863:             {
5864:                 case 'checkbox':
5865:                     $w = 3;
5866:                     $h = $w;
5867:                     if ($h<$f) $y+= ($f-$h)*0.5;
5868:                     $checked = (isset($param['checked']) && $param['checked']=='checked');
5869:                     $this->pdf->CheckBox($name, $w, $checked, $prop, array(), ($param['value'] ? $param['value'] : 'Yes'), $x, $y);
5870:                     break;
5871: 
5872:                 case 'radio':
5873:                     $w = 3;
5874:                     $h = $w;
5875:                     if ($h<$f) $y+= ($f-$h)*0.5;
5876:                     $checked = (isset($param['checked']) && $param['checked']=='checked');
5877:                     $this->pdf->RadioButton($name, $w, $prop, array(), ($param['value'] ? $param['value'] : 'On'), $checked, $x, $y);
5878:                     break;
5879: 
5880:                 case 'hidden':
5881:                     $w = 0;
5882:                     $h = 0;
5883:                     $prop['value'] = $param['value'];
5884:                     $this->pdf->TextField($name, $w, $h, $prop, array(), $x, $y);
5885:                     break;
5886: 
5887:                 case 'text':
5888:                     $w = $this->parsingCss->value['width']; if (!$w) $w = 40;
5889:                     $h = $f*1.3;
5890:                     $prop['value'] = $param['value'];
5891:                     $this->pdf->TextField($name, $w, $h, $prop, array(), $x, $y);
5892:                     break;
5893: 
5894:                 case 'submit':
5895:                     $w = $this->parsingCss->value['width'];    if (!$w) $w = 40;
5896:                     $h = $this->parsingCss->value['height'];    if (!$h) $h = $f*1.3;
5897:                     $action = array('S'=>'SubmitForm', 'F'=>$this->_isInForm, 'Flags'=>array('ExportFormat'));
5898:                     $this->pdf->Button($name, $w, $h, $param['value'], $action, $prop, array(), $x, $y);
5899:                     break;
5900: 
5901:                 case 'reset':
5902:                     $w = $this->parsingCss->value['width'];    if (!$w) $w = 40;
5903:                     $h = $this->parsingCss->value['height'];    if (!$h) $h = $f*1.3;
5904:                     $action = array('S'=>'ResetForm');
5905:                     $this->pdf->Button($name, $w, $h, $param['value'], $action, $prop, array(), $x, $y);
5906:                     break;
5907: 
5908:                 case 'button':
5909:                     $w = $this->parsingCss->value['width'];    if (!$w) $w = 40;
5910:                     $h = $this->parsingCss->value['height'];    if (!$h) $h = $f*1.3;
5911:                     $action = isset($param['onclick']) ? $param['onclick'] : '';
5912:                     $this->pdf->Button($name, $w, $h, $param['value'], $action, $prop, array(), $x, $y);
5913:                     break;
5914: 
5915:                 default:
5916:                     $w = 0;
5917:                     $h = 0;
5918:                     break;
5919:             }
5920: 
5921:             $this->_maxX = max($this->_maxX, $x+$w);
5922:             $this->_maxY = max($this->_maxY, $y+$h);
5923:             $this->_maxH = max($this->_maxH, $h);
5924:             $this->_maxE++;
5925:             $this->pdf->setX($x+$w);
5926: 
5927:             $this->parsingCss->load();
5928:             $this->parsingCss->fontSet();
5929: 
5930:             return true;
5931:         }
5932: 
5933:         /**
5934:          * tag : DRAW
5935:          * mode : OPEN
5936:          *
5937:          * @param  array $param
5938:          * @return boolean
5939:          */
5940:         protected function _tag_open_DRAW($param)
5941:         {
5942:             if ($this->_isForOneLine) return false;
5943:             if ($this->_debugActif) $this->_DEBUG_add('DRAW', true);
5944: 
5945:             $this->parsingCss->save();
5946:             $this->parsingCss->analyse('draw', $param);
5947:             $this->parsingCss->fontSet();
5948: 
5949:             $alignObject = null;
5950:             if ($this->parsingCss->value['margin-auto']) $alignObject = 'center';
5951: 
5952:             $overW = $this->parsingCss->value['width'];
5953:             $overH = $this->parsingCss->value['height'];
5954:             $this->parsingCss->value['old_maxX'] = $this->_maxX;
5955:             $this->parsingCss->value['old_maxY'] = $this->_maxY;
5956:             $this->parsingCss->value['old_maxH'] = $this->_maxH;
5957: 
5958:             $w = $this->parsingCss->value['width'];
5959:             $h = $this->parsingCss->value['height'];
5960: 
5961:             if (!$this->parsingCss->value['position']) {
5962:                 if (
5963:                     $w < ($this->pdf->getW() - $this->pdf->getlMargin()-$this->pdf->getrMargin()) &&
5964:                     $this->pdf->getX() + $w>=($this->pdf->getW() - $this->pdf->getrMargin())
5965:                     )
5966:                     $this->_tag_open_BR(array());
5967: 
5968:                 if (
5969:                         ($h < ($this->pdf->getH() - $this->pdf->gettMargin()-$this->pdf->getbMargin())) &&
5970:                         ($this->pdf->getY() + $h>=($this->pdf->getH() - $this->pdf->getbMargin())) &&
5971:                         !$this->_isInOverflow
5972:                     )
5973:                     $this->_setNewPage();
5974: 
5975:                 $old = $this->parsingCss->getOldValues();
5976:                 $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
5977: 
5978:                 if ($parentWidth>$w) {
5979:                     if ($alignObject=='center')        $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
5980:                     else if ($alignObject=='right')    $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
5981:                 }
5982: 
5983:                 $this->parsingCss->setPosition();
5984:             } else {
5985:                 $old = $this->parsingCss->getOldValues();
5986:                 $parentWidth = $old['width'] ? $old['width'] : $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
5987: 
5988:                 if ($parentWidth>$w) {
5989:                     if ($alignObject=='center')        $this->pdf->setX($this->pdf->getX() + ($parentWidth-$w)*0.5);
5990:                     else if ($alignObject=='right')    $this->pdf->setX($this->pdf->getX() + $parentWidth-$w);
5991:                 }
5992: 
5993:                 $this->parsingCss->setPosition();
5994:                 $this->_saveMax();
5995:                 $this->_maxX = 0;
5996:                 $this->_maxY = 0;
5997:                 $this->_maxH = 0;
5998:                 $this->_maxE = 0;
5999:             }
6000: 
6001:             $this->_drawRectangle(
6002:                 $this->parsingCss->value['x'],
6003:                 $this->parsingCss->value['y'],
6004:                 $this->parsingCss->value['width'],
6005:                 $this->parsingCss->value['height'],
6006:                 $this->parsingCss->value['border'],
6007:                 $this->parsingCss->value['padding'],
6008:                 0,
6009:                 $this->parsingCss->value['background']
6010:             );
6011: 
6012:             $marge = array();
6013:             $marge['l'] = $this->parsingCss->value['border']['l']['width'];
6014:             $marge['r'] = $this->parsingCss->value['border']['r']['width'];
6015:             $marge['t'] = $this->parsingCss->value['border']['t']['width'];
6016:             $marge['b'] = $this->parsingCss->value['border']['b']['width'];
6017: 
6018:             $this->parsingCss->value['width'] -= $marge['l']+$marge['r'];
6019:             $this->parsingCss->value['height']-= $marge['t']+$marge['b'];
6020: 
6021:             $overW-= $marge['l']+$marge['r'];
6022:             $overH-= $marge['t']+$marge['b'];
6023: 
6024:             // clipping to draw only in the size opf the DRAW tag
6025:             $this->pdf->clippingPathStart(
6026:                 $this->parsingCss->value['x']+$marge['l'],
6027:                 $this->parsingCss->value['y']+$marge['t'],
6028:                 $this->parsingCss->value['width'],
6029:                 $this->parsingCss->value['height']
6030:             );
6031: 
6032:             // left and right of the DRAW tag
6033:             $mL = $this->parsingCss->value['x']+$marge['l'];
6034:             $mR = $this->pdf->getW() - $mL - $overW;
6035: 
6036:             // position of the DRAW tag
6037:             $x = $this->parsingCss->value['x']+$marge['l'];
6038:             $y = $this->parsingCss->value['y']+$marge['t'];
6039: 
6040:             // prepare the drawing area
6041:             $this->_saveMargin($mL, 0, $mR);
6042:             $this->pdf->setXY($x, $y);
6043: 
6044:             // we are in a draw tag
6045:             $this->_isInDraw = array(
6046:                 'x' => $x,
6047:                 'y' => $y,
6048:                 'w' => $overW,
6049:                 'h' => $overH,
6050:             );
6051: 
6052:             // init the translate matrix : (0,0) => ($x, $y)
6053:             $this->pdf->doTransform(array(1,0,0,1,$x,$y));
6054:             $this->pdf->SetAlpha(1.);
6055:             return true;
6056:         }
6057: 
6058:         /**
6059:          * tag : DRAW
6060:          * mode : CLOSE
6061:          *
6062:          * @param  array $param
6063:          * @return boolean
6064:          */
6065:         protected function _tag_close_DRAW($param)
6066:         {
6067:             if ($this->_isForOneLine) return false;
6068: 
6069:             $this->pdf->SetAlpha(1.);
6070:             $this->pdf->undoTransform();
6071:             $this->pdf->clippingPathStop();
6072: 
6073:             $this->_maxX = $this->parsingCss->value['old_maxX'];
6074:             $this->_maxY = $this->parsingCss->value['old_maxY'];
6075:             $this->_maxH = $this->parsingCss->value['old_maxH'];
6076: 
6077:             $marge = array();
6078:             $marge['l'] = $this->parsingCss->value['border']['l']['width'];
6079:             $marge['r'] = $this->parsingCss->value['border']['r']['width'];
6080:             $marge['t'] = $this->parsingCss->value['border']['t']['width'];
6081:             $marge['b'] = $this->parsingCss->value['border']['b']['width'];
6082: 
6083:             $x = $this->parsingCss->value['x'];
6084:             $y = $this->parsingCss->value['y'];
6085:             $w = $this->parsingCss->value['width']+$marge['l']+$marge['r'];
6086:             $h = $this->parsingCss->value['height']+$marge['t']+$marge['b'];
6087: 
6088:             if ($this->parsingCss->value['position']!='absolute') {
6089:                 $this->pdf->setXY($x+$w, $y);
6090: 
6091:                 $this->_maxX = max($this->_maxX, $x+$w);
6092:                 $this->_maxY = max($this->_maxY, $y+$h);
6093:                 $this->_maxH = max($this->_maxH, $h);
6094:                 $this->_maxE++;
6095:             } else {
6096:                 // position
6097:                 $this->pdf->setXY($this->parsingCss->value['xc'], $this->parsingCss->value['yc']);
6098: 
6099:                 $this->_loadMax();
6100:             }
6101: 
6102:             $block = ($this->parsingCss->value['display']!='inline' && $this->parsingCss->value['position']!='absolute');
6103: 
6104:             $this->parsingCss->load();
6105:             $this->parsingCss->fontSet();
6106:             $this->_loadMargin();
6107: 
6108:             if ($block) $this->_tag_open_BR(array());
6109:             if ($this->_debugActif) $this->_DEBUG_add('DRAW', false);
6110: 
6111:             $this->_isInDraw = null;
6112: 
6113:             return true;
6114:         }
6115: 
6116:         /**
6117:          * tag : LINE
6118:          * mode : OPEN
6119:          *
6120:          * @param  array $param
6121:          * @return boolean
6122:          */
6123:         protected function _tag_open_LINE($param)
6124:         {
6125:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'LINE');
6126: 
6127:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6128:             $this->parsingCss->save();
6129:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6130:             $styles['fill'] = null;
6131:             $style = $this->pdf->svgSetStyle($styles);
6132: 
6133:             $x1 = isset($param['x1']) ? $this->parsingCss->ConvertToMM($param['x1'], $this->_isInDraw['w']) : 0.;
6134:             $y1 = isset($param['y1']) ? $this->parsingCss->ConvertToMM($param['y1'], $this->_isInDraw['h']) : 0.;
6135:             $x2 = isset($param['x2']) ? $this->parsingCss->ConvertToMM($param['x2'], $this->_isInDraw['w']) : 0.;
6136:             $y2 = isset($param['y2']) ? $this->parsingCss->ConvertToMM($param['y2'], $this->_isInDraw['h']) : 0.;
6137:             $this->pdf->svgLine($x1, $y1, $x2, $y2);
6138: 
6139:             $this->pdf->undoTransform();
6140:             $this->parsingCss->load();
6141:         }
6142: 
6143:         /**
6144:          * tag : RECT
6145:          * mode : OPEN
6146:          *
6147:          * @param  array $param
6148:          * @return boolean
6149:          */
6150:         protected function _tag_open_RECT($param)
6151:         {
6152:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'RECT');
6153: 
6154:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6155:             $this->parsingCss->save();
6156:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6157:             $style = $this->pdf->svgSetStyle($styles);
6158: 
6159:             $x = isset($param['x']) ? $this->parsingCss->ConvertToMM($param['x'], $this->_isInDraw['w']) : 0.;
6160:             $y = isset($param['y']) ? $this->parsingCss->ConvertToMM($param['y'], $this->_isInDraw['h']) : 0.;
6161:             $w = isset($param['w']) ? $this->parsingCss->ConvertToMM($param['w'], $this->_isInDraw['w']) : 0.;
6162:             $h = isset($param['h']) ? $this->parsingCss->ConvertToMM($param['h'], $this->_isInDraw['h']) : 0.;
6163: 
6164:             $this->pdf->svgRect($x, $y, $w, $h, $style);
6165: 
6166:             $this->pdf->undoTransform();
6167:             $this->parsingCss->load();
6168:         }
6169: 
6170:         /**
6171:          * tag : CIRCLE
6172:          * mode : OPEN
6173:          *
6174:          * @param  array $param
6175:          * @return boolean
6176:          */
6177:         protected function _tag_open_CIRCLE($param)
6178:         {
6179:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'CIRCLE');
6180: 
6181:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6182:             $this->parsingCss->save();
6183:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6184:             $style = $this->pdf->svgSetStyle($styles);
6185: 
6186:             $cx = isset($param['cx']) ? $this->parsingCss->ConvertToMM($param['cx'], $this->_isInDraw['w']) : 0.;
6187:             $cy = isset($param['cy']) ? $this->parsingCss->ConvertToMM($param['cy'], $this->_isInDraw['h']) : 0.;
6188:             $r = isset($param['r']) ? $this->parsingCss->ConvertToMM($param['r'], $this->_isInDraw['w']) : 0.;
6189:             $this->pdf->svgEllipse($cx, $cy, $r, $r, $style);
6190: 
6191:             $this->pdf->undoTransform();
6192:             $this->parsingCss->load();
6193:         }
6194: 
6195:         /**
6196:          * tag : ELLIPSE
6197:          * mode : OPEN
6198:          *
6199:          * @param  array $param
6200:          * @return boolean
6201:          */
6202:         protected function _tag_open_ELLIPSE($param)
6203:         {
6204:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'ELLIPSE');
6205: 
6206:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6207:             $this->parsingCss->save();
6208:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6209:             $style = $this->pdf->svgSetStyle($styles);
6210: 
6211:             $cx = isset($param['cx']) ? $this->parsingCss->ConvertToMM($param['cx'], $this->_isInDraw['w']) : 0.;
6212:             $cy = isset($param['cy']) ? $this->parsingCss->ConvertToMM($param['cy'], $this->_isInDraw['h']) : 0.;
6213:             $rx = isset($param['ry']) ? $this->parsingCss->ConvertToMM($param['rx'], $this->_isInDraw['w']) : 0.;
6214:             $ry = isset($param['rx']) ? $this->parsingCss->ConvertToMM($param['ry'], $this->_isInDraw['h']) : 0.;
6215:             $this->pdf->svgEllipse($cx, $cy, $rx, $ry, $style);
6216: 
6217:             $this->pdf->undoTransform();
6218:             $this->parsingCss->load();
6219:         }
6220: 
6221: 
6222:         /**
6223:          * tag : POLYLINE
6224:          * mode : OPEN
6225:          *
6226:          * @param  array $param
6227:          * @return boolean
6228:          */
6229:         protected function _tag_open_POLYLINE($param)
6230:         {
6231:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'POLYGON');
6232: 
6233:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6234:             $this->parsingCss->save();
6235:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6236:             $style = $this->pdf->svgSetStyle($styles);
6237: 
6238:             $path = isset($param['points']) ? $param['points'] : null;
6239:             if ($path) {
6240:                 $path = str_replace(',', ' ', $path);
6241:                 $path = preg_replace('/[\s]+/', ' ', trim($path));
6242: 
6243:                 // prepare the path
6244:                 $path = explode(' ', $path);
6245:                 foreach ($path as $k => $v) {
6246:                     $path[$k] = trim($v);
6247:                     if ($path[$k]==='') unset($path[$k]);
6248:                 }
6249:                 $path = array_values($path);
6250: 
6251:                 $actions = array();
6252:                 for ($k=0; $k<count($path); $k+=2) {
6253:                     $actions[] = array(
6254:                         ($k ? 'L' : 'M') ,
6255:                         $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']),
6256:                         $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h'])
6257:                     );
6258:                 }
6259: 
6260:                 // drawing
6261:                 $this->pdf->svgPolygone($actions, $style);
6262:             }
6263: 
6264:             $this->pdf->undoTransform();
6265:             $this->parsingCss->load();
6266:         }
6267: 
6268:         /**
6269:          * tag : POLYGON
6270:          * mode : OPEN
6271:          *
6272:          * @param  array $param
6273:          * @return boolean
6274:          */
6275:         protected function _tag_open_POLYGON($param)
6276:         {
6277:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'POLYGON');
6278: 
6279:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6280:             $this->parsingCss->save();
6281:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6282:             $style = $this->pdf->svgSetStyle($styles);
6283: 
6284:             $path = (isset($param['points']) ? $param['points'] : null);
6285:             if ($path) {
6286:                 $path = str_replace(',', ' ', $path);
6287:                 $path = preg_replace('/[\s]+/', ' ', trim($path));
6288: 
6289:                 // prepare the path
6290:                 $path = explode(' ', $path);
6291:                 foreach ($path as $k => $v) {
6292:                     $path[$k] = trim($v);
6293:                     if ($path[$k]==='') unset($path[$k]);
6294:                 }
6295:                 $path = array_values($path);
6296: 
6297:                 $actions = array();
6298:                 for ($k=0; $k<count($path); $k+=2) {
6299:                     $actions[] = array(
6300:                         ($k ? 'L' : 'M') ,
6301:                         $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']),
6302:                         $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h'])
6303:                     );
6304:                 }
6305:                 $actions[] = array('z');
6306: 
6307:                 // drawing
6308:                 $this->pdf->svgPolygone($actions, $style);
6309:             }
6310: 
6311:             $this->pdf->undoTransform();
6312:             $this->parsingCss->load();
6313:         }
6314: 
6315:         /**
6316:          * tag : PATH
6317:          * mode : OPEN
6318:          *
6319:          * @param  array $param
6320:          * @return boolean
6321:          */
6322:         protected function _tag_open_PATH($param)
6323:         {
6324:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'PATH');
6325: 
6326:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6327:             $this->parsingCss->save();
6328:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6329:             $style = $this->pdf->svgSetStyle($styles);
6330: 
6331:             $path = isset($param['d']) ? $param['d'] : null;
6332: 
6333:             if ($path) {
6334:                 // prepare the path
6335:                 $path = str_replace(',', ' ', $path);
6336:                 $path = preg_replace('/([a-zA-Z])([0-9\.\-])/', '$1 $2', $path);
6337:                 $path = preg_replace('/([0-9\.])([a-zA-Z])/', '$1 $2', $path);
6338:                 $path = preg_replace('/[\s]+/', ' ', trim($path));
6339:                 $path = preg_replace('/ ([a-z]{2})/', '$1', $path);
6340: 
6341:                 $path = explode(' ', $path);
6342:                 foreach ($path as $k => $v) {
6343:                     $path[$k] = trim($v);
6344:                     if ($path[$k]==='') unset($path[$k]);
6345:                 }
6346:                 $path = array_values($path);
6347: 
6348:                 // read each actions in the path
6349:                 $actions = array();
6350:                 $action = array();
6351:                 $lastAction = null; // last action found
6352:                 for ($k=0; $k<count($path);true) {
6353: 
6354:                     // for this actions, we can not have multi coordonate
6355:                     if (in_array($lastAction, array('z', 'Z'))) {
6356:                         $lastAction = null;
6357:                     }
6358: 
6359:                     // read the new action (forcing if no action before)
6360:                     if (preg_match('/^[a-z]+$/i', $path[$k]) || $lastAction===null) {
6361:                         $lastAction = $path[$k];
6362:                         $k++;
6363:                     }
6364: 
6365:                     // current action
6366:                     $action = array();
6367:                     $action[] = $lastAction;
6368:                     switch($lastAction)
6369:                     {
6370:                         case 'C':
6371:                         case 'c':
6372:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']);    // x1
6373:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']);    // y1
6374:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+2], $this->_isInDraw['w']);    // x2
6375:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+3], $this->_isInDraw['h']);    // y2
6376:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+4], $this->_isInDraw['w']);    // x
6377:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+5], $this->_isInDraw['h']);    // y
6378:                             $k+= 6;
6379:                             break;
6380: 
6381:                         case 'Q':
6382:                         case 'S':
6383:                         case 'q':
6384:                         case 's':
6385:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']);    // x2
6386:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']);    // y2
6387:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+2], $this->_isInDraw['w']);    // x
6388:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+3], $this->_isInDraw['h']);    // y
6389:                             $k+= 4;
6390:                             break;
6391: 
6392:                         case 'A':
6393:                         case 'a':
6394:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']);    // rx
6395:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']);    // ry
6396:                             $action[] = 1.*$path[$k+2];                                                        // angle de deviation de l'axe X
6397:                             $action[] = ($path[$k+3]=='1') ? 1 : 0;                                            // large-arc-flag
6398:                             $action[] = ($path[$k+4]=='1') ? 1 : 0;                                            // sweep-flag
6399:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+5], $this->_isInDraw['w']);    // x
6400:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+6], $this->_isInDraw['h']);    // y
6401:                             $k+= 7;
6402:                             break;
6403: 
6404:                         case 'M':
6405:                         case 'L':
6406:                         case 'T':
6407:                         case 'm':
6408:                         case 'l':
6409:                         case 't':
6410:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']);    // x
6411:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+1], $this->_isInDraw['h']);    // y
6412:                             $k+= 2;
6413:                             break;
6414: 
6415:                         case 'H':
6416:                         case 'h':
6417:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['w']);    // x
6418:                             $k+= 1;
6419:                             break;
6420: 
6421:                         case 'V':
6422:                         case 'v':
6423:                             $action[] = $this->parsingCss->ConvertToMM($path[$k+0], $this->_isInDraw['h']);    // y
6424:                             $k+= 1;
6425:                             break;
6426: 
6427:                         case 'z':
6428:                         case 'Z':
6429:                         default:
6430:                             break;
6431:                     }
6432:                     // add the action
6433:                     $actions[] = $action;
6434:                 }
6435: 
6436:                 // drawing
6437:                 $this->pdf->svgPolygone($actions, $style);
6438:             }
6439: 
6440:             $this->pdf->undoTransform();
6441:             $this->parsingCss->load();
6442:         }
6443: 
6444:         /**
6445:          * tag : G
6446:          * mode : OPEN
6447:          *
6448:          * @param  array $param
6449:          * @return boolean
6450:          */
6451:         protected function _tag_open_G($param)
6452:         {
6453:             if (!$this->_isInDraw) throw new HTML2PDF_exception(8, 'G');
6454: 
6455:             $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null);
6456:             $this->parsingCss->save();
6457:             $styles = $this->parsingCss->getSvgStyle('path', $param);
6458:             $style = $this->pdf->svgSetStyle($styles);
6459:         }
6460: 
6461:         /**
6462:          * tag : G
6463:          * mode : CLOSE
6464:          *
6465:          * @param  array $param
6466:          * @return boolean
6467:          */
6468:         protected function _tag_close_G($param)
6469:         {
6470:             $this->pdf->undoTransform();
6471:             $this->parsingCss->load();
6472:         }
6473: 
6474:         /**
6475:          * new page for the automatic Index, does not use thie method. Only HTML2PDF_myPdf could use it !!!!
6476:          *
6477:          * @param  &int $page
6478:          * @return integer $oldPage
6479:          */
6480:         public function _INDEX_NewPage(&$page)
6481:         {
6482:             if ($page) {
6483:                 $oldPage = $this->pdf->getPage();
6484:                 $this->pdf->setPage($page);
6485:                 $this->pdf->setXY($this->_margeLeft, $this->_margeTop);
6486:                 $this->_maxH = 0;
6487:                 $page++;
6488:                 return $oldPage;
6489:             } else {
6490:                 $this->_setNewPage();
6491:                 return null;
6492:             }
6493:         }
6494: 
6495:     }
6496: }