mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-05-23 11:06:44 -04:00
Implement proper index independent argument list reading of basic types.
Implemented for Point, Size, Rectangle and Color.
This commit is contained in:
parent
6f2ff18fa1
commit
30374ae3b4
13 changed files with 260 additions and 190 deletions
|
@ -34,8 +34,8 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
|
|||
// intersection outside the line segment are allowed.
|
||||
// With two parameters, the 2nd parameter is a direction, and infinite
|
||||
// is automatially true, since we're describing an infinite line.
|
||||
point1 = Point.read(arguments, 0, 1);
|
||||
point2 = Point.read(arguments, 1, 1);
|
||||
point1 = Point.read(arguments);
|
||||
point2 = Point.read(arguments);
|
||||
if (arguments.length == 3) {
|
||||
this.point = point1;
|
||||
this.vector = point2.subtract(point1);
|
||||
|
|
|
@ -128,24 +128,20 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
|
|||
* @param {Point} [center] The center for the scaling transformation
|
||||
* @return {Matrix} This affine transform
|
||||
*/
|
||||
scale: function(/* scale | */ hor, ver, center) {
|
||||
if (arguments.length < 2 || typeof ver === 'object') {
|
||||
// hor is the single scale parameter, representing both hor and ver
|
||||
// Read center first from argument 1, then set ver = hor (thus
|
||||
// modifing the content of argument 1!)
|
||||
center = Point.read(arguments, 1);
|
||||
ver = hor;
|
||||
} else {
|
||||
center = Point.read(arguments, 2);
|
||||
}
|
||||
if (center)
|
||||
this.translate(center);
|
||||
this._a *= hor;
|
||||
this._c *= hor;
|
||||
this._b *= ver;
|
||||
this._d *= ver;
|
||||
if (center)
|
||||
this.translate(center.negate());
|
||||
scale: function(scale, center) {
|
||||
// Do not modify scale, center, since that would arguments of which
|
||||
// we're reading from!
|
||||
var _scale = Point.read(arguments),
|
||||
_center = Point.read(arguments);
|
||||
// TODO: Isn't center always set this way??
|
||||
if (_center)
|
||||
this.translate(_center);
|
||||
this._a *= _scale.x;
|
||||
this._c *= _scale.x;
|
||||
this._b *= _scale.y;
|
||||
this._d *= _scale.y;
|
||||
if (_center)
|
||||
this.translate(_center.negate());
|
||||
return this;
|
||||
},
|
||||
|
||||
|
@ -168,7 +164,8 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
|
|||
*/
|
||||
translate: function(point) {
|
||||
point = Point.read(arguments);
|
||||
var x = point.x, y = point.y;
|
||||
var x = point.x,
|
||||
y = point.y;
|
||||
this._tx += x * this._a + y * this._b;
|
||||
this._ty += x * this._c + y * this._d;
|
||||
return this;
|
||||
|
@ -219,24 +216,21 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
|
|||
* @param {Point} [center] The center for the shear transformation
|
||||
* @return {Matrix} This affine transform
|
||||
*/
|
||||
shear: function(/* point | */ hor, ver, center) {
|
||||
// See #scale() for explanation of this:
|
||||
if (arguments.length < 2 || typeof ver === 'object') {
|
||||
center = Point.read(arguments, 1);
|
||||
ver = hor;
|
||||
} else {
|
||||
center = Point.read(arguments, 2);
|
||||
}
|
||||
if (center)
|
||||
this.translate(center);
|
||||
shear: function(point, center) {
|
||||
// Do not modify point, center, since that would arguments of which
|
||||
// we're reading from!
|
||||
var _point = Point.read(arguments),
|
||||
_center = Point.read(arguments);
|
||||
if (_center)
|
||||
this.translate(_center);
|
||||
var a = this._a,
|
||||
c = this._c;
|
||||
this._a += ver * this._b;
|
||||
this._c += ver * this._d;
|
||||
this._b += hor * a;
|
||||
this._d += hor * c;
|
||||
if (center)
|
||||
this.translate(center.negate());
|
||||
this._a += _point.y * this._b;
|
||||
this._c += _point.y * this._d;
|
||||
this._b += _point.x * a;
|
||||
this._d += _point.x * c;
|
||||
if (_center)
|
||||
this.translate(_center.negate());
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
* console.log(point.y); // 5
|
||||
*/
|
||||
var Point = this.Point = Base.extend(/** @lends Point# */{
|
||||
// Tell Base.read that the Point constructor supporst reading with index
|
||||
_readIndex: true,
|
||||
|
||||
/**
|
||||
* Creates a Point object with the given x and y coordinates.
|
||||
*
|
||||
|
@ -132,25 +135,36 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
|
|||
initialize: function(arg0, arg1) {
|
||||
var type = typeof arg0;
|
||||
if (type === 'number') {
|
||||
var hasY = typeof arg1 === 'number';
|
||||
this.x = arg0;
|
||||
this.y = typeof arg1 === 'number' ? arg1 : arg0;
|
||||
this.y = hasY ? arg1 : arg0;
|
||||
if (this._read)
|
||||
this._read = hasY ? 2 : 1;
|
||||
} else if (type === 'undefined' || arg0 === null) {
|
||||
this.x = this.y = 0;
|
||||
} else if (typeof arg0.x !== 'undefined') {
|
||||
this.x = arg0.x;
|
||||
this.y = arg0.y;
|
||||
} else if (Array.isArray(arg0)) {
|
||||
this.x = arg0[0];
|
||||
this.y = arg0.length > 1 ? arg0[1] : arg0[0];
|
||||
} else if (typeof arg0.width !== 'undefined') {
|
||||
this.x = arg0.width;
|
||||
this.y = arg0.height;
|
||||
} else if (typeof arg0.angle !== 'undefined') {
|
||||
this.x = arg0.length;
|
||||
this.y = 0;
|
||||
this.setAngle(arg0.angle);
|
||||
if (this._read)
|
||||
this._read = arg0 === null ? 1 : 0;
|
||||
} else {
|
||||
this.x = this.y = 0;
|
||||
if (typeof arg0.x !== 'undefined') {
|
||||
this.x = arg0.x;
|
||||
this.y = arg0.y;
|
||||
} else if (Array.isArray(arg0)) {
|
||||
this.x = arg0[0];
|
||||
this.y = arg0.length > 1 ? arg0[1] : arg0[0];
|
||||
} else if (typeof arg0.width !== 'undefined') {
|
||||
this.x = arg0.width;
|
||||
this.y = arg0.height;
|
||||
} else if (typeof arg0.angle !== 'undefined') {
|
||||
this.x = arg0.length;
|
||||
this.y = 0;
|
||||
this.setAngle(arg0.angle);
|
||||
} else {
|
||||
this.x = this.y = 0;
|
||||
if (this._read)
|
||||
this._read = 0;
|
||||
}
|
||||
if (this._read)
|
||||
this._read = 1;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -787,11 +801,11 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
|
|||
* console.log(minPoint); // {x: 10, y: 5}
|
||||
*/
|
||||
min: function(point1, point2) {
|
||||
point1 = Point.read(arguments, 0, 1);
|
||||
point2 = Point.read(arguments, 1, 1);
|
||||
var _point1 = Point.read(arguments);
|
||||
_point2 = Point.read(arguments);
|
||||
return Point.create(
|
||||
Math.min(point1.x, point2.x),
|
||||
Math.min(point1.y, point2.y)
|
||||
Math.min(_point1.x, _point2.x),
|
||||
Math.min(_point1.y, _point2.y)
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -811,11 +825,11 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
|
|||
* console.log(maxPoint); // {x: 200, y: 100}
|
||||
*/
|
||||
max: function(point1, point2) {
|
||||
point1 = Point.read(arguments, 0, 1);
|
||||
point2 = Point.read(arguments, 1, 1);
|
||||
var _point1 = Point.read(arguments);
|
||||
_point2 = Point.read(arguments);
|
||||
return Point.create(
|
||||
Math.max(point1.x, point2.x),
|
||||
Math.max(point1.y, point2.y)
|
||||
Math.max(_point1.x, _point2.x),
|
||||
Math.max(_point1.y, _point2.y)
|
||||
);
|
||||
},
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
* rectangular path, it is not an item.
|
||||
*/
|
||||
var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
|
||||
// Tell Base.read that the Rectangle constructor supporst reading with index
|
||||
_readIndex: true,
|
||||
|
||||
/**
|
||||
* Creates a Rectangle object.
|
||||
*
|
||||
|
@ -54,21 +57,34 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
|
|||
* @param {Rectangle} rt
|
||||
*/
|
||||
initialize: function(arg0, arg1, arg2, arg3) {
|
||||
if (arguments.length == 4) {
|
||||
var type = typeof arg0;
|
||||
if (type === 'number') {
|
||||
// new Rectangle(x, y, width, height)
|
||||
this.x = arg0;
|
||||
this.y = arg1;
|
||||
this.width = arg2;
|
||||
this.height = arg3;
|
||||
} else if (arguments.length == 2) {
|
||||
if (arg1 && arg1.x !== undefined) {
|
||||
if (this._read)
|
||||
this._read = 4;
|
||||
} else if (type === 'undefined' || arg0 === null) {
|
||||
// new Rectangle(), new Rectangle(null)
|
||||
this.x = this.y = this.width = this.height = 0;
|
||||
if (this._read)
|
||||
this._read = arg0 === null ? 1 : 0;
|
||||
} else if (arguments.length > 1 && typeof arg0.width === 'undefined') {
|
||||
// We're checking arg0.width to rule out Rectangles, which are
|
||||
// handled separately below.
|
||||
// Read a point argument and look at the next value to see wether
|
||||
// it's a size or a point, then read accordingly
|
||||
var point = Point.read(arguments),
|
||||
next = Base.peekValue(arguments);
|
||||
this.x = point.x;
|
||||
this.y = point.y;
|
||||
if (next && next.x !== undefined) {
|
||||
// new Rectangle(point1, point2)
|
||||
var point1 = Point.read(arguments, 0, 1);
|
||||
var point2 = Point.read(arguments, 1, 1);
|
||||
this.x = point1.x;
|
||||
this.y = point1.y;
|
||||
this.width = point2.x - point1.x;
|
||||
this.height = point2.y - point1.y;
|
||||
var point2 = Point.read(arguments);
|
||||
this.width = point2.x - point.x;
|
||||
this.height = point2.y - point.y;
|
||||
if (this.width < 0) {
|
||||
this.x = point2.x;
|
||||
this.width = -this.width;
|
||||
|
@ -79,22 +95,22 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
|
|||
}
|
||||
} else {
|
||||
// new Rectangle(point, size)
|
||||
var point = Point.read(arguments, 0, 1);
|
||||
var size = Size.read(arguments, 1, 1);
|
||||
this.x = point.x;
|
||||
this.y = point.y;
|
||||
var size = Size.read(arguments);
|
||||
this.width = size.width;
|
||||
this.height = size.height;
|
||||
}
|
||||
if (this._read)
|
||||
this._read = arguments._index;
|
||||
} else if (arg0) {
|
||||
// Use 0 as defaults, in case we're reading from a Point or Size
|
||||
// new Rectangle(rect)
|
||||
// Use 0 as defaults, in case we're not reading from a Rectangle,
|
||||
// but a Point or Size instead
|
||||
this.x = arg0.x || 0;
|
||||
this.y = arg0.y || 0;
|
||||
this.width = arg0.width || 0;
|
||||
this.height = arg0.height || 0;
|
||||
} else {
|
||||
// new Rectangle()
|
||||
this.x = this.y = this.width = this.height = 0;
|
||||
if (this._read)
|
||||
this._read = 1;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
* console.log(size.height); // 5
|
||||
*/
|
||||
var Size = this.Size = Base.extend(/** @lends Size# */{
|
||||
// Tell Base.read that the Point constructor supporst reading with index
|
||||
_readIndex: true,
|
||||
|
||||
// DOCS: improve Size class description
|
||||
/**
|
||||
* Creates a Size object with the given width and height values.
|
||||
|
@ -91,28 +94,34 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
|
|||
* console.log(size.height); // 50
|
||||
*/
|
||||
initialize: function(arg0, arg1) {
|
||||
if (arg1 !== undefined) {
|
||||
var type = typeof arg0;
|
||||
if (type === 'number') {
|
||||
var hasHeight = typeof arg1 === 'number';
|
||||
this.width = arg0;
|
||||
this.height = arg1;
|
||||
} else if (arg0 !== undefined) {
|
||||
if (arg0 == null) {
|
||||
this.width = this.height = 0;
|
||||
} else if (arg0.width !== undefined) {
|
||||
this.height = hasHeight ? arg1 : arg0;
|
||||
if (this._read)
|
||||
this._read = hasHeight ? 2 : 1;
|
||||
} else if (type === 'undefined' || arg0 === null) {
|
||||
this.width = this.height = 0;
|
||||
if (this._read)
|
||||
this._read = arg0 === null ? 1 : 0;
|
||||
} else {
|
||||
if (typeof arg0.width !== 'undefined') {
|
||||
this.width = arg0.width;
|
||||
this.height = arg0.height;
|
||||
} else if (arg0.x !== undefined) {
|
||||
this.width = arg0.x;
|
||||
this.height = arg0.y;
|
||||
} else if (Array.isArray(arg0)) {
|
||||
this.width = arg0[0];
|
||||
this.height = arg0.length > 1 ? arg0[1] : arg0[0];
|
||||
} else if (typeof arg0 === 'number') {
|
||||
this.width = this.height = arg0;
|
||||
} else if (typeof arg0.x !== 'undefined') {
|
||||
this.width = arg0.x;
|
||||
this.height = arg0.y;
|
||||
} else {
|
||||
this.width = this.height = 0;
|
||||
if (this._read)
|
||||
this._read = 0;
|
||||
}
|
||||
} else {
|
||||
this.width = this.height = 0;
|
||||
if (this._read)
|
||||
this._read = 1;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -207,16 +207,20 @@ var Color = this.Color = Base.extend(new function() {
|
|||
};
|
||||
|
||||
var fields = /** @lends Color# */{
|
||||
// Tell Base.read that we do not want null to be converted to a color.
|
||||
_readNull: true,
|
||||
// Tell Base.read that the Point constructor supporst reading with index
|
||||
_readIndex: true,
|
||||
|
||||
initialize: function(arg) {
|
||||
var isArray = Array.isArray(arg),
|
||||
type = this._colorType;
|
||||
type = this._colorType,
|
||||
res;
|
||||
if (typeof arg === 'object' && !isArray) {
|
||||
if (!type) {
|
||||
// Called on the abstract Color class. Guess color type
|
||||
// from arg
|
||||
return arg.red !== undefined
|
||||
res = arg.red !== undefined
|
||||
? new RgbColor(arg.red, arg.green, arg.blue, arg.alpha)
|
||||
: arg.gray !== undefined
|
||||
? new GrayColor(arg.gray, arg.alpha)
|
||||
|
@ -227,33 +231,41 @@ var Color = this.Color = Base.extend(new function() {
|
|||
? new HsbColor(arg.hue, arg.saturation, arg.brightness,
|
||||
arg.alpha)
|
||||
: new RgbColor(); // Fallback
|
||||
if (this._read)
|
||||
res._read = 1;
|
||||
} else {
|
||||
// Called on a subclass instance. Return the converted
|
||||
// color.
|
||||
return Color.read(arguments).convert(type);
|
||||
res = Color.read(arguments).convert(type);
|
||||
if (this._read)
|
||||
res._read = arguments._read;
|
||||
}
|
||||
} else if (typeof arg === 'string') {
|
||||
var rgbColor = arg.match(/^#[0-9a-f]{3,6}$/i)
|
||||
? hexToRgbColor(arg)
|
||||
: nameToRgbColor(arg);
|
||||
return type
|
||||
res = type
|
||||
? rgbColor.convert(type)
|
||||
: rgbColor;
|
||||
if (this._read)
|
||||
res._read = 1;
|
||||
} else {
|
||||
var components = isArray ? arg
|
||||
: Array.prototype.slice.call(arguments);
|
||||
if (!type) {
|
||||
// Called on the abstract Color class. Guess color type
|
||||
// from arg
|
||||
//if (components.length >= 4)
|
||||
// return new CmykColor(components);
|
||||
if (components.length >= 3)
|
||||
return new RgbColor(components);
|
||||
return new GrayColor(components);
|
||||
// var ctor = components.length >= 4
|
||||
// ? CmykColor
|
||||
// : components.length >= 3
|
||||
var ctor = components.length >= 3
|
||||
? RgbColor
|
||||
: GrayColor;
|
||||
res = new ctor(components);
|
||||
} else {
|
||||
// Called on a subclass instance. Just copy over
|
||||
// components.
|
||||
Base.each(this._components,
|
||||
res = Base.each(this._components,
|
||||
function(name, i) {
|
||||
var value = components[i];
|
||||
// Set internal propery directly
|
||||
|
@ -262,7 +274,10 @@ var Color = this.Color = Base.extend(new function() {
|
|||
},
|
||||
this);
|
||||
}
|
||||
if (this._read)
|
||||
res._read = res._components.length;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,18 +63,45 @@ this.Base = Base.inject(/** @lends Base# */{
|
|||
* cloned if they are already provided in the required type
|
||||
*/
|
||||
read: function(list, start, length, clone) {
|
||||
var start = start || 0,
|
||||
length = length || list.length - start;
|
||||
var obj = list[start];
|
||||
var proto = this.prototype,
|
||||
readIndex = proto._readIndex,
|
||||
index = start || readIndex && list._index || 0;
|
||||
if (!length)
|
||||
length = list.length - index;
|
||||
var obj = list[index];
|
||||
if (obj instanceof this
|
||||
// If the class defines _readNull, return null when nothing
|
||||
// was provided
|
||||
|| this.prototype._readNull && obj == null && length <= 1)
|
||||
|| proto._readNull && obj == null && length <= 1) {
|
||||
if (readIndex)
|
||||
list._index = index + 1;
|
||||
return obj && clone ? obj.clone() : obj;
|
||||
}
|
||||
obj = new this(this.dont);
|
||||
return obj.initialize.apply(obj, start > 0 || length < list.length
|
||||
? Array.prototype.slice.call(list, start, start + length)
|
||||
if (readIndex)
|
||||
obj._read = true;
|
||||
obj = obj.initialize.apply(obj, index > 0 || length < list.length
|
||||
? Array.prototype.slice.call(list, index, index + length)
|
||||
: list) || obj;
|
||||
if (readIndex) {
|
||||
list._index = index + obj._read;
|
||||
// Have arguments._read point to the amount of args read in the
|
||||
// last read() call
|
||||
list._read = obj._read;
|
||||
delete obj._read;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
peekValue: function(list, start) {
|
||||
return list[list._index = start || list._index || 0];
|
||||
},
|
||||
|
||||
readValue: function(list, start) {
|
||||
var value = this.peekValue(list, start);
|
||||
list._index++;
|
||||
list._read = 1;
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -107,10 +107,9 @@ HitResult = Base.extend(/** @lends HitResult# */{
|
|||
* @private
|
||||
*/
|
||||
getOptions: function(point, options) {
|
||||
// Use _merged property to not repeatetly call merge in recursion.
|
||||
return options && options._merged ? options : Base.merge({
|
||||
// Use the converted options object to perform point conversion
|
||||
// only once.
|
||||
point: Point.read(arguments, 0, 1),
|
||||
point: Point.read([point]),
|
||||
// Type of item, for instanceof check: PathItem, TexItem, etc
|
||||
type: null,
|
||||
// Tolerance
|
||||
|
|
|
@ -115,7 +115,7 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
|
|||
this._matrix = pointOrMatrix !== undefined
|
||||
? pointOrMatrix instanceof Matrix
|
||||
? pointOrMatrix.clone()
|
||||
: new Matrix().translate(Point.read(arguments, 0))
|
||||
: new Matrix().translate(Point.read(arguments))
|
||||
: new Matrix();
|
||||
},
|
||||
|
||||
|
|
|
@ -338,17 +338,16 @@ var Raster = this.Raster = PlacedItem.extend(/** @lends Raster# */{
|
|||
* @param color the color that the pixel will be set to
|
||||
*/
|
||||
setPixel: function(point, color) {
|
||||
var hasPoint = arguments.length == 2;
|
||||
point = Point.read(arguments, 0, hasPoint ? 1 : 2);
|
||||
color = Color.read(arguments, hasPoint ? 1 : 2);
|
||||
var _point = Point.read(arguments),
|
||||
_color = Color.read(arguments);
|
||||
var ctx = this.getContext(true),
|
||||
imageData = ctx.createImageData(1, 1),
|
||||
alpha = color.getAlpha();
|
||||
imageData.data[0] = color.getRed() * 255;
|
||||
imageData.data[1] = color.getGreen() * 255;
|
||||
imageData.data[2] = color.getBlue() * 255;
|
||||
imageData.data[0] = _color.getRed() * 255;
|
||||
imageData.data[1] = _color.getGreen() * 255;
|
||||
imageData.data[2] = _color.getBlue() * 255;
|
||||
imageData.data[3] = alpha != null ? alpha * 255 : 255;
|
||||
ctx.putImageData(imageData, point.x, point.y);
|
||||
ctx.putImageData(imageData, _point.x, _point.y);
|
||||
},
|
||||
|
||||
// DOCS: document Raster#createData
|
||||
|
|
|
@ -41,10 +41,9 @@ Path.inject({ statics: new function() {
|
|||
* path.strokeColor = 'black';
|
||||
*/
|
||||
Line: function() {
|
||||
var step = Math.floor(arguments.length / 2);
|
||||
return new Path(
|
||||
Segment.read(arguments, 0, step),
|
||||
Segment.read(arguments, step, step)
|
||||
Point.read(arguments),
|
||||
Point.read(arguments)
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -125,32 +124,27 @@ Path.inject({ statics: new function() {
|
|||
* var path = new Path.RoundRectangle(rectangle, cornerSize);
|
||||
*/
|
||||
RoundRectangle: function(rect, size) {
|
||||
if (arguments.length == 2) {
|
||||
rect = Rectangle.read(arguments, 0, 1);
|
||||
size = Size.read(arguments, 1, 1);
|
||||
} else if (arguments.length == 6) {
|
||||
rect = Rectangle.read(arguments, 0, 4);
|
||||
size = Size.read(arguments, 4, 2);
|
||||
}
|
||||
size = Size.min(size, rect.getSize(true).divide(2));
|
||||
var path = new Path(),
|
||||
uSize = size.multiply(kappa * 2),
|
||||
bl = rect.getBottomLeft(true),
|
||||
tl = rect.getTopLeft(true),
|
||||
tr = rect.getTopRight(true),
|
||||
br = rect.getBottomRight(true);
|
||||
var _rect = Rectangle.read(arguments),
|
||||
_size = Size.min(Size.read(arguments),
|
||||
_rect.getSize(true).divide(2)),
|
||||
path = new Path(),
|
||||
uSize = _size.multiply(kappa * 2),
|
||||
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),
|
||||
new Segment(bl.add(_size.width, 0), null, [-uSize.width, 0]),
|
||||
new Segment(bl.subtract(0, _size.height), [0, uSize.height], null),
|
||||
|
||||
new Segment(tl.add(0, size.height), null, [0, -uSize.height]),
|
||||
new Segment(tl.add(size.width, 0), [-uSize.width, 0], null),
|
||||
new Segment(tl.add(0, _size.height), null, [0, -uSize.height]),
|
||||
new Segment(tl.add(_size.width, 0), [-uSize.width, 0], null),
|
||||
|
||||
new Segment(tr.subtract(size.width, 0), null, [uSize.width, 0]),
|
||||
new Segment(tr.add(0, size.height), [0, -uSize.height], null),
|
||||
new Segment(tr.subtract(_size.width, 0), null, [uSize.width, 0]),
|
||||
new Segment(tr.add(0, _size.height), [0, -uSize.height], null),
|
||||
|
||||
new Segment(br.subtract(0, size.height), null, [0, uSize.height]),
|
||||
new Segment(br.subtract(size.width, 0), [uSize.width, 0], null)
|
||||
new Segment(br.subtract(0, _size.height), null, [0, uSize.height]),
|
||||
new Segment(br.subtract(_size.width, 0), [uSize.width, 0], null)
|
||||
]);
|
||||
path._closed = true;
|
||||
return path;
|
||||
|
@ -204,14 +198,10 @@ Path.inject({ statics: new function() {
|
|||
* var path = new Path.Circle(new Point(100, 100), 50);
|
||||
*/
|
||||
Circle: function(center, radius) {
|
||||
if (arguments.length == 3) {
|
||||
center = Point.read(arguments, 0, 2);
|
||||
radius = arguments[2];
|
||||
} else {
|
||||
center = Point.read(arguments, 0, 1);
|
||||
}
|
||||
return Path.Oval(new Rectangle(center.subtract(radius),
|
||||
Size.create(radius * 2, radius * 2)));
|
||||
var _center = Point.read(arguments),
|
||||
_radius = Base.readValue(arguments);
|
||||
return Path.Oval(new Rectangle(_center.subtract(_radius),
|
||||
Size.create(_radius * 2, _radius * 2)));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -261,15 +251,17 @@ Path.inject({ statics: new function() {
|
|||
* decahedron.fillColor = 'black';
|
||||
*/
|
||||
RegularPolygon: function(center, numSides, radius) {
|
||||
center = Point.read(arguments, 0, 1);
|
||||
var path = new Path(),
|
||||
step = 360 / numSides,
|
||||
three = !(numSides % 3),
|
||||
vector = new Point(0, three ? -radius : radius),
|
||||
var _center = Point.read(arguments),
|
||||
_numSides = Base.readValue(arguments),
|
||||
_radius = Base.readValue(arguments),
|
||||
path = new Path(),
|
||||
step = 360 / _numSides,
|
||||
three = !(_numSides % 3),
|
||||
vector = new Point(0, three ? -_radius : _radius),
|
||||
offset = three ? -1 : 0.5,
|
||||
segments = new Array(numSides);
|
||||
for (var i = 0; i < numSides; i++) {
|
||||
segments[i] = new Segment(center.add(
|
||||
segments = new Array(_numSides);
|
||||
for (var i = 0; i < _numSides; i++) {
|
||||
segments[i] = new Segment(_center.add(
|
||||
vector.rotate((i + offset) * step)));
|
||||
}
|
||||
path._add(segments);
|
||||
|
@ -299,15 +291,17 @@ Path.inject({ statics: new function() {
|
|||
* path.fillColor = 'black';
|
||||
*/
|
||||
Star: function(center, numPoints, radius1, radius2) {
|
||||
center = Point.read(arguments, 0, 1);
|
||||
numPoints *= 2;
|
||||
var path = new Path(),
|
||||
step = 360 / numPoints,
|
||||
var _center = Point.read(arguments),
|
||||
_numPoints = Base.readValue(arguments) * 2,
|
||||
_radius1 = Base.readValue(arguments),
|
||||
_radius2 = Base.readValue(arguments),
|
||||
path = new Path(),
|
||||
step = 360 / _numPoints,
|
||||
vector = new Point(0, -1),
|
||||
segments = new Array(numPoints);
|
||||
for (var i = 0; i < numPoints; i++) {
|
||||
segments[i] = new Segment(center.add(
|
||||
vector.rotate(step * i).multiply(i % 2 ? radius2 : radius1)));
|
||||
segments = new Array(_numPoints);
|
||||
for (var i = 0; i < _numPoints; i++) {
|
||||
segments[i] = new Segment(_center.add(
|
||||
vector.rotate(step * i).multiply(i % 2 ? _radius2 : _radius1)));
|
||||
}
|
||||
path._add(segments);
|
||||
path._closed = true;
|
||||
|
|
|
@ -1667,20 +1667,20 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
},
|
||||
|
||||
cubicCurveTo: function(handle1, handle2, to) {
|
||||
handle1 = Point.read(arguments, 0, 1);
|
||||
handle2 = Point.read(arguments, 1, 1);
|
||||
to = Point.read(arguments, 2, 1);
|
||||
var _handle1 = Point.read(arguments);
|
||||
_handle2 = Point.read(arguments);
|
||||
_to = Point.read(arguments);
|
||||
// First modify the current segment:
|
||||
var current = getCurrentSegment(this);
|
||||
// Convert to relative values:
|
||||
current.setHandleOut(handle1.subtract(current._point));
|
||||
current.setHandleOut(_handle1.subtract(current._point));
|
||||
// And add the new segment, with handleIn set to c2
|
||||
this._add([ new Segment(to, handle2.subtract(to)) ]);
|
||||
this._add([ new Segment(_to, _handle2.subtract(to)) ]);
|
||||
},
|
||||
|
||||
quadraticCurveTo: function(handle, to) {
|
||||
handle = Point.read(arguments, 0, 1);
|
||||
to = Point.read(arguments, 1, 1);
|
||||
var _handle = Point.read(arguments),
|
||||
to = Point.read(arguments);
|
||||
// This is exact:
|
||||
// If we have the three quad points: A E D,
|
||||
// and the cubic is A B C D,
|
||||
|
@ -1688,26 +1688,26 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
// C = E + 1/3 (D - E)
|
||||
var current = getCurrentSegment(this)._point;
|
||||
this.cubicCurveTo(
|
||||
handle.add(current.subtract(handle).multiply(1/3)),
|
||||
handle.add(to.subtract(handle).multiply(1/3)),
|
||||
to
|
||||
_handle.add(current.subtract(_handle).multiply(1 / 3)),
|
||||
_handle.add(to.subtract(_handle).multiply(1 / 3)),
|
||||
_to
|
||||
);
|
||||
},
|
||||
|
||||
curveTo: function(through, to, parameter) {
|
||||
through = Point.read(arguments, 0, 1);
|
||||
to = Point.read(arguments, 1, 1);
|
||||
var t = Base.pick(parameter, 0.5),
|
||||
var _through = Point.read(arguments),
|
||||
_to = Point.read(arguments),
|
||||
t = Base.pick(Base.readValue(arguments), 0.5),
|
||||
t1 = 1 - t,
|
||||
current = getCurrentSegment(this)._point,
|
||||
// handle = (through - (1 - t)^2 * current - t^2 * to) /
|
||||
// (2 * (1 - t) * t)
|
||||
handle = through.subtract(current.multiply(t1 * t1))
|
||||
.subtract(to.multiply(t * t)).divide(2 * t * t1);
|
||||
handle = _through.subtract(current.multiply(t1 * t1))
|
||||
.subtract(_to.multiply(t * t)).divide(2 * t * t1);
|
||||
if (handle.isNaN())
|
||||
throw new Error(
|
||||
'Cannot put a curve through points with parameter = ' + t);
|
||||
this.quadraticCurveTo(handle, to);
|
||||
this.quadraticCurveTo(handle, _to);
|
||||
},
|
||||
|
||||
// PORT: New implementation back to Scriptographer
|
||||
|
@ -1715,17 +1715,20 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
// Get the start point:
|
||||
var current = getCurrentSegment(this),
|
||||
from = current._point,
|
||||
through;
|
||||
if (clockwise === undefined)
|
||||
clockwise = true;
|
||||
if (typeof clockwise === 'boolean') {
|
||||
to = Point.read(arguments, 0, 1);
|
||||
through,
|
||||
point = Point.read(arguments),
|
||||
next = Base.peekValue(arguments);
|
||||
if (/boolean|undefined/.test(typeof next)) {
|
||||
// arcTo(to, clockwise)
|
||||
to = point;
|
||||
clockwise = next;
|
||||
var middle = from.add(to).divide(2),
|
||||
through = middle.add(middle.subtract(from).rotate(
|
||||
clockwise ? -90 : 90));
|
||||
} else {
|
||||
through = Point.read(arguments, 0, 1);
|
||||
to = Point.read(arguments, 1, 1);
|
||||
// arcTo(through, to)
|
||||
through = point;
|
||||
to = Point.read(arguments);
|
||||
}
|
||||
// Construct the two perpendicular middle lines to (from, through)
|
||||
// and (through, to), and intersect them to get the center
|
||||
|
|
|
@ -73,7 +73,7 @@ var SegmentPoint = Point.extend({
|
|||
} else {
|
||||
// If not Point-like already, read Point from pt = 3rd argument
|
||||
if ((x = pt.x) === undefined) {
|
||||
pt = Point.read(arguments, 2, 1);
|
||||
pt = Point.read(arguments, 2);
|
||||
x = pt.x;
|
||||
}
|
||||
y = pt.y;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue