mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-08 05:42: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
483
src/path/Path.js
483
src/path/Path.js
|
@ -1761,6 +1761,107 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, new function() { // A dedicated scope for the tricky bounds calculations
|
}, new function() { // A dedicated scope for the tricky bounds calculations
|
||||||
|
/**
|
||||||
|
* Returns the bounding rectangle of the item excluding stroke width.
|
||||||
|
*/
|
||||||
|
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,
|
||||||
|
first = segments[0];
|
||||||
|
if (!first)
|
||||||
|
return null;
|
||||||
|
var coords = new Array(6),
|
||||||
|
prevCoords = new Array(6);
|
||||||
|
// Make coordinates for first segment available in prevCoords.
|
||||||
|
first._transformCoordinates(matrix, prevCoords, false);
|
||||||
|
var min = prevCoords.slice(0, 2),
|
||||||
|
max = min.slice(0), // clone
|
||||||
|
// Add some tolerance for good roots, as t = 0 / 1 are added
|
||||||
|
// seperately anyhow, and we don't want joins to be added with
|
||||||
|
// radiuses in getStrokeBounds()
|
||||||
|
tMin = Numerical.TOLERANCE,
|
||||||
|
tMax = 1 - tMin;
|
||||||
|
function processSegment(segment) {
|
||||||
|
segment._transformCoordinates(matrix, coords, false);
|
||||||
|
|
||||||
|
for (var i = 0; i < 2; i++) {
|
||||||
|
var v0 = prevCoords[i], // prev.point
|
||||||
|
v1 = prevCoords[i + 4], // prev.handleOut
|
||||||
|
v2 = coords[i + 2], // segment.handleIn
|
||||||
|
v3 = coords[i]; // segment.point
|
||||||
|
|
||||||
|
function add(value, t) {
|
||||||
|
var padding = 0;
|
||||||
|
if (value == null) {
|
||||||
|
// Calculate bezier polynomial at t
|
||||||
|
var u = 1 - t;
|
||||||
|
value = u * u * u * v0
|
||||||
|
+ 3 * u * u * t * v1
|
||||||
|
+ 3 * u * t * t * v2
|
||||||
|
+ t * t * t * v3;
|
||||||
|
// Only add strokeWidth to bounds for points which lie
|
||||||
|
// within 0 < t < 1. The corner cases for cap and join
|
||||||
|
// are handled in getStrokeBounds()
|
||||||
|
padding = strokePadding ? strokePadding[i] : 0;
|
||||||
|
}
|
||||||
|
var left = value - padding,
|
||||||
|
right = value + padding;
|
||||||
|
if (left < min[i])
|
||||||
|
min[i] = left;
|
||||||
|
if (right > max[i])
|
||||||
|
max[i] = right;
|
||||||
|
|
||||||
|
}
|
||||||
|
add(v3, null);
|
||||||
|
|
||||||
|
// Calculate derivative of our bezier polynomial, divided by 3.
|
||||||
|
// Dividing by 3 allows for simpler calculations of a, b, c and
|
||||||
|
// leads to the same quadratic roots below.
|
||||||
|
var a = 3 * (v1 - v2) - v0 + v3,
|
||||||
|
b = 2 * (v0 + v2) - 4 * v1,
|
||||||
|
c = v1 - v0;
|
||||||
|
|
||||||
|
// Solve for derivative for quadratic roots. Each good root
|
||||||
|
// (meaning a solution 0 < t < 1) is an extrema in the cubic
|
||||||
|
// polynomial and thus a potential point defining the bounds
|
||||||
|
// TODO: Use tolerance here, just like Numerical.solveQuadratic
|
||||||
|
if (a == 0) {
|
||||||
|
if (b == 0)
|
||||||
|
continue;
|
||||||
|
var t = -c / b;
|
||||||
|
// Test for good root and add to bounds if good (same below)
|
||||||
|
if (tMin < t && t < tMax)
|
||||||
|
add(null, t);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var q = b * b - 4 * a * c;
|
||||||
|
if (q < 0)
|
||||||
|
continue;
|
||||||
|
// TODO: Match this with Numerical.solveQuadratic
|
||||||
|
var sqrt = Math.sqrt(q),
|
||||||
|
f = -0.5 / a,
|
||||||
|
t1 = (b - sqrt) * f,
|
||||||
|
t2 = (b + sqrt) * f;
|
||||||
|
if (tMin < t1 && t1 < tMax)
|
||||||
|
add(null, t1);
|
||||||
|
if (tMin < t2 && t2 < tMax)
|
||||||
|
add(null, t2);
|
||||||
|
}
|
||||||
|
// Swap coordinate buffers
|
||||||
|
var tmp = prevCoords;
|
||||||
|
prevCoords = coords;
|
||||||
|
coords = tmp;
|
||||||
|
}
|
||||||
|
for (var i = 1, l = segments.length; i < l; i++)
|
||||||
|
processSegment(segments[i]);
|
||||||
|
if (that._closed)
|
||||||
|
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
|
* Returns the horizontal and vertical padding that a transformed round
|
||||||
* stroke adds to the bounding box, by calculating the dimensions of a
|
* stroke adds to the bounding box, by calculating the dimensions of a
|
||||||
|
@ -1803,256 +1904,160 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
||||||
return [Math.abs(x), Math.abs(y)];
|
return [Math.abs(x), Math.abs(y)];
|
||||||
}
|
}
|
||||||
|
|
||||||
var get = {
|
/**
|
||||||
/**
|
* Returns the bounding rectangle of the item including stroke width.
|
||||||
* Returns the bounding rectangle of the item excluding stroke width.
|
*/
|
||||||
*/
|
function getStrokeBounds(that, matrix) {
|
||||||
bounds: function(that, matrix, strokePadding) {
|
// TODO: Should we access this.getStrokeColor, as we do in _transform?
|
||||||
// Code ported and further optimised from:
|
// TODO: Find a way to reuse 'bounds' cache instead?
|
||||||
// http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
|
if (!that._style._strokeColor || !that._style._strokeWidth)
|
||||||
var segments = that._segments,
|
return getBounds(that, matrix);
|
||||||
first = segments[0];
|
var width = that.getStrokeWidth(),
|
||||||
if (!first)
|
radius = width / 2,
|
||||||
return null;
|
padding = getPenPadding(radius, matrix),
|
||||||
var coords = new Array(6),
|
join = that.getStrokeJoin(),
|
||||||
prevCoords = new Array(6);
|
cap = that.getStrokeCap(),
|
||||||
// Make coordinates for first segment available in prevCoords.
|
// miter is relative to width. Divide it by 2 since we're
|
||||||
first._transformCoordinates(matrix, prevCoords, false);
|
// measuring half the distance below
|
||||||
var min = prevCoords.slice(0, 2),
|
miter = that.getMiterLimit() * width / 2,
|
||||||
max = min.slice(0), // clone
|
segments = that._segments,
|
||||||
// Add some tolerance for good roots, as t = 0 / 1 are added
|
length = segments.length,
|
||||||
// seperately anyhow, and we don't want joins to be added with
|
// It seems to be compatible with Ai we need to pass pen padding
|
||||||
// radiuses in getStrokeBounds()
|
// untransformed to getBounds
|
||||||
tMin = Numerical.TOLERANCE,
|
bounds = getBounds(that, matrix, getPenPadding(radius));
|
||||||
tMax = 1 - tMin;
|
// Create a rectangle of padding size, used for union with bounds
|
||||||
function processSegment(segment) {
|
// further down
|
||||||
segment._transformCoordinates(matrix, coords, false);
|
var joinBounds = new Rectangle(new Size(padding).multiply(2));
|
||||||
|
|
||||||
for (var i = 0; i < 2; i++) {
|
function add(point) {
|
||||||
var v0 = prevCoords[i], // prev.point
|
bounds = bounds.include(matrix
|
||||||
v1 = prevCoords[i + 4], // prev.handleOut
|
? matrix.transform(point) : point);
|
||||||
v2 = coords[i + 2], // segment.handleIn
|
}
|
||||||
v3 = coords[i]; // segment.point
|
|
||||||
|
|
||||||
function add(value, t) {
|
function addBevelJoin(curve, t) {
|
||||||
var padding = 0;
|
var point = curve.getPoint(t),
|
||||||
if (value == null) {
|
normal = curve.getNormal(t).normalize(radius);
|
||||||
// Calculate bezier polynomial at t
|
add(point.add(normal));
|
||||||
var u = 1 - t;
|
add(point.subtract(normal));
|
||||||
value = u * u * u * v0
|
}
|
||||||
+ 3 * u * u * t * v1
|
|
||||||
+ 3 * u * t * t * v2
|
|
||||||
+ t * t * t * v3;
|
|
||||||
// Only add strokeWidth to bounds for points which lie
|
|
||||||
// within 0 < t < 1. The corner cases for cap and join
|
|
||||||
// are handled in getStrokeBounds()
|
|
||||||
padding = strokePadding ? strokePadding[i] : 0;
|
|
||||||
}
|
|
||||||
var left = value - padding,
|
|
||||||
right = value + padding;
|
|
||||||
if (left < min[i])
|
|
||||||
min[i] = left;
|
|
||||||
if (right > max[i])
|
|
||||||
max[i] = right;
|
|
||||||
|
|
||||||
}
|
function addJoin(segment, join) {
|
||||||
add(v3, null);
|
// When both handles are set in a segment, the join setting is
|
||||||
|
// ignored and round is always used.
|
||||||
// Calculate derivative of our bezier polynomial, divided by 3.
|
if (join === 'round' || !segment._handleIn.isZero()
|
||||||
// Dividing by 3 allows for simpler calculations of a, b, c and
|
&& !segment._handleOut.isZero()) {
|
||||||
// leads to the same quadratic roots below.
|
bounds = bounds.unite(joinBounds.setCenter(matrix
|
||||||
var a = 3 * (v1 - v2) - v0 + v3,
|
? matrix.transform(segment._point) : segment._point));
|
||||||
b = 2 * (v0 + v2) - 4 * v1,
|
} else if (join == 'bevel') {
|
||||||
c = v1 - v0;
|
var curve = segment.getCurve();
|
||||||
|
addBevelJoin(curve, 0);
|
||||||
// Solve for derivative for quadratic roots. Each good root
|
addBevelJoin(curve.getPrevious(), 1);
|
||||||
// (meaning a solution 0 < t < 1) is an extrema in the cubic
|
} else if (join == 'miter') {
|
||||||
// polynomial and thus a potential point defining the bounds
|
var curve2 = segment.getCurve(),
|
||||||
// TODO: Use tolerance here, just like Numerical.solveQuadratic
|
curve1 = curve2.getPrevious(),
|
||||||
if (a == 0) {
|
point = curve2.getPoint(0),
|
||||||
if (b == 0)
|
normal1 = curve1.getNormal(1).normalize(radius),
|
||||||
continue;
|
normal2 = curve2.getNormal(0).normalize(radius),
|
||||||
var t = -c / b;
|
// Intersect the two lines
|
||||||
// Test for good root and add to bounds if good (same below)
|
line1 = new Line(point.subtract(normal1),
|
||||||
if (tMin < t && t < tMax)
|
new Point(-normal1.y, normal1.x)),
|
||||||
add(null, t);
|
line2 = new Line(point.subtract(normal2),
|
||||||
continue;
|
new Point(-normal2.y, normal2.x)),
|
||||||
}
|
corner = line1.intersect(line2);
|
||||||
|
// Now measure the distance from the segment to the
|
||||||
var q = b * b - 4 * a * c;
|
// intersection, which his half of the miter distance
|
||||||
if (q < 0)
|
if (!corner || point.getDistance(corner) > miter) {
|
||||||
continue;
|
addJoin(segment, 'bevel');
|
||||||
// TODO: Match this with Numerical.solveQuadratic
|
} else {
|
||||||
var sqrt = Math.sqrt(q),
|
add(corner);
|
||||||
f = -0.5 / a,
|
|
||||||
t1 = (b - sqrt) * f,
|
|
||||||
t2 = (b + sqrt) * f;
|
|
||||||
if (tMin < t1 && t1 < tMax)
|
|
||||||
add(null, t1);
|
|
||||||
if (tMin < t2 && t2 < tMax)
|
|
||||||
add(null, t2);
|
|
||||||
}
|
}
|
||||||
// Swap coordinate buffers
|
|
||||||
var tmp = prevCoords;
|
|
||||||
prevCoords = coords;
|
|
||||||
coords = tmp;
|
|
||||||
}
|
}
|
||||||
for (var i = 1, l = segments.length; i < l; i++)
|
}
|
||||||
processSegment(segments[i]);
|
|
||||||
if (that._closed)
|
|
||||||
processSegment(first);
|
|
||||||
return Rectangle.create(min[0], min[1],
|
|
||||||
max[0] - min[0], max[1] - min[1]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
function addCap(segment, cap, t) {
|
||||||
* Returns the bounding rectangle of the item including stroke width.
|
switch (cap) {
|
||||||
*/
|
case 'round':
|
||||||
strokeBounds: function(that, matrix) {
|
return addJoin(segment, cap);
|
||||||
// TODO: Should we access this.getStrokeColor, as we do in _transform?
|
case 'butt':
|
||||||
// TODO: Find a way to reuse 'bounds' cache instead?
|
case 'square':
|
||||||
if (!that._style._strokeColor || !that._style._strokeWidth)
|
// Calculate the corner points of butt and square caps
|
||||||
return get.bounds(that, matrix);
|
var curve = segment.getCurve(),
|
||||||
var width = that.getStrokeWidth(),
|
point = curve.getPoint(t),
|
||||||
radius = width / 2,
|
|
||||||
padding = getPenPadding(radius, matrix),
|
|
||||||
join = that.getStrokeJoin(),
|
|
||||||
cap = that.getStrokeCap(),
|
|
||||||
// miter is relative to width. Divide it by 2 since we're
|
|
||||||
// measuring half the distance below
|
|
||||||
miter = that.getMiterLimit() * width / 2,
|
|
||||||
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));
|
|
||||||
// Create a rectangle of padding size, used for union with bounds
|
|
||||||
// further down
|
|
||||||
var joinBounds = new Rectangle(new Size(padding).multiply(2));
|
|
||||||
|
|
||||||
function add(point) {
|
|
||||||
bounds = bounds.include(matrix
|
|
||||||
? matrix.transform(point) : point);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addBevelJoin(curve, t) {
|
|
||||||
var point = curve.getPoint(t),
|
|
||||||
normal = curve.getNormal(t).normalize(radius);
|
normal = curve.getNormal(t).normalize(radius);
|
||||||
|
// For square caps, we need to step away from point in the
|
||||||
|
// direction of the tangent, which is the rotated normal
|
||||||
|
if (cap === 'square')
|
||||||
|
point = point.add(normal.y, -normal.x);
|
||||||
add(point.add(normal));
|
add(point.add(normal));
|
||||||
add(point.subtract(normal));
|
add(point.subtract(normal));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addJoin(segment, join) {
|
|
||||||
// When both handles are set in a segment, the join setting is
|
|
||||||
// ignored and round is always used.
|
|
||||||
if (join === 'round' || !segment._handleIn.isZero()
|
|
||||||
&& !segment._handleOut.isZero()) {
|
|
||||||
bounds = bounds.unite(joinBounds.setCenter(matrix
|
|
||||||
? matrix.transform(segment._point) : segment._point));
|
|
||||||
} else if (join == 'bevel') {
|
|
||||||
var curve = segment.getCurve();
|
|
||||||
addBevelJoin(curve, 0);
|
|
||||||
addBevelJoin(curve.getPrevious(), 1);
|
|
||||||
} else if (join == 'miter') {
|
|
||||||
var curve2 = segment.getCurve(),
|
|
||||||
curve1 = curve2.getPrevious(),
|
|
||||||
point = curve2.getPoint(0),
|
|
||||||
normal1 = curve1.getNormal(1).normalize(radius),
|
|
||||||
normal2 = curve2.getNormal(0).normalize(radius),
|
|
||||||
// Intersect the two lines
|
|
||||||
line1 = new Line(point.subtract(normal1),
|
|
||||||
new Point(-normal1.y, normal1.x)),
|
|
||||||
line2 = new Line(point.subtract(normal2),
|
|
||||||
new Point(-normal2.y, normal2.x)),
|
|
||||||
corner = line1.intersect(line2);
|
|
||||||
// Now measure the distance from the segment to the
|
|
||||||
// intersection, which his half of the miter distance
|
|
||||||
if (!corner || point.getDistance(corner) > miter) {
|
|
||||||
addJoin(segment, 'bevel');
|
|
||||||
} else {
|
|
||||||
add(corner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCap(segment, cap, t) {
|
|
||||||
switch (cap) {
|
|
||||||
case 'round':
|
|
||||||
return addJoin(segment, cap);
|
|
||||||
case 'butt':
|
|
||||||
case 'square':
|
|
||||||
// Calculate the corner points of butt and square caps
|
|
||||||
var curve = segment.getCurve(),
|
|
||||||
point = curve.getPoint(t),
|
|
||||||
normal = curve.getNormal(t).normalize(radius);
|
|
||||||
// For square caps, we need to step away from point in the
|
|
||||||
// direction of the tangent, which is the rotated normal
|
|
||||||
if (cap === 'square')
|
|
||||||
point = point.add(normal.y, -normal.x);
|
|
||||||
add(point.add(normal));
|
|
||||||
add(point.subtract(normal));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 1, l = length - (that._closed ? 0 : 1); i < l; i++) {
|
|
||||||
addJoin(segments[i], join);
|
|
||||||
}
|
|
||||||
if (that._closed) {
|
|
||||||
addJoin(segments[0], join);
|
|
||||||
} else {
|
|
||||||
addCap(segments[0], cap, 0);
|
|
||||||
addCap(segments[length - 1], cap, 1);
|
|
||||||
}
|
|
||||||
return bounds;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bounding rectangle of the item including handles.
|
|
||||||
*/
|
|
||||||
handleBounds: function(that, matrix, stroke, join) {
|
|
||||||
var coords = new Array(6),
|
|
||||||
x1 = Infinity,
|
|
||||||
x2 = -x1,
|
|
||||||
y1 = x1,
|
|
||||||
y2 = x2;
|
|
||||||
stroke = stroke / 2 || 0; // Stroke padding
|
|
||||||
join = join / 2 || 0; // Join padding, for miterLimit
|
|
||||||
for (var i = 0, l = that._segments.length; i < l; i++) {
|
|
||||||
var segment = that._segments[i];
|
|
||||||
segment._transformCoordinates(matrix, coords, false);
|
|
||||||
for (var j = 0; j < 6; j += 2) {
|
|
||||||
// Use different padding for points or handles
|
|
||||||
var padding = j == 0 ? join : stroke,
|
|
||||||
x = coords[j],
|
|
||||||
y = coords[j + 1],
|
|
||||||
xn = x - padding,
|
|
||||||
xx = x + padding,
|
|
||||||
yn = y - padding,
|
|
||||||
yx = y + padding;
|
|
||||||
if (xn < x1) x1 = xn;
|
|
||||||
if (xx > x2) x2 = xx;
|
|
||||||
if (yn < y1) y1 = yn;
|
|
||||||
if (yx > y2) y2 = yx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
var width = that.getStrokeWidth();
|
|
||||||
return get.handleBounds(that, matrix, width,
|
|
||||||
that.getStrokeJoin() == 'miter'
|
|
||||||
? width * that.getMiterLimit()
|
|
||||||
: width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var i = 1, l = length - (that._closed ? 0 : 1); i < l; i++) {
|
||||||
|
addJoin(segments[i], join);
|
||||||
|
}
|
||||||
|
if (that._closed) {
|
||||||
|
addJoin(segments[0], join);
|
||||||
|
} else {
|
||||||
|
addCap(segments[0], cap, 0);
|
||||||
|
addCap(segments[length - 1], cap, 1);
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bounding rectangle of the item including handles.
|
||||||
|
*/
|
||||||
|
function getHandleBounds(that, matrix, stroke, join) {
|
||||||
|
var coords = new Array(6),
|
||||||
|
x1 = Infinity,
|
||||||
|
x2 = -x1,
|
||||||
|
y1 = x1,
|
||||||
|
y2 = x2;
|
||||||
|
stroke = stroke / 2 || 0; // Stroke padding
|
||||||
|
join = join / 2 || 0; // Join padding, for miterLimit
|
||||||
|
for (var i = 0, l = that._segments.length; i < l; i++) {
|
||||||
|
var segment = that._segments[i];
|
||||||
|
segment._transformCoordinates(matrix, coords, false);
|
||||||
|
for (var j = 0; j < 6; j += 2) {
|
||||||
|
// Use different padding for points or handles
|
||||||
|
var padding = j == 0 ? join : stroke,
|
||||||
|
x = coords[j],
|
||||||
|
y = coords[j + 1],
|
||||||
|
xn = x - padding,
|
||||||
|
xx = x + padding,
|
||||||
|
yn = y - padding,
|
||||||
|
yx = y + padding;
|
||||||
|
if (xn < x1) x1 = xn;
|
||||||
|
if (xx > x2) x2 = xx;
|
||||||
|
if (yn < y1) y1 = yn;
|
||||||
|
if (yx > y2) y2 = yx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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 getHandleBounds(that, matrix, width,
|
||||||
|
that.getStrokeJoin() == 'miter'
|
||||||
|
? width * that.getMiterLimit()
|
||||||
|
: width);
|
||||||
|
}
|
||||||
|
|
||||||
|
var get = {
|
||||||
|
bounds: getBounds,
|
||||||
|
strokeBounds: getStrokeBounds,
|
||||||
|
handleBounds: getHandleBounds,
|
||||||
|
roughBounds: getRoughBounds
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue