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
* @type Number
*/
getArea: function(_closed) {
getArea: function() {
var children = this._children,
area = 0;
for (var i = 0, l = children.length; i < l; i++)
area += children[i].getArea(_closed);
area += children[i].getArea();
return area;
},

View file

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

View file

@ -828,29 +828,23 @@ var Path = PathItem.extend(/** @lends Path# */{
* @bean
* @type Number
*/
getArea: function(_closed) {
// Cache the area for the open path, and the the final curve separately,
// so open and closed area can be returned at almost no additional cost.
var closed = Base.pick(_closed, this._closed),
cached = this._area;
if (cached == null) {
getArea: function() {
var area = this._area;
if (area == null) {
var segments = this._segments,
sum = 0,
close = 0;
closed = this._closed;
area = 0;
for (var i = 0, l = segments.length; i < l; i++) {
var next = i + 1,
last = next >= l,
area = Curve.getArea(Curve.getValues(
segments[i], segments[last ? 0 : i + 1]));
if (last) {
close = area;
} else {
sum += area;
}
var last = i + 1 === l;
area += Curve.getArea(Curve.getValues(
segments[i], segments[last ? 0 : i + 1],
// If this is the last curve and the last is not closed,
// connect with a straight curve and ignore the handles.
null, last && !closed));
}
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
// and exclusion, where we need them at opposite orientation.
if (_path2 && (operator.subtract || operator.exclude)
^ (_path2.isClockwise(true) ^ _path1.isClockwise(true)))
^ (_path2.isClockwise() ^ _path1.isClockwise()))
_path2.reverse();
// Split curves at crossings on both paths. Note that for self-
// 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
// into account, just like how closed paths behave.
if (!path._closed) {
var s1 = path.getLastCurve().getSegment2(),
s2 = curve.getSegment1(),
p1 = s1._point,
p2 = s2._point,
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];
vClose = Curve.getValues(
path.getLastCurve().getSegment2(),
curve.getSegment1(),
null, !closed);
// This closing curve is a potential candidate for the last
// non-horizontal curve.
if (vClose[io] !== vClose[io + 6]) {
@ -850,7 +845,7 @@ PathItem.inject(new function() {
// close to each other that they are considered the same
// location, but the winding calculation still produces a valid
// 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) {
// This path wasn't finished and is hence invalid.
// Report the error to the console for the time being.