Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Unified Diff: src/pathops/SkOpAngle.cpp

Issue 14865019: path ops work in progress (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpAngle.cpp
===================================================================
--- src/pathops/SkOpAngle.cpp (revision 9111)
+++ src/pathops/SkOpAngle.cpp (working copy)
@@ -6,12 +6,10 @@
*/
#include "SkIntersections.h"
#include "SkOpAngle.h"
+#include "SkOpSegment.h"
#include "SkPathOpsCurve.h"
#include "SkTSort.h"
-#if DEBUG_SORT || DEBUG_SORT_SINGLE
-#include "SkOpSegment.h"
-#endif
// FIXME: this is bogus for quads and cubics
// if the quads and cubics' line from end pt to ctrl pt are coincident,
@@ -31,7 +29,8 @@
maybe I could set up LineParameters lazily
*/
-static int simple_compare(double x, double y, double rx, double ry) {
+static int simple_compare(double x, double y, double rx, double ry, double error) {
+ SkASSERT(error);
if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ?
return y < 0;
}
@@ -40,7 +39,7 @@
}
double x_ry = x * ry;
double rx_y = rx * y;
- double cmp = x_ry - rx_y;
+ double cmp = (x_ry - rx_y) * error;
if (!approximately_zero(cmp)) {
return cmp < 0;
}
@@ -51,12 +50,18 @@
return -1;
}
+static double gError[] = {
+ 0, 1, 1.0/2, 1.0/3
+};
+
bool SkOpAngle::operator<(const SkOpAngle& rh) const {
double x = dx();
double y = dy();
double rx = rh.dx();
double ry = rh.dy();
- int simple = simple_compare(x, y, rx, ry);
+ SkPath::Verb verb = fSegment->verb();
+ SkPath::Verb rVerb = rh.fSegment->verb();
+ int simple = simple_compare(x, y, rx, ry, gError[verb] * gError[rVerb]);
if (simple >= 0) {
return simple;
}
@@ -70,16 +75,16 @@
return fSide < rh.fSide;
}
// see if either curve can be lengthened and try the tangent compare again
- if (/* cmp && */ (*fSpans)[fEnd].fOther != rh.fSegment // tangents not absolutely identical
- && (*rh.fSpans)[rh.fEnd].fOther != fSegment) { // and not intersecting
+ if (fSegment->other(fEnd) != rh.fSegment // tangents not absolutely identical
+ && rh.fSegment->other(rh.fEnd) != fSegment) { // and not intersecting
SkOpAngle longer = *this;
SkOpAngle rhLonger = rh;
if (longer.lengthen() | rhLonger.lengthen()) {
return longer < rhLonger;
}
}
- if ((fVerb == SkPath::kLine_Verb && approximately_zero(x) && approximately_zero(y))
- || (rh.fVerb == SkPath::kLine_Verb
+ if ((verb == SkPath::kLine_Verb && approximately_zero(x) && approximately_zero(y))
+ || (rVerb == SkPath::kLine_Verb
&& approximately_zero(rx) && approximately_zero(ry))) {
// See general unsortable comment below. This case can happen when
// one line has a non-zero change in t but no change in x and y.
@@ -87,14 +92,13 @@
rh.fUnsortable = true;
return this < &rh; // even with no solution, return a stable sort
}
- if ((*rh.fSpans)[SkMin32(rh.fStart, rh.fEnd)].fTiny
- || (*fSpans)[SkMin32(fStart, fEnd)].fTiny) {
+ if (fSegment->isTiny(this) || rh.fSegment->isTiny(&rh)) {
fUnsortable = true;
rh.fUnsortable = true;
return this < &rh; // even with no solution, return a stable sort
}
- SkASSERT(fVerb >= SkPath::kQuad_Verb);
- SkASSERT(rh.fVerb >= SkPath::kQuad_Verb);
+ SkASSERT(verb >= SkPath::kQuad_Verb);
+ SkASSERT(rVerb >= SkPath::kQuad_Verb);
// FIXME: until I can think of something better, project a ray from the
// end of the shorter tangent to midway between the end points
// through both curves and use the resulting angle to sort
@@ -110,14 +114,14 @@
do {
useThis = (len < rlen) ^ flip;
const SkDCubic& part = useThis ? fCurvePart : rh.fCurvePart;
- SkPath::Verb partVerb = useThis ? fVerb : rh.fVerb;
+ SkPath::Verb partVerb = useThis ? verb : rVerb;
ray[0] = partVerb == SkPath::kCubic_Verb && part[0].approximatelyEqual(part[1]) ?
part[2] : part[1];
ray[1].fX = (part[0].fX + part[partVerb].fX) / 2;
ray[1].fY = (part[0].fY + part[partVerb].fY) / 2;
SkASSERT(ray[0] != ray[1]);
- roots = (i.*CurveRay[fVerb])(fPts, ray);
- rroots = (ri.*CurveRay[rh.fVerb])(rh.fPts, ray);
+ roots = (i.*CurveRay[verb])(fSegment->pts(), ray);
+ rroots = (ri.*CurveRay[rVerb])(rh.fSegment->pts(), ray);
} while ((roots == 0 || rroots == 0) && (flip ^= true));
if (roots == 0 || rroots == 0) {
// FIXME: we don't have a solution in this case. The interim solution
@@ -167,7 +171,7 @@
#if 0
SkDVector lRay = lLoc - fCurvePart[0];
SkDVector rRay = rLoc - fCurvePart[0];
- int rayDir = simple_compare(lRay.fX, lRay.fY, rRay.fX, rRay.fY);
+ int rayDir = simple_compare(lRay.fX, lRay.fY, rRay.fX, rRay.fY, gError[verb] * gError[rVerb]);
SkASSERT(rayDir >= 0);
if (rayDir < 0) {
fUnsortable = true;
@@ -188,9 +192,13 @@
return leftLessThanRight;
}
+bool SkOpAngle::isHorizontal() const {
+ return dy() == 0 && fSegment->verb() == SkPath::kLine_Verb;
+}
+
bool SkOpAngle::lengthen() {
int newEnd = fEnd;
- if (fStart < fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
+ if (fStart < fEnd ? ++newEnd < fSegment->count() : --newEnd >= 0) {
fEnd = newEnd;
setSpans();
return true;
@@ -203,7 +211,7 @@
return false;
}
int newEnd = fStart;
- if (fStart > fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
+ if (fStart > fEnd ? ++newEnd < fSegment->count() : --newEnd >= 0) {
fEnd = newEnd;
fReversed = true;
setSpans();
@@ -217,9 +225,10 @@
fSegment = segment;
fStart = start;
fEnd = end;
- fPts = orig;
- fVerb = verb;
- fSpans = &spans;
+ if (fSegment->isTiny(this) && (start == 0 || end == fSegment->count() - 1)) {
+ fUnsortable = true;
+ return;
+ }
fReversed = false;
fUnsortable = false;
setSpans();
@@ -227,18 +236,15 @@
void SkOpAngle::setSpans() {
- double startT = (*fSpans)[fStart].fT;
- double endT = (*fSpans)[fEnd].fT;
- switch (fVerb) {
+ fSegment->subDivide(fStart, fEnd, &fCurvePart);
+ switch (fSegment->verb()) {
case SkPath::kLine_Verb: {
- SkDLine l = SkDLine::SubDivide(fPts, startT, endT);
// OPTIMIZATION: for pure line compares, we never need fTangent1.c
- fTangent1.lineEndPoints(l);
+ fTangent1.lineEndPoints(*SkTCast<SkDLine*>(&fCurvePart));
fSide = 0;
} break;
case SkPath::kQuad_Verb: {
SkDQuad& quad = *SkTCast<SkDQuad*>(&fCurvePart);
- quad = SkDQuad::SubDivide(fPts, startT, endT);
fTangent1.quadEndPoints(quad, 0, 1);
if (dx() == 0 && dy() == 0) {
fTangent1.quadEndPoints(quad);
@@ -247,7 +253,6 @@
} break;
case SkPath::kCubic_Verb: {
// int nextC = 2;
- fCurvePart = SkDCubic::SubDivide(fPts, startT, endT);
fTangent1.cubicEndPoints(fCurvePart, 0, 1);
if (dx() == 0 && dy() == 0) {
fTangent1.cubicEndPoints(fCurvePart, 0, 2);
@@ -262,7 +267,10 @@
// }
double testTs[4];
// OPTIMIZATION: keep inflections precomputed with cubic segment?
- int testCount = SkDCubic::FindInflections(fPts, testTs);
+ const SkPoint* pts = fSegment->pts();
+ int testCount = SkDCubic::FindInflections(pts, testTs);
+ double startT = fSegment->t(fStart);
+ double endT = fSegment->t(fEnd);
double limitT = endT;
int index;
for (index = 0; index < testCount; ++index) {
@@ -287,7 +295,7 @@
testT = (testT + testTs[testIndex + 1]) / 2;
}
// OPTIMIZE: could avoid call for t == startT, endT
- SkDPoint pt = dcubic_xy_at_t(fPts, testT);
+ SkDPoint pt = dcubic_xy_at_t(pts, testT);
double testSide = fTangent1.pointDistance(pt);
if (fabs(bestSide) < fabs(testSide)) {
bestSide = testSide;
@@ -306,16 +314,16 @@
int step = fStart < fEnd ? 1 : -1; // OPTIMIZE: worth fStart - fEnd >> 31 type macro?
for (int index = fStart; index != fEnd; index += step) {
#if 1
- const SkOpSpan& thisSpan = (*fSpans)[index];
- const SkOpSpan& nextSpan = (*fSpans)[index + step];
+ const SkOpSpan& thisSpan = fSegment->span(index);
+ const SkOpSpan& nextSpan = fSegment->span(index + step);
if (thisSpan.fTiny || precisely_equal(thisSpan.fT, nextSpan.fT)) {
continue;
}
fUnsortable = step > 0 ? thisSpan.fUnsortableStart : nextSpan.fUnsortableEnd;
#if DEBUG_UNSORTABLE
if (fUnsortable) {
- SkPoint iPt = (*CurvePointAtT[fVerb])(fPts, thisSpan.fT);
- SkPoint ePt = (*CurvePointAtT[fVerb])(fPts, nextSpan.fT);
+ SkPoint iPt = fSegment->xyAtT(index);
+ SkPoint ePt = fSegment->xyAtT(index + step);
SkDebugf("%s unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
index, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
}
@@ -330,8 +338,8 @@
}
#if 1
#if DEBUG_UNSORTABLE
- SkPoint iPt = (*CurvePointAtT[fVerb])(fPts, startT);
- SkPoint ePt = (*CurvePointAtT[fVerb])(fPts, endT);
+ SkPoint iPt = fSegment->xyAtT(fStart);
+ SkPoint ePt = fSegment->xyAtT(fEnd);
SkDebugf("%s all tiny unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
fStart, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
#endif
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698