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

Commit 61b54967 authored by Roozbeh Pournader's avatar Roozbeh Pournader Committed by Android (Google) Code Review
Browse files

Merge "Use bidi heuristics correctly in BoringLayout#isBoring()"

parents 0e29599f 5536c4fd
Loading
Loading
Loading
Loading
+58 −67
Original line number Diff line number Diff line
@@ -220,16 +220,6 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
        return isBoring(text, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR, null);
    }

    /**
     * Returns null if not boring; the width, ascent, and descent if boring.
     * @hide
     */
    public static Metrics isBoring(CharSequence text,
                                   TextPaint paint,
                                   TextDirectionHeuristic textDir) {
        return isBoring(text, paint, textDir, null);
    }

    /**
     * Returns null if not boring; the width, ascent, and descent in the
     * provided Metrics object (or a new one if the provided one was null)
@@ -240,24 +230,18 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
    }

    /**
     * Returns null if not boring; the width, ascent, and descent in the
     * provided Metrics object (or a new one if the provided one was null)
     * if boring.
     * @hide
     * Returns true if the text contains any RTL characters, bidi format characters, or surrogate
     * code units.
     */
    public static Metrics isBoring(CharSequence text, TextPaint paint,
            TextDirectionHeuristic textDir, Metrics metrics) {
    private static boolean hasAnyInterestingChars(CharSequence text, int textLength) {
        final int MAX_BUF_LEN = 500;
        final char[] buffer = TextUtils.obtain(MAX_BUF_LEN);
        final int textLength = text.length();
        boolean boring = true;

        outer:
        try {
            for (int start = 0; start < textLength; start += MAX_BUF_LEN) {
                final int end = Math.min(start + MAX_BUF_LEN, textLength);

            // No need to worry about getting half codepoints, since we reject surrogate code units
            // as non-boring as soon we see one.
                // No need to worry about getting half codepoints, since we consider surrogate code
                // units "interesting" as soon we see one.
                TextUtils.getChars(text, start, end, buffer, 0);

                final int len = end - start;
@@ -266,6 +250,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback

                    if (c == '\n' || c == '\t' ||
                            (c >= 0x0590 && c <= 0x08FF) ||  // RTL scripts
                            c == 0x200E ||  // Bidi format character
                            c == 0x200F ||  // Bidi format character
                            (c >= 0x202A && c <= 0x202E) ||  // Bidi format characters
                            (c >= 0x2066 && c <= 0x2069) ||  // Bidi format characters
@@ -273,30 +258,39 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
                            (c >= 0xFB1D && c <= 0xFDFF) ||  // Hebrew and Arabic presentation forms
                            (c >= 0xFE70 && c <= 0xFEFE) // Arabic presentation forms
                       ) {
                    boring = false;
                    break outer;
                        return true;
                    }
                }

            // TODO: This looks a little suspicious, and in some cases can result in O(n^2)
            // run time. Consider moving outside the loop.
            if (textDir != null && textDir.isRtl(buffer, 0, len)) {
               boring = false;
               break outer;
            }
            }

            return false;
        } finally {
            TextUtils.recycle(buffer);
        }
    }

        if (boring && text instanceof Spanned) {
    /**
     * Returns null if not boring; the width, ascent, and descent in the
     * provided Metrics object (or a new one if the provided one was null)
     * if boring.
     * @hide
     */
    public static Metrics isBoring(CharSequence text, TextPaint paint,
            TextDirectionHeuristic textDir, Metrics metrics) {
        final int textLength = text.length();
        if (hasAnyInterestingChars(text, textLength)) {
           return null;  // There are some interesting characters. Not boring.
        }
        if (textDir != null && textDir.isRtl(text, 0, textLength)) {
           return null;  // The heuristic considers the whole text RTL. Not boring.
        }
        if (text instanceof Spanned) {
            Spanned sp = (Spanned) text;
            Object[] styles = sp.getSpans(0, textLength, ParagraphStyle.class);
            if (styles.length > 0) {
                boring = false;
                return null;  // There are some PargraphStyle spans. Not boring.
            }
        }

        if (boring) {
        Metrics fm = metrics;
        if (fm == null) {
            fm = new Metrics();
@@ -311,9 +305,6 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
        TextLine.recycle(line);

        return fm;
        } else {
            return null;
        }
    }

    @Override