Fix misdetection of rectangles in SkPath::IsSimpleClosedRect.
BUG=chromium:630369 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2175923002 Review-Url: https://codereview.chromium.org/2175923002
This commit is contained in:
parent
5fa38fa287
commit
057ae8a15d
@ -3292,81 +3292,52 @@ bool SkPathPriv::IsSimpleClosedRect(const SkPath& path, SkRect* rect, SkPath::Di
|
||||
if (rectPts[0] != rectPts[4]) {
|
||||
return false;
|
||||
}
|
||||
int verticalCnt = 0;
|
||||
int horizontalCnt = 0;
|
||||
// dirs are 0 - right, 1 - down, 2 - left, 3 - up.
|
||||
int firstDir = 0;
|
||||
int secondDir = 0;
|
||||
SkRect tempRect;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int sameCnt = 0;
|
||||
if (rectPts[i].fX == rectPts[i + 1].fX) {
|
||||
verticalCnt += 1;
|
||||
sameCnt = 1;
|
||||
if (0 == i) {
|
||||
if (rectPts[1].fY > rectPts[0].fY) {
|
||||
firstDir = 1;
|
||||
tempRect.fTop = rectPts[0].fY;
|
||||
tempRect.fBottom = rectPts[1].fY;
|
||||
} else {
|
||||
firstDir = 3;
|
||||
tempRect.fTop = rectPts[1].fY;
|
||||
tempRect.fBottom = rectPts[0].fY;
|
||||
}
|
||||
} else if (1 == i) {
|
||||
if (rectPts[2].fY > rectPts[1].fY) {
|
||||
secondDir = 1;
|
||||
tempRect.fTop = rectPts[1].fY;
|
||||
tempRect.fBottom = rectPts[2].fY;
|
||||
} else {
|
||||
secondDir = 3;
|
||||
tempRect.fTop = rectPts[2].fY;
|
||||
tempRect.fBottom = rectPts[1].fY;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rectPts[i].fY == rectPts[i + 1].fY) {
|
||||
horizontalCnt += 1;
|
||||
sameCnt += 1;
|
||||
if (0 == i) {
|
||||
if (rectPts[1].fX > rectPts[0].fX) {
|
||||
firstDir = 0;
|
||||
tempRect.fLeft = rectPts[0].fX;
|
||||
tempRect.fRight = rectPts[1].fX;
|
||||
} else {
|
||||
firstDir = 2;
|
||||
tempRect.fLeft = rectPts[1].fX;
|
||||
tempRect.fRight = rectPts[0].fX;
|
||||
}
|
||||
} else if (1 == i) {
|
||||
if (rectPts[2].fX > rectPts[1].fX) {
|
||||
secondDir = 0;
|
||||
tempRect.fLeft = rectPts[1].fX;
|
||||
tempRect.fRight = rectPts[2].fX;
|
||||
} else {
|
||||
secondDir = 2;
|
||||
tempRect.fLeft = rectPts[2].fX;
|
||||
tempRect.fRight = rectPts[1].fX;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sameCnt != 1) {
|
||||
// Check for two cases of rectangles: pts 0 and 3 form a vertical edge or a horizontal edge (
|
||||
// and pts 1 and 2 the opposite vertical or horizontal edge).
|
||||
bool vec03IsVertical;
|
||||
if (rectPts[0].fX == rectPts[3].fX && rectPts[1].fX == rectPts[2].fX &&
|
||||
rectPts[0].fY == rectPts[1].fY && rectPts[3].fY == rectPts[2].fY) {
|
||||
// Make sure it has non-zero width and height
|
||||
if (rectPts[0].fX == rectPts[1].fX || rectPts[0].fY == rectPts[3].fY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (2 != horizontalCnt || 2 != verticalCnt) {
|
||||
vec03IsVertical = true;
|
||||
} else if (rectPts[0].fY == rectPts[3].fY && rectPts[1].fY == rectPts[2].fY &&
|
||||
rectPts[0].fX == rectPts[1].fX && rectPts[3].fX == rectPts[2].fX) {
|
||||
// Make sure it has non-zero width and height
|
||||
if (rectPts[0].fY == rectPts[1].fY || rectPts[0].fX == rectPts[3].fX) {
|
||||
return false;
|
||||
}
|
||||
vec03IsVertical = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
// low bit indicates a vertical dir
|
||||
SkASSERT((firstDir ^ secondDir) & 0b1);
|
||||
if (((firstDir + 1) & 0b11) == secondDir) {
|
||||
*direction = SkPath::kCW_Direction;
|
||||
*start = firstDir;
|
||||
} else {
|
||||
SkASSERT(((secondDir + 1) & 0b11) == firstDir);
|
||||
*direction = SkPath::kCCW_Direction;
|
||||
*start = secondDir;
|
||||
// Set sortFlags so that it has the low bit set if pt index 0 is on right edge and second bit
|
||||
// set if it is on the bottom edge.
|
||||
unsigned sortFlags =
|
||||
((rectPts[0].fX < rectPts[2].fX) ? 0b00 : 0b01) |
|
||||
((rectPts[0].fY < rectPts[2].fY) ? 0b00 : 0b10);
|
||||
switch (sortFlags) {
|
||||
case 0b00:
|
||||
rect->set(rectPts[0].fX, rectPts[0].fY, rectPts[2].fX, rectPts[2].fY);
|
||||
*direction = vec03IsVertical ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
|
||||
*start = 0;
|
||||
break;
|
||||
case 0b01:
|
||||
rect->set(rectPts[2].fX, rectPts[0].fY, rectPts[0].fX, rectPts[2].fY);
|
||||
*direction = vec03IsVertical ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
|
||||
*start = 1;
|
||||
break;
|
||||
case 0b10:
|
||||
rect->set(rectPts[0].fX, rectPts[2].fY, rectPts[2].fX, rectPts[0].fY);
|
||||
*direction = vec03IsVertical ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
|
||||
*start = 3;
|
||||
break;
|
||||
case 0b11:
|
||||
rect->set(rectPts[2].fX, rectPts[2].fY, rectPts[0].fX, rectPts[0].fY);
|
||||
*direction = vec03IsVertical ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
|
||||
*start = 2;
|
||||
break;
|
||||
}
|
||||
*rect = tempRect;
|
||||
return true;
|
||||
}
|
||||
|
@ -2094,6 +2094,42 @@ static void test_is_simple_closed_rect(skiatest::Reporter* reporter) {
|
||||
check_simple_closed_rect(reporter, path2, testRect, swapDir, kYSwapStarts[start]);
|
||||
}
|
||||
}
|
||||
// down, up, left, close
|
||||
path.reset();
|
||||
path.moveTo(1, 1);
|
||||
path.lineTo(1, 2);
|
||||
path.lineTo(1, 1);
|
||||
path.lineTo(0, 1);
|
||||
SkRect rect;
|
||||
SkPath::Direction dir;
|
||||
unsigned start;
|
||||
path.close();
|
||||
REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleClosedRect(path, &rect, &dir, &start));
|
||||
// right, left, up, close
|
||||
path.reset();
|
||||
path.moveTo(1, 1);
|
||||
path.lineTo(2, 1);
|
||||
path.lineTo(1, 1);
|
||||
path.lineTo(1, 0);
|
||||
path.close();
|
||||
REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleClosedRect(path, &rect, &dir, &start));
|
||||
// parallelogram with horizontal edges
|
||||
path.reset();
|
||||
path.moveTo(1, 0);
|
||||
path.lineTo(3, 0);
|
||||
path.lineTo(2, 1);
|
||||
path.lineTo(0, 1);
|
||||
path.close();
|
||||
REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleClosedRect(path, &rect, &dir, &start));
|
||||
// parallelogram with vertical edges
|
||||
path.reset();
|
||||
path.moveTo(0, 1);
|
||||
path.lineTo(0, 3);
|
||||
path.lineTo(1, 2);
|
||||
path.lineTo(1, 0);
|
||||
path.close();
|
||||
REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleClosedRect(path, &rect, &dir, &start));
|
||||
|
||||
}
|
||||
|
||||
static void test_isNestedFillRects(skiatest::Reporter* reporter) {
|
||||
|
Loading…
Reference in New Issue
Block a user