mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Add support for insertion of multiple segments at once to Path#_add(), #add() and #insert(), and change code that relies on these methods.
This commit is contained in:
parent
bdbbca487f
commit
a5099fd51d
4 changed files with 116 additions and 129 deletions
|
@ -37,11 +37,12 @@ Path.inject({ statics: new function() {
|
|||
rect = Rectangle.read(arguments);
|
||||
var path = new Path(),
|
||||
corners = ['getBottomLeft', 'getTopLeft', 'getTopRight',
|
||||
'getBottomRight'];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
path.add(rect[corners[i]]());
|
||||
}
|
||||
path.setClosed(true);
|
||||
'getBottomRight'],
|
||||
segments = new Array(4);
|
||||
for (var i = 0; i < 4; i++)
|
||||
segments[i] = new Segment(rect[corners[i]]());
|
||||
path._add(segments);
|
||||
path._closed = true;
|
||||
return path;
|
||||
},
|
||||
|
||||
|
@ -56,25 +57,24 @@ Path.inject({ statics: new function() {
|
|||
size = Size.min(size, rect.getSize().divide(2));
|
||||
var path = new Path(),
|
||||
uSize = size.multiply(kappa * 2),
|
||||
|
||||
bl = rect.getBottomLeft(),
|
||||
tl = rect.getTopLeft(),
|
||||
tr = rect.getTopRight(),
|
||||
br = rect.getBottomRight();
|
||||
path._add([
|
||||
new Segment(bl.add(size.width, 0), null, [-uSize.width, 0]),
|
||||
new Segment(bl.subtract(0, size.height), [0, uSize.height], null),
|
||||
|
||||
path.add(bl.add(size.width, 0), null, [-uSize.width, 0]);
|
||||
path.add(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),
|
||||
|
||||
path.add(tl.add(0, size.height), null, [0, -uSize.height]);
|
||||
path.add(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),
|
||||
|
||||
path.add(tr.subtract(size.width, 0), null, [uSize.width, 0]);
|
||||
path.add(tr.add(0, size.height), [0, -uSize.height], null);
|
||||
|
||||
path.add(br.subtract(0, size.height), null, [0, uSize.height]);
|
||||
path.add(br.subtract(size.width, 0), [uSize.width, 0], null);
|
||||
|
||||
path.setClosed(true);
|
||||
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;
|
||||
},
|
||||
|
||||
|
@ -82,16 +82,18 @@ Path.inject({ statics: new function() {
|
|||
rect = Rectangle.read(arguments);
|
||||
var path = new Path(),
|
||||
topLeft = rect.getTopLeft(),
|
||||
size = new Size(rect.width, rect.height);
|
||||
size = new Size(rect.width, rect.height),
|
||||
segments = new Array(4);
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var segment = ovalSegments[i];
|
||||
path._add(new Segment(
|
||||
segments[i] = new Segment(
|
||||
segment._point.multiply(size).add(topLeft),
|
||||
segment._handleIn.multiply(size),
|
||||
segment._handleOut.multiply(size)
|
||||
));
|
||||
);
|
||||
}
|
||||
path.setClosed(true);
|
||||
path._add(segments);
|
||||
path._closed = true;
|
||||
return path;
|
||||
},
|
||||
|
||||
|
@ -116,29 +118,33 @@ Path.inject({ statics: new function() {
|
|||
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),
|
||||
offset = three ? -1 : 0.5;
|
||||
offset = three ? -1 : 0.5,
|
||||
segments = new Array(numSides);
|
||||
for (var i = 0; i < numSides; i++) {
|
||||
var angle = (360 / numSides) * (i + offset);
|
||||
path.add(center.add(vector.rotate(angle)));
|
||||
segments[i] = new Segment(center.add(
|
||||
vector.rotate((i + offset) * step)));
|
||||
}
|
||||
path.setClosed(true);
|
||||
path._add(segments);
|
||||
path._closed = true;
|
||||
return path;
|
||||
},
|
||||
|
||||
Star: function(center, numPoints, radius1, radius2) {
|
||||
center = Point.read(arguments, 0, 1);
|
||||
numPoints *= 2;
|
||||
var angle = 360 / numPoints,
|
||||
path = new Path();
|
||||
var path = new Path(),
|
||||
step = 360 / numPoints,
|
||||
vector = new Point(0, -1),
|
||||
segments = new Array(numPoints);
|
||||
for (var i = 0; i < numPoints; i++) {
|
||||
path.add(center.add({
|
||||
angle: -90 + angle * i,
|
||||
length: i % 2 ? radius2 : radius1
|
||||
}));
|
||||
segments[i] = new Segment(center.add(
|
||||
vector.rotate(step * i).multiply(i % 2 ? radius2 : radius1)));
|
||||
}
|
||||
path.setClosed(true);
|
||||
path._add(segments);
|
||||
path._closed = true;
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -52,8 +52,7 @@ var Path = this.Path = PathItem.extend({
|
|||
if (this._curves)
|
||||
this._curves = null;
|
||||
}
|
||||
for (var i = 0, l = segments.length; i < l; i++)
|
||||
this._add(Segment.read(segments, i, 1));
|
||||
this._add(Segment.readAll(segments));
|
||||
},
|
||||
|
||||
getFirstSegment: function() {
|
||||
|
@ -137,60 +136,63 @@ var Path = this.Path = PathItem.extend({
|
|||
* If a curves list was requested, it will kept in sync with the segments
|
||||
* list automatically.
|
||||
*/
|
||||
// TODO: Add support for adding multiple segments at once
|
||||
_add: function(segment, index) {
|
||||
_add: function(segs, index) {
|
||||
// Local short-cuts:
|
||||
var segments = this._segments,
|
||||
curves = this._curves;
|
||||
// If this segment belongs to another path already, clone it before
|
||||
// adding.
|
||||
if (segment._path)
|
||||
segment = new Segment(segment);
|
||||
if (index === undefined) {
|
||||
// Insert at the end
|
||||
index = segments.push(segment) - 1;
|
||||
curves = this._curves,
|
||||
amount = segs.length,
|
||||
append = index === undefined,
|
||||
index = append ? segments.length : index;
|
||||
for (var i = 0; i < amount; i++) {
|
||||
var segment = segs[i];
|
||||
// If the segments belong to another path already, clone them before
|
||||
// adding:
|
||||
if (segment._path)
|
||||
segment = segs[i] = new Segment(segment);
|
||||
// Set _path and _index references for these new segments now
|
||||
segment._path = this;
|
||||
segment._index = index + i;
|
||||
}
|
||||
if (append) {
|
||||
// Append them all at the end by using push
|
||||
segments.push.apply(segments, segs);
|
||||
} else {
|
||||
// Insert somewhere else
|
||||
segments.splice(index, 0, segment);
|
||||
segments.splice.apply(segments, [index, 0].concat(segs));
|
||||
// Adjust the indices of the segments above.
|
||||
for (var i = index + 1, l = segments.length; i < l; i++)
|
||||
for (var i = index + amount, l = segments.length; i < l; i++)
|
||||
segments[i]._index = i;
|
||||
}
|
||||
segment._path = this;
|
||||
segment._index = index;
|
||||
// Keep the curves list in sync all the time in case it as requested
|
||||
// already. We need to step one index down from the inserted segment to
|
||||
// get its curve:
|
||||
if (curves && --index >= 0) {
|
||||
// Insert a new curve as well and update the curves above
|
||||
curves.splice(index, 0, Curve.create(this, segments[index],
|
||||
segments[++index]));
|
||||
segments[index + 1]));
|
||||
// Adjust segment1 now for the curves above the inserted one
|
||||
// (note the ++index in the statement above)/
|
||||
var curve = curves[index];
|
||||
var curve = curves[index + amount];
|
||||
if (curve)
|
||||
curve._segment1 = segments[index];
|
||||
curve._segment1 = segments[index + amount];
|
||||
}
|
||||
this._changed();
|
||||
return segment;
|
||||
return segs;
|
||||
},
|
||||
|
||||
// TODO: Add support for adding multiple segments at once
|
||||
add: function(segment) {
|
||||
segment = Segment.read(arguments);
|
||||
return segment ? this._add(segment) : null;
|
||||
// TODO: Port back support for adding multiple segments at once to Sg
|
||||
add: function(segment1 /*, segment2, ... */) {
|
||||
return this._add(Segment.readAll(arguments));
|
||||
},
|
||||
|
||||
// TODO: Add support for adding multiple segments at once
|
||||
insert: function(index, segment) {
|
||||
segment = Segment.read(arguments, 1);
|
||||
return segment ? this._add(segment, index) : null;
|
||||
// TODO: Port back support for adding multiple segments at once to Sg
|
||||
insert: function(index, segment1 /*, segment2, ... */) {
|
||||
return this._add(Segment.readAll(arguments, 1), index);
|
||||
},
|
||||
|
||||
// TODO: Port back to Sg
|
||||
removeSegment: function(index) {
|
||||
var segments = this.removeSegments(index, index + 1);
|
||||
return segments ? segments[0] : null;
|
||||
return segments[0] || null;
|
||||
},
|
||||
|
||||
// TODO: Port back to Sg
|
||||
|
@ -287,8 +289,7 @@ var Path = this.Path = PathItem.extend({
|
|||
var first2 = path.getFirstSegment();
|
||||
if (last1._point.equals(first2._point)) {
|
||||
last1.setHandleOut(first2._handleOut);
|
||||
for (var i = 1, l = segments.length; i < l; i++)
|
||||
this._add(segments[i]);
|
||||
this._add(segments.slice(1));
|
||||
} else {
|
||||
var first1 = this.getFirstSegment();
|
||||
if (first1._point.equals(first2._point))
|
||||
|
@ -296,11 +297,10 @@ var Path = this.Path = PathItem.extend({
|
|||
if (first1._point.equals(last2._point)) {
|
||||
first1.setHandleIn(last2._handleIn);
|
||||
// Prepend all segments from path except last one
|
||||
for (var i = 0, l = segments.length - 1; i < l; i++)
|
||||
this._add(segments[i], 0);
|
||||
// TODO: Test if -1 (== all) or -2 (as described by comment)
|
||||
this._add(segments.slice(0, segments.length - 2), 0);
|
||||
} else {
|
||||
for (var i = 0, l = segments.length; i < l; i++)
|
||||
this._add(segments[i]);
|
||||
this._add(segments.slice(0));
|
||||
}
|
||||
}
|
||||
path.remove();
|
||||
|
@ -679,12 +679,12 @@ var Path = this.Path = PathItem.extend({
|
|||
// Let's not be picky about calling moveTo() when not at the
|
||||
// beginning of a path, just bail out:
|
||||
if (!this._segments.length)
|
||||
this._add(new Segment(Point.read(arguments)));
|
||||
this._add([new Segment(Point.read(arguments))]);
|
||||
},
|
||||
|
||||
lineTo: function() {
|
||||
// Let's not be picky about calling moveTo() first:
|
||||
this._add(new Segment(Point.read(arguments)));
|
||||
this._add([new Segment(Point.read(arguments))]);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -700,7 +700,7 @@ var Path = this.Path = PathItem.extend({
|
|||
// Convert to relative values:
|
||||
current.setHandleOut(handle1.subtract(current._point));
|
||||
// And add the new segment, with handleIn set to c2
|
||||
this._add(new Segment(to, handle2.subtract(to), new Point()));
|
||||
this._add([new Segment(to, handle2.subtract(to), new Point())]);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -807,6 +807,7 @@ var Path = this.Path = PathItem.extend({
|
|||
var halfInc = inc / 2,
|
||||
z = 4 / 3 * Math.sin(halfInc) / (1 + Math.cos(halfInc));
|
||||
|
||||
var segments = [];
|
||||
for (var i = 0; i <= arcSegs; i++) {
|
||||
var relx = Math.cos(angle),
|
||||
rely = Math.sin(angle),
|
||||
|
@ -829,10 +830,12 @@ var Path = this.Path = PathItem.extend({
|
|||
var handleIn = new Point(
|
||||
centerX + (relx + z * rely) * radius - pt.x,
|
||||
centerY + (rely - z * relx) * radius - pt.y);
|
||||
this._add(new Segment(pt, handleIn, out));
|
||||
segments.push(new Segment(pt, handleIn, out));
|
||||
}
|
||||
angle += inc;
|
||||
}
|
||||
// Add all segments at once at the end for higher performance
|
||||
this._add(segments);
|
||||
},
|
||||
|
||||
lineBy: function(vector) {
|
||||
|
|
|
@ -3,12 +3,12 @@ module('Path');
|
|||
test('path.join(path)', function() {
|
||||
var doc = new Document();
|
||||
var path = new Path();
|
||||
path.add(0, 0);
|
||||
path.add(10, 0);
|
||||
path.add([0, 0]);
|
||||
path.add([10, 0]);
|
||||
|
||||
var path2 = new Path();
|
||||
path2.add(10, 0);
|
||||
path2.add(20, 10);
|
||||
path2.add([10, 0]);
|
||||
path2.add([20, 10]);
|
||||
|
||||
path.join(path2);
|
||||
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
|
||||
|
@ -16,37 +16,37 @@ test('path.join(path)', function() {
|
|||
equals(doc.activeLayer.children.length, 1);
|
||||
|
||||
var path = new Path();
|
||||
path.add(0, 0);
|
||||
path.add(10, 0);
|
||||
path.add([0, 0]);
|
||||
path.add([10, 0]);
|
||||
|
||||
var path2 = new Path();
|
||||
path2.add(20, 10);
|
||||
path2.add(10, 0);
|
||||
path2.add([20, 10]);
|
||||
path2.add([10, 0]);
|
||||
path.join(path2);
|
||||
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
|
||||
new Segment(new Point(10, 0)), new Segment(new Point(20, 10))]);
|
||||
|
||||
var path = new Path();
|
||||
path.add(0, 0);
|
||||
path.add(10, 0);
|
||||
path.add([0, 0]);
|
||||
path.add([10, 0]);
|
||||
|
||||
var path2 = new Path();
|
||||
path2.add(30, 10);
|
||||
path2.add(40, 0);
|
||||
path2.add([30, 10]);
|
||||
path2.add([40, 0]);
|
||||
path.join(path2);
|
||||
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
|
||||
new Segment(new Point(10, 0)), new Segment(new Point(30, 10)),
|
||||
new Segment(new Point(40, 0))]);
|
||||
|
||||
var path = new Path();
|
||||
path.add(0, 0);
|
||||
path.add(10, 0);
|
||||
path.add(20, 10);
|
||||
path.add([0, 0]);
|
||||
path.add([10, 0]);
|
||||
path.add([20, 10]);
|
||||
|
||||
var path2 = new Path();
|
||||
path2.add(0, 0);
|
||||
path2.add(10, 5);
|
||||
path2.add(20, 10);
|
||||
path2.add([0, 0]);
|
||||
path2.add([10, 5]);
|
||||
path2.add([20, 10]);
|
||||
|
||||
path.join(path2);
|
||||
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
|
||||
|
@ -58,10 +58,10 @@ test('path.join(path)', function() {
|
|||
test('path.remove()', function() {
|
||||
var doc = new Document();
|
||||
var path = new Path();
|
||||
path.add(0, 0);
|
||||
path.add(10, 0);
|
||||
path.add(20, 0);
|
||||
path.add(30, 0);
|
||||
path.add([0, 0]);
|
||||
path.add([10, 0]);
|
||||
path.add([20, 0]);
|
||||
path.add([30, 0]);
|
||||
|
||||
path.removeSegment(0);
|
||||
equals(path.segments.length, 3);
|
||||
|
|
|
@ -6,44 +6,22 @@ test('path.curves Synchronisation', function() {
|
|||
var path = new Path();
|
||||
|
||||
path.add(new Point(0, 100));
|
||||
equals(path.curves.toString(), '');
|
||||
|
||||
equals(path.segments.toString(), '{ point: { x: 0, y: 100 } }', 'path.segments: path.add(new Point(0, 100));');
|
||||
equals(path.curves.toString(), '', 'path.curves: path.add(new Point(0, 100));');
|
||||
path.add(new Point(100, 100));
|
||||
equals(path.curves.toString(),
|
||||
'{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } }',
|
||||
'2 x path.add()');
|
||||
|
||||
path.insert(1, { point: [50, 0], handleIn: [-25, 0], handleOut: [25, 0] });
|
||||
equals(path.curves.toString(),
|
||||
'{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } }',
|
||||
'path.insert()'
|
||||
);
|
||||
|
||||
equals(path.segments.toString(), '{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }', 'path.segments: path.add(new Point(100, 100));');
|
||||
equals(path.curves.toString(), '{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } }', 'path.curves: path.add(new Point(100, 100));');
|
||||
path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});
|
||||
equals(path.segments.toString(), '{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }', 'path.segments: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});');
|
||||
equals(path.curves.toString(), '{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } }', 'path.curves: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});');
|
||||
path.closed = true;
|
||||
equals(path.curves.toString(),
|
||||
'{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }',
|
||||
'path.closed = true');
|
||||
|
||||
equals(path.segments.toString(), '{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }', 'path.segments: path.closed = true;');
|
||||
equals(path.curves.toString(), '{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }', 'path.curves: path.closed = true;');
|
||||
path.removeSegments(2, 3);
|
||||
equals(path.curves.toString(),
|
||||
'{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 0, y: 100 } }',
|
||||
'path.removeSegments(2, 3)');
|
||||
|
||||
equals(path.segments.toString(),
|
||||
'{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } }',
|
||||
'segments');
|
||||
|
||||
equals(path.segments.toString(), '{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } }', 'path.segments: path.removeSegments(2, 3);');
|
||||
equals(path.curves.toString(), '{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 0, y: 100 } }', 'path.curves: path.removeSegments(2, 3);');
|
||||
path.add(new Point(100, 100));
|
||||
equals(path.curves.toString(),
|
||||
'{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }',
|
||||
'path.add()');
|
||||
|
||||
path.removeSegments(1, 2);
|
||||
equals(path.curves.toString(),
|
||||
'{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }',
|
||||
'path.removeSegments(1, 2)');
|
||||
|
||||
equals(path.segments.toString(),
|
||||
'{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }',
|
||||
'segments');
|
||||
equals(path.segments.toString(), '{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }', 'path.segments: path.add(new Point(100, 100));\n path.removeSegments(1, 2);');
|
||||
equals(path.curves.toString(), '{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }', 'path.curves: path.add(new Point(100, 100));\n path.removeSegments(1, 2);');
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue