mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Restructure code a bit for easier reading.
This commit is contained in:
parent
ea87be166e
commit
c989d3ee3f
1 changed files with 244 additions and 239 deletions
123
src/path/Path.js
123
src/path/Path.js
|
@ -1761,53 +1761,10 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
}
|
||||
};
|
||||
}, new function() { // A dedicated scope for the tricky bounds calculations
|
||||
/**
|
||||
* Returns the horizontal and vertical padding that a transformed round
|
||||
* stroke adds to the bounding box, by calculating the dimensions of a
|
||||
* rotated ellipse.
|
||||
*/
|
||||
function getPenPadding(radius, matrix) {
|
||||
if (!matrix)
|
||||
return [radius, radius];
|
||||
// If a matrix is provided, we need to rotate the stroke circle
|
||||
// and calculate the bounding box of the resulting rotated elipse:
|
||||
// Get rotated hor and ver vectors, and determine rotation angle
|
||||
// and elipse values from them:
|
||||
var mx = matrix.createShiftless(),
|
||||
hor = mx.transform(new Point(radius, 0)),
|
||||
ver = mx.transform(new Point(0, radius)),
|
||||
phi = hor.getAngleInRadians(),
|
||||
a = hor.getLength(),
|
||||
b = ver.getLength();
|
||||
// Formula for rotated ellipses:
|
||||
// x = cx + a*cos(t)*cos(phi) - b*sin(t)*sin(phi)
|
||||
// y = cy + b*sin(t)*cos(phi) + a*cos(t)*sin(phi)
|
||||
// Derivates (by Wolfram Alpha):
|
||||
// derivative of x = cx + a*cos(t)*cos(phi) - b*sin(t)*sin(phi)
|
||||
// dx/dt = a sin(t) cos(phi) + b cos(t) sin(phi) = 0
|
||||
// derivative of y = cy + b*sin(t)*cos(phi) + a*cos(t)*sin(phi)
|
||||
// dy/dt = b cos(t) cos(phi) - a sin(t) sin(phi) = 0
|
||||
// this can be simplified to:
|
||||
// tan(t) = -b * tan(phi) / a // x
|
||||
// tan(t) = b * cot(phi) / a // y
|
||||
// Solving for t gives:
|
||||
// t = pi * n - arctan(b tan(phi)) // x
|
||||
// t = pi * n + arctan(b cot(phi)) // y
|
||||
var tx = - Math.atan(b * Math.tan(phi)),
|
||||
ty = + Math.atan(b / Math.tan(phi)),
|
||||
// Due to symetry, we don't need to cycle through pi * n solutions:
|
||||
x = a * Math.cos(tx) * Math.cos(phi)
|
||||
- b * Math.sin(tx) * Math.sin(phi),
|
||||
y = b * Math.sin(ty) * Math.cos(phi)
|
||||
+ a * Math.cos(ty) * Math.sin(phi);
|
||||
return [Math.abs(x), Math.abs(y)];
|
||||
}
|
||||
|
||||
var get = {
|
||||
/**
|
||||
* Returns the bounding rectangle of the item excluding stroke width.
|
||||
*/
|
||||
bounds: function(that, matrix, strokePadding) {
|
||||
function getBounds(that, matrix, strokePadding) {
|
||||
// Code ported and further optimised from:
|
||||
// http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
|
||||
var segments = that._segments,
|
||||
|
@ -1903,16 +1860,58 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
processSegment(first);
|
||||
return Rectangle.create(min[0], min[1],
|
||||
max[0] - min[0], max[1] - min[1]);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the horizontal and vertical padding that a transformed round
|
||||
* stroke adds to the bounding box, by calculating the dimensions of a
|
||||
* rotated ellipse.
|
||||
*/
|
||||
function getPenPadding(radius, matrix) {
|
||||
if (!matrix)
|
||||
return [radius, radius];
|
||||
// If a matrix is provided, we need to rotate the stroke circle
|
||||
// and calculate the bounding box of the resulting rotated elipse:
|
||||
// Get rotated hor and ver vectors, and determine rotation angle
|
||||
// and elipse values from them:
|
||||
var mx = matrix.createShiftless(),
|
||||
hor = mx.transform(new Point(radius, 0)),
|
||||
ver = mx.transform(new Point(0, radius)),
|
||||
phi = hor.getAngleInRadians(),
|
||||
a = hor.getLength(),
|
||||
b = ver.getLength();
|
||||
// Formula for rotated ellipses:
|
||||
// x = cx + a*cos(t)*cos(phi) - b*sin(t)*sin(phi)
|
||||
// y = cy + b*sin(t)*cos(phi) + a*cos(t)*sin(phi)
|
||||
// Derivates (by Wolfram Alpha):
|
||||
// derivative of x = cx + a*cos(t)*cos(phi) - b*sin(t)*sin(phi)
|
||||
// dx/dt = a sin(t) cos(phi) + b cos(t) sin(phi) = 0
|
||||
// derivative of y = cy + b*sin(t)*cos(phi) + a*cos(t)*sin(phi)
|
||||
// dy/dt = b cos(t) cos(phi) - a sin(t) sin(phi) = 0
|
||||
// this can be simplified to:
|
||||
// tan(t) = -b * tan(phi) / a // x
|
||||
// tan(t) = b * cot(phi) / a // y
|
||||
// Solving for t gives:
|
||||
// t = pi * n - arctan(b tan(phi)) // x
|
||||
// t = pi * n + arctan(b cot(phi)) // y
|
||||
var tx = - Math.atan(b * Math.tan(phi)),
|
||||
ty = + Math.atan(b / Math.tan(phi)),
|
||||
// Due to symetry, we don't need to cycle through pi * n solutions:
|
||||
x = a * Math.cos(tx) * Math.cos(phi)
|
||||
- b * Math.sin(tx) * Math.sin(phi),
|
||||
y = b * Math.sin(ty) * Math.cos(phi)
|
||||
+ a * Math.cos(ty) * Math.sin(phi);
|
||||
return [Math.abs(x), Math.abs(y)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bounding rectangle of the item including stroke width.
|
||||
*/
|
||||
strokeBounds: function(that, matrix) {
|
||||
function getStrokeBounds(that, matrix) {
|
||||
// TODO: Should we access this.getStrokeColor, as we do in _transform?
|
||||
// TODO: Find a way to reuse 'bounds' cache instead?
|
||||
if (!that._style._strokeColor || !that._style._strokeWidth)
|
||||
return get.bounds(that, matrix);
|
||||
return getBounds(that, matrix);
|
||||
var width = that.getStrokeWidth(),
|
||||
radius = width / 2,
|
||||
padding = getPenPadding(radius, matrix),
|
||||
|
@ -1924,8 +1923,8 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
segments = that._segments,
|
||||
length = segments.length,
|
||||
// It seems to be compatible with Ai we need to pass pen padding
|
||||
// untransformed to get.bounds
|
||||
bounds = get.bounds(that, matrix, getPenPadding(radius));
|
||||
// untransformed to getBounds
|
||||
bounds = getBounds(that, matrix, getPenPadding(radius));
|
||||
// Create a rectangle of padding size, used for union with bounds
|
||||
// further down
|
||||
var joinBounds = new Rectangle(new Size(padding).multiply(2));
|
||||
|
@ -2005,12 +2004,12 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
addCap(segments[length - 1], cap, 1);
|
||||
}
|
||||
return bounds;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bounding rectangle of the item including handles.
|
||||
*/
|
||||
handleBounds: function(that, matrix, stroke, join) {
|
||||
function getHandleBounds(that, matrix, stroke, join) {
|
||||
var coords = new Array(6),
|
||||
x1 = Infinity,
|
||||
x2 = -x1,
|
||||
|
@ -2037,22 +2036,28 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
}
|
||||
}
|
||||
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rough bounding rectangle of the item that is shure to
|
||||
* include all of the drawing, including stroke width.
|
||||
* Returns the rough bounding rectangle of the item that is shure to include
|
||||
* all of the drawing, including stroke width.
|
||||
*/
|
||||
roughBounds: function(that, matrix) {
|
||||
// Delegate to handleBounds, but pass on radius values for stroke
|
||||
// and joins. Hanlde miter joins specially, by passing the largets
|
||||
// radius possible.
|
||||
function getRoughBounds(that, matrix) {
|
||||
// Delegate to handleBounds, but pass on radius values for stroke and
|
||||
// joins. Hanlde miter joins specially, by passing the largets radius
|
||||
// possible.
|
||||
var width = that.getStrokeWidth();
|
||||
return get.handleBounds(that, matrix, width,
|
||||
return getHandleBounds(that, matrix, width,
|
||||
that.getStrokeJoin() == 'miter'
|
||||
? width * that.getMiterLimit()
|
||||
: width);
|
||||
}
|
||||
|
||||
var get = {
|
||||
bounds: getBounds,
|
||||
strokeBounds: getStrokeBounds,
|
||||
handleBounds: getHandleBounds,
|
||||
roughBounds: getRoughBounds
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
Loading…
Reference in a new issue