build dists

This commit is contained in:
Asturur 2016-08-28 22:52:27 +02:00
parent bba8b3a705
commit 0fd9754c44
4 changed files with 377 additions and 234 deletions

387
dist/fabric.js vendored
View file

@ -282,7 +282,6 @@ fabric.Collection = {
* @param {Function} callback
* Callback invoked with current object as first argument,
* index - as second and an array of all objects - as third.
* Iteration happens in reverse order (for performance reasons).
* Callback is invoked in a context of Global Object (e.g. `window`)
* when no `context` argument is given
*
@ -291,9 +290,8 @@ fabric.Collection = {
* @chainable
*/
forEachObject: function(callback, context) {
var objects = this.getObjects(),
i = objects.length;
while (i--) {
var objects = this.getObjects();
for (var i = 0, len = objects.length; i < len; i++) {
callback.call(context, objects[i], i, objects);
}
return this;
@ -380,7 +378,7 @@ fabric.Collection = {
* @static
* @memberOf fabric.util
* @param {Array} array
* @param {Any} value
* @param {*} value
* @return {Array} original array
*/
removeFromArray: function(array, value) {
@ -536,6 +534,7 @@ fabric.Collection = {
* Converts from attribute value to pixel value if applicable.
* Returns converted pixels or original value not converted.
* @param {Number|String} value number to operate on
* @param {Number} fontSize
* @return {Number|String}
*/
parseUnit: function(value, fontSize) {
@ -618,7 +617,7 @@ fabric.Collection = {
* @memberOf fabric.util
* @param {String} url URL representing an image
* @param {Function} callback Callback; invoked with loaded image
* @param {Any} [context] Context to invoke callback in
* @param {*} [context] Context to invoke callback in
* @param {Object} [crossOrigin] crossOrigin value to set image element to
*/
loadImage: function(url, callback, context, crossOrigin) {
@ -711,6 +710,7 @@ fabric.Collection = {
* @memberOf fabric.util
* @param {Array} elements SVG elements to group
* @param {Object} [options] Options object
* @param {String} path Value to set sourcePath to
* @return {fabric.Object|fabric.PathGroup}
*/
groupSVGElements: function(elements, options, path) {
@ -1291,8 +1291,7 @@ fabric.Collection = {
if (!Array.prototype.indexOf) {
/**
* Finds index of an element in an array
* @param {Any} searchElement
* @param {Number} [fromIndex]
* @param {*} searchElement
* @return {Number}
*/
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
@ -1419,8 +1418,7 @@ fabric.Collection = {
/**
* Returns "folded" (reduced) result of iterating over elements in an array
* @param {Function} fn Callback to invoke for each element
* @param {Object} [initial] Object to use as the first argument to the first call of the callback
* @return {Any}
* @return {*}
*/
Array.prototype.reduce = function(fn /*, initial*/) {
var len = this.length >>> 0,
@ -1474,7 +1472,7 @@ fabric.Collection = {
* @memberOf fabric.util.array
* @param {Array} array Array to iterate over
* @param {String} byProperty
* @return {Any}
* @return {*}
*/
function max(array, byProperty) {
return find(array, byProperty, function(value1, value2) {
@ -1487,7 +1485,7 @@ fabric.Collection = {
* @memberOf fabric.util.array
* @param {Array} array Array to iterate over
* @param {String} byProperty
* @return {Any}
* @return {*}
*/
function min(array, byProperty) {
return find(array, byProperty, function(value1, value2) {
@ -2467,13 +2465,13 @@ fabric.Collection = {
/**
* Wrapper around `console.log` (when available)
* @param {Any} [values] Values to log
* @param {*} [values] Values to log
*/
fabric.log = function() { };
/**
* Wrapper around `console.warn` (when available)
* @param {Any} [values] Values to log as a warning
* @param {*} [values] Values to log as a warning
*/
fabric.warn = function() { };
@ -4391,13 +4389,13 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
* Returns new point which is the result of linear interpolation with this one and another one
* @param {fabric.Point} that
* @param {Number} t , position of interpolation, between 0 and 1 default 0.5
* TODO: lock t between 0 and 1 in fabric 2.0
* @return {fabric.Point}
*/
lerp: function (that, t) {
if (typeof t === 'undefined') {
t = 0.5;
}
t = Math.max(Math.min(1, t), 0);
return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);
},
@ -4967,12 +4965,12 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/;
/**
* Regex matching color in HEX format (ex: #FF5555, 010155, aff)
* Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff)
* @static
* @field
* @memberOf fabric.Color
*/
fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i;
fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;
/**
* Map of the 17 basic color names with HEX code
@ -5039,7 +5037,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
};
/**
* Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format
* Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format
* @memberOf fabric.Color
* @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)
* @return {Array} source
@ -5081,7 +5079,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
};
/**
* Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.
* Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.
* Adapted from <a href="https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html">https://github.com/mjijackson</a>
* @memberOf fabric.Color
* @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)
@ -5141,25 +5139,27 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
};
/**
* Returns array represenatation (ex: [100, 100, 200, 1]) of a color that's in HEX format
* Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format
* @static
* @memberOf fabric.Color
* @param {String} color ex: FF5555
* @param {String} color ex: FF5555 or FF5544CC (RGBa)
* @return {Array} source
*/
fabric.Color.sourceFromHex = function(color) {
if (color.match(Color.reHex)) {
var value = color.slice(color.indexOf('#') + 1),
isShortNotation = (value.length === 3),
isShortNotation = (value.length === 3 || value.length === 4),
isRGBa = (value.length === 8 || value.length === 4),
r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),
g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),
b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6);
b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6),
a = isRGBa ? (isShortNotation ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF';
return [
parseInt(r, 16),
parseInt(g, 16),
parseInt(b, 16),
1
parseFloat((parseInt(a, 16) / 255).toFixed(2))
];
}
};
@ -5344,7 +5344,6 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
/**
* Returns SVG representation of an gradient
* @param {Object} object Object to create a gradient for
* @param {Boolean} normalize Whether coords should be normalized
* @return {String} SVG representation of an gradient (linear/radial)
*/
toSVG: function(object) {
@ -5421,6 +5420,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
/**
* Returns an instance of CanvasGradient
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Object} object
* @return {CanvasGradient}
*/
toLive: function(ctx, object) {
@ -6180,6 +6180,14 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
return (fabric.devicePixelRatio !== 1 && this.enableRetinaScaling);
},
/**
* @private
* @return {Number} retinaScaling if applied, otherwise 1;
*/
getRetinaScaling: function() {
return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
},
/**
* @private
*/
@ -7869,8 +7877,6 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
/**
* Converts points to SVG path
* @param {Array} points Array of points
* @param {Number} minX
* @param {Number} minY
* @return {String} SVG path
*/
convertPointsToSVGPath: function(points) {
@ -8629,7 +8635,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Renders both the top canvas and the secondary container canvas.
* @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas
* @return {fabric.Canvas} instance
* @chainable
*/
@ -8665,7 +8670,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Resets the current transform to its original values and chooses the type of resizing based on the event
* @private
* @param {Event} e Event object fired on mousemove
*/
_resetCurrentTransform: function() {
var t = this._currentTransform;
@ -9453,6 +9457,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Returns pointer coordinates relative to canvas.
* @param {Event} e
* @param {Boolean} ignoreZoom
* @return {Object} object with "x" and "y" number values
*/
getPointer: function (e, ignoreZoom, upperCanvasEl) {
@ -9631,7 +9636,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
if (this.getActiveObject() === obj) {
this.fire('before:selection:cleared', { target: obj });
this._discardActiveObject();
this.fire('selection:cleared');
this.fire('selection:cleared', { target: obj });
obj.fire('deselected');
}
this.callSuper('_onObjectRemoved', obj);
},
@ -9647,14 +9653,17 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
},
/**
* Discards currently active object
* Discards currently active object and fire events
* @param {event} e
* @return {fabric.Canvas} thisArg
* @chainable
*/
discardActiveObject: function (e) {
var activeObject = this._activeObject;
this.fire('before:selection:cleared', { target: activeObject, e: e });
this._discardActiveObject();
this.renderAll();
this.fire('selection:cleared', { e: e });
activeObject && activeObject.fire('deselected', { e: e });
return this;
},
@ -9672,6 +9681,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Sets active group to a specified one
* @param {fabric.Group} group Group to set as a current one
* @param {Event} e Event object
* @return {fabric.Canvas} thisArg
* @chainable
*/
@ -9704,10 +9714,13 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
},
/**
* Discards currently active group
* Discards currently active group and fire events
* @return {fabric.Canvas} thisArg
* @chainable
*/
discardActiveGroup: function (e) {
var g = this.getActiveGroup();
this.fire('before:selection:cleared', { e: e, target: g });
this._discardActiveGroup();
this.fire('selection:cleared', { e: e });
return this;
@ -9716,6 +9729,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Deactivates all objects on canvas, removing any active group or object
* @return {fabric.Canvas} thisArg
* @chainable
*/
deactivateAll: function () {
var allObjects = this.getObjects(),
@ -9732,15 +9746,18 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Deactivates all objects and dispatches appropriate events
* @return {fabric.Canvas} thisArg
* @chainable
*/
deactivateAllWithDispatch: function (e) {
var activeObject = this.getActiveGroup() || this.getActiveObject();
if (activeObject) {
this.fire('before:selection:cleared', { target: activeObject, e: e });
var activeGroup = this.getActiveGroup(),
activeObject = this.getActiveObject();
if (activeObject || activeGroup) {
this.fire('before:selection:cleared', { target: activeObject || activeGroup, e: e });
}
this.deactivateAll();
if (activeObject) {
this.fire('selection:cleared', { e: e });
if (activeObject || activeGroup) {
this.fire('selection:cleared', { e: e, target: activeObject });
activeObject && activeObject.fire('deselected');
}
return this;
},
@ -9874,8 +9891,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
// mouse events
addListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);
addListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);
addListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel);
addListener(this.upperCanvasEl, 'mouseout', this._onMouseOut);
addListener(this.upperCanvasEl, 'wheel', this._onMouseWheel);
// touch events
addListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);
@ -9915,8 +9932,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
removeListener(this.upperCanvasEl, 'mousedown', this._onMouseDown);
removeListener(this.upperCanvasEl, 'mousemove', this._onMouseMove);
removeListener(this.upperCanvasEl, 'mousewheel', this._onMouseWheel);
removeListener(this.upperCanvasEl, 'mouseout', this._onMouseOut);
removeListener(this.upperCanvasEl, 'wheel', this._onMouseWheel);
removeListener(this.upperCanvasEl, 'touchstart', this._onMouseDown);
removeListener(this.upperCanvasEl, 'touchmove', this._onMouseMove);
@ -9950,11 +9967,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* @private
* @param {Event} [e] Event object fired on Event.js wheel event
* @param {Event} [self] Inner Event object
* @param {Event} [e] Event object fired on wheel event
*/
_onMouseWheel: function(e, self) {
this.__onMouseWheel && this.__onMouseWheel(e, self);
_onMouseWheel: function(e) {
this.__onMouseWheel(e);
},
/**
@ -10418,6 +10434,16 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
this._handleEvent(e, 'move', target ? target : null);
},
/**
* Method that defines actions when an Event Mouse Wheel
* @param {Event} e Event object fired on mouseup
*/
__onMouseWheel: function(e) {
this.fire('mouse:wheel', {
e: e
});
},
/**
* @private
* @param {Event} e Event fired on mousemove
@ -11272,6 +11298,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @fires removed
*
* @fires selected
* @fires deselected
* @fires modified
* @fires rotating
* @fires scaling
@ -12194,7 +12221,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* Basic getter
* @param {String} property Property name
* @return {Any} value of a property
* @return {*} value of a property
*/
get: function(property) {
return this[property];
@ -12248,7 +12275,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* @private
* @param {String} key
* @param {Any} value
* @param {*} value
* @return {fabric.Object} thisArg
*/
_set: function(key, value) {
@ -14685,7 +14712,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {String} key
* @param {Any} value
* @param {*} value
*/
_set: function(key, value) {
this.callSuper('_set', key, value);
@ -14734,6 +14761,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
_render: function(ctx, noTransform) {
ctx.beginPath();
@ -14984,7 +15012,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {String} key
* @param {Any} value
* @param {*} value
* @return {fabric.Circle} thisArg
*/
_set: function(key, value) {
@ -15352,7 +15380,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {String} key
* @param {Any} value
* @param {*} value
* @return {fabric.Ellipse} thisArg
*/
_set: function(key, value) {
@ -15592,6 +15620,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
_render: function(ctx, noTransform) {
@ -15799,7 +15828,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* Constructor
* @param {Array} points Array of points (where each point is an object with x and y)
* @param {Object} [options] Options object
* @param {Boolean} [skipOffset] Whether points offsetting should be skipped
* @return {fabric.Polyline} thisArg
* @example
* var poly = new fabric.Polyline([
@ -15849,6 +15877,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
_render: function(ctx, noTransform) {
if (!fabric.Polygon.prototype.commonRender.call(this, ctx, noTransform)) {
@ -16062,6 +16091,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
_render: function(ctx, noTransform) {
if (!this.commonRender(ctx, noTransform)) {
@ -16077,6 +16107,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
commonRender: function(ctx, noTransform) {
var point, len = this.points.length;
@ -17261,7 +17292,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* Sets certain property to a certain value
* @param {String} prop
* @param {Any} value
* @param {*} value
* @return {fabric.PathGroup} thisArg
*/
_set: function(prop, value) {
@ -17909,7 +17940,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* Returns requested property
* @param {String} prop Property to get
* @return {Any}
* @return {*}
*/
get: function(prop) {
if (prop in _lockProperties) {
@ -18051,18 +18082,28 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
*/
_lastScaleY: 1,
/**
* minimum scale factor under which any resizeFilter is triggered to resize the image
* 0 will disable the automatic resize. 1 will trigger automatically always.
* number bigger than 1 can be used in case we want to scale with some filter above
* the natural image dimensions
* @type Number
*/
minimumScaleTrigger: 0.5,
/**
* Constructor
* @param {HTMLImageElement | String} element Image element
* @param {Object} [options] Options object
* @param {function} [callback] callback function to call after eventual filters applied.
* @return {fabric.Image} thisArg
*/
initialize: function(element, options) {
initialize: function(element, options, callback) {
options || (options = { });
this.filters = [ ];
this.resizeFilters = [ ];
this.callSuper('initialize', options);
this._initElement(element, options);
this._initElement(element, options, callback);
},
/**
@ -18084,15 +18125,28 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @chainable
*/
setElement: function(element, callback, options) {
var _callback, _this;
this._element = element;
this._originalElement = element;
this._initConfig(options);
if (this.filters.length !== 0) {
this.applyFilters(callback);
if (this.resizeFilters.length === 0) {
_callback = callback;
}
else if (callback) {
callback();
else {
_this = this;
_callback = function() {
_this.applyFilters(callback, _this.resizeFilters, _this._filteredEl || _this._originalElement, true);
};
}
if (this.filters.length !== 0) {
this.applyFilters(_callback);
}
else if (_callback) {
_callback(this);
}
return this;
@ -18169,7 +18223,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
*/
toObject: function(propertiesToInclude) {
var filters = [ ], resizeFilters = [ ],
element = this._originalElement,
scaleX = 1, scaleY = 1;
this.filters.forEach(function(filterObj) {
@ -18187,7 +18240,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
});
var object = extend(this.callSuper('toObject', propertiesToInclude), {
src: element ? element.src || element._src : '',
src: this.getSrc(),
filters: filters,
resizeFilters: resizeFilters,
crossOrigin: this.crossOrigin,
@ -18260,8 +18313,12 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @return {String} Source of an image
*/
getSrc: function() {
if (this.getElement()) {
return this.getElement().src || this.getElement()._src;
var element = this._originalElement;
if (element) {
return fabric.isLikelyNode ? element._src : element.src;
}
else {
return this.src || '';
}
},
@ -18300,7 +18357,10 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* Applies filters assigned to this image (from "filters" array)
* @method applyFilters
* @param {Function} callback Callback is invoked when all filters have been applied and new image is generated
* @return {fabric.Image} thisArg
* @param {Array} filters to be applied
* @param {fabric.Image} imgElement image to filter ( default to this._element )
* @param {Boolean} forResizing
* @return {CanvasElement} canvasEl to be drawn immediately
* @chainable
*/
applyFilters: function(callback, filters, imgElement, forResizing) {
@ -18312,22 +18372,38 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
return;
}
var imgEl = imgElement,
canvasEl = fabric.util.createCanvasElement(),
replacement = fabric.util.createImage(),
_this = this;
canvasEl.width = imgEl.width;
canvasEl.height = imgEl.height;
canvasEl.getContext('2d').drawImage(imgEl, 0, 0, imgEl.width, imgEl.height);
var replacement = fabric.util.createImage(),
retinaScaling = this.canvas ? this.canvas.getRetinaScaling() : fabric.devicePixelRatio,
minimumScale = this.minimumScaleTrigger / retinaScaling,
_this = this, scaleX, scaleY;
if (filters.length === 0) {
this._element = imgElement;
callback && callback();
return canvasEl;
callback && callback(this);
return imgElement;
}
var canvasEl = fabric.util.createCanvasElement();
canvasEl.width = imgElement.width;
canvasEl.height = imgElement.height;
canvasEl.getContext('2d').drawImage(imgElement, 0, 0, imgElement.width, imgElement.height);
filters.forEach(function(filter) {
filter && filter.applyTo(canvasEl, filter.scaleX || _this.scaleX, filter.scaleY || _this.scaleY);
if (forResizing) {
scaleX = _this.scaleX < minimumScale ? _this.scaleX : 1;
scaleY = _this.scaleY < minimumScale ? _this.scaleY : 1;
if (scaleX * retinaScaling < 1) {
scaleX *= retinaScaling;
}
if (scaleY * retinaScaling < 1) {
scaleY *= retinaScaling;
}
}
else {
scaleX = filter.scaleX;
scaleY = filter.scaleY;
}
filter && filter.applyTo(canvasEl, scaleX, scaleY);
if (!forResizing && filter && filter.type === 'Resize') {
_this.width *= filter.scaleX;
_this.height *= filter.scaleY;
@ -18337,20 +18413,18 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/** @ignore */
replacement.width = canvasEl.width;
replacement.height = canvasEl.height;
if (fabric.isLikelyNode) {
replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);
// onload doesn't fire in some node versions, so we invoke callback manually
_this._element = replacement;
!forResizing && (_this._filteredEl = replacement);
callback && callback();
_this._element = replacement; // !forResizing && (_this._filteredEl = replacement);
callback && callback(_this);
}
else {
replacement.onload = function() {
_this._element = replacement;
!forResizing && (_this._filteredEl = replacement);
callback && callback();
replacement.onload = canvasEl = imgEl = null;
callback && callback(_this);
replacement.onload = canvasEl = null;
};
replacement.src = canvasEl.toDataURL('image/png');
}
@ -18360,6 +18434,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
_render: function(ctx, noTransform) {
var x, y, imageMargins = this._findMargins(), elementToDraw;
@ -18450,8 +18525,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @param {HTMLImageElement|String} element The element representing the image
* @param {Object} [options] Options object
*/
_initElement: function(element, options) {
this.setElement(fabric.util.getById(element), null, options);
_initElement: function(element, options, callback) {
this.setElement(fabric.util.getById(element), callback, options);
fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
},
@ -18537,8 +18612,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
object.filters = filters || [ ];
fabric.Image.prototype._initFilters.call(object, object.resizeFilters, function(resizeFilters) {
object.resizeFilters = resizeFilters || [ ];
var instance = new fabric.Image(img, object);
callback && callback(instance);
return new fabric.Image(img, object, callback);
});
});
}, null, object.crossOrigin);
@ -20150,8 +20224,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* Applies filter to canvas element
* @memberOf fabric.Image.filters.Resize.prototype
* @param {Object} canvasEl Canvas element to apply filter to
* @param {Number} scaleX
* @param {Number} scaleY
*/
applyTo: function(canvasEl, scaleX, scaleY) {
if (scaleX === 1 && scaleY === 1) {
return;
}
this.rcpScaleX = 1 / scaleX;
this.rcpScaleY = 1 / scaleY;
@ -20177,55 +20256,73 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
canvasEl.getContext('2d').putImageData(imageData, 0, 0);
},
sliceByTwo: function(canvasEl, width, height, newWidth, newHeight) {
/**
* Filter sliceByTwo
* @param {Object} canvasEl Canvas element to apply filter to
* @param {Number} oW Original Width
* @param {Number} oH Original Height
* @param {Number} dW Destination Width
* @param {Number} dH Destination Height
* @returns {ImageData}
*/
sliceByTwo: function(canvasEl, oW, oH, dW, dH) {
var context = canvasEl.getContext('2d'), imageData,
multW = 0.5, multH = 0.5, signW = 1, signH = 1,
doneW = false, doneH = false, stepW = width, stepH = height,
doneW = false, doneH = false, stepW = oW, stepH = oH,
tmpCanvas = fabric.util.createCanvasElement(),
tmpCtx = tmpCanvas.getContext('2d');
newWidth = floor(newWidth);
newHeight = floor(newHeight);
tmpCanvas.width = max(newWidth, width);
tmpCanvas.height = max(newHeight, height);
dW = floor(dW);
dH = floor(dH);
tmpCanvas.width = max(dW, oW);
tmpCanvas.height = max(dH, oH);
if (newWidth > width) {
if (dW > oW) {
multW = 2;
signW = -1;
}
if (newHeight > height) {
if (dH > oH) {
multH = 2;
signH = -1;
}
imageData = context.getImageData(0, 0, width, height);
canvasEl.width = max(newWidth, width);
canvasEl.height = max(newHeight, height);
imageData = context.getImageData(0, 0, oW, oH);
canvasEl.width = max(dW, oW);
canvasEl.height = max(dH, oH);
context.putImageData(imageData, 0, 0);
while (!doneW || !doneH) {
width = stepW;
height = stepH;
if (newWidth * signW < floor(stepW * multW * signW)) {
oW = stepW;
oH = stepH;
if (dW * signW < floor(stepW * multW * signW)) {
stepW = floor(stepW * multW);
}
else {
stepW = newWidth;
stepW = dW;
doneW = true;
}
if (newHeight * signH < floor(stepH * multH * signH)) {
if (dH * signH < floor(stepH * multH * signH)) {
stepH = floor(stepH * multH);
}
else {
stepH = newHeight;
stepH = dH;
doneH = true;
}
imageData = context.getImageData(0, 0, width, height);
imageData = context.getImageData(0, 0, oW, oH);
tmpCtx.putImageData(imageData, 0, 0);
context.clearRect(0, 0, stepW, stepH);
context.drawImage(tmpCanvas, 0, 0, width, height, 0, 0, stepW, stepH);
context.drawImage(tmpCanvas, 0, 0, oW, oH, 0, 0, stepW, stepH);
}
return context.getImageData(0, 0, newWidth, newHeight);
return context.getImageData(0, 0, dW, dH);
},
/**
* Filter lanczosResize
* @param {Object} canvasEl Canvas element to apply filter to
* @param {Number} oW Original Width
* @param {Number} oH Original Height
* @param {Number} dW Destination Width
* @param {Number} dH Destination Height
* @returns {ImageData}
*/
lanczosResize: function(canvasEl, oW, oH, dW, dH) {
function lanczosCreate(lobes) {
@ -20307,20 +20404,29 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
return process(0);
},
bilinearFiltering: function(canvasEl, w, h, w2, h2) {
/**
* bilinearFiltering
* @param {Object} canvasEl Canvas element to apply filter to
* @param {Number} oW Original Width
* @param {Number} oH Original Height
* @param {Number} dW Destination Width
* @param {Number} dH Destination Height
* @returns {ImageData}
*/
bilinearFiltering: function(canvasEl, oW, oH, dW, dH) {
var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl,
color, offset = 0, origPix, ratioX = this.rcpScaleX,
ratioY = this.rcpScaleY, context = canvasEl.getContext('2d'),
w4 = 4 * (w - 1), img = context.getImageData(0, 0, w, h),
pixels = img.data, destImage = context.getImageData(0, 0, w2, h2),
w4 = 4 * (oW - 1), img = context.getImageData(0, 0, oW, oH),
pixels = img.data, destImage = context.getImageData(0, 0, dW, dH),
destPixels = destImage.data;
for (i = 0; i < h2; i++) {
for (j = 0; j < w2; j++) {
for (i = 0; i < dH; i++) {
for (j = 0; j < dW; j++) {
x = floor(ratioX * j);
y = floor(ratioY * i);
xDiff = ratioX * j - x;
yDiff = ratioY * i - y;
origPix = 4 * (y * w + x);
origPix = 4 * (y * oW + x);
for (chnl = 0; chnl < 4; chnl++) {
a = pixels[origPix + chnl];
@ -20336,6 +20442,15 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
return destImage;
},
/**
* hermiteFastResize
* @param {Object} canvasEl Canvas element to apply filter to
* @param {Number} oW Original Width
* @param {Number} oH Original Height
* @param {Number} dW Destination Width
* @param {Number} dH Destination Height
* @returns {ImageData}
*/
hermiteFastResize: function(canvasEl, oW, oH, dW, dH) {
var ratioW = this.rcpScaleX, ratioH = this.rcpScaleY,
ratioWHalf = ceil(ratioW / 2),
@ -20531,7 +20646,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
extend = fabric.util.object.extend,
clone = fabric.util.object.clone,
toFixed = fabric.util.toFixed,
supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),
NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
if (fabric.Text) {
@ -20936,7 +21050,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @return {Number} Height of fabric.Text object
*/
_getTextHeight: function() {
@ -21085,6 +21198,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {String} method Method name ("fillText" or "strokeText")
*/
_renderTextCommon: function(ctx, method) {
@ -21133,15 +21247,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
}
ctx.save();
if (this.strokeDashArray) {
// Spec requires the concatenation of two copies the dash list when the number of elements is odd
if (1 & this.strokeDashArray.length) {
this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
}
supportsLineDash && ctx.setLineDash(this.strokeDashArray);
}
this._setLineDash(ctx, this.strokedashArray);
ctx.beginPath();
this._renderTextCommon(ctx, 'strokeText');
ctx.closePath();
@ -21167,7 +21273,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Array} textLines Array of all text lines
*/
_renderTextBackground: function(ctx) {
this._renderTextBoxBackground(ctx);
@ -21370,7 +21475,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
},
/**
* @private
* return font declaration string for canvas context
* @returns {String} font declaration formatted for canvas context.
*/
_getFontDeclaration: function() {
return [
@ -21378,13 +21484,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
(fabric.isLikelyNode ? this.fontWeight : this.fontStyle),
(fabric.isLikelyNode ? this.fontStyle : this.fontWeight),
this.fontSize + 'px',
(fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily)
'"' + this.fontFamily + '"'
].join(' ');
},
/**
* Renders text instance on a specified context
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
render: function(ctx, noTransform) {
// do not render if object is not visible
@ -21619,7 +21726,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1
*
* @private
* @param {Any} value
* @param {*} value
* @return {String}
*/
_getFillAttributes: function(value) {
@ -21634,7 +21741,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
/**
* Sets specified property to a specified value
* @param {String} key
* @param {Any} value
* @param {*} value
* @return {fabric.Text} thisArg
* @chainable
*/
@ -22352,6 +22459,11 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* @private
* @param {String} method
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {String} line Content of the line
* @param {Number} left
* @param {Number} top
* @param {Number} lineIndex
* @param {Number} charOffset
*/
_renderChars: function(method, ctx, line, left, top, lineIndex, charOffset) {
@ -22511,6 +22623,9 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* @param {String} method
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {String} line
* @param {Number} left
* @param {Number} top
* @param {Number} lineIndex
*/
_renderTextLine: function(method, ctx, line, left, top, lineIndex) {
// to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine
@ -22757,6 +22872,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Number} lineIndex
* @param {Number} charIndex
*/
_getHeightOfChar: function(ctx, lineIndex, charIndex) {
var style = this._getStyleDeclaration(lineIndex, charIndex);
@ -25159,7 +25276,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* the same font-size value would result in different actual size depending
* on the value of the scale.
* @param {String} key
* @param {Any} value
* @param {*} value
*/
setOnGroup: function(key, value) {
if (key === 'scaleX') {
@ -25608,20 +25725,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
});
};
fabric.Image.fromObject = function(object, callback) {
fabric.util.loadImage(object.src, function(img) {
var oImg = new fabric.Image(img);
// fabric.util.createCanvasElement = function(_, width, height) {
// return new Canvas(width, height);
// }
oImg._initConfig(object);
oImg._initFilters(object.filters, function(filters) {
oImg.filters = filters || [ ];
oImg._initFilters(object.resizeFilters, function(resizeFilters) {
oImg.resizeFilters = resizeFilters || [ ];
callback && callback(oImg);
});
});
});
};
/**
* Only available when running fabric on node.js
* @param {Number} width Canvas width

16
dist/fabric.min.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/fabric.min.js.gz vendored

Binary file not shown.

208
dist/fabric.require.js vendored
View file

@ -143,8 +143,8 @@ fabric.Collection = {
return this;
},
forEachObject: function(callback, context) {
var objects = this.getObjects(), i = objects.length;
while (i--) {
var objects = this.getObjects();
for (var i = 0, len = objects.length; i < len; i++) {
callback.call(context, objects[i], i, objects);
}
return this;
@ -2401,6 +2401,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
if (typeof t === "undefined") {
t = .5;
}
t = Math.max(Math.min(1, t), 0);
return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);
},
distanceFrom: function(that) {
@ -2661,7 +2662,7 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
};
fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/;
fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/;
fabric.Color.reHex = /^#?([0-9a-f]{6}|[0-9a-f]{3})$/i;
fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;
fabric.Color.colorNameMap = {
aqua: "#00FFFF",
black: "#000000",
@ -2736,8 +2737,8 @@ fabric.ElementsParser.prototype.checkIfDone = function() {
};
fabric.Color.sourceFromHex = function(color) {
if (color.match(Color.reHex)) {
var value = color.slice(color.indexOf("#") + 1), isShortNotation = value.length === 3, r = isShortNotation ? value.charAt(0) + value.charAt(0) : value.substring(0, 2), g = isShortNotation ? value.charAt(1) + value.charAt(1) : value.substring(2, 4), b = isShortNotation ? value.charAt(2) + value.charAt(2) : value.substring(4, 6);
return [ parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), 1 ];
var value = color.slice(color.indexOf("#") + 1), isShortNotation = value.length === 3 || value.length === 4, isRGBa = value.length === 8 || value.length === 4, r = isShortNotation ? value.charAt(0) + value.charAt(0) : value.substring(0, 2), g = isShortNotation ? value.charAt(1) + value.charAt(1) : value.substring(2, 4), b = isShortNotation ? value.charAt(2) + value.charAt(2) : value.substring(4, 6), a = isRGBa ? isShortNotation ? value.charAt(3) + value.charAt(3) : value.substring(6, 8) : "FF";
return [ parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), parseFloat((parseInt(a, 16) / 255).toFixed(2)) ];
}
};
fabric.Color.fromSource = function(source) {
@ -3185,6 +3186,9 @@ fabric.Pattern = fabric.util.createClass({
_isRetinaScaling: function() {
return fabric.devicePixelRatio !== 1 && this.enableRetinaScaling;
},
getRetinaScaling: function() {
return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
},
_initRetinaScaling: function() {
if (!this._isRetinaScaling()) {
return;
@ -4816,7 +4820,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
target: obj
});
this._discardActiveObject();
this.fire("selection:cleared");
this.fire("selection:cleared", {
target: obj
});
obj.fire("deselected");
}
this.callSuper("_onObjectRemoved", obj);
},
@ -4827,11 +4834,18 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
this._activeObject = null;
},
discardActiveObject: function(e) {
var activeObject = this._activeObject;
this.fire("before:selection:cleared", {
target: activeObject,
e: e
});
this._discardActiveObject();
this.renderAll();
this.fire("selection:cleared", {
e: e
});
activeObject && activeObject.fire("deselected", {
e: e
});
return this;
},
_setActiveGroup: function(group) {
@ -4864,6 +4878,11 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
this.setActiveGroup(null);
},
discardActiveGroup: function(e) {
var g = this.getActiveGroup();
this.fire("before:selection:cleared", {
e: e,
target: g
});
this._discardActiveGroup();
this.fire("selection:cleared", {
e: e
@ -4880,18 +4899,20 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
return this;
},
deactivateAllWithDispatch: function(e) {
var activeObject = this.getActiveGroup() || this.getActiveObject();
if (activeObject) {
var activeGroup = this.getActiveGroup(), activeObject = this.getActiveObject();
if (activeObject || activeGroup) {
this.fire("before:selection:cleared", {
target: activeObject,
target: activeObject || activeGroup,
e: e
});
}
this.deactivateAll();
if (activeObject) {
if (activeObject || activeGroup) {
this.fire("selection:cleared", {
e: e
e: e,
target: activeObject
});
activeObject && activeObject.fire("deselected");
}
return this;
},
@ -4960,8 +4981,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
addListener(fabric.window, "resize", this._onResize);
addListener(this.upperCanvasEl, "mousedown", this._onMouseDown);
addListener(this.upperCanvasEl, "mousemove", this._onMouseMove);
addListener(this.upperCanvasEl, "mousewheel", this._onMouseWheel);
addListener(this.upperCanvasEl, "mouseout", this._onMouseOut);
addListener(this.upperCanvasEl, "wheel", this._onMouseWheel);
addListener(this.upperCanvasEl, "touchstart", this._onMouseDown);
addListener(this.upperCanvasEl, "touchmove", this._onMouseMove);
if (typeof eventjs !== "undefined" && "add" in eventjs) {
@ -4989,8 +5010,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
removeListener(fabric.window, "resize", this._onResize);
removeListener(this.upperCanvasEl, "mousedown", this._onMouseDown);
removeListener(this.upperCanvasEl, "mousemove", this._onMouseMove);
removeListener(this.upperCanvasEl, "mousewheel", this._onMouseWheel);
removeListener(this.upperCanvasEl, "mouseout", this._onMouseOut);
removeListener(this.upperCanvasEl, "wheel", this._onMouseWheel);
removeListener(this.upperCanvasEl, "touchstart", this._onMouseDown);
removeListener(this.upperCanvasEl, "touchmove", this._onMouseMove);
if (typeof eventjs !== "undefined" && "remove" in eventjs) {
@ -5007,8 +5028,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
_onDrag: function(e, self) {
this.__onDrag && this.__onDrag(e, self);
},
_onMouseWheel: function(e, self) {
this.__onMouseWheel && this.__onMouseWheel(e, self);
_onMouseWheel: function(e) {
this.__onMouseWheel(e);
},
_onMouseOut: function(e) {
var target = this._hoveredTarget;
@ -5257,6 +5278,11 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, {
}
this._handleEvent(e, "move", target ? target : null);
},
__onMouseWheel: function(e) {
this.fire("mouse:wheel", {
e: e
});
},
_transformObject: function(e) {
var pointer = this.getPointer(e), transform = this._currentTransform;
transform.reset = false, transform.target.isMoving = true;
@ -8609,24 +8635,34 @@ fabric.util.object.extend(fabric.Object.prototype, {
strokeWidth: 0,
_lastScaleX: 1,
_lastScaleY: 1,
initialize: function(element, options) {
minimumScaleTrigger: .5,
initialize: function(element, options, callback) {
options || (options = {});
this.filters = [];
this.resizeFilters = [];
this.callSuper("initialize", options);
this._initElement(element, options);
this._initElement(element, options, callback);
},
getElement: function() {
return this._element;
},
setElement: function(element, callback, options) {
var _callback, _this;
this._element = element;
this._originalElement = element;
this._initConfig(options);
if (this.resizeFilters.length === 0) {
_callback = callback;
} else {
_this = this;
_callback = function() {
_this.applyFilters(callback, _this.resizeFilters, _this._filteredEl || _this._originalElement, true);
};
}
if (this.filters.length !== 0) {
this.applyFilters(callback);
} else if (callback) {
callback();
this.applyFilters(_callback);
} else if (_callback) {
_callback(this);
}
return this;
},
@ -8668,7 +8704,7 @@ fabric.util.object.extend(fabric.Object.prototype, {
ctx.restore();
},
toObject: function(propertiesToInclude) {
var filters = [], resizeFilters = [], element = this._originalElement, scaleX = 1, scaleY = 1;
var filters = [], resizeFilters = [], scaleX = 1, scaleY = 1;
this.filters.forEach(function(filterObj) {
if (filterObj) {
if (filterObj.type === "Resize") {
@ -8682,7 +8718,7 @@ fabric.util.object.extend(fabric.Object.prototype, {
filterObj && resizeFilters.push(filterObj.toObject());
});
var object = extend(this.callSuper("toObject", propertiesToInclude), {
src: element ? element.src || element._src : "",
src: this.getSrc(),
filters: filters,
resizeFilters: resizeFilters,
crossOrigin: this.crossOrigin,
@ -8717,8 +8753,11 @@ fabric.util.object.extend(fabric.Object.prototype, {
return reviver ? reviver(markup.join("")) : markup.join("");
},
getSrc: function() {
if (this.getElement()) {
return this.getElement().src || this.getElement()._src;
var element = this._originalElement;
if (element) {
return fabric.isLikelyNode ? element._src : element.src;
} else {
return this.src || "";
}
},
setSrc: function(src, callback, options) {
@ -8738,17 +8777,31 @@ fabric.util.object.extend(fabric.Object.prototype, {
if (!imgElement) {
return;
}
var imgEl = imgElement, canvasEl = fabric.util.createCanvasElement(), replacement = fabric.util.createImage(), _this = this;
canvasEl.width = imgEl.width;
canvasEl.height = imgEl.height;
canvasEl.getContext("2d").drawImage(imgEl, 0, 0, imgEl.width, imgEl.height);
var replacement = fabric.util.createImage(), retinaScaling = this.canvas ? this.canvas.getRetinaScaling() : fabric.devicePixelRatio, minimumScale = this.minimumScaleTrigger / retinaScaling, _this = this, scaleX, scaleY;
if (filters.length === 0) {
this._element = imgElement;
callback && callback();
return canvasEl;
callback && callback(this);
return imgElement;
}
var canvasEl = fabric.util.createCanvasElement();
canvasEl.width = imgElement.width;
canvasEl.height = imgElement.height;
canvasEl.getContext("2d").drawImage(imgElement, 0, 0, imgElement.width, imgElement.height);
filters.forEach(function(filter) {
filter && filter.applyTo(canvasEl, filter.scaleX || _this.scaleX, filter.scaleY || _this.scaleY);
if (forResizing) {
scaleX = _this.scaleX < minimumScale ? _this.scaleX : 1;
scaleY = _this.scaleY < minimumScale ? _this.scaleY : 1;
if (scaleX * retinaScaling < 1) {
scaleX *= retinaScaling;
}
if (scaleY * retinaScaling < 1) {
scaleY *= retinaScaling;
}
} else {
scaleX = filter.scaleX;
scaleY = filter.scaleY;
}
filter && filter.applyTo(canvasEl, scaleX, scaleY);
if (!forResizing && filter && filter.type === "Resize") {
_this.width *= filter.scaleX;
_this.height *= filter.scaleY;
@ -8759,14 +8812,13 @@ fabric.util.object.extend(fabric.Object.prototype, {
if (fabric.isLikelyNode) {
replacement.src = canvasEl.toBuffer(undefined, fabric.Image.pngCompression);
_this._element = replacement;
!forResizing && (_this._filteredEl = replacement);
callback && callback();
callback && callback(_this);
} else {
replacement.onload = function() {
_this._element = replacement;
!forResizing && (_this._filteredEl = replacement);
callback && callback();
replacement.onload = canvasEl = imgEl = null;
callback && callback(_this);
replacement.onload = canvasEl = null;
};
replacement.src = canvasEl.toDataURL("image/png");
}
@ -8827,8 +8879,8 @@ fabric.util.object.extend(fabric.Object.prototype, {
this.set("width", element.width);
this.set("height", element.height);
},
_initElement: function(element, options) {
this.setElement(fabric.util.getById(element), null, options);
_initElement: function(element, options, callback) {
this.setElement(fabric.util.getById(element), callback, options);
fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
},
_initConfig: function(options) {
@ -8864,8 +8916,7 @@ fabric.util.object.extend(fabric.Object.prototype, {
object.filters = filters || [];
fabric.Image.prototype._initFilters.call(object, object.resizeFilters, function(resizeFilters) {
object.resizeFilters = resizeFilters || [];
var instance = new fabric.Image(img, object);
callback && callback(instance);
return new fabric.Image(img, object, callback);
});
});
}, null, object.crossOrigin);
@ -9484,6 +9535,9 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
scaleY: 0,
lanczosLobes: 3,
applyTo: function(canvasEl, scaleX, scaleY) {
if (scaleX === 1 && scaleY === 1) {
return;
}
this.rcpScaleX = 1 / scaleX;
this.rcpScaleY = 1 / scaleY;
var oW = canvasEl.width, oH = canvasEl.height, dW = round(oW * scaleX), dH = round(oH * scaleY), imageData;
@ -9503,45 +9557,45 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
canvasEl.height = dH;
canvasEl.getContext("2d").putImageData(imageData, 0, 0);
},
sliceByTwo: function(canvasEl, width, height, newWidth, newHeight) {
var context = canvasEl.getContext("2d"), imageData, multW = .5, multH = .5, signW = 1, signH = 1, doneW = false, doneH = false, stepW = width, stepH = height, tmpCanvas = fabric.util.createCanvasElement(), tmpCtx = tmpCanvas.getContext("2d");
newWidth = floor(newWidth);
newHeight = floor(newHeight);
tmpCanvas.width = max(newWidth, width);
tmpCanvas.height = max(newHeight, height);
if (newWidth > width) {
sliceByTwo: function(canvasEl, oW, oH, dW, dH) {
var context = canvasEl.getContext("2d"), imageData, multW = .5, multH = .5, signW = 1, signH = 1, doneW = false, doneH = false, stepW = oW, stepH = oH, tmpCanvas = fabric.util.createCanvasElement(), tmpCtx = tmpCanvas.getContext("2d");
dW = floor(dW);
dH = floor(dH);
tmpCanvas.width = max(dW, oW);
tmpCanvas.height = max(dH, oH);
if (dW > oW) {
multW = 2;
signW = -1;
}
if (newHeight > height) {
if (dH > oH) {
multH = 2;
signH = -1;
}
imageData = context.getImageData(0, 0, width, height);
canvasEl.width = max(newWidth, width);
canvasEl.height = max(newHeight, height);
imageData = context.getImageData(0, 0, oW, oH);
canvasEl.width = max(dW, oW);
canvasEl.height = max(dH, oH);
context.putImageData(imageData, 0, 0);
while (!doneW || !doneH) {
width = stepW;
height = stepH;
if (newWidth * signW < floor(stepW * multW * signW)) {
oW = stepW;
oH = stepH;
if (dW * signW < floor(stepW * multW * signW)) {
stepW = floor(stepW * multW);
} else {
stepW = newWidth;
stepW = dW;
doneW = true;
}
if (newHeight * signH < floor(stepH * multH * signH)) {
if (dH * signH < floor(stepH * multH * signH)) {
stepH = floor(stepH * multH);
} else {
stepH = newHeight;
stepH = dH;
doneH = true;
}
imageData = context.getImageData(0, 0, width, height);
imageData = context.getImageData(0, 0, oW, oH);
tmpCtx.putImageData(imageData, 0, 0);
context.clearRect(0, 0, stepW, stepH);
context.drawImage(tmpCanvas, 0, 0, width, height, 0, 0, stepW, stepH);
context.drawImage(tmpCanvas, 0, 0, oW, oH, 0, 0, stepW, stepH);
}
return context.getImageData(0, 0, newWidth, newHeight);
return context.getImageData(0, 0, dW, dH);
},
lanczosResize: function(canvasEl, oW, oH, dW, dH) {
function lanczosCreate(lobes) {
@ -9607,15 +9661,15 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
var context = canvasEl.getContext("2d"), srcImg = context.getImageData(0, 0, oW, oH), destImg = context.getImageData(0, 0, dW, dH), srcData = srcImg.data, destData = destImg.data, lanczos = lanczosCreate(this.lanczosLobes), ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, rcpRatioX = 2 / this.rcpScaleX, rcpRatioY = 2 / this.rcpScaleY, range2X = ceil(ratioX * this.lanczosLobes / 2), range2Y = ceil(ratioY * this.lanczosLobes / 2), cacheLanc = {}, center = {}, icenter = {};
return process(0);
},
bilinearFiltering: function(canvasEl, w, h, w2, h2) {
var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl, color, offset = 0, origPix, ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, context = canvasEl.getContext("2d"), w4 = 4 * (w - 1), img = context.getImageData(0, 0, w, h), pixels = img.data, destImage = context.getImageData(0, 0, w2, h2), destPixels = destImage.data;
for (i = 0; i < h2; i++) {
for (j = 0; j < w2; j++) {
bilinearFiltering: function(canvasEl, oW, oH, dW, dH) {
var a, b, c, d, x, y, i, j, xDiff, yDiff, chnl, color, offset = 0, origPix, ratioX = this.rcpScaleX, ratioY = this.rcpScaleY, context = canvasEl.getContext("2d"), w4 = 4 * (oW - 1), img = context.getImageData(0, 0, oW, oH), pixels = img.data, destImage = context.getImageData(0, 0, dW, dH), destPixels = destImage.data;
for (i = 0; i < dH; i++) {
for (j = 0; j < dW; j++) {
x = floor(ratioX * j);
y = floor(ratioY * i);
xDiff = ratioX * j - x;
yDiff = ratioY * i - y;
origPix = 4 * (y * w + x);
origPix = 4 * (y * oW + x);
for (chnl = 0; chnl < 4; chnl++) {
a = pixels[origPix + chnl];
b = pixels[origPix + 4 + chnl];
@ -9715,7 +9769,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
(function(global) {
"use strict";
var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, supportsLineDash = fabric.StaticCanvas.supports("setLineDash"), NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
var fabric = global.fabric || (global.fabric = {}), extend = fabric.util.object.extend, clone = fabric.util.object.clone, toFixed = fabric.util.toFixed, NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
if (fabric.Text) {
fabric.warn("fabric.Text is already defined");
return;
@ -9896,12 +9950,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
this._removeShadow(ctx);
}
ctx.save();
if (this.strokeDashArray) {
if (1 & this.strokeDashArray.length) {
this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
}
supportsLineDash && ctx.setLineDash(this.strokeDashArray);
}
this._setLineDash(ctx, this.strokedashArray);
ctx.beginPath();
this._renderTextCommon(ctx, "strokeText");
ctx.closePath();
@ -10032,7 +10081,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
}
},
_getFontDeclaration: function() {
return [ fabric.isLikelyNode ? this.fontWeight : this.fontStyle, fabric.isLikelyNode ? this.fontStyle : this.fontWeight, this.fontSize + "px", fabric.isLikelyNode ? '"' + this.fontFamily + '"' : this.fontFamily ].join(" ");
return [ fabric.isLikelyNode ? this.fontWeight : this.fontStyle, fabric.isLikelyNode ? this.fontStyle : this.fontWeight, this.fontSize + "px", '"' + this.fontFamily + '"' ].join(" ");
},
render: function(ctx, noTransform) {
if (!this.visible) {
@ -12283,19 +12332,6 @@ fabric.util.object.extend(fabric.IText.prototype, {
callback && callback();
});
};
fabric.Image.fromObject = function(object, callback) {
fabric.util.loadImage(object.src, function(img) {
var oImg = new fabric.Image(img);
oImg._initConfig(object);
oImg._initFilters(object.filters, function(filters) {
oImg.filters = filters || [];
oImg._initFilters(object.resizeFilters, function(resizeFilters) {
oImg.resizeFilters = resizeFilters || [];
callback && callback(oImg);
});
});
});
};
fabric.createCanvasForNode = function(width, height, options, nodeCanvasOptions) {
nodeCanvasOptions = nodeCanvasOptions || options;
var canvasEl = fabric.document.createElement("canvas"), nodeCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions), nodeCacheCanvas = new Canvas(width || 600, height || 600, nodeCanvasOptions);