diff --git a/src/parser.js b/src/parser.js index 6fde58ce..927ab30f 100644 --- a/src/parser.js +++ b/src/parser.js @@ -468,11 +468,14 @@ viewBoxWidth, viewBoxHeight, matrix, el, widthAttr = element.getAttribute('width'), heightAttr = element.getAttribute('height'), + x = element.getAttribute('x') || 0, + y = element.getAttribute('y') || 0, + preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '', missingViewBox = (!viewBoxAttr || !reViewBoxTagNames.test(element.tagName) || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))), missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'), toBeParsed = missingViewBox && missingDimAttr, - parsedDim = { }; + parsedDim = { }, translateMatrix = ''; parsedDim.width = 0; parsedDim.height = 0; @@ -505,14 +508,21 @@ } // default is to preserve aspect ratio - // preserveAspectRatio attribute to be implemented - scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX); + preserveAspectRatio = fabric.util.parsePreserveAspectRatioAttribute(preserveAspectRatio); + if (preserveAspectRatio.alignX !== 'none') { + //translate all container for the effect of Mid, Min, Max + scaleY = scaleX = (scaleX > scaleY ? scaleY : scaleX); + } - if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0) { + if (scaleX === 1 && scaleY === 1 && minX === 0 && minY === 0 && x === 0 && y === 0) { return parsedDim; } - matrix = ' matrix(' + scaleX + + if (x || y) { + translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') '; + } + + matrix = translateMatrix + ' matrix(' + scaleX + ' 0' + ' 0 ' + scaleY + ' ' + diff --git a/src/shapes/image.class.js b/src/shapes/image.class.js index cc2107cf..65cad1cd 100644 --- a/src/shapes/image.class.js +++ b/src/shapes/image.class.js @@ -589,28 +589,13 @@ */ fabric.Image.fromElement = function(element, callback, options) { var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES), - align = 'xMidYMid', meetOrSlice = 'meet', alignX, alignY, aspectRatioAttrs; + preserveAR; if (parsedAttributes.preserveAspectRatio) { - aspectRatioAttrs = parsedAttributes.preserveAspectRatio.split(' '); + preserveAR = fabric.util.parsePreserveAspectRatioAttribute(parsedAttributes.preserveAspectRatio); + extend(parsedAttributes, preserveAR); } - if (aspectRatioAttrs && aspectRatioAttrs.length) { - meetOrSlice = aspectRatioAttrs.pop(); - if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') { - align = meetOrSlice; - meetOrSlice = 'meet'; - } - else if (aspectRatioAttrs.length) { - align = aspectRatioAttrs.pop(); - } - } - //divide align in alignX and alignY - alignX = align !== 'none' ? align.slice(1, 4) : 'none'; - alignY = align !== 'none' ? align.slice(5, 8) : 'none'; - parsedAttributes.alignX = alignX; - parsedAttributes.alignY = alignY; - parsedAttributes.meetOrSlice = meetOrSlice; fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); }; diff --git a/src/util/misc.js b/src/util/misc.js index 18b832a6..d5c4a23b 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -522,6 +522,35 @@ imageData = null; return _isTransparent; + }, + + /** + * Parse preserveAspectRatio attribute from element + * @param {string} attribute to be parsed + * @return {Object} an object containing align and meetOrSlice attribute + */ + parsePreserveAspectRatioAttribute: function(attribute) { + var meetOrSlice = 'meet', alignX = 'Mid', alignY = 'Mid', + aspectRatioAttrs = attribute.split(' '), align; + + if (aspectRatioAttrs && aspectRatioAttrs.length) { + meetOrSlice = aspectRatioAttrs.pop(); + if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') { + align = meetOrSlice; + meetOrSlice = 'meet'; + } + else if (aspectRatioAttrs.length) { + align = aspectRatioAttrs.pop(); + } + } + //divide align in alignX and alignY + alignX = align !== 'none' ? align.slice(1, 4) : 'none'; + alignY = align !== 'none' ? align.slice(5, 8) : 'none'; + return { + meetOrSlice: meetOrSlice, + alignX: alignX, + alignY: alignY + }; } };