Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAJOR feat(fabric) remove callbacks in for Promise support #7657

Merged
merged 43 commits into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
498a72b
this is all broken
asturur Feb 6, 2022
6733893
rect test pass
asturur Feb 6, 2022
7374726
clone ok
asturur Feb 6, 2022
3f42f35
fix active selection test
asturur Feb 11, 2022
935c33f
fix active selection test
asturur Feb 11, 2022
1bad76e
canvas fixed
asturur Feb 12, 2022
9e067cb
fix static canvas tests
asturur Feb 13, 2022
39a5a19
fixed group circle ellipse
asturur Feb 13, 2022
9b2c0a0
more progress
asturur Feb 13, 2022
9efe6b6
fixed images
asturur Feb 13, 2022
af37cbc
solved more
asturur Feb 13, 2022
f57d124
solved more
asturur Feb 13, 2022
2480b0f
solved more
asturur Feb 13, 2022
18580ff
more
asturur Feb 13, 2022
06a5d24
ok
asturur Feb 13, 2022
db7abc9
more test fixed
asturur Feb 13, 2022
3be7749
visual fixed
asturur Feb 13, 2022
d886bc9
ut passing
asturur Feb 13, 2022
b04f686
fix lint
asturur Feb 13, 2022
751b6ef
test lint
asturur Feb 13, 2022
1e7722b
removed this thing here
asturur Feb 13, 2022
78ef400
WTF
asturur Feb 13, 2022
83171df
fix generic enliving
asturur Feb 14, 2022
174d940
small errors removed
asturur Feb 14, 2022
e259205
try this
asturur Feb 14, 2022
1675215
another shot in the darl
asturur Feb 14, 2022
4e1bc07
Merge branch 'master' into promises-support
asturur Feb 14, 2022
fee8547
updated master
asturur Feb 14, 2022
5be02de
JSDOC
ShaMan123 Feb 14, 2022
041111d
Merge branch 'master' into promises-support
asturur Feb 14, 2022
4120f24
typo
ShaMan123 Feb 15, 2022
38d3bfe
more tests
asturur Feb 15, 2022
1beba19
more tests
asturur Feb 15, 2022
7b78236
removed death methods
asturur Feb 15, 2022
9f5ef64
use real class for Object.fromObject
asturur Feb 15, 2022
b2e5c66
Update eraser_brush.mixin.js
ShaMan123 Feb 15, 2022
683fc2d
lint + comment out Map until proper js
ShaMan123 Feb 15, 2022
0a9e403
Update blendimage_filter.class.js
ShaMan123 Feb 15, 2022
1cebdd5
jsdoc
ShaMan123 Feb 15, 2022
7c05e4f
Update circle.class.js
ShaMan123 Feb 15, 2022
73b2b73
Update object.class.js
ShaMan123 Feb 15, 2022
938140f
jsdoc
ShaMan123 Feb 15, 2022
dc7429c
Update canvas_serialization.mixin.js
asturur Feb 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"browser": true
},
"globals": {
"ActiveXObject": true,
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
"Promise": true,
"define": true,
"eventjs": true,
"exports": true,
Expand Down
148 changes: 37 additions & 111 deletions src/mixins/canvas_serialization.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* Populates canvas with data from the specified JSON.
* JSON format must conform to the one of {@link fabric.Canvas#toJSON}
* @param {String|Object} json JSON string or object
* @param {Function} callback Callback, invoked when json is parsed
* and corresponding objects (e.g: {@link fabric.Image})
* are initialized
* @param {Function} [reviver] Method for further parsing of JSON elements, called after each fabric object created.
* @return {fabric.Canvas} instance
* @return {Promise<fabric.Canvas>} instance
* @chainable
* @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization}
* @see {@link http://jsfiddle.net/fabricjs/fmgXt/|jsFiddle demo}
* @example <caption>loadFromJSON</caption>
* canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
* canvas.loadFromJSON(json).then((canvas) => canvas.requestRenderAll());
* @example <caption>loadFromJSON with reviver</caption>
* canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(o, object) {
* canvas.loadFromJSON(json, function(o, object) {
* // `o` = json object
* // `object` = fabric.Object instance
* // ... do some stuff ...
* }).then((canvas) => {
* ... your canvas callback
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
* });
*/
loadFromJSON: function (json, callback, reviver) {
loadFromJSON: function (json, reviver) {
if (!json) {
return;
}
Expand All @@ -31,38 +30,36 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
: fabric.util.object.clone(json);

var _this = this,
clipPath = serialized.clipPath,
renderOnAddRemove = this.renderOnAddRemove;

this.renderOnAddRemove = false;

delete serialized.clipPath;

this._enlivenObjects(serialized.objects, function (enlivenedObjects) {
_this.clear();
_this._setBgOverlay(serialized, function () {
if (clipPath) {
_this._enlivenObjects([clipPath], function (enlivenedCanvasClip) {
_this.clipPath = enlivenedCanvasClip[0];
_this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);
return fabric.util.enlivenObjects(serialized.objects || [], '', reviver)
.then(function(enlived) {
_this.clear();
return fabric.util.enlivenObjectEnlivables({
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
backgroundImage: serialized.backgroundImage,
backgroundColor: serialized.background,
overlayImage: serialized.overlayImage,
overlayColor: serialized.overlay,
clipPath: serialized.clipPath,
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
})
.then(function(enlivedMap) {
_this.set(enlivedMap);
_this.__setupCanvas(serialized, enlived, renderOnAddRemove);
return _this;
});
}
else {
_this.__setupCanvas.call(_this, serialized, enlivenedObjects, renderOnAddRemove, callback);
}
});
}, reviver);
return this;
},

/**
* @private
* @param {Object} serialized Object with background and overlay information
* @param {Array} restored canvas objects
* @param {Function} cached renderOnAddRemove callback
* @param {Function} callback Invoked after all background and overlay images/patterns loaded
* @param {Array} enlivenedObjects canvas objects
* @param {boolean} renderOnAddRemove renderOnAddRemove setting for the canvas
*/
__setupCanvas: function(serialized, enlivenedObjects, renderOnAddRemove, callback) {
__setupCanvas: function(serialized, enlivenedObjects, renderOnAddRemove) {
var _this = this;
enlivenedObjects.forEach(function(obj, index) {
// we splice the array just in case some custom classes restored from JSON
Expand All @@ -81,86 +78,20 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
// create the Object instance. Here the Canvas is
// already an instance and we are just loading things over it
this._setOptions(serialized);
this.renderAll();
callback && callback();
},

/**
* @private
* @param {Object} serialized Object with background and overlay information
* @param {Function} callback Invoked after all background and overlay images/patterns loaded
*/
_setBgOverlay: function(serialized, callback) {
var loaded = {
backgroundColor: false,
overlayColor: false,
backgroundImage: false,
overlayImage: false
};

if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {
callback && callback();
return;
}

var cbIfLoaded = function () {
if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {
callback && callback();
}
};

this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);
this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);
this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);
this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);
},

/**
* @private
* @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)
* @param {String} property Property to set (backgroundColor, overlayColor)
* @param {(Object|String)} value Value to set
* @param {Object} loaded Set loaded property to true if property is set
* @param {Object} callback Callback function to invoke after property is set
*/
__setBgOverlay: function(property, value, loaded, callback) {
__setBgOverlay: function(property, value) {
var _this = this;

if (!value) {
loaded[property] = true;
callback && callback();
return;
}

if (property === 'backgroundImage' || property === 'overlayImage') {
fabric.util.enlivenObjects([value], function(enlivedObject){
_this[property] = enlivedObject[0];
loaded[property] = true;
callback && callback();
});
}
else {
this['set' + fabric.util.string.capitalize(property, true)](value, function() {
loaded[property] = true;
callback && callback();
});
}
},

/**
* @private
* @param {Array} objects
* @param {Function} callback
* @param {Function} [reviver]
*/
_enlivenObjects: function (objects, callback, reviver) {
if (!objects || objects.length === 0) {
callback && callback([]);
return;
}

fabric.util.enlivenObjects(objects, function(enlivenedObjects) {
callback && callback(enlivenedObjects);
}, null, reviver);
this['set' + fabric.util.string.capitalize(property, true)](value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

},

/**
Expand Down Expand Up @@ -190,13 +121,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* Clones canvas instance
* @param {Object} [callback] Receives cloned instance as a first argument
* @param {Array} [properties] Array of properties to include in the cloned canvas and children
* @returns {Promise<fabric.Canvas>}
*/
clone: function (callback, properties) {
clone: function (properties) {
var data = JSON.stringify(this.toJSON(properties));
this.cloneWithoutData(function(clone) {
clone.loadFromJSON(data, function() {
callback && callback(clone);
});
return this.cloneWithoutData().then(function(clone) {
return clone.loadFromJSON(data);
});
},

Expand All @@ -205,24 +135,20 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* This essentially copies canvas dimensions, clipping properties, etc.
* but leaves data empty (so that you can populate it with your own)
* @param {Object} [callback] Receives cloned instance as a first argument
* @returns {Promise<fabric.Canvas>}
*/
cloneWithoutData: function(callback) {
cloneWithoutData: function() {
var el = fabric.util.createCanvasElement();

el.width = this.width;
el.height = this.height;

// this seems wrong. either Canvas or StaticCanvas
var clone = new fabric.Canvas(el);
if (this.backgroundImage) {
clone.setBackgroundImage(this.backgroundImage.src, function() {
clone.renderAll();
callback && callback(clone);
});
clone.backgroundImageOpacity = this.backgroundImageOpacity;
clone.backgroundImageStretch = this.backgroundImageStretch;
}
else {
callback && callback(clone);
// TODO verify this
clone.setBackgroundImage(this.backgroundImage.src);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should error, so we miss a test.

return Promise.resolve(clone);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return Promise.resolve(clone);

redundant

}
return Promise.resolve(clone);
}
});
26 changes: 0 additions & 26 deletions src/mixins/shared_methods.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,6 @@ fabric.CommonMethods = {
}
},

/**
* @private
* @param {Object} [filler] Options object
* @param {String} [property] property to set the Gradient to
*/
_initGradient: function(filler, property) {
if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {
this.set(property, new fabric.Gradient(filler));
}
},

/**
* @private
* @param {Object} [filler] Options object
* @param {String} [property] property to set the Pattern to
* @param {Function} [callback] callback to invoke after pattern load
*/
_initPattern: function(filler, property, callback) {
if (filler && filler.source && !(filler instanceof fabric.Pattern)) {
this.set(property, new fabric.Pattern(filler, callback));
}
else {
callback && callback();
}
},

/**
* @private
*/
Expand Down
28 changes: 13 additions & 15 deletions src/pattern.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,19 @@
*/
patternTransform: null,

type: 'pattern',

/**
* Constructor
* @param {Object} [options] Options object
* @param {option.source} [source] the pattern source, eventually empty or a drawable
* @param {Function} [callback] function to invoke after callback init.
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
* @return {fabric.Pattern} thisArg
*/
initialize: function(options, callback) {
initialize: function(options) {
options || (options = { });

this.id = fabric.Object.__uid++;
this.setOptions(options);
if (!options.source || (options.source && typeof options.source !== 'string')) {
callback && callback(this);
return;
}
else {
// img src string
var _this = this;
this.source = fabric.util.createImage();
fabric.util.loadImage(options.source, function(img, isError) {
_this.source = img;
callback && callback(_this, isError);
}, null, this.crossOrigin);
}
},

/**
Expand Down Expand Up @@ -186,4 +175,13 @@
return ctx.createPattern(source, this.repeat);
}
});

fabric.Pattern.fromObject = function(object) {
var patternOptions = Object.assign({}, object);
return fabric.util.loadImage(object.source, { crossOrigin: object.crossOrigin })
.then(function(img) {
patternOptions.source = img;
return new fabric.Pattern(patternOptions);
});
};
})();
12 changes: 7 additions & 5 deletions src/shapes/active_selection.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,14 @@
* @static
* @memberOf fabric.ActiveSelection
* @param {Object} object Object to create a group from
* @param {Function} [callback] Callback to invoke when an ActiveSelection instance is created
* @returns {Promise<fabric.ActiveSelection>}
*/
fabric.ActiveSelection.fromObject = function(object, callback) {
fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {
delete object.objects;
callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true));
fabric.ActiveSelection.fromObject = function(object) {
var objects = object.objects,
options = fabric.util.object.clone(object, true);
delete options.objects;
return fabric.util.enlivenObjects(objects).then(function(enlivenedObjects) {
return new fabric.ActiveSelection(enlivenedObjects, object, true);
});
};

Expand Down
6 changes: 3 additions & 3 deletions src/shapes/circle.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@
* @memberOf fabric.Circle
* @param {Object} object Object to create an instance from
* @param {function} [callback] invoked with new instance as first argument
* @return {void}
* @returns {Promise<fabric.Circle>}
*/
fabric.Circle.fromObject = function(object, callback) {
fabric.Object._fromObject('Circle', object, callback);
fabric.Circle.fromObject = function(object) {
return fabric.Object._fromObject('Circle', object);
};

})(typeof exports !== 'undefined' ? exports : this);
7 changes: 3 additions & 4 deletions src/shapes/ellipse.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,10 @@
* @static
* @memberOf fabric.Ellipse
* @param {Object} object Object to create an instance from
* @param {function} [callback] invoked with new instance as first argument
* @return {void}
* @returns {Promise<fabric.Ellipse>}
*/
fabric.Ellipse.fromObject = function(object, callback) {
fabric.Object._fromObject('Ellipse', object, callback);
fabric.Ellipse.fromObject = function(object) {
return fabric.Object._fromObject('Ellipse', object);
};

})(typeof exports !== 'undefined' ? exports : this);
23 changes: 5 additions & 18 deletions src/shapes/group.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -559,27 +559,14 @@
* @static
* @memberOf fabric.Group
* @param {Object} object Object to create a group from
* @param {Function} [callback] Callback to invoke when an group instance is created
* @returns {Promise<fabric.Group>}
*/
fabric.Group.fromObject = function(object, callback) {
var objects = object.objects,
fabric.Group.fromObject = function(object) {
var objects = object.objects || [],
options = fabric.util.object.clone(object, true);
delete options.objects;
if (typeof objects === 'string') {
// it has to be an url or something went wrong.
fabric.loadSVGFromURL(objects, function (elements) {
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
var group = fabric.util.groupSVGElements(elements, object, objects);
group.set(options);
callback && callback(group);
});
return;
}
fabric.util.enlivenObjects(objects, function (enlivenedObjects) {
var options = fabric.util.object.clone(object, true);
delete options.objects;
fabric.util.enlivenObjectEnlivables(object, options, function () {
callback && callback(new fabric.Group(enlivenedObjects, options, true));
});
return fabric.util.enlivenObjects(objects).then(function (enlivenedObjects) {
return new fabric.Group(enlivenedObjects, options, true);
});
};

Expand Down
Loading