mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-19 06:00:56 -05:00
Correctly handle #strokeScaling when calculating Path and Shape bounds.
Relates to #697
This commit is contained in:
parent
40551fcacf
commit
43a6c57cd6
4 changed files with 44 additions and 22 deletions
|
@ -788,6 +788,12 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
match = key.match(/^internal(.*)$/),
|
||||
internalGetter = match ? 'get' + match[1] : null;
|
||||
this[getter] = function(_matrix) {
|
||||
// TODO: If we're getting stroke based bounds (strokeBounds,
|
||||
// roughBounds, internalRoughBounds), and the object does not have
|
||||
// a stroke, fall back to the bounds getter without the stroke:
|
||||
// strokeBounds -> bounds
|
||||
// roughBounds -> handleBounds
|
||||
// internalRoughBounds -> internalHandleBounds
|
||||
var boundsGetter = this._boundsGetter,
|
||||
// Allow subclasses to override _boundsGetter if they use the
|
||||
// same calculations for multiple type of bounds.
|
||||
|
|
|
@ -277,18 +277,17 @@ var Shape = Item.extend(/** @lends Shape# */{
|
|||
|
||||
_getBounds: function(getter, matrix) {
|
||||
var rect = new Rectangle(this._size).setCenter(0, 0),
|
||||
strokeWidth = getter === 'getStrokeBounds' && this.hasStroke()
|
||||
&& this.getStrokeWidth(),
|
||||
scaling = strokeWidth && this.getStrokeScaling();
|
||||
style = this._style,
|
||||
strokeWidth = style.hasStroke() &&
|
||||
/^getStrokeBounds$|^get.*RoughBounds$/.test(getter) &&
|
||||
style.getStrokeWidth(),
|
||||
strokePadding = strokeWidth && Path._getStrokePadding(
|
||||
strokeWidth, style._getStrokeMatrix(matrix));
|
||||
// If we're getting the strokeBounds, include the stroke width before
|
||||
// or after transforming the rect, based on strokeScaling.
|
||||
if (strokeWidth && scaling)
|
||||
rect = rect.expand(strokeWidth);
|
||||
if (matrix)
|
||||
rect = matrix._transformBounds(rect);
|
||||
if (strokeWidth && !scaling)
|
||||
rect = rect.expand(strokeWidth);
|
||||
return rect;
|
||||
return strokePadding ? rect.expand(strokePadding) : rect;
|
||||
}
|
||||
},
|
||||
new function() { // Scope for _contains() and _hitTestSelf() code.
|
||||
|
|
|
@ -2765,28 +2765,34 @@ statics: {
|
|||
* @private
|
||||
*/
|
||||
getStrokeBounds: function(segments, closed, style, matrix) {
|
||||
// TODO: Find a way to reuse 'bounds' cache instead?
|
||||
if (!style.hasStroke())
|
||||
return Path.getBounds(segments, closed, style, matrix);
|
||||
var length = segments.length - (closed ? 0 : 1),
|
||||
radius = style.getStrokeWidth() / 2,
|
||||
padding = Path._getStrokePadding(radius, matrix),
|
||||
bounds = Path.getBounds(segments, closed, style, matrix, padding),
|
||||
strokeMatrix = style._getStrokeMatrix(matrix),
|
||||
strokePadding = Path._getStrokePadding(radius, 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();
|
||||
// Create a rectangle of padding size, used for union with bounds
|
||||
// further down
|
||||
var joinBounds = new Rectangle(new Size(padding).multiply(2));
|
||||
miterLimit = radius * style.getMiterLimit(),
|
||||
// Create a rectangle of padding size, used for union with bounds
|
||||
// further down
|
||||
joinBounds = new Rectangle(new Size(strokePadding).multiply(2));
|
||||
|
||||
// helper function that is passed to _addBevelJoin() and _addSquareCap()
|
||||
// to handle the point transformations. Use strokeMatrix here!
|
||||
function add(point) {
|
||||
bounds = bounds.include(matrix
|
||||
? matrix._transformPoint(point, point) : point);
|
||||
bounds = bounds.include(strokeMatrix
|
||||
? strokeMatrix._transformPoint(point, point) : point);
|
||||
}
|
||||
|
||||
function addRound(segment) {
|
||||
var point = segment._point;
|
||||
bounds = bounds.unite(joinBounds.setCenter(matrix
|
||||
? matrix._transformPoint(segment._point) : segment._point));
|
||||
? matrix._transformPoint(point) : point));
|
||||
}
|
||||
|
||||
function addJoin(segment, join) {
|
||||
|
@ -2967,9 +2973,9 @@ statics: {
|
|||
// Delegate to handleBounds, but pass on radius values for stroke and
|
||||
// joins. Handle miter joins specially, by passing the largest radius
|
||||
// possible.
|
||||
// TODO: Take strokeScaling into account here too!
|
||||
var strokeRadius = style.hasStroke() ? style.getStrokeWidth() / 2 : 0,
|
||||
joinRadius = strokeRadius;
|
||||
joinRadius = strokeRadius,
|
||||
strokeMatrix = strokeRadius && style._getStrokeMatrix(matrix);
|
||||
if (strokeRadius > 0) {
|
||||
if (style.getStrokeJoin() === 'miter')
|
||||
joinRadius = strokeRadius * style.getMiterLimit();
|
||||
|
@ -2977,7 +2983,7 @@ statics: {
|
|||
joinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));
|
||||
}
|
||||
return Path.getHandleBounds(segments, closed, style, matrix,
|
||||
Path._getStrokePadding(strokeRadius, matrix),
|
||||
Path._getStrokePadding(joinRadius, matrix));
|
||||
Path._getStrokePadding(strokeRadius, strokeMatrix),
|
||||
Path._getStrokePadding(joinRadius, strokeMatrix));
|
||||
}
|
||||
}});
|
||||
|
|
|
@ -305,6 +305,17 @@ var Style = Base.extend(new function() {
|
|||
return this._project._view;
|
||||
},
|
||||
|
||||
/**
|
||||
* Private helper that returns to correct matrix to use to transform stroke
|
||||
* relatd geometries when calculating bounds: the item's matrix if
|
||||
* {@link #strokeScaling} is `true`, otherwise the shiftless, inverted view
|
||||
* matrix.
|
||||
*/
|
||||
_getStrokeMatrix: function(matrix) {
|
||||
return this.getStrokeScaling() ? matrix
|
||||
: this.getView()._matrix._shiftless().invert();
|
||||
},
|
||||
|
||||
// Overrides
|
||||
|
||||
getFontStyle: function() {
|
||||
|
|
Loading…
Reference in a new issue