diff --git a/examples/Games/Paperoids.html b/examples/Games/Paperoids.html
new file mode 100644
index 00000000..e4f27722
--- /dev/null
+++ b/examples/Games/Paperoids.html
@@ -0,0 +1,571 @@
+
+
+
+
+
+ Paperoids
+
+
+
+
+
+
+
+
+ FPS
+
+
+
+
+
+
diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js
index 16bc87e7..4dbf59f5 100644
--- a/src/basic/Matrix.js
+++ b/src/basic/Matrix.js
@@ -422,7 +422,10 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
},
/**
- * @return {Number} The determinant of this transform
+ * The determinant of this transform.
+ *
+ * @type Number
+ * @bean
*/
getDeterminant: function() {
return this._a * this._d - this._b * this._c;
@@ -439,11 +442,12 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
},
/**
- * Returns the rotation angle of the matrix. If a non-uniform
- * rotation is applied as a result of a shear() or scale() command,
- * undefined is returned, as the resulting transformation cannot be
- * expressed in one rotation angle
- * @return {Number} The rotation angle of the matrix
+ * The rotation angle of the matrix. If a non-uniform rotation is applied as
+ * a result of a shear() or scale() command, undefined is returned, as the
+ * resulting transformation cannot be expressed in one rotation angle.
+ *
+ * @type Number
+ * @bean
*/
getRotation: function() {
var angle1 = -Math.atan2(this._b, this._d),
diff --git a/src/basic/Point.js b/src/basic/Point.js
index b8d0dc1a..5f36e26d 100644
--- a/src/basic/Point.js
+++ b/src/basic/Point.js
@@ -949,7 +949,12 @@ var LinkedPoint = Point.extend({
},
statics: {
- create: function(owner, setter, x, y) {
+ create: function(owner, setter, x, y, dontLink) {
+ // Support creation of normal Points rather than LinkedPoints
+ // through an optional parameter that can be passed to the getters.
+ // See e.g. Rectangle#getPoint(true).
+ if (dontLink)
+ return Point.create(x, y);
var point = new LinkedPoint(LinkedPoint.dont);
point._x = x;
point._y = y;
diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js
index a7b884ba..6f3275f7 100644
--- a/src/basic/Rectangle.js
+++ b/src/basic/Rectangle.js
@@ -145,7 +145,10 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
* @bean
*/
getPoint: function() {
- return LinkedPoint.create(this, 'setPoint', this.x, this.y);
+ // Pass on the optional argument dontLink which tells LinkedPoint to
+ // produce a normal point instead. Used internally for speed reasons.
+ return LinkedPoint.create(this, 'setPoint', this.x, this.y,
+ arguments[0]);
},
setPoint: function(point) {
@@ -162,7 +165,9 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
* @bean
*/
getSize: function() {
- return LinkedSize.create(this, 'setSize', this.width, this.height);
+ // See Rectangle#getPoint() about arguments[0]
+ return LinkedSize.create(this, 'setSize', this.width, this.height,
+ arguments[0]);
},
setSize: function(size) {
@@ -282,7 +287,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
*/
getCenter: function() {
return LinkedPoint.create(this, 'setCenter',
- this.getCenterX(), this.getCenterY());
+ this.getCenterX(), this.getCenterY(), arguments[0]);
},
setCenter: function(point) {
@@ -665,7 +670,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
set = 'set' + part;
this[get] = function() {
return LinkedPoint.create(this, set,
- this[getX](), this[getY]());
+ this[getX](), this[getY](), arguments[0]);
};
this[set] = function(point) {
point = Point.read(arguments);
diff --git a/src/basic/Size.js b/src/basic/Size.js
index bc231289..2ffdbad1 100644
--- a/src/basic/Size.js
+++ b/src/basic/Size.js
@@ -535,13 +535,16 @@ var LinkedSize = Size.extend({
},
statics: {
- create: function(owner, setter, width, height) {
- var point = new LinkedSize(LinkedSize.dont);
- point._width = width;
- point._height = height;
- point._owner = owner;
- point._setter = setter;
- return point;
+ create: function(owner, setter, width, height, dontLink) {
+ // See LinkedPoint.create() for an explanation about dontLink.
+ if (dontLink)
+ return Size.create(width, height);
+ var size = new LinkedSize(LinkedSize.dont);
+ size._width = width;
+ size._height = height;
+ size._owner = owner;
+ size._setter = setter;
+ return size;
}
}
});
diff --git a/src/color/Color.js b/src/color/Color.js
index 6e296653..dc39cb02 100644
--- a/src/color/Color.js
+++ b/src/color/Color.js
@@ -148,14 +148,15 @@ var Color = this.Color = Base.extend(new function() {
max = Math.max(r, g, b),
min = Math.min(r, g, b),
delta = max - min,
- h = delta == 0 ? 0
+ achromatic = delta == 0,
+ h = achromatic ? 0
: ( max == r ? (g - b) / delta + (g < b ? 6 : 0)
: max == g ? (b - r) / delta + 2
: (r - g) / delta + 4) * 60, // max == b
l = (max + min) / 2,
- s = l < 0.5
- ? delta / (max + min)
- : delta / (2 - max - min);
+ s = achromatic ? 0 : l < 0.5
+ ? delta / (max + min)
+ : delta / (2 - max - min);
return new HSLColor(h, s, l, color._alpha);
},
diff --git a/src/path/Path.Constructors.js b/src/path/Path.Constructors.js
index 47241fef..d861c47a 100644
--- a/src/path/Path.Constructors.js
+++ b/src/path/Path.Constructors.js
@@ -95,13 +95,17 @@ Path.inject({ statics: new function() {
*/
Rectangle: function(rect) {
rect = Rectangle.read(arguments);
- var path = new Path(),
- corners = ['getBottomLeft', 'getTopLeft', 'getTopRight',
- 'getBottomRight'],
- segments = new Array(4);
- for (var i = 0; i < 4; i++)
- segments[i] = new Segment(rect[corners[i]]());
- path._add(segments);
+ var left = rect.x,
+ top = rect.y
+ right = left + rect.width,
+ bottom = top + rect.height,
+ path = new Path();
+ path._add([
+ new Segment(Point.create(left, bottom)),
+ new Segment(Point.create(left, top)),
+ new Segment(Point.create(right, top)),
+ new Segment(Point.create(right, bottom))
+ ]);
path._closed = true;
return path;
},
@@ -128,13 +132,13 @@ Path.inject({ statics: new function() {
rect = Rectangle.read(arguments, 0, 4);
size = Size.read(arguments, 4, 2);
}
- size = Size.min(size, rect.getSize().divide(2));
+ size = Size.min(size, rect.getSize(true).divide(2));
var path = new Path(),
uSize = size.multiply(kappa * 2),
- bl = rect.getBottomLeft(),
- tl = rect.getTopLeft(),
- tr = rect.getTopRight(),
- br = rect.getBottomRight();
+ bl = rect.getBottomLeft(true),
+ tl = rect.getTopLeft(true),
+ tr = rect.getTopRight(true),
+ br = rect.getBottomRight(true);
path._add([
new Segment(bl.add(size.width, 0), null, [-uSize.width, 0]),
new Segment(bl.subtract(0, size.height), [0, uSize.height], null),
@@ -172,13 +176,13 @@ Path.inject({ statics: new function() {
Oval: function(rect) {
rect = Rectangle.read(arguments);
var path = new Path(),
- topLeft = rect.getTopLeft(),
- size = new Size(rect.width, rect.height),
+ point = rect.getPoint(true),
+ size = rect.getSize(true),
segments = new Array(4);
for (var i = 0; i < 4; i++) {
var segment = ovalSegments[i];
segments[i] = new Segment(
- segment._point.multiply(size).add(topLeft),
+ segment._point.multiply(size).add(point),
segment._handleIn.multiply(size),
segment._handleOut.multiply(size)
);
@@ -206,7 +210,7 @@ Path.inject({ statics: new function() {
center = Point.read(arguments, 0, 1);
}
return Path.Oval(new Rectangle(center.subtract(radius),
- new Size(radius * 2, radius * 2)));
+ Size.create(radius * 2, radius * 2)));
},
/**
diff --git a/src/path/Path.js b/src/path/Path.js
index adacd97c..3a184b2a 100644
--- a/src/path/Path.js
+++ b/src/path/Path.js
@@ -1286,10 +1286,10 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
// objects that were read from segments. This is because the SegmentPoint
// class overrides the plain x / y properties with getter / setters and
// stores the values in these private properties internally. To avoid
- // of getter functions all the time we directly access these private
+ // calling of getter functions all the time we directly access these private
// properties here. The distinction between normal Point objects and
- // SegmentPoint objects maybe seem a bit tedious but is worth the
- // performance benefit.
+ // SegmentPoint objects maybe seem a bit tedious but is worth the benefit in
+ // performance.
function drawHandles(ctx, segments) {
for (var i = 0, l = segments.length; i < l; i++) {
@@ -2028,7 +2028,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
return this._handleBounds;
var coords = new Array(6),
stroke = arguments[1] / 2 || 0, // Stroke padding
- join = arguments[2] / 2 || 0, // Join padding, for miterLimiet
+ join = arguments[2] / 2 || 0, // Join padding, for miterLimit
open = !this._closed,
x1 = Infinity,
x2 = -x1,
diff --git a/src/path/SegmentPoint.js b/src/path/SegmentPoint.js
index ec7a74f7..c0492796 100644
--- a/src/path/SegmentPoint.js
+++ b/src/path/SegmentPoint.js
@@ -47,6 +47,13 @@ var SegmentPoint = Point.extend({
this._owner._changed(this);
},
+ isZero: function() {
+ // Provide our own version of Point#isZero() that does not use the x / y
+ // accessors but the internal properties directly, for performance
+ // reasons, since it is used a lot internally.
+ return this._x == 0 && this._y == 0;
+ },
+
setSelected: function(selected) {
this._owner._setSelected(this, selected);
},
diff --git a/test/tests/Color.js b/test/tests/Color.js
index 04417b24..2619a60b 100644
--- a/test/tests/Color.js
+++ b/test/tests/Color.js
@@ -196,4 +196,10 @@ test('Color#convert', function() {
equals(function() {
return converted.equals(color);
}, true);
+});
+
+test('Saturation from black rgb', function() {
+ equals(function() {
+ return new RGBColor(0, 0, 0).saturation == 0;
+ }, true);
});
\ No newline at end of file