Improve handling of SymbolItem bounds with #applyMatrix = false.

Closes #1070
This commit is contained in:
Jürg Lehni 2016-06-10 21:32:22 +02:00
parent ed3e283802
commit 715025725d
3 changed files with 77 additions and 61 deletions

View file

@ -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

View file

@ -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) {

View file

@ -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 });
});