Merge remote-tracking branch 'origin/master'

This commit is contained in:
Jürg Lehni 2011-04-28 13:11:58 +01:00
commit 7dce6f3a6c
5 changed files with 92 additions and 55 deletions

View file

@ -193,33 +193,6 @@ var Rectangle = this.Rectangle = Base.extend({
&& rect.y < this.y + this.height;
},
intersect: function(rect) {
rect = Rectangle.read(arguments);
var x1 = Math.max(this.x, rect.x),
y1 = Math.max(this.y, rect.y),
x2 = Math.min(this.x + this.width, rect.x + rect.width),
y2 = Math.min(this.y + this.height, rect.y + rect.height);
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
},
unite: function(rect) {
rect = Rectangle.read(arguments);
var x1 = Math.min(this.x, rect.x),
y1 = Math.min(this.y, rect.y),
x2 = Math.max(this.x + this.width, rect.x + rect.width),
y2 = Math.max(this.y + this.height, rect.y + rect.height);
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
},
include: function(point) {
point = Point.read(arguments);
var x1 = Math.min(this.x, point.x),
y1 = Math.min(this.y, point.y),
x2 = Math.max(this.x + this.width, point.x),
y2 = Math.max(this.y + this.height, point.y);
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
},
toString: function() {
return '{ x: ' + this.x
+ ', y: ' + this.y
@ -234,6 +207,27 @@ var Rectangle = this.Rectangle = Base.extend({
return new Rectangle(Rectangle.dont).set(x, y, width, height);
}
}
}, new function() { // Scope for injecting intersect, unite and include.
return Base.each({
intersect: [true, false],
unite: [false, false],
include: [false, true]
}, function(values, name) {
var intersect = values[0],
isPoint = values[1],
math1 = Math[intersect ? 'max' : 'min'],
math2 = Math[intersect ? 'min' : 'max'];
this[name] = function() {
var object = (isPoint ? Point : Rectangle).read(arguments),
x1 = math1(this.x, object.x),
y1 = math1(this.y, object.y),
x2 = math2(this.x + this.width,
object.x + (isPoint ? 0 : object.width)),
y2 = math2(this.y + this.height,
object.y + (isPoint ? 0 : object.height));
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
};
}, {});
}, new function() {
return Base.each([
['Top', 'Left'], ['Top', 'Right'],

View file

@ -80,6 +80,26 @@ var Document = this.Document = Base.extend({
}
},
/**
* Selects all items in the document.
*/
selectAll: function() {
// TODO: is using for var i in good practice?
// or should we use Base.each? (JP)
for (var i = 0, l = this.layers.length; i < l; i++)
this.layers[i].setSelected(true);
},
/**
* Deselects all selected items in the document.
*/
deselectAll: function() {
// TODO: is using for var i in good practice?
// or should we use Base.each? (JP)
for (var i in this._selectedItems)
this._selectedItems[i].setSelected(false);
},
draw: function() {
if (this.canvas) {
var ctx = this.context;

View file

@ -221,28 +221,28 @@ var Item = this.Item = Base.extend({
* The first item contained within this item.
*/
getFirstChild: function() {
return this.children ? this.children[0] : null;
return this.children && this.children[0] || null;
},
/**
* The last item contained within this item.
*/
getLastChild: function() {
return this.children ? this.children[this.children.length - 1] : null;
return this.children && this.children[this.children.length - 1] || null;
},
/**
* The next item on the same level as this item.
*/
getNextSibling: function() {
return this.parent ? this.parent.children[this.getIndex() + 1] : null;
return this.parent && this.parent.children[this.getIndex() + 1] || null;
},
/**
* The previous item on the same level as this item.
*/
getPreviousSibling: function() {
return this.parent ? this.parent.children[this.getIndex() - 1] : null;
return this.parent && this.parent.children[this.getIndex() - 1] || null;
},
/**
@ -252,8 +252,7 @@ var Item = this.Item = Base.extend({
// TODO: Relying on indexOf() here is slow, especially since it is
// used for getPrevious/NextSibling().
// We need linked lists instead.
// TODO: Return null instead of -1?
return this.parent ? this.parent.children.indexOf(this) : -1;
return this.parent && this.parent.children.indexOf(this) || null;
},
/**
@ -272,7 +271,7 @@ var Item = this.Item = Base.extend({
* Removes the item.
*/
remove: function() {
if(this.isSelected())
if (this.isSelected())
this.setSelected(false);
return this.removeFromParent();
},
@ -428,23 +427,35 @@ var Item = this.Item = Base.extend({
}
return false;
},
getStrokeBounds: function() {
return this._getBounds(true);
},
getBounds: function() {
if (this.children && this.children.length) {
var rect = this.children[0].getBounds(),
x1 = rect.x,
y1 = rect.y,
x2 = rect.x + rect.width,
y2 = rect.y + rect.height;
for (var i = 1, l = this.children.length; i < l; i++) {
rect = this.children[i].getBounds();
return this._getBounds(false);
},
_getBounds: function(includeStroke) {
var children = this.children;
if (children && children.length) {
var x1, x2;
var y1 = x1 = Infinity;
var y2 = x2 = -Infinity;
for (var i = 0, l = children.length; i < l; i++) {
var child = children[i],
rect = includeStroke
? child.getStrokeBounds()
: child.getBounds();
x1 = Math.min(rect.x, x1);
y1 = Math.min(rect.y, y1);
x2 = Math.max(rect.x + rect.width, x1 + x2 - x1);
y2 = Math.max(rect.y + rect.height, y1 + y2 - y1);
x2 = Math.max(rect.x + rect.width, x2);
y2 = Math.max(rect.y + rect.height, y2);
}
return LinkedRectangle.create(this, 'setBounds',
x1, y1, x2 - x1, y2 - y1);
return includeStroke
? Rectangle.create(x1, y1, x2 - x1, y2 - y1)
: LinkedRectangle.create(this, 'setBounds',
x1, y1, x2 - x1, y2 - y1);
}
// TODO: What to return if nothing is defined, e.g. empty Groups?
// Scriptographer behaves weirdly then too.
@ -494,11 +505,11 @@ var Item = this.Item = Base.extend({
// weird results on Scriptographer. Also we can't use antialiasing, since
// Canvas doesn't support it yet. Document colorMode is also out of the
// question for now.
var bounds = this.getStrokeBounds();
var scale = resolution ? resolution / 72 : 1;
var canvas = CanvasProvider.getCanvas(bounds.getSize().multiply(scale));
var ctx = canvas.getContext('2d');
var matrix = new Matrix().scale(scale).translate(-bounds.x, -bounds.y);
var bounds = this.getStrokeBounds(),
scale = (resolution || 72) / 72,
canvas = CanvasProvider.getCanvas(bounds.getSize().multiply(scale)),
ctx = canvas.getContext('2d'),
matrix = new Matrix().scale(scale).translate(-bounds.x, -bounds.y);
matrix.applyToContext(ctx);
this.draw(ctx, {});
var raster = new Raster(canvas);
@ -720,8 +731,8 @@ var Item = this.Item = Base.extend({
// Floor the offset and ceil the size, so we don't cut off any
// antialiased pixels when drawing onto the temporary canvas.
var itemOffset = bounds.getTopLeft().floor();
var size = bounds.getSize().ceil().add(1, 1);
var itemOffset = bounds.getTopLeft().floor(),
size = bounds.getSize().ceil().add(1, 1);
tempCanvas = CanvasProvider.getCanvas(size);
// Save the parent context, so we can draw onto it later
@ -894,7 +905,7 @@ var Item = this.Item = Base.extend({
for(var id in set) {
var item = set[id];
item.remove();
for(var type in sets) {
for (var type in sets) {
var other = sets[type];
if (other != set && other[item.getId()])
delete other[item.getId()];

View file

@ -198,6 +198,10 @@ var Raster = this.Raster = Item.extend({
}
return this._bounds;
},
getStrokeBounds: function() {
return this.getBounds();
},
draw: function(ctx, param) {
if (param.selection) {

View file

@ -16,12 +16,20 @@ test('new Group([item])', function() {
test('Group bounds', function() {
var doc = new Document();
doc.currentStyle = {
strokeWidth: 5,
strokeColor: 'black'
};
var path = new Path.Circle([150, 150], 60);
var secondPath = new Path.Circle([175, 175], 85);
var group = new Group([path, secondPath]);
compareRectangles(group.bounds, { x: 90, y: 90, width: 170, height: 170 });
compareRectangles(group.strokeBounds, { x: 87.5, y: 87.5, width: 175, height: 175 });
group.rotate(20);
compareRectangles(group.bounds, { x: 89.97681, y: 82.94095, width: 170.04639, height: 177.08224 });
compareRectangles(group.strokeBounds, { x: 87.47681, y: 80.44095, width: 175.04639, height: 182.08224 });
group.rotate(20, new Point(50, 50));
compareRectangles(group.bounds, { x: 39.70692, y: 114.99196, width: 170.00412, height: 180.22401 });
compareRectangles(group.strokeBounds, { x: 37.20692, y: 112.49196, width: 175.00412, height: 185.22401 });
});