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('&', '&', $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('&', '&', 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('&', '&', $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: }