Improve handling of straight closing curves in open path checks.

This commit is contained in:
Jürg Lehni 2016-07-27 19:09:42 +02:00
parent e643338422
commit aee9a3190d
4 changed files with 32 additions and 39 deletions

View file

@ -251,11 +251,11 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
* @bean * @bean
* @type Number * @type Number
*/ */
getArea: function(_closed) { getArea: function() {
var children = this._children, var children = this._children,
area = 0; area = 0;
for (var i = 0, l = children.length; i < l; i++) for (var i = 0, l = children.length; i < l; i++)
area += children[i].getArea(_closed); area += children[i].getArea();
return area; return area;
}, },

View file

@ -577,17 +577,21 @@ var Curve = Base.extend(/** @lends Curve# */{
}, },
statics: /** @lends Curve */{ statics: /** @lends Curve */{
getValues: function(segment1, segment2, matrix) { getValues: function(segment1, segment2, matrix, straight) {
var p1 = segment1._point, var p1 = segment1._point,
h1 = segment1._handleOut, h1 = segment1._handleOut,
h2 = segment2._handleIn, h2 = segment2._handleIn,
p2 = segment2._point, p2 = segment2._point,
values = [ x1 = p1.x, y1 = p1.y,
p1._x, p1._y, x2 = p2.x, y2 = p2.y,
p1._x + h1._x, p1._y + h1._y, values = straight
p2._x + h2._x, p2._y + h2._y, ? [ x1, y1, x1, y1, x2, y2, x2, y2 ]
p2._x, p2._y : [
]; x1, y1,
x1 + h1._x, y1 + h1._y,
x2 + h2._x, y2 + h2._y,
x2, y2
];
if (matrix) if (matrix)
matrix._transformCoordinates(values, values, 4); matrix._transformCoordinates(values, values, 4);
return values; return values;

View file

@ -828,29 +828,23 @@ var Path = PathItem.extend(/** @lends Path# */{
* @bean * @bean
* @type Number * @type Number
*/ */
getArea: function(_closed) { getArea: function() {
// Cache the area for the open path, and the the final curve separately, var area = this._area;
// so open and closed area can be returned at almost no additional cost. if (area == null) {
var closed = Base.pick(_closed, this._closed),
cached = this._area;
if (cached == null) {
var segments = this._segments, var segments = this._segments,
sum = 0, closed = this._closed;
close = 0; area = 0;
for (var i = 0, l = segments.length; i < l; i++) { for (var i = 0, l = segments.length; i < l; i++) {
var next = i + 1, var last = i + 1 === l;
last = next >= l, area += Curve.getArea(Curve.getValues(
area = Curve.getArea(Curve.getValues( segments[i], segments[last ? 0 : i + 1],
segments[i], segments[last ? 0 : i + 1])); // If this is the last curve and the last is not closed,
if (last) { // connect with a straight curve and ignore the handles.
close = area; null, last && !closed));
} else {
sum += area;
}
} }
cached = this._area = [sum, close]; this._area = area;
} }
return cached[0] + (closed ? cached[1] : 0); return area;
}, },
/** /**

View file

@ -95,7 +95,7 @@ PathItem.inject(new function() {
// Give both paths the same orientation except for subtraction // Give both paths the same orientation except for subtraction
// and exclusion, where we need them at opposite orientation. // and exclusion, where we need them at opposite orientation.
if (_path2 && (operator.subtract || operator.exclude) if (_path2 && (operator.subtract || operator.exclude)
^ (_path2.isClockwise(true) ^ _path1.isClockwise(true))) ^ (_path2.isClockwise() ^ _path1.isClockwise()))
_path2.reverse(); _path2.reverse();
// Split curves at crossings on both paths. Note that for self- // Split curves at crossings on both paths. Note that for self-
// intersection, path2 is null and getIntersections() handles it. // intersection, path2 is null and getIntersections() handles it.
@ -510,15 +510,10 @@ PathItem.inject(new function() {
// - `true`: Connect with a curve that takes the segment handles // - `true`: Connect with a curve that takes the segment handles
// into account, just like how closed paths behave. // into account, just like how closed paths behave.
if (!path._closed) { if (!path._closed) {
var s1 = path.getLastCurve().getSegment2(), vClose = Curve.getValues(
s2 = curve.getSegment1(), path.getLastCurve().getSegment2(),
p1 = s1._point, curve.getSegment1(),
p2 = s2._point, null, !closed);
x1 = p1._x, y1 = p1._y,
x2 = p2._x, y2 = p2._y;
vClose = closed
? Curve.getValues(s1, s2)
: [x1, y1, x1, y1, x2, y2, x2, y2];
// This closing curve is a potential candidate for the last // This closing curve is a potential candidate for the last
// non-horizontal curve. // non-horizontal curve.
if (vClose[io] !== vClose[io + 6]) { if (vClose[io] !== vClose[io + 6]) {
@ -850,7 +845,7 @@ PathItem.inject(new function() {
// close to each other that they are considered the same // close to each other that they are considered the same
// location, but the winding calculation still produces a valid // location, but the winding calculation still produces a valid
// number due to their slight differences producing a tiny area. // number due to their slight differences producing a tiny area.
var area = path.getArea(true); var area = path.getArea();
if (abs(area) >= /*#=*/Numerical.GEOMETRIC_EPSILON) { if (abs(area) >= /*#=*/Numerical.GEOMETRIC_EPSILON) {
// This path wasn't finished and is hence invalid. // This path wasn't finished and is hence invalid.
// Report the error to the console for the time being. // Report the error to the console for the time being.