<?php
/**
* HTML2PDF Librairy : THE <IMG> SVG PATCH
*
* Add .svg file support to the <img> tag
*
* @author Bertrand VILLIEN <bertrand@villien.net>
* @version 0.01
*/
if (!defined('__CLASS_HTML2PDF__'))
die('ERROR : HTML2PDF_SVG require HTML2PDF. Please include HTML2PDF lib before.');
if (!class_exists('simple_html_dom'))
throw new HTML2PDF_exception(0, 'ERROR MISSING LIB : simplehtmldom. Please include simple_html_dom.php !');
class HTML2PDF_SVG extends HTML2PDF {
/**
* display a image (rewrite)
*
* @access protected
* @param string $src
* @param boolean $subLi if true=image of a list
* @return boolean depending on "isForOneLine"
*/
protected function _drawImage($src, $subLi=false)
{
// If its an .SVG calling the patch :
if (preg_match('/\.svg$/', $src) === 1) {
return $this->_drawImageSVG($src, $subLi);
}
// Else its a classic image. Calling original method :
else {
return parent::_drawImage($src, $subLi);
}
}
/**
* display an svg image
*
* @access protected
* @param string $src
* @param boolean $subLi if true=image of a list
* @return boolean depending on "isForOneLine"
*/
protected function _drawImageSVG($src, $subLi=false)
{
/****************************************
* SVG PATCH 1/2
****************************************/
// Check file exist
if (!file_exists($src)) {
// If image checking is enabled
if ($this->_testIsImage) {
throw new HTML2PDF_exception(0, 'SVG file does not exist : '.$src);
}
// else, display a gray rectangle
else {
$src = null;
$infos = array(16, 16);
}
}
// Load SVG file
$svg_raw = file_get_contents($src);
if (!$svg_raw) {
// If image checking is enabled
if ($this->_testIsImage) {
throw new HTML2PDF_exception(0, 'SVG file cannot be readed : '.$src);
}
// else, display a gray rectangle
else {
$src = null;
$infos = array(16, 16);
}
}
// Get the size of the SVG
$svg_html = new simple_html_dom();
$svg_html->load($svg_raw);
$svg_element = $svg_html->find('svg',0);
if ($svg_element === null)
throw new HTML2PDF_exception(0, 'SVG file cannot be readed (svg tag not found) : '.$src);
if (!$svg_element->hasAttribute('width') || !$svg_element->hasAttribute('height'))
throw new HTML2PDF_exception(0, 'SVG file error. Missing width and height attribute of svg tag. From : '.$src);
$infos = array($svg_element->getAttribute('width'), $svg_element->getAttribute('height'));
$svg_html->clear();
/***************************************/
// convert the size of the image in the unit of the PDF
$imageWidth = $infos[0]/$this->pdf->getK();
$imageHeight = $infos[1]/$this->pdf->getK();
// calculate the size from the css style
if ($this->parsingCss->value['width'] && $this->parsingCss->value['height']) {
$w = $this->parsingCss->value['width'];
$h = $this->parsingCss->value['height'];
} else if ($this->parsingCss->value['width']) {
$w = $this->parsingCss->value['width'];
$h = $imageHeight*$w/$imageWidth;
} else if ($this->parsingCss->value['height']) {
$h = $this->parsingCss->value['height'];
$w = $imageWidth*$h/$imageHeight;
} else {
// convert px to pt
$w = 72./96.*$imageWidth;
$h = 72./96.*$imageHeight;
}
// are we in a float
$float = $this->parsingCss->getFloat();
// if we are in a float, but if something else if on the line => Break Line
if ($float && $this->_maxH) {
// make the break line (false if we are in "_isForOneLine" mode)
if (!$this->_tag_open_BR(array())) {
return false;
}
}
// position of the image
$x = $this->pdf->getX();
$y = $this->pdf->getY();
// if the image can not be put on the current line => new line
if (!$float && ($x + $w>$this->pdf->getW() - $this->pdf->getrMargin()) && $this->_maxH) {
if ($this->_isForOneLine) {
return false;
}
// set the new line
$hnl = max($this->_maxH, $this->parsingCss->getLineHeight());
$this->_setNewLine($hnl);
// get the new position
$x = $this->pdf->getX();
$y = $this->pdf->getY();
}
// if the image can not be put on the current page
if (($y + $h>$this->pdf->getH() - $this->pdf->getbMargin()) && !$this->_isInOverflow) {
// new page
$this->_setNewPage();
// get the new position
$x = $this->pdf->getX();
$y = $this->pdf->getY();
}
// correction for display the image of a list
$hT = 0.80*$this->parsingCss->value['font-size'];
if ($subLi && $h<$hT) {
$y+=($hT-$h);
}
// add the margin top
$yc = $y-$this->parsingCss->value['margin']['t'];
// get the width and the position of the parent
$old = $this->parsingCss->getOldValues();
if ( $old['width']) {
$parentWidth = $old['width'];
$parentX = $x;
} else {
$parentWidth = $this->pdf->getW() - $this->pdf->getlMargin() - $this->pdf->getrMargin();
$parentX = $this->pdf->getlMargin();
}
// if we are in a gloat => adapt the parent position and width
if ($float) {
list($lx, $rx) = $this->_getMargins($yc);
$parentX = $lx;
$parentWidth = $rx-$lx;
}
// calculate the position of the image, if align to the right
if ($parentWidth>$w && $float!='left') {
if ($float=='right' || $this->parsingCss->value['text-align']=='li_right') $x = $parentX + $parentWidth - $w-$this->parsingCss->value['margin']['r']-$this->parsingCss->value['margin']['l'];
}
// display the image
if (!$this->_subPart && !$this->_isSubPart) {
if ($src) {
/****************************************
* SVG PATCH 2/2
****************************************/
$this->pdf->ImageSVG($src, $x, $y, $w, $h, $this->_isInLink, $_align='', $_palign='', $_border=0, $_fitonpage=false);
/***************************************/
} else {
// rectangle if the image can not be loaded
$this->pdf->setFillColorArray(array(240, 220, 220));
$this->pdf->Rect($x, $y, $w, $h, 'F');
}
}
// apply the margins
$x-= $this->parsingCss->value['margin']['l'];
$y-= $this->parsingCss->value['margin']['t'];
$w+= $this->parsingCss->value['margin']['l'] + $this->parsingCss->value['margin']['r'];
$h+= $this->parsingCss->value['margin']['t'] + $this->parsingCss->value['margin']['b'];
if ($float=='left') {
// save the current max
$this->_maxX = max($this->_maxX, $x+$w);
$this->_maxY = max($this->_maxY, $y+$h);
// add the image to the margins
$this->_addMargins($float, $x, $y, $x+$w, $y+$h);
// get the new position
list($lx, $rx) = $this->_getMargins($yc);
$this->pdf->setXY($lx, $yc);
} else if ($float=='right') {
// save the current max. We don't save the X because it is not the real max of the line
$this->_maxY = max($this->_maxY, $y+$h);
// add the image to the margins
$this->_addMargins($float, $x, $y, $x+$w, $y+$h);
// get the new position
list($lx, $rx) = $this->_getMargins($yc);
$this->pdf->setXY($lx, $yc);
} else {
// set the new position at the end of the image
$this->pdf->setX($x+$w);
// save the current max
$this->_maxX = max($this->_maxX, $x+$w);
$this->_maxY = max($this->_maxY, $y+$h);
$this->_maxH = max($this->_maxH, $h);
}
return true;
}
}
?>