The imageSVG() method of tcpdf is not rendering correctly the svg file

狂风中的少年 提交于 2019-12-24 09:58:54

问题


I have the following svg file:

http://jsfiddle.net/wptn28c5/

<svg></svg>

that renders:

However, by using tcpdf ($pdf->imageSVG()) i get a pdf file that renders:


回答1:


The SVG standard is not fully implemented in TCPDF, so not all SVGs will render correctly inside TCPDF as is. For those cases you'll either need to use setRasterizeVectorImages (requires ImageMagick) to rasterize the SVG on the fly for you - or tweak the SVG into a form that would work.

With this specific file, I suspect that the complexity of the path was the issue. Though, I'm not entirely sure. I made you a new SVG file that works in the latest version of TCPDF. I saved it in a JSFiddle here. Basically, I took the path and broke it out into individual elements using InkScape.

To do this, I entered the transform group, selected the path, and finally chose "Break Apart from the Path menu.




回答2:


It's quite unfortunate the project isn't being supported anymore, though it's one of the finest work I've ever seen. For those still using it and come across this problem, the issue is that according to the SVG specs, the "Z" command:

..in a subpath causes an automatic straight line to be drawn from the current point to the initial point of the current subpath.

This should "reset" the relative path of the next command to the start of the subpath. TCPDF didn't implement this part; it simply closes the path but never moves the pen to the start of the subpath, which is where the next command is meant to start from.

So to fix this, I simply created two variables at the start of the protected SVGPath function, and set their values in the "M" (moveto) switch to store the start of every path or subpath.

Then in the "Z" switch, I simply drew a line back to that stored point based on what the specs stated. I have tested this in different SVGs and works pretty fine. Here is the code..

For "M":

case 'M': { // moveto
foreach ($params as $ck => $cp) {
    if (($ck % 2) == 0) {
        $x = $cp + $xoffset;
    } else {
        $y = $cp + $yoffset;
        if ($firstcmd OR (abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {

            if ($ck == 1) {
                $this->_outPoint($x, $y);
                $firstcmd = false;
            } else {
                $this->_outLine($x, $y);
            }
            $x0 = $x;
            $y0 = $y;
        }
        $xmin = min($xmin, $x);
        $ymin = min($ymin, $y);
        $xmax = max($xmax, $x);
        $ymax = max($ymax, $y);
        if ($relcoord) {
            $xoffset = $x;
            $yoffset = $y;
        }
        $start_x = $x;
        $start_y = $y;
    }
}
break;

And for "Z":

case 'Z': {
$x = $start_x;
$y = $start_y;
$this->_outLine($x, $y);
$this->_out('h');
break;

The variables are: $start_x and $start_x and you can initialize them each with a 0 value at the start of the function to avoid errors if a path doesn't start with a moveto.



来源:https://stackoverflow.com/questions/51042409/the-imagesvg-method-of-tcpdf-is-not-rendering-correctly-the-svg-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!