Fix bounds of checking if a radii are too long for a side.

BUG=skia:4692,skia:4413
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1617763003

Review URL: https://codereview.chromium.org/1617763003
This commit is contained in:
herb 2016-01-22 08:34:35 -08:00 committed by Commit bot
parent 5286f0222c
commit 5e0883cf57
3 changed files with 46 additions and 37 deletions

View File

@ -19,23 +19,22 @@ DEF_FUZZ(ScaleToSides, fuzz) {
float radius1 = fuzz->nextF(),
radius2 = fuzz->nextF(),
width = fuzz->nextF();
SkDebugf("%g %g %g\n", radius1, radius2, width);
if (!std::isfinite(radius1) ||
!std::isfinite(radius2) ||
!std::isfinite(width))
!std::isfinite(width) ||
radius1 <= 0.0f ||
radius2 <= 0.0f ||
width <= 0.0f)
{
fuzz->signalBoring();
}
if (width <= 0.0f) {
fuzz->signalBoring();
}
double scale = (double)width / ((double)radius1 + (double)radius2);
if (scale >= 1.0) {
if (scale >= 1.0 || scale <= 0.0) {
fuzz->signalBoring();
}
SkDebugf("%g %g %g %g\n", radius1, radius2, width, scale);
ScaleToSides::AdjustRadii(width, scale, &radius1, &radius2);
// TODO(mtklein): add fuzz->keepResult()

View File

@ -14,7 +14,7 @@
class ScaleToSides {
public:
// This code assumes that a and b fit in in a float, and therefore the resulting smaller value
// This code assumes that a and b fit in a float, and therefore the resulting smaller value
// of a and b will fit in a float. The side of the rectangle may be larger than a float.
// Scale must be less than or equal to the ratio limit / (*a + *b).
// This code assumes that NaN and Inf are never passed in.
@ -24,8 +24,7 @@ public:
*a = (float)((double)*a * scale);
*b = (float)((double)*b * scale);
// This check is conservative. (double)*a + (double)*b >= (double)(*a + *b)
if ((double)*a + (double)*b > limit) {
if (*a + *b > limit) {
float* minRadius = a;
float* maxRadius = b;
@ -48,14 +47,16 @@ public:
// reduced by one ULP to be less than limit - newMinRadius.
// Note: nexttowardf is a c99 call and should be std::nexttoward, but this is not
// implemented in the ARM compiler.
if ((double)newMaxRadius + (double)newMinRadius > limit) {
if (newMaxRadius + newMinRadius > limit) {
newMaxRadius = nexttowardf(newMaxRadius, 0.0);
}
*maxRadius = newMaxRadius;
}
SkASSERTF(*a >= 0.0f && *b >= 0.0f, "a: %g, b: %g", *a, *b);
SkASSERTF((*a + *b) <= limit, "limit: %g, a: %g, b: %g", limit, *a, *b);
SkASSERTF(*a >= 0.0f && *b >= 0.0f, "a: %g, b: %g, limit: %g, scale: %g", *a, *b, limit,
scale);
SkASSERTF(*a + *b <= limit, "\nlimit: %.10f, a: %.10f, b: %.10f, scale: %.20f",
limit, *a, *b, scale);
}
};
#endif // ScaleToSides_DEFINED

View File

@ -7,23 +7,27 @@
#include "SkScaleToSides.h"
#include <cfloat>
#include <algorithm>
#include "Test.h"
DEF_TEST(ScaleToSides, reporter) {
float interestingValues[] = {
0.0f,
0.5f,
1.0f,
2.0f,
3.0f,
33.0f,
33554430.0f,
33554431.0f,
33554464.0f,
333333332.0f,
333333333.0f,
333333334.0f,
double interestingValues[] = {
// From skp bitbucket
111.60000228881836,
55.800003051757813,
0.99999996581812677920,
0.0,
0.5,
1.0,
2.0,
3.0,
33.0,
33554430.0,
33554431.0,
33554464.0,
333333332.0,
333333333.0,
333333334.0,
FLT_MAX,
FLT_EPSILON,
FLT_MIN
@ -31,16 +35,21 @@ DEF_TEST(ScaleToSides, reporter) {
int numInterestingValues = (int)SK_ARRAY_COUNT(interestingValues);
for (int i = 0; i < numInterestingValues; i++) {
for (int j = 0; j < numInterestingValues; j++) {
for (int k = 0; k < numInterestingValues; k++) {
float radius1 = interestingValues[i];
float radius2 = interestingValues[j];
float width = interestingValues[k];
if (width > 0.0f) {
double scale = (double)width / ((double)radius1 + (double)radius2);
if (scale < 1.0) {
ScaleToSides::AdjustRadii(width, scale, &radius1, &radius2);
for (int s = 0; s <= numInterestingValues; s++) {
for (int i = 0; i < numInterestingValues; i++) {
for (int j = 0; j < numInterestingValues; j++) {
for (int k = 0; k < numInterestingValues; k++) {
float radius1 = (float)interestingValues[i];
float radius2 = (float)interestingValues[j];
double width = interestingValues[k];
double scale = width / ((double)radius1 + (double)radius2);
if (width > 0.0) {
if (s != 0) {
scale = std::min(scale, interestingValues[s-1]);
}
if (scale < 1.0 && scale > 0.0) {
ScaleToSides::AdjustRadii(width, scale, &radius1, &radius2);
}
}
}
}