From 715025725d38fdebba2f40f812b0a2f364cdb86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Fri, 10 Jun 2016 21:32:22 +0200 Subject: [PATCH] Improve handling of SymbolItem bounds with #applyMatrix = false. Closes #1070 --- src/basic/Matrix.js | 98 +++++++++++++++++++++------------------- src/item/SymbolItem.js | 4 +- test/tests/SymbolItem.js | 36 ++++++++++----- 3 files changed, 77 insertions(+), 61 deletions(-) diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index 18309521..0e2f3cf3 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -355,23 +355,57 @@ var Matrix = Base.extend(/** @lends Matrix# */{ * @return {Matrix} this matrix, modified */ append: function(mx) { - var a1 = this._a, - b1 = this._b, - c1 = this._c, - d1 = this._d, - a2 = mx._a, - b2 = mx._c, - c2 = mx._b, - d2 = mx._d, - tx2 = mx._tx, - ty2 = mx._ty; - this._a = a2 * a1 + c2 * c1; - this._c = b2 * a1 + d2 * c1; - this._b = a2 * b1 + c2 * d1; - this._d = b2 * b1 + d2 * d1; - this._tx += tx2 * a1 + ty2 * c1; - this._ty += tx2 * b1 + ty2 * d1; - this._changed(); + if (mx) { + var a1 = this._a, + b1 = this._b, + c1 = this._c, + d1 = this._d, + a2 = mx._a, + b2 = mx._c, + c2 = mx._b, + d2 = mx._d, + tx2 = mx._tx, + ty2 = mx._ty; + this._a = a2 * a1 + c2 * c1; + this._c = b2 * a1 + d2 * c1; + this._b = a2 * b1 + c2 * d1; + this._d = b2 * b1 + d2 * d1; + this._tx += tx2 * a1 + ty2 * c1; + this._ty += tx2 * b1 + ty2 * d1; + this._changed(); + } + return this; + }, + + /** + * Prepends the specified matrix to this matrix. This is the equivalent of + * multiplying `(specified matrix) * (this matrix)`. + * + * @param {Matrix} matrix the matrix to prepend + * @return {Matrix} this matrix, modified + */ + prepend: function(mx) { + if (mx) { + var a1 = this._a, + b1 = this._b, + c1 = this._c, + d1 = this._d, + tx1 = this._tx, + ty1 = this._ty, + a2 = mx._a, + b2 = mx._c, + c2 = mx._b, + d2 = mx._d, + tx2 = mx._tx, + ty2 = mx._ty; + this._a = a2 * a1 + b2 * b1; + this._c = a2 * c1 + b2 * d1; + this._b = c2 * a1 + d2 * b1; + this._d = c2 * c1 + d2 * d1; + this._tx = a2 * tx1 + b2 * ty1 + tx2; + this._ty = c2 * tx1 + d2 * ty1 + ty2; + this._changed(); + } return this; }, @@ -387,36 +421,6 @@ var Matrix = Base.extend(/** @lends Matrix# */{ return this.clone().append(mx); }, - /** - * Prepends the specified matrix to this matrix. This is the equivalent of - * multiplying `(specified matrix) * (this matrix)`. - * - * @param {Matrix} matrix the matrix to prepend - * @return {Matrix} this matrix, modified - */ - prepend: function(mx) { - var a1 = this._a, - b1 = this._b, - c1 = this._c, - d1 = this._d, - tx1 = this._tx, - ty1 = this._ty, - a2 = mx._a, - b2 = mx._c, - c2 = mx._b, - d2 = mx._d, - tx2 = mx._tx, - ty2 = mx._ty; - this._a = a2 * a1 + b2 * b1; - this._c = a2 * c1 + b2 * d1; - this._b = c2 * a1 + d2 * b1; - this._d = c2 * c1 + d2 * d1; - this._tx = a2 * tx1 + b2 * ty1 + tx2; - this._ty = c2 * tx1 + d2 * ty1 + ty2; - this._changed(); - return this; - }, - /** * Returns a new matrix as the result of prepending the specified matrix * to this matrix. This is the equivalent of multiplying diff --git a/src/item/SymbolItem.js b/src/item/SymbolItem.js index 4cd37bfe..2e992d74 100644 --- a/src/item/SymbolItem.js +++ b/src/item/SymbolItem.js @@ -112,12 +112,10 @@ var SymbolItem = Item.extend(/** @lends SymbolItem# */{ return this._definition._item.isEmpty(); }, - _getBounds: function(matrix, options) { var item = this._definition._item; // Redirect the call to the definition item to calculate the bounds. - return item._getCachedBounds(matrix && matrix.appended(item._matrix), - options); + return item._getCachedBounds(item._matrix.prepended(matrix), options); }, _hitTestSelf: function(point, options, viewMatrix, strokeMatrix) { diff --git a/test/tests/SymbolItem.js b/test/tests/SymbolItem.js index 845d3f3c..e7ff1316 100644 --- a/test/tests/SymbolItem.js +++ b/test/tests/SymbolItem.js @@ -92,7 +92,7 @@ test('Changing the definition of a symbol should change the bounds of all instan 'Bounds after modifying symbol definition'); }); -test('Symbol definition selection', function() { +test('SymbolDefinition item selection', function() { var path = new Path.Circle([50, 50], 50); path.selected = true; var definition = new SymbolDefinition(path); @@ -104,28 +104,42 @@ test('Symbol definition selection', function() { }, true); }); -test('Symbol#place()', function() { +test('SymbolDefinition#place()', function() { var path = new Path.Circle([50, 50], 50); - var definition = new SymbolDefinition(path); - var placedSymbol = definition.place(); + var symbol = new SymbolDefinition(path); + var placed = symbol.place(); equals(function() { - return placedSymbol.parent == paper.project.activeLayer; + return placed.parent == paper.project.activeLayer; }, true); equals(function() { - return placedSymbol.definition == definition; + return placed.definition == symbol; }, true); equals(function() { - return placedSymbol.position.toString(); + return placed.position.toString(); }, '{ x: 0, y: 0 }'); }); -test('Symbol#place(position)', function() { +test('SymbolDefinition#place(position)', function() { var path = new Path.Circle([50, 50], 50); - var definition = new SymbolDefinition(path); - var placedSymbol = definition.place(new Point(100, 100)); + var symbol = new SymbolDefinition(path); + var placed = symbol.place(new Point(100, 100)); equals(function() { - return placedSymbol.position.toString(); + return placed.position.toString(); }, '{ x: 100, y: 100 }'); }); + +test('SymbolItem#bounds with #applyMatrix = false', function() { + var path = new Path.Rectangle({ + point: [100, 100], + size: [50, 50], + strokeColor: 'red', + applyMatrix: false, + strokeWidth: 50 + }); + var symbol = new SymbolDefinition(path); + var placed = symbol.place([200, 200]); + equals(function() { return placed.bounds; }, + { x: 150, y: 150, width: 100, height: 100 }); +});