aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops
diff options
context:
space:
mode:
Diffstat (limited to 'src/pathops')
-rw-r--r--src/pathops/SkOpAngle.cpp69
-rw-r--r--src/pathops/SkOpAngle.h1
2 files changed, 69 insertions, 1 deletions
diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp
index c07e8cc73f..194260f658 100644
--- a/src/pathops/SkOpAngle.cpp
+++ b/src/pathops/SkOpAngle.cpp
@@ -135,7 +135,7 @@ bool SkOpAngle::after(SkOpAngle* test) {
}
int trOrder;
if (rh->fSectorMask & fSectorMask) {
- trOrder = (int) orderable(rh);
+ trOrder = (int) this->orderable(rh);
} else {
int trGap = (rh->fSectorStart - fSectorStart + 32) & 0x1f;
trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1;
@@ -167,6 +167,41 @@ bool SkOpAngle::after(SkOpAngle* test) {
// SkASSERT(lrOpposite != trOpposite);
return COMPARE_RESULT(10, lrOpposite);
}
+ // if a pair couldn't be ordered, there's not enough information to determine the sort
+ if (fUnorderable || lh->fUnorderable || rh->fUnorderable) {
+ // limit to lines; should work with curves, but wait for a failing test to verify
+ if (!fPart.isCurve() && !lh->fPart.isCurve() && !rh->fPart.isCurve()) {
+ // see if original raw data is orderable
+ // if two share a point, check if third has both points in same half plane
+ int ltShare = lh->fOriginalCurvePart[0] == fOriginalCurvePart[0];
+ int lrShare = lh->fOriginalCurvePart[0] == rh->fOriginalCurvePart[0];
+ int trShare = fOriginalCurvePart[0] == rh->fOriginalCurvePart[0];
+ // if only one pair are the same, the third point touches neither of the pair
+ if (ltShare + lrShare + trShare == 1) {
+ if (ltShare) {
+ int lrOOrder = lh->allOnOriginalSide(rh);
+ int trOOrder = rh->allOnOriginalSide(this);
+ // result must be 0 and 1 or 1 and 0 to be valid
+ if ((lrOOrder ^ trOOrder) == 1) {
+ return trOOrder;
+ }
+ } else if (lrShare) {
+ int ltOOrder = lh->allOnOriginalSide(this);
+ int trOOrder = rh->allOnOriginalSide(this);
+ if ((ltOOrder ^ trOOrder) == 1) {
+ return ltOOrder;
+ }
+ } else {
+ SkASSERT(trShare);
+ int ltOOrder = this->allOnOriginalSide(lh);
+ int lrOOrder = rh->allOnOriginalSide(lh);
+ if ((ltOOrder ^ lrOOrder) == 1) {
+ return lrOOrder;
+ }
+ }
+ }
+ }
+ }
if (lrOrder < 0) {
if (ltOrder < 0) {
return COMPARE_RESULT(11, trOrder);
@@ -214,6 +249,38 @@ int SkOpAngle::allOnOneSide(const SkOpAngle* test) {
return -1;
}
+// experiment works only with lines for now
+int SkOpAngle::allOnOriginalSide(const SkOpAngle* test) {
+ SkASSERT(!fPart.isCurve());
+ SkASSERT(!test->fPart.isCurve());
+ SkDPoint origin = fOriginalCurvePart[0];
+ SkDVector line = fOriginalCurvePart[1] - origin;
+ double dots[2];
+ double crosses[2];
+ const SkDCurve& testCurve = test->fOriginalCurvePart;
+ for (int index = 0; index < 2; ++index) {
+ SkDVector testLine = testCurve[index] - origin;
+ double xy1 = line.fX * testLine.fY;
+ double xy2 = line.fY * testLine.fX;
+ dots[index] = line.fX * testLine.fX + line.fY * testLine.fY;
+ crosses[index] = AlmostBequalUlps(xy1, xy2) ? 0 : xy1 - xy2;
+ }
+ if (crosses[0] * crosses[1] < 0) {
+ return -1;
+ }
+ if (crosses[0]) {
+ return crosses[0] < 0;
+ }
+ if (crosses[1]) {
+ return crosses[1] < 0;
+ }
+ if ((!dots[0] && dots[1] < 0) || (dots[0] < 0 && !dots[1])) {
+ return 2; // 180 degrees apart
+ }
+ fUnorderable = true;
+ return -1;
+}
+
// To sort the angles, all curves are translated to have the same starting point.
// If the curve's control point in its original position is on one side of a compared line,
// and translated is on the opposite side, reverse the previously computed order.
diff --git a/src/pathops/SkOpAngle.h b/src/pathops/SkOpAngle.h
index d8615c3229..3d7a8950eb 100644
--- a/src/pathops/SkOpAngle.h
+++ b/src/pathops/SkOpAngle.h
@@ -99,6 +99,7 @@ private:
bool after(SkOpAngle* test);
void alignmentSameSide(const SkOpAngle* test, int* order) const;
int allOnOneSide(const SkOpAngle* test);
+ int allOnOriginalSide(const SkOpAngle* test);
bool checkCrossesZero() const;
bool checkParallel(SkOpAngle* );
bool computeSector();