yet another path is rect exploit

This one accumulates the othershoot when all four sides
have the same direction, and the final side when closed
should cause the overshoot to be ignored.

Docs-Preview: https://skia.org/?cl=121787
Bug: 824145,skia:7792
Change-Id: I71ea0fcdd0f03a4fcac224b57220c65c321112f6
Reviewed-on: https://skia-review.googlesource.com/121787
Commit-Queue: Cary Clark <caryclark@skia.org>
Commit-Queue: Robert Phillips <robertphillips@google.com>
Auto-Submit: Cary Clark <caryclark@skia.org>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Cary Clark 2018-04-17 09:30:14 -04:00 committed by Skia Commit-Bot
parent 8954d097c3
commit a7651567ca
3 changed files with 26 additions and 1 deletions

View File

@ -547,4 +547,15 @@ DEF_SIMPLE_GM(bug7792, canvas, 600, 800) {
path.moveTo(75, 75);
path.close();
canvas->drawPath(path, p);
// from skbug.com/7792#c31
canvas->translate(200, 0);
path.reset();
path.moveTo(75, 75);
path.lineTo(150, 75);
path.lineTo(150, 150);
path.lineTo(75, 150);
path.lineTo(75, 10);
path.moveTo(75, 75);
path.close();
canvas->drawPath(path, p);
}

View File

@ -453,6 +453,7 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
SkPoint lineStart; // used to construct line from previous point
const SkPoint* firstPt = nullptr; // first point in the rect (last of first moves)
const SkPoint* lastPt = nullptr; // last point in the rect (last of lines or first if closed)
const SkPoint* lastCountedPt = nullptr; // point creating 3rd corner
const SkPoint* pts = *ptsPtr;
const SkPoint* savePts = nullptr; // used to allow caller to iterate through a pair of rects
lineStart.set(0, 0);
@ -473,6 +474,9 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
accumulatingRect = false;
case kLine_Verb: {
if (accumulatingRect) {
lastCountedPt = pts;
}
if (kClose_Verb != verb) {
lastPt = pts;
}
SkPoint lineEnd = kClose_Verb == verb ? *firstPt : *pts++;
@ -512,6 +516,7 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
if ((directions[0] ^ directions[2]) != 2) {
return false;
}
accumulatingRect = false;
} else if (corners == 4) {
if ((directions[1] ^ directions[3]) != 2) {
return false;
@ -574,7 +579,7 @@ addMissingClose:
*ptsPtr = savePts;
}
if (result && rect) {
ptrdiff_t count = lastPt - firstPt + 1;
ptrdiff_t count = lastCountedPt - firstPt + 1;
rect->set(firstPt, (int) count);
}
if (result && isClosed) {

View File

@ -5003,4 +5003,13 @@ DEF_TEST(Path_isRect, reporter) {
SkPoint points29[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 250}, {75, 75} };
path = makePath2(points29, verbs29, SK_ARRAY_COUNT(verbs29));
REPORTER_ASSERT(reporter, !path.isRect(&rect, nullptr, nullptr));
// isolated from skbug.com/7792#c31
SkPath::Verb verbs31[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb,
SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb,
SkPath::kClose_Verb };
SkPoint points31[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 10}, {75, 75} };
path = makePath2(points31, verbs31, SK_ARRAY_COUNT(verbs31));
REPORTER_ASSERT(reporter, path.isRect(&rect, nullptr, nullptr));
compare.set(&points31[0], 4);
REPORTER_ASSERT(reporter, rect == compare);
}