Avoid malloc calls for these two temp arrays on the stack.

TODO: fRunsInVisualOrder is a long-lived array, but appears to..
- never resize after the constructor
- very often be size==1
Can we preallocate storage for it in the TextLine itself? (e.g. StSTArray or other trick)

Change-Id: I817b46a24e01ddf999bdd81a607aaf35b3c0674b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291776
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/include/private/SkTemplates.h b/include/private/SkTemplates.h
index 477bbcb..1edf812 100644
--- a/include/private/SkTemplates.h
+++ b/include/private/SkTemplates.h
@@ -114,6 +114,10 @@
         return fArray[index];
     }
 
+    // aliases matching other types like std::vector
+    const T* data() const { return fArray; }
+    T* data() { return fArray; }
+
 private:
     std::unique_ptr<T[]> fArray;
     SkDEBUGCODE(int fCount = 0;)
@@ -203,6 +207,11 @@
         return fArray[index];
     }
 
+    // aliases matching other types like std::vector
+    const T* data() const { return fArray; }
+    T* data() { return fArray; }
+    size_t size() const { return fCount; }
+
 private:
 #if defined(SK_BUILD_FOR_GOOGLE3)
     // Stack frame size is limited for SK_BUILD_FOR_GOOGLE3. 4k is less than the actual max, but some functions
diff --git a/modules/skparagraph/src/TextLine.cpp b/modules/skparagraph/src/TextLine.cpp
index cf6aacb..9a12bba 100644
--- a/modules/skparagraph/src/TextLine.cpp
+++ b/modules/skparagraph/src/TextLine.cpp
@@ -107,16 +107,24 @@
     }
 
     // Get the logical order
-    std::vector<UBiDiLevel> runLevels;
+
+    // This is just chosen to catch the common/fast cases. Feel free to tweak.
+    constexpr int kPreallocCount = 4;
+
+    SkAutoSTArray<kPreallocCount, UBiDiLevel> runLevels(numRuns);
+
+    size_t runLevelsIndex = 0;
     for (auto runIndex = start.runIndex(); runIndex <= end.runIndex(); ++runIndex) {
         auto& run = fMaster->run(runIndex);
-        runLevels.emplace_back(run.fBidiLevel);
-        fMaxRunMetrics.add(InternalLineMetrics(run.fFontMetrics.fAscent, run.fFontMetrics.fDescent, run.fFontMetrics.fLeading));
+        runLevels[runLevelsIndex++] = run.fBidiLevel;
+        fMaxRunMetrics.add(InternalLineMetrics(run.fFontMetrics.fAscent, run.fFontMetrics.fDescent,
+                                               run.fFontMetrics.fLeading));
     }
+    SkASSERT(runLevelsIndex == numRuns);
 
-    std::vector<int32_t> logicalOrder(numRuns);
+    SkAutoSTArray<kPreallocCount, int32_t> logicalOrder(numRuns);
+
     ubidi_reorderVisual(runLevels.data(), SkToU32(numRuns), logicalOrder.data());
-
     auto firstRunIndex = start.runIndex();
     for (auto index : logicalOrder) {
         fRunsInVisualOrder.push_back(firstRunIndex + index);