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

<?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;
  }

}






?>