mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-19 14:10:14 -05:00
Various renaming and introduction of additional methods in Matrix
- Rename Matrix#concatenate() to #append() and #preConcatenate() to #prepend(). - Over #invert() as alternative to #inverted(), directly modifying the matrix. - Make Matrix#_shiftless() and internal function. - Introduce versions that return copies instead, named #appended(). (previously #chain()) and #prepended(). - Rename internal Path#_getPenPadding() to #_getStrokePadding().
This commit is contained in:
parent
2ed9fae105
commit
d292e08ed2
9 changed files with 122 additions and 89 deletions
|
@ -346,12 +346,13 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
|||
},
|
||||
|
||||
/**
|
||||
* Concatenates the given affine transform to this transform.
|
||||
* Appends the specified matrix to this matrix. This is the equivalent of
|
||||
* multiplying `(this matrix) * (specified matrix)`.
|
||||
*
|
||||
* @param {Matrix} mx the transform to concatenate
|
||||
* @return {Matrix} this affine transform
|
||||
* @param {Matrix} matrix the matrix to append
|
||||
* @return {Matrix} this matrix, modified
|
||||
*/
|
||||
concatenate: function(mx) {
|
||||
append: function(mx) {
|
||||
var a1 = this._a,
|
||||
b1 = this._b,
|
||||
c1 = this._c,
|
||||
|
@ -373,12 +374,25 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
|||
},
|
||||
|
||||
/**
|
||||
* Pre-concatenates the given affine transform to this transform.
|
||||
* Returns a new matrix as the result of appending the specified matrix to
|
||||
* this matrix. This is the equivalent of multiplying
|
||||
* `(this matrix) * (specified matrix)`.
|
||||
*
|
||||
* @param {Matrix} mx the transform to preconcatenate
|
||||
* @return {Matrix} this affine transform
|
||||
* @param {Matrix} matrix the matrix to append
|
||||
* @return {Matrix} the newly created matrix
|
||||
*/
|
||||
preConcatenate: function(mx) {
|
||||
appended: function(mx) {
|
||||
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,
|
||||
|
@ -402,32 +416,74 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
|||
},
|
||||
|
||||
/**
|
||||
* Returns a new instance of the result of the concatenation of the given
|
||||
* affine transform with this transform.
|
||||
* Returns a new matrix as the result of prepending the specified matrix
|
||||
* to this matrix. This is the equivalent of multiplying
|
||||
* `(specified matrix) s* (this matrix)`.
|
||||
*
|
||||
* @param {Matrix} mx the transform to concatenate
|
||||
* @return {Matrix} the newly created affine transform
|
||||
* @param {Matrix} matrix the matrix to prepend
|
||||
* @return {Matrix} the newly created matrix
|
||||
*/
|
||||
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);
|
||||
prepended: function(mx) {
|
||||
return this.clone().prepend(mx);
|
||||
},
|
||||
|
||||
/**
|
||||
* Inverts the matrix, causing it to perform the opposite transformation.
|
||||
* If the matrix is not invertible (in which case {@link #isSingular()}
|
||||
* returns true), `null` is returned.
|
||||
*
|
||||
* @return {Matrix} this matrix, or `null`, if the matrix is singular.
|
||||
*/
|
||||
invert: function() {
|
||||
var det = this._getDeterminant(),
|
||||
tx = this._tx,
|
||||
ty = this._ty,
|
||||
res = null;
|
||||
if (det) {
|
||||
this._tx = (this._b * ty - this._d * tx) / det;
|
||||
this._ty = (this._c * tx - this._a * ty) / det;
|
||||
this._d /= det;
|
||||
this._c /= -det;
|
||||
this._b /= -det;
|
||||
this._a /= det;
|
||||
res = this;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new matrix that is the inversion of this matrix, causing it to
|
||||
* perform the opposite transformation. If the matrix is not invertible (in
|
||||
* which case {@link #isSingular()} returns true), `null` is returned.
|
||||
*
|
||||
* @return {Matrix} this matrix, or `null`, if the matrix is singular.
|
||||
*/
|
||||
inverted: function() {
|
||||
return this.clone().invert();
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated, use use {@link #append(matrix)} instead.
|
||||
*/
|
||||
concatenate: '#append',
|
||||
/**
|
||||
* @deprecated, use use {@link #prepend(matrix)} instead.
|
||||
*/
|
||||
preConcatenate: '#prepend',
|
||||
/**
|
||||
* @deprecated, use use {@link #appended(matrix)} instead.
|
||||
*/
|
||||
chain: '#appended',
|
||||
|
||||
/**
|
||||
* A private helper function to create a clone of this matrix, without the
|
||||
* translation factored in.
|
||||
*
|
||||
* @return {Matrix} a clone of this matrix, with {@link #tx} and {@link #ty}
|
||||
* set to `0`.
|
||||
*/
|
||||
_shiftless: function() {
|
||||
return new Matrix(this._a, this._c, this._b, this._d, 0, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -725,29 +781,6 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
|||
return (this.decompose() || {}).rotation;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the inversion of the transformation of the matrix and returns it
|
||||
* as a new insteance. If the matrix is not invertible (in which case {@link
|
||||
* #isSingular()} returns true), `null` is returned.
|
||||
*
|
||||
* @return {Matrix} the inverted matrix, or `null`, if the matrix is
|
||||
* singular
|
||||
*/
|
||||
inverted: function() {
|
||||
var det = this._getDeterminant();
|
||||
return det && new Matrix(
|
||||
this._d / det,
|
||||
-this._c / det,
|
||||
-this._b / det,
|
||||
this._a / det,
|
||||
(this._b * this._ty - this._d * this._tx) / det,
|
||||
(this._c * this._tx - this._a * this._ty) / det);
|
||||
},
|
||||
|
||||
shiftless: function() {
|
||||
return new Matrix(this._a, this._c, this._b, this._d, 0, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies this matrix to the specified Canvas Context.
|
||||
*
|
||||
|
|
|
@ -838,7 +838,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
var child = children[i];
|
||||
if (child._visible && !child.isEmpty()) {
|
||||
var rect = child._getCachedBounds(getter,
|
||||
matrix && matrix.chain(child._matrix), cacheItem);
|
||||
matrix && matrix.appended(child._matrix), cacheItem);
|
||||
x1 = Math.min(rect.x, x1);
|
||||
y1 = Math.min(rect.y, y1);
|
||||
x2 = Math.max(rect.x + rect.width, x2);
|
||||
|
@ -1089,7 +1089,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
matrix = this._globalMatrix = this._matrix.clone();
|
||||
var parent = this._parent;
|
||||
if (parent)
|
||||
matrix.preConcatenate(parent.getGlobalMatrix(true));
|
||||
matrix.prepend(parent.getGlobalMatrix(true));
|
||||
matrix._updateVersion = updateVersion;
|
||||
}
|
||||
return _dontClone ? matrix : matrix.clone();
|
||||
|
@ -1706,20 +1706,19 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
// this item does not have children, since we'd have to travel up the
|
||||
// chain already to determine the rough bounds.
|
||||
var matrix = this._matrix,
|
||||
parentTotalMatrix = options._totalMatrix,
|
||||
view = this.getView(),
|
||||
parentViewMatrix = options._viewMatrix,
|
||||
// Keep the accumulated matrices up to this item in options, so we
|
||||
// can keep calculating the correct _tolerancePadding values.
|
||||
totalMatrix = options._totalMatrix = parentTotalMatrix
|
||||
? parentTotalMatrix.chain(matrix)
|
||||
viewMatrix = options._viewMatrix = parentViewMatrix
|
||||
? parentViewMatrix.appended(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),
|
||||
: this.getGlobalMatrix().prepend(this.getView()._matrix),
|
||||
// Calculate the transformed padding as 2D size that describes the
|
||||
// transformed tolerance circle / ellipse. Make sure it's never 0
|
||||
// since we're using it for division.
|
||||
tolerancePadding = options._tolerancePadding = new Size(
|
||||
Path._getPenPadding(1, totalMatrix.inverted())
|
||||
Path._getStrokePadding(1, viewMatrix.inverted())
|
||||
).multiply(
|
||||
Math.max(options.tolerance, /*#=*/Numerical.TOLERANCE)
|
||||
);
|
||||
|
@ -1778,8 +1777,8 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
// Transform the point back to the outer coordinate system.
|
||||
if (res && res.point)
|
||||
res.point = matrix.transform(res.point);
|
||||
// Restore totalMatrix for next child.
|
||||
options._totalMatrix = parentTotalMatrix;
|
||||
// Restore viewMatrix for next child.
|
||||
options._viewMatrix = parentViewMatrix;
|
||||
return res;
|
||||
},
|
||||
|
||||
|
@ -1983,7 +1982,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
matrix = rect && (matrix || new Matrix());
|
||||
for (var i = 0, l = children && children.length; i < l; i++) {
|
||||
var child = children[i],
|
||||
childMatrix = matrix && matrix.chain(child._matrix),
|
||||
childMatrix = matrix && matrix.appended(child._matrix),
|
||||
add = true;
|
||||
if (rect) {
|
||||
var bounds = child.getBounds(childMatrix);
|
||||
|
@ -3137,9 +3136,9 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
// Bail out if there is nothing to do.
|
||||
if (!matrix && !applyMatrix)
|
||||
return this;
|
||||
// Simply preconcatenate the internal matrix with the passed one:
|
||||
// Simply prepend the internal matrix with the passed one:
|
||||
if (matrix)
|
||||
_matrix.preConcatenate(matrix);
|
||||
_matrix.prepend(matrix);
|
||||
// Call #_transformContent() now, if we need to directly apply the
|
||||
// internal _matrix transformations to the item's content.
|
||||
// Application is not possible on Raster, PointText, PlacedSymbol, since
|
||||
|
@ -3884,7 +3883,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
var matrices = param.matrices,
|
||||
viewMatrix = param.viewMatrix,
|
||||
matrix = this._matrix,
|
||||
globalMatrix = matrices[matrices.length - 1].chain(matrix);
|
||||
globalMatrix = matrices[matrices.length - 1].appended(matrix);
|
||||
// If this item is not invertible, do not draw it. It appears to be a
|
||||
// good idea generally to not draw in such circumstances, e.g. SVG
|
||||
// handles it the same way.
|
||||
|
@ -3893,10 +3892,10 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
|
||||
// Since globalMatrix does not take the view's matrix into account (we
|
||||
// could have multiple views with different zooms), we may have to
|
||||
// pre-concatenate the view's matrix.
|
||||
// prepend the view's matrix.
|
||||
// Note that it's only provided if it isn't the identity matrix.
|
||||
function getViewMatrix(matrix) {
|
||||
return viewMatrix ? viewMatrix.chain(matrix) : matrix;
|
||||
return viewMatrix ? viewMatrix.appended(matrix) : matrix;
|
||||
}
|
||||
|
||||
// Only keep track of transformation if told so. See Project#draw()
|
||||
|
@ -3952,7 +3951,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
ctx.save();
|
||||
// Get the transformation matrix for non-scaling strokes.
|
||||
var strokeMatrix = parentStrokeMatrix
|
||||
? parentStrokeMatrix.chain(matrix)
|
||||
? parentStrokeMatrix.appended(matrix)
|
||||
// pass `true` for dontMerge
|
||||
: this._canScaleStroke && !this.getStrokeScaling(true)
|
||||
&& getViewMatrix(globalMatrix),
|
||||
|
@ -4042,7 +4041,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
var layer,
|
||||
color = this.getSelectedColor(true)
|
||||
|| (layer = this.getLayer()) && layer.getSelectedColor(true),
|
||||
mx = matrix.chain(this.getGlobalMatrix(true));
|
||||
mx = matrix.appended(this.getGlobalMatrix(true));
|
||||
ctx.strokeStyle = ctx.fillStyle = color
|
||||
? color.toCanvasStyle(ctx) : '#009dec';
|
||||
if (this._drawSelected)
|
||||
|
|
|
@ -112,7 +112,7 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
|
|||
var definition = this.symbol._definition;
|
||||
// Redirect the call to the symbol definition to calculate the bounds
|
||||
return definition._getCachedBounds(getter,
|
||||
matrix && matrix.chain(definition._matrix), cacheItem);
|
||||
matrix && matrix.appended(definition._matrix), cacheItem);
|
||||
},
|
||||
|
||||
_hitTestSelf: function(point, options) {
|
||||
|
|
|
@ -470,7 +470,7 @@ var Raster = Item.extend(/** @lends Raster# */{
|
|||
raster = new Raster(Item.NO_INSERT);
|
||||
raster.setImage(this.getSubCanvas(rect));
|
||||
raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
|
||||
raster._matrix.preConcatenate(this._matrix);
|
||||
raster._matrix.prepend(this._matrix);
|
||||
raster.insertAbove(this);
|
||||
return raster;
|
||||
},
|
||||
|
|
|
@ -268,7 +268,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
|
|||
var child = children[i],
|
||||
mx = child._matrix;
|
||||
paths.push(child.getPathData(_matrix && !mx.isIdentity()
|
||||
? _matrix.chain(mx) : _matrix, _precision));
|
||||
? _matrix.appended(mx) : _matrix, _precision));
|
||||
}
|
||||
return paths.join(' ');
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
|
|||
mx = child._matrix;
|
||||
if (!selectedItems[child._id])
|
||||
child._drawSelected(ctx, mx.isIdentity() ? matrix
|
||||
: matrix.chain(mx));
|
||||
: matrix.appended(mx));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1504,9 +1504,9 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
radius: radius,
|
||||
insert: false
|
||||
});
|
||||
// Pass `true` to exclude the matrix, so we can preconcatenate after
|
||||
// Pass `true` to exclude the matrix, so we can prepend after
|
||||
shape.copyAttributes(this, true);
|
||||
shape._matrix.preConcatenate(this._matrix);
|
||||
shape._matrix.prepend(this._matrix);
|
||||
// Determine and apply the shape's angle of rotation.
|
||||
shape.rotate(topCenter.subtract(center).getAngle() + 90);
|
||||
if (insert === undefined || insert)
|
||||
|
@ -2701,7 +2701,7 @@ new function() { // PostScript-style drawing commands
|
|||
this.join();
|
||||
}
|
||||
};
|
||||
}, { // A dedicated scope for the tricky bounds calculations
|
||||
}, { // A dedicated scope for the tricky bounds calculations
|
||||
// We define all the different getBounds functions as static methods on Path
|
||||
// and have #_getBounds directly access these. All static bounds functions
|
||||
// below have the same first four parameters: segments, closed, style,
|
||||
|
@ -2826,14 +2826,14 @@ statics: {
|
|||
* stroke adds to the bounding box, by calculating the dimensions of a
|
||||
* rotated ellipse.
|
||||
*/
|
||||
_getPenPadding: function(radius, matrix) {
|
||||
_getStrokePadding: function(radius, matrix) {
|
||||
if (!matrix)
|
||||
return [radius, radius];
|
||||
// If a matrix is provided, we need to rotate the stroke circle
|
||||
// and calculate the bounding box of the resulting rotated elipse:
|
||||
// Get rotated hor and ver vectors, and determine rotation angle
|
||||
// and elipse values from them:
|
||||
var mx = matrix.shiftless(),
|
||||
var mx = matrix._shiftless(),
|
||||
hor = mx.transform(new Point(radius, 0)),
|
||||
ver = mx.transform(new Point(0, radius)),
|
||||
phi = hor.getAngleInRadians(),
|
||||
|
@ -2965,8 +2965,9 @@ statics: {
|
|||
*/
|
||||
getRoughBounds: function(segments, closed, style, matrix) {
|
||||
// Delegate to handleBounds, but pass on radius values for stroke and
|
||||
// joins. Hanlde miter joins specially, by passing the largets radius
|
||||
// joins. Handle miter joins specially, by passing the largest radius
|
||||
// possible.
|
||||
// TODO: Take strokeScaling into account here too!
|
||||
var strokeRadius = style.hasStroke() ? style.getStrokeWidth() / 2 : 0,
|
||||
joinRadius = strokeRadius;
|
||||
if (strokeRadius > 0) {
|
||||
|
@ -2976,7 +2977,7 @@ statics: {
|
|||
joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
|
||||
}
|
||||
return Path.getHandleBounds(segments, closed, style, matrix,
|
||||
Path._getPenPadding(strokeRadius, matrix),
|
||||
Path._getPenPadding(joinRadius, matrix));
|
||||
Path._getStrokePadding(strokeRadius, matrix),
|
||||
Path._getStrokePadding(joinRadius, matrix));
|
||||
}
|
||||
}});
|
||||
|
|
|
@ -49,7 +49,7 @@ new function() {
|
|||
// in rotate(). To do so, SVG requries us to inverse transform the
|
||||
// translation point by the matrix itself, since they are provided
|
||||
// in local coordinates.
|
||||
matrix = matrix.shiftless();
|
||||
matrix = matrix._shiftless();
|
||||
var point = matrix._inverseTransform(trans);
|
||||
attrs[center ? 'cx' : 'x'] = point.x;
|
||||
attrs[center ? 'cy' : 'y'] = point.y;
|
||||
|
|
|
@ -338,7 +338,7 @@ new function() {
|
|||
v[j] = parseFloat(v[j]);
|
||||
switch (command) {
|
||||
case 'matrix':
|
||||
matrix.concatenate(
|
||||
matrix.append(
|
||||
new Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));
|
||||
break;
|
||||
case 'rotate':
|
||||
|
@ -461,7 +461,7 @@ new function() {
|
|||
// symbol.
|
||||
var scale = size ? rect.getSize().divide(size) : 1,
|
||||
matrix = new Matrix().translate(rect.getPoint()).scale(scale);
|
||||
item.transform(matrix.inverted());
|
||||
item.transform(matrix.invert());
|
||||
} else if (item instanceof Symbol) {
|
||||
// The symbol is wrapping a group. Note that viewBox was already
|
||||
// applied to the group, and above code was executed for it.
|
||||
|
|
|
@ -536,7 +536,7 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
* @param {Matrix} matrix the matrix by which the view shall be transformed
|
||||
*/
|
||||
transform: function(matrix) {
|
||||
this._matrix.concatenate(matrix);
|
||||
this._matrix.append(matrix);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue