Skip to content

Commit

Permalink
Fix image import from SVG when width/height are larger than element (#…
Browse files Browse the repository at this point in the history
…4450)

* fixed

* removed extra function;

* fix import of preserver

* added tests

* fixed test names
  • Loading branch information
asturur authored Nov 12, 2017
1 parent ece82e6 commit a2f9c9f
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 63 deletions.
5 changes: 3 additions & 2 deletions src/elements_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ fabric.ElementsParser.prototype._createObject = function(klass, el, index) {
fabric.ElementsParser.prototype.createCallback = function(index, el) {
var _this = this;
return function(obj) {
var _options;
_this.resolveGradient(obj, 'fill');
_this.resolveGradient(obj, 'stroke');
obj._removeTransformMatrix();
if (obj instanceof fabric.Image) {
obj.parsePreserveAspectRatioAttribute(el);
_options = obj.parsePreserveAspectRatioAttribute(el);
}
obj._removeTransformMatrix(_options);
_this.reviver && _this.reviver(el, obj);
_this.instances[index] = obj;
_this.checkIfDone();
Expand Down
65 changes: 40 additions & 25 deletions src/shapes/image.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -549,53 +549,69 @@
: 0);
},

/**
* Calculate offset for center and scale factor for the image in order to respect
* the preserveAspectRatio attribute
* @private
* @return {Object}
*/
parsePreserveAspectRatioAttribute: function() {
if (!this.preserveAspectRatio) {
return;
}
var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio),
width = this._element.width, height = this._element.height, scale,
pWidth = this.width, pHeight = this.height, parsedAttributes = { width: pWidth, height: pHeight };
var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ''),
rWidth = this._element.width, rHeight = this._element.height,
scaleX = 1, scaleY = 1, offsetLeft = 0, offsetTop = 0, cropX = 0, cropY = 0,
offset, pWidth = this.width, pHeight = this.height, parsedAttributes = { width: pWidth, height: pHeight };
if (pAR && (pAR.alignX !== 'none' || pAR.alignY !== 'none')) {
if (pAR.meetOrSlice === 'meet') {
this.width = width;
this.height = height;
this.scaleX = this.scaleY = scale = fabric.util.findScaleToFit(this._element, parsedAttributes);
if (pAR.alignX === 'Mid') {
this.left += (pWidth - width * scale) / 2;
scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes);
offset = (pWidth - rWidth * scaleX) / 2;
if (pAR.alignX === 'Min') {
offsetLeft = -offset;
}
if (pAR.alignX === 'Max') {
this.left += pWidth - width * scale;
offsetLeft = offset;
}
if (pAR.alignY === 'Mid') {
this.top += (pHeight - height * scale) / 2;
offset = (pHeight - rHeight * scaleY) / 2;
if (pAR.alignY === 'Min') {
offsetTop = -offset;
}
if (pAR.alignY === 'Max') {
this.top += pHeight - height * scale;
offsetTop = offset;
}
}
if (pAR.meetOrSlice === 'slice') {
this.scaleX = this.scaleY = scale = fabric.util.findScaleToCover(this._element, parsedAttributes);
this.width = pWidth / scale;
this.height = pHeight / scale;
scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes);
offset = rWidth - pWidth / scaleX;
if (pAR.alignX === 'Mid') {
this.cropX = (width - this.width) / 2;
cropX = offset / 2;
}
if (pAR.alignX === 'Max') {
this.cropX = width - this.width;
cropX = offset;
}
offset = rHeight - pHeight / scaleY;
if (pAR.alignY === 'Mid') {
this.cropY = (height - this.height) / 2;
cropY = offset / 2;
}
if (pAR.alignY === 'Max') {
this.cropY = height - this.height;
cropY = offset;
}
rWidth = pWidth / scaleX;
rHeight = pHeight / scaleY;
}
}
else {
this.scaleX = pWidth / width;
this.scaleY = pHeight / height;
scaleX = pWidth / rWidth;
scaleY = pHeight / rHeight;
}
return {
width: rWidth,
height: rHeight,
scaleX: scaleX,
scaleY: scaleY,
offsetLeft: offsetLeft,
offsetTop: offsetTop,
cropX: cropX,
cropY: cropY
};
}
});

Expand Down Expand Up @@ -668,7 +684,6 @@
*/
fabric.Image.fromElement = function(element, callback, options) {
var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);

fabric.Image.fromURL(parsedAttributes['xlink:href'], callback,
extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
};
Expand Down
14 changes: 12 additions & 2 deletions src/shapes/object.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -1329,16 +1329,26 @@
* This function is an helper for svg import. it removes the transform matrix
* and set to object properties that fabricjs can handle
* @private
* @chainable
* @param {Object} preserveAspectRatioOptions
* @return {thisArg}
*/
_removeTransformMatrix: function() {
_removeTransformMatrix: function(preserveAspectRatioOptions) {
var center = this._findCenterFromElement();
if (this.transformMatrix) {
this._assignTransformMatrixProps();
center = fabric.util.transformPoint(center, this.transformMatrix);
}
this.transformMatrix = null;
if (preserveAspectRatioOptions) {
this.scaleX *= preserveAspectRatioOptions.scaleX;
this.scaleY *= preserveAspectRatioOptions.scaleY;
this.cropX = preserveAspectRatioOptions.cropX;
this.cropY = preserveAspectRatioOptions.cropY;
center.x += preserveAspectRatioOptions.offsetLeft;
center.y += preserveAspectRatioOptions.offsetTop;
this.width = preserveAspectRatioOptions.width;
this.height = preserveAspectRatioOptions.height;
}
this.setPositionByOrigin(center, 'center', 'center');
},

Expand Down
Loading

0 comments on commit a2f9c9f

Please sign in to comment.