(function() {
function getColorStopFromStyle(el) {
var style = el.getAttribute('style');
if (style) {
var keyValuePairs = style.split(/\s*;\s*/);
if (keyValuePairs[keyValuePairs.length-1] === '') {
keyValuePairs.pop();
}
for (var i = keyValuePairs.length; i--; ) {
var split = keyValuePairs[i].split(/\s*:\s*/),
key = split[0].trim(),
value = split[1].trim();
if (key === 'stop-color') {
return value;
}
}
}
}
/**
* @class Object
* @memberOf fabric
*/
fabric.Gradient = fabric.util.createClass(/** @scope fabric.Gradient.prototype */ {
initialize: function(options) {
options || (options = { });
this.x1 = options.x1 || 0;
this.y1 = options.y1 || 0;
this.x2 = options.x2 || 0;
this.y2 = options.y2 || 0;
this.colorStops = options.colorStops;
},
toObject: function() {
return {
x1: this.x1,
x2: this.x2,
y1: this.y1,
y2: this.y2,
colorStops: this.colorStops
};
},
toLiveGradient: function(ctx) {
var gradient = ctx.createLinearGradient(
this.x1, this.y1, this.x2 || ctx.canvas.width, this.y2);
for (var position in this.colorStops) {
var colorValue = this.colorStops[position];
gradient.addColorStop(parseFloat(position), colorValue);
}
return gradient;
}
});
fabric.util.object.extend(fabric.Gradient, {
/**
* @method fromElement
* @static
* @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement
*/
fromElement: function(el, instance) {
/**
* @example:
*
*
*
*
*
*
* OR
*
*
*
*
*
*
*/
var colorStopEls = el.getElementsByTagName('stop'),
el,
offset,
colorStops = { },
colorStopFromStyle,
coords = {
x1: el.getAttribute('x1') || 0,
y1: el.getAttribute('y1') || 0,
x2: el.getAttribute('x2') || '100%',
y2: el.getAttribute('y2') || 0
};
for (var i = colorStopEls.length; i--; ) {
el = colorStopEls[i];
offset = el.getAttribute('offset');
// convert percents to absolute values
offset = parseFloat(offset) / (/%$/.test(offset) ? 100 : 1);
colorStops[offset] = getColorStopFromStyle(el) || el.getAttribute('stop-color');
}
_convertPercentUnitsToValues(instance, coords);
return new fabric.Gradient({
x1: coords.x1,
y1: coords.y1,
x2: coords.x2,
y2: coords.y2,
colorStops: colorStops
});
},
/**
* @method forObject
* @static
*/
forObject: function(obj, options) {
options || (options = { });
_convertPercentUnitsToValues(obj, options);
return new fabric.Gradient(options);
}
});
function _convertPercentUnitsToValues(object, options) {
for (var prop in options) {
if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) {
var percents = parseFloat(options[prop], 10);
if (prop === 'x1' || prop === 'x2') {
options[prop] = object.width * percents / 100;
}
else if (prop === 'y1' || prop === 'y2') {
options[prop] = object.height * percents / 100;
}
}
// normalize rendering point (should be from top/left corner rather than center of the shape)
if (prop === 'x1' || prop === 'x2') {
options[prop] -= object.width / 2;
}
else if (prop === 'y1' || prop === 'y2') {
options[prop] -= object.height / 2;
}
}
}
/**
* Parses an SVG document, returning all of the gradient declarations found in it
* @static
* @function
* @memberOf fabric
* @method getGradientDefs
* @param {SVGDocument} doc SVG document to parse
* @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element
*/
function getGradientDefs(doc) {
var linearGradientEls = doc.getElementsByTagName('linearGradient'),
radialGradientEls = doc.getElementsByTagName('radialGradient'),
el,
gradientDefs = { };
for (var i = linearGradientEls.length; i--; ) {
el = linearGradientEls[i];
gradientDefs[el.getAttribute('id')] = el;
}
for (var i = radialGradientEls.length; i--; ) {
el = radialGradientEls[i];
gradientDefs[el.getAttribute('id')] = el;
}
return gradientDefs;
}
fabric.getGradientDefs = getGradientDefs;
})();