Comparing version 4.0.0-beta1 to 4.0.0-rc.1-browser
@@ -43,2 +43,8 @@ # Contributing to Fabric | ||
### Online one-click setup for making PRs | ||
Contribute to fabricjs using a fully featured online development environment that will automatically with a single click: clone the repo and install the dependencies. | ||
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) | ||
### Pull request guidelines | ||
@@ -45,0 +51,0 @@ |
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ | ||
var fabric = fabric || { version: '4.0.0-beta.1' }; | ||
var fabric = fabric || { version: '4.0.0-rc.1' }; | ||
if (typeof exports !== 'undefined') { | ||
@@ -67,3 +67,3 @@ exports.fabric = fabric; | ||
'id', 'paint-order', 'vector-effect', | ||
'instantiated_by_use', 'clip-path' | ||
'instantiated_by_use', 'clip-path', | ||
]; | ||
@@ -70,0 +70,0 @@ /* _FROM_SVG_END_ */ |
159
package.json
{ | ||
"name": "fabric", | ||
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.", | ||
"homepage": "http://fabricjs.com/", | ||
"version": "4.0.0-beta1", | ||
"author": "Juriy Zaytsev <kangax@gmail.com>", | ||
"contributors": [ | ||
{ | ||
"name": "Andrea Bogazzi", | ||
"email": "andreabogazzi79@gmail.com" | ||
} | ||
], | ||
"keywords": [ | ||
"canvas", | ||
"graphic", | ||
"graphics", | ||
"SVG", | ||
"node-canvas", | ||
"parser", | ||
"HTML5", | ||
"object model" | ||
], | ||
"browser": { | ||
"canvas": false, | ||
"fs": false, | ||
"jsdom": false, | ||
"jsdom/lib/jsdom/living/generated/utils": false, | ||
"jsdom/lib/jsdom/utils": false, | ||
"http": false, | ||
"https": false, | ||
"xmldom": false, | ||
"url": false | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/fabricjs/fabric.js" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/fabricjs/fabric.js/issues" | ||
}, | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "node build.js modules=ALL requirejs exclude=gestures,accessors", | ||
"build:fast": "node build.js modules=ALL requirejs fast exclude=gestures,accessors", | ||
"build:watch": "onchange 'src/**/**' 'HEADER.js' 'lib/**/**' -- npm run build_export", | ||
"link:watch": "onchange 'src/**/**' 'HEADER.js' 'lib/**/**' -- npm link", | ||
"build_with_gestures": "node build.js modules=ALL exclude=accessors", | ||
"build_export": "npm run build:fast && npm run export_dist_to_site", | ||
"test:single": "qunit test/node_test_setup.js test/lib", | ||
"test": "nyc qunit test/node_test_setup.js test/lib test/unit", | ||
"test:visual": "qunit test/node_test_setup.js test/lib test/visual", | ||
"test:visual:single": "qunit test/node_test_setup.js test/lib", | ||
"test:all": "npm run test && npm run test:visual", | ||
"lint": "eslint --config .eslintrc.json src", | ||
"lint_tests": "eslint test/unit --config .eslintrc_tests && eslint test/visual --config .eslintrc_tests", | ||
"export_dist_to_site": "cp dist/fabric.js ../fabricjs.com/lib/fabric.js && cp package.json ../fabricjs.com/lib/package.json && cp -r src HEADER.js lib ../fabricjs.com/build/files/", | ||
"export_tests_to_site": "cp test/unit/*.js ../fabricjs.com/test/unit && cp -r test/visual/* ../fabricjs.com/test/visual && cp -r test/fixtures/* ../fabricjs.com/test/fixtures && cp -r test/lib/* ../fabricjs.com/test/lib", | ||
"all": "npm run build && npm run test && npm run test:visual && npm run lint && npm run lint_tests && npm run export_dist_to_site && npm run export_tests_to_site", | ||
"testem": "testem .", | ||
"testem:visual": "testem --file testem-visual.json", | ||
"testem:ci": "testem ci" | ||
}, | ||
"optionalDependencies": { | ||
"canvas": "^2.6.1", | ||
"jsdom": "^15.1.0" | ||
}, | ||
"devDependencies": { | ||
"eslint": "4.18.x", | ||
"nyc": "13.3.x", | ||
"onchange": "^3.x.x", | ||
"qunit": "2.9.2", | ||
"testem": "^1.18.4", | ||
"uglify-js": "3.3.x", | ||
"pixelmatch": "^4.0.2", | ||
"chalk": "^2.4.1" | ||
}, | ||
"engines": { | ||
"node": ">=8.0.0" | ||
}, | ||
"main": "./dist/fabric.js", | ||
"dependencies": {} | ||
} | ||
"name": "fabric", | ||
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.", | ||
"homepage": "http://fabricjs.com/", | ||
"version": "4.0.0-rc.1-browser", | ||
"author": "Juriy Zaytsev <kangax@gmail.com>", | ||
"contributors": [ | ||
{ | ||
"name": "Andrea Bogazzi", | ||
"email": "andreabogazzi79@gmail.com" | ||
} | ||
], | ||
"keywords": [ | ||
"canvas", | ||
"graphic", | ||
"graphics", | ||
"SVG", | ||
"node-canvas", | ||
"parser", | ||
"HTML5", | ||
"object model" | ||
], | ||
"browser": { | ||
"canvas": false, | ||
"fs": false, | ||
"jsdom": false, | ||
"jsdom/lib/jsdom/living/generated/utils": false, | ||
"jsdom/lib/jsdom/utils": false, | ||
"http": false, | ||
"https": false, | ||
"xmldom": false, | ||
"url": false | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/fabricjs/fabric.js" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/fabricjs/fabric.js/issues" | ||
}, | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "node build.js modules=ALL requirejs exclude=gestures,accessors", | ||
"build:fast": "node build.js modules=ALL requirejs fast exclude=gestures,accessors", | ||
"build:watch": "onchange 'src/**/**' 'HEADER.js' 'lib/**/**' -- npm run build_export", | ||
"link:watch": "onchange 'src/**/**' 'HEADER.js' 'lib/**/**' -- npm link", | ||
"build_with_gestures": "node build.js modules=ALL exclude=accessors", | ||
"build_export": "npm run build:fast && npm run export_dist_to_site", | ||
"test:single": "qunit test/node_test_setup.js test/lib", | ||
"test": "nyc qunit test/node_test_setup.js test/lib test/unit", | ||
"test:visual": "qunit test/node_test_setup.js test/lib test/visual", | ||
"test:visual:single": "qunit test/node_test_setup.js test/lib", | ||
"test:all": "npm run test && npm run test:visual", | ||
"lint": "eslint --config .eslintrc.json src", | ||
"lint_tests": "eslint test/unit --config .eslintrc_tests && eslint test/visual --config .eslintrc_tests", | ||
"export_dist_to_site": "cp dist/fabric.js ../fabricjs.com/lib/fabric.js && cp package.json ../fabricjs.com/lib/package.json && cp -r src HEADER.js lib ../fabricjs.com/build/files/", | ||
"export_tests_to_site": "cp test/unit/*.js ../fabricjs.com/test/unit && cp -r test/visual/* ../fabricjs.com/test/visual && cp -r test/fixtures/* ../fabricjs.com/test/fixtures && cp -r test/lib/* ../fabricjs.com/test/lib", | ||
"all": "npm run build && npm run test && npm run test:visual && npm run lint && npm run lint_tests && npm run export_dist_to_site && npm run export_tests_to_site", | ||
"testem": "testem .", | ||
"testem:visual": "testem --file testem-visual.json", | ||
"testem:ci": "testem ci" | ||
}, | ||
"optionalDependencies": {}, | ||
"devDependencies": { | ||
"eslint": "4.18.x", | ||
"nyc": "13.3.x", | ||
"onchange": "^3.x.x", | ||
"qunit": "2.9.2", | ||
"testem": "^1.18.4", | ||
"uglify-js": "3.3.x", | ||
"pixelmatch": "^4.0.2", | ||
"chalk": "^2.4.1" | ||
}, | ||
"engines": { | ||
"node": ">=8.0.0" | ||
}, | ||
"main": "./dist/fabric.js", | ||
"dependencies": {} | ||
} |
@@ -10,3 +10,9 @@ var cp = require('child_process'); | ||
var args = process.argv.slice(2).join(' '); // args will be passed to npm publish (like --dry-run) | ||
var preRelease = process.env.PRE_RELEASE; | ||
// allow publishing of pre-releases with beta tag | ||
if (preRelease) { | ||
args = '--tag beta ' + args; | ||
} | ||
// override package.json with updated fields | ||
@@ -13,0 +19,0 @@ fs.writeFileSync( |
@@ -7,2 +7,3 @@ ### Fabric | ||
[![Coverage Status](https://coveralls.io/repos/fabricjs/fabric.js/badge.png?branch=master)](https://coveralls.io/r/kangax/fabric.js?branch=master) | ||
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/fabricjs/fabric.js) | ||
@@ -273,4 +274,1 @@ <!-- npm, bower, CDNJS versions, downloads --> | ||
SOFTWARE. | ||
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/kangax/fabric.js/trend.png)](https://bitdeli.com/free "Bitdeli Badge") |
@@ -60,13 +60,2 @@ /** | ||
/** | ||
* Sets shadow of an object | ||
* @param {Object|String} [options] Options object or string (e.g. "2px 2px 10px rgba(0,0,0,0.2)") | ||
* @return {fabric.Object} thisArg | ||
* @chainable | ||
*/ | ||
setShadow: function(options) { | ||
this.shadow = new fabric.Shadow(options); | ||
return this; | ||
}, | ||
/** | ||
* Sets brush styles | ||
@@ -73,0 +62,0 @@ * @private |
@@ -103,3 +103,3 @@ /** | ||
this.shadow && circle.setShadow(this.shadow); | ||
this.shadow && (circle.shadow = new fabric.Shadow(this.shadow)); | ||
@@ -106,0 +106,0 @@ circles.push(circle); |
@@ -230,3 +230,3 @@ (function() { | ||
this.shadow.affectStroke = true; | ||
path.setShadow(this.shadow); | ||
path.shadow = new fabric.Shadow(this.shadow); | ||
} | ||
@@ -233,0 +233,0 @@ |
@@ -113,3 +113,3 @@ /** | ||
var group = new fabric.Group(rects); | ||
this.shadow && group.setShadow(this.shadow); | ||
this.shadow && group.set('shadow', new fabric.Shadow(this.shadow)); | ||
this.canvas.add(group); | ||
@@ -116,0 +116,0 @@ this.canvas.fire('path:created', { path: group }); |
@@ -26,3 +26,2 @@ (function() { | ||
* @fires object:skewing while an object is being skewed from the controls | ||
* @fires object:selected this event is deprecated. use selection:created | ||
* | ||
@@ -662,4 +661,3 @@ * @fires before:transform before a transform is is started | ||
var pointer = this.getPointer(e), isTouch = isTouchEvent(e), | ||
corner = target._findTargetCorner(this.getPointer(e, true), isTouch), | ||
var pointer = this.getPointer(e), corner = target.__corner, | ||
actionHandler = !!corner && target.controls[corner].getActionHandler(), | ||
@@ -687,3 +685,3 @@ action = this._getActionFromCorner(alreadySelected, corner, e, target), | ||
lastY: pointer.y, | ||
// unsure they are usefull anymore. | ||
// unsure they are useful anymore. | ||
// left: target.left, | ||
@@ -1156,7 +1154,2 @@ // top: target.top, | ||
else if (objects.length > 0) { | ||
// deprecated event | ||
if (objects.length === 1) { | ||
opt.target = added[0]; | ||
this.fire('object:selected', opt); | ||
} | ||
opt.selected = added; | ||
@@ -1163,0 +1156,0 @@ // added for backward compatibility |
@@ -5,13 +5,5 @@ (function(global) { | ||
var fabric = global.fabric || (global.fabric = { }), | ||
degreesToRadians = fabric.util.degreesToRadians, | ||
renderCircleControl = fabric.controlRenderers.renderCircleControl, | ||
renderSquareControl = fabric.controlRenderers.renderSquareControl; | ||
var fabric = global.fabric || (global.fabric = { }); | ||
function Control(options) { | ||
if (options.position) { | ||
this.x = options.position.x; | ||
this.y = options.position.y; | ||
} | ||
delete options.position; | ||
for (var i in options) { | ||
@@ -51,3 +43,4 @@ this[i] = options[i]; | ||
* Drawing angle of the control. | ||
* Used to reuse the same drawing function for different rotated controls | ||
* NOT used for now, but name marked as needed for internal logic | ||
* example: to reuse the same drawing function for different rotated controls | ||
* @type {Number} | ||
@@ -59,9 +52,2 @@ * @default 0 | ||
/** | ||
* Maybe useless, maybe will get removed before releaseing | ||
* @type {String} | ||
* @default '' | ||
*/ | ||
name: '', | ||
/** | ||
* Relative position of the control. X | ||
@@ -123,2 +109,29 @@ * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities | ||
/** | ||
* The control actionHandler, provide one to handle action ( control being moved ) | ||
* @param {Event} eventData the native mouse event | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
*/ | ||
actionHandler: function(/* eventData, transformData, fabricObject */) { }, | ||
/** | ||
* The control handler for mouse down, provide one to handle mouse down on control | ||
* @param {Event} eventData the native mouse event | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
*/ | ||
mouseDownHandler: function(/* eventData, transformData, fabricObject */) { }, | ||
/** | ||
* The control mouseUpHandler, provide one to handle an effect on mouse up. | ||
* @param {Event} eventData the native mouse event | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
*/ | ||
mouseUpHandler: function(/* eventData, transformData, fabricObject */) { }, | ||
/** | ||
* Returns control actionHandler | ||
@@ -135,2 +148,24 @@ * @param {Event} eventData the native mouse event | ||
/** | ||
* Returns control mouseDown handler | ||
* @param {Event} eventData the native mouse event | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
*/ | ||
getMouseDownHandler: function(/* eventData, fabricObject, control */) { | ||
return this.mouseDownHandler; | ||
}, | ||
/** | ||
* Returns control mouseUp handler | ||
* @param {Event} eventData the native mouse event | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
*/ | ||
getMouseUpHandler: function(/* eventData, fabricObject, control */) { | ||
return this.mouseUpHandler; | ||
}, | ||
/** | ||
* Returns control cursorStyle for css using cursorStyle. If you need a more elaborate | ||
@@ -162,5 +197,10 @@ * function you can pass one in the constructor | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @param {String} controlKey key where the control is memorized on the | ||
* @return {Boolean} | ||
*/ | ||
getVisibility: function(/*fabricObject, name */) { | ||
getVisibility: function(fabricObject, controlKey) { | ||
var objectVisibility = fabricObject._controlsVisibility; | ||
if (objectVisibility && typeof objectVisibility[controlKey] !== 'undefined') { | ||
return objectVisibility[controlKey]; | ||
} | ||
return this.visible; | ||
@@ -179,27 +219,6 @@ }, | ||
positionHandler: function(dim, finalMatrix, fabricObject /* currentControl */ ) { | ||
var padding = fabricObject.padding, angle = degreesToRadians(fabricObject.angle), | ||
cos = fabric.util.cos(angle), sin = fabric.util.sin(angle), offsetX = this.offsetX, | ||
offsetY = this.offsetY, cosP = cos * padding, sinP = sin * padding, cosY = cos * offsetY, | ||
cosX = cos * offsetX, sinY = sin * offsetY, sinX = sin * offsetX, | ||
point = fabric.util.transformPoint({ | ||
x: (this.x * dim.x), | ||
y: (this.y * dim.y) }, finalMatrix); | ||
if (this.x > 0) { | ||
point.y += sinP + sinX + cosY; | ||
point.x += cosP + cosX - sinY; | ||
} | ||
if (this.y > 0) { | ||
point.y += cosP + sinX + cosY; | ||
point.x += -sinP + cosX - sinY; | ||
} | ||
// to be verified | ||
if (this.x < 0) { | ||
point.y += -sinP - sinX - cosY; | ||
point.x += -cosP - cosX + sinY; | ||
} | ||
if (this.y < 0) { | ||
point.y += -cosP - sinX + cosY; | ||
point.x += sinP + cosX - sinY; | ||
} | ||
positionHandler: function(dim, finalMatrix /*, fabricObject, currentControl */) { | ||
var point = fabric.util.transformPoint({ | ||
x: this.x * dim.x + this.offsetX, | ||
y: this.y * dim.y + this.offsetY }, finalMatrix); | ||
return point; | ||
@@ -223,11 +242,8 @@ }, | ||
styleOverride = styleOverride || {}; | ||
if (!this.getVisibility()) { | ||
return; | ||
} | ||
switch (styleOverride.cornerStyle || fabricObject.cornerStyle) { | ||
case 'circle': | ||
renderCircleControl.call(this, ctx, left, top, styleOverride, fabricObject); | ||
fabric.controlRenderers.renderCircleControl.call(this, ctx, left, top, styleOverride, fabricObject); | ||
break; | ||
default: | ||
renderSquareControl.call(this, ctx, left, top, styleOverride, fabricObject); | ||
fabric.controlRenderers.renderSquareControl.call(this, ctx, left, top, styleOverride, fabricObject); | ||
} | ||
@@ -234,0 +250,0 @@ }, |
@@ -10,3 +10,9 @@ (function(global) { | ||
LEFT = 'left', TOP = 'top', RIGHT = 'right', BOTTOM = 'bottom', CENTER = 'center', | ||
radiansToDegrees = fabric.util.radiansToDegrees; | ||
opposite = { | ||
top: BOTTOM, | ||
bottom: TOP, | ||
left: RIGHT, | ||
right: LEFT, | ||
}, radiansToDegrees = fabric.util.radiansToDegrees, | ||
sign = (Math.sign || function(x) { return ((x > 0) - (x < 0)) || +x; }); | ||
@@ -20,20 +26,43 @@ function findCornerQuadrant(fabricObject, corner) { | ||
var target = options.transform.target, | ||
canvas = target.canvas; | ||
canvas && canvas.fire('object:' + eventName, options); | ||
canvas = target.canvas, | ||
canasOptions = Object.assign({}, options, { target: target }); | ||
canvas && canvas.fire('object:' + eventName, canasOptions); | ||
target.fire(eventName, options); | ||
} | ||
function scaleCursorStyleHandler(eventData, corner, fabricObject) { | ||
var canvas = fabricObject.canvas, uniScaleKey = canvas.uniScaleKey, notAllowed = 'not-allowed', | ||
uniformIsToggled = eventData[uniScaleKey], | ||
scaleIsProportional = (canvas.uniformScaling && !uniformIsToggled) || | ||
(!canvas.uniformScaling && uniformIsToggled); | ||
function scaleIsProportional(eventData, fabricObject) { | ||
var canvas = fabricObject.canvas, uniScaleKey = canvas.uniScaleKey, | ||
uniformIsToggled = eventData[uniScaleKey]; | ||
return (canvas.uniformScaling && !uniformIsToggled) || | ||
(!canvas.uniformScaling && uniformIsToggled); | ||
} | ||
if (fabricObject.lockScalingX && fabricObject.lockScalingY) { | ||
return notAllowed; | ||
function scalingIsForbidden(fabricObject, by, scaleProportionally) { | ||
var lockX = fabricObject.lockScalingX, lockY = fabricObject.lockScalingY; | ||
if (lockX && lockY) { | ||
return true; | ||
} | ||
if (corner.x !== 0 && fabricObject.lockScalingX && scaleIsProportional) { | ||
return notAllowed; | ||
if (!by && (lockX || lockY) && scaleProportionally) { | ||
return true; | ||
} | ||
if (corner.y !== 0 && fabricObject.lockScalingY && scaleIsProportional) { | ||
if (lockX && by === 'x') { | ||
return true; | ||
} | ||
if (lockY && by === 'y') { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function scaleCursorStyleHandler(eventData, corner, fabricObject) { | ||
var notAllowed = 'not-allowed', | ||
scaleProportionally = scaleIsProportional(eventData, fabricObject), | ||
by = ''; | ||
if (corner.x !== 0 && corner.y === 0) { | ||
by = 'x'; | ||
} | ||
else if (corner.x === 0 && corner.y !== 0) { | ||
by = 'y'; | ||
} | ||
if (scalingIsForbidden(fabricObject, by, scaleProportionally)) { | ||
return notAllowed; | ||
@@ -97,6 +126,5 @@ } | ||
var target = transform.target, centerPoint = target.getCenterPoint(), | ||
anchorY = transform.originY, anchorX = transform.originX, | ||
constraint = target.translateToOriginPoint(centerPoint, anchorX, anchorY), | ||
constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY), | ||
actionPerformed = actionHandler(eventData, transform, x, y); | ||
target.setPositionByOrigin(constraint, anchorX, anchorY); | ||
target.setPositionByOrigin(constraint, transform.originX, transform.originY); | ||
return actionPerformed; | ||
@@ -106,4 +134,6 @@ }; | ||
function getLocalPoint(target, originX, originY, x, y) { | ||
var zoom = target.canvas.getZoom(), | ||
function getLocalPoint(transform, originX, originY, x, y) { | ||
var target = transform.target, | ||
control = target.controls[transform.corner], | ||
zoom = target.canvas.getZoom(), | ||
padding = target.padding / zoom, | ||
@@ -123,2 +153,4 @@ localPoint = target.toLocalPoint(new fabric.Point(x, y), originX, originY); | ||
} | ||
localPoint.x -= control.offsetX; | ||
localPoint.y -= control.offsetY; | ||
return localPoint; | ||
@@ -143,3 +175,3 @@ } | ||
dimNoSkew = target._getTransformedDimensions(0, target.skewY), | ||
localPoint = getLocalPoint(target, transform.originX, transform.originY, x, y), | ||
localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y), | ||
// the mouse is in the center of the object, and we want it to stay there. | ||
@@ -155,3 +187,3 @@ // so the object will grow twice as much as the mouse. | ||
else { | ||
newSkew = fabric.util.radiansToDegrees( | ||
newSkew = radiansToDegrees( | ||
Math.atan2((totalSkewSize / target.scaleX), (dimNoSkew.y / target.scaleY)) | ||
@@ -185,3 +217,3 @@ ); | ||
dimNoSkew = target._getTransformedDimensions(target.skewX, 0), | ||
localPoint = getLocalPoint(target, transform.originX, transform.originY, x, y), | ||
localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y), | ||
// the mouse is in the center of the object, and we want it to stay there. | ||
@@ -197,3 +229,3 @@ // so the object will grow twice as much as the mouse. | ||
else { | ||
newSkew = fabric.util.radiansToDegrees( | ||
newSkew = radiansToDegrees( | ||
Math.atan2((totalSkewSize / target.scaleY), (dimNoSkew.x / target.scaleX)) | ||
@@ -236,3 +268,3 @@ ); | ||
if (currentSkew === 0) { | ||
var localPointFromCenter = getLocalPoint(target, CENTER, CENTER, x, y); | ||
var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y); | ||
if (localPointFromCenter.x > 0) { | ||
@@ -279,3 +311,3 @@ // we are pulling right, anchor left; | ||
if (currentSkew === 0) { | ||
var localPointFromCenter = getLocalPoint(target, CENTER, CENTER, x, y); | ||
var localPointFromCenter = getLocalPoint(transform, CENTER, CENTER, x, y); | ||
if (localPointFromCenter.y > 0) { | ||
@@ -355,11 +387,24 @@ // we are pulling down, anchor up; | ||
var target = transform.target, | ||
uniScaleKey = target.canvas.uniScaleKey, isUniScalePressed = eventData[uniScaleKey], | ||
lockScalingX = target.lockScalingX, lockScalingY = target.lockScalingY, | ||
by = options.by, newPoint, scaleX, scaleY, dim; | ||
by = options.by, newPoint, scaleX, scaleY, dim, | ||
scaleProportionally = scaleIsProportional(eventData, target), | ||
forbidScaling = scalingIsForbidden(target, by, scaleProportionally), | ||
signX, signY; | ||
if (!isUniScalePressed && (lockScalingX || lockScalingY)) { | ||
if (forbidScaling) { | ||
return false; | ||
} | ||
newPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y); | ||
signX = sign(newPoint.x); | ||
signY = sign(newPoint.y); | ||
if (!transform.signX) { | ||
transform.signX = signX; | ||
} | ||
if (!transform.signY) { | ||
transform.signY = signY; | ||
} | ||
if (isUniScalePressed && lockScalingX && lockScalingY) { | ||
if (target.lockScalingFlip && | ||
(transform.signX !== signX || transform.signY !== signY) | ||
) { | ||
return false; | ||
@@ -369,6 +414,4 @@ } | ||
dim = target._getTransformedDimensions(); | ||
newPoint = getLocalPoint(target, transform.originX, transform.originY, x, y); | ||
// missing detection of flip and logic to switch the origin | ||
if (!isUniScalePressed && !by) { | ||
if (scaleProportionally && !by) { | ||
// uniform scaling | ||
@@ -392,9 +435,20 @@ var distance = Math.abs(newPoint.x) + Math.abs(newPoint.y), | ||
} | ||
if (transform.signX !== signX) { | ||
transform.originX = opposite[transform.originX]; | ||
scaleX *= -1; | ||
transform.signX = signX; | ||
} | ||
if (transform.signY !== signY) { | ||
transform.originY = opposite[transform.originY]; | ||
scaleY *= -1; | ||
transform.signY = signY; | ||
} | ||
// minScale is taken are in the setter. | ||
var oldScaleX = target.scaleX, oldScaleY = target.scaleY; | ||
if (!by) { | ||
target.set('scaleX', scaleX); | ||
target.set('scaleY', scaleY); | ||
!lockScalingX && target.set('scaleX', scaleX); | ||
!lockScalingY && target.set('scaleY', scaleY); | ||
} | ||
else { | ||
// forbidden cases already handled on top here. | ||
by === 'x' && target.set('scaleX', scaleX); | ||
@@ -440,4 +494,6 @@ by === 'y' && target.set('scaleY', scaleY); | ||
function changeWidth(eventData, transform, x, y) { | ||
var target = transform.target, localPoint = getLocalPoint(target, transform.originX, transform.originY, x, y); | ||
transform.target.set('width', Math.abs(localPoint.x)); | ||
var target = transform.target, localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y), | ||
strokePadding = target.strokeWidth / (target.strokeUniform ? target.scaleX : 1), | ||
newWidth = Math.abs(localPoint.x / target.scaleX) - strokePadding; | ||
target.set('width', Math.max(newWidth, 0)); | ||
return true; | ||
@@ -444,0 +500,0 @@ } |
@@ -11,5 +11,2 @@ (function(global) { | ||
styleOverride = styleOverride || {}; | ||
if (!this.getVisibility()) { | ||
return; | ||
} | ||
var size = styleOverride.cornerSize || fabricObject.cornerSize, | ||
@@ -36,5 +33,2 @@ transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? | ||
styleOverride = styleOverride || {}; | ||
if (!this.getVisibility()) { | ||
return; | ||
} | ||
var size = styleOverride.cornerSize || fabricObject.cornerSize, | ||
@@ -41,0 +35,0 @@ transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? |
@@ -137,2 +137,6 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOptions, doc) { | ||
} | ||
else { | ||
// if clip-path does not resolve to any element, delete the property. | ||
delete obj.clipPath; | ||
} | ||
}; | ||
@@ -139,0 +143,0 @@ |
@@ -18,3 +18,3 @@ (function(global) { | ||
* var filter = new fabric.Image.filters.Contrast({ | ||
* contrast: 40 | ||
* contrast: 0.25 | ||
* }); | ||
@@ -44,2 +44,7 @@ * object.filters.push(filter); | ||
/** | ||
* contrast value, range from -1 to 1. | ||
* @param {Number} contrast | ||
* @default 0 | ||
*/ | ||
contrast: 0, | ||
@@ -46,0 +51,0 @@ |
@@ -455,23 +455,4 @@ (function() { | ||
return gradient; | ||
}, | ||
} | ||
/* _FROM_SVG_END_ */ | ||
/** | ||
* Returns {@link fabric.Gradient} instance from its object representation | ||
* this function is uniquely used by Object.setGradient and is deprecated with it. | ||
* @static | ||
* @deprecated since 3.4.0 | ||
* @memberOf fabric.Gradient | ||
* @param {Object} obj | ||
* @param {Object} [options] Options object | ||
*/ | ||
forObject: function(obj, options) { | ||
options || (options = { }); | ||
__convertPercentUnitsToValues(obj, options.coords, options.gradientUnits, { | ||
// those values are to avoid errors. this function is uniquely used by | ||
viewBoxWidth: 100, | ||
viewBoxHeight: 100, | ||
}); | ||
return new fabric.Gradient(options); | ||
} | ||
}); | ||
@@ -478,0 +459,0 @@ |
@@ -177,2 +177,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { | ||
var propIsColor = | ||
_this.colorProperties.indexOf(property) > -1 || | ||
(propPair && _this.colorProperties.indexOf(propPair[1]) > -1); | ||
var currentValue = propPair | ||
@@ -186,10 +190,12 @@ ? this.get(propPair[0])[propPair[1]] | ||
if (~to.indexOf('=')) { | ||
to = currentValue + parseFloat(to.replace('=', '')); | ||
if (!propIsColor) { | ||
if (~to.indexOf('=')) { | ||
to = currentValue + parseFloat(to.replace('=', '')); | ||
} | ||
else { | ||
to = parseFloat(to); | ||
} | ||
} | ||
else { | ||
to = parseFloat(to); | ||
} | ||
fabric.util.animate({ | ||
var _options = { | ||
startValue: options.from, | ||
@@ -200,6 +206,6 @@ endValue: to, | ||
duration: options.duration, | ||
abort: options.abort && function() { | ||
abort: options.abort && function () { | ||
return options.abort.call(_this); | ||
}, | ||
onChange: function(value, valueProgress, timeProgress) { | ||
onChange: function (value, valueProgress, timeProgress) { | ||
if (propPair) { | ||
@@ -216,3 +222,3 @@ _this[propPair[0]][propPair[1]] = value; | ||
}, | ||
onComplete: function(value, valueProgress, timeProgress) { | ||
onComplete: function (value, valueProgress, timeProgress) { | ||
if (skipCallbacks) { | ||
@@ -225,4 +231,11 @@ return; | ||
} | ||
}); | ||
}; | ||
if (propIsColor) { | ||
fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options); | ||
} | ||
else { | ||
fabric.util.animate(_options); | ||
} | ||
} | ||
}); |
@@ -443,8 +443,22 @@ (function() { | ||
} | ||
if (!isClick) { | ||
var targetWasActive = target === this._activeObject; | ||
this._maybeGroupObjects(e); | ||
shouldRender || (shouldRender = this._shouldRender(target)); | ||
if (!shouldRender) { | ||
shouldRender = ( | ||
this._shouldRender(target) || | ||
(!targetWasActive && target === this._activeObject) | ||
); | ||
} | ||
} | ||
if (target) { | ||
var corner = target._findTargetCorner( | ||
this.getPointer(e, true), | ||
fabric.util.isTouchEvent(e) | ||
); | ||
var control = target.controls[corner], | ||
mouseUpHandler = control && control.getMouseUpHandler(e, target, control); | ||
if (mouseUpHandler) { | ||
mouseUpHandler(e, target, control); | ||
} | ||
target.isMoving = false; | ||
@@ -602,5 +616,2 @@ } | ||
} | ||
if (this.clipTo) { | ||
fabric.util.clipContext(this, this.contextTop); | ||
} | ||
var pointer = this.getPointer(e); | ||
@@ -629,5 +640,2 @@ this.freeDrawingBrush.onMouseDown(pointer, { e: e, pointer: pointer }); | ||
_onMouseUpInDrawingMode: function(e) { | ||
if (this.clipTo) { | ||
this.contextTop.restore(); | ||
} | ||
var pointer = this.getPointer(e); | ||
@@ -707,3 +715,13 @@ this._isCurrentlyDrawing = this.freeDrawingBrush.onMouseUp({ e: e, pointer: pointer }); | ||
} | ||
if (target === this._activeObject && (target.__corner || !shouldGroup)) { | ||
var corner = target._findTargetCorner( | ||
this.getPointer(e, true), | ||
fabric.util.isTouchEvent(e) | ||
); | ||
target.__corner = corner; | ||
if (target === this._activeObject && (corner || !shouldGroup)) { | ||
var control = target.controls[corner], | ||
mouseDownHandler = control && control.getMouseDownHandler(e, target, control); | ||
if (mouseDownHandler) { | ||
mouseDownHandler(e, target, control); | ||
} | ||
this._setupCurrentTransform(e, target, alreadySelected); | ||
@@ -919,2 +937,3 @@ } | ||
actionPerformed = false, | ||
actionHandler = transform.actionHandler, | ||
// this object could be created from the function in the control handlers | ||
@@ -935,4 +954,4 @@ options = { | ||
} | ||
else { | ||
(actionPerformed = transform.actionHandler(e, transform, x, y)) && this._fire(action, options); | ||
else if (actionHandler) { | ||
(actionPerformed = actionHandler(e, transform, x, y)) && this._fire(action, options); | ||
} | ||
@@ -939,0 +958,0 @@ transform.actionPerformed = transform.actionPerformed || actionPerformed; |
fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.StaticCanvas.prototype */ { | ||
/** | ||
* Populates canvas with data from the specified dataless JSON. | ||
* JSON format must conform to the one of {@link fabric.Canvas#toDatalessJSON} | ||
* @deprecated since 1.2.2 | ||
* @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 | ||
* @chainable | ||
* @tutorial {@link http://fabricjs.com/fabric-intro-part-3#deserialization} | ||
*/ | ||
loadFromDatalessJSON: function (json, callback, reviver) { | ||
return this.loadFromJSON(json, callback, reviver); | ||
}, | ||
/** | ||
* Populates canvas with data from the specified JSON. | ||
@@ -234,3 +216,2 @@ * JSON format must conform to the one of {@link fabric.Canvas#toJSON} | ||
var clone = new fabric.Canvas(el); | ||
clone.clipTo = this.clipTo; | ||
if (this.backgroundImage) { | ||
@@ -237,0 +218,0 @@ clone.setBackgroundImage(this.backgroundImage.src, function() { |
@@ -13,4 +13,4 @@ (function() { | ||
objectControls.ml = new fabric.Control({ | ||
name: 'ml', | ||
position: { x: -0.5, y: 0 }, | ||
x: -0.5, | ||
y: 0, | ||
cursorStyleHandler: scaleSkewStyleHandler, | ||
@@ -22,4 +22,4 @@ actionHandler: scalingXOrSkewingY, | ||
objectControls.mr = new fabric.Control({ | ||
name: 'mr', | ||
position: { x: 0.5, y: 0 }, | ||
x: 0.5, | ||
y: 0, | ||
cursorStyleHandler: scaleSkewStyleHandler, | ||
@@ -31,4 +31,4 @@ actionHandler: scalingXOrSkewingY, | ||
objectControls.mb = new fabric.Control({ | ||
name: 'mb', | ||
position: { x: 0, y: 0.5 }, | ||
x: 0, | ||
y: 0.5, | ||
cursorStyleHandler: scaleSkewStyleHandler, | ||
@@ -40,4 +40,4 @@ actionHandler: scalingYOrSkewingX, | ||
objectControls.mt = new fabric.Control({ | ||
name: 'mt', | ||
position: { x: 0, y: -0.5 }, | ||
x: 0, | ||
y: -0.5, | ||
cursorStyleHandler: scaleSkewStyleHandler, | ||
@@ -49,4 +49,4 @@ actionHandler: scalingYOrSkewingX, | ||
objectControls.tl = new fabric.Control({ | ||
name: 'tl', | ||
position: { x: -0.5, y: -0.5 }, | ||
x: -0.5, | ||
y: -0.5, | ||
cursorStyleHandler: scaleStyleHandler, | ||
@@ -57,4 +57,4 @@ actionHandler: scalingEqually | ||
objectControls.tr = new fabric.Control({ | ||
name: 'tr', | ||
position: { x: 0.5, y: -0.5 }, | ||
x: 0.5, | ||
y: -0.5, | ||
cursorStyleHandler: scaleStyleHandler, | ||
@@ -65,4 +65,4 @@ actionHandler: scalingEqually | ||
objectControls.bl = new fabric.Control({ | ||
name: 'bl', | ||
position: { x: -0.5, y: 0.5 }, | ||
x: -0.5, | ||
y: 0.5, | ||
cursorStyleHandler: scaleStyleHandler, | ||
@@ -73,4 +73,4 @@ actionHandler: scalingEqually | ||
objectControls.br = new fabric.Control({ | ||
name: 'br', | ||
position: { x: 0.5, y: 0.5 }, | ||
x: 0.5, | ||
y: 0.5, | ||
cursorStyleHandler: scaleStyleHandler, | ||
@@ -81,4 +81,4 @@ actionHandler: scalingEqually | ||
objectControls.mtr = new fabric.Control({ | ||
name: 'mtr', | ||
position: { x: 0, y: -0.5 }, | ||
x: 0, | ||
y: -0.5, | ||
actionHandler: controlHandlers.rotationWithSnapping, | ||
@@ -108,4 +108,4 @@ cursorStyleHandler: controlHandlers.rotationStyleHandler, | ||
textBoxControls.mr = new fabric.Control({ | ||
name: 'mr', | ||
position: { x: 0.5, y: 0 }, | ||
x: 0.5, | ||
y: 0, | ||
actionHandler: controlHandlers.changeWidth, | ||
@@ -117,4 +117,4 @@ cursorStyleHandler: scaleSkewStyleHandler, | ||
textBoxControls.ml = new fabric.Control({ | ||
name: 'ml', | ||
position: { x: -0.5, y: 0 }, | ||
x: -0.5, | ||
y: 0, | ||
actionHandler: controlHandlers.changeWidth, | ||
@@ -121,0 +121,0 @@ cursorStyleHandler: scaleSkewStyleHandler, |
@@ -604,2 +604,3 @@ (function() { | ||
var isTextChanged = (this._textBeforeEdit !== this.text); | ||
var hiddenTextarea = this.hiddenTextarea; | ||
this.selected = false; | ||
@@ -610,8 +611,7 @@ this.isEditing = false; | ||
if (this.hiddenTextarea) { | ||
this.hiddenTextarea.blur && this.hiddenTextarea.blur(); | ||
this.canvas && this.hiddenTextarea.parentNode.removeChild(this.hiddenTextarea); | ||
this.hiddenTextarea = null; | ||
if (hiddenTextarea) { | ||
hiddenTextarea.blur && hiddenTextarea.blur(); | ||
hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea); | ||
} | ||
this.hiddenTextarea = null; | ||
this.abortCursorAnimation(); | ||
@@ -730,3 +730,6 @@ this._restoreEditingProps(); | ||
/** | ||
* Inserts new style object | ||
* Handle insertion of more consecutive style lines for when one or more | ||
* newlines gets added to the text. Since current style needs to be shifted | ||
* first we shift the current style of the number lines needed, then we add | ||
* new lines from the last to the first. | ||
* @param {Number} lineIndex Index of a line | ||
@@ -740,3 +743,4 @@ * @param {Number} charIndex Index of a char | ||
newLineStyles = {}, | ||
somethingAdded = false; | ||
somethingAdded = false, | ||
isEndOfLine = this._unwrappedTextLines[lineIndex].length === charIndex; | ||
@@ -748,3 +752,2 @@ qty || (qty = 1); | ||
} | ||
// we clone styles of all chars | ||
@@ -758,17 +761,23 @@ // after cursor onto the current line | ||
// remove lines from the previous line since they're on a new line now | ||
delete this.styles[lineIndex][index]; | ||
if (!(isEndOfLine && charIndex === 0)) { | ||
delete this.styles[lineIndex][index]; | ||
} | ||
} | ||
} | ||
if (somethingAdded) { | ||
var styleCarriedOver = false; | ||
if (somethingAdded && !isEndOfLine) { | ||
// if is end of line, the extra style we copied | ||
// is probably not something we want | ||
this.styles[lineIndex + qty] = newLineStyles; | ||
styleCarriedOver = true; | ||
} | ||
else { | ||
delete this.styles[lineIndex + qty]; | ||
if (styleCarriedOver) { | ||
// skip the last line of since we already prepared it. | ||
qty--; | ||
} | ||
// for the other lines | ||
// for the all the lines or all the other lines | ||
// we clone current char style onto the next (otherwise empty) line | ||
while (qty > 1) { | ||
qty--; | ||
if (copiedStyle && copiedStyle[qty]) { | ||
this.styles[lineIndex + qty] = { 0: clone(copiedStyle[qty]) }; | ||
while (qty > 0) { | ||
if (copiedStyle && copiedStyle[qty - 1]) { | ||
this.styles[lineIndex + qty] = { 0: clone(copiedStyle[qty - 1]) }; | ||
} | ||
@@ -781,2 +790,3 @@ else if (currentCharStyle) { | ||
} | ||
qty--; | ||
} | ||
@@ -844,2 +854,3 @@ this._forceClearCache = true; | ||
addedLines = [0], linesLength = 0; | ||
// get an array of how many char per lines are being added. | ||
for (var i = 0; i < insertedText.length; i++) { | ||
@@ -854,2 +865,3 @@ if (insertedText[i] === '\n') { | ||
} | ||
// for the first line copy the style from the current char position. | ||
if (addedLines[0] > 0) { | ||
@@ -856,0 +868,0 @@ this.insertCharStyleObject(cursorLoc.lineIndex, cursorLoc.charIndex, addedLines[0], copiedStyle); |
@@ -96,2 +96,4 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { | ||
* find selectionEnd, initialize the drawing of either cursor or selection area | ||
* initializing a mousedDown on a text area will cancel fabricjs knowledge of | ||
* current compositionMode. It will be set to false. | ||
*/ | ||
@@ -106,2 +108,3 @@ _mouseDownHandler: function(options) { | ||
if (this.selected) { | ||
this.inCompositionMode = false; | ||
this.setCursorByClick(options.e); | ||
@@ -108,0 +111,0 @@ } |
@@ -83,7 +83,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { | ||
/** | ||
* Handles keyup event | ||
* Handles keydown event | ||
* only used for arrows and combination of modifier keys. | ||
* @param {Event} e Event object | ||
*/ | ||
onKeyDown: function(e) { | ||
if (!this.isEditing || this.inCompositionMode) { | ||
if (!this.isEditing) { | ||
return; | ||
@@ -104,2 +105,3 @@ } | ||
// if i press an arrow key just update selection | ||
this.inCompositionMode = false; | ||
this.clearContextTop(); | ||
@@ -151,3 +153,6 @@ this.renderCursorOrSelection(); | ||
removedText, insertedText, | ||
charDiff = nextCharCount - charCount; | ||
charDiff = nextCharCount - charCount, | ||
selectionStart = this.selectionStart, selectionEnd = this.selectionEnd, | ||
selection = selectionStart !== selectionEnd, | ||
copiedStyle, removeFrom, removeTo; | ||
if (this.hiddenTextarea.value === '') { | ||
@@ -169,14 +174,14 @@ this.styles = { }; | ||
); | ||
var backDelete = this.selectionStart > textareaSelection.selectionStart; | ||
var backDelete = selectionStart > textareaSelection.selectionStart; | ||
if (this.selectionStart !== this.selectionEnd) { | ||
removedText = this._text.slice(this.selectionStart, this.selectionEnd); | ||
charDiff += this.selectionEnd - this.selectionStart; | ||
if (selection) { | ||
removedText = this._text.slice(selectionStart, selectionEnd); | ||
charDiff += selectionEnd - selectionStart; | ||
} | ||
else if (nextCharCount < charCount) { | ||
if (backDelete) { | ||
removedText = this._text.slice(this.selectionEnd + charDiff, this.selectionEnd); | ||
removedText = this._text.slice(selectionEnd + charDiff, selectionEnd); | ||
} | ||
else { | ||
removedText = this._text.slice(this.selectionStart, this.selectionStart - charDiff); | ||
removedText = this._text.slice(selectionStart, selectionStart - charDiff); | ||
} | ||
@@ -186,20 +191,34 @@ } | ||
if (removedText && removedText.length) { | ||
if (this.selectionStart !== this.selectionEnd) { | ||
this.removeStyleFromTo(this.selectionStart, this.selectionEnd); | ||
if (insertedText.length) { | ||
// let's copy some style before deleting. | ||
// we want to copy the style before the cursor OR the style at the cursor if selection | ||
// is bigger than 0. | ||
copiedStyle = this.getSelectionStyles(selectionStart, selectionStart + 1, true); | ||
// now duplicate the style one for each inserted text. | ||
copiedStyle = insertedText.map(function() { | ||
// this return an array of references, but that is fine since we are | ||
// copying the style later. | ||
return copiedStyle[0]; | ||
}); | ||
} | ||
if (selection) { | ||
removeFrom = selectionStart; | ||
removeTo = selectionEnd; | ||
} | ||
else if (backDelete) { | ||
// detect differencies between forwardDelete and backDelete | ||
this.removeStyleFromTo(this.selectionEnd - removedText.length, this.selectionEnd); | ||
removeFrom = selectionEnd - removedText.length; | ||
removeTo = selectionEnd; | ||
} | ||
else { | ||
this.removeStyleFromTo(this.selectionEnd, this.selectionEnd + removedText.length); | ||
removeFrom = selectionEnd; | ||
removeTo = selectionEnd + removedText.length; | ||
} | ||
this.removeStyleFromTo(removeFrom, removeTo); | ||
} | ||
if (insertedText.length) { | ||
if (fromPaste && insertedText.join('') === fabric.copiedText && !fabric.disableStyleCopyPaste) { | ||
this.insertNewStyleBlock(insertedText, this.selectionStart, fabric.copiedTextStyle); | ||
copiedStyle = fabric.copiedTextStyle; | ||
} | ||
else { | ||
this.insertNewStyleBlock(insertedText, this.selectionStart); | ||
} | ||
this.insertNewStyleBlock(insertedText, selectionStart, copiedStyle); | ||
} | ||
@@ -206,0 +225,0 @@ this.updateFromTextArea(); |
(function() { | ||
function getCoords(coords) { | ||
function arrayFromCoords(coords) { | ||
return [ | ||
@@ -12,18 +12,17 @@ new fabric.Point(coords.tl.x, coords.tl.y), | ||
var degreesToRadians = fabric.util.degreesToRadians, | ||
multiplyMatrices = fabric.util.multiplyTransformMatrices, | ||
transformPoint = fabric.util.transformPoint; | ||
var util = fabric.util, | ||
degreesToRadians = util.degreesToRadians, | ||
multiplyMatrices = util.multiplyTransformMatrices, | ||
transformPoint = util.transformPoint; | ||
fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { | ||
util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { | ||
/** | ||
* Describe object's corner position in canvas element coordinates. | ||
* properties are tl,mt,tr,ml,mr,bl,mb,br,mtr for the main controls. | ||
* properties are depending on control keys and padding the main controls. | ||
* each property is an object with x, y and corner. | ||
* The `corner` property contains in a similar manner the 4 points of the | ||
* interactive area of the corner. | ||
* The coordinates depends from this properties: width, height, scaleX, scaleY | ||
* skewX, skewY, angle, strokeWidth, viewportTransform, top, left, padding. | ||
* The coordinates get updated with @method setCoords. | ||
* You can calculate them without updating with @method calcCoords; | ||
* The coordinates depends from the controls positionHandler and are used | ||
* to draw and locate controls | ||
* @memberOf fabric.Object.prototype | ||
@@ -42,3 +41,3 @@ */ | ||
* The coordinates get updated with @method setCoords. | ||
* You can calculate them without updating with @method calcCoords(true); | ||
* You can calculate them without updating with @method calcACoords(); | ||
* @memberOf fabric.Object.prototype | ||
@@ -49,2 +48,10 @@ */ | ||
/** | ||
* Describe object's corner position in canvas element coordinates. | ||
* includes padding. Used of object detection. | ||
* set and refreshed with setCoords and calcCoords. | ||
* @memberOf fabric.Object.prototype | ||
*/ | ||
lineCoords: null, | ||
/** | ||
* storage for object transform matrix | ||
@@ -67,12 +74,27 @@ */ | ||
* return correct set of coordinates for intersection | ||
* this will return either aCoords or lineCoords. | ||
* @param {Boolean} absolute will return aCoords if true or lineCoords | ||
* @return {Object} {tl, tr, br, bl} points | ||
*/ | ||
getCoords: function(absolute, calculate) { | ||
if (!this.oCoords) { | ||
this.setCoords(); | ||
_getCoords: function(absolute, calculate) { | ||
if (calculate) { | ||
return (absolute ? this.calcACoords() : this.calcLineCoords()); | ||
} | ||
var coords = absolute ? this.aCoords : this.lineCoords; | ||
return getCoords(calculate ? this.calcCoords(absolute) : coords); | ||
if (!this.aCoords || !this.lineCoords) { | ||
this.setCoords(true); | ||
} | ||
return (absolute ? this.aCoords : this.lineCoords); | ||
}, | ||
/** | ||
* return correct set of coordinates for intersection | ||
* this will return either aCoords or lineCoords. | ||
* The coords are returned in an array. | ||
* @return {Array} [tl, tr, br, bl] of points | ||
*/ | ||
getCoords: function(absolute, calculate) { | ||
return arrayFromCoords(this._getCoords(absolute, calculate)); | ||
}, | ||
/** | ||
* Checks if object intersects with an area formed by 2 points | ||
@@ -160,3 +182,3 @@ * @param {Object} pointTL top-left point of area | ||
containsPoint: function(point, lines, absolute, calculate) { | ||
var coords = calculate ? this.calcLineCoords(absolute) : absolute ? this.aCoords : this.lineCoords, | ||
var coords = this._getCoords(absolute, calculate), | ||
lines = lines || this._getImageLines(coords), | ||
@@ -179,8 +201,9 @@ xPoints = this._findCrossPoints(point, lines); | ||
var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br; | ||
var points = this.getCoords(true, calculate), point; | ||
for (var i = 0; i < 4; i++) { | ||
point = points[i]; | ||
if (point.x <= pointBR.x && point.x >= pointTL.x && point.y <= pointBR.y && point.y >= pointTL.y) { | ||
return true; | ||
} | ||
var points = this.getCoords(true, calculate); | ||
// if some point is on screen, the object is on screen. | ||
if (points.some(function(point) { | ||
return point.x <= pointBR.x && point.x >= pointTL.x && | ||
point.y <= pointBR.y && point.y >= pointTL.y; | ||
})) { | ||
return true; | ||
} | ||
@@ -225,3 +248,7 @@ // no points on screen, check intersection with absolute coordinates | ||
} | ||
return this._containsCenterOfCanvas(pointTL, pointBR, calculate); | ||
var allPointsAreOutside = this.getCoords(true, calculate).every(function(point) { | ||
return (point.x >= pointBR.x || point.x <= pointTL.x) && | ||
(point.y >= pointBR.y || point.y <= pointTL.y); | ||
}); | ||
return allPointsAreOutside && this._containsCenterOfCanvas(pointTL, pointBR, calculate); | ||
}, | ||
@@ -332,3 +359,3 @@ | ||
var coords = this.getCoords(absolute, calculate); | ||
return fabric.util.makeBoundingBoxFromPoints(coords); | ||
return util.makeBoundingBoxFromPoints(coords); | ||
}, | ||
@@ -415,4 +442,6 @@ | ||
* Calculates and returns the .coords of an object. | ||
* unused by the library, only for the end dev. | ||
* @return {Object} Object with tl, tr, br, bl .... | ||
* @chainable | ||
* @deprecated | ||
*/ | ||
@@ -427,24 +456,16 @@ calcCoords: function(absolute) { | ||
calcLineCoords: function(ignoreZoom) { | ||
if (!this.aCoords) { this.aCoords = this.calcACoords(); } | ||
var vpt = this.getViewportTransform(); | ||
var padding = this.padding, angle = degreesToRadians(this.angle), | ||
cos = fabric.util.cos(angle), sin = fabric.util.sin(angle), | ||
calcLineCoords: function() { | ||
var vpt = this.getViewportTransform(), | ||
padding = this.padding, angle = degreesToRadians(this.angle), | ||
cos = util.cos(angle), sin = util.sin(angle), | ||
cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP, | ||
cosPMinusSinP = cosP - sinP, aCoords = this.aCoords; | ||
cosPMinusSinP = cosP - sinP, aCoords = this.calcACoords(); | ||
var lineCoords = { | ||
tl: { x: aCoords.tl.x, y: aCoords.tl.y }, | ||
tr: { x: aCoords.tr.x, y: aCoords.tr.y }, | ||
bl: { x: aCoords.bl.x, y: aCoords.bl.y }, | ||
br: { x: aCoords.br.x, y: aCoords.br.y }, | ||
tl: transformPoint(aCoords.tl, vpt), | ||
tr: transformPoint(aCoords.tr, vpt), | ||
bl: transformPoint(aCoords.bl, vpt), | ||
br: transformPoint(aCoords.br, vpt), | ||
}; | ||
if (!ignoreZoom) { | ||
lineCoords.tl = transformPoint(aCoords.tl, vpt); | ||
lineCoords.tr = transformPoint(aCoords.tr, vpt); | ||
lineCoords.bl = transformPoint(aCoords.bl, vpt); | ||
lineCoords.br = transformPoint(aCoords.br, vpt); | ||
} | ||
if (padding) { | ||
@@ -467,8 +488,9 @@ lineCoords.tl.x -= cosPMinusSinP; | ||
translateMatrix = this._calcTranslateMatrix(), | ||
startMatrix = multiplyMatrices(translateMatrix, rotateMatrix), | ||
vpt = this.getViewportTransform(), | ||
finalMatrix = multiplyMatrices(vpt, startMatrix), | ||
dim = this._getTransformedDimensions(), | ||
startMatrix = multiplyMatrices(vpt, translateMatrix), | ||
finalMatrix = multiplyMatrices(startMatrix, rotateMatrix), | ||
finalMatrix = multiplyMatrices(finalMatrix, [1 / vpt[0], 0, 0, 1 / vpt[3], 0, 0]), | ||
dim = this._calculateCurrentDimensions(), | ||
coords = {}; | ||
this.forEachControl(function(control, fabricObject, key) { | ||
this.forEachControl(function(control, key, fabricObject) { | ||
coords[key] = control.positionHandler(dim, finalMatrix, fabricObject); | ||
@@ -507,18 +529,19 @@ }); | ||
* Sets corner position coordinates based on current angle, width and height. | ||
* oCoords are used to find the corners | ||
* aCoords are used to quickly find an object on the canvas | ||
* lineCoords are used to quickly find object during pointer events. | ||
* See {@link https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords|When-to-call-setCoords} | ||
* @param {Boolean} [ignoreZoom] set oCoords with or without the viewport transform. | ||
* @param {Boolean} [skipAbsolute] skip calculation of aCoords, useful in setViewportTransform | ||
* @param {Boolean} [skipCorners] skip calculation of oCoords. | ||
* @return {fabric.Object} thisArg | ||
* @chainable | ||
*/ | ||
setCoords: function(ignoreZoom, skipAbsolute) { | ||
// this.oCoords = this.calcCoords(ignoreZoom); | ||
if (!skipAbsolute) { | ||
this.aCoords = this.calcACoords(); | ||
setCoords: function(skipCorners) { | ||
this.aCoords = this.calcACoords(); | ||
this.lineCoords = this.calcLineCoords(); | ||
if (skipCorners) { | ||
return this; | ||
} | ||
// set coordinates of the draggable boxes in the corners used to scale/rotate the image | ||
this.oCoords = this.calcOCoords(); | ||
this.lineCoords = this.calcLineCoords(ignoreZoom); | ||
// set coordinates of the draggable boxes in the corners used to scale/rotate the image | ||
ignoreZoom || (this._setCornerCoords && this._setCornerCoords()); | ||
this._setCornerCoords && this._setCornerCoords(); | ||
return this; | ||
@@ -532,3 +555,3 @@ }, | ||
_calcRotateMatrix: function() { | ||
return fabric.util.calcRotateMatrix(this); | ||
return util.calcRotateMatrix(this); | ||
}, | ||
@@ -559,15 +582,16 @@ | ||
* @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations | ||
* There are some situation in which this is useful to avoid the fake rotation. | ||
* @return {Array} transform matrix for the object | ||
*/ | ||
calcTransformMatrix: function(skipGroup) { | ||
if (skipGroup) { | ||
return this.calcOwnMatrix(); | ||
var matrix = this.calcOwnMatrix(); | ||
if (skipGroup || !this.group) { | ||
return matrix; | ||
} | ||
var key = this.transformMatrixKey(), cache = this.matrixCache || (this.matrixCache = {}); | ||
var key = this.transformMatrixKey(skipGroup), cache = this.matrixCache || (this.matrixCache = {}); | ||
if (cache.key === key) { | ||
return cache.value; | ||
} | ||
var matrix = this.calcOwnMatrix(); | ||
if (this.group) { | ||
matrix = multiplyMatrices(this.group.calcTransformMatrix(), matrix); | ||
matrix = multiplyMatrices(this.group.calcTransformMatrix(false), matrix); | ||
} | ||
@@ -589,7 +613,16 @@ cache.key = key; | ||
} | ||
var tMatrix = this._calcTranslateMatrix(); | ||
this.translateX = tMatrix[4]; | ||
this.translateY = tMatrix[5]; | ||
var tMatrix = this._calcTranslateMatrix(), | ||
options = { | ||
angle: this.angle, | ||
translateX: tMatrix[4], | ||
translateY: tMatrix[5], | ||
scaleX: this.scaleX, | ||
scaleY: this.scaleY, | ||
skewX: this.skewX, | ||
skewY: this.skewY, | ||
flipX: this.flipX, | ||
flipY: this.flipY, | ||
}; | ||
cache.key = key; | ||
cache.value = fabric.util.composeMatrix(this); | ||
cache.value = util.composeMatrix(options); | ||
return cache.value; | ||
@@ -607,3 +640,3 @@ }, | ||
_calcDimensionsTransformMatrix: function(skewX, skewY, flipping) { | ||
return fabric.util.calcDimensionsMatrix({ | ||
return util.calcDimensionsMatrix({ | ||
skewX: skewX, | ||
@@ -658,31 +691,9 @@ skewY: skewY, | ||
} | ||
else { | ||
dimX /= 2; | ||
dimY /= 2; | ||
} | ||
var points = [ | ||
{ | ||
x: -dimX, | ||
y: -dimY | ||
}, | ||
{ | ||
x: dimX, | ||
y: -dimY | ||
}, | ||
{ | ||
x: -dimX, | ||
y: dimY | ||
}, | ||
{ | ||
x: dimX, | ||
y: dimY | ||
}], | ||
transformMatrix = fabric.util.calcDimensionsMatrix({ | ||
scaleX: this.scaleX, | ||
scaleY: this.scaleY, | ||
skewX: skewX, | ||
skewY: skewY, | ||
}), | ||
bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix); | ||
return this._finalizeDimensions(bbox.width, bbox.height); | ||
var bbox = util.sizeAfterTransform(dimX, dimY, { | ||
scaleX: this.scaleX, | ||
scaleY: this.scaleY, | ||
skewX: skewX, | ||
skewY: skewY, | ||
}); | ||
return this._finalizeDimensions(bbox.x, bbox.y); | ||
}, | ||
@@ -704,4 +715,6 @@ | ||
}, | ||
/* | ||
* Calculate object dimensions for controls, including padding and canvas zoom. | ||
* Calculate object dimensions for controls box, including padding and canvas zoom. | ||
* and active selection | ||
* private | ||
@@ -713,3 +726,2 @@ */ | ||
p = transformPoint(dim, vpt, true); | ||
return p.scalarAdd(2 * this.padding); | ||
@@ -716,0 +728,0 @@ }, |
@@ -6,3 +6,2 @@ (function() { | ||
fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { | ||
/** | ||
@@ -66,3 +65,3 @@ * Determines which corner has been clicked | ||
for (var i in this.controls) { | ||
fn(this.controls[i], this, i); | ||
fn(this.controls[i], i, this); | ||
}; | ||
@@ -175,3 +174,3 @@ }, | ||
var wh = this._calculateCurrentDimensions(), | ||
strokeWidth = 1 / this.borderScaleFactor, | ||
strokeWidth = this.borderScaleFactor, | ||
width = wh.x + strokeWidth, | ||
@@ -195,7 +194,7 @@ height = wh.y + strokeWidth, | ||
if (hasControls) { | ||
this.forEachControl(function(control) { | ||
ctx.beginPath(); | ||
this.forEachControl(function(control, key, fabricObject) { | ||
// in this moment, the ctx is centered on the object. | ||
// width and height of the above function are the size of the bbox. | ||
ctx.beginPath(); | ||
if (control.withConnection && control.getVisibility()) { | ||
if (control.withConnection && control.getVisibility(fabricObject, key)) { | ||
// reset movement for each control | ||
@@ -230,17 +229,13 @@ shouldStroke = true; | ||
styleOverride = styleOverride || {}; | ||
var p = this._getNonTransformedDimensions(), | ||
matrix = fabric.util.composeMatrix({ | ||
scaleX: options.scaleX, | ||
scaleY: options.scaleY, | ||
skewX: options.skewX | ||
}), | ||
wh = fabric.util.transformPoint(p, matrix), | ||
strokeWidth = 1 / this.borderScaleFactor, | ||
width = wh.x + strokeWidth, | ||
height = wh.y + strokeWidth; | ||
var bbox = fabric.util.sizeAfterTransform(this.width, this.height, options), | ||
strokeWidth = this.strokeWidth, | ||
strokeUniform = this.strokeUniform, | ||
borderScaleFactor = this.borderScaleFactor, | ||
width = | ||
bbox.x + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleX) + borderScaleFactor, | ||
height = | ||
bbox.y + strokeWidth * (strokeUniform ? this.canvas.getZoom() : options.scaleY) + borderScaleFactor; | ||
ctx.save(); | ||
this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null); | ||
ctx.strokeStyle = styleOverride.borderColor || this.borderColor; | ||
ctx.strokeRect( | ||
@@ -275,9 +270,10 @@ -width / 2, | ||
this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray, null); | ||
this.setCoords(false); | ||
for (var c in this.controls) { | ||
this.controls[c].render(ctx, | ||
this.oCoords[c].x, | ||
this.oCoords[c].y, styleOverride, this); | ||
} | ||
this.setCoords(); | ||
this.forEachControl(function(control, key, fabricObject) { | ||
if (control.getVisibility(fabricObject, key)) { | ||
control.render(ctx, | ||
fabricObject.oCoords[key].x, | ||
fabricObject.oCoords[key].y, styleOverride, fabricObject); | ||
} | ||
}); | ||
ctx.restore(); | ||
@@ -305,3 +301,6 @@ | ||
setControlVisible: function(controlKey, visible) { | ||
this.controls[controlKey].setVisibility(visible, this, controlKey); | ||
if (!this._controlsVisibility) { | ||
this._controlsVisibility = {}; | ||
} | ||
this._controlsVisibility[controlKey] = visible; | ||
return this; | ||
@@ -334,14 +333,2 @@ }, | ||
/** | ||
* Returns the instance of the control visibility set for this object. | ||
* @private | ||
* @returns {Object} | ||
*/ | ||
_getControlsVisibility: function() { | ||
var visibility = {}; | ||
this.forEachControl(function(control, fabricObject, key) { | ||
visibility[key] = control.getVisibility(fabricObject, key); | ||
}); | ||
return visibility; | ||
}, | ||
@@ -348,0 +335,0 @@ /** |
@@ -12,3 +12,3 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ { | ||
} | ||
else { | ||
else if (this.canvas) { | ||
this.canvas.sendToBack(this); | ||
@@ -28,3 +28,3 @@ } | ||
} | ||
else { | ||
else if (this.canvas) { | ||
this.canvas.bringToFront(this); | ||
@@ -45,3 +45,3 @@ } | ||
} | ||
else { | ||
else if (this.canvas) { | ||
this.canvas.sendBackwards(this, intersecting); | ||
@@ -62,3 +62,3 @@ } | ||
} | ||
else { | ||
else if (this.canvas) { | ||
this.canvas.bringForward(this, intersecting); | ||
@@ -79,3 +79,3 @@ } | ||
} | ||
else { | ||
else if (this.canvas) { | ||
this.canvas.moveTo(this, index); | ||
@@ -82,0 +82,0 @@ } |
@@ -105,7 +105,5 @@ /* _TO_SVG_START_ */ | ||
getSvgTextDecoration: function(style) { | ||
if ('overline' in style || 'underline' in style || 'linethrough' in style) { | ||
return (style.overline ? 'overline ' : '') + | ||
(style.underline ? 'underline ' : '') + (style.linethrough ? 'line-through ' : ''); | ||
} | ||
return ''; | ||
return ['overline', 'underline', 'line-through'].filter(function(decoration) { | ||
return style[decoration.replace('-', '')]; | ||
}).join(' '); | ||
}, | ||
@@ -141,13 +139,5 @@ | ||
return svgTransform + | ||
(additionalTransform || '') + this.getSvgTransformMatrix() + '" '; | ||
(additionalTransform || '') + '" '; | ||
}, | ||
/** | ||
* Returns transform-string for svg-export from the transform matrix of single elements | ||
* @return {String} | ||
*/ | ||
getSvgTransformMatrix: function() { | ||
return this.transformMatrix ? ' ' + fabric.util.matrixToSVG(this.transformMatrix) : ''; | ||
}, | ||
_setSVGBg: function(textBgRects) { | ||
@@ -154,0 +144,0 @@ if (this.backgroundColor) { |
@@ -23,3 +23,2 @@ (function() { | ||
* Observes specified event | ||
* @deprecated `observe` deprecated since 0.8.34 (use `on` instead) | ||
* @memberOf fabric.Observable | ||
@@ -32,3 +31,3 @@ * @alias on | ||
*/ | ||
function observe(eventName, handler) { | ||
function on(eventName, handler) { | ||
if (!this.__eventListeners) { | ||
@@ -55,3 +54,2 @@ this.__eventListeners = { }; | ||
* without arguments removes all handlers for all events | ||
* @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead) | ||
* @memberOf fabric.Observable | ||
@@ -64,3 +62,3 @@ * @alias off | ||
*/ | ||
function stopObserving(eventName, handler) { | ||
function off(eventName, handler) { | ||
if (!this.__eventListeners) { | ||
@@ -90,5 +88,3 @@ return this; | ||
* Fires event with an optional options object | ||
* @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead) | ||
* @memberOf fabric.Observable | ||
* @alias trigger | ||
* @param {String} eventName Event name to fire | ||
@@ -124,10 +120,6 @@ * @param {Object} [options] Options object | ||
fabric.Observable = { | ||
observe: observe, | ||
stopObserving: stopObserving, | ||
fire: fire, | ||
on: observe, | ||
off: stopObserving, | ||
trigger: fire | ||
on: on, | ||
off: off, | ||
}; | ||
})(); |
@@ -44,18 +44,3 @@ /** | ||
* @private | ||
* @param {Object} [options] Options object | ||
*/ | ||
_initClipping: function(options) { | ||
if (!options.clipTo || typeof options.clipTo !== 'string') { | ||
return; | ||
} | ||
var functionBody = fabric.util.getFunctionBody(options.clipTo); | ||
if (typeof functionBody !== 'undefined') { | ||
this.clipTo = new Function('ctx', functionBody); | ||
} | ||
}, | ||
/** | ||
* @private | ||
*/ | ||
_setObject: function(obj) { | ||
@@ -79,8 +64,3 @@ for (var prop in obj) { | ||
else { | ||
if (typeof value === 'function' && key !== 'clipTo') { | ||
this._set(key, value(this.get(key))); | ||
} | ||
else { | ||
this._set(key, value); | ||
} | ||
this._set(key, value); | ||
} | ||
@@ -87,0 +67,0 @@ return this; |
@@ -14,2 +14,3 @@ (function() { | ||
}); | ||
extend(origin[destination], tmpObj, deep); | ||
@@ -46,3 +47,4 @@ } | ||
// would be iterated as an object, this would lead to possible infinite recursion | ||
if (key === 'canvas') { | ||
// we do not want to compare those. | ||
if (key === 'canvas' || key === 'group') { | ||
continue; | ||
@@ -49,0 +51,0 @@ } |
@@ -165,3 +165,3 @@ (function() { | ||
* @param {Number} [selectionStart] Optional index. When not given, current selectionStart is used. | ||
* @param {Boolean} [skipWrapping] consider the location for unwrapped lines. usefull to manage styles. | ||
* @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles. | ||
*/ | ||
@@ -168,0 +168,0 @@ get2DCursorLocation: function(selectionStart, skipWrapping) { |
@@ -52,3 +52,4 @@ (function(global) { | ||
'clip-rule': 'clipRule', | ||
'vector-effect': 'strokeUniform' | ||
'vector-effect': 'strokeUniform', | ||
'image-rendering': 'imageSmoothing', | ||
}, | ||
@@ -87,4 +88,4 @@ | ||
} | ||
else if (attr === 'vector-effect') { | ||
value = value === 'non-scaling-stroke'; | ||
else if (attr === 'strokeUniform') { | ||
return (value === 'non-scaling-stroke'); | ||
} | ||
@@ -139,5 +140,8 @@ else if (attr === 'strokeDashArray') { | ||
} | ||
else if (attr === 'href' || attr === 'xlink:href') { | ||
else if (attr === 'href' || attr === 'xlink:href' || attr === 'font') { | ||
return value; | ||
} | ||
else if (attr === 'imageSmoothing') { | ||
return (value === 'optimizeQuality' ? true : false); | ||
} | ||
else { | ||
@@ -536,3 +540,5 @@ parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize); | ||
function applyViewboxTransform(element) { | ||
if (!fabric.svgViewBoxElementsRegEx.test(element.nodeName)) { | ||
return; | ||
} | ||
var viewBoxAttr = element.getAttribute('viewBox'), | ||
@@ -549,4 +555,3 @@ scaleX = 1, | ||
preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '', | ||
missingViewBox = (!viewBoxAttr || !fabric.svgViewBoxElementsRegEx.test(element.nodeName) | ||
|| !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))), | ||
missingViewBox = (!viewBoxAttr || !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))), | ||
missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'), | ||
@@ -560,2 +565,12 @@ toBeParsed = missingViewBox && missingDimAttr, | ||
if (missingViewBox) { | ||
if (((x || y) && element.parentNode.nodeName !== '#document')) { | ||
translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') '; | ||
matrix = (element.getAttribute('transform') || '') + translateMatrix; | ||
element.setAttribute('transform', matrix); | ||
element.removeAttribute('x'); | ||
element.removeAttribute('y'); | ||
} | ||
} | ||
if (toBeParsed) { | ||
@@ -568,2 +583,3 @@ return parsedDim; | ||
parsedDim.height = parseUnit(heightAttr); | ||
// set a transform for elements that have x y and are inner(only) SVGs | ||
return parsedDim; | ||
@@ -621,4 +637,3 @@ } | ||
} | ||
if (x || y) { | ||
if ((x || y) && element.parentNode.nodeName !== '#document') { | ||
translateMatrix = ' translate(' + parseUnit(x) + ' ' + parseUnit(y) + ') '; | ||
@@ -633,3 +648,4 @@ } | ||
(minY * scaleY + heightDiff) + ') '; | ||
parsedDim.viewboxTransform = fabric.parseTransformAttribute(matrix); | ||
// seems unused. | ||
// parsedDim.viewboxTransform = fabric.parseTransformAttribute(matrix); | ||
if (element.nodeName === 'svg') { | ||
@@ -645,2 +661,4 @@ el = element.ownerDocument.createElementNS(fabric.svgNS, 'g'); | ||
el = element; | ||
el.removeAttribute('x'); | ||
el.removeAttribute('y'); | ||
matrix = el.getAttribute('transform') + matrix; | ||
@@ -703,3 +721,2 @@ } | ||
}); | ||
if (!elements || (elements && !elements.length)) { | ||
@@ -980,4 +997,4 @@ callback && callback([], {}); | ||
for (i = 0, len = styles.length; i < len; i++) { | ||
// IE9 doesn't support textContent, but provides text instead. | ||
var styleContents = styles[i].textContent || styles[i].text; | ||
// <style/> could produce `undefined`, covering this case with '' | ||
var styleContents = styles[i].textContent || ''; | ||
@@ -1043,8 +1060,2 @@ // remove comments | ||
var xml = r.responseXML; | ||
if (xml && !xml.documentElement && fabric.window.ActiveXObject && r.responseText) { | ||
xml = new ActiveXObject('Microsoft.XMLDOM'); | ||
xml.async = 'false'; | ||
//IE chokes on DOCTYPE | ||
xml.loadXML(r.responseText.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i, '')); | ||
} | ||
if (!xml || !xml.documentElement) { | ||
@@ -1071,17 +1082,4 @@ callback && callback(null); | ||
loadSVGFromString: function(string, callback, reviver, options) { | ||
string = string.trim(); | ||
var doc; | ||
if (typeof fabric.window.DOMParser !== 'undefined') { | ||
var parser = new fabric.window.DOMParser(); | ||
if (parser && parser.parseFromString) { | ||
doc = parser.parseFromString(string, 'text/xml'); | ||
} | ||
} | ||
else if (fabric.window.ActiveXObject) { | ||
doc = new ActiveXObject('Microsoft.XMLDOM'); | ||
doc.async = 'false'; | ||
// IE chokes on DOCTYPE | ||
doc.loadXML(string.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i, '')); | ||
} | ||
var parser = new fabric.window.DOMParser(), | ||
doc = parser.parseFromString(string.trim(), 'text/xml'); | ||
fabric.parseSVGDocument(doc.documentElement, function (results, _options, elements, allElements) { | ||
@@ -1088,0 +1086,0 @@ callback(results, _options, elements, allElements); |
@@ -69,7 +69,2 @@ (function() { | ||
} | ||
// function string | ||
if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') { | ||
this.source = new Function(fabric.util.getFunctionBody(options.source)); | ||
callback && callback(this); | ||
} | ||
else { | ||
@@ -79,5 +74,5 @@ // img src string | ||
this.source = fabric.util.createImage(); | ||
fabric.util.loadImage(options.source, function(img) { | ||
fabric.util.loadImage(options.source, function(img, isError) { | ||
_this.source = img; | ||
callback && callback(_this); | ||
callback && callback(_this, isError); | ||
}, null, this.crossOrigin); | ||
@@ -96,8 +91,4 @@ } | ||
// callback | ||
if (typeof this.source === 'function') { | ||
source = String(this.source); | ||
} | ||
// <img> element | ||
else if (typeof this.source.src === 'string') { | ||
if (typeof this.source.src === 'string') { | ||
source = this.source.src; | ||
@@ -183,4 +174,3 @@ } | ||
toLive: function(ctx) { | ||
var source = typeof this.source === 'function' ? this.source() : this.source; | ||
var source = this.source; | ||
// if the image failed to load, return, and allow rest to continue loading | ||
@@ -187,0 +177,0 @@ if (!source) { |
@@ -110,5 +110,5 @@ (function(global) { | ||
_updateObjectsACoords: function() { | ||
var ignoreZoom = true; | ||
var skipControls = true; | ||
for (var i = this._objects.length; i--; ){ | ||
this._objects[i].setCoords(ignoreZoom); | ||
this._objects[i].setCoords(skipControls); | ||
} | ||
@@ -136,3 +136,3 @@ }, | ||
objectTop = object.top, | ||
ignoreZoom = true; | ||
skipControls = true; | ||
@@ -144,3 +144,3 @@ object.set({ | ||
object.group = this; | ||
object.setCoords(ignoreZoom); | ||
object.setCoords(skipControls); | ||
}, | ||
@@ -309,4 +309,4 @@ | ||
willDrawShadow: function() { | ||
if (this.shadow) { | ||
return fabric.Object.prototype.willDrawShadow.call(this); | ||
if (fabric.Object.prototype.willDrawShadow.call(this)) { | ||
return true; | ||
} | ||
@@ -469,5 +469,5 @@ for (var i = 0, len = this._objects.length; i < len; i++) { | ||
setObjectsCoords: function() { | ||
var ignoreZoom = true, skipAbsolute = true; | ||
var skipControls = true; | ||
this.forEachObject(function(object) { | ||
object.setCoords(ignoreZoom, skipAbsolute); | ||
object.setCoords(skipControls); | ||
}); | ||
@@ -486,8 +486,7 @@ return this; | ||
i = 0, iLen = this._objects.length, | ||
j, jLen = props.length, | ||
ignoreZoom = true; | ||
j, jLen = props.length; | ||
for ( ; i < iLen; ++i) { | ||
o = this._objects[i]; | ||
o.setCoords(ignoreZoom); | ||
o.aCoords = o.calcACoords(); | ||
for (j = 0; j < jLen; j++) { | ||
@@ -494,0 +493,0 @@ prop = props[j]; |
@@ -33,10 +33,2 @@ (function(global) { | ||
/** | ||
* crossOrigin value (one of "", "anonymous", "use-credentials") | ||
* @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes | ||
* @type String | ||
* @default | ||
*/ | ||
crossOrigin: '', | ||
/** | ||
* Width of a stroke. | ||
@@ -129,2 +121,11 @@ * For image quality a stroke multiple of 2 gives better results. | ||
/** | ||
* Indicates whether this canvas will use image smoothing when painting this image. | ||
* Also influence if the cacheCanvas for this image uses imageSmoothing | ||
* @since 4.0.0-beta.11 | ||
* @type Boolean | ||
* @default | ||
*/ | ||
imageSmoothing: true, | ||
/** | ||
* Constructor | ||
@@ -204,11 +205,6 @@ * @param {HTMLImageElement | String} element Image element | ||
/** | ||
* Sets crossOrigin value (on an instance and corresponding image element) | ||
* @return {fabric.Image} thisArg | ||
* @chainable | ||
* Get the crossOrigin value (of the corresponding image element) | ||
*/ | ||
setCrossOrigin: function(value) { | ||
this.crossOrigin = value; | ||
this._element.crossOrigin = value; | ||
return this; | ||
getCrossOrigin: function() { | ||
return this._originalElement && (this._originalElement.crossOrigin || null); | ||
}, | ||
@@ -284,5 +280,6 @@ | ||
'toObject', | ||
['crossOrigin', 'cropX', 'cropY'].concat(propertiesToInclude) | ||
['cropX', 'cropY'].concat(propertiesToInclude) | ||
), { | ||
src: this.getSrc(), | ||
crossOrigin: this.getCrossOrigin(), | ||
filters: filters, | ||
@@ -311,4 +308,7 @@ }); | ||
_toSVG: function() { | ||
var svgString = [], imageMarkup = [], strokeSvg, | ||
x = -this.width / 2, y = -this.height / 2, clipPath = ''; | ||
var svgString = [], imageMarkup = [], strokeSvg, element = this._element, | ||
x = -this.width / 2, y = -this.height / 2, clipPath = '', imageRendering = ''; | ||
if (!element) { | ||
return []; | ||
} | ||
if (this.hasCrop()) { | ||
@@ -323,2 +323,5 @@ var clipPathId = fabric.Object.__uid++; | ||
} | ||
if (!this.imageSmoothing) { | ||
imageRendering = '" image-rendering="optimizeSpeed'; | ||
} | ||
imageMarkup.push('\t<image ', 'COMMON_PARTS', 'xlink:href="', this.getSvgSrc(true), | ||
@@ -329,4 +332,5 @@ '" x="', x - this.cropX, '" y="', y - this.cropY, | ||
// so that object's center aligns with container's left/top | ||
'" width="', this._element.width || this._element.naturalWidth, | ||
'" height="', this._element.height || this._element.height, | ||
'" width="', element.width || element.naturalWidth, | ||
'" height="', element.height || element.height, | ||
imageRendering, | ||
'"', clipPath, | ||
@@ -386,2 +390,4 @@ '></image>\n'); | ||
* @param {Object} [options] Options object | ||
* @param {String} [options.crossOrigin] crossOrigin value (one of "", "anonymous", "use-credentials") | ||
* @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes | ||
* @return {fabric.Image} thisArg | ||
@@ -391,6 +397,6 @@ * @chainable | ||
setSrc: function(src, callback, options) { | ||
fabric.util.loadImage(src, function(img) { | ||
fabric.util.loadImage(src, function(img, isError) { | ||
this.setElement(img, options); | ||
this._setWidthHeight(); | ||
callback && callback(this); | ||
callback && callback(this, isError); | ||
}, this, options && options.crossOrigin); | ||
@@ -507,2 +513,3 @@ return this; | ||
_render: function(ctx) { | ||
fabric.util.setImageSmoothing(ctx, this.imageSmoothing); | ||
if (this.isMoving !== true && this.resizeFilter && this._needsResize()) { | ||
@@ -516,2 +523,12 @@ this.applyResizeFilters(); | ||
/** | ||
* Paint the cached copy of the object on the target context. | ||
* it will set the imageSmoothing for the draw operation | ||
* @param {CanvasRenderingContext2D} ctx Context to render on | ||
*/ | ||
drawCacheOnCanvas: function(ctx) { | ||
fabric.util.setImageSmoothing(ctx, this.imageSmoothing); | ||
fabric.Object.prototype.drawCacheOnCanvas.call(this, ctx); | ||
}, | ||
/** | ||
* Decide if the object should cache or not. Create its own cache level | ||
@@ -532,4 +549,7 @@ * needsItsOwnCache should be used when the object drawing method requires | ||
_renderFill: function(ctx) { | ||
var elementToDraw = this._element, | ||
w = this.width, h = this.height, | ||
var elementToDraw = this._element; | ||
if (!elementToDraw) { | ||
return; | ||
} | ||
var w = this.width, h = this.height, | ||
sW = Math.min(elementToDraw.naturalWidth || elementToDraw.width, w * this._filterScalingX), | ||
@@ -580,5 +600,2 @@ sH = Math.min(elementToDraw.naturalHeight || elementToDraw.height, h * this._filterScalingY), | ||
this._setWidthHeight(options); | ||
if (this._element && this.crossOrigin) { | ||
this._element.crossOrigin = this.crossOrigin; | ||
} | ||
}, | ||
@@ -703,5 +720,5 @@ | ||
var object = fabric.util.object.clone(_object); | ||
fabric.util.loadImage(object.src, function(img, error) { | ||
if (error) { | ||
callback && callback(null, error); | ||
fabric.util.loadImage(object.src, function(img, isError) { | ||
if (isError) { | ||
callback && callback(null, true); | ||
return; | ||
@@ -716,3 +733,3 @@ } | ||
var image = new fabric.Image(img, object); | ||
callback(image); | ||
callback(image, false); | ||
}); | ||
@@ -728,8 +745,8 @@ }); | ||
* @param {String} url URL to create an image from | ||
* @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) | ||
* @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument). Second argument is a boolean indicating if an error occured or not. | ||
* @param {Object} [imgOptions] Options object | ||
*/ | ||
fabric.Image.fromURL = function(url, callback, imgOptions) { | ||
fabric.util.loadImage(url, function(img) { | ||
callback && callback(new fabric.Image(img, imgOptions)); | ||
fabric.util.loadImage(url, function(img, isError) { | ||
callback && callback(new fabric.Image(img, imgOptions), isError); | ||
}, null, imgOptions && imgOptions.crossOrigin); | ||
@@ -745,3 +762,5 @@ }; | ||
fabric.Image.ATTRIBUTE_NAMES = | ||
fabric.SHARED_ATTRIBUTES.concat('x y width height preserveAspectRatio xlink:href crossOrigin'.split(' ')); | ||
fabric.SHARED_ATTRIBUTES.concat( | ||
'x y width height preserveAspectRatio xlink:href crossOrigin image-rendering'.split(' ') | ||
); | ||
@@ -748,0 +767,0 @@ /** |
@@ -117,7 +117,10 @@ (function() { | ||
/** | ||
* Color of default cursor (when not overwritten by character style) | ||
* Color of text cursor color in editing mode. | ||
* if not set (default) will take color from the text. | ||
* if set to a color value that fabric can understand, it will | ||
* be used instead of the color of the text at the current position. | ||
* @type String | ||
* @default | ||
*/ | ||
cursorColor: '#333', | ||
cursorColor: '', | ||
@@ -272,7 +275,5 @@ /** | ||
this.transform(ctx); | ||
this.transformMatrix && ctx.transform.apply(ctx, this.transformMatrix); | ||
this._clearTextArea(ctx); | ||
skipRestore || ctx.restore(); | ||
}, | ||
/** | ||
@@ -386,3 +387,3 @@ * Renders cursor or selection (depending on what exists) | ||
ctx.fillStyle = this.getValueOfPropertyAt(lineIndex, charIndex, 'fill'); | ||
ctx.fillStyle = this.cursorColor || this.getValueOfPropertyAt(lineIndex, charIndex, 'fill'); | ||
ctx.globalAlpha = this.__isMousedown ? 1 : this._currentCursorOpacity; | ||
@@ -464,2 +465,3 @@ ctx.fillRect( | ||
* Returns fontSize of char at the current cursor | ||
* Unused from the library, is for the end user | ||
* @return {Number} Character font size | ||
@@ -476,2 +478,3 @@ */ | ||
* Returns color (fill) of char at the current cursor | ||
* Unused from the library, is for the end user | ||
* @return {String} Character color (fill) | ||
@@ -478,0 +481,0 @@ */ |
@@ -184,3 +184,2 @@ (function(global) { | ||
var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); | ||
parsedAttributes.left = parsedAttributes.left || 0; | ||
@@ -187,0 +186,0 @@ parsedAttributes.top = parsedAttributes.top || 0; |
@@ -324,3 +324,3 @@ (function(global) { | ||
lineJustStarted = true, | ||
additionalSpace = splitByGrapheme ? 0 : this._getWidthOfCharSpacing(), | ||
additionalSpace = this._getWidthOfCharSpacing(), | ||
reservedSpace = reservedSpace || 0; | ||
@@ -339,3 +339,2 @@ // fix a difference between split and graphemeSplit | ||
lineWidth += infixWidth + wordWidth - additionalSpace; | ||
if (lineWidth >= desiredWidth && !lineJustStarted) { | ||
@@ -356,3 +355,3 @@ graphemeLines.push(line); | ||
infixWidth = this._measureWord([infix], lineIndex, offset); | ||
infixWidth = splitByGrapheme ? 0 : this._measureWord([infix], lineIndex, offset); | ||
offset++; | ||
@@ -371,3 +370,2 @@ lineJustStarted = false; | ||
} | ||
return graphemeLines; | ||
@@ -374,0 +372,0 @@ }, |
@@ -60,6 +60,2 @@ (function () { | ||
* Background image of canvas instance. | ||
* Should be set via {@link fabric.StaticCanvas#setBackgroundImage}. | ||
* <b>Backwards incompatibility note:</b> The "backgroundImageOpacity" | ||
* and "backgroundImageStretch" properties are deprecated since 1.3.9. | ||
* Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}. | ||
* since 2.4.0 image caching is active, please when putting an image as background, add to the | ||
@@ -84,6 +80,2 @@ * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom | ||
* Overlay image of canvas instance. | ||
* Should be set via {@link fabric.StaticCanvas#setOverlayImage}. | ||
* <b>Backwards incompatibility note:</b> The "overlayImageLeft" | ||
* and "overlayImageTop" properties are deprecated since 1.3.9. | ||
* Use {@link fabric.Image#left} and {@link fabric.Image#top}. | ||
* since 2.4.0 image caching is active, please when putting an image as overlay, add to the | ||
@@ -125,14 +117,2 @@ * canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom | ||
/** | ||
* Function that determines clipping of entire canvas area | ||
* Being passed context as first argument. | ||
* If you are using code minification, ctx argument can be minified/manglied you should use | ||
* as a workaround `var ctx = arguments[0];` in the function; | ||
* See clipping canvas area in {@link https://github.com/kangax/fabric.js/wiki/FAQ} | ||
* @deprecated since 2.0.0 | ||
* @type Function | ||
* @default | ||
*/ | ||
clipTo: null, | ||
/** | ||
* Indicates whether object controls (borders/controls) are rendered above overlay image | ||
@@ -230,3 +210,2 @@ * @type Boolean | ||
this._initOptions(options); | ||
this._setImageSmoothing(); | ||
// only initialize retina scaling once | ||
@@ -323,3 +302,3 @@ if (!this.interactive) { | ||
* @example <caption>Stretched overlayImage #1 - width/height correspond to canvas width/height</caption> | ||
* fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) { | ||
* fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img, isError) { | ||
* img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); | ||
@@ -375,3 +354,3 @@ * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas)); | ||
* @example <caption>Stretched backgroundImage #1 - width/height correspond to canvas width/height</caption> | ||
* fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) { | ||
* fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img, isError) { | ||
* img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); | ||
@@ -456,18 +435,6 @@ * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); | ||
* @private | ||
* @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-imagesmoothingenabled|WhatWG Canvas Standard} | ||
*/ | ||
_setImageSmoothing: function() { | ||
var ctx = this.getContext(); | ||
ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled | ||
|| ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled; | ||
ctx.imageSmoothingEnabled = this.imageSmoothingEnabled; | ||
}, | ||
/** | ||
* @private | ||
* @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} | ||
* or {@link fabric.StaticCanvas#overlayImage|overlayImage}) | ||
* @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to | ||
* @param {Function} callback Callback to invoke when image is loaded and set as background or overlay | ||
* @param {Function} callback Callback to invoke when image is loaded and set as background or overlay. The first argument is the created image, the second argument is a flag indicating whether an error occured or not. | ||
* @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. | ||
@@ -477,3 +444,3 @@ */ | ||
if (typeof image === 'string') { | ||
fabric.util.loadImage(image, function(img) { | ||
fabric.util.loadImage(image, function(img, isError) { | ||
if (img) { | ||
@@ -484,3 +451,3 @@ var instance = new fabric.Image(img, options); | ||
} | ||
callback && callback(img); | ||
callback && callback(img, isError); | ||
}, this, options && options.crossOrigin); | ||
@@ -492,3 +459,3 @@ } | ||
image && (image.canvas = this); | ||
callback && callback(image); | ||
callback && callback(image, false); | ||
} | ||
@@ -652,3 +619,2 @@ | ||
this._initRetinaScaling(); | ||
this._setImageSmoothing(); | ||
this.calcOffset(); | ||
@@ -724,10 +690,10 @@ | ||
setViewportTransform: function (vpt) { | ||
var activeObject = this._activeObject, object, ignoreVpt = false, skipAbsolute = true, i, len; | ||
var activeObject = this._activeObject, object, i, len; | ||
this.viewportTransform = vpt; | ||
for (i = 0, len = this._objects.length; i < len; i++) { | ||
object = this._objects[i]; | ||
object.group || object.setCoords(ignoreVpt, skipAbsolute); | ||
object.group || object.setCoords(true); | ||
} | ||
if (activeObject && activeObject.type === 'activeSelection') { | ||
activeObject.setCoords(ignoreVpt, skipAbsolute); | ||
if (activeObject) { | ||
activeObject.setCoords(); | ||
} | ||
@@ -943,6 +909,4 @@ this.calcViewportBoundaries(); | ||
this.clearContext(ctx); | ||
fabric.util.setImageSmoothing(ctx, this.imageSmoothingEnabled); | ||
this.fire('before:render', { ctx: ctx, }); | ||
if (this.clipTo) { | ||
fabric.util.clipContext(this, ctx); | ||
} | ||
this._renderBackground(ctx); | ||
@@ -958,5 +922,2 @@ | ||
} | ||
if (this.clipTo) { | ||
ctx.restore(); | ||
} | ||
if (path) { | ||
@@ -1442,4 +1403,11 @@ path.canvas = this; | ||
style, row, rowIndex, _char, charIndex, i, len, | ||
fontPaths = fabric.fontPaths, objects = this._objects; | ||
fontPaths = fabric.fontPaths, objects = []; | ||
this._objects.forEach(function add(object) { | ||
objects.push(object); | ||
if (object._objects) { | ||
object._objects.forEach(add); | ||
} | ||
}); | ||
for (i = 0, len = objects.length; i < len; i++) { | ||
@@ -1446,0 +1414,0 @@ obj = objects[i]; |
(function () { | ||
// since ie10 can use addEventListener but they do not support options, i need to check | ||
// since ie11 can use addEventListener but they do not support options, i need to check | ||
var couldUseAttachEvent = !!fabric.document.createElement('div').attachEvent, | ||
@@ -4,0 +4,0 @@ touchEvents = ['touchstart', 'touchmove', 'touchend']; |
@@ -255,37 +255,2 @@ (function() { | ||
(function() { | ||
/** | ||
* Inserts a script element with a given url into a document; invokes callback, when that script is finished loading | ||
* @memberOf fabric.util | ||
* @param {String} url URL of a script to load | ||
* @param {Function} callback Callback to execute when script is finished loading | ||
*/ | ||
function getScript(url, callback) { | ||
var headEl = fabric.document.getElementsByTagName('head')[0], | ||
scriptEl = fabric.document.createElement('script'), | ||
loading = true; | ||
/** @ignore */ | ||
scriptEl.onload = /** @ignore */ scriptEl.onreadystatechange = function(e) { | ||
if (loading) { | ||
if (typeof this.readyState === 'string' && | ||
this.readyState !== 'loaded' && | ||
this.readyState !== 'complete') { | ||
return; | ||
} | ||
loading = false; | ||
callback(e || fabric.window.event); | ||
scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null; | ||
} | ||
}; | ||
scriptEl.src = url; | ||
headEl.appendChild(scriptEl); | ||
// causes issue in Opera | ||
// headEl.removeChild(scriptEl); | ||
} | ||
fabric.util.getScript = getScript; | ||
})(); | ||
function getNodeCanvas(element) { | ||
@@ -311,10 +276,24 @@ var impl = fabric.jsdomImplForWrapper(element); | ||
function setImageSmoothing(ctx, value) { | ||
ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled | ||
|| ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled; | ||
ctx.imageSmoothingEnabled = value; | ||
} | ||
/** | ||
* setImageSmoothing sets the context imageSmoothingEnabled property. | ||
* Used by canvas and by ImageObject. | ||
* @memberOf fabric.util | ||
* @since 4.0.0 | ||
* @param {HTMLRenderingContext2D} ctx to set on | ||
* @param {Boolean} value true or false | ||
*/ | ||
fabric.util.setImageSmoothing = setImageSmoothing; | ||
fabric.util.getById = getById; | ||
fabric.util.toArray = toArray; | ||
fabric.util.addClass = addClass; | ||
fabric.util.makeElement = makeElement; | ||
fabric.util.addClass = addClass; | ||
fabric.util.wrapElement = wrapElement; | ||
fabric.util.getScrollLeftTop = getScrollLeftTop; | ||
fabric.util.getElementOffset = getElementOffset; | ||
fabric.util.getElementStyle = getElementStyle; | ||
fabric.util.getNodeCanvas = getNodeCanvas; | ||
@@ -321,0 +300,0 @@ fabric.util.cleanUpJsdomNode = cleanUpJsdomNode; |
@@ -7,3 +7,3 @@ (function() { | ||
* This is mostly for internal use and has extra handling for fabricJS objects | ||
* it skips the canvas property in deep cloning. | ||
* it skips the canvas and group properties in deep cloning. | ||
* @memberOf fabric.util.object | ||
@@ -32,4 +32,6 @@ * @param {Object} destination Where to copy to | ||
for (var property in source) { | ||
if (property === 'canvas') { | ||
destination[property] = extend({ }, source[property]); | ||
if (property === 'canvas' || property === 'group') { | ||
// we do not want to clone this props at all. | ||
// we want to keep the keys in the copy | ||
destination[property] = null; | ||
} | ||
@@ -36,0 +38,0 @@ else if (source.hasOwnProperty(property)) { |
@@ -348,3 +348,3 @@ (function(global) { | ||
var onLoadCallback = function () { | ||
callback && callback.call(context, img); | ||
callback && callback.call(context, img, false); | ||
img = img.onload = img.onerror = null; | ||
@@ -365,3 +365,6 @@ }; | ||
// https://bugzilla.mozilla.org/show_bug.cgi?id=935069 | ||
if (url.indexOf('data') !== 0 && crossOrigin) { | ||
// crossOrigin null is the same as not set. | ||
if (url.indexOf('data') !== 0 && | ||
crossOrigin !== undefined && | ||
crossOrigin !== null) { | ||
img.crossOrigin = crossOrigin; | ||
@@ -633,16 +636,2 @@ } | ||
/** | ||
* @static | ||
* @memberOf fabric.util | ||
* @deprecated since 2.0.0 | ||
* @param {fabric.Object} receiver Object implementing `clipTo` method | ||
* @param {CanvasRenderingContext2D} ctx Context to clip | ||
*/ | ||
clipContext: function(receiver, ctx) { | ||
ctx.save(); | ||
ctx.beginPath(); | ||
receiver.clipTo(ctx); | ||
ctx.clip(); | ||
}, | ||
/** | ||
* Multiply matrix A by matrix B to nest transformations | ||
@@ -679,6 +668,6 @@ * @static | ||
scaleX = sqrt(denom), | ||
scaleY = (a[0] * a[3] - a[2] * a [1]) / scaleX, | ||
scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX, | ||
skewX = atan2(a[0] * a[2] + a[1] * a [3], denom); | ||
return { | ||
angle: angle / PiBy180, | ||
angle: angle / PiBy180, | ||
scaleX: scaleX, | ||
@@ -789,17 +778,2 @@ scaleY: scaleY, | ||
/** | ||
* Returns a transform matrix that has the same effect of scaleX, scaleY and skewX. | ||
* Is deprecated for composeMatrix. Please do not use it. | ||
* @static | ||
* @deprecated since 3.4.0 | ||
* @memberOf fabric.util | ||
* @param {Number} scaleX | ||
* @param {Number} scaleY | ||
* @param {Number} skewX | ||
* @return {Number[]} transform matrix | ||
*/ | ||
customTransformMatrix: function(scaleX, scaleY, skewX) { | ||
return fabric.util.composeMatrix({ scaleX: scaleX, scaleY: scaleY, skewX: skewX }); | ||
}, | ||
/** | ||
* reset an object transform state to neutral. Top and left are not accounted for | ||
@@ -842,11 +816,2 @@ * @static | ||
/** | ||
* Returns string representation of function body | ||
* @param {Function} fn Function to get body of | ||
* @return {String} Function body | ||
*/ | ||
getFunctionBody: function(fn) { | ||
return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1]; | ||
}, | ||
/** | ||
* Returns true if context has transparent pixel | ||
@@ -966,2 +931,15 @@ * at specified location (taking tolerance into account) | ||
/** | ||
* Finds the scale for the object source to fit inside the object destination, | ||
* keeping aspect ratio intact. | ||
* respect the total allowed area for the cache. | ||
* @memberOf fabric.util | ||
* @param {Object | fabric.Object} source | ||
* @param {Number} source.height natural unscaled height of the object | ||
* @param {Number} source.width natural unscaled width of the object | ||
* @param {Object | fabric.Object} destination | ||
* @param {Number} destination.height natural unscaled height of the object | ||
* @param {Number} destination.width natural unscaled width of the object | ||
* @return {Number} scale factor to apply to source to fit into destination | ||
*/ | ||
findScaleToFit: function(source, destination) { | ||
@@ -971,2 +949,15 @@ return Math.min(destination.width / source.width, destination.height / source.height); | ||
/** | ||
* Finds the scale for the object source to cover entirely the object destination, | ||
* keeping aspect ratio intact. | ||
* respect the total allowed area for the cache. | ||
* @memberOf fabric.util | ||
* @param {Object | fabric.Object} source | ||
* @param {Number} source.height natural unscaled height of the object | ||
* @param {Number} source.width natural unscaled width of the object | ||
* @param {Object | fabric.Object} destination | ||
* @param {Number} destination.height natural unscaled height of the object | ||
* @param {Number} destination.width natural unscaled width of the object | ||
* @return {Number} scale factor to apply to source to cover destination | ||
*/ | ||
findScaleToCover: function(source, destination) { | ||
@@ -987,4 +978,47 @@ return Math.max(destination.width / source.width, destination.height / source.height); | ||
}).join(' ') + ')'; | ||
}, | ||
/** | ||
* given a width and height, return the size of the bounding box | ||
* that can contains the box with width/height with applied transform | ||
* described in options. | ||
* Use to calculate the boxes around objects for controls. | ||
* @memberOf fabric.util | ||
* @param {Number} width | ||
* @param {Number} height | ||
* @param {Object} options | ||
* @param {Number} options.scaleX | ||
* @param {Number} options.scaleY | ||
* @param {Number} options.skewX | ||
* @param {Number} options.skewY | ||
* @return {Object.x} width of containing | ||
* @return {Object.y} height of containing | ||
*/ | ||
sizeAfterTransform: function(width, height, options) { | ||
var dimX = width / 2, dimY = height / 2, | ||
points = [ | ||
{ | ||
x: -dimX, | ||
y: -dimY | ||
}, | ||
{ | ||
x: dimX, | ||
y: -dimY | ||
}, | ||
{ | ||
x: -dimX, | ||
y: dimY | ||
}, | ||
{ | ||
x: dimX, | ||
y: dimY | ||
}], | ||
transformMatrix = fabric.util.calcDimensionsMatrix(options), | ||
bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix); | ||
return { | ||
x: bbox.width, | ||
y: bbox.height, | ||
}; | ||
} | ||
}; | ||
})(typeof exports !== 'undefined' ? exports : this); |
@@ -191,18 +191,2 @@ (function() { | ||
/** | ||
* Retrieves object's {@link fabric.Object#clipTo|clipping function} | ||
* @method getClipTo | ||
* @memberOf fabric.Object.prototype | ||
* @return {Function} | ||
*/ | ||
/** | ||
* Sets object's {@link fabric.Object#clipTo|clipping function} | ||
* @method setClipTo | ||
* @memberOf fabric.Object.prototype | ||
* @param {Function} clipTo Clipping function | ||
* @return {fabric.Object} thisArg | ||
* @chainable | ||
*/ | ||
/** | ||
* Retrieves object's {@link fabric.Object#transformMatrix|transformMatrix} | ||
@@ -209,0 +193,0 @@ * @method getTransformMatrix |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
2422526
0
114
2
56819
273
3