Skip to content

Commit

Permalink
Canvas SVG export (fabricjs#4852)
Browse files Browse the repository at this point in the history
* changed export

* mmm

* mmm

* added some tests

* fixed tests

* ....lint

* ....lint
  • Loading branch information
asturur authored Mar 31, 2018
1 parent 2d94c78 commit 581fd2f
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/gradient.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@
'<stop ',
'offset="', (colorStop.offset * 100) + '%',
'" style="stop-color:', colorStop.color,
(colorStop.opacity !== null ? ';stop-opacity: ' + colorStop.opacity : ';'),
(typeof colorStop.opacity !== 'undefined' ? ';stop-opacity: ' + colorStop.opacity : ';'),
'"/>\n'
);
}
Expand Down
17 changes: 8 additions & 9 deletions src/static_canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -1406,33 +1406,32 @@
* @private
*/
_setSVGBgOverlayColor: function(markup, property) {
var filler = this[property];
var filler = this[property], vpt = this.viewportTransform, finalWidth = this.width / vpt[0],
finalHeight = this.height / vpt[3];
if (!filler) {
return;
}
if (filler.toLive) {
var repeat = filler.repeat;
markup.push(
'<rect transform="translate(', this.width / 2, ',', this.height / 2, ')"',
' x="', filler.offsetX - this.width / 2, '" y="', filler.offsetY - this.height / 2, '" ',
'<rect transform="translate(', finalWidth / 2, ',', finalHeight / 2, ')"',
' x="', filler.offsetX - finalWidth / 2, '" y="', filler.offsetY - finalHeight / 2, '" ',
'width="',
(repeat === 'repeat-y' || repeat === 'no-repeat'
? filler.source.width
: this.width),
: finalWidth ),
'" height="',
(repeat === 'repeat-x' || repeat === 'no-repeat'
? filler.source.height
: this.height),
: finalHeight),
'" fill="url(#SVGID_' + filler.id + ')"',
'></rect>\n'
);
}
else {
markup.push(
'<rect x="0" y="0" ',
'width="', this.width,
'" height="', this.height,
'" fill="', this[property], '"',
'<rect x="0" y="0" width="100%" height="100%" ',
'fill="', this[property], '"',
'></rect>\n'
);
}
Expand Down
2 changes: 1 addition & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ testrunner.run({
'./test/unit/canvas_events.js',
'./test/unit/text_to_svg.js',
],
// tests: ['./test/unit/pattern.js'],
//tests: ['./test/unit/canvas_static.js',],
}, function(err, report) {
if (err) {
console.log(err);
Expand Down
51 changes: 51 additions & 0 deletions test/unit/canvas_static.js
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,57 @@
}
});

QUnit.test('toSVG with background', function(assert) {
var canvas2 = new fabric.StaticCanvas();
canvas2.backgroundColor = 'red';
var svg = canvas2.toSVG();
var expectedSVG = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="150" viewBox="0 0 300 150" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs>\n</defs>\n<rect x="0" y="0" width="100%" height="100%" fill="red"></rect>\n</svg>';
assert.equal(svg, expectedSVG, 'svg is as expected');
});

QUnit.test('toSVG with background and zoom and svgViewportTransformation', function(assert) {
var canvas2 = new fabric.StaticCanvas();
canvas2.backgroundColor = 'blue';
canvas2.svgViewportTransformation = true;
canvas2.viewportTransform = [3, 0, 0, 3, 60, 30];
var svg = canvas2.toSVG();
var expectedSVG = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="150" viewBox="-20 -10 100 50" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs>\n</defs>\n<rect x="0" y="0" width="100%" height="100%" fill="blue"></rect>\n</svg>';
assert.equal(svg, expectedSVG, 'svg is as expected');
});

QUnit.test('toSVG with background gradient', function(assert) {
fabric.Object.__uid = 0;
var canvas2 = new fabric.StaticCanvas();
canvas2.backgroundColor = new fabric.Gradient({
type: 'linear',
colorStops: [
{ offset: 0, color: 'black' },
{ offset: 1, color: 'white' },
],
coords: {
x1: 0,
x2: 300,
y1: 0,
y2: 0,
},
});
var svg = canvas2.toSVG();
var expectedSVG = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="150" viewBox="0 0 300 150" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs>\n<linearGradient id="SVGID_0" gradientUnits="userSpaceOnUse" x1="-150" y1="-75" x2="150" y2="-75">\n<stop offset="0%" style="stop-color:black;"/>\n<stop offset="100%" style="stop-color:white;"/>\n</linearGradient>\n</defs>\n<rect transform="translate(150,75)" x="-150" y="-75" width="300" height="150" fill="url(#SVGID_0)"></rect>\n</svg>';
assert.equal(svg, expectedSVG, 'svg is as expected');
});

