Notify when SkFontMetrics bounds are bogus.

OpenType and many other font formats have the concept of pre-computed
metrics for the union of all glyph bounding boxes. This allows for fast
though course quick rejecting of bounds, since the glyphs themselves may
potentially be quite a bit larger than the EM. With the introduction of
variable fonts OpenType does not vary these bounds, so the bounds are
only valid for the default non-varied font.

As a result the fTop, fBottom, fXMax, and fXMin reported in
SkFontMetrics may be bogus. Since simply always setting them to empty
zeros may be disruptive, provide a way forward for new users to check if
the bounds are valid.

This exposed an issue where SkTextBlobBuilder::TightRunBounds does not
handle SkTextBlob::kRSXform_Positioning, so add a test for that.

Change-Id: I872729e0f16e2a196229f9902addf4b07b461590
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/301455
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/gm/drawatlas.cpp b/gm/drawatlas.cpp
index d447c69..1c70e7e 100644
--- a/gm/drawatlas.cpp
+++ b/gm/drawatlas.cpp
@@ -12,6 +12,7 @@
 #include "include/core/SkColorFilter.h"
 #include "include/core/SkFilterQuality.h"
 #include "include/core/SkFont.h"
+#include "include/core/SkFontMgr.h"
 #include "include/core/SkFontTypes.h"
 #include "include/core/SkImage.h"
 #include "include/core/SkImageInfo.h"
@@ -259,6 +260,44 @@
     canvas->drawTextBlob(blob, offset.fX, offset.fY, paint);
 }
 
+// Exercise xform blob and its tight bounds
+DEF_SIMPLE_GM(blob_rsxform_distortable, canvas, 500, 100) {
+    sk_sp<SkTypeface> typeface;
+    std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("fonts/Distortable.ttf"));
+    if (distortable) {
+        sk_sp<SkFontMgr> fm = SkFontMgr::RefDefault();
+        const SkFontArguments::VariationPosition::Coordinate position[] = {
+            { SkSetFourByteTag('w','g','h','t'), 1.618033988749895f }
+        };
+        SkFontArguments params;
+        params.setVariationDesignPosition({position, SK_ARRAY_COUNT(position)});
+        typeface = fm->makeFromStream(std::move(distortable), params);
+    }
+
+    SkFont font(typeface, 50);
+
+    const char text[] = "abcabcabc";
+    constexpr size_t len = sizeof(text) - 1;
+
+    SkRSXform xforms[len];
+    SkScalar scale = 1;
+    SkScalar x = 0, y = 0;
+    for (size_t i = 0; i < len; ++i) {
+        scale = SkScalarSin(i * SK_ScalarPI / (len-1)) * 0.75f + 0.5f;
+        xforms[i] = SkRSXform::Make(scale, 0, x, y);
+        x += 50 * scale;
+    }
+
+    auto blob = SkTextBlob::MakeFromRSXform(text, len, xforms, font);
+
+    SkPoint offset = { 20, 70 };
+    SkPaint paint;
+    paint.setColor(0xFFCCCCCC);
+    canvas->drawRect(blob->bounds().makeOffset(offset.fX, offset.fY), paint);
+    paint.setColor(SK_ColorBLACK);
+    canvas->drawTextBlob(blob, offset.fX, offset.fY, paint);
+}
+
 static sk_sp<SkVertices> make_vertices(sk_sp<SkImage> image, const SkRect& r,
                                        SkColor color) {
     SkPoint pos[4];