aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-23 16:56:56 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-23 16:56:56 +0000
commit158618ec62c36b8261e195f04567e09ed76f6534 (patch)
tree5ccb0c225e60de37ff723ef6571689f71b4be762
parentc8707d4686fd1740067247f024d1c602c0c051da (diff)
Removed degenerate quads from zero radius Chrome-style round rects
-rw-r--r--bench/PathBench.cpp38
-rw-r--r--src/core/SkPath.cpp9
-rw-r--r--tests/PathTest.cpp41
3 files changed, 74 insertions, 14 deletions
diff --git a/bench/PathBench.cpp b/bench/PathBench.cpp
index ac324a9d32..be16c75e5f 100644
--- a/bench/PathBench.cpp
+++ b/bench/PathBench.cpp
@@ -671,8 +671,10 @@ private:
typedef SkBenchmark INHERITED;
};
-// Chrome creates its own round rects with each corner possibly being different
-// Note: PathTest::test_arb_round_rect_is_convex performs almost exactly
+// Chrome creates its own round rects with each corner possibly being different.
+// In its "zero radius" incarnation it creates degenerate round rects.
+// Note: PathTest::test_arb_round_rect_is_convex and
+// test_arb_zero_rad_round_rect_is_rect perform almost exactly
// the same test (but with no drawing)
class ArbRoundRectBench : public SkBenchmark {
protected:
@@ -682,8 +684,12 @@ protected:
N = SkBENCHLOOP(100)
};
public:
- ArbRoundRectBench(void* param) : INHERITED(param) {
- fName.printf("arbroundrect");
+ ArbRoundRectBench(void* param, bool zeroRad) : INHERITED(param), fZeroRad(zeroRad) {
+ if (zeroRad) {
+ fName.printf("zeroradroundrect");
+ } else {
+ fName.printf("arbroundrect");
+ }
}
protected:
@@ -728,6 +734,7 @@ protected:
add_corner_arc(path, r, xCorner, yCorner, 0);
add_corner_arc(path, r, xCorner, yCorner, 90);
add_corner_arc(path, r, xCorner, yCorner, 180);
+ path->close();
#ifdef SK_REDEFINE_ROOT2OVER2_TO_MAKE_ARCTOS_CONVEX
SkASSERT(path->isConvex());
@@ -743,24 +750,32 @@ protected:
paint.setColor(0xff000000 | rand.nextU());
paint.setAntiAlias(true);
- SkScalar radius = rand.nextUScalar1() * 30;
- if (radius < SK_Scalar1) {
+ SkScalar size = rand.nextUScalar1() * 30;
+ if (size < SK_Scalar1) {
continue;
}
r.fLeft = rand.nextUScalar1() * 300;
r.fTop = rand.nextUScalar1() * 300;
- r.fRight = r.fLeft + 2 * radius;
- r.fBottom = r.fTop + 2 * radius;
+ r.fRight = r.fLeft + 2 * size;
+ r.fBottom = r.fTop + 2 * size;
SkPath temp;
- make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
+ if (fZeroRad) {
+ make_arb_round_rect(&temp, r, 0, 0);
+
+ SkASSERT(temp.isRect(NULL));
+ } else {
+ make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
+ }
canvas->drawPath(temp, paint);
}
}
private:
+ bool fZeroRad; // should 0 radius rounds rects be tested?
+
typedef SkBenchmark INHERITED;
};
@@ -863,5 +878,8 @@ static BenchRegistry gRegReverseTo(FactReverseTo);
static SkBenchmark* CirclesTest(void* p) { return new CirclesBench(p); }
static BenchRegistry gRegCirclesTest(CirclesTest);
-static SkBenchmark* ArbRoundRectTest(void* p) { return new ArbRoundRectBench(p); }
+static SkBenchmark* ArbRoundRectTest(void* p) { return new ArbRoundRectBench(p, false); }
static BenchRegistry gRegArbRoundRectTest(ArbRoundRectTest);
+
+static SkBenchmark* ZeroRadRoundRectTest(void* p) { return new ArbRoundRectBench(p, true); }
+static BenchRegistry gRegZeroRadRoundRectTest(ZeroRadRoundRectTest);
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 9723db929a..b8df23b671 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -1030,6 +1030,15 @@ static int build_arc_points(const SkRect& oval, SkScalar startAngle,
// bounding box (and break the circle special case).
pts[0].set(oval.fRight, oval.centerY());
return 1;
+ } else if (0 == oval.width() && 0 == oval.height()) {
+ // Chrome will sometimes create 0 radius round rects. Having degenerate
+ // quad segments in the path prevents the path from being recognized as
+ // a rect.
+ // TODO: optimizing the case where only one of width or height is zero
+ // should also be considered. This case, however, doesn't seem to be
+ // as common as the single point case.
+ pts[0].set(oval.fRight, oval.fTop);
+ return 1;
}
SkVector start, stop;
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index 819d3b3e87..cfad5d664e 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -114,6 +114,7 @@ static void make_arb_round_rect(SkPath* path, const SkRect& r,
add_corner_arc(path, r, xCorner, yCorner, 0);
add_corner_arc(path, r, xCorner, yCorner, 90);
add_corner_arc(path, r, xCorner, yCorner, 180);
+ path->close();
}
// Chrome creates its own round rects with each corner possibly being different.
@@ -126,14 +127,14 @@ static void test_arb_round_rect_is_convex(skiatest::Reporter* reporter) {
for (int i = 0; i < 5000; ++i) {
- SkScalar radius = rand.nextUScalar1() * 30;
- if (radius < SK_Scalar1) {
+ SkScalar size = rand.nextUScalar1() * 30;
+ if (size < SK_Scalar1) {
continue;
}
r.fLeft = rand.nextUScalar1() * 300;
r.fTop = rand.nextUScalar1() * 300;
- r.fRight = r.fLeft + 2 * radius;
- r.fBottom = r.fTop + 2 * radius;
+ r.fRight = r.fLeft + 2 * size;
+ r.fBottom = r.fTop + 2 * size;
SkPath temp;
@@ -145,6 +146,37 @@ static void test_arb_round_rect_is_convex(skiatest::Reporter* reporter) {
}
}
+// Chrome will sometimes create a 0 radius round rect. The degenerate
+// quads prevent the path from being converted to a rect
+// Note: PathBench::ArbRoundRectBench performs almost exactly
+// the same test (but with drawing)
+static void test_arb_zero_rad_round_rect_is_rect(skiatest::Reporter* reporter) {
+ SkRandom rand;
+ SkRect r;
+
+ for (int i = 0; i < 5000; ++i) {
+
+ SkScalar size = rand.nextUScalar1() * 30;
+ if (size < SK_Scalar1) {
+ continue;
+ }
+ r.fLeft = rand.nextUScalar1() * 300;
+ r.fTop = rand.nextUScalar1() * 300;
+ r.fRight = r.fLeft + 2 * size;
+ r.fBottom = r.fTop + 2 * size;
+
+ SkPath temp;
+
+ make_arb_round_rect(&temp, r, 0, 0);
+
+#ifdef SK_REDEFINE_ROOT2OVER2_TO_MAKE_ARCTOS_CONVEX
+ SkRect result;
+ REPORTER_ASSERT(reporter, temp.isRect(&result));
+ REPORTER_ASSERT(reporter, r == result);
+#endif
+ }
+}
+
static void test_rect_isfinite(skiatest::Reporter* reporter) {
const SkScalar inf = SK_ScalarInfinity;
const SkScalar nan = SK_ScalarNaN;
@@ -1685,6 +1717,7 @@ static void TestPath(skiatest::Reporter* reporter) {
test_isfinite_after_transform(reporter);
test_tricky_cubic(reporter);
test_arb_round_rect_is_convex(reporter);
+ test_arb_zero_rad_round_rect_is_rect(reporter);
}
#include "TestClassDef.h"