fabric-rails 1.0.12.1 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/README.md +1 -1
  3. data/lib/fabric/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/cufon.js +1226 -0
  5. data/vendor/assets/javascripts/event.js +20 -20
  6. data/vendor/assets/javascripts/excanvas.js +1464 -0
  7. data/vendor/assets/javascripts/fabric.js +56 -33
  8. data/vendor/assets/javascripts/fabric/HEADER.js +2 -4
  9. data/vendor/assets/javascripts/fabric/brushes/base_brush.class.js +96 -0
  10. data/vendor/assets/javascripts/fabric/brushes/circle_brush.class.js +99 -0
  11. data/vendor/assets/javascripts/fabric/brushes/pattern_brush.class.js +55 -0
  12. data/vendor/assets/javascripts/fabric/{freedrawing.class.js → brushes/pencil_brush.class.js} +73 -65
  13. data/vendor/assets/javascripts/fabric/brushes/spray_brush.class.js +157 -0
  14. data/vendor/assets/javascripts/fabric/canvas.class.js +154 -135
  15. data/vendor/assets/javascripts/fabric/color.class.js +195 -29
  16. data/vendor/assets/javascripts/fabric/filters/brightness_filter.class.js +70 -0
  17. data/vendor/assets/javascripts/fabric/filters/convolute_filter.class.js +122 -0
  18. data/vendor/assets/javascripts/fabric/filters/gradienttransparency_filter.class.js +69 -0
  19. data/vendor/assets/javascripts/fabric/filters/grayscale_filter.class.js +61 -0
  20. data/vendor/assets/javascripts/fabric/filters/invert_filter.class.js +57 -0
  21. data/vendor/assets/javascripts/fabric/filters/noise_filter.class.js +73 -0
  22. data/vendor/assets/javascripts/fabric/filters/pixelate_filter.class.js +98 -0
  23. data/vendor/assets/javascripts/fabric/filters/removewhite_filter.class.js +86 -0
  24. data/vendor/assets/javascripts/fabric/filters/sepia2_filter.class.js +61 -0
  25. data/vendor/assets/javascripts/fabric/filters/sepia_filter.class.js +58 -0
  26. data/vendor/assets/javascripts/fabric/filters/tint_filter.class.js +80 -0
  27. data/vendor/assets/javascripts/fabric/gradient.class.js +232 -80
  28. data/vendor/assets/javascripts/fabric/intersection.class.js +10 -28
  29. data/vendor/assets/javascripts/fabric/log.js +0 -2
  30. data/vendor/assets/javascripts/fabric/{canvas_animation.mixin.js → mixins/canvas_animation.mixin.js} +3 -6
  31. data/vendor/assets/javascripts/fabric/mixins/canvas_dataurl_exporter.mixin.js +137 -0
  32. data/vendor/assets/javascripts/fabric/{canvas_events.mixin.js → mixins/canvas_events.mixin.js} +97 -144
  33. data/vendor/assets/javascripts/fabric/{canvas_gestures.mixin.js → mixins/canvas_gestures.mixin.js} +4 -8
  34. data/vendor/assets/javascripts/fabric/{canvas_serialization.mixin.js → mixins/canvas_serialization.mixin.js} +19 -14
  35. data/vendor/assets/javascripts/fabric/mixins/collection.mixin.js +137 -0
  36. data/vendor/assets/javascripts/fabric/{object_geometry.mixin.js → mixins/object_geometry.mixin.js} +130 -47
  37. data/vendor/assets/javascripts/fabric/{object_interactivity.mixin.js → mixins/object_interactivity.mixin.js} +21 -102
  38. data/vendor/assets/javascripts/fabric/{object_origin.mixin.js → mixins/object_origin.mixin.js} +36 -26
  39. data/vendor/assets/javascripts/fabric/{object_straightening.mixin.js → mixins/object_straightening.mixin.js} +4 -9
  40. data/vendor/assets/javascripts/fabric/{observable.mixin.js → mixins/observable.mixin.js} +27 -35
  41. data/vendor/assets/javascripts/fabric/mixins/stateful.mixin.js +45 -0
  42. data/vendor/assets/javascripts/fabric/node.js +62 -26
  43. data/vendor/assets/javascripts/fabric/parser.js +181 -58
  44. data/vendor/assets/javascripts/fabric/pattern.class.js +43 -14
  45. data/vendor/assets/javascripts/fabric/point.class.js +4 -43
  46. data/vendor/assets/javascripts/fabric/shadow.class.js +19 -19
  47. data/vendor/assets/javascripts/fabric/{circle.class.js → shapes/circle.class.js} +32 -29
  48. data/vendor/assets/javascripts/fabric/{ellipse.class.js → shapes/ellipse.class.js} +45 -27
  49. data/vendor/assets/javascripts/fabric/{group.class.js → shapes/group.class.js} +67 -169
  50. data/vendor/assets/javascripts/fabric/{image.class.js → shapes/image.class.js} +134 -72
  51. data/vendor/assets/javascripts/fabric/{line.class.js → shapes/line.class.js} +67 -36
  52. data/vendor/assets/javascripts/fabric/{object.class.js → shapes/object.class.js} +394 -252
  53. data/vendor/assets/javascripts/fabric/{path.class.js → shapes/path.class.js} +89 -174
  54. data/vendor/assets/javascripts/fabric/{path_group.class.js → shapes/path_group.class.js} +12 -18
  55. data/vendor/assets/javascripts/fabric/{polygon.class.js → shapes/polygon.class.js} +64 -38
  56. data/vendor/assets/javascripts/fabric/{polyline.class.js → shapes/polyline.class.js} +64 -39
  57. data/vendor/assets/javascripts/fabric/{rect.class.js → shapes/rect.class.js} +78 -112
  58. data/vendor/assets/javascripts/fabric/{text.class.js → shapes/text.class.js} +264 -270
  59. data/vendor/assets/javascripts/fabric/shapes/text.cufon.js +79 -0
  60. data/vendor/assets/javascripts/fabric/{triangle.class.js → shapes/triangle.class.js} +46 -26
  61. data/vendor/assets/javascripts/fabric/static_canvas.class.js +134 -358
  62. data/vendor/assets/javascripts/fabric/util/anim_ease.js +2 -31
  63. data/vendor/assets/javascripts/fabric/util/dom_event.js +21 -7
  64. data/vendor/assets/javascripts/fabric/util/dom_misc.js +49 -39
  65. data/vendor/assets/javascripts/fabric/util/dom_request.js +1 -2
  66. data/vendor/assets/javascripts/fabric/util/dom_style.js +1 -2
  67. data/vendor/assets/javascripts/fabric/util/lang_array.js +19 -13
  68. data/vendor/assets/javascripts/fabric/util/lang_class.js +1 -2
  69. data/vendor/assets/javascripts/fabric/util/lang_function.js +3 -1
  70. data/vendor/assets/javascripts/fabric/util/lang_object.js +5 -5
  71. data/vendor/assets/javascripts/fabric/util/lang_string.js +7 -5
  72. data/vendor/assets/javascripts/fabric/util/misc.js +207 -42
  73. metadata +47 -29
  74. data/vendor/assets/javascripts/fabric/image_filters.js +0 -809
  75. data/vendor/assets/javascripts/fabric/scout.js +0 -45
  76. data/vendor/assets/javascripts/fabric/stateful.js +0 -88
