Restructure code a bit for easier reading.

This commit is contained in:
Jürg Lehni 2011-11-24 15:18:57 +01:00
parent ea87be166e
commit c989d3ee3f

View file

@ -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 {