Optimize findLimitingClusters

This method is called every time we paint a styled text range to find its cluster range.
Instead of scanning all the clusters in the run we can use
a helper table that for every UTF8 byte keeps its cluster.
(So the most important part of the change is this table in Paragraph)
Should have done it long time ago but fixing bugs seemed to be more
important than performance.

Change-Id: I309f18ace4654b140a8532fef415c0280ea09d08
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/295005
Commit-Queue: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/modules/skparagraph/src/ParagraphImpl.h b/modules/skparagraph/src/ParagraphImpl.h
index 780c8a4..7f46158 100644
--- a/modules/skparagraph/src/ParagraphImpl.h
+++ b/modules/skparagraph/src/ParagraphImpl.h
@@ -153,10 +153,16 @@
     SkSpan<const char> text(TextRange textRange);
     SkSpan<Cluster> clusters(ClusterRange clusterRange);
     Cluster& cluster(ClusterIndex clusterIndex);
+    ClusterIndex clusterIndex(TextIndex textIndex) {
+        auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
+        SkASSERT(clusterIndex != EMPTY_INDEX);
+        return clusterIndex;
+    }
     Run& run(RunIndex runIndex) {
         SkASSERT(runIndex < fRuns.size());
         return fRuns[runIndex];
     }
+
     Run& runByCluster(ClusterIndex clusterIndex);
     SkSpan<Block> blocks(BlockRange blockRange);
     Block& block(BlockIndex blockIndex);
@@ -240,6 +246,7 @@
     SkTArray<Run, false> fRuns;         // kShaped
     SkTArray<Cluster, true> fClusters;  // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
     SkTArray<CodeUnitFlags> fCodeUnitProperties;
+    SkTArray<size_t> fClustersIndexFromCodeUnit;
     std::vector<size_t> fWords;
     SkTArray<BidiRegion> fBidiRegions;
     SkTArray<Grapheme, true> fGraphemes16;