QUnit.test('toSVG with background pattern', function(assert) {
fabric.Object.__uid = 0;
var canvas2 = new fabric.StaticCanvas();
canvas2.backgroundColor = new fabric.Pattern({
source: 'a.jpeg',
repeat: 'repeat',
});
var svg = canvas2.toSVG();
var expectedSVG = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="150" viewBox="0 0 300 150" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs>\n<pattern id="SVGID_0" x="0" y="0" width="0" height="0">\n<image x="0" y="0" width="0" height="0" xlink:href=""></image>\n</pattern>\n</defs>\n<rect transform="translate(150,75)" x="-150" y="-75" width="300" height="150" fill="url(#SVGID_0)"></rect>\n</svg>';
assert.equal(svg, expectedSVG, 'svg is as expected');
});

// QUnit.test('backgroundImage', function(assert) {
// var done = assert.async();
// assert.deepEqual('', canvas.backgroundImage);
Expand Down
8 changes: 4 additions & 4 deletions test/unit/gradient.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@
});
}

var SVG_LINEAR = '<linearGradient id="SVGID_0" gradientUnits="userSpaceOnUse" x1="-50" y1="-40" x2="50" y2="150">\n<stop offset="0%" style="stop-color:red;stop-opacity: 0"/>\n<stop offset="100%" style="stop-color:green;stop-opacity: undefined"/>\n</linearGradient>\n';
var SVG_RADIAL = '<radialGradient id="SVGID_0" gradientUnits="userSpaceOnUse" cx="50" cy="150" r="50" fx="-50" fy="-40">\n<stop offset="0%" style="stop-color:red;stop-opacity: undefined"/>\n<stop offset="100%" style="stop-color:green;stop-opacity: 0"/>\n</radialGradient>\n';
var SVG_INTERNALRADIUS = '<radialGradient id="SVGID_0" gradientUnits="userSpaceOnUse" cx="50" cy="150" r="50" fx="-50" fy="-40">\n<stop offset="20%" style="stop-color:red;stop-opacity: undefined"/>\n<stop offset="100%" style="stop-color:green;stop-opacity: 0"/>\n</radialGradient>\n';
var SVG_SWAPPED = '<radialGradient id="SVGID_0" gradientUnits="userSpaceOnUse" cx="-50" cy="-40" r="50" fx="50" fy="150">\n<stop offset="20%" style="stop-color:green;stop-opacity: 0"/>\n<stop offset="100%" style="stop-color:red;stop-opacity: undefined"/>\n</radialGradient>\n';
var SVG_LINEAR = '<linearGradient id="SVGID_0" gradientUnits="userSpaceOnUse" x1="-50" y1="-40" x2="50" y2="150">\n<stop offset="0%" style="stop-color:red;stop-opacity: 0"/>\n<stop offset="100%" style="stop-color:green;"/>\n</linearGradient>\n';
var SVG_RADIAL = '<radialGradient id="SVGID_0" gradientUnits="userSpaceOnUse" cx="50" cy="150" r="50" fx="-50" fy="-40">\n<stop offset="0%" style="stop-color:red;"/>\n<stop offset="100%" style="stop-color:green;stop-opacity: 0"/>\n</radialGradient>\n';
var SVG_INTERNALRADIUS = '<radialGradient id="SVGID_0" gradientUnits="userSpaceOnUse" cx="50" cy="150" r="50" fx="-50" fy="-40">\n<stop offset="20%" style="stop-color:red;"/>\n<stop offset="100%" style="stop-color:green;stop-opacity: 0"/>\n</radialGradient>\n';
var SVG_SWAPPED = '<radialGradient id="SVGID_0" gradientUnits="userSpaceOnUse" cx="-50" cy="-40" r="50" fx="50" fy="150">\n<stop offset="20%" style="stop-color:green;stop-opacity: 0"/>\n<stop offset="100%" style="stop-color:red;"/>\n</radialGradient>\n';


QUnit.test('constructor linearGradient', function(assert) {
Expand Down

0 comments on commit 581fd2f

Please sign in to comment.