1 (function() { 2 3 function getColorStopFromStyle(el) { 4 var style = el.getAttribute('style'); 5 6 if (style) { 7 var keyValuePairs = style.split(/\s*;\s*/); 8 9 for (var i = keyValuePairs.length; i--; ) { 10 11 var split = keyValuePairs[i].split(/\s*:\s*/), 12 key = split[0].trim(), 13 value = split[1].trim(); 14 15 if (key === 'stop-color') { 16 return value; 17 } 18 } 19 } 20 } 21 22 /** @namespace */ 23 24 fabric.Gradient = { 25 26 /** 27 * @method create 28 * @static 29 */ 30 create: function(ctx, options) { 31 options || (options = { }); 32 33 var x1 = options.x1 || 0, 34 y1 = options.y1 || 0, 35 x2 = options.x2 || ctx.canvas.width, 36 y2 = options.y2 || 0, 37 colorStops = options.colorStops; 38 39 var gradient = ctx.createLinearGradient(x1, y1, x2, y2); 40 41 for (var position in colorStops) { 42 var colorValue = colorStops[position]; 43 gradient.addColorStop(parseFloat(position), colorValue); 44 } 45 return gradient; 46 }, 47 48 /** 49 * @method fromElement 50 * @static 51 * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement 52 */ 53 fromElement: function(el, ctx, instance) { 54 55 /** 56 * @example: 57 * 58 * <linearGradient id="grad1"> 59 * <stop offset="0%" stop-color="white"/> 60 * <stop offset="100%" stop-color="black"/> 61 * </linearGradient> 62 * 63 * OR 64 * 65 * <linearGradient id="grad1"> 66 * <stop offset="0%" style="stop-color:rgb(255,255,255)"/> 67 * <stop offset="100%" style="stop-color:rgb(0,0,0)"/> 68 * </linearGradient> 69 * 70 */ 71 72 var colorStopEls = el.getElementsByTagName('stop'), 73 el, 74 offset, 75 colorStops = { }, 76 colorStopFromStyle; 77 78 for (var i = colorStopEls.length; i--; ) { 79 el = colorStopEls[i]; 80 offset = parseInt(el.getAttribute('offset'), 10) / 100; 81 colorStops[offset] = getColorStopFromStyle(el) || el.getAttribute('stop-color'); 82 } 83 84 var coords = { 85 x1: el.getAttribute('x1') || 0, 86 y1: el.getAttribute('y1') || 0, 87 x2: el.getAttribute('x2') || '100%', 88 y2: el.getAttribute('y2') || 0 89 }; 90 91 _convertPercentUnitsToValues(instance, coords); 92 93 return fabric.Gradient.create(ctx, { 94 x1: coords.x1, 95 y1: coords.y1, 96 x2: coords.x2, 97 y2: coords.y2, 98 colorStops: colorStops 99 }); 100 }, 101 102 /** 103 * @method forObject 104 * @static 105 */ 106 forObject: function(obj, ctx, options) { 107 options || (options = { }); 108 109 _convertPercentUnitsToValues(obj, options); 110 111 var gradient = fabric.Gradient.create(ctx, { 112 x1: options.x1 - (obj.width / 2), 113 y1: options.y1 - (obj.height / 2), 114 x2: options.x2 - (obj.width / 2), 115 y2: options.y2 - (obj.height / 2), 116 colorStops: options.colorStops 117 }); 118 119 return gradient; 120 } 121 }; 122 123 function _convertPercentUnitsToValues(object, options) { 124 for (var prop in options) { 125 if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) { 126 var percents = parseFloat(options[prop], 10); 127 if (prop === 'x1' || prop === 'x2') { 128 options[prop] = object.width * percents / 100; 129 } 130 else if (prop === 'y1' || prop === 'y2') { 131 options[prop] = object.height * percents / 100; 132 } 133 } 134 // normalize rendering point (should be from top/left corner rather than center of the shape) 135 if (prop === 'x1' || prop === 'x2') { 136 options[prop] -= object.width / 2; 137 } 138 else if (prop === 'y1' || prop === 'y2') { 139 options[prop] -= object.height / 2; 140 } 141 } 142 } 143 144 /** 145 * Parses an SVG document, returning all of the gradient declarations found in it 146 * @static 147 * @function 148 * @memberOf fabric 149 * @method getGradientDefs 150 * @param {SVGDocument} doc SVG document to parse 151 * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element 152 */ 153 function getGradientDefs(doc) { 154 var linearGradientEls = doc.getElementsByTagName('linearGradient'), 155 radialGradientEls = doc.getElementsByTagName('radialGradient'), 156 el, 157 gradientDefs = { }; 158 159 for (var i = linearGradientEls.length; i--; ) { 160 el = linearGradientEls[i]; 161 gradientDefs[el.id] = el; 162 } 163 164 for (var i = radialGradientEls.length; i--; ) { 165 el = radialGradientEls[i]; 166 gradientDefs[el.id] = el; 167 } 168 169 return gradientDefs; 170 } 171 172 fabric.getGradientDefs = getGradientDefs; 173 174 })();