Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14a081f2 authored by Seigo Nonaka's avatar Seigo Nonaka Committed by Android (Google) Code Review
Browse files

Merge "Unhide Paint.getTextRunAdvances"

parents 4c888c77 eb749119
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14015,6 +14015,7 @@ package android.graphics {
    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();
+21 −56
Original line number Diff line number Diff line
@@ -186,44 +186,28 @@ public class PaintTest extends InstrumentationTestCase {
        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);
                }
                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 class PaintTest extends InstrumentationTestCase {

    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 @@ public class PaintTest extends InstrumentationTestCase {
        }

        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) {
        }
+48 −135
Original line number Diff line number Diff line
@@ -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 @@ public class Paint {
    }

    /**
     * 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
     */
    @UnsupportedAppUsage
    public float getTextRunAdvances(char[] chars, int index, int count,
            int contextIndex, int contextCount, boolean isRtl, float[] advances,
            int advancesIndex) {

     * 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
     */
    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");
        }
@@ -2371,131 +2409,6 @@ public class Paint {
        return res * mInvCompatScaling; // assume errors are not significant
    }

    /**
     * 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,