@@ -26,7 +26,6 @@
26
26
 
27
27
  /**
28
28
  * Cross-browser abstraction for sending XMLHttpRequest
29
- * @method request
30
29
  * @memberOf fabric.util
31
30
  * @param {String} url URL to send XMLHttpRequest to
32
31
  * @param {Object} [options] Options object
@@ -69,4 +68,4 @@
69
68
  }
70
69
 
71
70
  fabric.util.request = request;
72
- })();
71
+ })();
@@ -2,7 +2,6 @@
2
2
 
3
3
  /**
4
4
  * Cross-browser wrapper for setting element's style
5
- * @method setStyle
6
5
  * @memberOf fabric.util
7
6
  * @param {HTMLElement} element
8
7
  * @param {Object} styles
@@ -68,4 +67,4 @@
68
67
 
69
68
  fabric.util.setStyle = setStyle;
70
69
 
71
- })();
70
+ })();
@@ -2,12 +2,14 @@
2
2
 
3
3
  var slice = Array.prototype.slice;
4
4
 
5
+ /* _ES5_COMPAT_START_ */
6
+
5
7
  if (!Array.prototype.indexOf) {
6
8
  /**
7
9
  * Finds index of an element in an array
8
- * @method indexOf
9
10
  * @param {Any} searchElement
10
11
  * @param {Number} [fromIndex]
12
+ * @return {Number}
11
13
  */
12
14
  Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
13
15
  if (this === void 0 || this === null) {
@@ -23,7 +25,7 @@
23
25
  if (n !== n) { // shortcut for verifying if it's NaN
24
26
  n = 0;
25
27
  }
26
- else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
28
+ else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {
27
29
  n = (n > 0 || -1) * Math.floor(Math.abs(n));
28
30
  }
29
31
  }
@@ -43,9 +45,9 @@
43
45
  if (!Array.prototype.forEach) {
44
46
  /**
45
47
  * Iterates an array, invoking callback for each element
46
- * @method forEach
47
48
  * @param {Function} fn Callback to invoke for each element
48
49
  * @param {Object} [context] Context to invoke callback in
50
+ * @return {Array}
49
51
  */
50
52
  Array.prototype.forEach = function(fn, context) {
51
53
  for (var i = 0, len = this.length >>> 0; i < len; i++) {
@@ -59,9 +61,9 @@
59
61
  if (!Array.prototype.map) {
60
62
  /**
61
63
  * Returns a result of iterating over an array, invoking callback for each element
62
- * @method map
63
64
  * @param {Function} fn Callback to invoke for each element
64
65
  * @param {Object} [context] Context to invoke callback in
66
+ * @return {Array}
65
67
  */
66
68
  Array.prototype.map = function(fn, context) {
67
69
  var result = [ ];
@@ -77,9 +79,9 @@
77
79
  if (!Array.prototype.every) {
78
80
  /**
79
81
  * Returns true if a callback returns truthy value for all elements in an array
80
- * @method every
81
82
  * @param {Function} fn Callback to invoke for each element
82
83
  * @param {Object} [context] Context to invoke callback in
84
+ * @return {Boolean}
83
85
  */
84
86
  Array.prototype.every = function(fn, context) {
85
87
  for (var i = 0, len = this.length >>> 0; i < len; i++) {
@@ -94,9 +96,9 @@
94
96
  if (!Array.prototype.some) {
95
97
  /**
96
98
  * Returns true if a callback returns truthy value for at least one element in an array
97
- * @method every
98
99
  * @param {Function} fn Callback to invoke for each element
99
100
  * @param {Object} [context] Context to invoke callback in
101
+ * @return {Boolean}
100
102
  */
101
103
  Array.prototype.some = function(fn, context) {
102
104
  for (var i = 0, len = this.length >>> 0; i < len; i++) {
@@ -111,9 +113,9 @@
111
113
  if (!Array.prototype.filter) {
112
114
  /**
113
115
  * Returns the result of iterating over elements in an array
114
- * @method filter
115
116
  * @param {Function} fn Callback to invoke for each element
116
117
  * @param {Object} [context] Context to invoke callback in
118
+ * @return {Array}
117
119
  */
118
120
  Array.prototype.filter = function(fn, context) {
119
121
  var result = [ ], val;
@@ -132,9 +134,9 @@
132
134
  if (!Array.prototype.reduce) {
133
135
  /**
134
136
  * Returns "folded" (reduced) result of iterating over elements in an array
135
- * @method filter
136
137
  * @param {Function} fn Callback to invoke for each element
137
138
  * @param {Object} [context] Context to invoke callback in
139
+ * @return {Any}
138
140
  */
139
141
  Array.prototype.reduce = function(fn /*, initial*/) {
140
142
  var len = this.length >>> 0,
@@ -166,12 +168,14 @@
166
168
  };
167
169
  }
168
170
 
171
+ /* _ES5_COMPAT_END_ */
172
+
169
173
  /**
170
174
  * Invokes method on all items in a given array
171
- * @method invoke
172
175
  * @memberOf fabric.util.array
173
176
  * @param {Array} array Array to iterate over
174
177
  * @param {String} method Name of a method to invoke
178
+ * @return {Array}
175
179
  */
176
180
  function invoke(array, method) {
177
181
  var args = slice.call(arguments, 2), result = [ ];
@@ -183,10 +187,10 @@
183
187
 
184
188
  /**
185
189
  * Finds maximum value in array (not necessarily "first" one)
186
- * @method max
187
190
  * @memberOf fabric.util.array
188
191
  * @param {Array} array Array to iterate over
189
192
  * @param {String} byProperty
193
+ * @return {Any}
190
194
  */
191
195
  function max(array, byProperty) {
192
196
  if (!array || array.length === 0) return undefined;
@@ -212,10 +216,10 @@
212
216
 
213
217
  /**
214
218
  * Finds minimum value in array (not necessarily "first" one)
215
- * @method min
216
219
  * @memberOf fabric.util.array
217
220
  * @param {Array} array Array to iterate over
218
221
  * @param {String} byProperty
222
+ * @return {Any}
219
223
  */
220
224
  function min(array, byProperty) {
221
225
  if (!array || array.length === 0) return undefined;
@@ -240,11 +244,13 @@
240
244
  return result;
241
245
  }
242
246
 
243
- /** @namespace */
247
+ /**
248
+ * @namespace fabric.util.array
249
+ */
244
250
  fabric.util.array = {
245
251
  invoke: invoke,
246
252
  min: min,
247
253
  max: max
248
254
  };
249
255
 
250
- })();
256
+ })();
@@ -57,7 +57,6 @@
57
57
 
58
58
  /**
59
59
  * Helper for creation of "classes". Note that pr
60
- * @method createClass
61
60
  * @param parent optional "Class" to inherit from
62
61
  * @param properties Properties shared by all instances of this class
63
62
  * (be careful modifying objects defined here as this would affect all instances)
@@ -94,4 +93,4 @@
94
93
  }
95
94
 
96
95
  fabric.util.createClass = createClass;
97
- })();
96
+ })();
@@ -1,3 +1,4 @@
1
+ /* _ES5_COMPAT_START_ */
1
2
  (function() {
2
3
 
3
4
  var slice = Array.prototype.slice,
@@ -32,4 +33,5 @@
32
33
  };
33
34
  }
34
35
 
35
- })();
36
+ })();
37
+ /* _ES5_COMPAT_END_ */
@@ -1,11 +1,11 @@
1
1
  (function(){
2
-
2
+
3
3
  /**
4
4
  * Copies all enumerable properties of one object to another
5
5
  * @memberOf fabric.util.object
6
- * @method extend
7
6
  * @param {Object} destination Where to copy to
8
7
  * @param {Object} source Where to copy from
8
+ * @return {Object}
9
9
  */
10
10
  function extend(destination, source) {
11
11
  // JScript DontEnum bug is not taken care of
@@ -17,9 +17,9 @@
17
17
 
18
18
  /**
19
19
  * Creates an empty object and copies all enumerable properties of another object to it
20
- * @method clone
21
20
  * @memberOf fabric.util.object
22
21
  * @param {Object} object Object to clone
22
+ * @return {Object}
23
23
  */
24
24
  function clone(object) {
25
25
  return extend({ }, object);
@@ -30,5 +30,5 @@
30
30
  extend: extend,
31
31
  clone: clone
32
32
  };
33
-
34
- })();
33
+
34
+ })();
@@ -1,9 +1,10 @@
1
1
  (function() {
2
2
 
3
+ /* _ES5_COMPAT_START_ */
3
4
  if (!String.prototype.trim) {
4
5
  /**
5
6
  * Trims a string (removing whitespace from the beginning and the end)
6
- * @method trim
7
+ * @function external:String#trim
7
8
  * @see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim">String#trim on MDN</a>
8
9
  */
9
10
  String.prototype.trim = function () {
@@ -11,11 +12,11 @@ if (!String.prototype.trim) {
11
12
  return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '');
12
13
  };
13
14
  }
15
+ /* _ES5_COMPAT_END_ */
14
16
 
15
17
  /**
16
18
  * Camelizes a string
17
19
  * @memberOf fabric.util.string
18
- * @method camelize
19
20
  * @param {String} string String to camelize
20
21
  * @return {String} Camelized version of a string
21
22
  */
@@ -28,7 +29,6 @@ function camelize(string) {
28
29
  /**
29
30
  * Capitalizes a string
30
31
  * @memberOf fabric.util.string
31
- * @method capitalize
32
32
  * @param {String} string String to capitalize
33
33
  * @return {String} Capitalized version of a string
34
34
  */
@@ -39,7 +39,6 @@ function capitalize(string) {
39
39
  /**
40
40
  * Escapes XML in a string
41
41
  * @memberOf fabric.util.string
42
- * @method escapeXml
43
42
  * @param {String} string String to escape
44
43
  * @return {String} Escaped version of a string
45
44
  */
@@ -51,7 +50,10 @@ function escapeXml(string) {
51
50
  .replace(/>/g, '&gt;');
52
51
  }
53
52
 
54
- /** @namespace */
53
+ /**
54
+ * String utilities
55
+ * @namespace fabric.util.string
56
+ */
55
57
  fabric.util.string = {
56
58
  camelize: camelize,
57
59
  capitalize: capitalize,
@@ -4,7 +4,7 @@
4
4
  atan2 = Math.atan2;
5
5
 
6
6
  /**
7
- * @namespace
7
+ * @namespace fabric.util
8
8
  */
9
9
  fabric.util = { };
10
10
 
@@ -13,7 +13,6 @@
13
13
  * Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`
14
14
  * @static
15
15
  * @memberOf fabric.util
16
- * @method removeFromArray
17
16
  * @param {Array} array
18
17
  * @param {Any} value
19
18
  * @return {Array} original array
@@ -29,7 +28,6 @@
29
28
  /**
30
29
  * Returns random number between 2 specified ones.
31
30
  * @static
32
- * @method getRandomInt
33
31
  * @memberOf fabric.util
34
32
  * @param {Number} min lower limit
35
33
  * @param {Number} max upper limit
@@ -44,7 +42,6 @@
44
42
  /**
45
43
  * Transforms degrees to radians.
46
44
  * @static
47
- * @method degreesToRadians
48
45
  * @memberOf fabric.util
49
46
  * @param {Number} degrees value in degrees
50
47
  * @return {Number} value in radians
@@ -56,7 +53,6 @@
56
53
  /**
57
54
  * Transforms radians to degrees.
58
55
  * @static
59
- * @method radiansToDegrees
60
56
  * @memberOf fabric.util
61
57
  * @param {Number} radians value in radians
62
58
  * @return {Number} value in degrees
@@ -68,7 +64,6 @@
68
64
  /**
69
65
  * Rotates `point` around `origin` with `radians`
70
66
  * @static
71
- * @method rotatePoint
72
67
  * @memberOf fabric.util
73
68
  * @param {fabric.Point} The point to rotate
74
69
  * @param {fabric.Point} The origin of the rotation
@@ -90,7 +85,6 @@
90
85
  /**
91
86
  * A wrapper around Number#toFixed, which contrary to native method returns number, not string.
92
87
  * @static
93
- * @method toFixed
94
88
  * @memberOf fabric.util
95
89
  * @param {Number | String} number number to operate on
96
90
  * @param {Number} fractionDigits number of fraction digits to "leave"
@@ -103,7 +97,6 @@
103
97
  /**
104
98
  * Function which always returns `false`.
105
99
  * @static
106
- * @method falseFunction
107
100
  * @memberOf fabric.util
108
101
  * @return {Boolean}
109
102
  */
@@ -113,7 +106,6 @@
113
106
 
114
107
  /**
115
108
  * Changes value from one to another within certain period of time, invoking callbacks as value is being changed.
116
- * @method animate
117
109
  * @memberOf fabric.util
118
110
  * @param {Object} [options] Animation options
119
111
  * @param {Function} [options.onChange] Callback; invoked on every value change
@@ -162,7 +154,6 @@
162
154
  };
163
155
  /**
164
156
  * requestAnimationFrame polyfill based on http://paulirish.com/2011/requestanimationframe-for-smart-animating/
165
- * @method requestAnimFrame
166
157
  * @memberOf fabric.util
167
158
  * @param {Function} callback Callback to invoke
168
159
  * @param {DOMElement} element optional Element to associate with animation
@@ -171,9 +162,18 @@
171
162
  return _requestAnimFrame.apply(fabric.window, arguments);
172
163
  };
173
164
 
165
+ /**
166
+ * Returns klass "Class" object of given fabric.Object type
167
+ * @memberOf fabric.util
168
+ * @param {String} type Type of object (eg. 'circle')
169
+ * @return {Object} klass "Class"
170
+ */
171
+ function getKlass(type) {
172
+ return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(type))];
173
+ }
174
+
174
175
  /**
175
176
  * Loads image element from given url and passes it to a callback
176
- * @method loadImage
177
177
  * @memberOf fabric.util
178
178
  * @param {String} url URL representing an image
179
179
  * @param {Function} callback Callback; invoked with loaded image
@@ -181,7 +181,7 @@
181
181
  */
182
182
  function loadImage(url, callback, context) {
183
183
  if (url) {
184
- var img = new Image();
184
+ var img = fabric.util.createImage();
185
185
  /** @ignore */
186
186
  img.onload = function () {
187
187
  callback && callback.call(context, img);
@@ -198,16 +198,11 @@
198
198
  * Creates corresponding fabric instances from their object representations
199
199
  * @static
200
200
  * @memberOf fabric.util
201
- * @method enlivenObjects
202
201
  * @param {Array} objects Objects to enliven
203
202
  * @param {Function} callback Callback to invoke when all objects are created
204
203
  */
205
204
  function enlivenObjects(objects, callback) {
206
205
 
207
- function getKlass(type) {
208
- return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(type))];
209
- }
210
-
211
206
  function onLoaded() {
212
207
  if (++numLoadedObjects === numTotalObjects) {
213
208
  if (callback) {
@@ -224,7 +219,7 @@
224
219
  if (!o.type) {
225
220
  return;
226
221
  }
227
- var klass = getKlass(o.type);
222
+ var klass = fabric.util.getKlass(o.type);
228
223
  if (klass.async) {
229
224
  klass.fromObject(o, function (o, error) {
230
225
  if (!error) {
@@ -244,7 +239,6 @@
244
239
  * Groups SVG elements (usually those retrieved from SVG document)
245
240
  * @static
246
241
  * @memberOf fabric.util
247
- * @method groupSVGElements
248
242
  * @param {Array} elements SVG elements to group
249
243
  * @param {Object} [options] Options object
250
244
  * @return {fabric.Object|fabric.PathGroup}
@@ -253,23 +247,7 @@
253
247
  var object;
254
248
 
255
249
  if (elements.length > 1) {
256
- var hasText = elements.some(function(el) { return el.type === 'text'; });
257
-
258
- if (hasText) {
259
- object = new fabric.Group([ ], options);
260
- elements.reverse().forEach(function(obj) {
261
- if (obj.cx) {
262
- obj.left = obj.cx;
263
- }
264
- if (obj.cy) {
265
- obj.top = obj.cy;
266
- }
267
- object.addWithUpdate(obj);
268
- });
269
- }
270
- else {
271
- object = new fabric.PathGroup(elements, options);
272
- }
250
+ object = new fabric.PathGroup(elements, options);
273
251
  }
274
252
  else {
275
253
  object = elements[0];
@@ -285,7 +263,6 @@
285
263
  * Populates an object with properties of another object
286
264
  * @static
287
265
  * @memberOf fabric.util
288
- * @method populateWithProperties
289
266
  * @param {Object} source Source object
290
267
  * @param {Object} destination Destination object
291
268
  * @return {Array} properties Propertie names to include
@@ -293,7 +270,9 @@
293
270
  function populateWithProperties(source, destination, properties) {
294
271
  if (properties && Object.prototype.toString.call(properties) === '[object Array]') {
295
272
  for (var i = 0, len = properties.length; i < len; i++) {
296
- destination[properties[i]] = source[properties[i]];
273
+ if (properties[i] in source) {
274
+ destination[properties[i]] = source[properties[i]];
275
+ }
297
276
  }
298
277
  }
299
278
  }
@@ -304,7 +283,6 @@
304
283
  * This method is used to draw dashed line around selection area.
305
284
  * See <a href="http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas">dotted stroke in canvas</a>
306
285
  *
307
- * @method drawDashedLine
308
286
  * @param ctx {Canvas} context
309
287
  * @param x {Number} start x coordinate
310
288
  * @param y {Number} start y coordinate
@@ -343,7 +321,6 @@
343
321
  * Creates canvas element and initializes it via excanvas if necessary
344
322
  * @static
345
323
  * @memberOf fabric.util
346
- * @method createCanvasElement
347
324
  * @param {CanvasElement} [canvasEl] optional canvas element to initialize; when not given, element is created implicitly
348
325
  * @return {CanvasElement} initialized canvas element
349
326
  */
@@ -355,11 +332,22 @@
355
332
  return canvasEl;
356
333
  }
357
334
 
335
+ /**
336
+ * Creates image element (works on client and node)
337
+ * @static
338
+ * @memberOf fabric.util
339
+ * @return {Image} image element
340
+ */
341
+ function createImage() {
342
+ return fabric.isLikelyNode
343
+ ? new (require('canvas').Image)()
344
+ : fabric.document.createElement('img');
345
+ }
346
+
358
347
  /**
359
348
  * Creates accessors (getXXX, setXXX) for a "class", based on "stateProperties" array
360
349
  * @static
361
350
  * @memberOf fabric.util
362
- * @method createAccessors
363
351
  * @param {Object} klass "Class" to create accessors for
364
352
  */
365
353
  function createAccessors(klass) {
@@ -386,6 +374,177 @@
386
374
  }
387
375
  }
388
376
 
377
+ /**
378
+ * @static
379
+ * @memberOf fabric.util
380
+ * @param {fabric.Object} receiver Object implementing `clipTo` method
381
+ * @param {CanvasRenderingContext2D} ctx Context to clip
382
+ */
383
+ function clipContext(receiver, ctx) {
384
+ ctx.save();
385
+ ctx.beginPath();
386
+ receiver.clipTo(ctx);
387
+ ctx.clip();
388
+ }
389
+
390
+ /**
391
+ * Multiply matrix A by matrix B to nest transformations
392
+ * @static
393
+ * @memberOf fabric.util
394
+ * @param {Array} matrixA First transformMatrix
395
+ * @param {Array} matrixB Second transformMatrix
396
+ * @return {Array} The product of the two transform matrices
397
+ */
398
+ function multiplyTransformMatrices(matrixA, matrixB) {
399
+ // Matrix multiply matrixA * matrixB
400
+ var a = [
401
+ [matrixA[0], matrixA[2], matrixA[4]],
402
+ [matrixA[1], matrixA[3], matrixA[5]],
403
+ [0 , 0 , 1 ]
404
+ ];
405
+
406
+ var b = [
407
+ [matrixB[0], matrixB[2], matrixB[4]],
408
+ [matrixB[1], matrixB[3], matrixB[5]],
409
+ [0 , 0 , 1 ]
410
+ ];
411
+
412
+ var result = [];
413
+ for (var r=0; r<3; r++) {
414
+ result[r] = [];
415
+ for (var c=0; c<3; c++) {
416
+ var sum = 0;
417
+ for (var k=0; k<3; k++) {
418
+ sum += a[r][k]*b[k][c];
419
+ }
420
+
421
+ result[r][c] = sum;
422
+ }
423
+ }
424
+
425
+ return [
426
+ result[0][0],
427
+ result[1][0],
428
+ result[0][1],
429
+ result[1][1],
430
+ result[0][2],
431
+ result[1][2]
432
+ ];
433
+ }
434
+
435
+ function getFunctionBody(fn) {
436
+ return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1];
437
+ }
438
+
439
+ function drawArc(ctx, x, y, coords) {
440
+ var rx = coords[0];
441
+ var ry = coords[1];
442
+ var rot = coords[2];
443
+ var large = coords[3];
444
+ var sweep = coords[4];
445
+ var ex = coords[5];
446
+ var ey = coords[6];
447
+ var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y);
448
+ for (var i=0; i<segs.length; i++) {
449
+ var bez = segmentToBezier.apply(this, segs[i]);
450
+ ctx.bezierCurveTo.apply(ctx, bez);
451
+ }
452
+ }
453
+
454
+ var arcToSegmentsCache = { },
455
+ segmentToBezierCache = { },
456
+ _join = Array.prototype.join,
457
+ argsString;
458
+
459
+ // Generous contribution by Raph Levien, from libsvg-0.1.0.tar.gz
460
+ function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
461
+ argsString = _join.call(arguments);
462
+ if (arcToSegmentsCache[argsString]) {
463
+ return arcToSegmentsCache[argsString];
464
+ }
465
+
466
+ var th = rotateX * (Math.PI/180);
467
+ var sin_th = Math.sin(th);
468
+ var cos_th = Math.cos(th);
469
+ rx = Math.abs(rx);
470
+ ry = Math.abs(ry);
471
+ var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
472
+ var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
473
+ var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry);
474
+ if (pl > 1) {
475
+ pl = Math.sqrt(pl);
476
+ rx *= pl;
477
+ ry *= pl;
478
+ }
479
+
480
+ var a00 = cos_th / rx;
481
+ var a01 = sin_th / rx;
482
+ var a10 = (-sin_th) / ry;
483
+ var a11 = (cos_th) / ry;
484
+ var x0 = a00 * ox + a01 * oy;
485
+ var y0 = a10 * ox + a11 * oy;
486
+ var x1 = a00 * x + a01 * y;
487
+ var y1 = a10 * x + a11 * y;
488
+
489
+ var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0);
490
+ var sfactor_sq = 1 / d - 0.25;
491
+ if (sfactor_sq < 0) sfactor_sq = 0;
492
+ var sfactor = Math.sqrt(sfactor_sq);
493
+ if (sweep === large) sfactor = -sfactor;
494
+ var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0);
495
+ var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
496
+
497
+ var th0 = Math.atan2(y0-yc, x0-xc);
498
+ var th1 = Math.atan2(y1-yc, x1-xc);
499
+
500
+ var th_arc = th1-th0;
501
+ if (th_arc < 0 && sweep === 1){
502
+ th_arc += 2*Math.PI;
503
+ } else if (th_arc > 0 && sweep === 0) {
504
+ th_arc -= 2 * Math.PI;
505
+ }
506
+
507
+ var segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
508
+ var result = [];
509
+ for (var i=0; i<segments; i++) {
510
+ var th2 = th0 + i * th_arc / segments;
511
+ var th3 = th0 + (i+1) * th_arc / segments;
512
+ result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
513
+ }
514
+
515
+ arcToSegmentsCache[argsString] = result;
516
+ return result;
517
+ }
518
+
519
+ function segmentToBezier(cx, cy, th0, th1, rx, ry, sin_th, cos_th) {
520
+ argsString = _join.call(arguments);
521
+ if (segmentToBezierCache[argsString]) {
522
+ return segmentToBezierCache[argsString];
523
+ }
524
+
525
+ var a00 = cos_th * rx;
526
+ var a01 = -sin_th * ry;
527
+ var a10 = sin_th * rx;
528
+ var a11 = cos_th * ry;
529
+
530
+ var th_half = 0.5 * (th1 - th0);
531
+ var t = (8/3) * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half);
532
+ var x1 = cx + Math.cos(th0) - t * Math.sin(th0);
533
+ var y1 = cy + Math.sin(th0) + t * Math.cos(th0);
534
+ var x3 = cx + Math.cos(th1);
535
+ var y3 = cy + Math.sin(th1);
536
+ var x2 = x3 + t * Math.sin(th1);
537
+ var y2 = y3 - t * Math.cos(th1);
538
+
539
+ segmentToBezierCache[argsString] = [
540
+ a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
541
+ a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
542
+ a00 * x3 + a01 * y3, a10 * x3 + a11 * y3
543
+ ];
544
+
545
+ return segmentToBezierCache[argsString];
546
+ }
547
+
389
548
  fabric.util.removeFromArray = removeFromArray;
390
549
  fabric.util.degreesToRadians = degreesToRadians;
391
550
  fabric.util.radiansToDegrees = radiansToDegrees;
@@ -395,12 +554,18 @@
395
554
  fabric.util.falseFunction = falseFunction;
396
555
  fabric.util.animate = animate;
397
556
  fabric.util.requestAnimFrame = requestAnimFrame;
557
+ fabric.util.getKlass = getKlass;
398
558
  fabric.util.loadImage = loadImage;
399
559
  fabric.util.enlivenObjects = enlivenObjects;
400
560
  fabric.util.groupSVGElements = groupSVGElements;
401
561
  fabric.util.populateWithProperties = populateWithProperties;
402
562
  fabric.util.drawDashedLine = drawDashedLine;
403
563
  fabric.util.createCanvasElement = createCanvasElement;
564
+ fabric.util.createImage = createImage;
404
565
  fabric.util.createAccessors = createAccessors;
566
+ fabric.util.clipContext = clipContext;
567
+ fabric.util.multiplyTransformMatrices = multiplyTransformMatrices;
568
+ fabric.util.getFunctionBody = getFunctionBody;
569
+ fabric.util.drawArc = drawArc;
405
570
 
406
- })();
571
+ })();