mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Do not keep the view's matrix baked into _globalMatrix, since we might allow multiple views soon.
This commit is contained in:
parent
66b1087d33
commit
60f6eca6c4
4 changed files with 49 additions and 44 deletions
|
@ -1152,25 +1152,20 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
* @type Matrix
|
* @type Matrix
|
||||||
* @bean
|
* @bean
|
||||||
*/
|
*/
|
||||||
getGlobalMatrix: function(_internal) {
|
getGlobalMatrix: function(_dontClone) {
|
||||||
var matrix = this._globalMatrix,
|
var matrix = this._globalMatrix,
|
||||||
updateVersion = this._project._updateVersion,
|
updateVersion = this._project._updateVersion;
|
||||||
viewMatrix = this.getView()._matrix;
|
|
||||||
// Internally we actually do factor in the view's transformations as
|
|
||||||
// well, but these are removed again in the return statement below.
|
|
||||||
// This way it is easier to draw selections and handle non-direct
|
|
||||||
// blitting, see Item#draw().
|
|
||||||
// If #_globalMatrix is out of sync, recalculate it now.
|
// If #_globalMatrix is out of sync, recalculate it now.
|
||||||
if (matrix && matrix._updateVersion !== updateVersion)
|
if (matrix && matrix._updateVersion !== updateVersion)
|
||||||
matrix = null;
|
matrix = null;
|
||||||
if (!matrix) {
|
if (!matrix) {
|
||||||
matrix = this._globalMatrix = this._matrix.clone();
|
matrix = this._globalMatrix = this._matrix.clone();
|
||||||
matrix.preConcatenate(this._parent
|
var parent = this._parent;
|
||||||
? this._parent.getGlobalMatrix(true)
|
if (parent)
|
||||||
: viewMatrix);
|
matrix.preConcatenate(parent.getGlobalMatrix(true));
|
||||||
matrix._updateVersion = updateVersion;
|
matrix._updateVersion = updateVersion;
|
||||||
}
|
}
|
||||||
return _internal ? matrix : viewMatrix.inverted().concatenate(matrix);
|
return _dontClone ? matrix : matrix.clone();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1591,7 +1586,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
ctx.save();
|
ctx.save();
|
||||||
matrix.applyToContext(ctx);
|
matrix.applyToContext(ctx);
|
||||||
// See Project#draw() for an explanation of new Base()
|
// See Project#draw() for an explanation of new Base()
|
||||||
this.draw(ctx, new Base({ transforms: [matrix] }));
|
this.draw(ctx, new Base({ matrices: [matrix] }));
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
var raster = new Raster(Item.NO_INSERT);
|
var raster = new Raster(Item.NO_INSERT);
|
||||||
raster.setCanvas(canvas);
|
raster.setCanvas(canvas);
|
||||||
|
@ -1706,8 +1701,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
? parentTotalMatrix.clone().concatenate(matrix)
|
? parentTotalMatrix.clone().concatenate(matrix)
|
||||||
// If this is the first one in the recursion, factor in the
|
// If this is the first one in the recursion, factor in the
|
||||||
// zoom of the view and the globalMatrix of the item.
|
// zoom of the view and the globalMatrix of the item.
|
||||||
: this.getGlobalMatrix().clone().preConcatenate(
|
: this.getGlobalMatrix().preConcatenate(view._matrix),
|
||||||
view._matrix),
|
|
||||||
// Calculate the transformed padding as 2D size that describes the
|
// Calculate the transformed padding as 2D size that describes the
|
||||||
// transformed tolerance circle / ellipse. Make sure it's never 0
|
// transformed tolerance circle / ellipse. Make sure it's never 0
|
||||||
// since we're using it for division.
|
// since we're using it for division.
|
||||||
|
@ -2911,8 +2905,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
* @return {Point} the transformed point as a new instance
|
* @return {Point} the transformed point as a new instance
|
||||||
*/
|
*/
|
||||||
globalToLocal: function(/* point */) {
|
globalToLocal: function(/* point */) {
|
||||||
var matrix = this.getGlobalMatrix();
|
return this.getGlobalMatrix(true)._inverseTransform(
|
||||||
return matrix && matrix._inverseTransform(Point.read(arguments));
|
Point.read(arguments));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2923,8 +2917,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
* @return {Point} the transformed point as a new instance
|
* @return {Point} the transformed point as a new instance
|
||||||
*/
|
*/
|
||||||
localToGlobal: function(/* point */) {
|
localToGlobal: function(/* point */) {
|
||||||
var matrix = this.getGlobalMatrix();
|
return this.getGlobalMatrix(true)._transformPoint(
|
||||||
return matrix && matrix._transformPoint(Point.read(arguments));
|
Point.read(arguments));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3520,10 +3514,10 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
var updateVersion = this._updateVersion = this._project._updateVersion;
|
var updateVersion = this._updateVersion = this._project._updateVersion;
|
||||||
// Keep calculating the current global matrix, by keeping a history
|
// Keep calculating the current global matrix, by keeping a history
|
||||||
// and pushing / popping as we go along.
|
// and pushing / popping as we go along.
|
||||||
var trackTransforms = param.trackTransforms,
|
var matrices = param.matrices,
|
||||||
transforms = param.transforms,
|
parentMatrix = matrices[matrices.length - 1],
|
||||||
|
viewMatrix = param.viewMatrix,
|
||||||
matrix = this._matrix,
|
matrix = this._matrix,
|
||||||
parentMatrix = transforms[transforms.length - 1],
|
|
||||||
globalMatrix = parentMatrix.clone().concatenate(matrix);
|
globalMatrix = parentMatrix.clone().concatenate(matrix);
|
||||||
// If this item is not invertible, do not draw it, since it would cause
|
// 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
|
// empty ctx.currentPath and mess up caching. It appears to also be a
|
||||||
|
@ -3531,11 +3525,21 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// handles it the same way.
|
// handles it the same way.
|
||||||
if (!globalMatrix.isInvertible())
|
if (!globalMatrix.isInvertible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// Note that it's only provided if it isn't the identity matrix.
|
||||||
|
function getViewMatrix(matrix) {
|
||||||
|
return viewMatrix ? viewMatrix.clone().concatenate(matrix) : matrix;
|
||||||
|
}
|
||||||
|
|
||||||
// Only keep track of transformation if told so. See Project#draw()
|
// Only keep track of transformation if told so. See Project#draw()
|
||||||
if (trackTransforms) {
|
matrices.push(globalMatrix);
|
||||||
transforms.push(this._globalMatrix = globalMatrix);
|
if (param.updateMatrix) {
|
||||||
// We also keep the cached _globalMatrix versioned.
|
// Update the cached _globalMatrix and keep it versioned.
|
||||||
globalMatrix._updateVersion = updateVersion;
|
globalMatrix._updateVersion = updateVersion;
|
||||||
|
this._globalMatrix = globalMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the item has a blendMode or is defining an opacity, draw it on
|
// If the item has a blendMode or is defining an opacity, draw it on
|
||||||
|
@ -3561,7 +3565,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
if (!direct) {
|
if (!direct) {
|
||||||
// Apply the parent's global matrix to the calculation of correct
|
// Apply the parent's global matrix to the calculation of correct
|
||||||
// bounds.
|
// bounds.
|
||||||
var bounds = this.getStrokeBounds(parentMatrix);
|
var bounds = this.getStrokeBounds(getViewMatrix(parentMatrix));
|
||||||
if (!bounds.width || !bounds.height)
|
if (!bounds.width || !bounds.height)
|
||||||
return;
|
return;
|
||||||
// Store previous offset and save the main context, so we can
|
// Store previous offset and save the main context, so we can
|
||||||
|
@ -3590,15 +3594,14 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
ctx.translate(-itemOffset.x, -itemOffset.y);
|
ctx.translate(-itemOffset.x, -itemOffset.y);
|
||||||
}
|
}
|
||||||
// Apply globalMatrix when drawing into temporary canvas.
|
// Apply globalMatrix when drawing into temporary canvas.
|
||||||
(direct ? matrix : globalMatrix).applyToContext(ctx);
|
(direct ? matrix : getViewMatrix(globalMatrix)).applyToContext(ctx);
|
||||||
// If we're drawing into a separate canvas and a clipItem is defined for
|
// 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 again.
|
// the current rendering loop, we need to draw the clip item again.
|
||||||
if (!direct && param.clipItem)
|
if (!direct && param.clipItem)
|
||||||
param.clipItem.draw(ctx, param.extend({ clip: true }));
|
param.clipItem.draw(ctx, param.extend({ clip: true }));
|
||||||
this._draw(ctx, param);
|
this._draw(ctx, param);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
if (trackTransforms)
|
matrices.pop();
|
||||||
transforms.pop();
|
|
||||||
if (param.clip && !param.dontFinish)
|
if (param.clip && !param.dontFinish)
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
// If a temporary canvas was created, composite it onto the main canvas:
|
// If a temporary canvas was created, composite it onto the main canvas:
|
||||||
|
|
|
@ -489,7 +489,7 @@ var Raster = Item.extend(/** @lends Raster# */{
|
||||||
// If a path was passed, draw it as a clipping mask:
|
// If a path was passed, draw it as a clipping mask:
|
||||||
// See Project#draw() for an explanation of new Base()
|
// See Project#draw() for an explanation of new Base()
|
||||||
if (path)
|
if (path)
|
||||||
path.draw(ctx, new Base({ clip: true, transforms: [matrix] }));
|
path.draw(ctx, new Base({ clip: true, matrices: [matrix] }));
|
||||||
// Now draw the image clipped into it.
|
// Now draw the image clipped into it.
|
||||||
this._matrix.applyToContext(ctx);
|
this._matrix.applyToContext(ctx);
|
||||||
ctx.drawImage(this.getElement(),
|
ctx.drawImage(this.getElement(),
|
||||||
|
|
|
@ -150,6 +150,8 @@ PathItem.inject(new function() {
|
||||||
// See if the CompoundPath can be reduced to just a simple Path.
|
// See if the CompoundPath can be reduced to just a simple Path.
|
||||||
result = result.reduce();
|
result = result.reduce();
|
||||||
// Copy over the left-hand item's style and we're done.
|
// Copy over the left-hand item's style and we're done.
|
||||||
|
// TODO: Consider using Item#_clone() for this, but find a way to not
|
||||||
|
// clone children / name (content).
|
||||||
result.setStyle(path1._style);
|
result.setStyle(path1._style);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -426,12 +426,12 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
|
||||||
var param = new Base({
|
var param = new Base({
|
||||||
offset: new Point(0, 0),
|
offset: new Point(0, 0),
|
||||||
pixelRatio: pixelRatio,
|
pixelRatio: pixelRatio,
|
||||||
// Tell the drawing routine that we want to track nested matrices
|
viewMatrix: matrix.isIdentity() ? null : matrix,
|
||||||
// in param.transforms, and that we want it to set _globalMatrix
|
matrices: [new Matrix()], // Start with the identity matrix.
|
||||||
// as used below. Item#rasterize() and Raster#getAverageColor() do
|
// Tell the drawing routine that we want to keep _globalMatrix up to
|
||||||
// not need to set this.
|
// date. Item#rasterize() and Raster#getAverageColor() should not
|
||||||
trackTransforms: true,
|
// set this.
|
||||||
transforms: [matrix]
|
updateMatrix: true
|
||||||
});
|
});
|
||||||
for (var i = 0, l = this.layers.length; i < l; i++)
|
for (var i = 0, l = this.layers.length; i < l; i++)
|
||||||
this.layers[i].draw(ctx, param);
|
this.layers[i].draw(ctx, param);
|
||||||
|
@ -441,24 +441,24 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
|
||||||
if (this._selectedItemCount > 0) {
|
if (this._selectedItemCount > 0) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.strokeWidth = 1;
|
ctx.strokeWidth = 1;
|
||||||
for (var id in this._selectedItems) {
|
var size = this._scope.settings.handleSize,
|
||||||
var item = this._selectedItems[id],
|
|
||||||
globalMatrix = item._globalMatrix,
|
|
||||||
size = this._scope.settings.handleSize,
|
|
||||||
half = size / 2;
|
half = size / 2;
|
||||||
|
for (var id in this._selectedItems) {
|
||||||
|
var item = this._selectedItems[id];
|
||||||
if (item._updateVersion === this._updateVersion
|
if (item._updateVersion === this._updateVersion
|
||||||
&& (item._drawSelected || item._boundsSelected)
|
&& (item._drawSelected || item._boundsSelected)) {
|
||||||
&& globalMatrix) {
|
|
||||||
// Allow definition of selected color on a per item and per
|
// Allow definition of selected color on a per item and per
|
||||||
// layer level, with a fallback to #009dec
|
// layer level, with a fallback to #009dec
|
||||||
var color = item.getSelectedColor()
|
var color = item.getSelectedColor()
|
||||||
|| item.getLayer().getSelectedColor();
|
|| item.getLayer().getSelectedColor(),
|
||||||
|
mx = matrix.clone().concatenate(
|
||||||
|
item.getGlobalMatrix(true));
|
||||||
ctx.strokeStyle = ctx.fillStyle = color
|
ctx.strokeStyle = ctx.fillStyle = color
|
||||||
? color.toCanvasStyle(ctx) : '#009dec';
|
? color.toCanvasStyle(ctx) : '#009dec';
|
||||||
if (item._drawSelected)
|
if (item._drawSelected)
|
||||||
item._drawSelected(ctx, globalMatrix);
|
item._drawSelected(ctx, mx);
|
||||||
if (item._boundsSelected) {
|
if (item._boundsSelected) {
|
||||||
var coords = globalMatrix._transformCorners(
|
var coords = mx._transformCorners(
|
||||||
item.getInternalBounds());
|
item.getInternalBounds());
|
||||||
// Now draw a rectangle that connects the transformed
|
// Now draw a rectangle that connects the transformed
|
||||||
// bounds corners, and draw the corners.
|
// bounds corners, and draw the corners.
|
||||||
|
|
Loading…
Reference in a new issue