Bug fixes

Change-Id: I2b4b210301584c23a3b9325ebfdfdd9e6c4712d1
Bug: skia:9881, skia:9882
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271865
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
diff --git a/modules/skparagraph/src/ParagraphCache.cpp b/modules/skparagraph/src/ParagraphCache.cpp
index e3a1e3f..3ee287c 100644
--- a/modules/skparagraph/src/ParagraphCache.cpp
+++ b/modules/skparagraph/src/ParagraphCache.cpp
@@ -35,15 +35,13 @@
 public:
     ParagraphCacheValue(const ParagraphImpl* paragraph)
         : fKey(ParagraphCacheKey(paragraph))
-        , fRuns(paragraph->fRuns)
-        , fClusters(paragraph->fClusters) { }
+        , fRuns(paragraph->fRuns) { }
 
     // Input == key
     ParagraphCacheKey fKey;
 
     // Shaped results
     SkTArray<Run, false> fRuns;
-    SkTArray<Cluster, true> fClusters;
 };
 
 uint32_t ParagraphCache::KeyHash::mix(uint32_t hash, uint32_t data) const {
@@ -208,14 +206,6 @@
     for (auto& run : paragraph->fRuns) {
         run.setMaster(paragraph);
     }
-
-    paragraph->fClusters.reset();
-    paragraph->fClusters = entry->fValue->fClusters;
-    for (auto& cluster : paragraph->fClusters) {
-        cluster.setMaster(paragraph);
-    }
-
-    paragraph->fState = kMarked;
 }
 
 void ParagraphCache::printStatistics() {
diff --git a/modules/skparagraph/src/ParagraphImpl.cpp b/modules/skparagraph/src/ParagraphImpl.cpp
index ee1a386..45c7bd4 100644
--- a/modules/skparagraph/src/ParagraphImpl.cpp
+++ b/modules/skparagraph/src/ParagraphImpl.cpp
@@ -133,19 +133,12 @@
     } else if (fState >= kLineBroken && (fOldWidth != floorWidth || fOldHeight != fHeight)) {
         // We can use the results from SkShaper but have to do EVERYTHING ELSE again
         this->fClusters.reset();
-        this->fRunShifts.reset();
         this->resetRunShifts();
         fState = kShaped;
-
-        this->buildClusterTable();
-        fState = kClusterized;
-
-        this->markLineBreaks(); // Just because it's on cluster table
-        fState = kMarked;
     }
 
     if (fState < kShaped) {
-        fClusters.reset();
+
         fGraphemes.reset();
         this->markGraphemes();
 
@@ -173,23 +166,18 @@
 
             return;
         }
-        if (fState < kShaped) {
-            this->resetRunShifts();
-            fState = kShaped;
-        } else {
-            layout(floorWidth);
-            return;
-        }
 
-        if (fState < kMarked) {
-            this->buildClusterTable();
-            fState = kClusterized;
-            this->markLineBreaks();
-            fState = kMarked;
+        this->fClusters.reset();
+        this->resetRunShifts();
+        fState = kShaped;
+    }
 
-            // Add the paragraph to the cache
-            fFontCollection->getParagraphCache()->updateParagraph(this);
-        }
+    if (fState < kMarked) {
+        this->buildClusterTable();
+        fState = kClusterized;
+
+        this->markLineBreaks();
+        fState = kMarked;
     }
 
     if (fState >= kLineBroken)  {
@@ -377,7 +365,6 @@
 
     // Check the font-resolved text against the cache
     if (fFontCollection->getParagraphCache()->findParagraph(this)) {
-        this->fRunShifts.reset();
         return true;
     }
 
@@ -390,7 +377,8 @@
     if (!result) {
         return false;
     } else {
-        this->fRunShifts.reset();
+        // Add the paragraph to the cache
+        fFontCollection->getParagraphCache()->updateParagraph(this);
         return true;
     }
 }
@@ -1275,5 +1263,27 @@
     return true;
 }
 
+void ParagraphImpl::shiftCluster(ClusterIndex index, SkScalar shift, SkScalar lastShift) {
+    auto& cluster = fClusters[index];
+    auto& runShift = fRunShifts[cluster.runIndex()];
+    auto& run = fRuns[cluster.runIndex()];
+    auto start = cluster.startPos();
+    auto end = cluster.endPos();
+    if (!run.leftToRight()) {
+        runShift.fShifts[start] = lastShift;
+        ++start;
+        ++end;
+    }
+
+    if (end == runShift.fShifts.size() - 1) {
+        // Set the same shift for the fake last glyph (to avoid all extra checks)
+        ++end;
+    }
+
+    for (size_t pos = start; pos < end; ++pos) {
+        runShift.fShifts[pos] = shift;
+    }
+}
+
 }  // namespace textlayout
 }  // namespace skia
