Comparing version 4.2.0 to 4.3.0-browser
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */ | ||
var fabric = fabric || { version: '4.2.0' }; | ||
var fabric = fabric || { version: '4.3.0' }; | ||
if (typeof exports !== 'undefined') { | ||
@@ -76,3 +76,3 @@ exports.fabric = fabric; | ||
fabric.reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:[eE][-+]?\\d+)?)'; | ||
fabric.commaWsp = '(?:\\s+,?\\s*|,\\s*)' | ||
fabric.commaWsp = '(?:\\s+,?\\s*|,\\s*)'; | ||
fabric.rePathCommand = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:[eE][-+]?\d+)?)/ig; | ||
@@ -166,3 +166,3 @@ fabric.reNonWord = /[ \n\.,;!\?\-]/; | ||
/** | ||
* This object contains the result of arc to beizer conversion for faster retrieving if the same arc needs to be converted again. | ||
* This object contains the result of arc to bezier conversion for faster retrieving if the same arc needs to be converted again. | ||
* It was an internal variable, is accessible since version 2.3.4 | ||
@@ -169,0 +169,0 @@ */ |
161
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.2.0", | ||
"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 && npm run build_with_gestures && npm run export_gesture_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_gesture_to_site": "cp dist/fabric.js ../fabricjs.com/lib/fabric_with_gestures.js", | ||
"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.2.1" | ||
}, | ||
"devDependencies": { | ||
"chalk": "^2.4.1", | ||
"eslint": "4.18.x", | ||
"nyc": "^15.1.0", | ||
"onchange": "^3.x.x", | ||
"pixelmatch": "^4.0.2", | ||
"qunit": "2.9.2", | ||
"testem": "^3.2.0", | ||
"uglify-js": "3.3.x" | ||
}, | ||
"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.3.0-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_gesture_to_site": "cp dist/fabric.js ../fabricjs.com/lib/fabric_with_gestures.js", | ||
"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": { | ||
"chalk": "^2.4.1", | ||
"eslint": "4.18.x", | ||
"nyc": "^15.1.0", | ||
"onchange": "^3.x.x", | ||
"pixelmatch": "^4.0.2", | ||
"qunit": "2.9.2", | ||
"testem": "^3.2.0", | ||
"uglify-js": "3.3.x" | ||
}, | ||
"engines": { | ||
"node": ">=8.0.0" | ||
}, | ||
"main": "./dist/fabric.js", | ||
"dependencies": {} | ||
} |
@@ -8,3 +8,3 @@ ## Fabric.js | ||
[![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) | ||
[![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) | ||
@@ -55,7 +55,8 @@ <!-- npm, bower, CDNJS versions, downloads --> | ||
- Firefox 2+ | ||
- Safari 3+ | ||
- Firefox 4+ | ||
- Safari 5+ | ||
- Opera 9.64+ | ||
- Chrome (all versions) | ||
- IE10, IE11, Edge | ||
- Edge (chromium based, all versions) | ||
- IE11 and Edge legacy, supported but deprecated. | ||
@@ -81,4 +82,4 @@ You can [run automated unit tests](http://fabricjs.com/test/unit/) right in the browser. | ||
$ npm install fabric --save | ||
After this, you can import fabric like so: | ||
@@ -85,0 +86,0 @@ |
@@ -37,3 +37,3 @@ (function() { | ||
/** | ||
* Inovoked on mouse down | ||
* Invoked on mouse down | ||
* @param {Object} pointer | ||
@@ -53,3 +53,3 @@ */ | ||
/** | ||
* Inovoked on mouse move | ||
* Invoked on mouse move | ||
* @param {Object} pointer | ||
@@ -239,3 +239,3 @@ */ | ||
/** | ||
* Decimate poins array with the decimate value | ||
* Decimate points array with the decimate value | ||
*/ | ||
@@ -242,0 +242,0 @@ decimatePoints: function(points, distance) { |
@@ -516,3 +516,3 @@ (function() { | ||
/** | ||
* takes an event and determins if selection key has been pressed | ||
* takes an event and determines if selection key has been pressed | ||
* @private | ||
@@ -612,6 +612,2 @@ * @param {Event} e Event object | ||
} | ||
else if (corner === 'mtr') { | ||
origin.x = 'center'; | ||
origin.y = 'center'; | ||
} | ||
return origin; | ||
@@ -646,4 +642,5 @@ }, | ||
var pointer = this.getPointer(e), corner = target.__corner, | ||
control = target.controls[corner], | ||
actionHandler = (alreadySelected && corner) ? | ||
target.controls[corner].getActionHandler() : fabric.controlsUtils.dragHandler, | ||
control.getActionHandler(e, target, control) : fabric.controlsUtils.dragHandler, | ||
action = this._getActionFromCorner(alreadySelected, corner, e, target), | ||
@@ -650,0 +647,0 @@ origin = this._getOriginFromCorner(target, corner), |
@@ -28,3 +28,3 @@ (function(global) { | ||
/** | ||
* Name of the action that the controll will likely execute. | ||
* Name of the action that the control will likely execute. | ||
* This is optional. FabricJS uses to identify what the user is doing for some | ||
@@ -73,3 +73,3 @@ * extra optimizations. If you are writing a custom control and you want to know | ||
* the bounding box. Example: rotation control is placed at x:0, y: 0.5 on | ||
* the boundindbox, with an offset of 30 pixels vertivally. Those 30 pixels will | ||
* the boundindbox, with an offset of 30 pixels vertically. Those 30 pixels will | ||
* stay 30 pixels no matter how the object is big. Another example is having 2 | ||
@@ -92,2 +92,34 @@ * controls in the corner, that stay in the same position when the object scale. | ||
/** | ||
* Sets the length of the control. If null, defaults to object's cornerSize. | ||
* Expects both sizeX and sizeY to be set when set. | ||
* @type {?Number} | ||
* @default null | ||
*/ | ||
sizeX: null, | ||
/** | ||
* Sets the height of the control. If null, defaults to object's cornerSize. | ||
* Expects both sizeX and sizeY to be set when set. | ||
* @type {?Number} | ||
* @default null | ||
*/ | ||
sizeY: null, | ||
/** | ||
* Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize. | ||
* Expects both touchSizeX and touchSizeY to be set when set. | ||
* @type {?Number} | ||
* @default null | ||
*/ | ||
touchSizeX: null, | ||
/** | ||
* Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize. | ||
* Expects both touchSizeX and touchSizeY to be set when set. | ||
* @type {?Number} | ||
* @default null | ||
*/ | ||
touchSizeY: null, | ||
/** | ||
* Css cursor style to display when the control is hovered. | ||
@@ -112,6 +144,7 @@ * if the method `cursorStyleHandler` is provided, this property is ignored. | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
* @param {Number} x x position of the cursor | ||
* @param {Number} y y position of the cursor | ||
* @return {Boolean} true if the action/event modified the object | ||
*/ | ||
actionHandler: function(/* eventData, transformData, fabricObject */) { }, | ||
actionHandler: function(/* eventData, transformData, x, y */) { }, | ||
@@ -122,6 +155,7 @@ /** | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
* @param {Number} x x position of the cursor | ||
* @param {Number} y y position of the cursor | ||
* @return {Boolean} true if the action/event modified the object | ||
*/ | ||
mouseDownHandler: function(/* eventData, transformData, fabricObject */) { }, | ||
mouseDownHandler: function(/* eventData, transformData, x, y */) { }, | ||
@@ -132,6 +166,7 @@ /** | ||
* @param {Object} transformData properties of the current transform | ||
* @param {fabric.Object} object on which the control is displayed | ||
* @return {Function} | ||
* @param {Number} x x position of the cursor | ||
* @param {Number} y y position of the cursor | ||
* @return {Boolean} true if the action/event modified the object | ||
*/ | ||
mouseUpHandler: function(/* eventData, transformData, fabricObject */) { }, | ||
mouseUpHandler: function(/* eventData, transformData, x, y */) { }, | ||
@@ -141,7 +176,7 @@ /** | ||
* @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} | ||
* @param {fabric.Object} fabricObject on which the control is displayed | ||
* @param {fabric.Control} control control for which the action handler is being asked | ||
* @return {Function} the action handler | ||
*/ | ||
getActionHandler: function(/* eventData, transformData, fabricObject */) { | ||
getActionHandler: function(/* eventData, fabricObject, control */) { | ||
return this.actionHandler; | ||
@@ -153,5 +188,5 @@ }, | ||
* @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} | ||
* @param {fabric.Object} fabricObject on which the control is displayed | ||
* @param {fabric.Control} control control for which the action handler is being asked | ||
* @return {Function} the action handler | ||
*/ | ||
@@ -165,5 +200,5 @@ getMouseDownHandler: function(/* eventData, fabricObject, 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} | ||
* @param {fabric.Object} fabricObject on which the control is displayed | ||
* @param {fabric.Control} control control for which the action handler is being asked | ||
* @return {Function} the action handler | ||
*/ | ||
@@ -230,2 +265,62 @@ getMouseUpHandler: function(/* eventData, fabricObject, control */) { | ||
/** | ||
* Returns the coords for this control based on object values. | ||
* @param {Number} objectAngle angle from the fabric object holding the control | ||
* @param {Number} objectCornerSize cornerSize from the fabric object holding the control (or touchCornerSize if | ||
* isTouch is true) | ||
* @param {Number} centerX x coordinate where the control center should be | ||
* @param {Number} centerY y coordinate where the control center should be | ||
* @param {boolean} isTouch true if touch corner, false if normal corner | ||
*/ | ||
calcCornerCoords: function(objectAngle, objectCornerSize, centerX, centerY, isTouch) { | ||
var cosHalfOffset, | ||
sinHalfOffset, | ||
cosHalfOffsetComp, | ||
sinHalfOffsetComp, | ||
xSize = (isTouch) ? this.touchSizeX : this.sizeX, | ||
ySize = (isTouch) ? this.touchSizeY : this.sizeY; | ||
if (xSize && ySize && xSize !== ySize) { | ||
// handle rectangular corners | ||
var controlTriangleAngle = Math.atan2(ySize, xSize); | ||
var cornerHypotenuse = Math.sqrt(xSize * xSize + ySize * ySize) / 2; | ||
var newTheta = controlTriangleAngle - fabric.util.degreesToRadians(objectAngle); | ||
var newThetaComp = Math.PI / 2 - controlTriangleAngle - fabric.util.degreesToRadians(objectAngle); | ||
cosHalfOffset = cornerHypotenuse * fabric.util.cos(newTheta); | ||
sinHalfOffset = cornerHypotenuse * fabric.util.sin(newTheta); | ||
// use complementary angle for two corners | ||
cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newThetaComp); | ||
sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newThetaComp); | ||
} | ||
else { | ||
// handle square corners | ||
// use default object corner size unless size is defined | ||
var cornerSize = (xSize && ySize) ? xSize : objectCornerSize; | ||
/* 0.7071067812 stands for sqrt(2)/2 */ | ||
cornerHypotenuse = cornerSize * 0.7071067812; | ||
// complementary angles are equal since they're both 45 degrees | ||
var newTheta = fabric.util.degreesToRadians(45 - objectAngle); | ||
cosHalfOffset = cosHalfOffsetComp = cornerHypotenuse * fabric.util.cos(newTheta); | ||
sinHalfOffset = sinHalfOffsetComp = cornerHypotenuse * fabric.util.sin(newTheta); | ||
} | ||
return { | ||
tl: { | ||
x: centerX - sinHalfOffsetComp, | ||
y: centerY - cosHalfOffsetComp, | ||
}, | ||
tr: { | ||
x: centerX + cosHalfOffset, | ||
y: centerY - sinHalfOffset, | ||
}, | ||
bl: { | ||
x: centerX - cosHalfOffset, | ||
y: centerY + sinHalfOffset, | ||
}, | ||
br: { | ||
x: centerX + sinHalfOffsetComp, | ||
y: centerY + cosHalfOffsetComp, | ||
}, | ||
}; | ||
}, | ||
/** | ||
* Render function for the control. | ||
@@ -232,0 +327,0 @@ * When this function runs the context is unscaled. unrotate. Just retina scaled. |
@@ -22,14 +22,31 @@ (function(global) { | ||
styleOverride = styleOverride || {}; | ||
var size = styleOverride.cornerSize || fabricObject.cornerSize, | ||
var xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize, | ||
ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize, | ||
transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? | ||
styleOverride.transparentCorners : this.transparentCorners, | ||
methodName = transparentCorners ? 'stroke' : 'fill', | ||
stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor); | ||
stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor), | ||
myLeft = left, | ||
myTop = top, size; | ||
ctx.save(); | ||
ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor; | ||
ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor; | ||
// as soon as fabric react v5, remove ie11, use proper ellipse code. | ||
if (xSize > ySize) { | ||
size = xSize; | ||
ctx.scale(1.0, ySize / xSize); | ||
myTop = top * xSize / ySize; | ||
} | ||
else if (ySize > xSize) { | ||
size = ySize; | ||
ctx.scale(xSize / ySize, 1.0); | ||
myLeft = left * ySize / xSize; | ||
} | ||
else { | ||
size = xSize; | ||
} | ||
// this is still wrong | ||
ctx.lineWidth = 1; | ||
ctx.beginPath(); | ||
ctx.arc(left, top, size / 2, 0, 2 * Math.PI, false); | ||
ctx.arc(myLeft, myTop, size / 2, 0, 2 * Math.PI, false); | ||
ctx[methodName](); | ||
@@ -55,3 +72,4 @@ if (stroke) { | ||
styleOverride = styleOverride || {}; | ||
var size = styleOverride.cornerSize || fabricObject.cornerSize, | ||
var xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize, | ||
ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize, | ||
transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? | ||
@@ -62,3 +80,3 @@ styleOverride.transparentCorners : fabricObject.transparentCorners, | ||
styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor | ||
), sizeBy2 = size / 2; | ||
), xSizeBy2 = xSize / 2, ySizeBy2 = ySize / 2; | ||
ctx.save(); | ||
@@ -73,6 +91,6 @@ ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor; | ||
// to have real transparent corners we need the controls on upperCanvas | ||
// transparentCorners || ctx.clearRect(-sizeBy2, -sizeBy2, size, size); | ||
ctx[methodName + 'Rect'](-sizeBy2, -sizeBy2, size, size); | ||
// transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize); | ||
ctx[methodName + 'Rect'](-xSizeBy2, -ySizeBy2, xSize, ySize); | ||
if (stroke) { | ||
ctx.strokeRect(-sizeBy2, -sizeBy2, size, size); | ||
ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize); | ||
} | ||
@@ -79,0 +97,0 @@ ctx.restore(); |
@@ -197,3 +197,3 @@ /** | ||
* on the image | ||
* Other filters may need their own verison ( ColorMatrix, HueRotation, gamma, ComposedFilter ) | ||
* Other filters may need their own version ( ColorMatrix, HueRotation, gamma, ComposedFilter ) | ||
* @param {Object} options | ||
@@ -200,0 +200,0 @@ **/ |
@@ -75,3 +75,3 @@ (function(global) { | ||
* specific to keep the image blur constant at different resolutions | ||
* range bewteen 0 and 1. | ||
* range between 0 and 1. | ||
*/ | ||
@@ -78,0 +78,0 @@ blur: 0, |
@@ -71,3 +71,3 @@ (function() { | ||
* of recreating them during frequent filtering. If you are previewing a filter with | ||
* a slider you problably do not want to create help layers every filter step. | ||
* a slider you probably do not want to create help layers every filter step. | ||
* in this object there will be appended some canvases, created once, resized sometimes | ||
@@ -249,3 +249,3 @@ * cleared never. Clearing is left to the developer. | ||
* | ||
* Accepts specific dimensions to initialize the textuer to or a source image. | ||
* Accepts specific dimensions to initialize the texture to or a source image. | ||
* | ||
@@ -252,0 +252,0 @@ * @param {WebGLRenderingContext} gl The GL context to use for creating the texture. |
@@ -241,3 +241,3 @@ (function() { | ||
} | ||
if (object.type === 'path') { | ||
if (object.type === 'path' && this.gradientUnits !== 'percentage') { | ||
offsetX -= object.pathOffset.x; | ||
@@ -364,3 +364,3 @@ offsetY -= object.pathOffset.y; | ||
* @param {String} opacityAttr A fill-opacity or stroke-opacity attribute to multiply to each stop's opacity. | ||
* @param {Object} svgOptions an object containing the size of the SVG in order to parse correctly graidents | ||
* @param {Object} svgOptions an object containing the size of the SVG in order to parse correctly gradients | ||
* that uses gradientUnits as 'userSpaceOnUse' and percentages. | ||
@@ -367,0 +367,0 @@ * @param {Object.number} viewBoxWidth width part of the viewBox attribute on svg |
@@ -461,3 +461,4 @@ (function() { | ||
if (mouseUpHandler) { | ||
mouseUpHandler(e, target, control); | ||
var pointer = this.getPointer(e); | ||
mouseUpHandler(e, transform, pointer.x, pointer.y); | ||
} | ||
@@ -727,8 +728,9 @@ target.isMoving = false; | ||
if (target === this._activeObject && (corner || !shouldGroup)) { | ||
this._setupCurrentTransform(e, target, alreadySelected); | ||
var control = target.controls[corner], | ||
pointer = this.getPointer(e), | ||
mouseDownHandler = control && control.getMouseDownHandler(e, target, control); | ||
if (mouseDownHandler) { | ||
mouseDownHandler(e, target, control); | ||
mouseDownHandler(e, this._currentTransform, pointer.x, pointer.y); | ||
} | ||
this._setupCurrentTransform(e, target, alreadySelected); | ||
} | ||
@@ -735,0 +737,0 @@ } |
@@ -150,3 +150,3 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { | ||
/** | ||
* standard hander for mouse up, overridable | ||
* standard handler for mouse up, overridable | ||
* @private | ||
@@ -153,0 +153,0 @@ */ |
@@ -204,3 +204,3 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { | ||
else if (backDelete) { | ||
// detect differencies between forwardDelete and backDelete | ||
// detect differences between forwardDelete and backDelete | ||
removeFrom = selectionEnd - removedText.length; | ||
@@ -207,0 +207,0 @@ removeTo = selectionEnd; |
@@ -517,3 +517,3 @@ (function() { | ||
/** | ||
* Sets corner position coordinates based on current angle, width and height. | ||
* Sets corner and controls position coordinates based on current angle, width and height, left and top. | ||
* oCoords are used to find the corners | ||
@@ -520,0 +520,0 @@ * aCoords are used to quickly find an object on the canvas |
@@ -34,4 +34,4 @@ (function() { | ||
lines = this._getImageLines(forTouch ? this.oCoords[i].touchCorner : this.oCoords[i].corner); | ||
// debugging | ||
// // debugging | ||
// | ||
// this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2); | ||
@@ -77,55 +77,10 @@ // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2); | ||
_setCornerCoords: function() { | ||
var coords = this.oCoords, | ||
newTheta = degreesToRadians(45 - this.angle), | ||
cosTheta = fabric.util.cos(newTheta), | ||
sinTheta = fabric.util.sin(newTheta), | ||
/* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */ | ||
/* 0.707106 stands for sqrt(2)/2 */ | ||
cornerHypotenuse = this.cornerSize * 0.707106, | ||
touchHypotenuse = this.touchCornerSize * 0.707106, | ||
cosHalfOffset = cornerHypotenuse * cosTheta, | ||
sinHalfOffset = cornerHypotenuse * sinTheta, | ||
touchCosHalfOffset = touchHypotenuse * cosTheta, | ||
touchSinHalfOffset = touchHypotenuse * sinTheta, | ||
x, y; | ||
var coords = this.oCoords; | ||
for (var control in coords) { | ||
x = coords[control].x; | ||
y = coords[control].y; | ||
coords[control].corner = { | ||
tl: { | ||
x: x - sinHalfOffset, | ||
y: y - cosHalfOffset | ||
}, | ||
tr: { | ||
x: x + cosHalfOffset, | ||
y: y - sinHalfOffset | ||
}, | ||
bl: { | ||
x: x - cosHalfOffset, | ||
y: y + sinHalfOffset | ||
}, | ||
br: { | ||
x: x + sinHalfOffset, | ||
y: y + cosHalfOffset | ||
} | ||
}; | ||
coords[control].touchCorner = { | ||
tl: { | ||
x: x - touchSinHalfOffset, | ||
y: y - touchCosHalfOffset | ||
}, | ||
tr: { | ||
x: x + touchCosHalfOffset, | ||
y: y - touchSinHalfOffset | ||
}, | ||
bl: { | ||
x: x - touchCosHalfOffset, | ||
y: y + touchSinHalfOffset | ||
}, | ||
br: { | ||
x: x + touchSinHalfOffset, | ||
y: y + touchCosHalfOffset | ||
} | ||
}; | ||
var controlObject = this.controls[control]; | ||
coords[control].corner = controlObject.calcCornerCoords( | ||
this.angle, this.cornerSize, coords[control].x, coords[control].y, false); | ||
coords[control].touchCorner = controlObject.calcCornerCoords( | ||
this.angle, this.touchCornerSize, coords[control].x, coords[control].y, true); | ||
} | ||
@@ -132,0 +87,0 @@ }, |
@@ -190,3 +190,3 @@ (function() { | ||
* Gets style of a current selection/cursor (at the start position) | ||
* if startIndex or endIndex are not provided, slectionStart or selectionEnd will be used. | ||
* if startIndex or endIndex are not provided, selectionStart or selectionEnd will be used. | ||
* @param {Number} [startIndex] Start index to get styles at | ||
@@ -193,0 +193,0 @@ * @param {Number} [endIndex] End index to get styles at, if not specified selectionEnd or startIndex + 1 |
@@ -142,3 +142,3 @@ (function(global) { | ||
else if (attr === 'imageSmoothing') { | ||
return (value === 'optimizeQuality' ? true : false); | ||
return (value === 'optimizeQuality'); | ||
} | ||
@@ -987,4 +987,3 @@ else { | ||
for (i = 0, len = styles.length; i < len; i++) { | ||
// <style/> could produce `undefined`, covering this case with '' | ||
var styleContents = styles[i].textContent || ''; | ||
var styleContents = styles[i].textContent; | ||
@@ -991,0 +990,0 @@ // remove comments |
@@ -37,3 +37,3 @@ (function(global) { | ||
* Start angle of the circle, moving clockwise | ||
* deprectated type, this should be in degree, this was an oversight. | ||
* deprecated type, this should be in degree, this was an oversight. | ||
* probably will change to degrees in next major version | ||
@@ -47,3 +47,3 @@ * @type Number | ||
* End angle of the circle | ||
* deprectated type, this should be in degree, this was an oversight. | ||
* deprecated type, this should be in degree, this was an oversight. | ||
* probably will change to degrees in next major version | ||
@@ -50,0 +50,0 @@ * @type Number |
@@ -359,3 +359,3 @@ (function(global) { | ||
/** | ||
* Retores original state of each of group objects (original state is that which was before group was created). | ||
* Restores original state of each of group objects (original state is that which was before group was created). | ||
* @private | ||
@@ -362,0 +362,0 @@ * @return {fabric.Group} thisArg |
@@ -171,3 +171,3 @@ (function(global) { | ||
// we need to apply resizeFilters AFTER normal filters. | ||
// applyResizeFilters is run more often than normal fiters | ||
// applyResizeFilters is run more often than normal filters | ||
// and is triggered by user interactions rather than dev code | ||
@@ -291,3 +291,3 @@ if (this.resizeFilter) { | ||
/** | ||
* Returns true if an image has crop applied, inspecting values of cropX,cropY,width,hight. | ||
* Returns true if an image has crop applied, inspecting values of cropX,cropY,width,height. | ||
* @return {Boolean} | ||
@@ -740,3 +740,3 @@ */ | ||
* @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). Second argument is a boolean indicating if an error occured or not. | ||
* @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 occurred or not. | ||
* @param {Object} [imgOptions] Options object | ||
@@ -743,0 +743,0 @@ */ |
@@ -203,3 +203,3 @@ (function(global) { | ||
* Returns object representation of an instance | ||
* @methd toObject | ||
* @method toObject | ||
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output | ||
@@ -206,0 +206,0 @@ * @return {Object} object representation of an instance |
@@ -93,3 +93,3 @@ (function(global) { | ||
* Calculate the polygon min and max point from points array, | ||
* returning an object with left, top, widht, height to measure the | ||
* returning an object with left, top, width, height to measure the | ||
* polygon size | ||
@@ -96,0 +96,0 @@ * @return {Object} object.left X coordinate of the polygon leftmost point |
@@ -13,2 +13,6 @@ (function(global) { | ||
var styleProps = | ||
'fontFamily fontWeight fontSize text underline overline linethrough' + | ||
' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles path'.split(' '); | ||
/** | ||
@@ -39,2 +43,3 @@ * Text class | ||
'styles', | ||
'path' | ||
], | ||
@@ -172,15 +177,3 @@ | ||
*/ | ||
stateProperties: fabric.Object.prototype.stateProperties.concat('fontFamily', | ||
'fontWeight', | ||
'fontSize', | ||
'text', | ||
'underline', | ||
'overline', | ||
'linethrough', | ||
'textAlign', | ||
'fontStyle', | ||
'lineHeight', | ||
'textBackgroundColor', | ||
'charSpacing', | ||
'styles'), | ||
stateProperties: fabric.Object.prototype.stateProperties.concat(styleProps), | ||
@@ -191,15 +184,3 @@ /** | ||
*/ | ||
cacheProperties: fabric.Object.prototype.cacheProperties.concat('fontFamily', | ||
'fontWeight', | ||
'fontSize', | ||
'text', | ||
'underline', | ||
'overline', | ||
'linethrough', | ||
'textAlign', | ||
'fontStyle', | ||
'lineHeight', | ||
'textBackgroundColor', | ||
'charSpacing', | ||
'styles'), | ||
cacheProperties: fabric.Object.prototype.cacheProperties.concat(styleProps), | ||
@@ -253,3 +234,3 @@ /** | ||
* Object containing character styles - top-level properties -> line numbers, | ||
* 2nd-level properties - charater numbers | ||
* 2nd-level properties - character numbers | ||
* @type Object | ||
@@ -263,3 +244,3 @@ * @default | ||
* the cacheContext of the canvas will be used or a freshly created one if the object is not on canvas | ||
* once created it will be referenced on fabric._measuringContext to avoide creating a canvas for every | ||
* once created it will be referenced on fabric._measuringContext to avoid creating a canvas for every | ||
* text object created. | ||
@@ -272,3 +253,3 @@ * @type {CanvasRenderingContext2D} | ||
/** | ||
* Baseline shift, stlyes only, keep at 0 for the main text object | ||
* Baseline shift, styles only, keep at 0 for the main text object | ||
* @type {Number} | ||
@@ -331,2 +312,5 @@ * @default | ||
this.callSuper('initialize', options); | ||
if (this.path) { | ||
this.setPathInfo(); | ||
} | ||
this.__skipDimension = false; | ||
@@ -339,3 +323,15 @@ this.initDimensions(); | ||
/** | ||
* Return a contex for measurement of text string. | ||
* If text has a path, it will add the extra information needed | ||
* for path and text calculations | ||
* @return {fabric.Text} thisArg | ||
*/ | ||
setPathInfo: function() { | ||
var path = this.path; | ||
if (path) { | ||
path.segmentsInfo = fabric.util.getPathSegmentsInfo(path.path); | ||
} | ||
}, | ||
/** | ||
* Return a context for measurement of text string. | ||
* if created it gets stored for reuse | ||
@@ -379,3 +375,10 @@ * @param {String} text Text string | ||
this._clearCache(); | ||
this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH; | ||
if (this.path) { | ||
this.width = this.path.width; | ||
this.height = this.path.height; | ||
} | ||
else { | ||
this.width = this.calcTextWidth() || this.cursorWidth || this.MIN_TEXT_WIDTH; | ||
this.height = this.calcTextHeight(); | ||
} | ||
if (this.textAlign.indexOf('justify') !== -1) { | ||
@@ -385,3 +388,2 @@ // once text is measured we need to make space fatter to make justified text. | ||
} | ||
this.height = this.calcTextHeight(); | ||
this.saveState({ propertySet: '_dimensionAffectingProps' }); | ||
@@ -551,8 +553,8 @@ }, | ||
} | ||
var lineTopOffset = 0, heightOfLine, | ||
var heightOfLine, | ||
lineLeftOffset, originalFill = ctx.fillStyle, | ||
line, lastColor, | ||
leftOffset = this._getLeftOffset(), | ||
topOffset = this._getTopOffset(), | ||
boxStart = 0, boxWidth = 0, charBox, currentColor; | ||
lineTopOffset = this._getTopOffset(), | ||
boxStart = 0, boxWidth = 0, charBox, currentColor, path = this.path; | ||
@@ -573,7 +575,20 @@ for (var i = 0, len = this._textLines.length; i < len; i++) { | ||
currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor'); | ||
if (currentColor !== lastColor) { | ||
if (path) { | ||
ctx.save(); | ||
ctx.translate(charBox.renderLeft, charBox.renderTop); | ||
ctx.rotate(charBox.angle); | ||
ctx.fillStyle = currentColor; | ||
currentColor && ctx.fillRect( | ||
-charBox.width / 2, | ||
-heightOfLine / this.lineHeight * (1 - this._fontSizeFraction), | ||
charBox.width, | ||
heightOfLine / this.lineHeight | ||
); | ||
ctx.restore(); | ||
} | ||
else if (currentColor !== lastColor) { | ||
ctx.fillStyle = lastColor; | ||
lastColor && ctx.fillRect( | ||
leftOffset + lineLeftOffset + boxStart, | ||
topOffset + lineTopOffset, | ||
lineTopOffset, | ||
boxWidth, | ||
@@ -590,7 +605,7 @@ heightOfLine / this.lineHeight | ||
} | ||
if (currentColor) { | ||
if (currentColor && !path) { | ||
ctx.fillStyle = currentColor; | ||
ctx.fillRect( | ||
leftOffset + lineLeftOffset + boxStart, | ||
topOffset + lineTopOffset, | ||
lineTopOffset, | ||
boxWidth, | ||
@@ -630,18 +645,2 @@ heightOfLine / this.lineHeight | ||
/** | ||
* apply all the character style to canvas for rendering | ||
* @private | ||
* @param {String} _char | ||
* @param {Number} lineIndex | ||
* @param {Number} charIndex | ||
* @param {Object} [decl] | ||
*/ | ||
_applyCharStyles: function(method, ctx, lineIndex, charIndex, styleDeclaration) { | ||
this._setFillStyles(ctx, styleDeclaration); | ||
this._setStrokeStyles(ctx, styleDeclaration); | ||
ctx.font = this._getFontDeclaration(styleDeclaration); | ||
}, | ||
/** | ||
* measure and return the width of a single character. | ||
@@ -729,10 +728,24 @@ * possibly overridden to accommodate different measure logic or | ||
var width = 0, i, grapheme, line = this._textLines[lineIndex], prevGrapheme, | ||
graphemeInfo, numOfSpaces = 0, lineBounds = new Array(line.length); | ||
graphemeInfo, numOfSpaces = 0, lineBounds = new Array(line.length), | ||
positionInPath = 0, startingPoint, totalPathLength, path = this.path; | ||
this.__charBounds[lineIndex] = lineBounds; | ||
if (path) { | ||
startingPoint = fabric.util.getPointOnPath(path.path, 0, path.segmentsInfo); | ||
totalPathLength = path.segmentsInfo[path.segmentsInfo.length - 1].length; | ||
startingPoint.x += path.pathOffset.x; | ||
startingPoint.y += path.pathOffset.y; | ||
} | ||
for (i = 0; i < line.length; i++) { | ||
grapheme = line[i]; | ||
graphemeInfo = this._getGraphemeBox(grapheme, lineIndex, i, prevGrapheme); | ||
if (path) { | ||
if (positionInPath > totalPathLength) { | ||
positionInPath %= totalPathLength; | ||
} | ||
this._setGraphemeOnPath(positionInPath, graphemeInfo, startingPoint); | ||
} | ||
lineBounds[i] = graphemeInfo; | ||
width += graphemeInfo.kernedWidth; | ||
positionInPath += graphemeInfo.kernedWidth; | ||
prevGrapheme = grapheme; | ||
@@ -752,2 +765,22 @@ } | ||
/** | ||
* Calculate the angle and the left,top position of the char that follow a path. | ||
* It appends it to graphemeInfo to be reused later at rendering | ||
* @private | ||
* @param {Number} positionInPath to be measured | ||
* @param {Object} graphemeInfo current grapheme box information | ||
* @param {Object} startingPoint position of the point | ||
*/ | ||
_setGraphemeOnPath: function(positionInPath, graphemeInfo, startingPoint) { | ||
var centerPosition = positionInPath + graphemeInfo.kernedWidth / 2, | ||
path = this.path; | ||
// we are at currentPositionOnPath. we want to know what point on the path is. | ||
var p1 = fabric.util.getPointOnPath(path.path, centerPosition - 0.1, path.segmentsInfo), | ||
p2 = fabric.util.getPointOnPath(path.path, centerPosition + 0.1, path.segmentsInfo); | ||
graphemeInfo.renderLeft = p1.x - startingPoint.x; | ||
graphemeInfo.renderTop = p1.y - startingPoint.y; | ||
graphemeInfo.angle = Math.atan2(p2.y - p1.y, p2.x - p1.x); | ||
}, | ||
/** | ||
* Measure and return the info of a single grapheme. | ||
@@ -844,4 +877,3 @@ * needs the the info of previous graphemes already filled | ||
ctx.save(); | ||
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset(), | ||
offsets = this._applyPatternGradientTransform(ctx, method === 'fillText' ? this.fill : this.stroke); | ||
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset(); | ||
for (var i = 0, len = this._textLines.length; i < len; i++) { | ||
@@ -855,4 +887,4 @@ var heightOfLine = this.getHeightOfLine(i), | ||
this._textLines[i], | ||
left + leftOffset - offsets.offsetX, | ||
top + lineHeights + maxHeight - offsets.offsetY, | ||
left + leftOffset, | ||
top + lineHeights + maxHeight, | ||
i | ||
@@ -917,3 +949,4 @@ ); | ||
timeToRender, | ||
shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex); | ||
path = this.path, | ||
shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path; | ||
@@ -929,3 +962,3 @@ ctx.save(); | ||
for (var i = 0, len = line.length - 1; i <= len; i++) { | ||
timeToRender = i === len || this.charSpacing; | ||
timeToRender = i === len || this.charSpacing || path; | ||
charsToRender += line[i]; | ||
@@ -952,3 +985,12 @@ charBox = this.__charBounds[lineIndex][i]; | ||
if (timeToRender) { | ||
this._renderChar(method, ctx, lineIndex, i, charsToRender, left, top, lineHeight); | ||
if (path) { | ||
ctx.save(); | ||
ctx.translate(charBox.renderLeft, charBox.renderTop); | ||
ctx.rotate(charBox.angle); | ||
this._renderChar(method, ctx, lineIndex, i, charsToRender, -boxWidth / 2, 0, lineHeight); | ||
ctx.restore(); | ||
} | ||
else { | ||
this._renderChar(method, ctx, lineIndex, i, charsToRender, left, top, lineHeight); | ||
} | ||
charsToRender = ''; | ||
@@ -964,3 +1006,70 @@ actualStyle = nextStyle; | ||
/** | ||
* This function try to patch the missing gradientTransform on canvas gradients. | ||
* transforming a context to transform the gradient, is going to transform the stroke too. | ||
* we want to transform the gradient but not the stroke operation, so we create | ||
* a transformed gradient on a pattern and then we use the pattern instead of the gradient. | ||
* this method has drawbacks: is slow, is in low resolution, needs a patch for when the size | ||
* is limited. | ||
* @private | ||
* @param {fabric.Gradient} filler a fabric gradient instance | ||
* @return {CanvasPattern} a pattern to use as fill/stroke style | ||
*/ | ||
_applyPatternGradientTransformText: function(filler) { | ||
var pCanvas = fabric.util.createCanvasElement(), pCtx, | ||
// TODO: verify compatibility with strokeUniform | ||
width = this.width + this.strokeWidth, height = this.height + this.strokeWidth; | ||
pCanvas.width = width; | ||
pCanvas.height = height; | ||
pCtx = pCanvas.getContext('2d'); | ||
pCtx.beginPath(); pCtx.moveTo(0, 0); pCtx.lineTo(width, 0); pCtx.lineTo(width, height); | ||
pCtx.lineTo(0, height); pCtx.closePath(); | ||
pCtx.translate(width / 2, height / 2); | ||
pCtx.fillStyle = filler.toLive(pCtx); | ||
this._applyPatternGradientTransform(pCtx, filler); | ||
pCtx.fill(); | ||
return pCtx.createPattern(pCanvas, 'no-repeat'); | ||
}, | ||
handleFiller: function(ctx, property, filler) { | ||
var offsetX, offsetY; | ||
if (filler.toLive) { | ||
if (filler.gradientUnits === 'percentage' || filler.gradientTrasnform || filler.patternTransform) { | ||
// need to transform gradient in a pattern. | ||
// this is a slow process. If you are hitting this codepath, and the object | ||
// is not using caching, you should consider switching it on. | ||
// we need a canvas as big as the current object caching canvas. | ||
offsetX = -this.width / 2; | ||
offsetY = -this.height / 2; | ||
ctx.translate(offsetX, offsetY); | ||
ctx[property] = this._applyPatternGradientTransformText(filler); | ||
return { offsetX: offsetX, offsetY: offsetY }; | ||
} | ||
else { | ||
// is a simple gradient or pattern | ||
ctx[property] = filler.toLive(ctx, this); | ||
return this._applyPatternGradientTransform(ctx, filler); | ||
} | ||
} | ||
else { | ||
// is a color | ||
ctx[property] = filler; | ||
} | ||
return { offsetX: 0, offsetY: 0 }; | ||
}, | ||
_setStrokeStyles: function(ctx, decl) { | ||
ctx.lineWidth = decl.strokeWidth; | ||
ctx.lineCap = this.strokeLineCap; | ||
ctx.lineDashOffset = this.strokeDashOffset; | ||
ctx.lineJoin = this.strokeLineJoin; | ||
ctx.miterLimit = this.strokeMiterLimit; | ||
return this.handleFiller(ctx, 'strokeStyle', decl.stroke); | ||
}, | ||
_setFillStyles: function(ctx, decl) { | ||
return this.handleFiller(ctx, 'fillStyle', decl.fill); | ||
}, | ||
/** | ||
* @private | ||
* @param {String} method | ||
@@ -979,3 +1088,4 @@ * @param {CanvasRenderingContext2D} ctx Context to render on | ||
shouldFill = method === 'fillText' && fullDecl.fill, | ||
shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth; | ||
shouldStroke = method === 'strokeText' && fullDecl.stroke && fullDecl.strokeWidth, | ||
fillOffsets, strokeOffsets; | ||
@@ -985,6 +1095,10 @@ if (!shouldStroke && !shouldFill) { | ||
} | ||
decl && ctx.save(); | ||
ctx.save(); | ||
this._applyCharStyles(method, ctx, lineIndex, charIndex, fullDecl); | ||
shouldFill && (fillOffsets = this._setFillStyles(ctx, fullDecl)); | ||
shouldStroke && (strokeOffsets = this._setStrokeStyles(ctx, fullDecl)); | ||
ctx.font = this._getFontDeclaration(fullDecl); | ||
if (decl && decl.textBackgroundColor) { | ||
@@ -996,6 +1110,5 @@ this._removeShadow(ctx); | ||
} | ||
shouldFill && ctx.fillText(_char, left, top); | ||
shouldStroke && ctx.strokeText(_char, left, top); | ||
decl && ctx.restore(); | ||
shouldFill && ctx.fillText(_char, left - fillOffsets.offsetX, top - fillOffsets.offsetY); | ||
shouldStroke && ctx.strokeText(_char, left - strokeOffsets.offsetX, top - strokeOffsets.offsetY); | ||
ctx.restore(); | ||
}, | ||
@@ -1150,3 +1263,3 @@ | ||
* @param {Number} lineIndex the line number | ||
* @param {Number} charIndex the charater number | ||
* @param {Number} charIndex the character number | ||
* @param {String} property the property name | ||
@@ -1177,3 +1290,3 @@ * @returns the value of 'property' | ||
boxStart, boxWidth, charBox, currentDecoration, | ||
maxHeight, currentFill, lastFill, | ||
maxHeight, currentFill, lastFill, path = this.path, | ||
charSpacing = this._getWidthOfCharSpacing(); | ||
@@ -1203,11 +1316,26 @@ | ||
_dy = this.getValueOfPropertyAt(i, j, 'deltaY'); | ||
if ((currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy) && | ||
boxWidth > 0) { | ||
if (path && currentDecoration && currentFill) { | ||
ctx.save(); | ||
ctx.fillStyle = lastFill; | ||
lastDecoration && lastFill && ctx.fillRect( | ||
leftOffset + lineLeftOffset + boxStart, | ||
top + this.offsets[type] * size + dy, | ||
boxWidth, | ||
ctx.translate(charBox.renderLeft, charBox.renderTop); | ||
ctx.rotate(charBox.angle); | ||
ctx.fillRect( | ||
-charBox.kernedWidth / 2, | ||
this.offsets[type] * _size + _dy, | ||
charBox.kernedWidth, | ||
this.fontSize / 15 | ||
); | ||
ctx.restore(); | ||
} | ||
else if ( | ||
(currentDecoration !== lastDecoration || currentFill !== lastFill || _size !== size || _dy !== dy) | ||
&& boxWidth > 0 | ||
) { | ||
lastDecoration && lastFill && | ||
ctx.fillRect( | ||
leftOffset + lineLeftOffset + boxStart, | ||
top + this.offsets[type] * size + dy, | ||
boxWidth, | ||
this.fontSize / 15 | ||
); | ||
boxStart = charBox.left; | ||
@@ -1331,5 +1459,10 @@ boxWidth = charBox.width; | ||
var needsDims = false; | ||
var isAddingPath = false; | ||
if (typeof key === 'object') { | ||
for (var _key in key) { | ||
if (_key === 'path') { | ||
this.setPathInfo(); | ||
} | ||
needsDims = needsDims || this._dimensionAffectingProps.indexOf(_key) !== -1; | ||
isAddingPath = isAddingPath || _key === 'path'; | ||
} | ||
@@ -1339,3 +1472,7 @@ } | ||
needsDims = this._dimensionAffectingProps.indexOf(key) !== -1; | ||
isAddingPath = key === 'path'; | ||
} | ||
if (isAddingPath) { | ||
this.setPathInfo(); | ||
} | ||
if (needsDims) { | ||
@@ -1342,0 +1479,0 @@ this.initDimensions(); |
@@ -75,3 +75,3 @@ (function(global) { | ||
* Use this boolean property in order to split strings that have no white space concept. | ||
* this is a cheap way to help with chinese/japaense | ||
* this is a cheap way to help with chinese/japanese | ||
* @type Boolean | ||
@@ -316,3 +316,3 @@ * @since 2.6.0 | ||
line = [], | ||
// spaces in different languges? | ||
// spaces in different languages? | ||
words = splitByGrapheme ? fabric.util.string.graphemeSplit(_line) : _line.split(this._wordJoiners), | ||
@@ -340,3 +340,3 @@ word = '', | ||
lineWidth += infixWidth + wordWidth - additionalSpace; | ||
if (lineWidth >= desiredWidth && !lineJustStarted) { | ||
if (lineWidth > desiredWidth && !lineJustStarted) { | ||
graphemeLines.push(line); | ||
@@ -343,0 +343,0 @@ line = []; |
@@ -432,3 +432,3 @@ (function () { | ||
* @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. The first argument is the created image, the second argument is a flag indicating whether an error occured or not. | ||
* @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 occurred or not. | ||
* @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. | ||
@@ -695,3 +695,6 @@ */ | ||
/** | ||
* Sets zoom level of this canvas instance, zoom centered around point | ||
* Sets zoom level of this canvas instance, the zoom centered around point | ||
* meaning that following zoom to point with the same point will have the visual | ||
* effect of the zoom originating from that point. The point won't move. | ||
* It has nothing to do with canvas center or visual center of the viewport. | ||
* @param {fabric.Point} point to zoom with respect to | ||
@@ -1117,3 +1120,3 @@ * @param {Number} value to set zoom to, less than 1 zooms out | ||
/** | ||
* Returs dataless JSON representation of canvas | ||
* Returns dataless JSON representation of canvas | ||
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output | ||
@@ -1234,3 +1237,3 @@ * @return {String} json string | ||
* @param {Object} [options.viewBox] SVG viewbox object | ||
* @param {Number} [options.viewBox.x] x-cooridnate of viewbox | ||
* @param {Number} [options.viewBox.x] x-coordinate of viewbox | ||
* @param {Number} [options.viewBox.y] y-coordinate of viewbox | ||
@@ -1575,3 +1578,3 @@ * @param {Number} [options.viewBox.width] Width of viewbox | ||
* Moves an object or a selection down in stack of drawn objects | ||
* An optional paramter, intersecting allowes to move the object in behind | ||
* An optional parameter, intersecting allows to move the object in behind | ||
* the first intersecting object. Where intersection is calculated with | ||
@@ -1649,3 +1652,3 @@ * bounding box. If no intersection is found, there will not be change in the | ||
* Moves an object or a selection up in stack of drawn objects | ||
* An optional paramter, intersecting allowes to move the object in front | ||
* An optional parameter, intersecting allows to move the object in front | ||
* of the first intersecting object. Where intersection is calculated with | ||
@@ -1820,6 +1823,9 @@ * bounding box. If no intersection is found, there will not be change in the | ||
/** | ||
* Returns JSON representation of canvas | ||
* Returns Object representation of canvas | ||
* this alias is provided because if you call JSON.stringify on an instance, | ||
* the toJSON object will be invoked if it exists. | ||
* Having a toJSON method means you can do JSON.stringify(myCanvas) | ||
* @function | ||
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output | ||
* @return {String} JSON string | ||
* @return {Object} JSON compatible object | ||
* @tutorial {@link http://fabricjs.com/fabric-intro-part-3#serialization} | ||
@@ -1826,0 +1832,0 @@ * @see {@link http://jsfiddle.net/fabricjs/pec86/|jsFiddle demo} |
@@ -962,3 +962,3 @@ (function(global) { | ||
* @memberOf fabric.util | ||
* @param {Array} trasnform an array with 6 numbers | ||
* @param {Array} transform an array with 6 numbers | ||
* @return {String} transform matrix for svg | ||
@@ -965,0 +965,0 @@ * @return {Object.y} Limited dimensions by Y |
@@ -118,3 +118,3 @@ (function() { | ||
* @param {Number} y2 | ||
* @param {Number} x3 end of beizer | ||
* @param {Number} x3 end of bezier | ||
* @param {Number} y3 | ||
@@ -207,3 +207,3 @@ */ | ||
/** | ||
* Converts arc to a bunch of beizer curves | ||
* Converts arc to a bunch of bezier curves | ||
* @param {Number} fx starting point x | ||
@@ -213,3 +213,3 @@ * @param {Number} fy starting point y | ||
*/ | ||
function fromArcToBeizers(fx, fy, coords) { | ||
function fromArcToBeziers(fx, fy, coords) { | ||
var rx = coords[1], | ||
@@ -235,3 +235,9 @@ ry = coords[2], | ||
/** | ||
* This function take a parsed SVG path and make it simpler for fabricJS logic. | ||
* simplification consist of: only UPPERCASE absolute commands ( relative converted to absolute ) | ||
* S converted in C, T converted in Q, A converted in C. | ||
* @param {Array} path the array of commands of a parsed svg path for fabric.Path | ||
* @return {Array} the simplified array of commands of a parsed svg path for fabric.Path | ||
*/ | ||
function makePathSimpler(path) { | ||
@@ -384,3 +390,3 @@ // x and y represent the last point of the path. the previous command point. | ||
converted = true; | ||
destinationPath = destinationPath.concat(fromArcToBeizers(x, y, current)); | ||
destinationPath = destinationPath.concat(fromArcToBeziers(x, y, current)); | ||
x = current[6]; | ||
@@ -463,2 +469,4 @@ y = current[7]; | ||
// this will run over a path segment ( a cubic or quadratic segment) and approximate it | ||
// with 100 segemnts. This will good enough to calculate the length of the curve | ||
function pathIterator(iterator, x1, y1) { | ||
@@ -474,3 +482,39 @@ var tempP = { x: x1, y: y1 }, p, tmpLen = 0, perc; | ||
//measures the length of a pre-simplified path | ||
/** | ||
* Given a pathInfo, and a distance in pixels, find the percentage from 0 to 1 | ||
* that correspond to that pixels run over the path. | ||
* The percentage will be then used to find the correct point on the canvas for the path. | ||
* @param {Array} segInfo fabricJS collection of information on a parsed path | ||
* @param {Number} distance from starting point, in pixels. | ||
* @return {Number} length of segment | ||
*/ | ||
function findPercentageForDistance(segInfo, distance) { | ||
var perc = 0, tmpLen = 0, iterator = segInfo.iterator, tempP = { x: segInfo.x, y: segInfo.y }, | ||
p, nextLen, nextStep = 0.01; | ||
// nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100 | ||
// the path | ||
while (tmpLen < distance && perc <= 1 && nextStep > 0.0001) { | ||
p = iterator(perc); | ||
nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y); | ||
// compare tmpLen each cycle with distance, decide next perc to test. | ||
if ((nextLen + tmpLen) > distance) { | ||
// we discard this step and we make smaller steps. | ||
nextStep /= 2; | ||
perc -= nextStep; | ||
} | ||
else { | ||
tempP = p; | ||
perc += nextStep; | ||
tmpLen += nextLen; | ||
} | ||
} | ||
return p; | ||
} | ||
/** | ||
* Run over a parsed and simplifed path and extrac some informations. | ||
* informations are length of each command and starting point | ||
* @param {Array} path fabricJS parsed path commands | ||
* @return {Array} path commands informations | ||
*/ | ||
function getPathSegmentsInfo(path) { | ||
@@ -510,2 +554,3 @@ var totalLength = 0, len = path.length, current, | ||
); | ||
tempInfo.iterator = iterator; | ||
tempInfo.length = pathIterator(iterator, x1, y1); | ||
@@ -524,2 +569,3 @@ x1 = current[5]; | ||
); | ||
tempInfo.iterator = iterator; | ||
tempInfo.length = pathIterator(iterator, x1, y1); | ||
@@ -546,14 +592,18 @@ x1 = current[3]; | ||
function getPointOnPath(path, perc, infos) { | ||
function getPointOnPath(path, distance, infos) { | ||
if (!infos) { | ||
infos = getPathSegmentsInfo(path); | ||
} | ||
var distance = infos[infos.length - 1] * perc, i = 0; | ||
while ((distance - infos[i] > 0) && i < infos.length) { | ||
distance -= infos[i]; | ||
// var distance = infos[infos.length - 1] * perc; | ||
var i = 0; | ||
while ((distance - infos[i].length > 0) && i < (infos.length - 2)) { | ||
distance -= infos[i].length; | ||
i++; | ||
} | ||
var segInfo = infos[i], segPercent = distance / segInfo.length, | ||
command = segInfo.length, segment = path[i]; | ||
command = segInfo.command, segment = path[i]; | ||
switch (command) { | ||
case 'M': | ||
return { x: segInfo.x, y: segInfo.y }; | ||
case 'Z': | ||
@@ -565,3 +615,2 @@ case 'z': | ||
); | ||
break; | ||
case 'L': | ||
@@ -572,25 +621,6 @@ return new fabric.Point(segInfo.x, segInfo.y).lerp( | ||
); | ||
break; | ||
case 'C': | ||
return getPointOnCubicBezierIterator( | ||
segInfo.x, | ||
segInfo.y, | ||
segment[1], | ||
segment[2], | ||
segment[3], | ||
segment[4], | ||
segment[5], | ||
segment[6] | ||
)(segPercent); | ||
break; | ||
return findPercentageForDistance(segInfo, distance); | ||
case 'Q': | ||
return getPointOnQuadraticBezierIterator( | ||
segInfo.x, | ||
segInfo.y, | ||
segment[1], | ||
segment[2], | ||
segment[3], | ||
segment[4] | ||
)(segPercent); | ||
break; | ||
return findPercentageForDistance(segInfo, distance); | ||
} | ||
@@ -697,2 +727,3 @@ } | ||
* Draws arc | ||
* @deprecated | ||
* @param {CanvasRenderingContext2D} ctx | ||
@@ -705,5 +736,5 @@ * @param {Number} fx | ||
coords = coords.slice(0).unshift('X'); // command A or a does not matter | ||
var beizers = fromArcToBeizers(fx, fy, coords); | ||
beizers.forEach(function(beizer) { | ||
ctx.bezierCurveTo.apply(ctx, beizer.slice(1)); | ||
var beziers = fromArcToBeziers(fx, fy, coords); | ||
beziers.forEach(function(bezier) { | ||
ctx.bezierCurveTo.apply(ctx, bezier.slice(1)); | ||
}); | ||
@@ -715,3 +746,9 @@ }; | ||
fabric.util.getPathSegmentsInfo = getPathSegmentsInfo; | ||
fabric.util.fromArcToBeizers = fromArcToBeizers; | ||
fabric.util.fromArcToBeziers = fromArcToBeziers; | ||
/** | ||
* Typo of `fromArcToBeziers` kept for not breaking the api once corrected. | ||
* Will be removed in fabric 5.0 | ||
* @deprecated | ||
*/ | ||
fabric.util.fromArcToBeizers = fromArcToBeziers; | ||
fabric.util.getBoundsOfCurve = getBoundsOfCurve; | ||
@@ -718,0 +755,0 @@ fabric.util.getPointOnPath = getPointOnPath; |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
2474235
0
57692
294
2