test for extents of SkTextBlob drawing

Change-Id: I40e0630e913f4551da5f5fd045beae91dd7cd759
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332740
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/tests/GrTextBlobTest.cpp b/tests/GrTextBlobTest.cpp
index 32c329d..4bb499d 100644
--- a/tests/GrTextBlobTest.cpp
+++ b/tests/GrTextBlobTest.cpp
@@ -66,3 +66,77 @@
     }
     REPORTER_ASSERT(reporter, anyBlack);
 }
+
+// Test extreme positions for all combinations of positions, origins, and translation matrices.
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextBlobMoveAround, 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);
+
+    auto makeBlob = [&](SkPoint delta) {
+        SkTextBlobBuilder builder;
+        const auto& runBuffer = builder.allocRunPos(font, 30, nullptr);
+
+        for (int i = 0; i < 30; i++) {
+            runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
+            runBuffer.points()[i] = SkPoint::Make(SkIntToScalar(i*10) + delta.x(), 50 + delta.y());
+        }
+        return builder.make();
+    };
+
+    auto dContext = ctxInfo.directContext();
+    auto rasterizeBlob = [&](SkTextBlob* blob, SkPoint origin, const SkMatrix& matrix) {
+        SkPaint paint;
+        const SkImageInfo info =
+                SkImageInfo::Make(350, 80, kN32_SkColorType, kPremul_SkAlphaType);
+        auto surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
+        auto canvas = surface->getCanvas();
+        canvas->drawColor(SK_ColorWHITE);
+        canvas->concat(matrix);
+        canvas->drawTextBlob(blob, 10 + origin.x(), 40 + origin.y(), paint);
+        SkBitmap bitmap;
+        bitmap.allocN32Pixels(350, 80);
+        surface->readPixels(bitmap, 0, 0);
+        return bitmap;
+    };
+
+    SkBitmap benchMark;
+    {
+        auto blob = makeBlob({0, 0});
+        benchMark = rasterizeBlob(blob.get(), {0,0}, SkMatrix::I());
+    }
+
+    auto checkBitmap = [&](const SkBitmap& bitmap) {
+        REPORTER_ASSERT(reporter, benchMark.width() == bitmap.width());
+        REPORTER_ASSERT(reporter, benchMark.width() == bitmap.width());
+
+        for (int y = 0; y < benchMark.height(); y++) {
+            for (int x = 0; x < benchMark.width(); x++) {
+                if (benchMark.getColor(x, y) != bitmap.getColor(x, y)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    };
+
+    SkScalar interestingNumbers[] = {-10'000'000, -1'000'000, -1, 0, +1, +1'000'000, +10'000'000};
+    for (auto originX : interestingNumbers) {
+        for (auto originY : interestingNumbers) {
+            for (auto translateX : interestingNumbers) {
+                for (auto translateY : interestingNumbers) {
+                    // Make sure everything adds to zero.
+                    SkScalar deltaPosX = -(originX + translateX);
+                    SkScalar deltaPosY = -(originY + translateY);
+                    auto blob = makeBlob({deltaPosX, deltaPosY});
+                    SkMatrix t = SkMatrix::Translate(translateX, translateY);
+                    auto bitmap = rasterizeBlob(blob.get(), {originX, originY}, t);
+                    REPORTER_ASSERT(reporter, checkBitmap(bitmap));
+                }
+            }
+        }
+    }
+}