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
@@ -13,32 +13,20 @@
13
13
 
14
14
  /**
15
15
  * Intersection class
16
- * @class Intersection
17
- * @memberOf fabric
16
+ * @class fabric.Intersection
17
+ * @constructor
18
18
  */
19
19
  function Intersection(status) {
20
- if (arguments.length > 0) {
21
- this.init(status);
22
- }
20
+ this.status = status;
21
+ this.points = [];
23
22
  }
24
23
 
25
24
  fabric.Intersection = Intersection;
26
25
 
27
- fabric.Intersection.prototype = /** @scope fabric.Intersection.prototype */ {
28
-
29
- /**
30
- * Constructor
31
- * @method init
32
- * @param {String} status
33
- */
34
- init: function (status) {
35
- this.status = status;
36
- this.points = [];
37
- },
26
+ fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ {
38
27
 
39
28
  /**
40
29
  * Appends a point to intersection
41
- * @method appendPoint
42
30
  * @param {fabric.Point} point
43
31
  */
44
32
  appendPoint: function (point) {
@@ -47,7 +35,6 @@
47
35
 
48
36
  /**
49
37
  * Appends points to intersection
50
- * @method appendPoints
51
38
  * @param {Array} points
52
39
  */
53
40
  appendPoints: function (points) {
@@ -58,7 +45,6 @@
58
45
  /**
59
46
  * Checks if one line intersects another
60
47
  * @static
61
- * @method intersectLineLine
62
48
  * @param {fabric.Point} a1
63
49
  * @param {fabric.Point} a2
64
50
  * @param {fabric.Point} b1
@@ -78,7 +64,7 @@
78
64
  result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));
79
65
  }
80
66
  else {
81
- result = new Intersection("No Intersection");
67
+ result = new Intersection();
82
68
  }
83
69
  }
84
70
  else {
@@ -94,7 +80,6 @@
94
80
 
95
81
  /**
96
82
  * Checks if line intersects polygon
97
- * @method intersectLinePolygon
98
83
  * @static
99
84
  * @param {fabric.Point} a1
100
85
  * @param {fabric.Point} a2
@@ -102,7 +87,7 @@
102
87
  * @return {fabric.Intersection}
103
88
  */
104
89
  fabric.Intersection.intersectLinePolygon = function(a1,a2,points){
105
- var result = new Intersection("No Intersection"),
90
+ var result = new Intersection(),
106
91
  length = points.length;
107
92
 
108
93
  for (var i = 0; i < length; i++) {
@@ -120,14 +105,13 @@
120
105
 
121
106
  /**
122
107
  * Checks if polygon intersects another polygon
123
- * @method intersectPolygonPolygon
124
108
  * @static
125
109
  * @param {Array} points1
126
110
  * @param {Array} points2
127
111
  * @return {fabric.Intersection}
128
112
  */
129
113
  fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {
130
- var result = new Intersection("No Intersection"),
114
+ var result = new Intersection(),
131
115
  length = points1.length;
132
116
 
133
117
  for (var i = 0; i < length; i++) {
@@ -145,8 +129,6 @@
145
129
 
146
130
  /**
147
131
  * Checks if polygon intersects rectangle
148
- * @method intersectPolygonRectangle
149
-
150
132
  * @static
151
133
  * @param {Array} points
152
134
  * @param {Number} r1
@@ -162,7 +144,7 @@
162
144
  inter2 = Intersection.intersectLinePolygon(topRight, max, points),
163
145
  inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),
164
146
  inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),
165
- result = new Intersection("No Intersection");
147
+ result = new Intersection();
166
148
 
167
149
  result.appendPoints(inter1.points);
168
150
  result.appendPoints(inter2.points);
@@ -175,4 +157,4 @@
175
157
  return result;
176
158
  };
177
159
 
178
- })(typeof exports !== 'undefined' ? exports : this);
160
+ })(typeof exports !== 'undefined' ? exports : this);
@@ -1,13 +1,11 @@
1
1
  /**
2
2
  * Wrapper around `console.log` (when available)
3
- * @method log
4
3
  * @param {Any} values Values to log
5
4
  */
6
5
  fabric.log = function() { };
7
6
 
8
7
  /**
9
8
  * Wrapper around `console.warn` (when available)
10
- * @method warn
11
9
  * @param {Any} Values to log as a warning
12
10
  */
13
11
  fabric.warn = function() { };
@@ -1,4 +1,4 @@
1
- fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @scope fabric.StaticCanvas.prototype */ {
1
+ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
2
2
 
3
3
  /**
4
4
  * Animation duration (in ms) for fx* methods
@@ -8,7 +8,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @scope fabric.Stati
8
8
 
9
9
  /**
10
10
  * Centers object horizontally with animation.
11
- * @method fxCenterObjectH
12
11
  * @param {fabric.Object} object Object to center
13
12
  * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
14
13
  * @return {fabric.Canvas} thisArg
@@ -42,7 +41,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @scope fabric.Stati
42
41
 
43
42
  /**
44
43
  * Centers object vertically with animation.
45
- * @method fxCenterObjectV
46
44
  * @param {fabric.Object} object Object to center
47
45
  * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
48
46
  * @return {fabric.Canvas} thisArg
@@ -76,7 +74,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @scope fabric.Stati
76
74
 
77
75
  /**
78
76
  * Same as `fabric.Canvas#remove` but animated
79
- * @method fxRemove
80
77
  * @param {fabric.Object} object Object to remove
81
78
  * @param {Function} callback Callback, invoked on effect completion
82
79
  * @return {fabric.Canvas} thisArg
@@ -95,7 +92,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @scope fabric.Stati
95
92
  endValue: 0,
96
93
  duration: this.FX_DURATION,
97
94
  onStart: function() {
98
- object.setActive(false);
95
+ object.set('active', false);
99
96
  },
100
97
  onChange: function(value) {
101
98
  object.set('opacity', value);
@@ -110,4 +107,4 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @scope fabric.Stati
110
107
 
111
108
  return this;
112
109
  }
113
- });
110
+ });
@@ -0,0 +1,137 @@
1
+ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
2
+
3
+ /**
4
+ * Exports canvas element to a dataurl image.
5
+ * @param {Object} options
6
+ *
7
+ * `format` the format of the output image. Either "jpeg" or "png".
8
+ * `quality` quality level (0..1)
9
+ * `multiplier` multiplier to scale by {Number}
10
+ *
11
+ * @return {String}
12
+ */
13
+ toDataURL: function (options) {
14
+ options || (options = { });
15
+
16
+ var format = options.format || 'png',
17
+ quality = options.quality || 1,
18
+ multiplier = options.multiplier || 1;
19
+
20
+ if (multiplier !== 1) {
21
+ return this.__toDataURLWithMultiplier(format, quality, multiplier);
22
+ }
23
+ else {
24
+ return this.__toDataURL(format, quality);
25
+ }
26
+ },
27
+
28
+ /**
29
+ * @private
30
+ */
31
+ __toDataURL: function(format, quality) {
32
+ this.renderAll(true);
33
+ var canvasEl = this.upperCanvasEl || this.lowerCanvasEl;
34
+ var data = (fabric.StaticCanvas.supports('toDataURLWithQuality'))
35
+ ? canvasEl.toDataURL('image/' + format, quality)
36
+ : canvasEl.toDataURL('image/' + format);
37
+
38
+ this.contextTop && this.clearContext(this.contextTop);
39
+ this.renderAll();
40
+ return data;
41
+ },
42
+
43
+ /**
44
+ * @private
45
+ */
46
+ __toDataURLWithMultiplier: function(format, quality, multiplier) {
47
+
48
+ var origWidth = this.getWidth(),
49
+ origHeight = this.getHeight(),
50
+ scaledWidth = origWidth * multiplier,
51
+ scaledHeight = origHeight * multiplier,
52
+ activeObject = this.getActiveObject(),
53
+ activeGroup = this.getActiveGroup(),
54
+
55
+ ctx = this.contextTop || this.contextContainer;
56
+
57
+ this.setWidth(scaledWidth).setHeight(scaledHeight);
58
+ ctx.scale(multiplier, multiplier);
59
+
60
+ if (activeGroup) {
61
+ // not removing group due to complications with restoring it with correct state afterwords
62
+ this._tempRemoveBordersControlsFromGroup(activeGroup);
63
+ }
64
+ else if (activeObject && this.deactivateAll) {
65
+ this.deactivateAll();
66
+ }
67
+
68
+ // restoring width, height for `renderAll` to draw
69
+ // background properly (while context is scaled)
70
+ this.width = origWidth;
71
+ this.height = origHeight;
72
+
73
+ this.renderAll(true);
74
+
75
+ var data = this.__toDataURL(format, quality);
76
+
77
+ ctx.scale(1 / multiplier, 1 / multiplier);
78
+ this.setWidth(origWidth).setHeight(origHeight);
79
+
80
+ if (activeGroup) {
81
+ this._restoreBordersControlsOnGroup(activeGroup);
82
+ }
83
+ else if (activeObject && this.setActiveObject) {
84
+ this.setActiveObject(activeObject);
85
+ }
86
+
87
+ this.contextTop && this.clearContext(this.contextTop);
88
+ this.renderAll();
89
+
90
+ return data;
91
+ },
92
+
93
+ /**
94
+ * Exports canvas element to a dataurl image (allowing to change image size via multiplier).
95
+ * @deprecated since 1.0.13
96
+ * @param {String} format (png|jpeg)
97
+ * @param {Number} multiplier
98
+ * @param {Number} quality (0..1)
99
+ * @return {String}
100
+ */
101
+ toDataURLWithMultiplier: function (format, multiplier, quality) {
102
+ return this.toDataURL({
103
+ format: format,
104
+ multiplier: multiplier,
105
+ quality: quality
106
+ });
107
+ },
108
+
109
+ /**
110
+ * @private
111
+ */
112
+ _tempRemoveBordersControlsFromGroup: function(group) {
113
+ group.origHasControls = group.hasControls;
114
+ group.origBorderColor = group.borderColor;
115
+
116
+ group.hasControls = true;
117
+ group.borderColor = 'rgba(0,0,0,0)';
118
+
119
+ group.forEachObject(function(o) {
120
+ o.origBorderColor = o.borderColor;
121
+ o.borderColor = 'rgba(0,0,0,0)';
122
+ });
123
+ },
124
+
125
+ /**
126
+ * @private
127
+ */
128
+ _restoreBordersControlsOnGroup: function(group) {
129
+ group.hideControls = group.origHideControls;
130
+ group.borderColor = group.origBorderColor;
131
+
132
+ group.forEachObject(function(o) {
133
+ o.borderColor = o.origBorderColor;
134
+ delete o.origBorderColor;
135
+ });
136
+ }
137
+ });
@@ -1,26 +1,34 @@
1
1
  (function(){
2
2
 
3
- var cursorMap = {
4
- 'tr': 'ne-resize',
5
- 'br': 'se-resize',
6
- 'bl': 'sw-resize',
7
- 'tl': 'nw-resize',
8
- 'ml': 'w-resize',
9
- 'mt': 'n-resize',
10
- 'mr': 'e-resize',
11
- 'mb': 's-resize'
3
+ var cursorMap = [
4
+ 'n-resize',
5
+ 'ne-resize',
6
+ 'e-resize',
7
+ 'se-resize',
8
+ 's-resize',
9
+ 'sw-resize',
10
+ 'w-resize',
11
+ 'nw-resize'
12
+ ],
13
+ cursorOffset = {
14
+ 'mt': 0, // n
15
+ 'tr': 1, // ne
16
+ 'mr': 2, // e
17
+ 'br': 3, // se
18
+ 'mb': 4, // s
19
+ 'bl': 5, // sw
20
+ 'ml': 6, // w
21
+ 'tl': 7 // nw
12
22
  },
13
23
  addListener = fabric.util.addListener,
14
24
  removeListener = fabric.util.removeListener,
15
25
  getPointer = fabric.util.getPointer;
16
26
 
17
- fabric.util.object.extend(fabric.Canvas.prototype, /** @scope fabric.Canvas.prototype */ {
27
+ fabric.util.object.extend(fabric.Canvas.prototype, /** @lends fabric.Canvas.prototype */ {
18
28
 
19
29
  /**
20
- * Adds mouse listeners to canvas
21
- * @method _initEvents
30
+ * Adds mouse listeners to canvas
22
31
  * @private
23
- * See configuration documentation for more details.
24
32
  */
25
33
  _initEvents: function () {
26
34
  var _this = this;
@@ -30,6 +38,10 @@
30
38
  this._onMouseUp = this._onMouseUp.bind(this);
31
39
  this._onResize = this._onResize.bind(this);
32
40
 
41
+ this._onGesture = function(e, s) {
42
+ _this.__onTransformGesture(e, s);
43
+ };
44
+
33
45
  addListener(fabric.window, 'resize', this._onResize);
34
46
 
35
47
  if (fabric.isTouchSupported) {
@@ -37,9 +49,7 @@
37
49
  addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);
38
50
 
39
51
  if (typeof Event !== 'undefined' && 'add' in Event) {
40
- Event.add(this.upperCanvasEl, 'gesture', function(e, s) {
41
- _this.__onTransformGesture(e, s);
42
- });
52
+ Event.add(this.upperCanvasEl, 'gesture', this._onGesture);
43
53
  }
44
54
  }
45
55
  else {
@@ -49,8 +59,8 @@
49
59
  },
50
60
 
51
61
  /**
52
- * @method _onMouseDown
53
62
  * @private
63
+ * @param {Event} e Event object fired on mousedown
54
64
  */
55
65
  _onMouseDown: function (e) {
56
66
  this.__onMouseDown(e);
@@ -66,8 +76,8 @@
66
76
  },
67
77
 
68
78
  /**
69
- * @method _onMouseUp
70
79
  * @private
80
+ * @param {Event} e Event object fired on mouseup
71
81
  */
72
82
  _onMouseUp: function (e) {
73
83
  this.__onMouseUp(e);
@@ -83,8 +93,8 @@
83
93
  },
84
94
 
85
95
  /**
86
- * @method _onMouseMove
87
96
  * @private
97
+ * @param {Event} e Event object fired on mousemove
88
98
  */
89
99
  _onMouseMove: function (e) {
90
100
  e.preventDefault && e.preventDefault();
@@ -92,7 +102,6 @@
92
102
  },
93
103
 
94
104
  /**
95
- * @method _onResize
96
105
  * @private
97
106
  */
98
107
  _onResize: function () {
@@ -103,16 +112,16 @@
103
112
  * Method that defines the actions when mouse is released on canvas.
104
113
  * The method resets the currentTransform parameters, store the image corner
105
114
  * position in the image object and render the canvas on top.
106
- * @method __onMouseUp
115
+ * @private
107
116
  * @param {Event} e Event object fired on mouseup
108
- *
109
117
  */
110
118
  __onMouseUp: function (e) {
111
119
 
112
120
  var target;
113
121
 
114
122
  if (this.isDrawingMode && this._isCurrentlyDrawing) {
115
- this.freeDrawing._finalizeAndAddPath();
123
+ this._isCurrentlyDrawing = false;
124
+ this.freeDrawingBrush.onMouseUp();
116
125
  this.fire('mouse:up', { e: e });
117
126
  return;
118
127
  }
@@ -126,13 +135,8 @@
126
135
  target._scaling = false;
127
136
  }
128
137
 
129
- // determine the new coords everytime the image changes its position
130
- var i = this._objects.length;
131
- while (i--) {
132
- this._objects[i].setCoords();
133
- }
134
-
135
138
  target.isMoving = false;
139
+ target.setCoords();
136
140
 
137
141
  // only fire :modified event if target coordinates were changed during mousedown-mouseup
138
142
  if (this.stateful && target.hasStateChanged()) {
@@ -148,7 +152,7 @@
148
152
 
149
153
  this._currentTransform = null;
150
154
 
151
- if (this._groupSelector) {
155
+ if (this.selection && this._groupSelector) {
152
156
  // group selection was completed, determine its bounds
153
157
  this._findSelectedObjects(e);
154
158
  }
@@ -182,9 +186,8 @@
182
186
  * The method inits the currentTransform parameters and renders all the
183
187
  * canvas so the current image can be placed on the top canvas and the rest
184
188
  * in on the container one.
185
- * @method __onMouseDown
186
- * @param e {Event} Event object fired on mousedown
187
- *
189
+ * @private
190
+ * @param {Event} e Event object fired on mousedown
188
191
  */
189
192
  __onMouseDown: function (e) {
190
193
 
@@ -196,12 +199,9 @@
196
199
 
197
200
  if (this.isDrawingMode) {
198
201
  pointer = this.getPointer(e);
199
- this.freeDrawing._prepareForDrawing(pointer);
200
-
201
- // capture coordinates immediately;
202
- // this allows to draw dots (when movement never occurs)
203
- this.freeDrawing._captureDrawingPath(pointer);
204
-
202
+ this._isCurrentlyDrawing = true;
203
+ this.discardActiveObject().renderAll();
204
+ this.freeDrawingBrush.onMouseDown(pointer);
205
205
  this.fire('mouse:down', { e: e });
206
206
  return;
207
207
  }
@@ -212,7 +212,7 @@
212
212
  var target = this.findTarget(e), corner;
213
213
  pointer = this.getPointer(e);
214
214
 
215
- if (this._shouldClearSelection(e)) {
215
+ if (this._shouldClearSelection(e, target)) {
216
216
  this._groupSelector = {
217
217
  ex: pointer.x,
218
218
  ey: pointer.y,
@@ -220,6 +220,11 @@
220
220
  left: 0
221
221
  };
222
222
  this.deactivateAllWithDispatch();
223
+ target && target.selectable && this.setActiveObject(target, e);
224
+ }
225
+ else if (this._shouldHandleGroupLogic(e, target)) {
226
+ this._handleGroupLogic(e, target);
227
+ target = this.getActiveGroup();
223
228
  }
224
229
  else {
225
230
  // determine if it's a drag or rotate case
@@ -229,14 +234,8 @@
229
234
  this.onBeforeScaleRotate(target);
230
235
  }
231
236
 
232
- if (this._shouldHandleGroupLogic(e, target)) {
233
- this._handleGroupLogic(e, target);
234
- target = this.getActiveGroup();
235
- }
236
- else {
237
- if (target !== this.getActiveGroup()) {
238
- this.deactivateAll();
239
- }
237
+ if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
238
+ this.deactivateAll();
240
239
  this.setActiveObject(target, e);
241
240
  }
242
241
 
@@ -263,9 +262,8 @@
263
262
  * an image or neither of them (only hovering). A group selection is also possible and would cancel
264
263
  * all any other type of action.
265
264
  * In case of an image transformation only the top canvas will be rendered.
266
- * @method __onMouseMove
267
- * @param e {Event} Event object fired on mousemove
268
- *
265
+ * @private
266
+ * @param {Event} e Event object fired on mousemove
269
267
  */
270
268
  __onMouseMove: function (e) {
271
269
 
@@ -274,12 +272,7 @@
274
272
  if (this.isDrawingMode) {
275
273
  if (this._isCurrentlyDrawing) {
276
274
  pointer = this.getPointer(e);
277
- this.freeDrawing._captureDrawingPath(pointer);
278
-
279
- // redraw curve
280
- // clear top canvas
281
- this.clearContext(this.contextTop);
282
- this.freeDrawing._render(this.contextTop);
275
+ this.freeDrawingBrush.onMouseMove(pointer);
283
276
  }
284
277
  this.upperCanvasEl.style.cursor = this.freeDrawingCursor;
285
278
  this.fire('mouse:move', { e: e });
@@ -289,7 +282,7 @@
289
282
  var groupSelector = this._groupSelector;
290
283
 
291
284
  // We initially clicked in an empty area, so we draw a box for multiple selection.
292
- if (groupSelector !== null) {
285
+ if (groupSelector) {
293
286
  pointer = getPointer(e, this.upperCanvasEl);
294
287
 
295
288
  groupSelector.left = pointer.x - this._offset.left - groupSelector.ex;
@@ -307,11 +300,11 @@
307
300
  // performance.
308
301
  target = this.findTarget(e);
309
302
 
310
- if (!target) {
303
+ if (!target || target && !target.selectable) {
311
304
  // image/text was hovered-out from, we remove its borders
312
305
  for (var i = this._objects.length; i--; ) {
313
306
  if (this._objects[i] && !this._objects[i].active) {
314
- this._objects[i].setActive(false);
307
+ this._objects[i].set('active', false);
315
308
  }
316
309
  }
317
310
  style.cursor = this.defaultCursor;
@@ -326,115 +319,69 @@
326
319
  pointer = getPointer(e, this.upperCanvasEl);
327
320
 
328
321
  var x = pointer.x,
329
- y = pointer.y;
330
-
331
- this._currentTransform.target.isMoving = true;
332
-
333
- var t = this._currentTransform, reset = false;
334
- if (
335
- (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY')
336
- &&
337
- (
338
- // Switch from a normal resize to center-based
339
- (e.altKey && (t.originX !== 'center' || t.originY !== 'center'))
340
- ||
341
- // Switch from center-based resize to normal one
342
- (!e.altKey && t.originX === 'center' && t.originY === 'center')
343
- )
344
- ) {
322
+ y = pointer.y,
323
+ reset = false,
324
+ transform = this._currentTransform;
325
+
326
+ target = transform.target;
327
+ target.isMoving = true;
328
+
329
+ if ((transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') &&
330
+ // Switch from a normal resize to center-based
331
+ ((e.altKey && (transform.originX !== 'center' || transform.originY !== 'center')) ||
332
+ // Switch from center-based resize to normal one
333
+ (!e.altKey && transform.originX === 'center' && transform.originY === 'center'))
334
+ ) {
345
335
  this._resetCurrentTransform(e);
346
336
  reset = true;
347
337
  }
348
338
 
349
- if (this._currentTransform.action === 'rotate') {
339
+ if (transform.action === 'rotate') {
350
340
  this._rotateObject(x, y);
351
341
 
352
- this.fire('object:rotating', {
353
- target: this._currentTransform.target,
354
- e: e
355
- });
356
- this._currentTransform.target.fire('rotating');
342
+ this.fire('object:rotating', { target: target, e: e });
343
+ target.fire('rotating', { e: e });
357
344
  }
358
- else if (this._currentTransform.action === 'scale') {
345
+ else if (transform.action === 'scale') {
359
346
  // rotate object only if shift key is not pressed
360
347
  // and if it is not a group we are transforming
361
-
362
- // TODO
363
- /*if (!e.shiftKey) {
364
- this._rotateObject(x, y);
365
-
366
- this.fire('object:rotating', {
367
- target: this._currentTransform.target,
368
- e: e
369
- });
370
- this._currentTransform.target.fire('rotating');
371
- }*/
372
-
373
- // if (!this._currentTransform.target.hasRotatingPoint) {
374
- // this._scaleObject(x, y);
375
- // this.fire('object:scaling', {
376
- // target: this._currentTransform.target
377
- // });
378
- // this._currentTransform.target.fire('scaling');
379
- // }
380
-
381
- if (e.shiftKey || this.uniScaleTransform) {
382
- this._currentTransform.currentAction = 'scale';
348
+ if ((e.shiftKey || this.uniScaleTransform) && !target.get('lockUniScaling')) {
349
+ transform.currentAction = 'scale';
383
350
  this._scaleObject(x, y);
384
351
  }
385
352
  else {
386
- if (!reset && t.currentAction === 'scale') {
387
- // Switch from a normal resize to proportional
353
+ // Switch from a normal resize to proportional
354
+ if (!reset && transform.currentAction === 'scale') {
388
355
  this._resetCurrentTransform(e);
389
356
  }
390
357
 
391
- this._currentTransform.currentAction = 'scaleEqually';
358
+ transform.currentAction = 'scaleEqually';
392
359
  this._scaleObject(x, y, 'equally');
393
360
  }
394
361
 
395
- this.fire('object:scaling', {
396
- target: this._currentTransform.target,
397
- e: e
398
- });
362
+ this.fire('object:scaling', { target: target, e: e });
363
+ target.fire('scaling', { e: e });
399
364
  }
400
- // else if (this._currentTransform.action === 'scale') {
401
- // this._scaleObject(x, y);
402
- // this.fire('object:scaling', {
403
- // target: this._currentTransform.target
404
- // });
405
- // this._currentTransform.target.fire('scaling');
406
- // }
407
- else if (this._currentTransform.action === 'scaleX') {
365
+ else if (transform.action === 'scaleX') {
408
366
  this._scaleObject(x, y, 'x');
409
367
 
410
- this.fire('object:scaling', {
411
- target: this._currentTransform.target,
412
- e: e
413
- });
414
- this._currentTransform.target.fire('scaling', { e: e });
368
+ this.fire('object:scaling', { target: target, e: e});
369
+ target.fire('scaling', { e: e });
415
370
  }
416
- else if (this._currentTransform.action === 'scaleY') {
371
+ else if (transform.action === 'scaleY') {
417
372
  this._scaleObject(x, y, 'y');
418
373
 
419
- this.fire('object:scaling', {
420
- target: this._currentTransform.target,
421
- e: e
422
- });
423
- this._currentTransform.target.fire('scaling', { e: e });
374
+ this.fire('object:scaling', { target: target, e: e});
375
+ target.fire('scaling', { e: e });
424
376
  }
425
377
  else {
426
378
  this._translateObject(x, y);
427
379
 
428
- this.fire('object:moving', {
429
- target: this._currentTransform.target,
430
- e: e
431
- });
432
-
380
+ this.fire('object:moving', { target: target, e: e});
381
+ target.fire('moving', { e: e });
433
382
  this._setCursor(this.moveCursor);
434
-
435
- this._currentTransform.target.fire('moving', { e: e });
436
383
  }
437
- // only commit here. when we are actually moving the pictures
384
+
438
385
  this.renderAll();
439
386
  }
440
387
  this.fire('mouse:move', { target: target, e: e });
@@ -443,9 +390,8 @@
443
390
  /**
444
391
  * Sets the cursor depending on where the canvas is being hovered.
445
392
  * Note: very buggy in Opera
446
- * @method _setCursorFromEvent
447
- * @param e {Event} Event object
448
- * @param target {Object} Object that the mouse is hovering, if so.
393
+ * @param {Event} e Event object
394
+ * @param {Object} target Object that the mouse is hovering, if so.
449
395
  */
450
396
  _setCursorFromEvent: function (e, target) {
451
397
  var s = this.upperCanvasEl.style;
@@ -464,8 +410,15 @@
464
410
  s.cursor = this.hoverCursor;
465
411
  }
466
412
  else {
467
- if (corner in cursorMap) {
468
- s.cursor = cursorMap[corner];
413
+ if (corner in cursorOffset) {
414
+ var n = Math.round((target.getAngle() % 360) / 45);
415
+ if (n<0) {
416
+ n += 8; // full circle ahead
417
+ }
418
+ n += cursorOffset[corner];
419
+ // normalize n to be from 0 to 7
420
+ n %= 8;
421
+ s.cursor = cursorMap[n];
469
422
  }
470
423
  else if (corner === 'mtr' && target.hasRotatingPoint) {
471
424
  s.cursor = this.rotationCursor;