Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svg viewport transform fixes #2642

Merged
merged 4 commits into from
Dec 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/mixins/object.svg_export.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
angle = this.getAngle(),
skewX = (this.getSkewX() % 360),
skewY = (this.getSkewY() % 360),
vpt = !this.canvas || this.canvas.svgViewportTransformation ? this.getViewportTransform() : [1, 0, 0, 1, 0, 0],
center = fabric.util.transformPoint(this.getCenterPoint(), vpt),
center = this.getCenterPoint(),

NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,

Expand All @@ -75,23 +74,23 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')')
: '',

scalePart = (this.scaleX === 1 && this.scaleY === 1 && vpt[0] === 1 && vpt[3] === 1)
scalePart = (this.scaleX === 1 && this.scaleY === 1)
? '' :
(' scale(' +
toFixed(this.scaleX * vpt[0], NUM_FRACTION_DIGITS) +
toFixed(this.scaleX, NUM_FRACTION_DIGITS) +
' ' +
toFixed(this.scaleY * vpt[3], NUM_FRACTION_DIGITS) +
toFixed(this.scaleY, NUM_FRACTION_DIGITS) +
')'),

skewXPart = skewX !== 0 ? ' skewX(' + toFixed(skewX, NUM_FRACTION_DIGITS) + ')' : '',

skewYPart = skewY !== 0 ? ' skewY(' + toFixed(skewY, NUM_FRACTION_DIGITS) + ')' : '',

addTranslateX = this.type === 'path-group' ? this.width * vpt[0] : 0,
addTranslateX = this.type === 'path-group' ? this.width : 0,

flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '',

addTranslateY = this.type === 'path-group' ? this.height * vpt[3] : 0,
addTranslateY = this.type === 'path-group' ? this.height : 0,

flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : '';

Expand Down
47 changes: 26 additions & 21 deletions src/static_canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
var extend = fabric.util.object.extend,
getElementOffset = fabric.util.getElementOffset,
removeFromArray = fabric.util.removeFromArray,
toFixed = fabric.util.toFixed,

CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');

Expand Down Expand Up @@ -1183,6 +1184,8 @@
* @param {Number} [options.viewBox.width] Width of viewbox
* @param {Number} [options.viewBox.height] Height of viewbox
* @param {String} [options.encoding=UTF-8] Encoding of SVG output
* @param {String} [options.width] desired width of svg with or without units
* @param {String} [options.height] desired height of svg with or without units
* @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation.
* @return {String} SVG string
* @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization}
Expand Down Expand Up @@ -1232,32 +1235,40 @@
* @private
*/
_setSVGPreamble: function(markup, options) {
if (!options.suppressPreamble) {
markup.push(
'<?xml version="1.0" encoding="', (options.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'
);
if (options.suppressPreamble) {
return;
}
markup.push(
'<?xml version="1.0" encoding="', (options.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'
);
},

/**
* @private
*/
_setSVGHeader: function(markup, options) {
var width, height, vpt;
var width = options.width || this.width,
height = options.height || this.height,
vpt, viewBox = 'viewBox="0 0 ' + this.width + ' ' + this.height + '" ',
NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;

if (options.viewBox) {
width = options.viewBox.width;
height = options.viewBox.height;
viewBox = 'viewBox="' +
options.viewBox.x + ' ' +
options.viewBox.y + ' ' +
options.viewBox.width + ' ' +
options.viewBox.height + '" ';
}
else {
width = this.width;
height = this.height;
if (!this.svgViewportTransformation) {
if (this.svgViewportTransformation) {
vpt = this.viewportTransform;
width /= vpt[0];
height /= vpt[3];
viewBox = 'viewBox="' +
toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' +
toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' +
toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' +
toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '" ';
}
}

Expand All @@ -1271,13 +1282,7 @@
(this.backgroundColor && !this.backgroundColor.toLive
? 'style="background-color: ' + this.backgroundColor + '" '
: null),
(options.viewBox
? 'viewBox="' +
options.viewBox.x + ' ' +
options.viewBox.y + ' ' +
options.viewBox.width + ' ' +
options.viewBox.height + '" '
: null),
viewBox,
'xml:space="preserve">\n',
'<desc>Created with Fabric.js ', fabric.version, '</desc>\n',
'<defs>',
Expand Down
4 changes: 2 additions & 2 deletions test/unit/canvas_static.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// var emptyImageCanvasData = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAH7ElEQVR4nO3VMQ0AMAzAsPInvYHoMS2yEeTLHADge/M6AADYM3QACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIuMjH4b7osLFBAAAAAElFTkSuQmCC";

var CANVAS_SVG = '<?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="600" height="600" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs></defs>\n</svg>';
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="600" viewBox="0 0 600 600" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs></defs>\n</svg>';

var CANVAS_SVG_VIEWBOX = '<?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="300" viewBox="100 100 300 300" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs></defs>\n</svg>';
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="600" viewBox="100 100 300 300" xml:space="preserve">\n<desc>Created with Fabric.js ' + fabric.version + '</desc>\n<defs></defs>\n</svg>';

var PATH_JSON = '{"objects": [{"type": "path", "originX": "left", "originY": "top", "left": 268, "top": 266, "width": 51, "height": 49,'+
' "fill": "rgb(0,0,0)", "stroke": null, "strokeWidth": 1, "scaleX": 1, "scaleY": 1, '+
Expand Down
8 changes: 5 additions & 3 deletions test/unit/shadow.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,17 @@
ok(typeof shadow.toObject == 'function');

var object = shadow.toObject();
equal(JSON.stringify(object), '{"color":"rgb(0,0,0)","blur":0,"offsetX":0,"offsetY":0}');
equal(JSON.stringify(object), '{"color":"rgb(0,0,0)","blur":0,"offsetX":0,"offsetY":0,"affectStroke":false}');
});

test('clone with affectStroke', function() {
var shadow = new fabric.Shadow({affectStroke: true, blur: 5});
ok(typeof shadow.toObject == 'function');
var object = shadow.toObject(),
shadow2 = new fabric.Shadow(object);
deepEqual(shadow, shadow2);
shadow2 = new fabric.Shadow(object),
object2 = shadow2.toObject();
equal(shadow.affectStroke, shadow2.affectStroke)
deepEqual(object, object2);
});

test('toObject without default value', function() {
Expand Down