Add support for PDF canvas on Node.js again.

This commit is contained in:
Jürg Lehni 2016-01-27 09:34:37 +01:00
parent 86f6d8eccd
commit e722be5b62
5 changed files with 86 additions and 32 deletions

View file

@ -4,16 +4,15 @@ var paper = require('paper'),
var canvas = paper.createCanvas(612, 792, 'pdf'); var canvas = paper.createCanvas(612, 792, 'pdf');
paper.setup(canvas); paper.setup(canvas);
with (paper) { fs.readFile('./in.json', { encoding: 'utf8' }, function (err, data) {
fs.readFile('./in.json', { encoding: 'utf8' }, function (err, data) { if (err)
throw err;
paper.project.importJSON(data);
paper.view.update();
fs.writeFile(path.resolve(__dirname, 'out.pdf'), canvas.toBuffer(), function (err) {
if (err) if (err)
throw err; throw err;
project.importJSON(data); console.log('Saved!');
view.update(); process.exit();
fs.writeFile(path.resolve(__dirname, 'out.pdf'), canvas.toBuffer(), function (err) {
if (err)
throw err;
console.log('Saved!');
});
}); });
} });

View file

@ -253,18 +253,10 @@ var PaperScope = Base.extend(/** @lends PaperScope# */{
return this; return this;
}, },
createCanvas: function(width, height, type) { createCanvas: function(width, height) {
if (type) {
// TODO: Support 'pdf' on node.js!
}
return CanvasProvider.getCanvas(width, height); return CanvasProvider.getCanvas(width, height);
}, },
/**
* @deprecated, use use {@link #createCanvas(width, height)} instead.
*/
Canvas: '#createCanvas',
/** /**
* Activates this PaperScope, so all newly created items will be placed * Activates this PaperScope, so all newly created items will be placed
* in its active project. * in its active project.

53
src/node/canvas.js Normal file
View file

@ -0,0 +1,53 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
* http://scratchdisk.com/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
var Canvas = require('canvas'),
idlUtils = require('jsdom/lib/jsdom/living/generated/utils');
// Add some useful extensions to HTMLCanvasElement:
// - HTMLCanvasElement#type, so we can switch to a PDF canvas
// - Various Node Canvas methods, routed through from HTMLCanvasElement:
// toBuffer, pngStream, createPNGStream, jpgStream, createJPGStream
module.exports = function(window) {
var HTMLCanvasElement = window.HTMLCanvasElement;
function getImplementation(obj) {
return obj._canvas ? obj : idlUtils.implForWrapper(obj);
}
// Add fake HTMLCanvasElement#type property:
Object.defineProperty(HTMLCanvasElement.prototype, 'type', {
get: function() {
return getImplementation(this)._type;
},
set: function(type) {
// Allow replacement of internal node-canvas, so we can switch to a
// PDF canvas.
var impl = getImplementation(this),
size = impl._canvas || impl;
impl._canvas = new Canvas(size.width, size.height, type);
impl._context = null;
impl._type = type;
}
});
// Extend HTMLCanvasElement with useful methods from the underlying Canvas:
['toBuffer', 'pngStream', 'createPNGStream', 'jpgStream', 'createJPGStream']
.forEach(function(key) {
HTMLCanvasElement.prototype[key] = function() {
var canvas = getImplementation(this)._canvas;
return canvas[key].apply(canvas, arguments);
};
});
};

View file

@ -12,6 +12,7 @@
var fs = require('fs'), var fs = require('fs'),
path = require('path'); path = require('path');
Canvas = require('canvas');
module.exports = function(paper) { module.exports = function(paper) {
var sourceMaps = {}, var sourceMaps = {},
@ -52,6 +53,24 @@ module.exports = function(paper) {
}; };
}; };
paper.PaperScope.inject({
createCanvas: function(width, height, type) {
// Do not use CanvasProvider.getCanvas(), since we may be changing
// the underlying node-canvas and don't want to release it after
// back into the pool.
var canvas = paper.document.createElement('canvas');
canvas.width = width;
canvas.height = height;
canvas.type = type;
return canvas;
},
/**
* @deprecated, use use {@link #createCanvas(width, height)} instead.
*/
Canvas: '#createCanvas'
});
// Node.js based image exporting code. // Node.js based image exporting code.
paper.CanvasView.inject({ paper.CanvasView.inject({
// DOCS: CanvasView#exportFrames(param); // DOCS: CanvasView#exportFrames(param);

View file

@ -13,8 +13,7 @@
// Node.js emulation layer of browser environment, based on jsdom with node- // Node.js emulation layer of browser environment, based on jsdom with node-
// canvas integration. // canvas integration.
var jsdom = require('jsdom'), var jsdom = require('jsdom');
idlUtils = require('jsdom/lib/jsdom/living/generated/utils');
// Create our document and window objects through jsdom. // Create our document and window objects through jsdom.
/* global document:true, window:true */ /* global document:true, window:true */
@ -25,18 +24,10 @@ var document = jsdom.jsdom('<html><body></body></html>', {
}), }),
window = document.defaultView; window = document.defaultView;
['pngStream', 'createPNGStream', 'jpgStream', 'createJPGStream'].forEach( require('./canvas')(window);
function(key) {
this[key] = function() {
var impl = this._canvas ? this : idlUtils.implForWrapper(this),
canvas = impl && impl._canvas;
return canvas[key].apply(canvas, arguments);
};
},
window.HTMLCanvasElement.prototype);
// Define XMLSerializer and DOMParser shims, to emulate browser behavior. // Define XMLSerializer and DOMParser shims, to emulate browser behavior.
// TODO: Put this into a simple node module, with dependency on jsdom? // Effort to bring this to jsdom: https://github.com/tmpvar/jsdom/issues/1368
function XMLSerializer() { function XMLSerializer() {
} }
@ -44,7 +35,7 @@ XMLSerializer.prototype.serializeToString = function(node) {
var text = jsdom.serializeDocument(node); var text = jsdom.serializeDocument(node);
// Fix a jsdom issue where all SVG tagNames are lowercased: // Fix a jsdom issue where all SVG tagNames are lowercased:
// https://github.com/tmpvar/jsdom/issues/620 // https://github.com/tmpvar/jsdom/issues/620
var tagNames = ['linearGradient', 'radialGradient', 'clipPath']; var tagNames = ['linearGradient', 'radialGradient', 'clipPath', 'textPath'];
for (var i = 0, l = tagNames.length; i < l; i++) { for (var i = 0, l = tagNames.length; i < l; i++) {
var tagName = tagNames[i]; var tagName = tagNames[i];
text = text.replace( text = text.replace(