Recompute PcT with existing PcT for different direction

The text direction can not be fully determined in detached state.
To improve even in that case, compute PrecomputedText from existing
PrecomputedText with new direction.

Here is the performance difference. According to the perf test result,
up to 80% of computation can be recycled from existing PrecomputedText.

android.text.StaticLayoutPerfTest (u sec):
    PrecomputedText Greedy NoHyphenation             :    371 ->    371: (   +0,  +0.0%)
    PrecomputedText Greedy NoHyphenation DirDifferent:  6,923 ->  1,437: (-5486, -79.2%)
    RandomText Greedy NoHyphenation                  :  6,633 ->  6,627: (   -6,  -0.1%)

On the other hand, this CL increase the memory usage of the
PrecomputedText up to 10%. Here is an reference memory usage.

android.text.PrecomputedTextMemoryUsageTest (bytes):
  MemoryUsage
    Arabic Hyphenation                               : 17,135 -> 18,116: ( +981, +5.7%)
    Arabic NoHyphenation                             : 17,135 -> 18,116: ( +981, +5.7%)
    CJK Hyphenation                                  : 29,000 -> 31,584: (+2584, +8.9%)
    CJK NoHyphenation                                : 29,000 -> 31,584: (+2584, +8.9%)
    Latin Hyphenation                                : 16,526 -> 17,185: ( +659, +4.0%)
    Latin NoHyphenation                              : 14,200 -> 14,784: ( +584, +4.1%)

Bug: 119312268
Test: atest CtsWidgetTestCases
Test: atest CtsTextTestCases
Test: atest CtsGraphicsTestCases
Test: minikin_tests

Change-Id: Ia02c201afac5d7d1c086a45f15696f39a6b2a76c
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index f9370a8..7e41878 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -377,6 +377,9 @@
      * @param start the inclusive start offset of the target region in the text
      * @param end the exclusive end offset of the target region in the text
      * @param textDir the text direction
+     * @param computeHyphenation true if need to compute hyphenation, otherwise false
+     * @param computeLayout true if need to compute full layout, otherwise false.
+     * @param hint pass if you already have measured paragraph.
      * @param recycle pass existing MeasuredParagraph if you want to recycle it.
      *
      * @return measured text
@@ -389,12 +392,18 @@
             @NonNull TextDirectionHeuristic textDir,
             boolean computeHyphenation,
             boolean computeLayout,
+            @Nullable MeasuredParagraph hint,
             @Nullable MeasuredParagraph recycle) {
         final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
         mt.resetAndAnalyzeBidi(text, start, end, textDir);
-        final MeasuredText.Builder builder = new MeasuredText.Builder(mt.mCopiedBuffer);
-        builder.setComputeHyphenation(computeHyphenation);
-        builder.setComputeLayout(computeLayout);
+        final MeasuredText.Builder builder;
+        if (hint == null) {
+            builder = new MeasuredText.Builder(mt.mCopiedBuffer)
+                    .setComputeHyphenation(computeHyphenation)
+                    .setComputeLayout(computeLayout);
+        } else {
+            builder = new MeasuredText.Builder(hint.mMeasuredText);
+        }
         if (mt.mTextLength == 0) {
             // Need to build empty native measured text for StaticLayout.
             // TODO: Stop creating empty measured text for empty lines.