fabric-rails 1.0.12 → 1.0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/CHANGELOG.md +16 -0
  2. data/README.md +1 -1
  3. data/lib/fabric/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/event.js +1909 -0
  5. data/vendor/assets/javascripts/fabric.js +64 -16464
  6. data/vendor/assets/javascripts/fabric/HEADER.js +31 -0
  7. data/vendor/assets/javascripts/fabric/canvas.class.js +1007 -0
  8. data/vendor/assets/javascripts/fabric/canvas_animation.mixin.js +113 -0
  9. data/vendor/assets/javascripts/fabric/canvas_events.mixin.js +482 -0
  10. data/vendor/assets/javascripts/fabric/canvas_gestures.mixin.js +79 -0
  11. data/vendor/assets/javascripts/fabric/canvas_serialization.mixin.js +311 -0
  12. data/vendor/assets/javascripts/fabric/circle.class.js +182 -0
  13. data/vendor/assets/javascripts/fabric/color.class.js +284 -0
  14. data/vendor/assets/javascripts/fabric/ellipse.class.js +169 -0
  15. data/vendor/assets/javascripts/fabric/freedrawing.class.js +256 -0
  16. data/vendor/assets/javascripts/fabric/gradient.class.js +211 -0
  17. data/vendor/assets/javascripts/fabric/group.class.js +556 -0
  18. data/vendor/assets/javascripts/fabric/image.class.js +418 -0
  19. data/vendor/assets/javascripts/fabric/image_filters.js +809 -0
  20. data/vendor/assets/javascripts/fabric/intersection.class.js +178 -0
  21. data/vendor/assets/javascripts/fabric/line.class.js +188 -0
  22. data/vendor/assets/javascripts/fabric/log.js +26 -0
  23. data/vendor/assets/javascripts/fabric/node.js +149 -0
  24. data/vendor/assets/javascripts/fabric/object.class.js +1068 -0
  25. data/vendor/assets/javascripts/fabric/object_geometry.mixin.js +308 -0
  26. data/vendor/assets/javascripts/fabric/object_interactivity.mixin.js +496 -0
  27. data/vendor/assets/javascripts/fabric/object_origin.mixin.js +207 -0
  28. data/vendor/assets/javascripts/fabric/object_straightening.mixin.js +94 -0
  29. data/vendor/assets/javascripts/fabric/observable.mixin.js +91 -0
  30. data/vendor/assets/javascripts/fabric/parser.js +750 -0
  31. data/vendor/assets/javascripts/fabric/path.class.js +794 -0
  32. data/vendor/assets/javascripts/fabric/path_group.class.js +240 -0
  33. data/vendor/assets/javascripts/fabric/pattern.class.js +69 -0
  34. data/vendor/assets/javascripts/fabric/point.class.js +327 -0
  35. data/vendor/assets/javascripts/fabric/polygon.class.js +184 -0
  36. data/vendor/assets/javascripts/fabric/polyline.class.js +157 -0
  37. data/vendor/assets/javascripts/fabric/rect.class.js +298 -0
  38. data/vendor/assets/javascripts/fabric/scout.js +45 -0
  39. data/vendor/assets/javascripts/fabric/shadow.class.js +70 -0
  40. data/vendor/assets/javascripts/fabric/stateful.js +88 -0
  41. data/vendor/assets/javascripts/fabric/static_canvas.class.js +1298 -0
  42. data/vendor/assets/javascripts/fabric/text.class.js +934 -0
  43. data/vendor/assets/javascripts/fabric/triangle.class.js +108 -0
  44. data/vendor/assets/javascripts/fabric/util/anim_ease.js +360 -0
  45. data/vendor/assets/javascripts/fabric/util/dom_event.js +237 -0
  46. data/vendor/assets/javascripts/fabric/util/dom_misc.js +245 -0
  47. data/vendor/assets/javascripts/fabric/util/dom_request.js +72 -0
  48. data/vendor/assets/javascripts/fabric/util/dom_style.js +71 -0
  49. data/vendor/assets/javascripts/fabric/util/lang_array.js +250 -0
  50. data/vendor/assets/javascripts/fabric/util/lang_class.js +97 -0
  51. data/vendor/assets/javascripts/fabric/util/lang_function.js +35 -0
  52. data/vendor/assets/javascripts/fabric/util/lang_object.js +34 -0
  53. data/vendor/assets/javascripts/fabric/util/lang_string.js +60 -0
  54. data/vendor/assets/javascripts/fabric/util/misc.js +406 -0
  55. data/vendor/assets/javascripts/json2.js +491 -0
  56. metadata +53 -2
