diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index 9b081508..d2d9c8d0 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -350,16 +350,22 @@ var Matrix = Base.extend(/** @lends Matrix# */{ * @return {Matrix} this affine transform */ concatenate: function(mx) { - var a = this._a, - b = this._b, - c = this._c, - d = this._d; - this._a = mx._a * a + mx._c * b; - this._b = mx._b * a + mx._d * b; - this._c = mx._a * c + mx._c * d; - this._d = mx._b * c + mx._d * d; - this._tx += mx._tx * a + mx._ty * b; - this._ty += mx._tx * c + mx._ty * d; + var a1 = this._a, + b1 = this._b, + c1 = this._c, + d1 = this._d, + a2 = mx._a, + b2 = mx._b, + c2 = mx._c, + d2 = mx._d, + tx2 = mx._tx, + ty2 = mx._ty; + this._a = a2 * a1 + c2 * b1; + this._b = b2 * a1 + d2 * b1; + this._c = a2 * c1 + c2 * d1; + this._d = b2 * c1 + d2 * d1; + this._tx += tx2 * a1 + ty2 * b1; + this._ty += tx2 * c1 + ty2 * d1; this._changed(); return this; }, @@ -371,22 +377,50 @@ var Matrix = Base.extend(/** @lends Matrix# */{ * @return {Matrix} this affine transform */ preConcatenate: function(mx) { - var a = this._a, - b = this._b, - c = this._c, - d = this._d, - tx = this._tx, - ty = this._ty; - this._a = mx._a * a + mx._b * c; - this._b = mx._a * b + mx._b * d; - this._c = mx._c * a + mx._d * c; - this._d = mx._c * b + mx._d * d; - this._tx = mx._a * tx + mx._b * ty + mx._tx; - this._ty = mx._c * tx + mx._d * ty + mx._ty; + var a1 = this._a, + b1 = this._b, + c1 = this._c, + d1 = this._d, + tx1 = this._tx, + ty1 = this._ty, + a2 = mx._a, + b2 = mx._b, + c2 = mx._c, + d2 = mx._d, + tx2 = mx._tx, + ty2 = mx._ty; + this._a = a2 * a1 + b2 * c1; + this._b = a2 * b1 + b2 * d1; + this._c = c2 * a1 + d2 * c1; + this._d = c2 * b1 + d2 * d1; + this._tx = a2 * tx1 + b2 * ty1 + tx2; + this._ty = c2 * tx1 + d2 * ty1 + ty2; this._changed(); return this; }, + chain: 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._b, + c2 = mx._c, + d2 = mx._d, + tx2 = mx._tx, + ty2 = mx._ty; + return new Matrix( + a2 * a1 + c2 * b1, + a2 * c1 + c2 * d1, + b2 * a1 + d2 * b1, + b2 * c1 + d2 * d1, + tx1 + tx2 * a1 + ty2 * b1, + ty1 + tx2 * c1 + ty2 * d1); + }, + /** * @return {Boolean} whether this transform is the identity transform */ diff --git a/src/item/Item.js b/src/item/Item.js index 272c258e..5a1cca92 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -978,7 +978,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ matrix = !matrix ? _matrix : _matrix - ? matrix.clone().concatenate(_matrix) + ? matrix.chain(_matrix) : matrix; // If we're caching bounds on this item, pass it on as cacheItem, so the // children can setup the _boundsCache structures for it. @@ -1692,7 +1692,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ // Keep the accumulated matrices up to this item in options, so we // can keep calculating the correct _tolerancePadding values. totalMatrix = options._totalMatrix = parentTotalMatrix - ? parentTotalMatrix.clone().concatenate(matrix) + ? parentTotalMatrix.chain(matrix) // If this is the first one in the recursion, factor in the // zoom of the view and the globalMatrix of the item. : this.getGlobalMatrix().preConcatenate(view._matrix), @@ -3600,7 +3600,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ parentMatrix = matrices[matrices.length - 1], viewMatrix = param.viewMatrix, matrix = this._matrix, - globalMatrix = parentMatrix.clone().concatenate(matrix); + globalMatrix = parentMatrix.chain(matrix); // If this item is not invertible, do not draw it, since it would cause // empty ctx.currentPath and mess up caching. It appears to also be a // good idea generally to not draw in such circumstances, e.g. SVG @@ -3613,7 +3613,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ // pre-concatenate the view's matrix. // Note that it's only provided if it isn't the identity matrix. function getViewMatrix(matrix) { - return viewMatrix ? viewMatrix.clone().concatenate(matrix) : matrix; + return viewMatrix ? viewMatrix.chain(matrix) : matrix; } // Only keep track of transformation if told so. See Project#draw() @@ -3669,7 +3669,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ ctx.save(); // Get the transformation matrix for non-scaling strokes. var strokeMatrix = parentStrokeMatrix - ? parentStrokeMatrix.clone().concatenate(matrix) + ? parentStrokeMatrix.chain(matrix) : !this.getStrokeScaling() && getViewMatrix(globalMatrix), // If we're drawing into a separate canvas and a clipItem is defined // for the current rendering loop, we need to draw the clip item @@ -3758,7 +3758,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ // layer level, with a fallback to #009dec var color = this.getSelectedColor(true) || this.getLayer().getSelectedColor(true), - mx = matrix.clone().concatenate(this.getGlobalMatrix(true)); + mx = matrix.chain(this.getGlobalMatrix(true)); ctx.strokeStyle = ctx.fillStyle = color ? color.toCanvasStyle(ctx) : '#009dec'; if (this._drawSelected) diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js index 8f2289cf..4ed795de 100644 --- a/src/path/CompoundPath.js +++ b/src/path/CompoundPath.js @@ -232,7 +232,8 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{ for (var i = 0, l = children.length; i < l; i++) { var child = children[i], mx = child._matrix; - paths.push(child.getPathData(_matrix ? _matrix.clone().concatenate(mx) : mx, _precision)); + paths.push(child.getPathData(_matrix && !mx.isIdentity() + ? _matrix.chain(mx) : mx, _precision)); } return paths.join(' '); } @@ -282,7 +283,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{ mx = child._matrix; if (!selectedItems[child._id]) child._drawSelected(ctx, mx.isIdentity() ? matrix - : matrix.clone().concatenate(mx)); + : matrix.chain(mx)); } } }, new function() { // Injection scope for PostScript-like drawing functions