When filling nested rect path check for empty inner and empty outer rects
authorbsalomon <bsalomon@google.com>
Mon, 2 May 2016 20:22:13 +0000 (13:22 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 2 May 2016 20:22:13 +0000 (13:22 -0700)
BUG=skia:5221
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1936073003

Review-Url: https://codereview.chromium.org/1936073003

src/gpu/GrDrawContext.cpp
src/gpu/batches/GrAAStrokeRectBatch.cpp
src/gpu/batches/GrAAStrokeRectBatch.h
src/gpu/batches/GrRectBatchFactory.cpp
tests/skbug5221.cpp [new file with mode: 0644]

index af04f74fcfd13c5a1aa0cb9b3d9872078ff9ef05..6c80f52bba5c9260e815fed142a708bd1e0708d1 100644 (file)
@@ -822,9 +822,10 @@ void GrDrawContext::drawPath(const GrClip& clip,
             if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
                 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
                     paint.getColor(), viewMatrix, rects));
-
-                GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get(), clip);
-                this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
+                if (batch) {
+                    GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get(), clip);
+                    this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
+                }
                 return;
             }
         }
index e4c40624cf18fdf7e894a942ae71304a175b88ec..cc5440871fbead19c04b231d5a29168dd07890c8 100644 (file)
@@ -580,15 +580,14 @@ static void compute_rects(SkRect* devOutside, SkRect* devOutsideAssist, SkRect*
 
 namespace GrAAStrokeRectBatch {
 
-GrDrawBatch* Create(GrColor color,
-                    const SkMatrix& viewMatrix,
-                    const SkRect& devOutside,
-                    const SkRect& devOutsideAssist,
-                    const SkRect& devInside,
-                    bool miterStroke,
-                    bool degenerate) {
-    AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, miterStroke);
-    batch->append(color, devOutside, devOutsideAssist, devInside, degenerate);
+GrDrawBatch* CreateFillBetweenRects(GrColor color,
+                                    const SkMatrix& viewMatrix,
+                                    const SkRect& devOutside,
+                                    const SkRect& devInside) {
+    SkASSERT(!devOutside.isEmpty())
+    SkASSERT(!devInside.isEmpty())
+    AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, true);
+    batch->append(color, devOutside, devOutside, devInside, false);
     batch->init();
     return batch;
 }
@@ -643,19 +642,21 @@ bool Append(GrBatch* origBatch,
 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) {
     bool miterStroke = random->nextBool();
 
-    // Create mock stroke rect
-    SkRect outside = GrTest::TestRect(random);
-    SkScalar minDim = SkMinScalar(outside.width(), outside.height());
-    SkScalar strokeWidth = minDim * 0.1f;
-    SkRect outsideAssist = outside;
-    outsideAssist.outset(strokeWidth, strokeWidth);
-    SkRect inside = outside;
-    inside.inset(strokeWidth, strokeWidth);
+    // Create either a empty rect or a non-empty rect.
+    SkRect rect = random->nextBool() ? SkRect::MakeXYWH(10, 10, 50, 40) :
+                                       SkRect::MakeXYWH(6, 7, 0, 0);
+    SkScalar minDim = SkMinScalar(rect.width(), rect.height());
+    SkScalar strokeWidth = random->nextUScalar1() * minDim;
 
     GrColor color = GrRandomColor(random);
 
-    return GrAAStrokeRectBatch::Create(color, GrTest::TestMatrix(random), outside, outsideAssist,
-                                       inside, miterStroke, inside.isFinite() && inside.isEmpty());
+    SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
+    rec.setStrokeStyle(strokeWidth);
+    rec.setStrokeParams(SkPaint::kButt_Cap,
+                        miterStroke ? SkPaint::kMiter_Join : SkPaint::kBevel_Join,
+                        1.f);
+    SkMatrix matrix = GrTest::TestMatrixRectStaysRect(random);
+    return GrAAStrokeRectBatch::Create(color, matrix, rect, rec);
 }
 
 #endif
index 4959232bab92cb321bfb3083da15aa746c979605..e0069a1febbef682f3e937f4ceabdc67cece8c24 100644 (file)
@@ -19,13 +19,10 @@ class SkStrokeRec;
 
 namespace GrAAStrokeRectBatch {
 
-GrDrawBatch* Create(GrColor color,
-                    const SkMatrix& viewMatrix,
-                    const SkRect& devOutside,
-                    const SkRect& devOutsideAssist,
-                    const SkRect& devInside,
-                    bool miterStroke,
-                    bool degenerate);
+GrDrawBatch* CreateFillBetweenRects(GrColor color,
+                                    const SkMatrix& viewMatrix,
+                                    const SkRect& devOutside,
+                                    const SkRect& devInside);
 
 GrDrawBatch* Create(GrColor color,
                     const SkMatrix& viewMatrix,
index f144d1b5325ec40a0f4fe25bc9dd2f1ccdc1ce87..d2ba7f4442d7a223507c9063a58ddaef69d038ce 100644 (file)
@@ -22,9 +22,14 @@ GrDrawBatch* CreateAAFillNestedRects(GrColor color,
     SkRect devOutside, devInside;
     viewMatrix.mapRect(&devOutside, rects[0]);
     viewMatrix.mapRect(&devInside, rects[1]);
-
-    return GrAAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutside, devInside, true,
-                                       devInside.isEmpty());
+    if (devInside.isEmpty()) {
+        if (devOutside.isEmpty()) {
+            return nullptr;
+        }
+        return GrAAFillRectBatch::Create(color, viewMatrix, devOutside, devOutside);
+    }
+
+    return GrAAStrokeRectBatch::CreateFillBetweenRects(color, viewMatrix, devOutside, devInside);
 }
 
 };
diff --git a/tests/skbug5221.cpp b/tests/skbug5221.cpp
new file mode 100644 (file)
index 0000000..45847ee
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+#include "SkCanvas.h"
+#include "SkSurface.h"
+
+// This passes by not crashing.
+static void test(SkCanvas* canvas) {
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    canvas->scale(63, 0);
+    static const char kTxt[] = "A";
+    canvas->drawText(kTxt, SK_ARRAY_COUNT(kTxt), 50, 50, paint);
+}
+
+DEF_TEST(skbug5221, r) {
+    sk_sp<SkSurface> surface(SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(256, 256)));
+    test(surface->getCanvas());
+}
+
+#if SK_SUPPORT_GPU
+DEF_GPUTEST_FOR_ALL_CONTEXTS(skbug5221_GPU, r, contextInfo) {
+    sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(contextInfo.fGrContext, SkBudgeted::kYes,
+                                                         SkImageInfo::MakeN32Premul(256, 256), 0,
+                                                         nullptr));
+    test(surface->getCanvas());
+}
+#endif