mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
Simplify handling of strokeJoin / strokeCap geometries.
This commit is contained in:
parent
b40efbf6db
commit
f19a50093b
1 changed files with 26 additions and 30 deletions
|
@ -1673,7 +1673,7 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
if (strokeRadius > 0) {
|
if (strokeRadius > 0) {
|
||||||
join = style.getStrokeJoin();
|
join = style.getStrokeJoin();
|
||||||
cap = style.getStrokeCap();
|
cap = style.getStrokeCap();
|
||||||
miterLimit = strokeRadius * style.getMiterLimit();
|
miterLimit = style.getMiterLimit();
|
||||||
// Add the stroke radius to tolerance padding, taking
|
// Add the stroke radius to tolerance padding, taking
|
||||||
// #strokeScaling into account through _getStrokeMatrix().
|
// #strokeScaling into account through _getStrokeMatrix().
|
||||||
strokePadding = strokePadding.add(
|
strokePadding = strokePadding.add(
|
||||||
|
@ -1723,21 +1723,22 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
function checkSegmentStroke(segment) {
|
function checkSegmentStroke(segment) {
|
||||||
// Handle joins / caps that are not round specificelly, by
|
// Handle joins / caps that are not round specificelly, by
|
||||||
// hit-testing their polygon areas.
|
// hit-testing their polygon areas.
|
||||||
if (join !== 'round' || cap !== 'round') {
|
var isJoin = closed || segment._index > 0
|
||||||
|
&& segment._index < numSegments - 1;
|
||||||
|
if ((isJoin ? join : cap) === 'round') {
|
||||||
|
// Round join / cap is easy to handle.
|
||||||
|
return isCloseEnough(segment._point, strokePadding);
|
||||||
|
} else {
|
||||||
// Create an 'internal' path without id and outside the scene
|
// Create an 'internal' path without id and outside the scene
|
||||||
// graph to run the hit-test on it.
|
// graph to run the hit-test on it.
|
||||||
area = new Path({ internal: true, closed: true });
|
area = new Path({ internal: true, closed: true });
|
||||||
if (closed || segment._index > 0
|
if (isJoin) {
|
||||||
&& segment._index < numSegments - 1) {
|
// It's a join. See that it's not a round one (collinear
|
||||||
// It's a join. See that it's not a round one (one of
|
// handles).
|
||||||
// the handles has to be zero too for this!)
|
// _addBevelJoin() handles both 'bevel' and 'miter' joins.
|
||||||
if (join !== 'round' && (segment._handleIn.isZero()
|
Path._addBevelJoin(segment, join, strokeRadius,
|
||||||
|| segment._handleOut.isZero()))
|
miterLimit, null, strokeMatrix, addToArea, true);
|
||||||
// _addBevelJoin() handles both 'bevel' and 'miter'!
|
} else if (cap === 'square') {
|
||||||
Path._addBevelJoin(segment, join, strokeRadius,
|
|
||||||
miterLimit, null, strokeMatrix, addToArea, true);
|
|
||||||
} else if (cap !== 'round') {
|
|
||||||
// It's a cap
|
|
||||||
Path._addSquareCap(segment, cap, strokeRadius, null,
|
Path._addSquareCap(segment, cap, strokeRadius, null,
|
||||||
strokeMatrix, addToArea, true);
|
strokeMatrix, addToArea, true);
|
||||||
}
|
}
|
||||||
|
@ -1752,8 +1753,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
&& isCloseEnough(loc.getPoint(), tolerancePadding);
|
&& isCloseEnough(loc.getPoint(), tolerancePadding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fallback scenario is a round join / cap.
|
|
||||||
return isCloseEnough(segment._point, strokePadding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're asked to query for segments, ends or handles, do all that
|
// If we're asked to query for segments, ends or handles, do all that
|
||||||
|
@ -1790,7 +1789,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
if (!loc && join === 'miter' && numSegments > 1) {
|
if (!loc && join === 'miter' && numSegments > 1) {
|
||||||
for (var i = 0; i < numSegments; i++) {
|
for (var i = 0; i < numSegments; i++) {
|
||||||
var segment = segments[i];
|
var segment = segments[i];
|
||||||
if (point.getDistance(segment._point) <= miterLimit
|
if (point.getDistance(segment._point)
|
||||||
|
<= miterLimit * strokeRadius
|
||||||
&& checkSegmentStroke(segment)) {
|
&& checkSegmentStroke(segment)) {
|
||||||
loc = segment.getLocation();
|
loc = segment.getLocation();
|
||||||
break;
|
break;
|
||||||
|
@ -2695,7 +2695,7 @@ statics: {
|
||||||
var strokeRadius = strokeWidth / 2,
|
var strokeRadius = strokeWidth / 2,
|
||||||
join = style.getStrokeJoin(),
|
join = style.getStrokeJoin(),
|
||||||
cap = style.getStrokeCap(),
|
cap = style.getStrokeCap(),
|
||||||
miterLimit = strokeRadius * style.getMiterLimit(),
|
miterLimit = style.getMiterLimit(),
|
||||||
// Create a rectangle of padding size, used for union with bounds
|
// Create a rectangle of padding size, used for union with bounds
|
||||||
// further down
|
// further down
|
||||||
joinBounds = new Rectangle(new Size(strokePadding));
|
joinBounds = new Rectangle(new Size(strokePadding));
|
||||||
|
@ -2720,6 +2720,7 @@ statics: {
|
||||||
&& handleIn.isCollinear(handleOut)) {
|
&& handleIn.isCollinear(handleOut)) {
|
||||||
addRound(segment);
|
addRound(segment);
|
||||||
} else {
|
} else {
|
||||||
|
// _addBevelJoin() handles both 'bevel' and 'miter' joins.
|
||||||
Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
|
Path._addBevelJoin(segment, join, strokeRadius, miterLimit,
|
||||||
matrix, strokeMatrix, addPoint);
|
matrix, strokeMatrix, addPoint);
|
||||||
}
|
}
|
||||||
|
@ -2729,6 +2730,7 @@ statics: {
|
||||||
if (cap === 'round') {
|
if (cap === 'round') {
|
||||||
addRound(segment);
|
addRound(segment);
|
||||||
} else {
|
} else {
|
||||||
|
// _addSquareCap() handles both 'square' and 'butt' caps.
|
||||||
Path._addSquareCap(segment, cap, strokeRadius, matrix,
|
Path._addSquareCap(segment, cap, strokeRadius, matrix,
|
||||||
strokeMatrix, addPoint);
|
strokeMatrix, addPoint);
|
||||||
}
|
}
|
||||||
|
@ -2806,10 +2808,9 @@ statics: {
|
||||||
normal1 = normal1.negate();
|
normal1 = normal1.negate();
|
||||||
normal2 = normal2.negate();
|
normal2 = normal2.negate();
|
||||||
}
|
}
|
||||||
if (isArea) {
|
if (isArea)
|
||||||
addPoint(point);
|
addPoint(point);
|
||||||
addPoint(point.add(normal1));
|
addPoint(point.add(normal1));
|
||||||
}
|
|
||||||
if (join === 'miter') {
|
if (join === 'miter') {
|
||||||
// Intersect the two lines
|
// Intersect the two lines
|
||||||
var corner = new Line(point.add(normal1),
|
var corner = new Line(point.add(normal1),
|
||||||
|
@ -2819,15 +2820,11 @@ statics: {
|
||||||
), true);
|
), true);
|
||||||
// See if we actually get a bevel point and if its distance is below
|
// See if we actually get a bevel point and if its distance is below
|
||||||
// the miterLimit. If not, make a normal bevel.
|
// the miterLimit. If not, make a normal bevel.
|
||||||
if (corner && point.getDistance(corner) <= miterLimit) {
|
if (corner && point.getDistance(corner) <= miterLimit * radius) {
|
||||||
addPoint(corner);
|
addPoint(corner);
|
||||||
if (!isArea)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Produce a normal bevel
|
// Produce a normal bevel
|
||||||
if (!isArea)
|
|
||||||
addPoint(point.add(normal1));
|
|
||||||
addPoint(point.add(normal2));
|
addPoint(point.add(normal2));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2839,18 +2836,17 @@ statics: {
|
||||||
// Style#strokeScaling.
|
// Style#strokeScaling.
|
||||||
var point = segment._point.transform(matrix),
|
var point = segment._point.transform(matrix),
|
||||||
loc = segment.getLocation(),
|
loc = segment.getLocation(),
|
||||||
// NOTE: normal is normalized, so multiply instead of normalize.
|
|
||||||
normal = loc.getNormal().multiply(radius).transform(strokeMatrix);
|
normal = loc.getNormal().multiply(radius).transform(strokeMatrix);
|
||||||
if (isArea) {
|
|
||||||
addPoint(point.subtract(normal));
|
|
||||||
addPoint(point.add(normal));
|
|
||||||
}
|
|
||||||
// For square caps, we need to step away from point in the direction of
|
// For square caps, we need to step away from point in the direction of
|
||||||
// the tangent, which is the rotated normal.
|
// the tangent, which is the rotated normal.
|
||||||
// Checking loc.getTime() for 0 is to see whether this is the first
|
// Checking loc.getTime() for 0 is to see whether this is the first
|
||||||
// or the last segment of the open path, in order to determine in which
|
// or the last segment of the open path, in order to determine in which
|
||||||
// direction to move the point.
|
// direction to move the point.
|
||||||
if (cap === 'square') {
|
if (cap === 'square') {
|
||||||
|
if (isArea) {
|
||||||
|
addPoint(point.subtract(normal));
|
||||||
|
addPoint(point.add(normal));
|
||||||
|
}
|
||||||
point = point.add(normal.rotate(
|
point = point.add(normal.rotate(
|
||||||
loc.getTime() === 0 ? -90 : 90));
|
loc.getTime() === 0 ? -90 : 90));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue