mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
Move PostScript commands to the end of Path definition in its own injection block.
This commit is contained in:
parent
f803e1ad1d
commit
e533b4edbb
1 changed files with 201 additions and 201 deletions
402
src/path/Path.js
402
src/path/Path.js
|
@ -137,207 +137,6 @@ var Path = this.Path = PathItem.extend({
|
|||
return segment ? this._add(segment, index) : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* PostScript-style drawing commands
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper method that returns the current segment and checks if we need to
|
||||
* execute a moveTo() command first.
|
||||
*/
|
||||
getCurrentSegment: function() {
|
||||
if (this._segments.length == 0)
|
||||
throw('Use a moveTo() command first');
|
||||
return this._segments[this._segments.length - 1];
|
||||
},
|
||||
|
||||
moveTo: function() {
|
||||
var segment = new Segment(Point.read(arguments));
|
||||
if (segment && !this._segments.length)
|
||||
this._add(segment);
|
||||
},
|
||||
|
||||
lineTo: function() {
|
||||
var segment = new Segment(Point.read(arguments));
|
||||
if (segment)
|
||||
this._add(segment);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a cubic bezier curve to the path, defined by two handles and a to
|
||||
* point.
|
||||
*/
|
||||
cubicCurveTo: function(handle1, handle2, to) {
|
||||
// First modify the current segment:
|
||||
var current = this.currentSegment;
|
||||
// Convert to relative values:
|
||||
current.setHandleOut(new Point(
|
||||
handle1.x - current._point.x,
|
||||
handle1.y - current._point.y));
|
||||
// And add the new segment, with handleIn set to c2
|
||||
this._add(
|
||||
new Segment(to, handle2.subtract(to), new Point())
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a quadratic bezier curve to the path, defined by a handle and a to
|
||||
* point.
|
||||
*/
|
||||
quadraticCurveTo: function(handle, to) {
|
||||
// This is exact:
|
||||
// If we have the three quad points: A E D,
|
||||
// and the cubic is A B C D,
|
||||
// B = E + 1/3 (A - E)
|
||||
// C = E + 1/3 (D - E)
|
||||
var current = this.currentSegment,
|
||||
x1 = current._point.x,
|
||||
y1 = current._point.y;
|
||||
this.cubicCurveTo(
|
||||
handle.add(current._point.subtract(handle).multiply(1/3)),
|
||||
handle.add(to.subtract(handle).multiply(1/3)),
|
||||
to
|
||||
);
|
||||
},
|
||||
|
||||
curveTo: function(through, to, parameter) {
|
||||
through = new Point(through);
|
||||
to = new Point(to);
|
||||
if (parameter == null)
|
||||
parameter = 0.5;
|
||||
var current = this.currentSegment._point;
|
||||
// handle = (through - (1 - t)^2 * current - t^2 * to) /
|
||||
// (2 * (1 - t) * t)
|
||||
var t1 = 1 - parameter;
|
||||
var handle = through.subtract(
|
||||
current.multiply(t1 * t1)).subtract(
|
||||
to.multiply(parameter * parameter)).divide(
|
||||
2.0 * parameter * t1);
|
||||
if (handle.isNaN())
|
||||
throw new Error(
|
||||
"Cannot put a curve through points with parameter="
|
||||
+ parameter);
|
||||
this.quadraticCurveTo(handle, to);
|
||||
},
|
||||
|
||||
arcTo: function(to, clockwise) {
|
||||
var through, to;
|
||||
// Get the start point:
|
||||
var current = this.currentSegment;
|
||||
if (arguments[1] && typeof arguments[1] != 'boolean') {
|
||||
through = Point.read(arguments, 0, 1);
|
||||
to = Point.read(arguments, 1, 1);
|
||||
} else {
|
||||
to = Point.read(arguments, 0, 1);
|
||||
if (clockwise === null)
|
||||
clockwise = true;
|
||||
var middle = current._point.add(to).divide(2),
|
||||
step = middle.subtract(current._point);
|
||||
through = clockwise
|
||||
? middle.subtract(-step.y, step.x)
|
||||
: middle.add(-step.y, step.x);
|
||||
}
|
||||
|
||||
var x1 = current._point.x, x2 = through.x, x3 = to.x,
|
||||
y1 = current._point.y, y2 = through.y, y3 = to.y,
|
||||
|
||||
f = x3 * x3 - x3 * x2 - x1 * x3 + x1 * x2 + y3 * y3 - y3 * y2
|
||||
- y1 * y3 + y1 * y2,
|
||||
g = x3 * y1 - x3 * y2 + x1 * y2 - x1 * y3 + x2 * y3 - x2 * y1,
|
||||
m = g == 0 ? 0 : f / g,
|
||||
|
||||
c = (m * y2) - x2 - x1 - (m * y1),
|
||||
d = (m * x1) - y1 - y2 - (x2 * m),
|
||||
e = (x1 * x2) + (y1 * y2) - (m * x1 * y2) + (m * x2 * y1),
|
||||
|
||||
centerX = -c / 2,
|
||||
centerY = -d / 2,
|
||||
radius = Math.sqrt(centerX * centerX + centerY * centerY - e),
|
||||
|
||||
// Note: reversing the Y equations negates the angle to adjust
|
||||
// for the upside down coordinate system.
|
||||
angle = Math.atan2(centerY - y1, x1 - centerX),
|
||||
middle = Math.atan2(centerY - y2, x2 - centerX),
|
||||
extent = Math.atan2(centerY - y3, x3 - centerX),
|
||||
|
||||
diff = middle - angle;
|
||||
|
||||
if (diff < -Math.PI)
|
||||
diff += Math.PI * 2;
|
||||
else if (diff > Math.PI)
|
||||
diff -= Math.PI * 2;
|
||||
|
||||
extent -= angle;
|
||||
if (extent <= 0.0)
|
||||
extent += Math.PI * 2;
|
||||
|
||||
if (diff < 0) extent = Math.PI * 2 - extent;
|
||||
else extent = -extent;
|
||||
angle = -angle;
|
||||
|
||||
var ext = Math.abs(extent),
|
||||
arcSegs;
|
||||
if (ext >= 2 * Math.PI) arcSegs = 4;
|
||||
else arcSegs = Math.ceil(ext * 2 / Math.PI);
|
||||
|
||||
var inc = extent;
|
||||
if (inc > 2 * Math.PI) inc = 2 * Math.PI;
|
||||
else if (inc < -2 * Math.PI) inc = -2 * Math.PI;
|
||||
inc /= arcSegs;
|
||||
|
||||
var halfInc = inc / 2,
|
||||
z = 4 / 3 * Math.sin(halfInc) / (1 + Math.cos(halfInc));
|
||||
|
||||
for (var i = 0; i <= arcSegs; i++) {
|
||||
var relx = Math.cos(angle),
|
||||
rely = Math.sin(angle),
|
||||
pt = new Point(centerX + relx * radius,
|
||||
centerY + rely * radius);
|
||||
var out;
|
||||
if (i == arcSegs) out = null;
|
||||
else out = new Point(centerX + (relx - z * rely) * radius - pt.x,
|
||||
centerY + (rely + z * relx) * radius - pt.y);
|
||||
if (i == 0) {
|
||||
// Modify startSegment
|
||||
current.setHandleOut(out);
|
||||
} else {
|
||||
// Add new Segment
|
||||
var inPoint = new Point(
|
||||
centerX + (relx + z * rely) * radius - pt.x,
|
||||
centerY + (rely - z * relx) * radius - pt.y);
|
||||
this._add(new Segment(pt, inPoint, out));
|
||||
}
|
||||
angle += inc;
|
||||
}
|
||||
},
|
||||
|
||||
lineBy: function() {
|
||||
var vector = Point.read(arguments);
|
||||
if (vector) {
|
||||
var current = this.currentSegment;
|
||||
this.lineTo(current._point.add(vector));
|
||||
}
|
||||
},
|
||||
|
||||
curveBy: function(throughVector, toVector, parameter) {
|
||||
throughVector = Point.read(throughVector);
|
||||
toVector = Point.read(toVector);
|
||||
var current = this.currentSegment._point;
|
||||
this.curveTo(current.add(throughVector), current.add(toVector),
|
||||
parameter);
|
||||
},
|
||||
|
||||
arcBy: function(throughVector, toVector) {
|
||||
throughVector = Point.read(throughVector);
|
||||
toVector = Point.read(toVector);
|
||||
var current = this.currentSegment._point;
|
||||
this.arcBy(current.add(throughVector), current.add(toVector));
|
||||
},
|
||||
|
||||
closePath: function() {
|
||||
this.closed = ture;
|
||||
},
|
||||
|
||||
getLength: function() {
|
||||
var curves = this.getCurves();
|
||||
var length = 0;
|
||||
|
@ -751,4 +550,205 @@ var Path = this.Path = PathItem.extend({
|
|||
}
|
||||
}
|
||||
};
|
||||
}, {
|
||||
/**
|
||||
* PostScript-style drawing commands
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper method that returns the current segment and checks if we need to
|
||||
* execute a moveTo() command first.
|
||||
*/
|
||||
getCurrentSegment: function() {
|
||||
if (this._segments.length == 0)
|
||||
throw('Use a moveTo() command first');
|
||||
return this._segments[this._segments.length - 1];
|
||||
},
|
||||
|
||||
moveTo: function() {
|
||||
var segment = new Segment(Point.read(arguments));
|
||||
if (segment && !this._segments.length)
|
||||
this._add(segment);
|
||||
},
|
||||
|
||||
lineTo: function() {
|
||||
var segment = new Segment(Point.read(arguments));
|
||||
if (segment)
|
||||
this._add(segment);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a cubic bezier curve to the path, defined by two handles and a to
|
||||
* point.
|
||||
*/
|
||||
cubicCurveTo: function(handle1, handle2, to) {
|
||||
// First modify the current segment:
|
||||
var current = this.currentSegment;
|
||||
// Convert to relative values:
|
||||
current.setHandleOut(new Point(
|
||||
handle1.x - current._point.x,
|
||||
handle1.y - current._point.y));
|
||||
// And add the new segment, with handleIn set to c2
|
||||
this._add(
|
||||
new Segment(to, handle2.subtract(to), new Point())
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a quadratic bezier curve to the path, defined by a handle and a to
|
||||
* point.
|
||||
*/
|
||||
quadraticCurveTo: function(handle, to) {
|
||||
// This is exact:
|
||||
// If we have the three quad points: A E D,
|
||||
// and the cubic is A B C D,
|
||||
// B = E + 1/3 (A - E)
|
||||
// C = E + 1/3 (D - E)
|
||||
var current = this.currentSegment,
|
||||
x1 = current._point.x,
|
||||
y1 = current._point.y;
|
||||
this.cubicCurveTo(
|
||||
handle.add(current._point.subtract(handle).multiply(1/3)),
|
||||
handle.add(to.subtract(handle).multiply(1/3)),
|
||||
to
|
||||
);
|
||||
},
|
||||
|
||||
curveTo: function(through, to, parameter) {
|
||||
through = new Point(through);
|
||||
to = new Point(to);
|
||||
if (parameter == null)
|
||||
parameter = 0.5;
|
||||
var current = this.currentSegment._point;
|
||||
// handle = (through - (1 - t)^2 * current - t^2 * to) /
|
||||
// (2 * (1 - t) * t)
|
||||
var t1 = 1 - parameter;
|
||||
var handle = through.subtract(
|
||||
current.multiply(t1 * t1)).subtract(
|
||||
to.multiply(parameter * parameter)).divide(
|
||||
2.0 * parameter * t1);
|
||||
if (handle.isNaN())
|
||||
throw new Error(
|
||||
"Cannot put a curve through points with parameter="
|
||||
+ parameter);
|
||||
this.quadraticCurveTo(handle, to);
|
||||
},
|
||||
|
||||
arcTo: function(to, clockwise) {
|
||||
var through, to;
|
||||
// Get the start point:
|
||||
var current = this.currentSegment;
|
||||
if (arguments[1] && typeof arguments[1] != 'boolean') {
|
||||
through = Point.read(arguments, 0, 1);
|
||||
to = Point.read(arguments, 1, 1);
|
||||
} else {
|
||||
to = Point.read(arguments, 0, 1);
|
||||
if (clockwise === null)
|
||||
clockwise = true;
|
||||
var middle = current._point.add(to).divide(2),
|
||||
step = middle.subtract(current._point);
|
||||
through = clockwise
|
||||
? middle.subtract(-step.y, step.x)
|
||||
: middle.add(-step.y, step.x);
|
||||
}
|
||||
|
||||
var x1 = current._point.x, x2 = through.x, x3 = to.x,
|
||||
y1 = current._point.y, y2 = through.y, y3 = to.y,
|
||||
|
||||
f = x3 * x3 - x3 * x2 - x1 * x3 + x1 * x2 + y3 * y3 - y3 * y2
|
||||
- y1 * y3 + y1 * y2,
|
||||
g = x3 * y1 - x3 * y2 + x1 * y2 - x1 * y3 + x2 * y3 - x2 * y1,
|
||||
m = g == 0 ? 0 : f / g,
|
||||
|
||||
c = (m * y2) - x2 - x1 - (m * y1),
|
||||
d = (m * x1) - y1 - y2 - (x2 * m),
|
||||
e = (x1 * x2) + (y1 * y2) - (m * x1 * y2) + (m * x2 * y1),
|
||||
|
||||
centerX = -c / 2,
|
||||
centerY = -d / 2,
|
||||
radius = Math.sqrt(centerX * centerX + centerY * centerY - e),
|
||||
|
||||
// Note: reversing the Y equations negates the angle to adjust
|
||||
// for the upside down coordinate system.
|
||||
angle = Math.atan2(centerY - y1, x1 - centerX),
|
||||
middle = Math.atan2(centerY - y2, x2 - centerX),
|
||||
extent = Math.atan2(centerY - y3, x3 - centerX),
|
||||
|
||||
diff = middle - angle;
|
||||
|
||||
if (diff < -Math.PI)
|
||||
diff += Math.PI * 2;
|
||||
else if (diff > Math.PI)
|
||||
diff -= Math.PI * 2;
|
||||
|
||||
extent -= angle;
|
||||
if (extent <= 0.0)
|
||||
extent += Math.PI * 2;
|
||||
|
||||
if (diff < 0) extent = Math.PI * 2 - extent;
|
||||
else extent = -extent;
|
||||
angle = -angle;
|
||||
|
||||
var ext = Math.abs(extent),
|
||||
arcSegs;
|
||||
if (ext >= 2 * Math.PI) arcSegs = 4;
|
||||
else arcSegs = Math.ceil(ext * 2 / Math.PI);
|
||||
|
||||
var inc = extent;
|
||||
if (inc > 2 * Math.PI) inc = 2 * Math.PI;
|
||||
else if (inc < -2 * Math.PI) inc = -2 * Math.PI;
|
||||
inc /= arcSegs;
|
||||
|
||||
var halfInc = inc / 2,
|
||||
z = 4 / 3 * Math.sin(halfInc) / (1 + Math.cos(halfInc));
|
||||
|
||||
for (var i = 0; i <= arcSegs; i++) {
|
||||
var relx = Math.cos(angle),
|
||||
rely = Math.sin(angle),
|
||||
pt = new Point(centerX + relx * radius,
|
||||
centerY + rely * radius);
|
||||
var out;
|
||||
if (i == arcSegs) out = null;
|
||||
else out = new Point(centerX + (relx - z * rely) * radius - pt.x,
|
||||
centerY + (rely + z * relx) * radius - pt.y);
|
||||
if (i == 0) {
|
||||
// Modify startSegment
|
||||
current.setHandleOut(out);
|
||||
} else {
|
||||
// Add new Segment
|
||||
var inPoint = new Point(
|
||||
centerX + (relx + z * rely) * radius - pt.x,
|
||||
centerY + (rely - z * relx) * radius - pt.y);
|
||||
this._add(new Segment(pt, inPoint, out));
|
||||
}
|
||||
angle += inc;
|
||||
}
|
||||
},
|
||||
|
||||
lineBy: function() {
|
||||
var vector = Point.read(arguments);
|
||||
if (vector) {
|
||||
var current = this.currentSegment;
|
||||
this.lineTo(current._point.add(vector));
|
||||
}
|
||||
},
|
||||
|
||||
curveBy: function(throughVector, toVector, parameter) {
|
||||
throughVector = Point.read(throughVector);
|
||||
toVector = Point.read(toVector);
|
||||
var current = this.currentSegment._point;
|
||||
this.curveTo(current.add(throughVector), current.add(toVector),
|
||||
parameter);
|
||||
},
|
||||
|
||||
arcBy: function(throughVector, toVector) {
|
||||
throughVector = Point.read(throughVector);
|
||||
toVector = Point.read(toVector);
|
||||
var current = this.currentSegment._point;
|
||||
this.arcBy(current.add(throughVector), current.add(toVector));
|
||||
},
|
||||
|
||||
closePath: function() {
|
||||
this.closed = ture;
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue