Hack up SkShaper to pass additional callback info

- rename LineHandler -> RunHandler (since it gets called per run)
- pass additionl run info:

  * line index
  * cumulative advance
  * ascent/descent/leading

Bug: skia:
Change-Id: Ie848e5a35243088b99989c73fdec44c6a1bdd051
Reviewed-on: https://skia-review.googlesource.com/c/183300
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/skshaper/include/SkShaper.h b/modules/skshaper/include/SkShaper.h
index 391e583..aa37d5c 100644
--- a/modules/skshaper/include/SkShaper.h
+++ b/modules/skshaper/include/SkShaper.h
@@ -27,9 +27,17 @@
     SkShaper(sk_sp<SkTypeface> face);
     ~SkShaper();
 
-    class LineHandler {
+    class RunHandler {
     public:
-        virtual ~LineHandler() = default;
+        virtual ~RunHandler() = default;
+
+        struct RunInfo {
+            size_t   fLineIndex;
+            SkVector fAdvance;
+            SkScalar fAscent,
+                     fDescent,
+                     fLeading;
+        };
 
         struct Buffer {
             SkGlyphID* glyphs;    // required
@@ -38,11 +46,12 @@
             uint32_t*  clusters;  // optional
         };
 
-        virtual Buffer newLineBuffer(const SkFont&, int glyphCount, int utf8textCount) = 0;
+        virtual Buffer newRunBuffer(const RunInfo&, const SkFont&, int glyphCount,
+                                    int utf8textCount) = 0;
     };
 
     bool good() const;
-    SkPoint shape(LineHandler* handler,
+    SkPoint shape(RunHandler* handler,
                   const SkFont& srcPaint,
                   const char* utf8text,
                   size_t textBytes,
@@ -61,11 +70,11 @@
 /**
  * Helper for shaping text directly into a SkTextBlob.
  */
-class SkTextBlobBuilderLineHandler final : public SkShaper::LineHandler {
+class SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler {
 public:
     sk_sp<SkTextBlob> makeBlob();
 
-    SkShaper::LineHandler::Buffer newLineBuffer(const SkFont&, int, int) override;
+    SkShaper::RunHandler::Buffer newRunBuffer(const RunInfo&, const SkFont&, int, int) override;
 
 private:
     SkTextBlobBuilder fBuilder;
diff --git a/modules/skshaper/src/SkShaper.cpp b/modules/skshaper/src/SkShaper.cpp
index 78f973c..e08b7b3 100644
--- a/modules/skshaper/src/SkShaper.cpp
+++ b/modules/skshaper/src/SkShaper.cpp
@@ -9,9 +9,10 @@
 
 #include "SkTextBlobPriv.h"
 
-SkShaper::LineHandler::Buffer SkTextBlobBuilderLineHandler::newLineBuffer(const SkFont& font,
-                                                                          int glyphCount,
-                                                                          int textCount) {
+SkShaper::RunHandler::Buffer SkTextBlobBuilderRunHandler::newRunBuffer(const RunInfo&,
+                                                                       const SkFont& font,
+                                                                       int glyphCount,
+                                                                       int textCount) {
     const auto& runBuffer = SkTextBlobBuilderPriv::AllocRunTextPos(&fBuilder, font, glyphCount,
                                                                    textCount, SkString());
     return { runBuffer.glyphs,
@@ -20,6 +21,6 @@
              runBuffer.clusters };
 }
 
-sk_sp<SkTextBlob> SkTextBlobBuilderLineHandler::makeBlob() {
+sk_sp<SkTextBlob> SkTextBlobBuilderRunHandler::makeBlob() {
     return fBuilder.make();
 }
diff --git a/modules/skshaper/src/SkShaper_harfbuzz.cpp b/modules/skshaper/src/SkShaper_harfbuzz.cpp
index beb5923..6560a6c 100644
--- a/modules/skshaper/src/SkShaper_harfbuzz.cpp
+++ b/modules/skshaper/src/SkShaper_harfbuzz.cpp
@@ -407,17 +407,19 @@
     SkFont fFont;
     UBiDiLevel fLevel;
     std::unique_ptr<ShapedGlyph[]> fGlyphs;
+    SkVector fAdvance = { 0, 0 };
 };
 
 static constexpr bool is_LTR(UBiDiLevel level) {
     return (level & 1) == 0;
 }
 
-static void append(SkShaper::LineHandler* handler, const ShapedRun& run, int start, int end,
+static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
+                   const ShapedRun& run, int start, int end,
                    SkPoint* p) {
     unsigned len = end - start;
 
-    const auto buffer = handler->newLineBuffer(run.fFont, len, run.fUtf8End - run.fUtf8Start);
+    const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8End - run.fUtf8Start);
     SkASSERT(buffer.glyphs);
     SkASSERT(buffer.positions);
 
@@ -522,7 +524,7 @@
            fImpl->fBreakIterator;
 }
 
-SkPoint SkShaper::shape(LineHandler* handler,
+SkPoint SkShaper::shape(RunHandler* handler,
                         const SkFont& srcPaint,
                         const char* utf8,
                         size_t utf8Bytes,
@@ -647,6 +649,7 @@
         hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
         double textSizeY = run.fFont.getSize() / scaleY;
         double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
+        SkVector runAdvance = { 0, 0 };
         for (unsigned i = 0; i < len; i++) {
             ShapedGlyph& glyph = run.fGlyphs[i];
             glyph.fID = info[i].codepoint;
@@ -658,7 +661,10 @@
             glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
             //info->mask safe_to_break;
             glyph.fMustLineBreakBefore = false;
+
+            runAdvance += glyph.fAdvance;
         }
+        run.fAdvance = runAdvance;
 
         int32_t clusterOffset = utf8Start - utf8;
         uint32_t previousCluster = 0xFFFFFFFF;
@@ -729,6 +735,7 @@
     SkScalar maxDescent = 0;
     SkScalar maxLeading = 0;
     int previousRunIndex = -1;
+    size_t lineIndex = 0;
     while (glyphIterator.current()) {
         int runIndex = glyphIterator.fRunIndex;
         int glyphIndex = glyphIterator.fGlyphIndex;
@@ -767,7 +774,16 @@
             int endGlyphIndex = (logicalIndex == runIndex)
                               ? glyphIndex + 1
                               : runs[logicalIndex].fNumGlyphs;
-            append(handler, runs[logicalIndex], startGlyphIndex, endGlyphIndex, &currentPoint);
+
+            const auto& run = runs[logicalIndex];
+            const RunHandler::RunInfo info = {
+                lineIndex,
+                run.fAdvance,
+                maxAscent,
+                maxDescent,
+                maxLeading,
+            };
+            append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
         }
 
         currentPoint.fY += maxDescent + maxLeading;
@@ -776,6 +792,7 @@
         maxDescent = 0;
         maxLeading = 0;
         previousRunIndex = -1;
+        ++lineIndex;
         previousBreak = glyphIterator;
     }
 }
diff --git a/modules/skshaper/src/SkShaper_primitive.cpp b/modules/skshaper/src/SkShaper_primitive.cpp
index 3d54262..f00db9f 100644
--- a/modules/skshaper/src/SkShaper_primitive.cpp
+++ b/modules/skshaper/src/SkShaper_primitive.cpp
@@ -31,7 +31,7 @@
     return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
 }
 
-SkPoint SkShaper::shape(LineHandler* handler,
+SkPoint SkShaper::shape(RunHandler* handler,
                         const SkFont& srcFont,
                         const char* utf8text,
                         size_t textBytes,
@@ -52,7 +52,14 @@
     font.getMetrics(&metrics);
     point.fY -= metrics.fAscent;
 
-    const auto buffer = handler->newLineBuffer(font, glyphCount, textBytes);
+    const RunHandler::RunInfo info = {
+        0,
+        { font.measureText(utf8text, textBytes, SkTextEncoding::kUTF8), 0 },
+        metrics.fAscent,
+        metrics.fDescent,
+        metrics.fLeading,
+    };
+    const auto buffer = handler->newRunBuffer(info, font, glyphCount, textBytes);
     SkAssertResult(font.textToGlyphs(utf8text, textBytes, SkTextEncoding::kUTF8, buffer.glyphs,
                                      glyphCount) == glyphCount);
     font.getPos(buffer.glyphs, glyphCount, buffer.positions, point);