Merge "Unhide Paint.getTextRunAdvances"
diff --git a/api/current.txt b/api/current.txt
index c1a1c52..1eecc2d 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -14015,6 +14015,7 @@
     method public android.os.LocaleList getTextLocales();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
+    method public float getTextRunAdvances(char[], int, int, int, int, boolean, float[], int);
     method public float getTextScaleX();
     method public float getTextSize();
     method public float getTextSkewX();
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index 2f28606..b5ed01f 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -186,44 +186,28 @@
         Paint p = new Paint();
 
         final int count = end - start;
-        final float[][] advanceArrays = new float[4][count];
-
-        final float advance = p.getTextRunAdvances(str, start, end, contextStart, contextEnd,
-                isRtl, advanceArrays[0], 0);
-
+        final int contextCount = contextEnd - contextStart;
+        final float[][] advanceArrays = new float[2][count];
         char chars[] = str.toCharArray();
-        final float advance_c = p.getTextRunAdvances(chars, start, count, contextStart,
-                contextEnd - contextStart, isRtl, advanceArrays[1], 0);
-        assertEquals(advance, advance_c, 1.0f);
-
+        final float advance = p.getTextRunAdvances(chars, start, count,
+                contextStart, contextCount, isRtl, advanceArrays[0], 0);
         for (int c = 1; c < count; ++c) {
-            final float firstPartAdvance = p.getTextRunAdvances(str, start, start + c,
-                    contextStart, contextEnd, isRtl, advanceArrays[2], 0);
-            final float secondPartAdvance = p.getTextRunAdvances(str, start + c, end,
-                    contextStart, contextEnd, isRtl, advanceArrays[2], c);
+            final float firstPartAdvance = p.getTextRunAdvances(chars, start, c,
+                    contextStart, contextCount, isRtl, advanceArrays[1], 0);
+            final float secondPartAdvance = p.getTextRunAdvances(chars, start + c, count - c,
+                    contextStart, contextCount, isRtl, advanceArrays[1], c);
             assertEquals(advance, firstPartAdvance + secondPartAdvance, 1.0f);
 
-
-            final float firstPartAdvance_c = p.getTextRunAdvances(chars, start, c,
-                    contextStart, contextEnd - contextStart, isRtl, advanceArrays[3], 0);
-            final float secondPartAdvance_c = p.getTextRunAdvances(chars, start + c,
-                    count - c, contextStart, contextEnd - contextStart, isRtl,
-                    advanceArrays[3], c);
-            assertEquals(advance, firstPartAdvance_c + secondPartAdvance_c, 1.0f);
-            assertEquals(firstPartAdvance, firstPartAdvance_c, 1.0f);
-            assertEquals(secondPartAdvance, secondPartAdvance_c, 1.0f);
-
-            for (int i = 1; i < advanceArrays.length; i++) {
-                for (int j = 0; j < count; j++) {
-                    assertEquals(advanceArrays[0][j], advanceArrays[i][j], 1.0f);
-                }
+            for (int j = 0; j < count; j++) {
+                assertEquals(advanceArrays[0][j], advanceArrays[1][j], 1.0f);
             }
 
+
             // Compare results with measureText, getRunAdvance, and getTextWidths.
             if (compareWithOtherMethods && start == contextStart && end == contextEnd) {
                 assertEquals(advance, p.measureText(str, start, end), 1.0f);
                 assertEquals(advance, p.getRunAdvance(
-                        str, start, end, contextStart, contextEnd, isRtl, end), 1.0f);
+                        chars, start, count, contextStart, contextCount, isRtl, end), 1.0f);
 
                 final float[] widths = new float[count];
                 p.getTextWidths(str, start, end, widths);
@@ -236,19 +220,7 @@
 
     public void testGetTextRunAdvances_invalid() {
         Paint p = new Paint();
-        String text = "test";
-
-        try {
-            p.getTextRunAdvances((String)null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
-
-        try {
-            p.getTextRunAdvances((CharSequence)null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
+        char[] text = "test".toCharArray();
 
         try {
             p.getTextRunAdvances((char[])null, 0, 0, 0, 0, false, null, 0);
@@ -257,50 +229,43 @@
         }
 
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
-                    new float[text.length() - 1], 0);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length, false,
+                    new float[text.length - 1], 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
-                    new float[text.length()], 1);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length, false,
+                    new float[text.length], 1);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // 0 > contextStart
         try {
-            p.getTextRunAdvances(text, 0, text.length(), -1, text.length(), false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, -1, text.length, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // contextStart > start
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 1, text.length(), false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // start > end
-        try {
-            p.getTextRunAdvances(text, 1, 0, 0, text.length(), false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, 1, text.length, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // end > contextEnd
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() - 1, false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length - 1, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // contextEnd > text.length
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() + 1, false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length + 1, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 6f30653..85b39fe 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -17,7 +17,9 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.Px;
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
@@ -2325,17 +2327,53 @@
     }
 
     /**
-     * Convenience overload that takes a char array instead of a
-     * String.
+     * Retrieve the character advances of the text.
      *
-     * @see #getTextRunAdvances(String, int, int, int, int, boolean, float[], int)
-     * @hide
+     * Returns the total advance width for the characters in the run from {@code index} for
+     * {@code count} of chars, and if {@code advances} is not null, the advance assigned to each of
+     * these characters (java chars).
+     *
+     * <p>
+     * The trailing surrogate in a valid surrogate pair is assigned an advance of 0.  Thus the
+     * number of returned advances is always equal to count, not to the number of unicode codepoints
+     * represented by the run.
+     * </p>
+     *
+     * <p>
+     * In the case of conjuncts or combining marks, the total advance is assigned to the first
+     * logical character, and the following characters are assigned an advance of 0.
+     * </p>
+     *
+     * <p>
+     * This generates the sum of the advances of glyphs for characters in a reordered cluster as the
+     * width of the first logical character in the cluster, and 0 for the widths of all other
+     * characters in the cluster.  In effect, such clusters are treated like conjuncts.
+     * </p>
+     *
+     * <p>
+     * The shaping bounds limit the amount of context available outside start and end that can be
+     * used for shaping analysis.  These bounds typically reflect changes in bidi level or font
+     * metrics across which shaping does not occur.
+     * </p>
+     *
+     * @param chars the text to measure.
+     * @param index the index of the first character to measure
+     * @param count the number of characters to measure
+     * @param contextIndex the index of the first character to use for shaping context.
+     *                     Context must cover the measureing target.
+     * @param contextCount the number of character to use for shaping context.
+     *                     Context must cover the measureing target.
+     * @param isRtl whether the run is in RTL direction
+     * @param advances array to receive the advances, must have room for all advances.
+     *                 This can be null if only total advance is needed
+     * @param advancesIndex the position in advances at which to put the advance corresponding to
+     *                      the character at start
+     * @return the total advance in pixels
      */
-    @UnsupportedAppUsage
-    public float getTextRunAdvances(char[] chars, int index, int count,
-            int contextIndex, int contextCount, boolean isRtl, float[] advances,
-            int advancesIndex) {
-
+    public float getTextRunAdvances(@NonNull char[] chars, @IntRange(from = 0) int index,
+            @IntRange(from = 0) int count, @IntRange(from = 0) int contextIndex,
+            @IntRange(from = 0) int contextCount, boolean isRtl, @Nullable float[] advances,
+            @IntRange(from = 0) int advancesIndex) {
         if (chars == null) {
             throw new IllegalArgumentException("text cannot be null");
         }
@@ -2372,131 +2410,6 @@
     }
 
     /**
-     * Convenience overload that takes a CharSequence instead of a
-     * String.
-     *
-     * @see #getTextRunAdvances(String, int, int, int, int, boolean, float[], int)
-     * @hide
-     */
-    public float getTextRunAdvances(CharSequence text, int start, int end,
-            int contextStart, int contextEnd, boolean isRtl, float[] advances,
-            int advancesIndex) {
-        if (text == null) {
-            throw new IllegalArgumentException("text cannot be null");
-        }
-        if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
-                | (start - contextStart) | (contextEnd - end)
-                | (text.length() - contextEnd)
-                | (advances == null ? 0 :
-                    (advances.length - advancesIndex - (end - start)))) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (text instanceof String) {
-            return getTextRunAdvances((String) text, start, end,
-                    contextStart, contextEnd, isRtl, advances, advancesIndex);
-        }
-        if (text instanceof SpannedString ||
-            text instanceof SpannableString) {
-            return getTextRunAdvances(text.toString(), start, end,
-                    contextStart, contextEnd, isRtl, advances, advancesIndex);
-        }
-        if (text instanceof GraphicsOperations) {
-            return ((GraphicsOperations) text).getTextRunAdvances(start, end,
-                    contextStart, contextEnd, isRtl, advances, advancesIndex, this);
-        }
-        if (text.length() == 0 || end == start) {
-            return 0f;
-        }
-
-        int contextLen = contextEnd - contextStart;
-        int len = end - start;
-        char[] buf = TemporaryBuffer.obtain(contextLen);
-        TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-        float result = getTextRunAdvances(buf, start - contextStart, len,
-                0, contextLen, isRtl, advances, advancesIndex);
-        TemporaryBuffer.recycle(buf);
-        return result;
-    }
-
-    /**
-     * Returns the total advance width for the characters in the run
-     * between start and end, and if advances is not null, the advance
-     * assigned to each of these characters (java chars).
-     *
-     * <p>The trailing surrogate in a valid surrogate pair is assigned
-     * an advance of 0.  Thus the number of returned advances is
-     * always equal to count, not to the number of unicode codepoints
-     * represented by the run.
-     *
-     * <p>In the case of conjuncts or combining marks, the total
-     * advance is assigned to the first logical character, and the
-     * following characters are assigned an advance of 0.
-     *
-     * <p>This generates the sum of the advances of glyphs for
-     * characters in a reordered cluster as the width of the first
-     * logical character in the cluster, and 0 for the widths of all
-     * other characters in the cluster.  In effect, such clusters are
-     * treated like conjuncts.
-     *
-     * <p>The shaping bounds limit the amount of context available
-     * outside start and end that can be used for shaping analysis.
-     * These bounds typically reflect changes in bidi level or font
-     * metrics across which shaping does not occur.
-     *
-     * @param text the text to measure. Cannot be null.
-     * @param start the index of the first character to measure
-     * @param end the index past the last character to measure
-     * @param contextStart the index of the first character to use for shaping context,
-     * must be <= start
-     * @param contextEnd the index past the last character to use for shaping context,
-     * must be >= end
-     * @param isRtl whether the run is in RTL direction
-     * @param advances array to receive the advances, must have room for all advances,
-     * can be null if only total advance is needed
-     * @param advancesIndex the position in advances at which to put the
-     * advance corresponding to the character at start
-     * @return the total advance
-     *
-     * @hide
-     */
-    public float getTextRunAdvances(String text, int start, int end, int contextStart,
-            int contextEnd, boolean isRtl, float[] advances, int advancesIndex) {
-        if (text == null) {
-            throw new IllegalArgumentException("text cannot be null");
-        }
-        if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
-                | (start - contextStart) | (contextEnd - end)
-                | (text.length() - contextEnd)
-                | (advances == null ? 0 :
-                    (advances.length - advancesIndex - (end - start)))) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (text.length() == 0 || start == end) {
-            return 0f;
-        }
-
-        if (!mHasCompatScaling) {
-            return nGetTextAdvances(mNativePaint, text, start, end, contextStart, contextEnd,
-                    isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances, advancesIndex);
-        }
-
-        final float oldSize = getTextSize();
-        setTextSize(oldSize * mCompatScaling);
-        final float totalAdvance = nGetTextAdvances(mNativePaint, text, start, end, contextStart,
-                contextEnd, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances, advancesIndex);
-        setTextSize(oldSize);
-
-        if (advances != null) {
-            for (int i = advancesIndex, e = i + (end - start); i < e; i++) {
-                advances[i] *= mInvCompatScaling;
-            }
-        }
-        return totalAdvance * mInvCompatScaling; // assume errors are insignificant
-    }
-
-    /**
      * Returns the next cursor position in the run.  This avoids placing the
      * cursor between surrogates, between characters that form conjuncts,
      * between base characters and combining marks, or within a reordering