check for nonfinites in rrects

BUG=457128

Review URL: https://codereview.chromium.org/913743002
This commit is contained in:
reed 2015-02-10 08:46:22 -08:00 committed by Commit bot
parent 88f0a99fd4
commit 454fa71cc3
3 changed files with 38 additions and 6 deletions

View File

@ -128,7 +128,23 @@ static inline bool SkScalarIsFinite(SkScalar x) {
// 0 * NaN --> NaN
SkScalar prod = x * 0;
// At this point, prod will either be NaN or 0
// Therefore we can return (prod == prod) or (0 == prod).
return !SkScalarIsNaN(prod);
}
static inline bool SkScalarsAreFinite(SkScalar a, SkScalar b) {
SkScalar prod = 0;
prod *= a;
prod *= b;
// At this point, prod will either be NaN or 0
return !SkScalarIsNaN(prod);
}
static inline bool SkScalarsAreFinite(const SkScalar array[], int count) {
SkScalar prod = 0;
for (int i = 0; i < count; ++i) {
prod *= array[i];
}
// At this point, prod will either be NaN or 0
return !SkScalarIsNaN(prod);
}

View File

@ -11,11 +11,14 @@
///////////////////////////////////////////////////////////////////////////////
void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
if (rect.isEmpty()) {
if (rect.isEmpty() || !rect.isFinite()) {
this->setEmpty();
return;
}
if (!SkScalarsAreFinite(xRad, yRad)) {
xRad = yRad = 0; // devolve into a simple rect
}
if (xRad <= 0 || yRad <= 0) {
// all corners are square in this case
this->setRect(rect);
@ -45,11 +48,17 @@ void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
void SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
SkScalar rightRad, SkScalar bottomRad) {
if (rect.isEmpty()) {
if (rect.isEmpty() || !rect.isFinite()) {
this->setEmpty();
return;
}
const SkScalar array[4] = { leftRad, topRad, rightRad, bottomRad };
if (!SkScalarsAreFinite(array, 4)) {
this->setRect(rect); // devolve into a simple rect
return;
}
leftRad = SkMaxScalar(leftRad, 0);
topRad = SkMaxScalar(topRad, 0);
rightRad = SkMaxScalar(rightRad, 0);
@ -125,11 +134,16 @@ static SkScalar clamp_radius_sub(SkScalar rad, SkScalar min, SkScalar max) {
}
void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) {
if (rect.isEmpty()) {
if (rect.isEmpty() || !rect.isFinite()) {
this->setEmpty();
return;
}
if (!SkScalarsAreFinite(&radii[0].fX, 8)) {
this->setRect(rect); // devolve into a simple rect
return;
}
fRect = rect;
memcpy(fRadii, radii, sizeof(fRadii));

View File

@ -3113,10 +3113,12 @@ static void test_rrect(skiatest::Reporter* reporter) {
rr.setRectRadii(largeR, radii);
p.addRRect(rr);
test_rrect_convexity_is_unknown(reporter, &p, SkPath::kCW_Direction);
// we check for non-finites
SkRect infR = {0, 0, SK_ScalarMax, SK_ScalarInfinity};
rr.setRectRadii(infR, radii);
p.addRRect(rr);
test_rrect_convexity_is_unknown(reporter, &p, SkPath::kCW_Direction);
REPORTER_ASSERT(reporter, rr.isEmpty());
SkRect tinyR = {0, 0, 1e-9f, 1e-9f};
p.addRoundRect(tinyR, 5e-11f, 5e-11f);
test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);