diff --git a/modules/skparagraph/src/ParagraphImpl.h b/modules/skparagraph/src/ParagraphImpl.h
index 2f4d2cd..960922a 100644
--- a/modules/skparagraph/src/ParagraphImpl.h
+++ b/modules/skparagraph/src/ParagraphImpl.h
@@ -144,21 +144,7 @@
     sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
     void formatLines(SkScalar maxWidth);
 
-    void shiftCluster(ClusterIndex index, SkScalar shift, SkScalar lastShift) {
-        auto& cluster = fClusters[index];
-        auto& runShift = fRunShifts[cluster.runIndex()];
-        auto& run = fRuns[cluster.runIndex()];
-        auto start = cluster.startPos();
-        auto end = cluster.endPos();
-        if (!run.leftToRight()) {
-            runShift.fShifts[start] = lastShift;
-            ++start;
-            ++end;
-        }
-        for (size_t pos = start; pos < end; ++pos) {
-            runShift.fShifts[pos] = shift;
-        }
-    }
+    void shiftCluster(ClusterIndex index, SkScalar shift, SkScalar lastShift);
 
     SkScalar posShift(RunIndex index, size_t pos) const {
         if (fRunShifts.count() == 0) return 0.0;
diff --git a/modules/skparagraph/src/TextLine.cpp b/modules/skparagraph/src/TextLine.cpp
index 4cf587b..5924c92 100644
--- a/modules/skparagraph/src/TextLine.cpp
+++ b/modules/skparagraph/src/TextLine.cpp
@@ -123,7 +123,7 @@
 
 SkRect TextLine::calculateBoundaries() {
 
-    auto boundaries = SkRect::MakeEmpty();
+    auto boundaries = SkRect::MakeIWH(fAdvance.fX, fAdvance.fY);
     auto clusters = fMaster->clusters(fClusterRange);
     Run* run = nullptr;
     auto runShift = 0.0f;
diff --git a/samplecode/SampleParagraph.cpp b/samplecode/SampleParagraph.cpp
index 2dcc11e..6391670 100644
--- a/samplecode/SampleParagraph.cpp
+++ b/samplecode/SampleParagraph.cpp
@@ -2177,32 +2177,48 @@
 
     void onDrawContent(SkCanvas* canvas) override {
 
-        const char* text = "test text with space at end   ";
+        /*
+         *     text: TextSpan(
+      text: 'aaaa bbbb ',
+      style: TextStyle(fontSize: 48.0),
+      children: <TextSpan>[
+        TextSpan(text: 'cc dd', style:TextStyle(fontFamily: 'serif', fontSize: 64.0)),
+      ],
+    ),
+    textDirection: TextDirection.ltr,
+    textAlign: TextAlign.justify,
+
+         */
+
+        const char* text1 = "aaaa bbbb ";
+        const char* text2 = "cc dd";
+
         canvas->drawColor(SK_ColorWHITE);
 
         ParagraphStyle paragraph_style;
-        paragraph_style.setTextAlign(TextAlign::kCenter);
+        paragraph_style.setTextAlign(TextAlign::kJustify);
         auto collection = getFontCollection();
+        SkPaint red;
+        red.setColor(SK_ColorRED);
         TextStyle text_style;
         text_style.setColor(SK_ColorBLACK);
-        text_style.setFontFamilies({SkString("Roboto")});
-        text_style.setFontSize(48);
 
         ParagraphBuilderImpl builder(paragraph_style, collection);
+
+        text_style.setFontFamilies({SkString("Roboto")});
+        text_style.setFontSize(48);
         builder.pushStyle(text_style);
-        builder.addText(text);
+        builder.addText(text1);
+
+        text_style.setFontFamilies({SkString("Google Sans")});
+        text_style.setFontSize(64);
+        builder.pushStyle(text_style);
+        builder.addText(text2);
+
         auto paragraph = builder.Build();
 
-        auto width = this->width();
-        paragraph->layout(width);
-        SkDebugf("%f: %f %f\n", width, paragraph->getMinIntrinsicWidth(), paragraph->getMaxIntrinsicWidth());
+        paragraph->layout(310);
         paragraph->paint(canvas, 0, 0);
-        auto boxes = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight, RectWidthStyle::kTight);
-        for (auto& b : boxes) {
-            SkDebugf("box[%f:%f * %f:%f] %s\n",
-                    b.rect.fLeft, b.rect.fRight, b.rect.fTop, b.rect.fBottom,
-                    b.direction == TextDirection::kRtl ? "rtl" : "ltr");
-        }
     }
 
 private: