Search code examples
phpsvgfabricjstcpdfdata-uri

TCPDF producing errors when passing SVG using data uri for images


I'm using FabricJS on the front-end in order to design monograms and the images uploaded to the canvas are cropped to fit the design. Fabric uses the source image when generating the SVG, so I am updating the image source to the data uri and rendering the canvas before finally calling toSVG()

The above works, needs tweaking, but the SVG is being generated and looks good.

Now when we pass SVG data to TCPDF, TCPDF throws errors and builds an incomplete PDF. Everything except for the embedded image is drawn correctly. The image portion, however, is just a white square.

What is causing TCPDF to fail parsing the data-uri image?

Warning: Illegal string offset 'masked' in /home/xxx/includes/tcpdf/tcpdf.php on line 7145

Warning: Illegal string offset 'altimgs' in /home/xxx/includes/tcpdf/tcpdf.php on line 7151

Warning: Illegal string offset 'i' in /home/xxx/includes/tcpdf/tcpdf.php on line 20877

Warning: Illegal string offset 'i' in /home/xxx/includes/tcpdf/tcpdf.php on line 20890

Warning: Illegal string offset 'i' in /home/xxx/includes/tcpdf/tcpdf.php on line 7153

Warning: Illegal string offset 'i' in /home/xxx/includes/tcpdf/tcpdf.php on line 7188

Warning: Illegal string offset 'i' in /home/xxx/includes/tcpdf/tcpdf.php on line 7235

Link to the SVG data: http://pastebin.com/SqjYT89Q


Solution

  • I believe this issue is being caused by a bug in FabricJS. The SVG file that you produced using FabricJS has many instances of the stroke-dasharray parameter being used in the stroke attribute of the path tags, except it fails to include any option specification, which is, according to the SVG specs, wrong:

    http://www.w3.org/TR/SVG/painting.html#StrokeProperties

    The file contains many instances that look like this:

    style="stroke: none; stroke-width: 1; stroke-dasharray: ; stroke-linecap: butt;...
    

    But should actually look like this:

    style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt;...
    

    Note the addition of the none option after stroke-dasharray.

    To test this theory I did a simple search and replace on the SVG file that you provided, adding the none option and once I did that, I was able to successfully convert your SVG file into a JPG using Imagick (got the purple oval with the URL and the picture of the beautiful dog. :-). Based on that result, I'm pretty confident that the TCPDF errors will go away if this issue in the SVG file is resolved.

    The proper solution to this problem is to raise an issue in the FabricJS project on GitHub and, if your JavaScript skills are up to it, you could probably make the fix and submit a pull request.

    In the meantime, you could work around the issue by running the incoming SVG file through the str_replace() function, replacing all instances of stroke-dasharray: ; with stroke-dasharray: none; before you pass the SVG data into TCPDF and that should fix your problem.