@@ -0,0 +1,418 @@
1
+ (function(global) {
2
+
3
+ "use strict";
4
+
5
+ var extend = fabric.util.object.extend;
6
+
7
+ if (!global.fabric) {
8
+ global.fabric = { };
9
+ }
10
+
11
+ if (global.fabric.Image) {
12
+ fabric.warn('fabric.Image is already defined.');
13
+ return;
14
+ }
15
+
16
+ /**
17
+ * Image class
18
+ * @class Image
19
+ * @extends fabric.Object
20
+ */
21
+ fabric.Image = fabric.util.createClass(fabric.Object, /** @scope fabric.Image.prototype */ {
22
+
23
+ /**
24
+ * Type of an object
25
+ * @property
26
+ * @type String
27
+ */
28
+ type: 'image',
29
+
30
+ /**
31
+ * Constructor
32
+ * @param {HTMLImageElement | String} element Image element
33
+ * @param {Object} [options] Options object
34
+ * @return {fabric.Image}
35
+ */
36
+ initialize: function(element, options) {
37
+ options || (options = { });
38
+
39
+ this.callSuper('initialize', options);
40
+ this._initElement(element);
41
+ this._originalImage = this.getElement();
42
+ this._initConfig(options);
43
+
44
+ this.filters = [ ];
45
+
46
+ if (options.filters) {
47
+ this.filters = options.filters;
48
+ this.applyFilters();
49
+ }
50
+ },
51
+
52
+ /**
53
+ * Returns image element which this instance if based on
54
+ * @method getElement
55
+ * @return {HTMLImageElement} image element
56
+ */
57
+ getElement: function() {
58
+ return this._element;
59
+ },
60
+
61
+ /**
62
+ * Sets image element for this instance to a specified one
63
+ * @method setElement
64
+ * @param {HTMLImageElement} element
65
+ * @return {fabric.Image} thisArg
66
+ * @chainable
67
+ */
68
+ setElement: function(element) {
69
+ this._element = element;
70
+ this._initConfig();
71
+ return this;
72
+ },
73
+
74
+ /**
75
+ * Returns original size of an image
76
+ * @method getOriginalSize
77
+ * @return {Object} object with "width" and "height" properties
78
+ */
79
+ getOriginalSize: function() {
80
+ var element = this.getElement();
81
+ return {
82
+ width: element.width,
83
+ height: element.height
84
+ };
85
+ },
86
+
87
+ /**
88
+ * Renders image on a specified context
89
+ * @method render
90
+ * @param {CanvasRenderingContext2D} ctx Context to render on
91
+ */
92
+ render: function(ctx, noTransform) {
93
+ ctx.save();
94
+ var m = this.transformMatrix;
95
+ // this._resetWidthHeight();
96
+ if (this.group) {
97
+ ctx.translate(-this.group.width/2 + this.width/2, -this.group.height/2 + this.height/2);
98
+ }
99
+ if (m) {
100
+ ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
101
+ }
102
+ if (!noTransform) {
103
+ this.transform(ctx);
104
+ }
105
+
106
+ this._setShadow(ctx);
107
+ this._render(ctx);
108
+ this._removeShadow(ctx);
109
+
110
+ if (this.active && !noTransform) {
111
+ this.drawBorders(ctx);
112
+ this.drawControls(ctx);
113
+ }
114
+ ctx.restore();
115
+ },
116
+
117
+ /**
118
+ * Returns object representation of an instance
119
+ * @method toObject
120
+ * @param {Array} propertiesToInclude
121
+ * @return {Object} object representation of an instance
122
+ */
123
+ toObject: function(propertiesToInclude) {
124
+ return extend(this.callSuper('toObject', propertiesToInclude), {
125
+ src: this._originalImage.src || this._originalImage._src,
126
+ filters: this.filters.concat()
127
+ });
128
+ },
129
+
130
+ /**
131
+ * Returns SVG representation of an instance
132
+ * @method toSVG
133
+ * @return {String} svg representation of an instance
134
+ */
135
+ toSVG: function() {
136
+ return '<g transform="' + this.getSvgTransform() + '">'+
137
+ '<image xlink:href="' + this.getSvgSrc() + '" '+
138
+ 'style="' + this.getSvgStyles() + '" ' +
139
+ // we're essentially moving origin of transformation from top/left corner to the center of the shape
140
+ // by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
141
+ // so that object's center aligns with container's left/top
142
+ 'transform="translate('+ (-this.width/2) + ' ' + (-this.height/2) + ')" ' +
143
+ 'width="' + this.width + '" ' +
144
+ 'height="' + this.height + '"' + '></image>' +
145
+ '</g>';
146
+ },
147
+
148
+ /**
149
+ * Returns source of an image
150
+ * @method getSrc
151
+ * @return {String} Source of an image
152
+ */
153
+ getSrc: function() {
154
+ return this.getElement().src || this.getElement()._src;
155
+ },
156
+
157
+ /**
158
+ * Returns string representation of an instance
159
+ * @method toString
160
+ * @return {String} String representation of an instance
161
+ */
162
+ toString: function() {
163
+ return '#<fabric.Image: { src: "' + this.getSrc() + '" }>';
164
+ },
165
+
166
+ /**
167
+ * Returns a clone of an instance
168
+ * @method clone
169
+ * @param {Array} propertiesToInclude
170
+ * @param {Function} callback Callback is invoked with a clone as a first argument
171
+ */
172
+ clone: function(callback, propertiesToInclude) {
173
+ this.constructor.fromObject(this.toObject(propertiesToInclude), callback);
174
+ },
175
+
176
+ /**
177
+ * Applies filters assigned to this image (from "filters" array)
178
+ * @mthod applyFilters
179
+ * @param {Function} callback Callback is invoked when all filters have been applied and new image is generated
180
+ * @return {fabric.Image} thisArg
181
+ * @chainable
182
+ */
183
+ applyFilters: function(callback) {
184
+
185
+ if (this.filters.length === 0) {
186
+ this.setElement(this._originalImage);
187
+ callback && callback();
188
+ return;
189
+ }
190
+
191
+ var isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined',
192
+ imgEl = this._originalImage,
193
+ canvasEl = fabric.util.createCanvasElement(),
194
+ replacement = isLikelyNode ? new (require('canvas').Image)() : fabric.document.createElement('img'),
195
+ _this = this;
196
+
197
+ canvasEl.width = imgEl.width;
198
+ canvasEl.height = imgEl.height;
199
+
200
+ canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height);
201
+
202
+ this.filters.forEach(function(filter) {
203
+ filter && filter.applyTo(canvasEl);
204
+ });
205
+
206
+ /** @ignore */
207
+ replacement.onload = function() {
208
+ _this._element = replacement;
209
+ callback && callback();
210
+ replacement.onload = canvasEl = imgEl = null;
211
+ };
212
+ replacement.width = imgEl.width;
213
+ replacement.height = imgEl.height;
214
+
215
+ if (isLikelyNode) {
216
+ // cut off data:image/png;base64, part in the beginning
217
+ var base64str = canvasEl.toDataURL('image/png').substring(22);
218
+ replacement.src = new Buffer(base64str, 'base64');
219
+ _this._element = replacement;
220
+
221
+ // onload doesn't fire in node, so we invoke callback manually
222
+ callback && callback();
223
+ }
224
+ else {
225
+ replacement.src = canvasEl.toDataURL('image/png');
226
+ }
227
+
228
+ return this;
229
+ },
230
+
231
+ /**
232
+ * @private
233
+ * @method _render
234
+ * @param ctx
235
+ */
236
+ _render: function(ctx) {
237
+ ctx.drawImage(
238
+ this._element,
239
+ -this.width / 2,
240
+ -this.height / 2,
241
+ this.width,
242
+ this.height
243
+ );
244
+ },
245
+
246
+ /**
247
+ * @private
248
+ * @method _resetWidthHeight
249
+ */
250
+ _resetWidthHeight: function() {
251
+ var element = this.getElement();
252
+
253
+ this.set('width', element.width);
254
+ this.set('height', element.height);
255
+ },
256
+
257
+ /**
258
+ * The Image class's initialization method. This method is automatically
259
+ * called by the constructor.
260
+ * @private
261
+ * @method _initElement
262
+ * @param {HTMLImageElement|String} el The element representing the image
263
+ */
264
+ _initElement: function(element) {
265
+ this.setElement(fabric.util.getById(element));
266
+ fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
267
+ },
268
+
269
+ /**
270
+ * @private
271
+ * @method _initConfig
272
+ * @param {Object} [options] Options object
273
+ */
274
+ _initConfig: function(options) {
275
+ options || (options = { });
276
+ this.setOptions(options);
277
+ this._setWidthHeight(options);
278
+ },
279
+
280
+ /**
281
+ * @private
282
+ * @method _initFilters
283
+ * @param {Object} object Object with filters property
284
+ */
285
+ _initFilters: function(object) {
286
+ if (object.filters && object.filters.length) {
287
+ this.filters = object.filters.map(function(filterObj) {
288
+ return filterObj && fabric.Image.filters[filterObj.type].fromObject(filterObj);
289
+ });
290
+ }
291
+ },
292
+
293
+ /**
294
+ * @private
295
+ * @method _setWidthHeight
296
+ * @param {Object} [options] Object with width/height properties
297
+ */
298
+ _setWidthHeight: function(options) {
299
+ this.width = 'width' in options
300
+ ? options.width
301
+ : (this.getElement().width || 0);
302
+
303
+ this.height = 'height' in options
304
+ ? options.height
305
+ : (this.getElement().height || 0);
306
+ },
307
+
308
+ /**
309
+ * Returns complexity of an instance
310
+ * @method complexity
311
+ * @return {Number} complexity
312
+ */
313
+ complexity: function() {
314
+ return 1;
315
+ }
316
+ });
317
+
318
+ /**
319
+ * Default CSS class name for canvas
320
+ * @static
321
+ * @type String
322
+ */
323
+ fabric.Image.CSS_CANVAS = "canvas-img";
324
+
325
+ /**
326
+ * Alias for getSrc
327
+ * @static
328
+ * @method getSvgSrc
329
+ */
330
+ fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;
331
+
332
+ /**
333
+ * Creates an instance of fabric.Image from its object representation
334
+ * @static
335
+ * @method fromObject
336
+ * @param {Object} object
337
+ * @param {Function} [callback] Callback to invoke when an image instance is created
338
+ */
339
+ fabric.Image.fromObject = function(object, callback) {
340
+ var img = fabric.document.createElement('img'),
341
+ src = object.src;
342
+
343
+ if (object.width) {
344
+ img.width = object.width;
345
+ }
346
+ if (object.height) {
347
+ img.height = object.height;
348
+ }
349
+
350
+ /** @ignore */
351
+ img.onload = function() {
352
+ fabric.Image.prototype._initFilters.call(object, object);
353
+
354
+ var instance = new fabric.Image(img, object);
355
+ callback && callback(instance);
356
+ img = img.onload = img.onerror = null;
357
+ };
358
+
359
+ /** @ignore */
360
+ img.onerror = function() {
361
+ fabric.log('Error loading ' + img.src);
362
+ callback && callback(null, true);
363
+ img = img.onload = img.onerror = null;
364
+ };
365
+ img.src = src;
366
+ };
367
+
368
+ /**
369
+ * Creates an instance of fabric.Image from an URL string
370
+ * @static
371
+ * @method fromURL
372
+ * @param {String} url URL to create an image from
373
+ * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument)
374
+ * @param {Object} [imgOptions] Options object
375
+ */
376
+ fabric.Image.fromURL = function(url, callback, imgOptions) {
377
+ var img = fabric.document.createElement('img');
378
+
379
+ /** @ignore */
380
+ img.onload = function() {
381
+ if (callback) {
382
+ callback(new fabric.Image(img, imgOptions));
383
+ }
384
+ img = img.onload = null;
385
+ };
386
+ img.src = url;
387
+ };
388
+
389
+ /**
390
+ * List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})
391
+ * @static
392
+ * @see http://www.w3.org/TR/SVG/struct.html#ImageElement
393
+ */
394
+ fabric.Image.ATTRIBUTE_NAMES = 'x y width height fill fill-opacity opacity stroke stroke-width transform xlink:href'.split(' ');
395
+
396
+ /**
397
+ * Returns {@link fabric.Image} instance from an SVG element
398
+ * @static
399
+ * @method fabric.Image.fromElement
400
+ * @param {SVGElement} element Element to parse
401
+ * @param {Function} callback Callback to execute when fabric.Image object is created
402
+ * @param {Object} [options] Options object
403
+ * @return {fabric.Image}
404
+ */
405
+ fabric.Image.fromElement = function(element, callback, options) {
406
+ var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);
407
+
408
+ fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
409
+ };
410
+
411
+ /**
412
+ * Indicates that instances of this type are async
413
+ * @static
414
+ * @type Boolean
415
+ */
416
+ fabric.Image.async = true;
417
+
418
+ })(typeof exports !== 'undefined' ? exports : this);
@@ -0,0 +1,809 @@
1
+ /**
2
+ * @namespace
3
+ */
4
+ fabric.Image.filters = { };
5
+
6
+ /**
7
+ * Grayscale image filter class
8
+ * @class fabric.Image.filters.Grayscale
9
+ * @memberOf fabric.Image.filters
10
+ */
11
+ fabric.Image.filters.Grayscale = fabric.util.createClass( /** @scope fabric.Image.filters.Grayscale.prototype */ {
12
+
13
+ /**
14
+ * Filter type
15
+ * @param {String} type
16
+ */
17
+ type: "Grayscale",
18
+
19
+ /**
20
+ * Applies filter to canvas element
21
+ * @method applyTo
22
+ * @memberOf fabric.Image.filters.Grayscale.prototype
23
+ * @param {Object} canvasEl Canvas element to apply filter to
24
+ */
25
+ applyTo: function(canvasEl) {
26
+ var context = canvasEl.getContext('2d'),
27
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
28
+ data = imageData.data,
29
+ iLen = imageData.width,
30
+ jLen = imageData.height,
31
+ index, average, i, j;
32
+
33
+ for (i = 0; i < iLen; i++) {
34
+ for (j = 0; j < jLen; j++) {
35
+
36
+ index = (i * 4) * jLen + (j * 4);
37
+ average = (data[index] + data[index + 1] + data[index + 2]) / 3;
38
+
39
+ data[index] = average;
40
+ data[index + 1] = average;
41
+ data[index + 2] = average;
42
+ }
43
+ }
44
+
45
+ context.putImageData(imageData, 0, 0);
46
+ },
47
+
48
+ /**
49
+ * Returns json representation of filter
50
+ * @method toJSON
51
+ * @return {String} json representation of filter
52
+ */
53
+ toJSON: function() {
54
+ return { type: this.type };
55
+ }
56
+ });
57
+
58
+ /**
59
+ * Returns filter instance from an object representation
60
+ * @static
61
+ * @method fabric.Image.filters.Grayscale.fromObject
62
+ * @return {fabric.Image.filters.Grayscale}
63
+ */
64
+ fabric.Image.filters.Grayscale.fromObject = function() {
65
+ return new fabric.Image.filters.Grayscale();
66
+ };
67
+
68
+ /**
69
+ * Remove white filter class
70
+ * @class fabric.Image.filters.RemoveWhite
71
+ * @memberOf fabric.Image.filters
72
+ */
73
+ fabric.Image.filters.RemoveWhite = fabric.util.createClass( /** @scope fabric.Image.filters.RemoveWhite.prototype */ {
74
+
75
+ /**
76
+ * Filter type
77
+ * @param {String} type
78
+ */
79
+ type: "RemoveWhite",
80
+
81
+ /**
82
+ * Constructor
83
+ * @memberOf fabric.Image.filters.RemoveWhite.prototype
84
+ * @param {Object} [options] Options object
85
+ */
86
+ initialize: function(options) {
87
+ options || (options = { });
88
+ this.threshold = options.threshold || 30;
89
+ this.distance = options.distance || 20;
90
+ },
91
+
92
+ /**
93
+ * Applies filter to canvas element
94
+ * @method applyTo
95
+ * @param {Object} canvasEl Canvas element to apply filter to
96
+ */
97
+ applyTo: function(canvasEl) {
98
+ var context = canvasEl.getContext('2d'),
99
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
100
+ data = imageData.data,
101
+ threshold = this.threshold,
102
+ distance = this.distance,
103
+ limit = 255 - threshold,
104
+ abs = Math.abs,
105
+ r, g, b;
106
+
107
+ for (var i = 0, len = data.length; i < len; i += 4) {
108
+
109
+ r = data[i];
110
+ g = data[i+1];
111
+ b = data[i+2];
112
+
113
+ if (r > limit &&
114
+ g > limit &&
115
+ b > limit &&
116
+ abs(r-g) < distance &&
117
+ abs(r-b) < distance &&
118
+ abs(g-b) < distance) {
119
+
120
+ data[i+3] = 1;
121
+ }
122
+ }
123
+
124
+ context.putImageData(imageData, 0, 0);
125
+ },
126
+
127
+ /**
128
+ * Returns json representation of filter
129
+ * @method toJSON
130
+ * @return {String} json representation of filter
131
+ */
132
+ toJSON: function() {
133
+ return {
134
+ type: this.type,
135
+ threshold: this.threshold,
136
+ distance: this.distance
137
+ };
138
+ }
139
+ });
140
+
141
+ /**
142
+ * Returns filter instance from an object representation
143
+ * @static
144
+ * @method fabric.Image.filters.RemoveWhite.fromObject
145
+ * @return {fabric.Image.filters.RemoveWhite}
146
+ */
147
+ fabric.Image.filters.RemoveWhite.fromObject = function(object) {
148
+ return new fabric.Image.filters.RemoveWhite(object);
149
+ };
150
+
151
+ /**
152
+ * Invert filter class
153
+ * @class fabric.Image.filters.Invert
154
+ * @memberOf fabric.Image.filters
155
+ */
156
+ fabric.Image.filters.Invert = fabric.util.createClass( /** @scope fabric.Image.filters.Invert.prototype */ {
157
+
158
+ /**
159
+ * Filter type
160
+ * @param {String} type
161
+ */
162
+ type: "Invert",
163
+
164
+ /**
165
+ * Applies filter to canvas element
166
+ * @method applyTo
167
+ * @memberOf fabric.Image.filters.Invert.prototype
168
+ * @param {Object} canvasEl Canvas element to apply filter to
169
+ */
170
+ applyTo: function(canvasEl) {
171
+ var context = canvasEl.getContext('2d'),
172
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
173
+ data = imageData.data,
174
+ iLen = data.length, i;
175
+
176
+ for (i = 0; i < iLen; i+=4) {
177
+ data[i] = 255 - data[i];
178
+ data[i + 1] = 255 - data[i + 1];
179
+ data[i + 2] = 255 - data[i + 2];
180
+ }
181
+
182
+ context.putImageData(imageData, 0, 0);
183
+ },
184
+
185
+ /**
186
+ * Returns json representation of filter
187
+ * @method toJSON
188
+ * @return {String} json representation of filter
189
+ */
190
+ toJSON: function() {
191
+ return { type: this.type };
192
+ }
193
+ });
194
+
195
+ /**
196
+ * Returns filter instance from an object representation
197
+ * @static
198
+ * @method fabric.Image.filters.Invert.fromObject
199
+ * @return {fabric.Image.filters.Invert}
200
+ */
201
+ fabric.Image.filters.Invert.fromObject = function() {
202
+ return new fabric.Image.filters.Invert();
203
+ };
204
+
205
+ /**
206
+ * Sepia filter class
207
+ * @class fabric.Image.filters.Sepia
208
+ * @memberOf fabric.Image.filters
209
+ */
210
+ fabric.Image.filters.Sepia = fabric.util.createClass( /** @scope fabric.Image.filters.Sepia.prototype */ {
211
+
212
+ /**
213
+ * Filter type
214
+ * @param {String} type
215
+ */
216
+ type: "Sepia",
217
+
218
+ /**
219
+ * Applies filter to canvas element
220
+ * @method applyTo
221
+ * @memberOf fabric.Image.filters.Sepia.prototype
222
+ * @param {Object} canvasEl Canvas element to apply filter to
223
+ */
224
+ applyTo: function(canvasEl) {
225
+ var context = canvasEl.getContext('2d'),
226
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
227
+ data = imageData.data,
228
+ iLen = data.length, i, avg;
229
+
230
+ for (i = 0; i < iLen; i+=4) {
231
+ avg = 0.3 * data[i] + 0.59 * data[i + 1] + 0.11 * data[i + 2];
232
+ data[i] = avg + 100;
233
+ data[i + 1] = avg + 50;
234
+ data[i + 2] = avg + 255;
235
+ }
236
+
237
+ context.putImageData(imageData, 0, 0);
238
+ },
239
+
240
+ /**
241
+ * Returns json representation of filter
242
+ * @method toJSON
243
+ * @return {String} json representation of filter
244
+ */
245
+ toJSON: function() {
246
+ return { type: this.type };
247
+ }
248
+ });
249
+
250
+ /**
251
+ * Returns filter instance from an object representation
252
+ * @static
253
+ * @method fabric.Image.filters.Sepia.fromObject
254
+ * @return {fabric.Image.filters.Sepia}
255
+ */
256
+ fabric.Image.filters.Sepia.fromObject = function() {
257
+ return new fabric.Image.filters.Sepia();
258
+ };
259
+
260
+ /**
261
+ * Sepia2 filter class
262
+ * @class fabric.Image.filters.Sepia2
263
+ * @memberOf fabric.Image.filters
264
+ */
265
+ fabric.Image.filters.Sepia2 = fabric.util.createClass( /** @scope fabric.Image.filters.Sepia2.prototype */ {
266
+
267
+ /**
268
+ * Filter type
269
+ * @param {String} type
270
+ */
271
+ type: "Sepia2",
272
+
273
+ /**
274
+ * Applies filter to canvas element
275
+ * @method applyTo
276
+ * @memberOf fabric.Image.filters.Sepia.prototype
277
+ * @param {Object} canvasEl Canvas element to apply filter to
278
+ */
279
+ applyTo: function(canvasEl) {
280
+ var context = canvasEl.getContext('2d'),
281
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
282
+ data = imageData.data,
283
+ iLen = data.length, i, r, g, b;
284
+
285
+ for (i = 0; i < iLen; i+=4) {
286
+
287
+ r = data[i];
288
+ g = data[i + 1];
289
+ b = data[i + 2];
290
+
291
+ data[i] = (r * 0.393 + g * 0.769 + b * 0.189 ) / 1.351;
292
+ data[i + 1] = (r * 0.349 + g * 0.686 + b * 0.168 ) / 1.203;
293
+ data[i + 2] = (r * 0.272 + g * 0.534 + b * 0.131 ) / 2.140;
294
+ }
295
+
296
+ context.putImageData(imageData, 0, 0);
297
+ },
298
+
299
+ /**
300
+ * Returns json representation of filter
301
+ * @method toJSON
302
+ * @return {String} json representation of filter
303
+ */
304
+ toJSON: function() {
305
+ return { type: this.type };
306
+ }
307
+ });
308
+
309
+ /**
310
+ * Returns filter instance from an object representation
311
+ * @static
312
+ * @method fabric.Image.filters.Sepia2.fromObject
313
+ * @return {fabric.Image.filters.Sepia2}
314
+ */
315
+ fabric.Image.filters.Sepia2.fromObject = function() {
316
+ return new fabric.Image.filters.Sepia2();
317
+ };
318
+
319
+ /**
320
+ * Brightness filter class
321
+ * @class fabric.Image.filters.Brightness
322
+ * @memberOf fabric.Image.filters
323
+ */
324
+ fabric.Image.filters.Brightness = fabric.util.createClass( /** @scope fabric.Image.filters.Brightness.prototype */ {
325
+
326
+ /**
327
+ * Filter type
328
+ * @param {String} type
329
+ */
330
+ type: "Brightness",
331
+
332
+ /**
333
+ * Constructor
334
+ * @memberOf fabric.Image.filters.Brightness.prototype
335
+ * @param {Object} [options] Options object
336
+ */
337
+ initialize: function(options) {
338
+ options || (options = { });
339
+ this.brightness = options.brightness || 100;
340
+ },
341
+
342
+ /**
343
+ * Applies filter to canvas element
344
+ * @method applyTo
345
+ * @param {Object} canvasEl Canvas element to apply filter to
346
+ */
347
+ applyTo: function(canvasEl) {
348
+ var context = canvasEl.getContext('2d'),
349
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
350
+ data = imageData.data,
351
+ brightness = this.brightness;
352
+
353
+ for (var i = 0, len = data.length; i < len; i += 4) {
354
+ data[i] += brightness;
355
+ data[i + 1] += brightness;
356
+ data[i + 2] += brightness;
357
+ }
358
+
359
+ context.putImageData(imageData, 0, 0);
360
+ },
361
+
362
+ /**
363
+ * Returns json representation of filter
364
+ * @method toJSON
365
+ * @return {String} json representation of filter
366
+ */
367
+ toJSON: function() {
368
+ return {
369
+ type: this.type,
370
+ brightness: this.brightness
371
+ };
372
+ }
373
+ });
374
+
375
+ /**
376
+ * Returns filter instance from an object representation
377
+ * @static
378
+ * @method fabric.Image.filters.Brightness.fromObject
379
+ * @return {fabric.Image.filters.Brightness}
380
+ */
381
+ fabric.Image.filters.Brightness.fromObject = function(object) {
382
+ return new fabric.Image.filters.Brightness(object);
383
+ };
384
+
385
+ /**
386
+ * Noise filter class
387
+ * @class fabric.Image.filters.Noise
388
+ * @memberOf fabric.Image.filters
389
+ */
390
+ fabric.Image.filters.Noise = fabric.util.createClass( /** @scope fabric.Image.filters.Noise.prototype */ {
391
+
392
+ /**
393
+ * Filter type
394
+ * @param {String} type
395
+ */
396
+ type: "Noise",
397
+
398
+ /**
399
+ * Constructor
400
+ * @memberOf fabric.Image.filters.Noise.prototype
401
+ * @param {Object} [options] Options object
402
+ */
403
+ initialize: function(options) {
404
+ options || (options = { });
405
+ this.noise = options.noise || 100;
406
+ },
407
+
408
+ /**
409
+ * Applies filter to canvas element
410
+ * @method applyTo
411
+ * @param {Object} canvasEl Canvas element to apply filter to
412
+ */
413
+ applyTo: function(canvasEl) {
414
+ var context = canvasEl.getContext('2d'),
415
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
416
+ data = imageData.data,
417
+ noise = this.noise, rand;
418
+
419
+ for (var i = 0, len = data.length; i < len; i += 4) {
420
+
421
+ rand = (0.5 - Math.random()) * noise;
422
+
423
+ data[i] += rand;
424
+ data[i + 1] += rand;
425
+ data[i + 2] += rand;
426
+ }
427
+
428
+ context.putImageData(imageData, 0, 0);
429
+ },
430
+
431
+ /**
432
+ * Returns json representation of filter
433
+ * @method toJSON
434
+ * @return {String} json representation of filter
435
+ */
436
+ toJSON: function() {
437
+ return {
438
+ type: this.type,
439
+ noise: this.noise
440
+ };
441
+ }
442
+ });
443
+
444
+ /**
445
+ * Returns filter instance from an object representation
446
+ * @static
447
+ * @method fabric.Image.filters.Noise.fromObject
448
+ * @return {fabric.Image.filters.Noise}
449
+ */
450
+ fabric.Image.filters.Noise.fromObject = function(object) {
451
+ return new fabric.Image.filters.Noise(object);
452
+ };
453
+
454
+ /**
455
+ * GradientTransparency filter class
456
+ * @class fabric.Image.filters.GradientTransparency
457
+ * @memberOf fabric.Image.filters
458
+ */
459
+ fabric.Image.filters.GradientTransparency = fabric.util.createClass( /** @scope fabric.Image.filters.GradientTransparency.prototype */ {
460
+
461
+ /**
462
+ * Filter type
463
+ * @param {String} type
464
+ */
465
+ type: "GradientTransparency",
466
+
467
+ /**
468
+ * Constructor
469
+ * @memberOf fabric.Image.filters.GradientTransparency
470
+ * @param {Object} [options] Options object
471
+ */
472
+ initialize: function(options) {
473
+ options || (options = { });
474
+ this.threshold = options.threshold || 100;
475
+ },
476
+
477
+ /**
478
+ * Applies filter to canvas element
479
+ * @method applyTo
480
+ * @param {Object} canvasEl Canvas element to apply filter to
481
+ */
482
+ applyTo: function(canvasEl) {
483
+ var context = canvasEl.getContext('2d'),
484
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
485
+ data = imageData.data,
486
+ threshold = this.threshold,
487
+ total = data.length;
488
+
489
+ for (var i = 0, len = data.length; i < len; i += 4) {
490
+ data[i + 3] = threshold + 255 * (total - i) / total;
491
+ }
492
+
493
+ context.putImageData(imageData, 0, 0);
494
+ },
495
+
496
+ /**
497
+ * Returns json representation of filter
498
+ * @method toJSON
499
+ * @return {String} json representation of filter
500
+ */
501
+ toJSON: function() {
502
+ return {
503
+ type: this.type,
504
+ threshold: this.threshold
505
+ };
506
+ }
507
+ });
508
+
509
+ /**
510
+ * Returns filter instance from an object representation
511
+ * @static
512
+ * @method fabric.Image.filters.GradientTransparency.fromObject
513
+ * @return {fabric.Image.filters.GradientTransparency}
514
+ */
515
+ fabric.Image.filters.GradientTransparency.fromObject = function(object) {
516
+ return new fabric.Image.filters.GradientTransparency(object);
517
+ };
518
+
519
+ /**
520
+ * Tint filter class
521
+ * @class fabric.Image.filters.Tint
522
+ * @memberOf fabric.Image.filters
523
+ */
524
+ fabric.Image.filters.Tint = fabric.util.createClass( /** @scope fabric.Image.filters.Tint.prototype */ {
525
+
526
+ /**
527
+ * Filter type
528
+ * @param {String} type
529
+ */
530
+ type: "Tint",
531
+
532
+ /**
533
+ * Constructor
534
+ * @memberOf fabric.Image.filters.Tint.prototype
535
+ * @param {Object} [options] Options object
536
+ */
537
+ initialize: function(options) {
538
+ options || (options = { });
539
+ this.color = options.color || 0;
540
+ },
541
+
542
+ /**
543
+ * Applies filter to canvas element
544
+ * @method applyTo
545
+ * @param {Object} canvasEl Canvas element to apply filter to
546
+ */
547
+ applyTo: function(canvasEl) {
548
+
549
+ var context = canvasEl.getContext('2d'),
550
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
551
+ data = imageData.data,
552
+ iLen = data.length, i, a;
553
+
554
+ var rgb = parseInt(this.color, 10).toString(16);
555
+
556
+ var cr = parseInt('0x' + rgb.substr(0, 2), 16);
557
+ var cg = parseInt('0x' + rgb.substr(2, 2), 16);
558
+ var cb = parseInt('0x' + rgb.substr(4, 2), 16);
559
+
560
+ for (i = 0; i < iLen; i+=4) {
561
+
562
+ a = data[i+3];
563
+
564
+ if (a > 0){
565
+ data[i] = cr;
566
+ data[i+1] = cg;
567
+ data[i+2] = cb;
568
+ }
569
+ }
570
+
571
+ context.putImageData(imageData, 0, 0);
572
+ },
573
+
574
+ /**
575
+ * Returns json representation of filter
576
+ * @method toJSON
577
+ * @return {String} json representation of filter
578
+ */
579
+ toJSON: function() {
580
+ return {
581
+ type: this.type,
582
+ color: this.color
583
+ };
584
+ }
585
+ });
586
+
587
+ /**
588
+ * Returns filter instance from an object representation
589
+ * @static
590
+ * @method fabric.Image.filters.Tint.fromObject
591
+ * @return {fabric.Image.filters.Tint}
592
+ */
593
+ fabric.Image.filters.Tint.fromObject = function(object) {
594
+ return new fabric.Image.filters.Tint(object);
595
+ };
596
+
597
+ /**
598
+ * Adapted from <a href="http://www.html5rocks.com/en/tutorials/canvas/imagefilters/">html5rocks article</a>
599
+ * @class fabric.Image.filters.Convolute
600
+ * @memberOf fabric.Image.filters
601
+ */
602
+ fabric.Image.filters.Convolute = fabric.util.createClass(/** @scope fabric.Image.filters.Convolute.prototype */ {
603
+
604
+ /**
605
+ * Filter type
606
+ * @param {String} type
607
+ */
608
+ type: 'Convolute',
609
+
610
+ /**
611
+ * Constructor
612
+ * @memberOf fabric.Image.filters.Convolute.prototype
613
+ * @param {Object} [options] Options object
614
+ */
615
+ initialize: function(options) {
616
+ options || (options = { });
617
+
618
+ this.opaque = options.opaque;
619
+ this.matrix = options.matrix || [ 0, 0, 0,
620
+ 0, 1, 0,
621
+ 0, 0, 0 ];
622
+
623
+ var canvasEl = fabric.util.createCanvasElement();
624
+ this.tmpCtx = canvasEl.getContext('2d');
625
+ },
626
+
627
+ /**
628
+ * @private
629
+ * @method _createImageData
630
+ */
631
+ _createImageData: function(w, h) {
632
+ return this.tmpCtx.createImageData(w, h);
633
+ },
634
+
635
+ /**
636
+ * Applies filter to canvas element
637
+ * @method applyTo
638
+ * @param {Object} canvasEl Canvas element to apply filter to
639
+ */
640
+ applyTo: function(canvasEl) {
641
+
642
+ var weights = this.matrix;
643
+ var context = canvasEl.getContext('2d');
644
+ var pixels = context.getImageData(0, 0, canvasEl.width, canvasEl.height);
645
+
646
+ var side = Math.round(Math.sqrt(weights.length));
647
+ var halfSide = Math.floor(side/2);
648
+ var src = pixels.data;
649
+ var sw = pixels.width;
650
+ var sh = pixels.height;
651
+
652
+ // pad output by the convolution matrix
653
+ var w = sw;
654
+ var h = sh;
655
+ var output = this._createImageData(w, h);
656
+
657
+ var dst = output.data;
658
+
659
+ // go through the destination image pixels
660
+ var alphaFac = this.opaque ? 1 : 0;
661
+ for (var y=0; y<h; y++) {
662
+ for (var x=0; x<w; x++) {
663
+ var sy = y;
664
+ var sx = x;
665
+ var dstOff = (y*w+x)*4;
666
+ // calculate the weighed sum of the source image pixels that
667
+ // fall under the convolution matrix
668
+ var r=0, g=0, b=0, a=0;
669
+ for (var cy=0; cy<side; cy++) {
670
+ for (var cx=0; cx<side; cx++) {
671
+ var scy = sy + cy - halfSide;
672
+ var scx = sx + cx - halfSide;
673
+ if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
674
+ var srcOff = (scy*sw+scx)*4;
675
+ var wt = weights[cy*side+cx];
676
+ r += src[srcOff] * wt;
677
+ g += src[srcOff+1] * wt;
678
+ b += src[srcOff+2] * wt;
679
+ a += src[srcOff+3] * wt;
680
+ }
681
+ }
682
+ }
683
+ dst[dstOff] = r;
684
+ dst[dstOff+1] = g;
685
+ dst[dstOff+2] = b;
686
+ dst[dstOff+3] = a + alphaFac*(255-a);
687
+ }
688
+ }
689
+
690
+ context.putImageData(output, 0, 0);
691
+ },
692
+
693
+ /**
694
+ * Returns json representation of filter
695
+ * @method toJSON
696
+ * @return {String} json representation of filter
697
+ */
698
+ toJSON: function() {
699
+ return {
700
+ type: this.type,
701
+ matrix: this.matrix
702
+ };
703
+ }
704
+ });
705
+
706
+ /**
707
+ * Returns filter instance from an object representation
708
+ * @static
709
+ * @method fabric.Image.filters.Convolute.fromObject
710
+ * @return {fabric.Image.filters.Convolute}
711
+ */
712
+ fabric.Image.filters.Convolute.fromObject = function(object) {
713
+ return new fabric.Image.filters.Convolute(object);
714
+ };
715
+
716
+ /**
717
+ * Pixelate filter class
718
+ * @class fabric.Image.filters.Pixelate
719
+ * @memberOf fabric.Image.filters
720
+ */
721
+ fabric.Image.filters.Pixelate = fabric.util.createClass(/** @scope fabric.Image.filters.Pixelate.prototype */ {
722
+
723
+ /**
724
+ * Filter type
725
+ * @param {String} type
726
+ */
727
+ type: 'Pixelate',
728
+
729
+ /**
730
+ * Constructor
731
+ * @memberOf fabric.Image.filters.Pixelate.prototype
732
+ * @param {Object} [options] Options object
733
+ */
734
+ initialize: function(options) {
735
+ options || (options = { });
736
+ this.blocksize = options.blocksize || 4;
737
+ },
738
+
739
+ /**
740
+ * Applies filter to canvas element
741
+ * @method applyTo
742
+ * @param {Object} canvasEl Canvas element to apply filter to
743
+ */
744
+ applyTo: function(canvasEl) {
745
+
746
+ var context = canvasEl.getContext('2d'),
747
+ imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
748
+ data = imageData.data,
749
+ iLen = imageData.width,
750
+ jLen = imageData.height,
751
+ index, i, j, r, g, b, a;
752
+
753
+ for (i = 0; i < iLen; i += this.blocksize) {
754
+ for (j = 0; j < jLen; j += this.blocksize) {
755
+
756
+ index = (i * 4) * jLen + (j * 4);
757
+
758
+ r = data[index];
759
+ g = data[index+1];
760
+ b = data[index+2];
761
+ a = data[index+3];
762
+
763
+ /*
764
+ blocksize: 4
765
+
766
+ [1,x,x,x,1]
767
+ [x,x,x,x,1]
768
+ [x,x,x,x,1]
769
+ [x,x,x,x,1]
770
+ [1,1,1,1,1]
771
+ */
772
+
773
+ for (var _i = i, _ilen = i + this.blocksize; _i < _ilen; _i++) {
774
+ for (var _j = j, _jlen = j + this.blocksize; _j < _jlen; _j++) {
775
+ index = (_i * 4) * jLen + (_j * 4);
776
+ data[index] = r;
777
+ data[index + 1] = g;
778
+ data[index + 2] = b;
779
+ data[index + 3] = a;
780
+ }
781
+ }
782
+ }
783
+ }
784
+
785
+ context.putImageData(imageData, 0, 0);
786
+ },
787
+
788
+ /**
789
+ * Returns json representation of filter
790
+ * @method toJSON
791
+ * @return {String} json representation of filter
792
+ */
793
+ toJSON: function() {
794
+ return {
795
+ type: this.type,
796
+ blocksize: this.blocksize
797
+ };
798
+ }
799
+ });
800
+
801
+ /**
802
+ * Returns filter instance from an object representation
803
+ * @static
804
+ * @method fabric.Image.filters.Pixelate.fromObject
805
+ * @return {fabric.Image.filters.Pixelate}
806
+ */
807
+ fabric.Image.filters.Pixelate.fromObject = function(object) {
808
+ return new fabric.Image.filters.Pixelate(object);
809
+ };