You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2019/02/07 11:22:11 UTC
[openmeetings] branch 4.0.x updated: [OPENMEETINGS-1975] fabric.js
is updated
This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch 4.0.x
in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/4.0.x by this push:
new 6cf3a3b [OPENMEETINGS-1975] fabric.js is updated
6cf3a3b is described below
commit 6cf3a3b96385fdf30f6645262d3908fe856e5a84
Author: Maxim Solodovnik <so...@gmail.com>
AuthorDate: Thu Feb 7 18:21:58 2019 +0700
[OPENMEETINGS-1975] fabric.js is updated
---
.../org/apache/openmeetings/web/room/wb/fabric.js | 396 ++++++++++-----------
1 file changed, 196 insertions(+), 200 deletions(-)
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
index 2419e14..179a3d3 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
@@ -2,7 +2,7 @@
/* build: `node build.js modules=ALL exclude=gestures,accessors requirejs minifier=uglifyjs` */
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
-var fabric = fabric || { version: '2.4.5' };
+var fabric = fabric || { version: '2.6.0' };
if (typeof exports !== 'undefined') {
exports.fabric = fabric;
}
@@ -1175,6 +1175,7 @@ fabric.CommonMethods = {
/**
* Creates a canvas element that is a copy of another and is also painted
+ * @param {CanvasElement} canvas to copy size and content of
* @static
* @memberOf fabric.util
* @return {CanvasElement} initialized canvas element
@@ -1188,6 +1189,19 @@ fabric.CommonMethods = {
},
/**
+ * since 2.6.0 moved from canvas instance to utility.
+ * @param {CanvasElement} canvasEl to copy size and content of
+ * @param {String} format 'jpeg' or 'png', in some browsers 'webp' is ok too
+ * @param {Number} quality <= 1 and > 0
+ * @static
+ * @memberOf fabric.util
+ * @return {String} data url
+ */
+ toDataURL: function(canvasEl, format, quality) {
+ return canvasEl.toDataURL('image/' + format, quality);
+ },
+
+ /**
* Creates image element (works on client and node)
* @static
* @memberOf fabric.util
@@ -5875,29 +5889,25 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
var coords = clone(this.coords, true), i, len,
markup, commonAttributes, colorStops = clone(this.colorStops, true),
needsSwap = coords.r1 > coords.r2,
- offsetX = object.width / 2, offsetY = object.height / 2;
+ transform = this.gradientTransform ? this.gradientTransform.concat() : fabric.iMatrix.concat(),
+ offsetX = object.width / 2 - this.offsetX, offsetY = object.height / 2 - this.offsetY;
// colorStops must be sorted ascending
colorStops.sort(function(a, b) {
return a.offset - b.offset;
});
+
if (object.type === 'path') {
offsetX -= object.pathOffset.x;
offsetY -= object.pathOffset.y;
}
- for (var prop in coords) {
- if (prop === 'x1' || prop === 'x2') {
- coords[prop] += this.offsetX - offsetX;
- }
- else if (prop === 'y1' || prop === 'y2') {
- coords[prop] += this.offsetY - offsetY;
- }
- }
+
+ transform[4] -= offsetX;
+ transform[5] -= offsetY;
commonAttributes = 'id="SVGID_' + this.id +
'" gradientUnits="userSpaceOnUse"';
- if (this.gradientTransform) {
- commonAttributes += ' gradientTransform="matrix(' + this.gradientTransform.join(' ') + ')" ';
- }
+ commonAttributes += ' gradientTransform="matrix(' + transform.join(' ') + ')" ';
+
if (this.type === 'linear') {
markup = [
'<linearGradient ',
@@ -6632,6 +6642,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
/**
* Indicates whether toObject/toDatalessObject should include default values
+ * if set to false, takes precedence over the object value.
* @type Boolean
* @default
*/
@@ -7714,7 +7725,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
objects: this._toObjects(methodName, propertiesToInclude),
};
if (clipPath) {
- clipPath = clipPath.toObject(propertiesToInclude);
+ data.clipPath = this._toObjectMethod(clipPath, methodName, propertiesToInclude);
}
extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));
@@ -8332,7 +8343,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
* (either those of HTMLCanvasElement itself, or rendering context)
*
* @param {String} methodName Method to check support for;
- * Could be one of "getImageData", "toDataURL", "toDataURLWithQuality" or "setLineDash"
+ * Could be one of "setLineDash"
* @return {Boolean | null} `true` if method is supported (or at least exists),
* `null` if canvas element or context can not be initialized
*/
@@ -8350,23 +8361,9 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
switch (methodName) {
- case 'getImageData':
- return typeof ctx.getImageData !== 'undefined';
-
case 'setLineDash':
return typeof ctx.setLineDash !== 'undefined';
- case 'toDataURL':
- return typeof el.toDataURL !== 'undefined';
-
- case 'toDataURLWithQuality':
- try {
- el.toDataURL('image/jpeg', 0);
- return true;
- }
- catch (e) { }
- return false;
-
default:
return null;
}
@@ -9715,13 +9712,15 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
* @return {Boolean}
*/
isTargetTransparent: function (target, x, y) {
- if (target.shouldCache() && target._cacheCanvas) {
+ // in case the target is the activeObject, we cannot execute this optimization
+ // because we need to draw controls too.
+ if (target.shouldCache() && target._cacheCanvas && target !== this._activeObject) {
var normalizedPointer = this._normalizePointer(target, {x: x, y: y}),
- targetRelativeX = target.cacheTranslationX + (normalizedPointer.x * target.zoomX),
- targetRelativeY = target.cacheTranslationY + (normalizedPointer.y * target.zoomY);
+ targetRelativeX = Math.max(target.cacheTranslationX + (normalizedPointer.x * target.zoomX), 0),
+ targetRelativeY = Math.max(target.cacheTranslationY + (normalizedPointer.y * target.zoomY), 0);
var isTransparent = fabric.util.isTransparent(
- target._cacheContext, targetRelativeX, targetRelativeY, this.targetFindTolerance);
+ target._cacheContext, Math.round(targetRelativeX), Math.round(targetRelativeY), this.targetFindTolerance);
return isTransparent;
}
@@ -10100,12 +10099,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
*/
_setObjectScale: function(localMouse, transform, lockScalingX, lockScalingY, by, lockScalingFlip, _dim) {
var target = transform.target, forbidScalingX = false, forbidScalingY = false, scaled = false,
- changeX, changeY, scaleX, scaleY;
-
- scaleX = localMouse.x * target.scaleX / _dim.x;
- scaleY = localMouse.y * target.scaleY / _dim.y;
- changeX = target.scaleX !== scaleX;
- changeY = target.scaleY !== scaleY;
+ scaleX = localMouse.x * target.scaleX / _dim.x,
+ scaleY = localMouse.y * target.scaleY / _dim.y,
+ changeX = target.scaleX !== scaleX,
+ changeY = target.scaleY !== scaleY;
if (lockScalingFlip && scaleX <= 0 && scaleX < target.scaleX) {
forbidScalingX = true;
@@ -10125,10 +10122,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY));
}
else if (by === 'x' && !target.get('lockUniScaling')) {
- forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = scaled || changeX));
+ forbidScalingX || lockScalingX || (target.set('scaleX', scaleX) && (scaled = changeX));
}
else if (by === 'y' && !target.get('lockUniScaling')) {
- forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = scaled || changeY));
+ forbidScalingY || lockScalingY || (target.set('scaleY', scaleY) && (scaled = changeY));
}
transform.newScaleX = scaleX;
transform.newScaleY = scaleY;
@@ -10146,15 +10143,15 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
lastDist = _dim.y * transform.original.scaleY / target.scaleY +
_dim.x * transform.original.scaleX / target.scaleX,
scaled, signX = localMouse.x < 0 ? -1 : 1,
- signY = localMouse.y < 0 ? -1 : 1;
+ signY = localMouse.y < 0 ? -1 : 1, newScaleX, newScaleY;
// We use transform.scaleX/Y instead of target.scaleX/Y
// because the object may have a min scale and we'll loose the proportions
- transform.newScaleX = signX * Math.abs(transform.original.scaleX * dist / lastDist);
- transform.newScaleY = signY * Math.abs(transform.original.scaleY * dist / lastDist);
- scaled = transform.newScaleX !== target.scaleX || transform.newScaleY !== target.scaleY;
- target.set('scaleX', transform.newScaleX);
- target.set('scaleY', transform.newScaleY);
+ newScaleX = signX * Math.abs(transform.original.scaleX * dist / lastDist);
+ newScaleY = signY * Math.abs(transform.original.scaleY * dist / lastDist);
+ scaled = newScaleX !== target.scaleX || newScaleY !== target.scaleY;
+ target.set('scaleX', newScaleX);
+ target.set('scaleY', newScaleY);
return scaled;
},
@@ -12078,9 +12075,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
(function () {
-
- var supportQuality = fabric.StaticCanvas.supports('toDataURLWithQuality');
-
fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ {
/**
@@ -12120,69 +12114,57 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
var format = options.format || 'png',
quality = options.quality || 1,
- multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? 1 : 1 / this.getRetinaScaling()),
- cropping = {
- left: options.left || 0,
- top: options.top || 0,
- width: options.width || 0,
- height: options.height || 0,
- };
- return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier);
- },
-
- /**
- * @private
- */
- __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) {
-
- var origWidth = this.width,
- origHeight = this.height,
- scaledWidth = (cropping.width || this.width) * multiplier,
+ multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? this.getRetinaScaling() : 1),
+ canvasEl = this.toCanvasElement(multiplier, options);
+ return fabric.util.toDataURL(canvasEl, format, quality);
+ },
+
+ /**
+ * Create a new HTMLCanvas element painted with the current canvas content.
+ * No need to resize the actual one or repaint it.
+ * Will transfer object ownership to a new canvas, paint it, and set everything back.
+ * This is an intermediary step used to get to a dataUrl but also it is usefull to
+ * create quick image copies of a canvas without passing for the dataUrl string
+ * @param {Number} [multiplier] a zoom factor.
+ * @param {Object} [cropping] Cropping informations
+ * @param {Number} [cropping.left] Cropping left offset.
+ * @param {Number} [cropping.top] Cropping top offset.
+ * @param {Number} [cropping.width] Cropping width.
+ * @param {Number} [cropping.height] Cropping height.
+ */
+ toCanvasElement: function(multiplier, cropping) {
+ multiplier = multiplier || 1;
+ cropping = cropping || { };
+ var scaledWidth = (cropping.width || this.width) * multiplier,
scaledHeight = (cropping.height || this.height) * multiplier,
zoom = this.getZoom(),
+ originalWidth = this.width,
+ originalHeight = this.height,
newZoom = zoom * multiplier,
vp = this.viewportTransform,
- translateX = (vp[4] - cropping.left) * multiplier,
- translateY = (vp[5] - cropping.top) * multiplier,
- newVp = [newZoom, 0, 0, newZoom, translateX, translateY],
+ translateX = (vp[4] - (cropping.left || 0)) * multiplier,
+ translateY = (vp[5] - (cropping.top || 0)) * multiplier,
originalInteractive = this.interactive,
- originalSkipOffScreen = this.skipOffscreen,
- needsResize = origWidth !== scaledWidth || origHeight !== scaledHeight;
-
- this.viewportTransform = newVp;
- this.skipOffscreen = false;
- // setting interactive to false avoid exporting controls
+ originalContext = this.contextContainer,
+ newVp = [newZoom, 0, 0, newZoom, translateX, translateY],
+ canvasEl = fabric.util.createCanvasElement();
+ canvasEl.width = scaledWidth;
+ canvasEl.height = scaledHeight;
this.interactive = false;
- if (needsResize) {
- this.setDimensions({ width: scaledWidth, height: scaledHeight }, { backstoreOnly: true });
- }
- // call a renderAll to force sync update. This will cancel the scheduled requestRenderAll
- // from setDimensions
+ this.viewportTransform = newVp;
+ this.width = scaledWidth;
+ this.height = scaledHeight;
+ this.calcViewportBoundaries();
+ this.contextContainer = canvasEl.getContext('2d');
+ // will be renderAllExport();
this.renderAll();
- var data = this.__toDataURL(format, quality, cropping);
- this.interactive = originalInteractive;
- this.skipOffscreen = originalSkipOffScreen;
this.viewportTransform = vp;
- //setDimensions with no option object is taking care of:
- //this.width, this.height, this.requestRenderAll()
- if (needsResize) {
- this.setDimensions({ width: origWidth, height: origHeight }, { backstoreOnly: true });
- }
- this.renderAll();
- return data;
- },
-
- /**
- * @private
- */
- __toDataURL: function(format, quality) {
-
- var canvasEl = this.contextContainer.canvas;
- var data = supportQuality
- ? canvasEl.toDataURL('image/' + format, quality)
- : canvasEl.toDataURL('image/' + format);
-
- return data;
+ this.width = originalWidth;
+ this.height = originalHeight;
+ this.calcViewportBoundaries();
+ this.contextContainer = originalContext;
+ this.interactive = originalInteractive;
+ return canvasEl;
},
});
@@ -13591,8 +13573,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
drawObject: function(ctx, forClipping) {
-
+ var originalFill = this.fill, originalStroke = this.stroke;
if (forClipping) {
+ this.fill = 'black';
+ this.stroke = '';
this._setClippingProperties(ctx);
}
else {
@@ -13602,6 +13586,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
}
this._render(ctx);
this._drawClipPath(ctx);
+ this.fill = originalFill;
+ this.stroke = originalStroke;
},
_drawClipPath: function(ctx) {
@@ -13782,18 +13768,19 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
return;
}
- var multX = (this.canvas && this.canvas.viewportTransform[0]) || 1,
- multY = (this.canvas && this.canvas.viewportTransform[3]) || 1,
+ var shadow = this.shadow, canvas = this.canvas,
+ multX = (canvas && canvas.viewportTransform[0]) || 1,
+ multY = (canvas && canvas.viewportTransform[3]) || 1,
scaling = this.getObjectScaling();
- if (this.canvas && this.canvas._isRetinaScaling()) {
+ if (canvas && canvas._isRetinaScaling()) {
multX *= fabric.devicePixelRatio;
multY *= fabric.devicePixelRatio;
}
- ctx.shadowColor = this.shadow.color;
- ctx.shadowBlur = this.shadow.blur * fabric.browserShadowBlurConstant *
+ ctx.shadowColor = shadow.color;
+ ctx.shadowBlur = shadow.blur * fabric.browserShadowBlurConstant *
(multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;
- ctx.shadowOffsetX = this.shadow.offsetX * multX * scaling.scaleX;
- ctx.shadowOffsetY = this.shadow.offsetY * multY * scaling.scaleY;
+ ctx.shadowOffsetX = shadow.offsetX * multX * scaling.scaleX;
+ ctx.shadowOffsetY = shadow.offsetY * multY * scaling.scaleY;
},
/**
@@ -13813,6 +13800,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Object} filler fabric.Pattern or fabric.Gradient
+ * @return {Object} offset.offsetX offset for text rendering
+ * @return {Object} offset.offsetY offset for text rendering
*/
_applyPatternGradientTransform: function(ctx, filler) {
if (!filler || !filler.toLive) {
@@ -13953,6 +13942,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* Creates an instance of fabric.Image out of an object
+ * could make use of both toDataUrl or toCanvasElement.
* @param {Function} callback callback, invoked with an instance as a first argument
* @param {Object} [options] for clone as image, passed to toDataURL
* @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
@@ -13968,20 +13958,16 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @return {fabric.Object} thisArg
*/
cloneAsImage: function(callback, options) {
- var dataUrl = this.toDataURL(options);
- fabric.util.loadImage(dataUrl, function(img) {
- if (callback) {
- callback(new fabric.Image(img));
- }
- });
+ var canvasEl = this.toCanvasElement(options);
+ if (callback) {
+ callback(new fabric.Image(canvasEl));
+ }
return this;
},
/**
- * Converts an object into a data-url-like string
+ * Converts an object into a HTMLCanvas element
* @param {Object} options Options object
- * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
- * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
* @param {Number} [options.multiplier=1] Multiplier to scale by
* @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
* @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
@@ -13992,11 +13978,12 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2
* @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
*/
- toDataURL: function(options) {
+ toCanvasElement: function(options) {
options || (options = { });
var utils = fabric.util, origParams = utils.saveObjectTransform(this),
- originalShadow = this.shadow, abs = Math.abs;
+ originalShadow = this.shadow, abs = Math.abs,
+ multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? fabric.devicePixelRatio : 1);
if (options.withoutTransform) {
utils.resetObjectTransform(this);
@@ -14022,7 +14009,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
el.width += el.width % 2 ? 2 - el.width % 2 : 0;
el.height += el.height % 2 ? 2 - el.height % 2 : 0;
var canvas = new fabric.StaticCanvas(el, {
- enableRetinaScaling: options.enableRetinaScaling,
+ enableRetinaScaling: false,
renderOnAddRemove: false,
skipOffscreen: false,
});
@@ -14033,10 +14020,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
var originalCanvas = this.canvas;
canvas.add(this);
- var data = canvas.toDataURL(options);
+ var canvasEl = canvas.toCanvasElement(multiplier || 1, options);
this.shadow = originalShadow;
- this.set(origParams).setCoords();
this.canvas = originalCanvas;
+ this.set(origParams).setCoords();
// canvas.dispose will call image.dispose that will nullify the elements
// since this canvas is a simple element for the process, we remove references
// to objects in this way in order to avoid object trashing.
@@ -14044,7 +14031,27 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
canvas.dispose();
canvas = null;
- return data;
+ return canvasEl;
+ },
+
+ /**
+ * Converts an object into a data-url-like string
+ * @param {Object} options Options object
+ * @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
+ * @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
+ * @param {Number} [options.multiplier=1] Multiplier to scale by
+ * @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
+ * @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
+ * @param {Number} [options.width] Cropping width. Introduced in v1.2.14
+ * @param {Number} [options.height] Cropping height. Introduced in v1.2.14
+ * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4
+ * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4
+ * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2
+ * @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
+ */
+ toDataURL: function(options) {
+ options || (options = { });
+ return fabric.util.toDataURL(this.toCanvasElement(options), options.format || 'png', options.quality || 1);
},
/**
@@ -14786,7 +14793,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* Checks if object is contained within the canvas with current viewportTransform
* the check is done stopping at first point that appears on screen
- * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords
+ * @param {Boolean} [calculate] use coordinates of current position instead of .aCoords
* @return {Boolean} true if object is fully or partially contained within canvas
*/
isOnScreen: function(calculate) {
@@ -15560,7 +15567,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
absoluteClipPath = this.clipPath && this.clipPath.absolutePositioned,
commonPieces, markup = [], clipPathMarkup,
// insert commons in the markup, style and svgCommons
- index = objectMarkup.indexOf('COMMON_PARTS');
+ index = objectMarkup.indexOf('COMMON_PARTS'),
+ additionalTransform = options.additionalTransform;
if (clipPath) {
clipPath.clipPathId = 'CLIPPATH_' + fabric.Object.__uid++;
clipPathMarkup = '<clipPath id="' + clipPath.clipPathId + '" >\n' +
@@ -15580,7 +15588,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
);
commonPieces = [
styleInfo,
- noStyle ? '' : this.addPaintOrder(), ' '
+ noStyle ? '' : this.addPaintOrder(), ' ',
+ additionalTransform ? 'transform="' + additionalTransform + '" ' : '',
].join('');
objectMarkup[index] = commonPieces;
if (this.fill && this.fill.toLive) {
@@ -18250,6 +18259,16 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform }
);
},
+
+ /**
+ * Returns svg representation of an instance
+ * @param {Function} [reviver] Method for further parsing of svg representation.
+ * @return {String} svg representation of an instance
+ */
+ toSVG: function(reviver) {
+ var additionalTransform = this._getOffsetTransform();
+ return this._createBaseSVGMarkup(this._toSVG(), { reviver: reviver, additionalTransform: additionalTransform });
+ },
/* _TO_SVG_END_ */
/**
@@ -19921,14 +19940,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
},
_renderFill: function(ctx) {
- var w = this.width, h = this.height, sW = w * this._filterScalingX, sH = h * this._filterScalingY,
- x = -w / 2, y = -h / 2, elementToDraw = this._element;
- elementToDraw && ctx.drawImage(elementToDraw,
- this.cropX * this._filterScalingX,
- this.cropY * this._filterScalingY,
- sW,
- sH,
- x, y, w, h);
+ var elementToDraw = this._element,
+ w = this.width, h = this.height,
+ sW = Math.min(elementToDraw.naturalWidth || elementToDraw.width, w * this._filterScalingX),
+ sH = Math.min(elementToDraw.naturalHeight || elementToDraw.height, h * this._filterScalingY),
+ x = -w / 2, y = -h / 2,
+ sX = Math.max(0, this.cropX * this._filterScalingX),
+ sY = Math.max(0, this.cropY * this._filterScalingY);
+
+ elementToDraw && ctx.drawImage(elementToDraw, sX, sY, sW, sH, x, y, w, h);
},
/**
@@ -20456,51 +20476,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
},
/**
- * The same as the applyFilter method but with additional logging of WebGL
- * errors.
- */
- applyFiltersDebug: function(filters, source, width, height, targetCanvas, cacheKey) {
- // The following code is useful when debugging a specific issue but adds ~10x slowdown.
- var gl = this.gl;
- var ret = this.applyFilters(filters, source, width, height, targetCanvas, cacheKey);
- var glError = gl.getError();
- if (glError !== gl.NO_ERROR) {
- var errorString = this.glErrorToString(gl, glError);
- var error = new Error('WebGL Error ' + errorString);
- error.glErrorCode = glError;
- throw error;
- }
- return ret;
- },
-
- glErrorToString: function(context, errorCode) {
- if (!context) {
- return 'Context undefined for error code: ' + errorCode;
- }
- else if (typeof errorCode !== 'number') {
- return 'Error code is not a number';
- }
- switch (errorCode) {
- case context.NO_ERROR:
- return 'NO_ERROR';
- case context.INVALID_ENUM:
- return 'INVALID_ENUM';
- case context.INVALID_VALUE:
- return 'INVALID_VALUE';
- case context.INVALID_OPERATION:
- return 'INVALID_OPERATION';
- case context.INVALID_FRAMEBUFFER_OPERATION:
- return 'INVALID_FRAMEBUFFER_OPERATION';
- case context.OUT_OF_MEMORY:
- return 'OUT_OF_MEMORY';
- case context.CONTEXT_LOST_WEBGL:
- return 'CONTEXT_LOST_WEBGL';
- default:
- return 'UNKNOWN_ERROR';
- }
- },
-
- /**
* Detach event listeners, remove references, and clean up caches.
*/
dispose: function() {
@@ -20593,9 +20568,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
if (this.gpuInfo) {
return this.gpuInfo;
}
- var gl = this.gl;
+ var gl = this.gl, gpuInfo = { renderer: '', vendor: '' };
+ if (!gl) {
+ return gpuInfo;
+ }
var ext = gl.getExtension('WEBGL_debug_renderer_info');
- var gpuInfo = { renderer: '', vendor: '' };
if (ext) {
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
@@ -28684,6 +28661,20 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
_dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat('width'),
/**
+ * Use this regular expression to split strings in breakable lines
+ * @private
+ */
+ _wordJoiners: /[ \t\r\u200B\u200C]/,
+
+ /**
+ * Use this boolean property in order to split strings that have no white space concept.
+ * this is a cheap way to help with chinese/japaense
+ * @type Boolean
+ * @since 2.6.0
+ */
+ splitByGrapheme: false,
+
+ /**
* Unlike superclass's version of this function, Textbox does not update
* its width.
* @private
@@ -28919,19 +28910,20 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* to.
*/
_wrapLine: function(_line, lineIndex, desiredWidth, reservedSpace) {
- var lineWidth = 0,
- graphemeLines = [],
- line = [],
+ var lineWidth = 0,
+ splitByGrapheme = this.splitByGrapheme,
+ graphemeLines = [],
+ line = [],
// spaces in different languges?
- words = _line.split(this._reSpaceAndTab),
- word = '',
- offset = 0,
- infix = ' ',
- wordWidth = 0,
- infixWidth = 0,
+ words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners),
+ word = '',
+ offset = 0,
+ infix = splitByGrapheme ? '' : ' ',
+ wordWidth = 0,
+ infixWidth = 0,
largestWordWidth = 0,
lineJustStarted = true,
- additionalSpace = this._getWidthOfCharSpacing(),
+ additionalSpace = splitByGrapheme ? 0 : this._getWidthOfCharSpacing(),
reservedSpace = reservedSpace || 0;
desiredWidth -= reservedSpace;
@@ -29025,7 +29017,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @return {Object} object representation of an instance
*/
toObject: function(propertiesToInclude) {
- return this.callSuper('toObject', ['minWidth'].concat(propertiesToInclude));
+ return this.callSuper('toObject', ['minWidth', 'splitByGrapheme'].concat(propertiesToInclude));
}
});
@@ -29053,13 +29045,18 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
fabric.Canvas.prototype._setObjectScale = function(localMouse, transform,
lockScalingX, lockScalingY, by, lockScalingFlip, _dim) {
- var t = transform.target;
+ var t = transform.target, scaled,
+ scaleX = localMouse.x * t.scaleX / _dim.x,
+ scaleY = localMouse.y * t.scaleY / _dim.y;
if (by === 'x' && t instanceof fabric.Textbox) {
var tw = t._getTransformedDimensions().x;
var w = t.width * (localMouse.x / tw);
+ transform.newScaleX = scaleX;
+ transform.newScaleY = scaleY;
if (w >= t.getMinWidth()) {
+ scaled = w !== t.width;
t.set('width', w);
- return true;
+ return scaled;
}
}
else {
@@ -29082,4 +29079,3 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
});
})();
-