fabric 4.5.1-browser → 5.0.0-browser
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.
- package/CHANGELOG.md +78 -0
- package/CONTRIBUTING.md +14 -0
- package/HEADER.js +1 -1
- package/README.md +3 -6
- package/SECURITY.md +5 -0
- package/build.js +1 -0
- package/dist/fabric.js +1160 -668
- package/dist/fabric.min.js +1 -1
- package/lib/event.js +7 -3
- package/package.json +9 -3
- package/publish-next.js +15 -0
- package/publish.js +3 -0
- package/src/brushes/base_brush.class.js +3 -5
- package/src/brushes/pattern_brush.class.js +7 -5
- package/src/brushes/pencil_brush.class.js +49 -37
- package/src/canvas.class.js +27 -57
- package/src/filters/saturate_filter.class.js +9 -1
- package/src/filters/vibrance_filter.class.js +122 -0
- package/src/mixins/animation.mixin.js +20 -25
- package/src/mixins/canvas_events.mixin.js +30 -59
- package/src/mixins/canvas_grouping.mixin.js +4 -4
- package/src/mixins/collection.mixin.js +11 -2
- package/src/mixins/eraser_brush.mixin.js +495 -452
- package/src/mixins/itext_behavior.mixin.js +7 -1
- package/src/mixins/itext_key_behavior.mixin.js +7 -1
- package/src/mixins/object_geometry.mixin.js +5 -35
- package/src/mixins/object_interactivity.mixin.js +18 -7
- package/src/mixins/object_straightening.mixin.js +4 -9
- package/src/mixins/observable.mixin.js +22 -0
- package/src/parser.js +13 -9
- package/src/shapes/circle.class.js +22 -19
- package/src/shapes/ellipse.class.js +2 -2
- package/src/shapes/group.class.js +24 -32
- package/src/shapes/image.class.js +3 -25
- package/src/shapes/itext.class.js +10 -0
- package/src/shapes/line.class.js +5 -21
- package/src/shapes/object.class.js +67 -32
- package/src/shapes/path.class.js +17 -18
- package/src/shapes/polygon.class.js +11 -10
- package/src/shapes/polyline.class.js +33 -24
- package/src/shapes/rect.class.js +0 -18
- package/src/shapes/text.class.js +120 -58
- package/src/shapes/triangle.class.js +0 -15
- package/src/static_canvas.class.js +43 -20
- package/src/util/animate.js +149 -16
- package/src/util/animate_color.js +2 -1
- package/src/util/lang_object.js +5 -1
- package/src/util/misc.js +193 -42
- package/src/util/path.js +89 -52
package/lib/event.js
CHANGED
|
@@ -1368,7 +1368,11 @@ root.gesture = function(conf) {
|
|
|
1368
1368
|
var dx = touch.move.x - self.x;
|
|
1369
1369
|
var dy = touch.move.y - self.y;
|
|
1370
1370
|
var distance = Math.sqrt(dx * dx + dy * dy);
|
|
1371
|
-
|
|
1371
|
+
// If touch start.distance from centroid is 0, scale should not be updated.
|
|
1372
|
+
// This prevents dividing by 0 in cases where start.distance is oddly 0.
|
|
1373
|
+
if (start.distance !== 0) {
|
|
1374
|
+
scale += distance / start.distance;
|
|
1375
|
+
}
|
|
1372
1376
|
// Calculate rotation.
|
|
1373
1377
|
var angle = Math.atan2(dx, dy) / RAD_DEG;
|
|
1374
1378
|
var rotate = (start.angle - angle + 360) % 360 - 180;
|
|
@@ -1765,8 +1769,8 @@ root.tap = function(conf) {
|
|
|
1765
1769
|
var identifier = touch.identifier || Infinity;
|
|
1766
1770
|
var pt = conf.tracker[identifier];
|
|
1767
1771
|
if (!pt) continue;
|
|
1768
|
-
var x = (touch.pageX - bbox.x1);
|
|
1769
|
-
var y = (touch.pageY - bbox.y1);
|
|
1772
|
+
var x = (touch.pageX - bbox.x1 - parseInt(window.scrollX));
|
|
1773
|
+
var y = (touch.pageY - bbox.y1 - parseInt(window.scrollY));
|
|
1770
1774
|
///
|
|
1771
1775
|
var dx = x - pt.start.x;
|
|
1772
1776
|
var dy = y - pt.start.y;
|
package/package.json
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
"name": "fabric",
|
|
3
3
|
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
|
|
4
4
|
"homepage": "http://fabricjs.com/",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "5.0.0-browser",
|
|
6
6
|
"author": "Juriy Zaytsev <kangax@gmail.com>",
|
|
7
7
|
"contributors": [
|
|
8
8
|
{
|
|
9
9
|
"name": "Andrea Bogazzi",
|
|
10
10
|
"email": "andreabogazzi79@gmail.com"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "Steve Eberhardt",
|
|
14
|
+
"email": "melchiar2@gmail.com"
|
|
11
15
|
}
|
|
12
16
|
],
|
|
13
17
|
"keywords": [
|
|
@@ -40,6 +44,7 @@
|
|
|
40
44
|
},
|
|
41
45
|
"license": "MIT",
|
|
42
46
|
"scripts": {
|
|
47
|
+
"changelog": "auto-changelog -o change-output.md --unreleased-only",
|
|
43
48
|
"build": "node build.js modules=ALL requirejs exclude=gestures,accessors,erasing",
|
|
44
49
|
"build:fast": "node build.js modules=ALL requirejs fast exclude=gestures,accessors,erasing",
|
|
45
50
|
"build:watch": "onchange 'src/**/**' 'HEADER.js' 'lib/**/**' -- npm run build_export",
|
|
@@ -65,17 +70,18 @@
|
|
|
65
70
|
},
|
|
66
71
|
"optionalDependencies": {},
|
|
67
72
|
"devDependencies": {
|
|
73
|
+
"auto-changelog": "^2.3.0",
|
|
68
74
|
"chalk": "^2.4.1",
|
|
69
75
|
"eslint": "4.18.x",
|
|
70
76
|
"nyc": "^15.1.0",
|
|
71
|
-
"onchange": "^
|
|
77
|
+
"onchange": "^7.1.0",
|
|
72
78
|
"pixelmatch": "^4.0.2",
|
|
73
79
|
"qunit": "^2.13.0",
|
|
74
80
|
"testem": "^3.2.0",
|
|
75
81
|
"uglify-js": "3.3.x"
|
|
76
82
|
},
|
|
77
83
|
"engines": {
|
|
78
|
-
"node": ">=
|
|
84
|
+
"node": ">=14.0.0"
|
|
79
85
|
},
|
|
80
86
|
"main": "./dist/fabric.js",
|
|
81
87
|
"dependencies": {}
|
package/publish-next.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var cp = require('child_process');
|
|
2
|
+
|
|
3
|
+
console.log('npm version prerelease --preid=rc');
|
|
4
|
+
|
|
5
|
+
cp.execSync('npm version prerelease --preid=rc');
|
|
6
|
+
|
|
7
|
+
console.log('npm run build');
|
|
8
|
+
|
|
9
|
+
cp.execSync('npm run build');
|
|
10
|
+
|
|
11
|
+
console.log('npm publish --tag next');
|
|
12
|
+
|
|
13
|
+
cp.execSync('npm publish --tag next');
|
|
14
|
+
|
|
15
|
+
console.log('pre release package is published');
|
package/publish.js
CHANGED
|
@@ -2,6 +2,9 @@ var cp = require('child_process');
|
|
|
2
2
|
var path = require('path');
|
|
3
3
|
var fs = require('fs');
|
|
4
4
|
|
|
5
|
+
// useful changelog regexp for atom
|
|
6
|
+
// \(#([0-9]+)\) [#$1](https://github.com/fabricjs/fabric.js/pull/$1)
|
|
7
|
+
|
|
5
8
|
// eslint-disable-next-line no-undef
|
|
6
9
|
var pkgPath = path.resolve(__dirname, './package.json');
|
|
7
10
|
var pkgText = fs.readFileSync(pkgPath); // get original pkg text to restore it later
|
|
@@ -68,17 +68,15 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
68
68
|
/**
|
|
69
69
|
* Sets brush styles
|
|
70
70
|
* @private
|
|
71
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
71
72
|
*/
|
|
72
|
-
_setBrushStyles: function() {
|
|
73
|
-
var ctx = this.canvas.contextTop;
|
|
73
|
+
_setBrushStyles: function (ctx) {
|
|
74
74
|
ctx.strokeStyle = this.color;
|
|
75
75
|
ctx.lineWidth = this.width;
|
|
76
76
|
ctx.lineCap = this.strokeLineCap;
|
|
77
77
|
ctx.miterLimit = this.strokeMiterLimit;
|
|
78
78
|
ctx.lineJoin = this.strokeLineJoin;
|
|
79
|
-
|
|
80
|
-
ctx.setLineDash(this.strokeDashArray || []);
|
|
81
|
-
}
|
|
79
|
+
ctx.setLineDash(this.strokeDashArray || []);
|
|
82
80
|
},
|
|
83
81
|
|
|
84
82
|
/**
|
|
@@ -29,17 +29,19 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Creates "pattern" instance property
|
|
32
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
32
33
|
*/
|
|
33
|
-
getPattern: function() {
|
|
34
|
-
return
|
|
34
|
+
getPattern: function(ctx) {
|
|
35
|
+
return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');
|
|
35
36
|
},
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* Sets brush styles
|
|
40
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
39
41
|
*/
|
|
40
|
-
_setBrushStyles: function() {
|
|
41
|
-
this.callSuper('_setBrushStyles');
|
|
42
|
-
|
|
42
|
+
_setBrushStyles: function(ctx) {
|
|
43
|
+
this.callSuper('_setBrushStyles', ctx);
|
|
44
|
+
ctx.strokeStyle = this.getPattern(ctx);
|
|
43
45
|
},
|
|
44
46
|
|
|
45
47
|
/**
|
|
@@ -13,6 +13,22 @@
|
|
|
13
13
|
*/
|
|
14
14
|
decimate: 0.4,
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Draws a straight line between last recorded point to current pointer
|
|
18
|
+
* Used for `shift` functionality
|
|
19
|
+
*
|
|
20
|
+
* @type boolean
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
drawStraightLine: false,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The event modifier key that makes the brush draw a straight line.
|
|
27
|
+
* If `null` or 'none' or any other string that is not a modifier key the feature is disabled.
|
|
28
|
+
* @type {'altKey' | 'shiftKey' | 'ctrlKey' | 'none' | undefined | null}
|
|
29
|
+
*/
|
|
30
|
+
straightLineKey: 'shiftKey',
|
|
31
|
+
|
|
16
32
|
/**
|
|
17
33
|
* Constructor
|
|
18
34
|
* @param {fabric.Canvas} canvas
|
|
@@ -23,6 +39,10 @@
|
|
|
23
39
|
this._points = [];
|
|
24
40
|
},
|
|
25
41
|
|
|
42
|
+
needsFullRender: function () {
|
|
43
|
+
return this.callSuper('needsFullRender') || this._hasStraightLine;
|
|
44
|
+
},
|
|
45
|
+
|
|
26
46
|
/**
|
|
27
47
|
* Invoked inside on mouse down and mouse move
|
|
28
48
|
* @param {Object} pointer
|
|
@@ -41,6 +61,7 @@
|
|
|
41
61
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
42
62
|
return;
|
|
43
63
|
}
|
|
64
|
+
this.drawStraightLine = options.e[this.straightLineKey];
|
|
44
65
|
this._prepareForDrawing(pointer);
|
|
45
66
|
// capture coordinates immediately
|
|
46
67
|
// this allows to draw dots (when movement never occurs)
|
|
@@ -56,6 +77,7 @@
|
|
|
56
77
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
57
78
|
return;
|
|
58
79
|
}
|
|
80
|
+
this.drawStraightLine = options.e[this.straightLineKey];
|
|
59
81
|
if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {
|
|
60
82
|
return;
|
|
61
83
|
}
|
|
@@ -88,6 +110,7 @@
|
|
|
88
110
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
89
111
|
return true;
|
|
90
112
|
}
|
|
113
|
+
this.drawStraightLine = false;
|
|
91
114
|
this.oldEnd = undefined;
|
|
92
115
|
this._finalizeAndAddPath();
|
|
93
116
|
return false;
|
|
@@ -114,6 +137,10 @@
|
|
|
114
137
|
if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {
|
|
115
138
|
return false;
|
|
116
139
|
}
|
|
140
|
+
if (this.drawStraightLine && this._points.length > 1) {
|
|
141
|
+
this._hasStraightLine = true;
|
|
142
|
+
this._points.pop();
|
|
143
|
+
}
|
|
117
144
|
this._points.push(point);
|
|
118
145
|
return true;
|
|
119
146
|
},
|
|
@@ -124,8 +151,9 @@
|
|
|
124
151
|
*/
|
|
125
152
|
_reset: function() {
|
|
126
153
|
this._points = [];
|
|
127
|
-
this._setBrushStyles();
|
|
154
|
+
this._setBrushStyles(this.canvas.contextTop);
|
|
128
155
|
this._setShadow();
|
|
156
|
+
this._hasStraightLine = false;
|
|
129
157
|
},
|
|
130
158
|
|
|
131
159
|
/**
|
|
@@ -140,12 +168,13 @@
|
|
|
140
168
|
/**
|
|
141
169
|
* Draw a smooth path on the topCanvas using quadraticCurveTo
|
|
142
170
|
* @private
|
|
171
|
+
* @param {CanvasRenderingContext2D} [ctx]
|
|
143
172
|
*/
|
|
144
|
-
_render: function() {
|
|
145
|
-
var
|
|
173
|
+
_render: function(ctx) {
|
|
174
|
+
var i, len,
|
|
146
175
|
p1 = this._points[0],
|
|
147
176
|
p2 = this._points[1];
|
|
148
|
-
|
|
177
|
+
ctx = ctx || this.canvas.contextTop;
|
|
149
178
|
this._saveAndTransform(ctx);
|
|
150
179
|
ctx.beginPath();
|
|
151
180
|
//if we only have 2 points in the path and they are the same
|
|
@@ -179,43 +208,26 @@
|
|
|
179
208
|
/**
|
|
180
209
|
* Converts points to SVG path
|
|
181
210
|
* @param {Array} points Array of points
|
|
182
|
-
* @return {
|
|
211
|
+
* @return {(string|number)[][]} SVG path commands
|
|
183
212
|
*/
|
|
184
|
-
convertPointsToSVGPath: function(points) {
|
|
185
|
-
var
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
len = points.length, multSignX = 1, multSignY = 0, manyPoints = len > 2;
|
|
213
|
+
convertPointsToSVGPath: function (points) {
|
|
214
|
+
var correction = this.width / 1000;
|
|
215
|
+
return fabric.util.getSmoothPathFromPoints(points, correction);
|
|
216
|
+
},
|
|
189
217
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// p1 is our bezier control point
|
|
199
|
-
// midpoint is our endpoint
|
|
200
|
-
// start point is p(i-1) value.
|
|
201
|
-
path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' ');
|
|
202
|
-
}
|
|
203
|
-
p1 = points[i];
|
|
204
|
-
if ((i + 1) < points.length) {
|
|
205
|
-
p2 = points[i + 1];
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (manyPoints) {
|
|
209
|
-
multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;
|
|
210
|
-
multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;
|
|
211
|
-
}
|
|
212
|
-
path.push('L ', p1.x + multSignX * width, ' ', p1.y + multSignY * width);
|
|
213
|
-
return path;
|
|
218
|
+
/**
|
|
219
|
+
* @private
|
|
220
|
+
* @param {(string|number)[][]} pathData SVG path commands
|
|
221
|
+
* @returns {boolean}
|
|
222
|
+
*/
|
|
223
|
+
_isEmptySVGPath: function (pathData) {
|
|
224
|
+
var pathString = fabric.util.joinPath(pathData);
|
|
225
|
+
return pathString === 'M 0 0 Q 0 0 0 0 L 0 0';
|
|
214
226
|
},
|
|
215
227
|
|
|
216
228
|
/**
|
|
217
229
|
* Creates fabric.Path object to add on canvas
|
|
218
|
-
* @param {
|
|
230
|
+
* @param {(string|number)[][]} pathData Path data
|
|
219
231
|
* @return {fabric.Path} Path to add on canvas
|
|
220
232
|
*/
|
|
221
233
|
createPath: function(pathData) {
|
|
@@ -272,8 +284,8 @@
|
|
|
272
284
|
if (this.decimate) {
|
|
273
285
|
this._points = this.decimatePoints(this._points, this.decimate);
|
|
274
286
|
}
|
|
275
|
-
var pathData = this.convertPointsToSVGPath(this._points)
|
|
276
|
-
if (pathData
|
|
287
|
+
var pathData = this.convertPointsToSVGPath(this._points);
|
|
288
|
+
if (this._isEmptySVGPath(pathData)) {
|
|
277
289
|
// do not create 0 width/height paths, as they are
|
|
278
290
|
// rendered inconsistently across browsers
|
|
279
291
|
// Firefox 4, for example, renders a dot,
|
package/src/canvas.class.js
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var getPointer = fabric.util.getPointer,
|
|
4
4
|
degreesToRadians = fabric.util.degreesToRadians,
|
|
5
|
-
|
|
6
|
-
supportLineDash = fabric.StaticCanvas.supports('setLineDash'),
|
|
7
|
-
isTouchEvent = fabric.util.isTouchEvent,
|
|
8
|
-
STROKE_OFFSET = 0.5;
|
|
5
|
+
isTouchEvent = fabric.util.isTouchEvent;
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* Canvas class
|
|
@@ -40,15 +37,11 @@
|
|
|
40
37
|
* @fires dragover
|
|
41
38
|
* @fires dragenter
|
|
42
39
|
* @fires dragleave
|
|
40
|
+
* @fires drop:before before drop event. same native event. This is added to handle edge cases
|
|
43
41
|
* @fires drop
|
|
44
42
|
* @fires after:render at the end of the render process, receives the context in the callback
|
|
45
43
|
* @fires before:render at start the render process, receives the context in the callback
|
|
46
44
|
*
|
|
47
|
-
* the following events are deprecated:
|
|
48
|
-
* @fires object:rotated at the end of a rotation transform
|
|
49
|
-
* @fires object:scaled at the end of a scale transform
|
|
50
|
-
* @fires object:moved at the end of translation transform
|
|
51
|
-
* @fires object:skewed at the end of a skew transform
|
|
52
45
|
*/
|
|
53
46
|
fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {
|
|
54
47
|
|
|
@@ -233,13 +226,6 @@
|
|
|
233
226
|
*/
|
|
234
227
|
freeDrawingCursor: 'crosshair',
|
|
235
228
|
|
|
236
|
-
/**
|
|
237
|
-
* Cursor value used for rotation point
|
|
238
|
-
* @type String
|
|
239
|
-
* @default
|
|
240
|
-
*/
|
|
241
|
-
rotationCursor: 'crosshair',
|
|
242
|
-
|
|
243
229
|
/**
|
|
244
230
|
* Cursor value used for disabled elements ( corners with disabled action )
|
|
245
231
|
* @type String
|
|
@@ -345,6 +331,13 @@
|
|
|
345
331
|
*/
|
|
346
332
|
targets: [],
|
|
347
333
|
|
|
334
|
+
/**
|
|
335
|
+
* When the option is enabled, PointerEvent is used instead of MouseEvent.
|
|
336
|
+
* @type Boolean
|
|
337
|
+
* @default
|
|
338
|
+
*/
|
|
339
|
+
enablePointerEvents: false,
|
|
340
|
+
|
|
348
341
|
/**
|
|
349
342
|
* Keep track of the hovered target
|
|
350
343
|
* @type fabric.Object
|
|
@@ -420,6 +413,7 @@
|
|
|
420
413
|
}
|
|
421
414
|
if (this.hasLostContext) {
|
|
422
415
|
this.renderTopLayer(this.contextTop);
|
|
416
|
+
this.hasLostContext = false;
|
|
423
417
|
}
|
|
424
418
|
var canvasToDrawOn = this.contextContainer;
|
|
425
419
|
this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());
|
|
@@ -689,21 +683,20 @@
|
|
|
689
683
|
* @param {CanvasRenderingContext2D} ctx to draw the selection on
|
|
690
684
|
*/
|
|
691
685
|
_drawSelection: function (ctx) {
|
|
692
|
-
var
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
686
|
+
var selector = this._groupSelector,
|
|
687
|
+
viewportStart = new fabric.Point(selector.ex, selector.ey),
|
|
688
|
+
start = fabric.util.transformPoint(viewportStart, this.viewportTransform),
|
|
689
|
+
viewportExtent = new fabric.Point(selector.ex + selector.left, selector.ey + selector.top),
|
|
690
|
+
extent = fabric.util.transformPoint(viewportExtent, this.viewportTransform),
|
|
691
|
+
minX = Math.min(start.x, extent.x),
|
|
692
|
+
minY = Math.min(start.y, extent.y),
|
|
693
|
+
maxX = Math.max(start.x, extent.x),
|
|
694
|
+
maxY = Math.max(start.y, extent.y),
|
|
695
|
+
strokeOffset = this.selectionLineWidth / 2;
|
|
697
696
|
|
|
698
697
|
if (this.selectionColor) {
|
|
699
698
|
ctx.fillStyle = this.selectionColor;
|
|
700
|
-
|
|
701
|
-
ctx.fillRect(
|
|
702
|
-
groupSelector.ex - ((left > 0) ? 0 : -left),
|
|
703
|
-
groupSelector.ey - ((top > 0) ? 0 : -top),
|
|
704
|
-
aleft,
|
|
705
|
-
atop
|
|
706
|
-
);
|
|
699
|
+
ctx.fillRect(minX, minY, maxX - minX, maxY - minY);
|
|
707
700
|
}
|
|
708
701
|
|
|
709
702
|
if (!this.selectionLineWidth || !this.selectionBorderColor) {
|
|
@@ -712,31 +705,13 @@
|
|
|
712
705
|
ctx.lineWidth = this.selectionLineWidth;
|
|
713
706
|
ctx.strokeStyle = this.selectionBorderColor;
|
|
714
707
|
|
|
708
|
+
minX += strokeOffset;
|
|
709
|
+
minY += strokeOffset;
|
|
710
|
+
maxX -= strokeOffset;
|
|
711
|
+
maxY -= strokeOffset;
|
|
715
712
|
// selection border
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
var px = groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),
|
|
719
|
-
py = groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop);
|
|
720
|
-
|
|
721
|
-
ctx.beginPath();
|
|
722
|
-
|
|
723
|
-
fabric.util.drawDashedLine(ctx, px, py, px + aleft, py, this.selectionDashArray);
|
|
724
|
-
fabric.util.drawDashedLine(ctx, px, py + atop - 1, px + aleft, py + atop - 1, this.selectionDashArray);
|
|
725
|
-
fabric.util.drawDashedLine(ctx, px, py, px, py + atop, this.selectionDashArray);
|
|
726
|
-
fabric.util.drawDashedLine(ctx, px + aleft - 1, py, px + aleft - 1, py + atop, this.selectionDashArray);
|
|
727
|
-
|
|
728
|
-
ctx.closePath();
|
|
729
|
-
ctx.stroke();
|
|
730
|
-
}
|
|
731
|
-
else {
|
|
732
|
-
fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);
|
|
733
|
-
ctx.strokeRect(
|
|
734
|
-
groupSelector.ex + STROKE_OFFSET - ((left > 0) ? 0 : aleft),
|
|
735
|
-
groupSelector.ey + STROKE_OFFSET - ((top > 0) ? 0 : atop),
|
|
736
|
-
aleft,
|
|
737
|
-
atop
|
|
738
|
-
);
|
|
739
|
-
}
|
|
713
|
+
fabric.Object.prototype._setLineDash.call(this, ctx, this.selectionDashArray);
|
|
714
|
+
ctx.strokeRect(minX, minY, maxX - minX, maxY - minY);
|
|
740
715
|
},
|
|
741
716
|
|
|
742
717
|
/**
|
|
@@ -1108,17 +1083,12 @@
|
|
|
1108
1083
|
e: e,
|
|
1109
1084
|
selected: added,
|
|
1110
1085
|
deselected: removed,
|
|
1111
|
-
// added for backward compatibility
|
|
1112
|
-
// deprecated
|
|
1113
|
-
updated: added[0] || removed[0],
|
|
1114
|
-
target: this._activeObject,
|
|
1115
1086
|
});
|
|
1116
1087
|
}
|
|
1117
1088
|
else if (objects.length > 0) {
|
|
1118
1089
|
this.fire('selection:created', {
|
|
1119
1090
|
e: e,
|
|
1120
1091
|
selected: added,
|
|
1121
|
-
target: this._activeObject,
|
|
1122
1092
|
});
|
|
1123
1093
|
}
|
|
1124
1094
|
else if (oldObjects.length > 0) {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo}
|
|
16
16
|
* @example
|
|
17
17
|
* var filter = new fabric.Image.filters.Saturation({
|
|
18
|
-
* saturation:
|
|
18
|
+
* saturation: 1
|
|
19
19
|
* });
|
|
20
20
|
* object.filters.push(filter);
|
|
21
21
|
* object.applyFilters();
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
'gl_FragColor = color;\n' +
|
|
44
44
|
'}',
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Saturation value, from -1 to 1.
|
|
48
|
+
* Increases/decreases the color saturation.
|
|
49
|
+
* A value of 0 has no effect.
|
|
50
|
+
*
|
|
51
|
+
* @param {Number} saturation
|
|
52
|
+
* @default
|
|
53
|
+
*/
|
|
46
54
|
saturation: 0,
|
|
47
55
|
|
|
48
56
|
mainParameter: 'saturation',
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
(function(global) {
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
var fabric = global.fabric || (global.fabric = { }),
|
|
6
|
+
filters = fabric.Image.filters,
|
|
7
|
+
createClass = fabric.util.createClass;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Vibrance filter class
|
|
11
|
+
* @class fabric.Image.filters.Vibrance
|
|
12
|
+
* @memberOf fabric.Image.filters
|
|
13
|
+
* @extends fabric.Image.filters.BaseFilter
|
|
14
|
+
* @see {@link fabric.Image.filters.Vibrance#initialize} for constructor definition
|
|
15
|
+
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo}
|
|
16
|
+
* @example
|
|
17
|
+
* var filter = new fabric.Image.filters.Vibrance({
|
|
18
|
+
* vibrance: 1
|
|
19
|
+
* });
|
|
20
|
+
* object.filters.push(filter);
|
|
21
|
+
* object.applyFilters();
|
|
22
|
+
*/
|
|
23
|
+
filters.Vibrance = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Vibrance.prototype */ {
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Filter type
|
|
27
|
+
* @param {String} type
|
|
28
|
+
* @default
|
|
29
|
+
*/
|
|
30
|
+
type: 'Vibrance',
|
|
31
|
+
|
|
32
|
+
fragmentSource: 'precision highp float;\n' +
|
|
33
|
+
'uniform sampler2D uTexture;\n' +
|
|
34
|
+
'uniform float uVibrance;\n' +
|
|
35
|
+
'varying vec2 vTexCoord;\n' +
|
|
36
|
+
'void main() {\n' +
|
|
37
|
+
'vec4 color = texture2D(uTexture, vTexCoord);\n' +
|
|
38
|
+
'float max = max(color.r, max(color.g, color.b));\n' +
|
|
39
|
+
'float avg = (color.r + color.g + color.b) / 3.0;\n' +
|
|
40
|
+
'float amt = (abs(max - avg) * 2.0) * uVibrance;\n' +
|
|
41
|
+
'color.r += max != color.r ? (max - color.r) * amt : 0.00;\n' +
|
|
42
|
+
'color.g += max != color.g ? (max - color.g) * amt : 0.00;\n' +
|
|
43
|
+
'color.b += max != color.b ? (max - color.b) * amt : 0.00;\n' +
|
|
44
|
+
'gl_FragColor = color;\n' +
|
|
45
|
+
'}',
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Vibrance value, from -1 to 1.
|
|
49
|
+
* Increases/decreases the saturation of more muted colors with less effect on saturated colors.
|
|
50
|
+
* A value of 0 has no effect.
|
|
51
|
+
*
|
|
52
|
+
* @param {Number} vibrance
|
|
53
|
+
* @default
|
|
54
|
+
*/
|
|
55
|
+
vibrance: 0,
|
|
56
|
+
|
|
57
|
+
mainParameter: 'vibrance',
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Constructor
|
|
61
|
+
* @memberOf fabric.Image.filters.Vibrance.prototype
|
|
62
|
+
* @param {Object} [options] Options object
|
|
63
|
+
* @param {Number} [options.vibrance=0] Vibrance value for the image (between -1 and 1)
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Apply the Vibrance operation to a Uint8ClampedArray representing the pixels of an image.
|
|
68
|
+
*
|
|
69
|
+
* @param {Object} options
|
|
70
|
+
* @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.
|
|
71
|
+
*/
|
|
72
|
+
applyTo2d: function(options) {
|
|
73
|
+
if (this.vibrance === 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
var imageData = options.imageData,
|
|
77
|
+
data = imageData.data, len = data.length,
|
|
78
|
+
adjust = -this.vibrance, i, max, avg, amt;
|
|
79
|
+
|
|
80
|
+
for (i = 0; i < len; i += 4) {
|
|
81
|
+
max = Math.max(data[i], data[i + 1], data[i + 2]);
|
|
82
|
+
avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
|
|
83
|
+
amt = ((Math.abs(max - avg) * 2 / 255) * adjust);
|
|
84
|
+
data[i] += max !== data[i] ? (max - data[i]) * amt : 0;
|
|
85
|
+
data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * amt : 0;
|
|
86
|
+
data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * amt : 0;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Return WebGL uniform locations for this filter's shader.
|
|
92
|
+
*
|
|
93
|
+
* @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.
|
|
94
|
+
* @param {WebGLShaderProgram} program This filter's compiled shader program.
|
|
95
|
+
*/
|
|
96
|
+
getUniformLocations: function(gl, program) {
|
|
97
|
+
return {
|
|
98
|
+
uVibrance: gl.getUniformLocation(program, 'uVibrance'),
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Send data from this filter to its shader program's uniforms.
|
|
104
|
+
*
|
|
105
|
+
* @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.
|
|
106
|
+
* @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects
|
|
107
|
+
*/
|
|
108
|
+
sendUniformData: function(gl, uniformLocations) {
|
|
109
|
+
gl.uniform1f(uniformLocations.uVibrance, -this.vibrance);
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Returns filter instance from an object representation
|
|
115
|
+
* @static
|
|
116
|
+
* @param {Object} object Object to create an instance from
|
|
117
|
+
* @param {Function} [callback] to be invoked after filter creation
|
|
118
|
+
* @return {fabric.Image.filters.Vibrance} Instance of fabric.Image.filters.Vibrance
|
|
119
|
+
*/
|
|
120
|
+
fabric.Image.filters.Vibrance.fromObject = fabric.Image.filters.BaseFilter.fromObject;
|
|
121
|
+
|
|
122
|
+
})(typeof exports !== 'undefined' ? exports : this);
|