mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-19 06:00:56 -05:00
Correctly handle #strokeScaling in Path item hit-tests.
Hit-testing of Shape items with #strokeScaling still needs fixing too. Relates to #697.
This commit is contained in:
parent
43a6c57cd6
commit
fd72ad0937
4 changed files with 25 additions and 18 deletions
|
@ -1715,16 +1715,17 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
parentViewMatrix = options._viewMatrix,
|
||||
// Keep the accumulated matrices up to this item in options, so we
|
||||
// can keep calculating the correct _tolerancePadding values.
|
||||
viewMatrix = options._viewMatrix = parentViewMatrix
|
||||
viewMatrix = parentViewMatrix
|
||||
? parentViewMatrix.appended(matrix)
|
||||
// If this is the first one in the recursion, factor in the
|
||||
// zoom of the view and the globalMatrix of the item.
|
||||
: this.getGlobalMatrix().prepend(this.getView()._matrix),
|
||||
strokeMatrix = viewMatrix.inverted(),
|
||||
// Calculate the transformed padding as 2D size that describes the
|
||||
// transformed tolerance circle / ellipse. Make sure it's never 0
|
||||
// since we're using it for division.
|
||||
tolerancePadding = options._tolerancePadding = new Size(
|
||||
Path._getStrokePadding(1, viewMatrix.inverted())
|
||||
Path._getStrokePadding(1, strokeMatrix)
|
||||
).multiply(
|
||||
Math.max(options.tolerance, /*#=*/Numerical.TOLERANCE)
|
||||
);
|
||||
|
@ -1774,17 +1775,18 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
var children = !res && this._children;
|
||||
if (children) {
|
||||
var opts = this._getChildHitTestOptions(options);
|
||||
opts._viewMatrix = viewMatrix;
|
||||
// Loop backwards, so items that get drawn last are tested first
|
||||
for (var i = children.length - 1; i >= 0 && !res; i--)
|
||||
res = children[i]._hitTest(point, opts);
|
||||
// Restore viewMatrix for next child, as opts === options sometimes.
|
||||
opts._viewMatrix = parentViewMatrix;
|
||||
}
|
||||
if (!res && checkSelf)
|
||||
res = this._hitTestSelf(point, options);
|
||||
res = this._hitTestSelf(point, options, strokeMatrix);
|
||||
// Transform the point back to the outer coordinate system.
|
||||
if (res && res.point)
|
||||
res.point = matrix.transform(res.point);
|
||||
// Restore viewMatrix for next child.
|
||||
options._viewMatrix = parentViewMatrix;
|
||||
return res;
|
||||
},
|
||||
|
||||
|
|
|
@ -280,14 +280,13 @@ var Shape = Item.extend(/** @lends Shape# */{
|
|||
style = this._style,
|
||||
strokeWidth = style.hasStroke() &&
|
||||
/^getStrokeBounds$|^get.*RoughBounds$/.test(getter) &&
|
||||
style.getStrokeWidth(),
|
||||
strokePadding = strokeWidth && Path._getStrokePadding(
|
||||
strokeWidth, style._getStrokeMatrix(matrix));
|
||||
style.getStrokeWidth();
|
||||
// If we're getting the strokeBounds, include the stroke width before
|
||||
// or after transforming the rect, based on strokeScaling.
|
||||
if (matrix)
|
||||
rect = matrix._transformBounds(rect);
|
||||
return strokePadding ? rect.expand(strokePadding) : rect;
|
||||
return strokeWidth ? rect.expand(Path._getStrokePadding(
|
||||
strokeWidth, style._getStrokeMatrix(matrix))) : rect;
|
||||
}
|
||||
},
|
||||
new function() { // Scope for _contains() and _hitTestSelf() code.
|
||||
|
@ -337,6 +336,7 @@ new function() { // Scope for _contains() and _hitTestSelf() code.
|
|||
|
||||
_hitTestSelf: function _hitTestSelf(point, options) {
|
||||
var hit = false;
|
||||
// TODO: Correctly support strokeScaling here too!
|
||||
if (this.hasStroke()) {
|
||||
var type = this._type,
|
||||
radius = this._radius,
|
||||
|
|
|
@ -761,6 +761,7 @@ statics: {
|
|||
* NOTE: padding is only used for Path.getBounds().
|
||||
*/
|
||||
_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {
|
||||
padding /= 2; // strokePadding is in width, not radius
|
||||
// Code ported and further optimised from:
|
||||
// http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
|
||||
function add(value, padding) {
|
||||
|
|
|
@ -1518,7 +1518,7 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
|
||||
toPath: '#clone',
|
||||
|
||||
_hitTestSelf: function(point, options) {
|
||||
_hitTestSelf: function(point, options, strokeMatrix) {
|
||||
var that = this,
|
||||
style = this.getStyle(),
|
||||
segments = this._segments,
|
||||
|
@ -1545,8 +1545,11 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
join = style.getStrokeJoin();
|
||||
cap = style.getStrokeCap();
|
||||
miterLimit = radius * style.getMiterLimit();
|
||||
// Add the stroke radius to tolerance padding.
|
||||
strokePadding = tolerancePadding.add(new Point(radius, radius));
|
||||
// Add the stroke radius to tolerance padding, taking
|
||||
// #strokeScaling into account through _getStrokeMatrix().
|
||||
strokePadding = tolerancePadding.add(
|
||||
Path._getStrokePadding(radius,
|
||||
!style.getStrokeScaling() && strokeMatrix));
|
||||
} else {
|
||||
join = cap = 'round';
|
||||
}
|
||||
|
@ -2768,19 +2771,20 @@ statics: {
|
|||
if (!style.hasStroke())
|
||||
return Path.getBounds(segments, closed, style, matrix);
|
||||
var length = segments.length - (closed ? 0 : 1),
|
||||
radius = style.getStrokeWidth() / 2,
|
||||
strokeWidth = style.getStrokeWidth(),
|
||||
strokeRadius = strokeWidth / 2,
|
||||
strokeMatrix = style._getStrokeMatrix(matrix),
|
||||
strokePadding = Path._getStrokePadding(radius, strokeMatrix),
|
||||
strokePadding = Path._getStrokePadding(strokeWidth, strokeMatrix),
|
||||
// Start with normal path bounds with added stroke padding. Then we
|
||||
// only need to look at each segment and handle join / cap / miter.
|
||||
bounds = Path.getBounds(segments, closed, style, matrix,
|
||||
strokePadding),
|
||||
join = style.getStrokeJoin(),
|
||||
cap = style.getStrokeCap(),
|
||||
miterLimit = radius * style.getMiterLimit(),
|
||||
miterLimit = strokeRadius * style.getMiterLimit(),
|
||||
// Create a rectangle of padding size, used for union with bounds
|
||||
// further down
|
||||
joinBounds = new Rectangle(new Size(strokePadding).multiply(2));
|
||||
joinBounds = new Rectangle(new Size(strokePadding));
|
||||
|
||||
// helper function that is passed to _addBevelJoin() and _addSquareCap()
|
||||
// to handle the point transformations. Use strokeMatrix here!
|
||||
|
@ -2804,7 +2808,7 @@ statics: {
|
|||
&& handleIn.isCollinear(handleOut)) {
|
||||
addRound(segment);
|
||||
} else {
|
||||
Path._addBevelJoin(segment, join, radius, miterLimit, add);
|
||||
Path._addBevelJoin(segment, join, strokeRadius, miterLimit, add);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2812,7 +2816,7 @@ statics: {
|
|||
if (cap === 'round') {
|
||||
addRound(segment);
|
||||
} else {
|
||||
Path._addSquareCap(segment, cap, radius, add);
|
||||
Path._addSquareCap(segment, cap, strokeRadius, add);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue