Fabric.js: How to convert fabrics js into pdf

Created on 2 Oct 2019  Â·  27Comments  Â·  Source: fabricjs/fabric.js

Hello,
How can we convert fabricsjs json into pdf and save it in backend server?

Most helpful comment

this is how i load it

const fs = require('fs');
const fabric = require('fabric').fabric;
const { createCanvas } = require('canvas')
const utils = require('jsdom/lib/jsdom/living/generated/utils');
const svg = fs.readFileSync(__dirname + '/file.svg', 'utf8');
const mPDFcanvas = createCanvas(800, 800, 'pdf') // see "PDF Support" section
const el = fabric.document.createElement('canvas');
el[utils.implSymbol]._canvas = mPDFcanvas;
const fabricCanvas = new fabric.StaticCanvas(el, { width: 800, height: 800 });

fabric.loadSVGFromString(svg, function (objects, options) {
    var svg = fabric.util.groupSVGElements(objects, options);
    fabricCanvas.add(svg);
    fabricCanvas.renderAll();
    var stream = fabric.util.getNodeCanvas(fabricCanvas.lowerCanvasEl).createPDFStream();
    // var stream = fabricCanvas.createPNGStream();
    stream.pipe(fs.createWriteStream('output.pdf'));
});

this is the PDF i get

output.pdf

All 27 comments

may you take a look at node-canvas ?

So node-canvas will allow you to have a pdf renderer from the canvas itself, so all the low level instructions of fabricJS should become a PDF.
I'm not sure how would you handle fonts.

I'll close the issue since there is nothing to solve from me, but if you want to talk about it, feel free to write.

Why fabricjs rely on the jsdom? can fabricjs rely on NodeCanvas and remove jsdom? I think that is better

Well fabric run in browser and additionally in node.
Fabric does some dom manipulation and without JSDOM that would not be possible.
Jsdom also provide a clean interface for the canvas.

If the point is to initialize a backend as PDF in node from node-canvas, that should be somehow organized trough JSDOM to pass the correct options.

@asturur I found the solution to export pdf, but the result is a image inside the pdf.

const fs = require('fs');
const fabric = require('fabric').fabric;
const { createCanvas } = require('canvas')
const utils = require('jsdom/lib/jsdom/living/generated/utils');

const mPDFcanvas = createCanvas(600, 800, 'pdf') // see "PDF Support" section

const el = fabric.document.createElement('canvas');
el[utils.implSymbol]._canvas = mPDFcanvas;
const fabricCanvas = new fabric.StaticCanvas(el, { width: 1024, height: 1024 });
fabricCanvas.setZoom(10);

fabric.Image.fromURL('http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg', function (data) {
    var img = data.set({ left: 0, top: 0, width: 500, height: 500 });
    fabricCanvas.add(img);
    fabricCanvas.renderAll();
    var stream = fabric.util.getNodeCanvas(fabricCanvas.lowerCanvasEl).createPDFStream();
    // var stream = fabricCanvas.createPNGStream();
    stream.pipe(fs.createWriteStream('output.pdf'));
});

looks nice. i think we should document somewhere. Does it work good also with custom fonts?

I am not test yet, I will test with custom fonts later

Does anyone have luck with the solution?

@asturur I found the solution to export pdf, but the result is a image inside the pdf.

const fs = require('fs');
const fabric = require('fabric').fabric;
const { createCanvas } = require('canvas')
const utils = require('jsdom/lib/jsdom/living/generated/utils');

const mPDFcanvas = createCanvas(600, 800, 'pdf') // see "PDF Support" section

const el = fabric.document.createElement('canvas');
el[utils.implSymbol]._canvas = mPDFcanvas;
const fabricCanvas = new fabric.StaticCanvas(el, { width: 1024, height: 1024 });
fabricCanvas.setZoom(10);

fabric.Image.fromURL('http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg', function (data) {
    var img = data.set({ left: 0, top: 0, width: 500, height: 500 });
    fabricCanvas.add(img);
    fabricCanvas.renderAll();
    var stream = fabric.util.getNodeCanvas(fabricCanvas.lowerCanvasEl).createPDFStream();
    // var stream = fabricCanvas.createPNGStream();
    stream.pipe(fs.createWriteStream('output.pdf'));
});

This work, if you importsvg instead of insert the svg as image the pdf elements remains vector.

If you load it as an image YES. if you load as loadSVGfromURL or loadSVGfromString probably it won't be.

this is how i load it

const fs = require('fs');
const fabric = require('fabric').fabric;
const { createCanvas } = require('canvas')
const utils = require('jsdom/lib/jsdom/living/generated/utils');
const svg = fs.readFileSync(__dirname + '/file.svg', 'utf8');
const mPDFcanvas = createCanvas(800, 800, 'pdf') // see "PDF Support" section
const el = fabric.document.createElement('canvas');
el[utils.implSymbol]._canvas = mPDFcanvas;
const fabricCanvas = new fabric.StaticCanvas(el, { width: 800, height: 800 });

fabric.loadSVGFromString(svg, function (objects, options) {
    var svg = fabric.util.groupSVGElements(objects, options);
    fabricCanvas.add(svg);
    fabricCanvas.renderAll();
    var stream = fabric.util.getNodeCanvas(fabricCanvas.lowerCanvasEl).createPDFStream();
    // var stream = fabricCanvas.createPNGStream();
    stream.pipe(fs.createWriteStream('output.pdf'));
});

