Reland "SkShaper JSON output with cluster visualization"

This is a reland of 53610832a04157e4edf18347c3e69ddd9d799e3f

Fixes conversion of size_t to int.

Original change's description:
> SkShaper JSON output with cluster visualization
>
> A simple JSON output for diagnostic purposes.
> If the run is not 1:1 code points to glyphs, then
> break the run into clusters.
>
> Change-Id: I06980e0bac2cdca8a69b5b5ba0759a021fd4eb3b
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209740
> Commit-Queue: Herb Derby <herb@google.com>
> Reviewed-by: Julia Lavrova <jlavrova@google.com>

Change-Id: I712293c4820eb23234d64fa019d28bac8b105637
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211986
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/utils/SkShaperJSONWriter.h b/src/utils/SkShaperJSONWriter.h
new file mode 100644
index 0000000..bca0cd1
--- /dev/null
+++ b/src/utils/SkShaperJSONWriter.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkShaperJSONWriter_DEFINED
+#define SkShaperJSONWriter_DEFINED
+
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include "modules/skshaper/include/SkShaper.h"
+#include "src/core/SkSpan.h"
+
+class SkJSONWriter;
+
+class SkShaperJSONWriter final : public SkShaper::RunHandler {
+public:
+    SkShaperJSONWriter(SkJSONWriter* JSONWriter, const char* utf8, size_t size);
+
+    void beginLine() override;
+    void runInfo(const RunInfo& info) override;
+    void commitRunInfo() override;
+
+    Buffer runBuffer(const RunInfo& info) override;
+
+    void commitRunBuffer(const RunInfo& info) override;
+
+    void commitLine() override {}
+
+    using BreakupCluastersCallback =
+            std::function<void(size_t, size_t, uint32_t, uint32_t)>;
+
+    // Break up cluster into a set of ranges for the UTF8, and the glyphIDs.
+    static void BreakupClusters(size_t utf8Begin, size_t utf8End,
+                                SkSpan<const uint32_t> clusters,
+                                const BreakupCluastersCallback& processMToN);
+
+
+    using VisualizeClustersCallback =
+        std::function<void(size_t, SkSpan<const char>, SkSpan<const SkGlyphID>)>;
+
+    // Gather runs of 1:1 into larger runs, and display M:N as single entries.
+    static void VisualizeClusters(const char utf8[],
+                                  size_t utf8Begin, size_t utf8End,
+                                  SkSpan<const SkGlyphID> glyphIDs,
+                                  SkSpan<const uint32_t> clusters,
+                                  const VisualizeClustersCallback& processMToN);
+
+private:
+    void displayMToN(size_t codePointCount,
+                     SkSpan<const char> utf8,
+                     SkSpan<const SkGlyphID> glyphIDs);
+
+    SkJSONWriter* fJSONWriter;
+    std::vector<SkGlyphID> fGlyphs;
+    std::vector<SkPoint> fPositions;
+    std::vector<uint32_t> fClusters;
+
+    std::string fUTF8;
+};
+
+#endif  // SkShaperJSONWriter_DEFINED