问题
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