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

Unified Diff: src/core/SkPath.cpp

Issue 139483002: change isRect to return true for 3-sided rectangular paths (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: handle overshoot on a incomplete/overcomplete rect Created 6 years, 11 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 | « no previous file | tests/PathTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkPath.cpp
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index af8b1aa56e2ba0a56e86d3d7aa23d190b94fdfbd..2f8eab20b27c2f63da3b78efb0bcaf7f932bc3ae 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -359,10 +359,13 @@ The test fails if:
There's more than four changes of direction.
There's a discontinuity on the line (e.g., a move in the middle)
The line reverses direction.
- The rectangle doesn't complete a cycle.
The path contains a quadratic or cubic.
The path contains fewer than four points.
- The final point isn't equal to the first point.
+ *The rectangle doesn't complete a cycle.
+ *The final point isn't equal to the first point.
+
+ *These last two conditions we relax if we have a 3-edge path that would
+ form a rectangle if it were closed (as we do when we fill a path)
It's OK if the path has:
Several colinear line segments composing a rectangle side.
@@ -374,7 +377,18 @@ must travel in opposite directions.
FIXME: Allow colinear quads and cubics to be treated like lines.
FIXME: If the API passes fill-only, return true if the filled stroke
is a rectangle, though the caller failed to close the path.
+
+ first,last,next direction state-machine:
+ 0x1 is set if the segment is horizontal
+ 0x2 is set if the segment is moving to the right or down
+ thus:
+ two directions are opposites iff (dirA ^ dirB) == 0x2
+ two directions are perpendicular iff (dirA ^ dirB) == 0x1
+
*/
+static int rect_make_dir(SkScalar dx, SkScalar dy) {
+ return ((0 != dx) << 0) | ((dx > 0 || dy > 0) << 1);
+}
bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** ptsPtr,
bool* isClosed, Direction* direction) const {
int corners = 0;
@@ -407,8 +421,7 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
if (left == right && top == bottom) {
break; // single point on side OK
}
- nextDirection = (left != right) << 0 |
- (left < right || top < bottom) << 1;
+ nextDirection = rect_make_dir(right - left, bottom - top);
if (0 == corners) {
firstDirection = nextDirection;
first = last;
@@ -460,6 +473,25 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
}
// Success if 4 corners and first point equals last
bool result = 4 == corners && (first == last || autoClose);
+ if (!result) {
+ // check if we are just an incomplete rectangle, in which case we can
+ // return true, but not claim to be closed.
+ // e.g.
+ // 3 sided rectangle
+ // 4 sided but the last edge is not long enough to reach the start
+ //
+ SkScalar closeX = first.x() - last.x();
+ SkScalar closeY = first.y() - last.y();
+ if (closeX && closeY) {
+ return false; // we're diagonal, abort (can we ever reach this?)
+ }
+ int closeDirection = rect_make_dir(closeX, closeY);
+ // make sure the close-segment doesn't double-back on itself
+ if (3 == corners || (4 == corners && closeDirection == lastDirection)) {
+ result = true;
+ autoClose = false; // we are not closed
+ }
+ }
if (savePts) {
*ptsPtr = savePts;
}
« no previous file with comments | « no previous file | tests/PathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698