diff options
author | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-23 16:56:56 +0000 |
---|---|---|
committer | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-23 16:56:56 +0000 |
commit | 158618ec62c36b8261e195f04567e09ed76f6534 (patch) | |
tree | 5ccb0c225e60de37ff723ef6571689f71b4be762 | |
parent | c8707d4686fd1740067247f024d1c602c0c051da (diff) |
Removed degenerate quads from zero radius Chrome-style round rects
https://codereview.appspot.com/6737059/
git-svn-id: http://skia.googlecode.com/svn/trunk@6053 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | bench/PathBench.cpp | 38 | ||||
-rw-r--r-- | src/core/SkPath.cpp | 9 | ||||
-rw-r--r-- | tests/PathTest.cpp | 41 |
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" |