diff --git a/src/elements_parser.js b/src/elements_parser.js index ab2088be121..0bb377f0b9c 100644 --- a/src/elements_parser.js +++ b/src/elements_parser.js @@ -46,8 +46,8 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp var _this = this; return function(obj) { var _options; - _this.resolveGradient(obj, 'fill'); - _this.resolveGradient(obj, 'stroke'); + _this.resolveGradient(obj, el, 'fill'); + _this.resolveGradient(obj, el, 'stroke'); if (obj instanceof fabric.Image && obj._originalElement) { _options = obj.parsePreserveAspectRatioAttribute(el); } @@ -69,10 +69,12 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp return fabric[storage][this.svgUid][id]; }; - proto.resolveGradient = function(obj, property) { + proto.resolveGradient = function(obj, el, property) { var gradientDef = this.extractPropertyDefinition(obj, property, 'gradientDefs'); if (gradientDef) { - obj.set(property, fabric.Gradient.fromElement(gradientDef, obj)); + var opacityAttr = el.getAttribute(property + '-opacity'); + var gradient = fabric.Gradient.fromElement(gradientDef, obj, opacityAttr); + obj.set(property, gradient); } }; diff --git a/src/gradient.class.js b/src/gradient.class.js index 8288fc49cf2..b3313b53e67 100644 --- a/src/gradient.class.js +++ b/src/gradient.class.js @@ -1,7 +1,7 @@ (function() { /* _FROM_SVG_START_ */ - function getColorStop(el) { + function getColorStop(el, multiplier) { var style = el.getAttribute('style'), offset = el.getAttribute('offset') || 0, color, colorAlpha, opacity, i; @@ -41,7 +41,7 @@ color = new fabric.Color(color); colorAlpha = color.getAlpha(); opacity = isNaN(parseFloat(opacity)) ? 1 : parseFloat(opacity); - opacity *= colorAlpha; + opacity *= colorAlpha * multiplier; return { offset: offset, @@ -302,11 +302,12 @@ * @memberOf fabric.Gradient * @param {SVGGradientElement} el SVG gradient element * @param {fabric.Object} instance + * @param {String} opacityAttr A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity. * @return {fabric.Gradient} Gradient instance * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement * @see http://www.w3.org/TR/SVG/pservers.html#RadialGradientElement */ - fromElement: function(el, instance) { + fromElement: function(el, instance, opacityAttr) { /** * @example: * @@ -340,6 +341,12 @@ * */ + var multiplier = parseFloat(opacityAttr) / (/%$/.test(opacityAttr) ? 100 : 1); + multiplier = multiplier < 0 ? 0 : multiplier > 1 ? 1 : multiplier; + if (isNaN(multiplier)) { + multiplier = 1; + } + var colorStopEls = el.getElementsByTagName('stop'), type, gradientUnits = el.getAttribute('gradientUnits') || 'objectBoundingBox', @@ -362,7 +369,7 @@ } for (i = colorStopEls.length; i--; ) { - colorStops.push(getColorStop(colorStopEls[i])); + colorStops.push(getColorStop(colorStopEls[i], multiplier)); } ellipseMatrix = _convertPercentUnitsToValues(instance, coords, gradientUnits); diff --git a/test/unit/gradient.js b/test/unit/gradient.js index 66f97cfe6c1..7c32f1b18fe 100644 --- a/test/unit/gradient.js +++ b/test/unit/gradient.js @@ -209,7 +209,7 @@ element.appendChild(stop2); var object = new fabric.Object({ width: 100, height: 100 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -250,7 +250,7 @@ element.appendChild(stop2); var object = new fabric.Object({ width: 200, height: 200 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -283,7 +283,7 @@ element.appendChild(stop2); var object = new fabric.Object({ width: 200, height: 200 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -315,7 +315,7 @@ element.appendChild(stop2); var object = new fabric.Object({ width: 100, height: 100, top: 0, left: 0 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -350,7 +350,7 @@ element.appendChild(stop2); var object = new fabric.Object({ width: 100, height: 100 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -369,13 +369,13 @@ element.setAttribute('y2', 'Infinity'); var object = new fabric.Object({ width: 200, height: 200 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 60); assert.equal(gradient.coords.y1, 20); assert.equal(gradient.coords.x2, 40); assert.equal(gradient.coords.y2, 200); object = new fabric.Object({ width: 200, height: 200, top: 50, left: 10 }); - gradient = fabric.Gradient.fromElement(element, object); + gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 70); assert.equal(gradient.coords.y1, 70); assert.equal(gradient.coords.x2, 50); @@ -394,7 +394,7 @@ element.setAttribute('r', '100%'); var object = new fabric.Object({ width: 200, height: 200 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 60, 'should change with width height'); assert.equal(gradient.coords.y1, 40, 'should change with width height'); assert.equal(gradient.coords.x2, 20, 'should change with width height'); @@ -403,7 +403,7 @@ assert.equal(gradient.coords.r2, 200, 'should change with width height'); object = new fabric.Object({ width: 200, height: 200, top: 10, left: 10 }); - gradient = fabric.Gradient.fromElement(element, object); + gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 70, 'should change with top left'); assert.equal(gradient.coords.y1, 50, 'should change with top left'); assert.equal(gradient.coords.x2, 30, 'should change with top left'); @@ -425,7 +425,7 @@ element.setAttribute('gradientUnits', 'userSpaceOnUse'); var object = new fabric.Object({ width: 200, height: 200 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 30, 'should not change with width height'); assert.equal(gradient.coords.y1, 20, 'should not change with width height'); assert.equal(gradient.coords.x2, 15, 'should not change with width height'); @@ -434,7 +434,7 @@ assert.equal(gradient.coords.r2, 100, 'should not change with width height'); object = new fabric.Object({ width: 200, height: 200, top: 50, left: 60 }); - gradient = fabric.Gradient.fromElement(element, object); + gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 30, 'should not change with top left'); assert.equal(gradient.coords.y1, 20, 'should not change with top left'); assert.equal(gradient.coords.x2, 15, 'should not change with top left'); @@ -455,14 +455,14 @@ element.setAttribute('gradientUnits', 'userSpaceOnUse'); var object = new fabric.Object({ width: 200, height: 200 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 30, 'should not change with width height'); assert.equal(gradient.coords.y1, 20, 'should not change with width height'); assert.equal(gradient.coords.x2, 15, 'should not change with width height'); assert.equal(gradient.coords.y2, 18, 'should not change with width height'); object = new fabric.Object({ width: 200, height: 200, top: 40, left: 40 }); - gradient = fabric.Gradient.fromElement(element, object); + gradient = fabric.Gradient.fromElement(element, object, ''); assert.equal(gradient.coords.x1, 30, 'should not change with top left'); assert.equal(gradient.coords.y1, 20, 'should not change with top left'); assert.equal(gradient.coords.x2, 15, 'should not change with top left'); @@ -486,7 +486,7 @@ element.appendChild(stop2); var object = new fabric.Object({ width: 100, height: 100 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -519,7 +519,7 @@ element.appendChild(stop2); element.setAttribute('gradientTransform', 'matrix(3.321 -0.6998 0.4077 1.9347 -440.9168 -408.0598)'); var object = new fabric.Object({ width: 100, height: 100 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -568,7 +568,7 @@ element.appendChild(stop4); var object = new fabric.Object({ width: 100, height: 100 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); @@ -625,7 +625,7 @@ element.appendChild(stop4); var object = new fabric.Object({ width: 100, height: 100 }); - var gradient = fabric.Gradient.fromElement(element, object); + var gradient = fabric.Gradient.fromElement(element, object, ''); assert.ok(gradient instanceof fabric.Gradient); diff --git a/test/unit/parser.js b/test/unit/parser.js index 7938d9d87f3..75bdb4138a9 100644 --- a/test/unit/parser.js +++ b/test/unit/parser.js @@ -451,6 +451,28 @@ }); }); + QUnit.test('parseSVGFromString path fill-opacity with gradient', function(assert) { + var done = assert.async(); + var string = '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + + fabric.loadSVGFromString(string, function(objects) { + assert.equal(objects[0].fill.colorStops[0].opacity, 0.5); + assert.equal(objects[0].fill.colorStops[0].color, 'rgb(255,0,0)'); + assert.equal(objects[0].fill.colorStops[1].opacity, 0.25); + assert.equal(objects[0].fill.colorStops[1].color, 'rgb(0,255,0)'); + done(); + }); + }); + QUnit.test('parseSVGFromString with svg:namespace', function(assert) { var done = assert.async(); var string = '' +