error on the side of safety for empty blobs

If the blob is empty, then try to regenerate it. Using
this method caused a slowdown in Skia perf, so we
added an extra check to allow some empty blobs through
for perf performance. The perf problem was caused by
SKPs generate empty blobs because of font mismatches.
Flutter has shown that scaling from very small to
normal size is not correctly handled by the existing
check. This CL favors correctness over optimizing empty
text blob and always regenerates empty blobs.

https://github.com/flutter/flutter/issues/64936

Change-Id: Ib18ecb684b0af5cf6dce274b6dc09a9c61b17c77
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/319031
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/gn/tests.gni b/gn/tests.gni
index 1518a2e..47dc7d3 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -119,6 +119,7 @@
   "$_tests/GrSurfaceTest.cpp",
   "$_tests/GrTBlockListTest.cpp",
   "$_tests/GrTestingBackendTextureUploadTest.cpp",
+  "$_tests/GrTextBlobTest.cpp",
   "$_tests/GrTextureMipMapInvalidationTest.cpp",
   "$_tests/GrThreadSafeViewCacheTest.cpp",
   "$_tests/GrUploadPixelsTests.cpp",
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index d1b0848..93e7ee4 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -1112,9 +1112,8 @@
 
 bool GrTextBlob::canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) {
     // A singular matrix will create a GrTextBlob with no SubRuns, but unknown glyphs can
-    // also cause empty runs. If there are no subRuns, and the matrix is complicated, then
-    // regenerate.
-    if (fSubRunList.isEmpty() && !fInitialMatrix.rectStaysRect()) {
+    // also cause empty runs. If there are no subRuns, then regenerate.
+    if (fSubRunList.isEmpty()) {
         return false;
     }
 
diff --git a/tests/GrTextBlobTest.cpp b/tests/GrTextBlobTest.cpp
new file mode 100644
index 0000000..32c329d
--- /dev/null
+++ b/tests/GrTextBlobTest.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkTextBlob.h"
+#include "src/core/SkSurfacePriv.h"
+#include "tests/Test.h"
+#include "tools/ToolUtils.h"
+
+SkBitmap rasterize_blob(SkTextBlob* blob,
+                        const SkPaint& paint,
+                        GrRecordingContext* rContext,
+                        const SkMatrix& matrix) {
+    const SkImageInfo info =
+            SkImageInfo::Make(500, 500, kN32_SkColorType, kPremul_SkAlphaType);
+    auto surface = SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
+    auto canvas = surface->getCanvas();
+    canvas->drawColor(SK_ColorWHITE);
+    canvas->concat(matrix);
+    canvas->drawTextBlob(blob, 10, 250, paint);
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(500, 500);
+    surface->readPixels(bitmap, 0, 0);
+    return bitmap;
+}
+
+bool check_for_black(const SkBitmap& bm) {
+    for (int y = 0; y < bm.height(); y++) {
+        for (int x = 0; x < bm.width(); x++) {
+            if (bm.getColor(x, y) == SK_ColorBLACK) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextBlobScaleAnimation, reporter, ctxInfo) {
+    auto tf = ToolUtils::create_portable_typeface("Mono", SkFontStyle());
+    SkFont font{tf};
+    font.setHinting(SkFontHinting::kNormal);
+    font.setSize(12);
+    font.setEdging(SkFont::Edging::kAntiAlias);
+    font.setSubpixel(true);
+
+    SkTextBlobBuilder builder;
+    const auto& runBuffer = builder.allocRunPosH(font, 30, 0, nullptr);
+
+    for (int i = 0; i < 30; i++) {
+        runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
+        runBuffer.pos[i] = SkIntToScalar(i);
+    }
+    auto blob = builder.make();
+
+    auto dContext = ctxInfo.directContext();
+    bool anyBlack = false;
+    for (int n = -13; n < 5; n++) {
+        SkMatrix m = SkMatrix::Scale(std::exp2(n), std::exp2(n));
+        auto bm = rasterize_blob(blob.get(), SkPaint(), dContext, m);
+        anyBlack |= check_for_black(bm);
+    }
+    REPORTER_ASSERT(reporter, anyBlack);
+}