this is the PDF i get

output.pdf

Hello,
We can do it in different way.
We can use puppeteer to convert canva page to pdf.

If you are laravel developer you can use : https://github.com/spatie/browsershot

But that will give you a raster PDF, that is what @morenogiudici was complaining about

@onlinecheckwriter, If you're going to print this PDF then it's not a case. Ideally it would be great to have a CMYK colors support. I'm thinkg about developing it.

@asturur I was saying the same thing, but after having tested the libraries over the weekend and checked the results of "node-canvas" and pdfKit (with svgtopdfkit) I prefer to export to svg and use an illustrator script to convert to pdf, because it gives a better result and more stable.

@andrewzolotukhin If you print with professional Rip software the conversion in cymk during rasterization it is much more accurate, so I think it is enough to limit the RGB color space to the color space of the cymk during user choices.

I agree that limiting the color space and let professional do the work is way better. Conversion is print machine dependent and you do not want to mess it up.

@morenogiudici how does svg to pdf from illustrator handle custom fonts linked with external refs?

@asturur I'm limiting the choice of fonts to some selected googlefonts and I do not plan to give the possibility to upload custom fonts, so I simply pre-installed the fonts on the system that do the conversion with illustrator. Unfortunately, I don't think it's a solution suitable for everyone.

can you run illustrator in a linux container? or are you bound to some desktop like server?

In my case I use the pdf to print at the factory. On the server I save the data in JSON and when clients confirm the order and I have to print I create the files locally.

I think that the illustrator license does not allow it to be used for server automation, maybe inkskape it's more appropriate both legally and at the automation level

inkscape can be run in a container and from command line, i use it for converting pdf and eps to fabricjs importable stuff ( most of the time )

Sometime printing companies needs to specify CMYK values directly in
template (not on RIP stage). That's why I said that it would be great (for
me) to have CMYK color space directly in Fabric.
But main issue here is that CMYK in SVG is not very broad used, for example
Inkscape can't convert SVGs with objects having CMYK colors to PDFs with
CMYK colored objects.
I mean that it isn't enough just to generate a SVG with CMYK colors, the
main challenge is to correctly convert it to PDF with CMYK colors.

On Tue, May 26, 2020 at 11:56 AM Andrea Bogazzi notifications@github.com
wrote:

inkscape can be run in a container and from command line, i use it for
converting pdf and eps to fabricjs importable stuff ( most of the time )

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fabricjs/fabric.js/issues/5906#issuecomment-633898974,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAOOTZL6GUU2ZWUUB6XEF4LRTN73ZANCNFSM4I424BHA
.

The svg specifications support icc profiles, but there are incompatibilities with browsers.

PDFKit supports cymk colors but svgtopdfkit dosen't (it is easy to extend the parseColor function of svgtopdfkit)

Scribus seems to generate pdfs that are more compatible with typographic standards than inkscape

I haven't tested the libraries enough to evaluate the full support of the svg created by fabricjs, but maybe it's a starting point

once you solve the conversion problem accurately, any rgb color svg can become a cymk svg, outside fabricjs. There is no reason for this to happen in fabric.

Also i wonder when printing standars will start to consider svg as valid format.

@morenogiudici, yes, SVG specs support ICC profiles, but a little of
editors respect colors set using ICC profile while converting to PDF. For
example Inkscape just ignore it and replaces with RGB fallback. Scribus is
better, I managed to run it in Docker container to convert ICC SVG to CMYK
PDF, but it's very slow. I didn't know about the SVG-to-PDFKit, that might
simplify the process. But how it deals with things like filters. shadows,
etc?

On Thu, May 28, 2020 at 12:18 PM Andrea Bogazzi notifications@github.com
wrote:

once you solve the conversion problem accurately, any rgb color svg can
become a cymk svg, outside fabricjs. There is no reason for this to happen
in fabric.

Also i wonder when printing standars will start to consider svg as valid
format.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fabricjs/fabric.js/issues/5906#issuecomment-635223589,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAOOTZOM7SQCXTHQXDOFBATRTYT6VANCNFSM4I424BHA
.

looks nice. i think we should document somewhere. Does it work good also with custom fonts?

@asturur node-canvas does support custom font right? registerFont()

Yes it does, but i wonder if those are converted to path or left text. Both
are an option in PDF.

Il giorno mar 9 giu 2020 alle ore 15:02 Jackson notifications@github.com
ha scritto:

looks nice. i think we should document somewhere. Does it work good also
with custom fonts?

@asturur https://github.com/asturur node-canvas does support custom
font right? registerFont()
https://github.com/Automattic/node-canvas/#registerfont-for-bundled-fonts

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fabricjs/fabric.js/issues/5906#issuecomment-641276180,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAJDQQEOKVERYYV7E22URLDRVYXIDANCNFSM4I424BHA
.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

semiadam picture semiadam  Â·  3Comments

bevacqua picture bevacqua  Â·  4Comments

urcoder picture urcoder  Â·  5Comments

AbhijitParate picture AbhijitParate  Â·  3Comments

bhaskardas9475 picture bhaskardas9475  Â·  4Comments