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

Unified Diff: src/pathops/SkOpEdgeBuilder.cpp

Issue 14407006: path ops -- handle non-finite numbers (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 8 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/SkOpEdgeBuilder.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpEdgeBuilder.cpp
===================================================================
--- src/pathops/SkOpEdgeBuilder.cpp (revision 8862)
+++ src/pathops/SkOpEdgeBuilder.cpp (working copy)
@@ -28,8 +28,10 @@
preFetch();
}
-void SkOpEdgeBuilder::finish() {
- walk();
+bool SkOpEdgeBuilder::finish() {
+ if (!walk()) {
+ return false;
+ }
complete();
if (fCurrentContour && !fCurrentContour->segments().count()) {
fContours.pop_back();
@@ -51,6 +53,7 @@
&fReducePts[rIndex]);
}
fExtra.reset(); // we're done with this
+ return true;
}
// Note that copying the points here avoids copying the resulting path later.
@@ -74,14 +77,73 @@
return fPathVerbs.count() - 1;
}
-void SkOpEdgeBuilder::walk() {
+static bool is_finite_point(const SkPoint& pt) {
+ // repeat logic in SkRect::isFinite()
+ float accum = 0;
+ accum *= pt.fX;
+ accum *= pt.fY;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || !(accum == accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return accum == accum;
+}
+
+static bool is_finite_line(const SkPoint pts[2]) {
+ // repeat logic in SkRect::isFinite()
+ float accum = 0;
+ accum *= pts[0].fX;
+ accum *= pts[0].fY;
+ accum *= pts[1].fX;
+ accum *= pts[1].fY;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || !(accum == accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return accum == accum;
+}
+
+static bool is_finite_quad(const SkPoint pts[3]) {
+ // repeat logic in SkRect::isFinite()
+ float accum = 0;
+ accum *= pts[0].fX;
+ accum *= pts[0].fY;
+ accum *= pts[1].fX;
+ accum *= pts[1].fY;
+ accum *= pts[2].fX;
+ accum *= pts[2].fY;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || !(accum == accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return accum == accum;
+}
+
+bool SkOpEdgeBuilder::close() {
+ if (fFinalCurveStart && fFinalCurveEnd && *fFinalCurveStart != *fFinalCurveEnd) {
+ *fReducePts.append() = *fFinalCurveStart;
+ *fReducePts.append() = *fFinalCurveEnd;
+ const SkPoint* lineStart = fReducePts.end() - 2;
+ *fExtra.append() = fCurrentContour->addLine(lineStart);
+ }
+ complete();
+ return true;
+}
+
+bool SkOpEdgeBuilder::walk() {
SkPath::Verb reducedVerb;
uint8_t* verbPtr = fPathVerbs.begin();
uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
const SkPoint* pointsPtr = fPathPts.begin();
- const SkPoint* finalCurveStart = NULL;
- const SkPoint* finalCurveEnd = NULL;
SkPath::Verb verb;
+ fFinalCurveStart = NULL;
+ fFinalCurveEnd = NULL;
while ((verb = (SkPath::Verb) *verbPtr) != SkPath::kDone_Verb) {
if (verbPtr == endOfFirstHalf) {
fOperand = true;
@@ -89,64 +151,88 @@
verbPtr++;
switch (verb) {
case SkPath::kMove_Verb:
- complete();
+ if (fCurrentContour) {
+ if (fAllowOpenContours) {
+ complete();
+ } else if (!close()) {
+ return false;
+ }
+ }
if (!fCurrentContour) {
fCurrentContour = fContours.push_back_n(1);
fCurrentContour->setOperand(fOperand);
fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_PathOpsMask);
*fExtra.append() = -1; // start new contour
}
- finalCurveEnd = pointsPtr++;
+ if (!is_finite_point(pointsPtr[0])) {
reed1 2013/04/26 17:49:14 Would it be faster to just ask for the path's boun
caryclark 2013/04/26 19:47:30 Yes indeed. Done and uploaded. On 2013/04/26 17:4
+ return false;
+ }
+ fFinalCurveEnd = pointsPtr++;
continue;
- case SkPath::kLine_Verb:
+ case SkPath::kLine_Verb: {
+ const SkPoint& lineEnd = pointsPtr[0];
+ if (!is_finite_point(lineEnd)) {
+ return false;
+ }
+ const SkPoint& lineStart = pointsPtr[-1];
// skip degenerate points
- if (pointsPtr[-1].fX != pointsPtr[0].fX || pointsPtr[-1].fY != pointsPtr[0].fY) {
- fCurrentContour->addLine(&pointsPtr[-1]);
+ if (lineStart.fX != lineEnd.fX || lineStart.fY != lineEnd.fY) {
+ fCurrentContour->addLine(&lineStart);
}
- break;
- case SkPath::kQuad_Verb:
- reducedVerb = SkReduceOrder::Quad(&pointsPtr[-1], &fReducePts);
+ } break;
+ case SkPath::kQuad_Verb: {
+ if (!is_finite_line(pointsPtr)) {
+ return false;
+ }
+ const SkPoint* quadStart = &pointsPtr[-1];
+ reducedVerb = SkReduceOrder::Quad(quadStart, &fReducePts);
if (reducedVerb == 0) {
break; // skip degenerate points
}
if (reducedVerb == 1) {
- *fExtra.append() =
- fCurrentContour->addLine(fReducePts.end() - 2);
+ const SkPoint* lineStart = fReducePts.end() - 2;
+ *fExtra.append() = fCurrentContour->addLine(lineStart);
break;
}
- fCurrentContour->addQuad(&pointsPtr[-1]);
- break;
- case SkPath::kCubic_Verb:
- reducedVerb = SkReduceOrder::Cubic(&pointsPtr[-1], &fReducePts);
+ fCurrentContour->addQuad(quadStart);
+ } break;
+ case SkPath::kCubic_Verb: {
+ if (!is_finite_quad(pointsPtr)) {
+ return false;
+ }
+ const SkPoint* cubicStart = &pointsPtr[-1];
+ reducedVerb = SkReduceOrder::Cubic(cubicStart, &fReducePts);
if (reducedVerb == 0) {
break; // skip degenerate points
}
if (reducedVerb == 1) {
- *fExtra.append() = fCurrentContour->addLine(fReducePts.end() - 2);
+ const SkPoint* lineStart = fReducePts.end() - 2;
+ *fExtra.append() = fCurrentContour->addLine(lineStart);
break;
}
if (reducedVerb == 2) {
- *fExtra.append() = fCurrentContour->addQuad(fReducePts.end() - 3);
+ const SkPoint* quadStart = fReducePts.end() - 3;
+ *fExtra.append() = fCurrentContour->addQuad(quadStart);
break;
}
- fCurrentContour->addCubic(&pointsPtr[-1]);
- break;
+ fCurrentContour->addCubic(cubicStart);
+ } break;
case SkPath::kClose_Verb:
SkASSERT(fCurrentContour);
- if (finalCurveStart && finalCurveEnd
- && *finalCurveStart != *finalCurveEnd) {
- *fReducePts.append() = *finalCurveStart;
- *fReducePts.append() = *finalCurveEnd;
- *fExtra.append() = fCurrentContour->addLine(fReducePts.end() - 2);
+ if (!close()) {
+ return false;
}
- complete();
continue;
default:
SkDEBUGFAIL("bad verb");
- return;
+ return false;
}
- finalCurveStart = &pointsPtr[verb - 1];
+ fFinalCurveStart = &pointsPtr[verb - 1];
pointsPtr += verb;
SkASSERT(fCurrentContour);
}
+ if (fCurrentContour && !fAllowOpenContours && !close()) {
+ return false;
+ }
+ return true;
}
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698