Merge remote-tracking branch 'origin/master'

Conflicts:
	src/basic/Matrix.js
	src/item/Raster.js
This commit is contained in:
Jürg Lehni 2011-02-28 23:27:03 +01:00
commit 3f972be500
13 changed files with 263 additions and 96 deletions

View file

@ -458,10 +458,18 @@ var Matrix = Base.extend({
// Canvas contexts seem to use another orientation: The scaleX (m00) and
// scaleY (m11) values need to be flipped to get correct behaviour e.g.
// when using rotation or shearing.
if (reset) {
context.setTransform(
-this._m00, this._m01, this._m10,
-this._m11, this._m02, this._m12
);
} else {
context.transform(
-this._m00, this._m01, this._m10,
-this._m11, this._m02, this._m12
);
}
>>>>>>> origin/master
},
statics: {

View file

@ -2,17 +2,25 @@ Doc = Base.extend({
beans: true,
initialize: function(canvas) {
if (canvas) {
if (canvas && canvas instanceof HTMLCanvasElement) {
this.canvas = canvas;
this.ctx = this.canvas.getContext('2d');
this.size = new Size(canvas.offsetWidth, canvas.offsetHeight);
} else {
this.size = Size.read(arguments) || new Size(1024, 768);
this.canvas = document.createElement('canvas');
this.canvas.width = this.size.width;
this.canvas.height = this.size.height;
}
this.bounds = new Rectangle(new Point(0, 0), this.size);
this.ctx = this.canvas.getContext('2d');
Paper.documents.push(this);
this.activate();
this.layers = [];
this.activeLayer = new Layer();
this.currentStyle = null;
this.symbols = [];
this.views = [new DocumentView(this)];
this.activeView = this.views[0];
},
getCurrentStyle: function() {
@ -29,13 +37,18 @@ Doc = Base.extend({
redraw: function() {
if (this.canvas) {
// Initial tests conclude that clearing the canvas is always
// faster than using clearRect:
// Initial tests conclude that clearing the canvas using clearRect
// is always faster than setting canvas.width = canvas.width
// http://jsperf.com/clearrect-vs-setting-width/7
var view = this.activeView;
var bounds = view.bounds;
this.ctx.clearRect(0, 0, this.size.width + 1, this.size.height + 1);
this.ctx.save();
view.matrix.applyToContext(this.ctx, true);
for (var i = 0, l = this.layers.length; i < l; i++) {
this.layers[i].draw(this.ctx, {});
}
this.ctx.restore();
}
}
});

View file

@ -0,0 +1,97 @@
DocumentView = Base.extend({
beans: true,
initialize: function(document) {
this.document = document;
this._bounds = this.document.bounds.clone();
this.matrix = new Matrix();
this._zoom = 1;
this._center = this._bounds.center;
},
// TODO: test this.
getCenter: function() {
return this._center;
},
setCenter: function() {
var center = Point.read(arguments);
if (center) {
var delta = center.subtract(this._center);
this.scrollBy(delta);
this._center = center;
}
},
getZoom: function() {
return this._zoom;
},
setZoom: function(zoom) {
// TODO: clamp the view between 1/32 and 64?
var mx = new Matrix();
mx.scale(zoom / this._zoom, this.center);
this.transform(mx);
this._zoom = zoom;
},
scrollBy: function() {
var point = Point.read(arguments).negate();
var mx = new Matrix().translate(point);
this.transform(mx);
},
getBounds: function() {
return this._bounds;
},
// TODO:
// setBounds: function(rect) {
//
// },
// TODO: getInvalidBounds
// TODO: invalidate(rect)
// TODO: style: artwork / preview / raster / opaque / ink
// TODO: getShowGrid
// TODO: getMousePoint
// TODO: artworkToView(rect)
artworkToView: function(point) {
return this.matrix.transform(point);
},
viewToArtwork: function(point) {
// TODO: cache the inverse matrix:
return this.matrix.createInverse().transform(point);
},
// TODO: inherit this code somehow?
transform: function(matrix, flags) {
var width = this.document.bounds.width;
var height = this.document.bounds.height;
var x = width * -0.5;
var y = height * -0.5;
var coords = [
x, y,
x + width, y,
x + width, y + height,
x, y + height];
this.matrix.preConcatenate(matrix);
this.matrix.createInverse().transform(coords, 0, coords, 0, 4);
var xMin = coords[0], xMax = coords[0];
var yMin = coords[1], yMax = coords[1];
for (var i = 2; i < 8; i += 2) {
var x = coords[i];
var y = coords[i + 1];
xMin = Math.min(x, xMin);
xMax = Math.max(x, xMax);
yMin = Math.min(y, yMin);
yMax = Math.max(y, yMax);
};
var bounds = this._bounds;
bounds.x = xMin;
bounds.y = yMin;
bounds.width = xMax - xMin;
bounds.height = yMax - yMin;
}
});

View file

@ -30,14 +30,17 @@ BlendMode = {
process: function(documentContext, item, param) {
// TODO: use strokeBounds
var itemBounds = item.bounds;
if (!itemBounds)
return;
var top = Math.floor(itemBounds.top);
var left = Math.floor(itemBounds.left);
var size = itemBounds.size.ceil();
var size = itemBounds.size.ceil().add(1, 1);
var width = size.width;
var height = size.height;
var itemCanvas = CanvasProvider.getCanvas(size);
var itemContext = itemCanvas.getContext('2d');
itemContext.save();
if (item.matrix) {
var matrix = item.matrix.clone();
var transMatrix = Matrix.getTranslateInstance(-left, -top);
@ -210,6 +213,7 @@ BlendMode = {
}
}
documentContext.putImageData(dstD, left, top);
itemContext.restore();
CanvasProvider.returnCanvas(itemCanvas);
}
};

View file

@ -27,6 +27,8 @@ Group = Item.extend({
// TODO: use strokeBounds for this, when implemented:
tempCanvas = CanvasProvider.getCanvas(this.document.size);
ctx = tempCanvas.getContext('2d');
ctx.save();
this.document.activeView.matrix.applyToContext(ctx);
}
for (var i = 0, l = this.children.length; i < l; i++) {
this.children[i].draw(ctx, param);
@ -34,11 +36,18 @@ Group = Item.extend({
ctx.clip();
}
if (tempCanvas) {
// restore the activeView.matrix transformation,
// so we can draw the image without transformation.
originalCtx.restore();
originalCtx.save();
originalCtx.globalAlpha = this.opacity;
originalCtx.drawImage(tempCanvas, 0, 0);
originalCtx.restore();
// Return the canvas, so it can be reused
// apply the view transformation again.
this.document.activeView.matrix.applyToContext(ctx);
// Restore the state of the temp canvas:
ctx.restore();
// Return the temp canvas, so it can be reused
CanvasProvider.returnCanvas(tempCanvas);
}
}

View file

@ -547,7 +547,7 @@ Item = Base.extend({
var context = canvas.getContext('2d');
var matrix = new Matrix().scale(scale).translate(-bounds.x, -bounds.y);
matrix.applyToContext(context);
this.draw(context);
this.draw(context, {});
var raster = new Raster(canvas);
raster.position = this.bounds.center;
raster.scale(1 / scale);

View file

@ -63,6 +63,16 @@ PlacedSymbol = Item.extend({
if (this.blendMode != 'normal' && !param.ignoreBlendMode) {
BlendMode.process(ctx, this, param);
} else {
var tempCanvas, originalCtx;
if (this.opacity < 1) {
originalCtx = ctx;
// TODO: use strokeBounds for this, when implemented:
tempCanvas = CanvasProvider.getCanvas(this.document.size);
ctx = tempCanvas.getContext('2d');
ctx.save();
this.document.activeView.matrix.applyToContext(ctx);
}
// TODO: we need to preserve strokewidth, but still transform the fill
ctx.save();
if (param.ignoreBlendMode !== true)
@ -70,6 +80,22 @@ PlacedSymbol = Item.extend({
param.ignoreBlendMode = false;
this.symbol.definition.draw(ctx, param);
ctx.restore();
if (tempCanvas) {
// restore the activeView.matrix transformation,
// so we can draw the image without transformation.
originalCtx.restore();
originalCtx.save();
originalCtx.globalAlpha = this.opacity;
originalCtx.drawImage(tempCanvas, 0, 0);
originalCtx.restore();
// apply the view transformation again.
this.document.activeView.matrix.applyToContext(ctx, true);
// Restore the state of the temp canvas:
ctx.restore();
// Return the temp canvas, so it can be reused
CanvasProvider.returnCanvas(tempCanvas);
}
}
}
// TODO:

View file

@ -1,4 +1,11 @@
Tool = ToolHandler.extend({
Tool = ToolHandler.extend(new function() {
function viewToArtwork(event, document) {
var point = Point.create(event.offset.x, event.offset.y);
// TODO: always the active view?
return document.activeView.viewToArtwork(point);
};
return {
beans: true,
initialize: function(handlers, doc) {
@ -15,7 +22,7 @@ Tool = ToolHandler.extend({
var dragging = false;
var events = {
dragstart: function(e) {
curPoint = new Point(e.offset);
curPoint = viewToArtwork(e, that._document);
that.onHandleEvent('MOUSE_DOWN', curPoint, null, null);
if (that.onMouseDown)
that._document.redraw();
@ -24,7 +31,7 @@ Tool = ToolHandler.extend({
dragging = true;
},
drag: function(e) {
if (e) curPoint = new Point(e.offset);
if (e) curPoint = viewToArtwork(e, that._document);
if (curPoint) {
that.onHandleEvent('MOUSE_DRAG', curPoint, null, null);
if (that.onMouseDrag)
@ -35,14 +42,16 @@ Tool = ToolHandler.extend({
curPoint = null;
if (this.eventInterval != -1)
clearInterval(this.intervalId);
that.onHandleEvent('MOUSE_UP', new Point(e.offset), null, null);
that.onHandleEvent('MOUSE_UP',
viewToArtwork(e, that._document), null, null);
if (that.onMouseUp)
that._document.redraw();
dragging = false;
},
mousemove: function(e) {
if (!dragging) {
that.onHandleEvent('MOUSE_MOVE', new Point(e.offset), null, null);
that.onHandleEvent('MOUSE_MOVE',
viewToArtwork(e, that._document), null, null);
if (that.onMouseMove)
that._document.redraw();
}
@ -71,4 +80,5 @@ Tool = ToolHandler.extend({
getDocument: function() {
return this._document;
}
};
});