Beispiel #1
0
 /**
  * Embedd a Scalable Vector Graphics (SVG) image.
  * NOTE: SVG standard is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library.
  * @param $file (string) Name of the SVG file or a '@' character followed by the SVG data string.
  * @param $x (float) Abscissa of the upper-left corner.
  * @param $y (float) Ordinate of the upper-left corner.
  * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated.
  * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated.
  * @param $link (mixed) URL or identifier returned by AddLink().
  * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> If the alignment is an empty string, then the pointer will be restored on the starting SVG position.
  * @param $palign (string) Allows to center or align the image on the current line. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul>
  * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)))
  * @param $fitonpage (boolean) if true the image is resized to not exceed page dimensions.
  * @author Nicola Asuni
  * @since 5.0.000 (2010-05-02)
  * @public
  */
 public function ImageSVG($file, $x = '', $y = '', $w = 0, $h = 0, $link = '', $align = '', $palign = '', $border = 0, $fitonpage = false)
 {
     if ($this->state != 2) {
         return;
     }
     if ($this->rasterize_vector_images and $w > 0 and $h > 0) {
         // convert SVG to raster image using GD or ImageMagick libraries
         return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false);
     }
     if ($file[0] === '@') {
         // image from string
         $this->svgdir = '';
         $svgdata = substr($file, 1);
     } else {
         // SVG file
         $this->svgdir = dirname($file);
         $svgdata = TCPDF_STATIC::fileGetContents($file);
     }
     if ($svgdata === FALSE) {
         $this->Error('SVG file not found: ' . $file);
     }
     if ($x === '') {
         $x = $this->x;
     }
     if ($y === '') {
         $y = $this->y;
     }
     // check page for no-write regions and adapt page margins if necessary
     list($x, $y) = $this->checkPageRegions($h, $x, $y);
     $k = $this->k;
     $ox = 0;
     $oy = 0;
     $ow = $w;
     $oh = $h;
     $aspect_ratio_align = 'xMidYMid';
     $aspect_ratio_ms = 'meet';
     $regs = array();
     // get original image width and height
     preg_match('/<svg([^\\>]*)>/si', $svgdata, $regs);
     if (isset($regs[1]) and !empty($regs[1])) {
         $tmp = array();
         if (preg_match('/[\\s]+x[\\s]*=[\\s]*"([^"]*)"/si', $regs[1], $tmp)) {
             $ox = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false);
         }
         $tmp = array();
         if (preg_match('/[\\s]+y[\\s]*=[\\s]*"([^"]*)"/si', $regs[1], $tmp)) {
             $oy = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false);
         }
         $tmp = array();
         if (preg_match('/[\\s]+width[\\s]*=[\\s]*"([^"]*)"/si', $regs[1], $tmp)) {
             $ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false);
         }
         $tmp = array();
         if (preg_match('/[\\s]+height[\\s]*=[\\s]*"([^"]*)"/si', $regs[1], $tmp)) {
             $oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false);
         }
         $tmp = array();
         $view_box = array();
         if (preg_match('/[\\s]+viewBox[\\s]*=[\\s]*"[\\s]*([0-9\\.\\-]+)[\\s]+([0-9\\.\\-]+)[\\s]+([0-9\\.]+)[\\s]+([0-9\\.]+)[\\s]*"/si', $regs[1], $tmp)) {
             if (count($tmp) == 5) {
                 array_shift($tmp);
                 foreach ($tmp as $key => $val) {
                     $view_box[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false);
                 }
                 $ox = $view_box[0];
                 $oy = $view_box[1];
             }
             // get aspect ratio
             $tmp = array();
             if (preg_match('/[\\s]+preserveAspectRatio[\\s]*=[\\s]*"([^"]*)"/si', $regs[1], $tmp)) {
                 $aspect_ratio = preg_split('/[\\s]+/si', $tmp[1]);
                 switch (count($aspect_ratio)) {
                     case 3:
                         $aspect_ratio_align = $aspect_ratio[1];
                         $aspect_ratio_ms = $aspect_ratio[2];
                         break;
                     case 2:
                         $aspect_ratio_align = $aspect_ratio[0];
                         $aspect_ratio_ms = $aspect_ratio[1];
                         break;
                     case 1:
                         $aspect_ratio_align = $aspect_ratio[0];
                         $aspect_ratio_ms = 'meet';
                         break;
                 }
             }
         }
     }
     if ($ow <= 0) {
         $ow = 1;
     }
     if ($oh <= 0) {
         $oh = 1;
     }
     // calculate image width and height on document
     if ($w <= 0 and $h <= 0) {
         // convert image size to document unit
         $w = $ow;
         $h = $oh;
     } elseif ($w <= 0) {
         $w = $h * $ow / $oh;
     } elseif ($h <= 0) {
         $h = $w * $oh / $ow;
     }
     // fit the image on available space
     list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage);
     if ($this->rasterize_vector_images) {
         // convert SVG to raster image using GD or ImageMagick libraries
         return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false);
     }
     // set alignment
     $this->img_rb_y = $y + $h;
     // set alignment
     if ($this->rtl) {
         if ($palign == 'L') {
             $ximg = $this->lMargin;
         } elseif ($palign == 'C') {
             $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
         } elseif ($palign == 'R') {
             $ximg = $this->w - $this->rMargin - $w;
         } else {
             $ximg = $x - $w;
         }
         $this->img_rb_x = $ximg;
     } else {
         if ($palign == 'L') {
             $ximg = $this->lMargin;
         } elseif ($palign == 'C') {
             $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
         } elseif ($palign == 'R') {
             $ximg = $this->w - $this->rMargin - $w;
         } else {
             $ximg = $x;
         }
         $this->img_rb_x = $ximg + $w;
     }
     // store current graphic vars
     $gvars = $this->getGraphicVars();
     // store SVG position and scale factors
     $svgoffset_x = ($ximg - $ox) * $this->k;
     $svgoffset_y = -($y - $oy) * $this->k;
     if (isset($view_box[2]) and $view_box[2] > 0 and $view_box[3] > 0) {
         $ow = $view_box[2];
         $oh = $view_box[3];
     } else {
         if ($ow <= 0) {
             $ow = $w;
         }
         if ($oh <= 0) {
             $oh = $h;
         }
     }
     $svgscale_x = $w / $ow;
     $svgscale_y = $h / $oh;
     // scaling and alignment
     if ($aspect_ratio_align != 'none') {
         // store current scaling values
         $svgscale_old_x = $svgscale_x;
         $svgscale_old_y = $svgscale_y;
         // force uniform scaling
         if ($aspect_ratio_ms == 'slice') {
             // the entire viewport is covered by the viewBox
             if ($svgscale_x > $svgscale_y) {
                 $svgscale_y = $svgscale_x;
             } elseif ($svgscale_x < $svgscale_y) {
                 $svgscale_x = $svgscale_y;
             }
         } else {
             // meet
             // the entire viewBox is visible within the viewport
             if ($svgscale_x < $svgscale_y) {
                 $svgscale_y = $svgscale_x;
             } elseif ($svgscale_x > $svgscale_y) {
                 $svgscale_x = $svgscale_y;
             }
         }
         // correct X alignment
         switch (substr($aspect_ratio_align, 1, 3)) {
             case 'Min':
                 // do nothing
                 break;
             case 'Max':
                 $svgoffset_x += $w * $this->k - $ow * $this->k * $svgscale_x;
                 break;
             default:
             case 'Mid':
                 $svgoffset_x += ($w * $this->k - $ow * $this->k * $svgscale_x) / 2;
                 break;
         }
         // correct Y alignment
         switch (substr($aspect_ratio_align, 5)) {
             case 'Min':
                 // do nothing
                 break;
             case 'Max':
                 $svgoffset_y -= $h * $this->k - $oh * $this->k * $svgscale_y;
                 break;
             default:
             case 'Mid':
                 $svgoffset_y -= ($h * $this->k - $oh * $this->k * $svgscale_y) / 2;
                 break;
         }
     }
     // store current page break mode
     $page_break_mode = $this->AutoPageBreak;
     $page_break_margin = $this->getBreakMargin();
     $cell_padding = $this->cell_padding;
     $this->SetCellPadding(0);
     $this->SetAutoPageBreak(false);
     // save the current graphic state
     $this->_out('q' . $this->epsmarker);
     // set initial clipping mask
     $this->Rect($x, $y, $w, $h, 'CNZ', array(), array());
     // scale and translate
     $e = $ox * $this->k * (1 - $svgscale_x);
     $f = ($this->h - $oy) * $this->k * (1 - $svgscale_y);
     $this->_out(sprintf('%F %F %F %F %F %F cm', $svgscale_x, 0, 0, $svgscale_y, $e + $svgoffset_x, $f + $svgoffset_y));
     // creates a new XML parser to be used by the other XML functions
     $this->parser = xml_parser_create('UTF-8');
     // the following function allows to use parser inside object
     xml_set_object($this->parser, $this);
     // disable case-folding for this XML parser
     xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
     // sets the element handler functions for the XML parser
     xml_set_element_handler($this->parser, 'startSVGElementHandler', 'endSVGElementHandler');
     // sets the character data handler function for the XML parser
     xml_set_character_data_handler($this->parser, 'segSVGContentHandler');
     // start parsing an XML document
     if (!xml_parse($this->parser, $svgdata)) {
         $error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser));
         $this->Error($error_message);
     }
     // free this XML parser
     xml_parser_free($this->parser);
     // restore previous graphic state
     $this->_out($this->epsmarker . 'Q');
     // restore graphic vars
     $this->setGraphicVars($gvars);
     $this->lasth = $gvars['lasth'];
     if (!empty($border)) {
         $bx = $this->x;
         $by = $this->y;
         $this->x = $ximg;
         if ($this->rtl) {
             $this->x += $w;
         }
         $this->y = $y;
         $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true);
         $this->x = $bx;
         $this->y = $by;
     }
     if ($link) {
         $this->Link($ximg, $y, $w, $h, $link, 0);
     }
     // set pointer to align the next text/objects
     switch ($align) {
         case 'T':
             $this->y = $y;
             $this->x = $this->img_rb_x;
             break;
         case 'M':
             $this->y = $y + round($h / 2);
             $this->x = $this->img_rb_x;
             break;
         case 'B':
             $this->y = $this->img_rb_y;
             $this->x = $this->img_rb_x;
             break;
         case 'N':
             $this->SetY($this->img_rb_y);
             break;
         default:
             // restore pointer to starting position
             $this->x = $gvars['x'];
             $this->y = $gvars['y'];
             $this->page = $gvars['page'];
             $this->current_column = $gvars['current_column'];
             $this->tMargin = $gvars['tMargin'];
             $this->bMargin = $gvars['bMargin'];
             $this->w = $gvars['w'];
             $this->h = $gvars['h'];
             $this->wPt = $gvars['wPt'];
             $this->hPt = $gvars['hPt'];
             $this->fwPt = $gvars['fwPt'];
             $this->fhPt = $gvars['fhPt'];
             break;
     }
     $this->endlinex = $this->img_rb_x;
     // restore page break
     $this->SetAutoPageBreak($page_break_mode, $page_break_margin);
     $this->cell_padding = $cell_padding;
 }