mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-03-16 22:10:32 +00:00
Limit sin and cosin very small floats on 90/270 degrees (#4734)
* so far ok * fix transformations decimal * remove some changes * less changes * test passing * less calculation * added shortcut * modified tests
This commit is contained in:
parent
687cd7b495
commit
2e532cc362
12 changed files with 260 additions and 73 deletions
|
|
@ -45,7 +45,7 @@
|
|||
mainParameter: 'rotation',
|
||||
|
||||
calculateMatrix: function() {
|
||||
var rad = this.rotation * Math.PI, cos = Math.cos(rad), sin = Math.sin(rad),
|
||||
var rad = this.rotation * Math.PI, cos = fabric.util.cos(rad), sin = fabric.util.sin(rad),
|
||||
aThird = 1 / 3, aThirdSqtSin = Math.sqrt(aThird) * sin, OneMinusCos = 1 - cos;
|
||||
this.matrix = [
|
||||
1, 0, 0, 0, 0,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
}
|
||||
|
||||
var degreesToRadians = fabric.util.degreesToRadians,
|
||||
multiplyMatrices = fabric.util.multiplyTransformMatrices;
|
||||
multiplyMatrices = fabric.util.multiplyTransformMatrices,
|
||||
transformPoint = fabric.util.transformPoint;
|
||||
|
||||
fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
|
||||
|
||||
|
|
@ -355,45 +356,55 @@
|
|||
* @chainable
|
||||
*/
|
||||
calcCoords: function(absolute) {
|
||||
var theta = degreesToRadians(this.angle),
|
||||
var rotateMatrix = this._calcRotateMatrix(),
|
||||
translateMatrix = this._calcTranslateMatrix(),
|
||||
startMatrix = multiplyMatrices(translateMatrix, rotateMatrix),
|
||||
vpt = this.getViewportTransform(),
|
||||
dim = absolute ? this._getTransformedDimensions() : this._calculateCurrentDimensions(),
|
||||
currentWidth = dim.x, currentHeight = dim.y,
|
||||
sinTh = theta ? Math.sin(theta) : 0,
|
||||
cosTh = theta ? Math.cos(theta) : 1,
|
||||
_angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0,
|
||||
_hypotenuse = (currentWidth / Math.cos(_angle)) / 2,
|
||||
offsetX = Math.cos(_angle + theta) * _hypotenuse,
|
||||
offsetY = Math.sin(_angle + theta) * _hypotenuse,
|
||||
center = this.getCenterPoint(),
|
||||
// offset added for rotate and scale actions
|
||||
coords = absolute ? center : fabric.util.transformPoint(center, vpt),
|
||||
tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),
|
||||
tr = new fabric.Point(tl.x + (currentWidth * cosTh), tl.y + (currentWidth * sinTh)),
|
||||
bl = new fabric.Point(tl.x - (currentHeight * sinTh), tl.y + (currentHeight * cosTh)),
|
||||
br = new fabric.Point(coords.x + offsetX, coords.y + offsetY);
|
||||
finalMatrix = absolute ? startMatrix : multiplyMatrices(vpt, startMatrix),
|
||||
dim = this._getTransformedDimensions(),
|
||||
w = dim.x / 2, h = dim.y / 2,
|
||||
tl = transformPoint({ x: -w, y: -h }, finalMatrix),
|
||||
tr = transformPoint({ x: w, y: -h }, finalMatrix),
|
||||
bl = transformPoint({ x: -w, y: h }, finalMatrix),
|
||||
br = transformPoint({ x: w, y: h }, finalMatrix);
|
||||
if (!absolute) {
|
||||
var padding = this.padding, angle = degreesToRadians(this.angle),
|
||||
cos = fabric.util.cos(angle), sin = fabric.util.sin(angle),
|
||||
cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP,
|
||||
cosPMinusSinP = cosP - sinP;
|
||||
if (padding) {
|
||||
tl.x -= cosPMinusSinP;
|
||||
tl.y -= cosPSinP;
|
||||
tr.x += cosPSinP;
|
||||
tr.y -= cosPMinusSinP;
|
||||
bl.x -= cosPSinP;
|
||||
bl.y += cosPMinusSinP;
|
||||
br.x += cosPMinusSinP;
|
||||
br.y += cosPSinP;
|
||||
}
|
||||
var ml = new fabric.Point((tl.x + bl.x) / 2, (tl.y + bl.y) / 2),
|
||||
mt = new fabric.Point((tr.x + tl.x) / 2, (tr.y + tl.y) / 2),
|
||||
mr = new fabric.Point((br.x + tr.x) / 2, (br.y + tr.y) / 2),
|
||||
mb = new fabric.Point((br.x + bl.x) / 2, (br.y + bl.y) / 2),
|
||||
mtr = new fabric.Point(mt.x + sinTh * this.rotatingPointOffset, mt.y - cosTh * this.rotatingPointOffset);
|
||||
mtr = new fabric.Point(mt.x + sin * this.rotatingPointOffset, mt.y - cos * this.rotatingPointOffset);
|
||||
}
|
||||
|
||||
// debugging
|
||||
|
||||
/* setTimeout(function() {
|
||||
canvas.contextTop.fillStyle = 'green';
|
||||
canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);
|
||||
canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);
|
||||
canvas.contextTop.fillRect(br.x, br.y, 3, 3);
|
||||
canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);
|
||||
canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);
|
||||
canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);
|
||||
canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);
|
||||
canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);
|
||||
canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);
|
||||
}, 50); */
|
||||
// if (!absolute) {
|
||||
// var canvas = this.canvas;
|
||||
// setTimeout(function() {
|
||||
// canvas.contextTop.clearRect(0, 0, 700, 700);
|
||||
// canvas.contextTop.fillStyle = 'green';
|
||||
// canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(br.x, br.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);
|
||||
// canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);
|
||||
// }, 50);
|
||||
// }
|
||||
|
||||
var coords = {
|
||||
// corners
|
||||
|
|
@ -437,16 +448,21 @@
|
|||
*/
|
||||
_calcRotateMatrix: function() {
|
||||
if (this.angle) {
|
||||
var theta = degreesToRadians(this.angle), cos = Math.cos(theta), sin = Math.sin(theta);
|
||||
// trying to keep rounding error small, ugly but it works.
|
||||
if (cos === 6.123233995736766e-17 || cos === -1.8369701987210297e-16) {
|
||||
cos = 0;
|
||||
}
|
||||
var theta = degreesToRadians(this.angle), cos = fabric.util.cos(theta), sin = fabric.util.sin(theta);
|
||||
return [cos, sin, -sin, cos, 0, 0];
|
||||
}
|
||||
return fabric.iMatrix.concat();
|
||||
},
|
||||
|
||||
/**
|
||||
* calculate the translation matrix for an object transform
|
||||
* @return {Array} rotation matrix for the object
|
||||
*/
|
||||
_calcTranslateMatrix: function() {
|
||||
var center = this.getCenterPoint();
|
||||
return [1, 0, 0, 1, center.x, center.y];
|
||||
},
|
||||
|
||||
transformMatrixKey: function(skipGroup) {
|
||||
var sep = '_', prefix = '';
|
||||
if (!skipGroup && this.group) {
|
||||
|
|
@ -485,8 +501,7 @@
|
|||
if (cache.key === key) {
|
||||
return cache.value;
|
||||
}
|
||||
var center = this.getCenterPoint(),
|
||||
matrix = [1, 0, 0, 1, center.x, center.y],
|
||||
var matrix = this._calcTranslateMatrix(),
|
||||
rotateMatrix,
|
||||
dimensionMatrix = this._calcDimensionsTransformMatrix(this.skewX, this.skewY, true);
|
||||
if (this.angle) {
|
||||
|
|
@ -542,8 +557,11 @@
|
|||
if (typeof skewY === 'undefined') {
|
||||
skewY = this.skewY;
|
||||
}
|
||||
var dimensions = this._getNonTransformedDimensions(),
|
||||
dimX = dimensions.x / 2, dimY = dimensions.y / 2,
|
||||
var dimensions = this._getNonTransformedDimensions();
|
||||
if (skewX === 0 && skewY === 0) {
|
||||
return { x: dimensions.x * this.scaleX, y: dimensions.y * this.scaleY };
|
||||
}
|
||||
var dimX = dimensions.x / 2, dimY = dimensions.y / 2,
|
||||
points = [
|
||||
{
|
||||
x: -dimX,
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@
|
|||
/* Math.sqrt(2 * Math.pow(this.cornerSize, 2)) / 2, */
|
||||
/* 0.707106 stands for sqrt(2)/2 */
|
||||
cornerHypotenuse = this.cornerSize * 0.707106,
|
||||
cosHalfOffset = cornerHypotenuse * Math.cos(newTheta),
|
||||
sinHalfOffset = cornerHypotenuse * Math.sin(newTheta),
|
||||
cosHalfOffset = cornerHypotenuse * fabric.util.cos(newTheta),
|
||||
sinHalfOffset = cornerHypotenuse * fabric.util.sin(newTheta),
|
||||
x, y;
|
||||
|
||||
for (var point in coords) {
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@
|
|||
adjustPosition: function(to) {
|
||||
var angle = degreesToRadians(this.angle),
|
||||
hypotFull = this.getScaledWidth(),
|
||||
xFull = Math.cos(angle) * hypotFull,
|
||||
yFull = Math.sin(angle) * hypotFull,
|
||||
xFull = fabric.util.cos(angle) * hypotFull,
|
||||
yFull = fabric.util.sin(angle) * hypotFull,
|
||||
offsetFrom, offsetTo;
|
||||
|
||||
//TODO: this function does not consider mixed situation like top, center.
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@
|
|||
*/
|
||||
fabric.parseTransformAttribute = (function() {
|
||||
function rotateMatrix(matrix, args) {
|
||||
var cos = Math.cos(args[0]), sin = Math.sin(args[0]),
|
||||
var cos = fabric.util.cos(args[0]), sin = fabric.util.sin(args[0]),
|
||||
x = 0, y = 0;
|
||||
if (args.length === 3) {
|
||||
x = args[1];
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@
|
|||
);
|
||||
}
|
||||
else {
|
||||
var startX = Math.cos(this.startAngle) * this.radius,
|
||||
startY = Math.sin(this.startAngle) * this.radius,
|
||||
endX = Math.cos(this.endAngle) * this.radius,
|
||||
endY = Math.sin(this.endAngle) * this.radius,
|
||||
var startX = fabric.util.cos(this.startAngle) * this.radius,
|
||||
startY = fabric.util.sin(this.startAngle) * this.radius,
|
||||
endX = fabric.util.cos(this.endAngle) * this.radius,
|
||||
endY = fabric.util.sin(this.endAngle) * this.radius,
|
||||
largeFlag = angle > pi ? '1' : '0';
|
||||
|
||||
markup.push(
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
}
|
||||
|
||||
var PI = Math.PI, th = rotateX * PI / 180,
|
||||
sinTh = Math.sin(th),
|
||||
cosTh = Math.cos(th),
|
||||
sinTh = fabric.util.sin(th),
|
||||
cosTh = fabric.util.cos(th),
|
||||
fromX = 0, fromY = 0;
|
||||
|
||||
rx = Math.abs(rx);
|
||||
|
|
@ -76,10 +76,10 @@
|
|||
return segmentToBezierCache[argsString2];
|
||||
}
|
||||
|
||||
var costh2 = Math.cos(th2),
|
||||
sinth2 = Math.sin(th2),
|
||||
costh3 = Math.cos(th3),
|
||||
sinth3 = Math.sin(th3),
|
||||
var costh2 = fabric.util.cos(th2),
|
||||
sinth2 = fabric.util.sin(th2),
|
||||
costh3 = fabric.util.cos(th3),
|
||||
sinth3 = fabric.util.sin(th3),
|
||||
toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,
|
||||
toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,
|
||||
cp1X = fromX + mT * ( -cosTh * rx * sinth2 - sinTh * ry * costh2),
|
||||
|
|
|
|||
|
|
@ -4,13 +4,57 @@
|
|||
atan2 = Math.atan2,
|
||||
pow = Math.pow,
|
||||
abs = Math.abs,
|
||||
PiBy180 = Math.PI / 180;
|
||||
PiBy180 = Math.PI / 180,
|
||||
PiBy2 = Math.PI / 2;
|
||||
|
||||
/**
|
||||
* @namespace fabric.util
|
||||
*/
|
||||
fabric.util = {
|
||||
|
||||
/**
|
||||
* Calculate the cos of an angle, avoiding returning floats for known results
|
||||
* @static
|
||||
* @memberOf fabric.util
|
||||
* @param {Number} angle the angle in radians or in degree
|
||||
* @return {Number}
|
||||
*/
|
||||
cos: function(angle) {
|
||||
if (angle === 0) { return 1; }
|
||||
if (angle < 0) {
|
||||
// cos(a) = cos(-a)
|
||||
angle = -angle;
|
||||
}
|
||||
var angleSlice = angle / PiBy2;
|
||||
switch (angleSlice) {
|
||||
case 1: case 3: return 0;
|
||||
case 2: return -1;
|
||||
}
|
||||
return Math.cos(angle);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate the sin of an angle, avoiding returning floats for known results
|
||||
* @static
|
||||
* @memberOf fabric.util
|
||||
* @param {Number} angle the angle in radians or in degree
|
||||
* @return {Number}
|
||||
*/
|
||||
sin: function(angle) {
|
||||
if (angle === 0) { return 0; }
|
||||
var angleSlice = angle / PiBy2, sign = 1;
|
||||
if (angle < 0) {
|
||||
// sin(-a) = -sin(a)
|
||||
sign = -1;
|
||||
}
|
||||
switch (angleSlice) {
|
||||
case 1: return sign;
|
||||
case 2: return 0;
|
||||
case 3: return -sign;
|
||||
}
|
||||
return Math.sin(angle);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes value from an array.
|
||||
* Presence of value (and its position in an array) is determined via `Array.prototype.indexOf`
|
||||
|
|
@ -86,8 +130,8 @@
|
|||
* @return {Object} The new rotated point
|
||||
*/
|
||||
rotateVector: function(vector, radians) {
|
||||
var sin = Math.sin(radians),
|
||||
cos = Math.cos(radians),
|
||||
var sin = fabric.util.sin(radians),
|
||||
cos = fabric.util.cos(radians),
|
||||
rx = vector.x * cos - vector.y * sin,
|
||||
ry = vector.x * sin + vector.y * cos;
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -672,13 +672,132 @@
|
|||
assert.deepEqual(coords[3], new fabric.Point(40, 47), 'return bottom left corner cached oCoords');
|
||||
});
|
||||
|
||||
// QUnit.test('getCoords return coordinate of object', function(assert) {
|
||||
// var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40 });
|
||||
// var coords = cObj.getCoords();
|
||||
// assert.equal(coords[0], { x: 40, y: 30 }, 'return top left corner');
|
||||
// assert.equal(coords[1], { x: 1, y: 1 }, 'return top right corner');
|
||||
// assert.equal(coords[2], { x: 1, y: 1 }, 'return bottom right corner');
|
||||
// assert.equal(coords[3], { x: 1, y: 1 }, 'return bottom left corner');
|
||||
// });
|
||||
QUnit.test('getCoords absolute with angle', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, angle: 20 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords(true);
|
||||
assert.deepEqual(coords[0].x, 40, 'return top left absolute with angle X');
|
||||
assert.deepEqual(coords[1].x, 51.2763114494309, 'return top right absolute with angle X');
|
||||
assert.deepEqual(coords[2].x, 45.46196901289453, 'return bottom right absolute with angle X');
|
||||
assert.deepEqual(coords[3].x, 34.18565756346363, 'return bottom left absolute with angle X');
|
||||
assert.deepEqual(coords[0].y, 30, 'return top left absolute with angle Y');
|
||||
assert.deepEqual(coords[1].y, 34.104241719908025, 'return top right absolute with angle Y');
|
||||
assert.deepEqual(coords[2].y, 50.079016273268465, 'return bottom right absolute with angle Y');
|
||||
assert.deepEqual(coords[3].y, 45.97477455336044, 'return bottom left absolute with angle Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords with angle', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, angle: 20 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords();
|
||||
assert.deepEqual(coords[0].x, 115, 'return top left with angle X');
|
||||
assert.deepEqual(coords[1].x, 137.55262289886178, 'return top right with angle X');
|
||||
assert.deepEqual(coords[2].x, 125.92393802578906, 'return bottom right with angle X');
|
||||
assert.deepEqual(coords[3].x, 103.37131512692726, 'return bottom left with angle X');
|
||||
assert.deepEqual(coords[0].y, 85, 'return top left with angle Y');
|
||||
assert.deepEqual(coords[1].y, 93.20848343981605, 'return top right with angle Y');
|
||||
assert.deepEqual(coords[2].y, 125.15803254653693, 'return bottom right with angle Y');
|
||||
assert.deepEqual(coords[3].y, 116.94954910672088, 'return bottom left with angle Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords absolute with skewX', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, skewX: 45 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords(true);
|
||||
assert.deepEqual(coords[0].x, 40, 'return top left absolute with skewX X');
|
||||
assert.deepEqual(coords[1].x, 69, 'return top right absolute with skewX X');
|
||||
assert.deepEqual(coords[2].x, 69, 'return bottom absolute right with skewX X');
|
||||
assert.deepEqual(coords[3].x, 40, 'return bottom absolute left with skewX X');
|
||||
assert.deepEqual(coords[0].y, 30, 'return top left absolute with skewX Y');
|
||||
assert.deepEqual(coords[1].y, 30, 'return top right absolute with skewX Y');
|
||||
assert.deepEqual(coords[2].y, 47, 'return bottom absolute right with skewX Y');
|
||||
assert.deepEqual(coords[3].y, 47, 'return bottom absolute left with skewX Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords with skewX', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, skewX: 45 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords();
|
||||
assert.deepEqual(coords[0].x, 115, 'return top left with skewX X');
|
||||
assert.deepEqual(coords[1].x, 173, 'return top right with skewX X');
|
||||
assert.deepEqual(coords[2].x, 173, 'return bottom right with skewX X');
|
||||
assert.deepEqual(coords[3].x, 115, 'return bottom left with skewX X');
|
||||
assert.deepEqual(coords[0].y, 85, 'return top left with skewX Y');
|
||||
assert.deepEqual(coords[1].y, 85, 'return top right with skewX Y');
|
||||
assert.deepEqual(coords[2].y, 119, 'return bottom right with skewX Y');
|
||||
assert.deepEqual(coords[3].y, 119, 'return bottom left with skewX Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords absolute with skewY', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, skewY: 45 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords(true);
|
||||
assert.deepEqual(coords[0].x, 40, 'return top left absolute with skewY X');
|
||||
assert.deepEqual(coords[1].x, 52, 'return top right absolute with skewY X');
|
||||
assert.deepEqual(coords[2].x, 52, 'return bottom absolute right with skewY X');
|
||||
assert.deepEqual(coords[3].x, 40, 'return bottom absolute left with skewY X');
|
||||
assert.deepEqual(coords[0].y, 30, 'return top left absolute with skewY Y');
|
||||
assert.deepEqual(coords[1].y, 30, 'return top right absolute with skewY Y');
|
||||
assert.deepEqual(coords[2].y, 59, 'return bottom absolute right with skewY Y');
|
||||
assert.deepEqual(coords[3].y, 59, 'return bottom absolute left with skewY Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords with skewY', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, skewY: 45 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords();
|
||||
assert.deepEqual(coords[0].x, 115, 'return top left with skewY X');
|
||||
assert.deepEqual(coords[1].x, 139, 'return top right with skewY X');
|
||||
assert.deepEqual(coords[2].x, 139, 'return bottom right with skewY X');
|
||||
assert.deepEqual(coords[3].x, 115, 'return bottom left with skewY X');
|
||||
assert.deepEqual(coords[0].y, 85, 'return top left with skewY Y');
|
||||
assert.deepEqual(coords[1].y, 85, 'return top right with skewY Y');
|
||||
assert.deepEqual(coords[2].y, 143, 'return bottom right with skewY Y');
|
||||
assert.deepEqual(coords[3].y, 143, 'return bottom left with skewY Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords absolute with skewY skewX angle', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, skewY: 45, skewX: 30, angle: 90 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords(true);
|
||||
assert.deepEqual(coords[0].x, 40, 'return top left absolute with skewY skewX angle X');
|
||||
assert.deepEqual(coords[1].x, 40, 'return top right absolute with skewY skewX angle X');
|
||||
assert.deepEqual(coords[2].x, 11, 'return bottom absolute right with skewY skewX angle X');
|
||||
assert.deepEqual(coords[3].x, 11, 'return bottom absolute left with skewY skewX angle X');
|
||||
assert.deepEqual(coords[0].y, 30, 'return top left absolute with skewY skewX angle Y');
|
||||
assert.deepEqual(coords[1].y, 58.74315780649914, 'return top right absolute with skewY skewX angle Y');
|
||||
assert.deepEqual(coords[2].y, 58.74315780649914, 'return bottom absolute right with skewY skewX angle Y');
|
||||
assert.deepEqual(coords[3].y, 30, 'return bottom absolute left with skewY skewX angle Y');
|
||||
});
|
||||
|
||||
QUnit.test('getCoords with skewY skewX angle', function(assert) {
|
||||
var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 2, top: 30, left: 40, skewY: 45, skewX: 30, angle: 90 });
|
||||
cObj.canvas = {
|
||||
viewportTransform: [2, 0, 0, 2, 35, 25]
|
||||
};
|
||||
var coords = cObj.getCoords();
|
||||
assert.deepEqual(coords[0].x, 115, 'return top left with skewY skewX angle X');
|
||||
assert.deepEqual(coords[1].x, 115, 'return top right with skewY skewX angle X');
|
||||
assert.deepEqual(coords[2].x, 57, 'return bottom right with skewY skewX angle X');
|
||||
assert.deepEqual(coords[3].x, 57, 'return bottom left with skewY skewX angle X');
|
||||
assert.deepEqual(coords[0].y, 85, 'return top left with skewY skewX angle Y');
|
||||
assert.deepEqual(coords[1].y, 142.48631561299828, 'return top right with skewY skewX angle Y');
|
||||
assert.deepEqual(coords[2].y, 142.48631561299828, 'return bottom right with skewY skewX angle Y');
|
||||
assert.deepEqual(coords[3].y, 85, 'return bottom left with skewY skewX angle Y');
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@
|
|||
var ANGLE = ANGLE_DEG * Math.PI / 180;
|
||||
element.setAttribute('transform', 'rotate(' + ANGLE_DEG + ')');
|
||||
parsedValue = fabric.parseTransformAttribute(element.getAttribute('transform'));
|
||||
assert.deepEqual(parsedValue, [Math.cos(ANGLE), Math.sin(ANGLE), -Math.sin(ANGLE), Math.cos(ANGLE), 0, 0]);
|
||||
assert.deepEqual(parsedValue, [fabric.util.cos(ANGLE), fabric.util.sin(ANGLE), -fabric.util.sin(ANGLE), fabric.util.cos(ANGLE), 0, 0]);
|
||||
|
||||
element.setAttribute('transform', 'scale(3.5)');
|
||||
parsedValue = fabric.parseTransformAttribute(element.getAttribute('transform'));
|
||||
|
|
|
|||
|
|
@ -221,14 +221,12 @@
|
|||
}));
|
||||
|
||||
var ANGLE_DEG = 90;
|
||||
var ANGLE = ANGLE_DEG * Math.PI / 180;
|
||||
|
||||
elPath.setAttribute('transform', 'rotate(' + ANGLE_DEG + ')');
|
||||
fabric.Path.fromElement(elPath, function(path) {
|
||||
|
||||
assert.deepEqual(
|
||||
path.get('transformMatrix'),
|
||||
[Math.cos(ANGLE), Math.sin(ANGLE), -Math.sin(ANGLE), Math.cos(ANGLE), 0, 0]
|
||||
[0, 1, -1, 0, 0, 0]
|
||||
);
|
||||
done();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -910,7 +910,7 @@
|
|||
{ x: 0, y: -8.318331151877368 },
|
||||
{ x: 133.33333333333331, y: 19.99999999999999 },
|
||||
{ x: 100.00000000000003, y: 19.99999999999999 },
|
||||
{ x: 147.19721858646224, y: 100 }
|
||||
{ x: 147.19721858646224, y: 100 },
|
||||
];
|
||||
assert.deepEqual(bounds, expectedBounds, 'bounds are as expected');
|
||||
});
|
||||
|
|
@ -951,4 +951,12 @@
|
|||
var val = fabric.util.capValue(3, 80, 70);
|
||||
assert.equal(val, 70, 'max cap');
|
||||
});
|
||||
|
||||
QUnit.test('fabric.util.cos', function(assert) {
|
||||
assert.ok(typeof fabric.util.cos === 'function');
|
||||
assert.equal(fabric.util.cos(0), 1, 'cos 0 correct');
|
||||
assert.equal(fabric.util.cos(Math.PI / 2), 0, 'cos 90 correct');
|
||||
assert.equal(fabric.util.cos(Math.PI), -1, 'cos 180 correct');
|
||||
assert.equal(fabric.util.cos(3 * Math.PI / 2), 0,' cos 270 correct');
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
Loading…
Reference in a new issue