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

Commit d04892d2 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio Committed by Android (Google) Code Review
Browse files

Merge "Add BidiFormatter utility"

parents e6a213ff 57a85740
Loading
Loading
Loading
Loading
+57 −0
Original line number Original line Diff line number Diff line
@@ -22273,6 +22273,21 @@ package android.text {
    method public int getTopPadding();
    method public int getTopPadding();
  }
  }
  public abstract interface TextDirectionHeuristic {
    method public abstract boolean isRtl(char[], int, int);
    method public abstract boolean isRtl(java.lang.CharSequence, int, int);
  }
  public class TextDirectionHeuristics {
    ctor public TextDirectionHeuristics();
    field public static final android.text.TextDirectionHeuristic ANYRTL_LTR;
    field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_LTR;
    field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_RTL;
    field public static final android.text.TextDirectionHeuristic LOCALE;
    field public static final android.text.TextDirectionHeuristic LTR;
    field public static final android.text.TextDirectionHeuristic RTL;
  }
  public class TextPaint extends android.graphics.Paint {
  public class TextPaint extends android.graphics.Paint {
    ctor public TextPaint();
    ctor public TextPaint();
    ctor public TextPaint(int);
    ctor public TextPaint(int);
@@ -22364,6 +22379,48 @@ package android.text {
}
}
package android.text.bidi {
  public final class BidiFormatter {
    method public java.lang.String dirAttr(java.lang.String);
    method public java.lang.String dirAttr(java.lang.String, android.text.TextDirectionHeuristic);
    method public java.lang.String dirAttr(boolean);
    method public java.lang.String dirAttrValue(java.lang.String);
    method public java.lang.String dirAttrValue(java.lang.String, android.text.TextDirectionHeuristic);
    method public java.lang.String dirAttrValue(boolean);
    method public java.lang.String endEdge();
    method public static android.text.bidi.BidiFormatter getInstance(boolean);
    method public static android.text.bidi.BidiFormatter getInstance(java.util.Locale);
    method public boolean getStereoReset();
    method public boolean isRtl(java.lang.String);
    method public boolean isRtlContext();
    method public java.lang.String mark();
    method public java.lang.String markAfter(java.lang.String);
    method public java.lang.String markAfter(java.lang.String, android.text.TextDirectionHeuristic);
    method public java.lang.String markBefore(java.lang.String);
    method public java.lang.String markBefore(java.lang.String, android.text.TextDirectionHeuristic);
    method public java.lang.String spanWrap(java.lang.String, android.text.TextDirectionHeuristic, boolean);
    method public java.lang.String spanWrap(java.lang.String, android.text.TextDirectionHeuristic);
    method public java.lang.String spanWrap(java.lang.String, boolean);
    method public java.lang.String spanWrap(java.lang.String);
    method public java.lang.String startEdge();
    method public java.lang.String unicodeWrap(java.lang.String, android.text.TextDirectionHeuristic, boolean);
    method public java.lang.String unicodeWrap(java.lang.String, android.text.TextDirectionHeuristic);
    method public java.lang.String unicodeWrap(java.lang.String, boolean);
    method public java.lang.String unicodeWrap(java.lang.String);
  }
  public static final class BidiFormatter.Builder {
    ctor public BidiFormatter.Builder();
    ctor public BidiFormatter.Builder(boolean);
    ctor public BidiFormatter.Builder(java.util.Locale);
    method public android.text.bidi.BidiFormatter build();
    method public android.text.bidi.BidiFormatter.Builder setTextDirectionHeuristic(android.text.TextDirectionHeuristic);
    method public android.text.bidi.BidiFormatter.Builder stereoReset(boolean);
  }
}
package android.text.format {
package android.text.format {
  public class DateFormat {
  public class DateFormat {
+24 −4
Original line number Original line Diff line number Diff line
@@ -17,10 +17,30 @@
package android.text;
package android.text;


/**
/**
 * Interface for objects that guess at the paragraph direction by examining text.
 * Interface for objects that use a heuristic for guessing at the paragraph direction by examining text.
 *
 * @hide
 */
 */
public interface TextDirectionHeuristic {
public interface TextDirectionHeuristic {
    boolean isRtl(char[] text, int start, int count);
    /**
     * Guess if a chars array is in the RTL direction or not.
     *
     * @param array the char array.
     * @param start start index, inclusive.
     * @param count the length to check, must not be negative and not greater than
     *          {@code array.length - start}.
     * @return true if all chars in the range are to be considered in a RTL direction,
     *          false otherwise.
     */
    boolean isRtl(char[] array, int start, int count);

    /**
     * Guess if a {@code CharSequence} is in the RTL direction or not.
     *
     * @param cs the CharSequence.
     * @param start start index, inclusive.
     * @param count the length to check, must not be negative and not greater than
     *            {@code CharSequence.length() - start}.
     * @return true if all chars in the range are to be considered in a RTL direction,
     *          false otherwise.
     */
    boolean isRtl(CharSequence cs, int start, int count);
}
}
+76 −71
Original line number Original line Diff line number Diff line
@@ -19,43 +19,45 @@ package android.text;


import android.view.View;
import android.view.View;


import java.nio.CharBuffer;

/**
/**
 * Some objects that implement TextDirectionHeuristic.
 * Some objects that implement TextDirectionHeuristic.
 *
 *
 * @hide
 */
 */
public class TextDirectionHeuristics {
public class TextDirectionHeuristics {


    /** Always decides that the direction is left to right. */
    /**
     * Always decides that the direction is left to right.
     */
    public static final TextDirectionHeuristic LTR =
    public static final TextDirectionHeuristic LTR =
        new TextDirectionHeuristicInternal(null /* no algorithm */, false);
        new TextDirectionHeuristicInternal(null /* no algorithm */, false);


    /** Always decides that the direction is right to left. */
    /**
     * Always decides that the direction is right to left.
     */
    public static final TextDirectionHeuristic RTL =
    public static final TextDirectionHeuristic RTL =
        new TextDirectionHeuristicInternal(null /* no algorithm */, true);
        new TextDirectionHeuristicInternal(null /* no algorithm */, true);


    /**
    /**
     * Determines the direction based on the first strong directional character,
     * Determines the direction based on the first strong directional character, including bidi
     * including bidi format chars, falling back to left to right if it
     * format chars, falling back to left to right if it finds none. This is the default behavior
     * finds none.  This is the default behavior of the Unicode Bidirectional
     * of the Unicode Bidirectional Algorithm.
     * Algorithm.
     */
     */
    public static final TextDirectionHeuristic FIRSTSTRONG_LTR =
    public static final TextDirectionHeuristic FIRSTSTRONG_LTR =
        new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, false);
        new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, false);


    /**
    /**
     * Determines the direction based on the first strong directional character,
     * Determines the direction based on the first strong directional character, including bidi
     * including bidi format chars, falling back to right to left if it
     * format chars, falling back to right to left if it finds none. This is similar to the default
     * finds none.  This is similar to the default behavior of the Unicode
     * behavior of the Unicode Bidirectional Algorithm, just with different fallback behavior.
     * Bidirectional Algorithm, just with different fallback behavior.
     */
     */
    public static final TextDirectionHeuristic FIRSTSTRONG_RTL =
    public static final TextDirectionHeuristic FIRSTSTRONG_RTL =
        new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);
        new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);


    /**
    /**
     * If the text contains any strong right to left non-format character, determines
     * If the text contains any strong right to left non-format character, determines that the
     * that the direction is right to left, falling back to left to right if it
     * direction is right to left, falling back to left to right if it finds none.
     * finds none.
     */
     */
    public static final TextDirectionHeuristic ANYRTL_LTR =
    public static final TextDirectionHeuristic ANYRTL_LTR =
        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
@@ -65,8 +67,39 @@ public class TextDirectionHeuristics {
     */
     */
    public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
    public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;


    private static enum TriState {
    /**
        TRUE, FALSE, UNKNOWN;
     * State constants for taking care about true / false / unknown
     */
    private static final int STATE_TRUE = 0;
    private static final int STATE_FALSE = 1;
    private static final int STATE_UNKNOWN = 2;

    private static int isRtlText(int directionality) {
        switch (directionality) {
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
                return STATE_FALSE;
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
                return STATE_TRUE;
            default:
                return STATE_UNKNOWN;
        }
    }

    private static int isRtlTextOrFormat(int directionality) {
        switch (directionality) {
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
                return STATE_FALSE;
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
                return STATE_TRUE;
            default:
                return STATE_UNKNOWN;
        }
    }
    }


    /**
    /**
@@ -87,21 +120,26 @@ public class TextDirectionHeuristics {
        abstract protected boolean defaultIsRtl();
        abstract protected boolean defaultIsRtl();


        @Override
        @Override
        public boolean isRtl(char[] chars, int start, int count) {
        public boolean isRtl(char[] array, int start, int count) {
            if (chars == null || start < 0 || count < 0 || chars.length - count < start) {
            return isRtl(CharBuffer.wrap(array), start, count);
        }

        @Override
        public boolean isRtl(CharSequence cs, int start, int count) {
            if (cs == null || start < 0 || count < 0 || cs.length() - count < start) {
                throw new IllegalArgumentException();
                throw new IllegalArgumentException();
            }
            }
            if (mAlgorithm == null) {
            if (mAlgorithm == null) {
                return defaultIsRtl();
                return defaultIsRtl();
            }
            }
            return doCheck(chars, start, count);
            return doCheck(cs, start, count);
        }
        }


        private boolean doCheck(char[] chars, int start, int count) {
        private boolean doCheck(CharSequence cs, int start, int count) {
            switch(mAlgorithm.checkRtl(chars, start, count)) {
            switch(mAlgorithm.checkRtl(cs, start, count)) {
                case TRUE:
                case STATE_TRUE:
                    return true;
                    return true;
                case FALSE:
                case STATE_FALSE:
                    return false;
                    return false;
                default:
                default:
                    return defaultIsRtl();
                    return defaultIsRtl();
@@ -124,58 +162,26 @@ public class TextDirectionHeuristics {
        }
        }
    }
    }


    private static TriState isRtlText(int directionality) {
        switch (directionality) {
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
                return TriState.FALSE;
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
                return TriState.TRUE;
            default:
                return TriState.UNKNOWN;
        }
    }

    private static TriState isRtlTextOrFormat(int directionality) {
        switch (directionality) {
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
                return TriState.FALSE;
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
                return TriState.TRUE;
            default:
                return TriState.UNKNOWN;
        }
    }

    /**
    /**
     * Interface for an algorithm to guess the direction of a paragraph of text.
     * Interface for an algorithm to guess the direction of a paragraph of text.
     *
     */
     */
    private static interface TextDirectionAlgorithm {
    private static interface TextDirectionAlgorithm {
        /**
        /**
         * Returns whether the range of text is RTL according to the algorithm.
         * Returns whether the range of text is RTL according to the algorithm.
         *
         */
         */
        TriState checkRtl(char[] text, int start, int count);
        int checkRtl(CharSequence cs, int start, int count);
    }
    }


    /**
    /**
     * Algorithm that uses the first strong directional character to determine
     * Algorithm that uses the first strong directional character to determine the paragraph
     * the paragraph direction.  This is the standard Unicode Bidirectional
     * direction. This is the standard Unicode Bidirectional algorithm.
     * algorithm.
     *
     */
     */
    private static class FirstStrong implements TextDirectionAlgorithm {
    private static class FirstStrong implements TextDirectionAlgorithm {
        @Override
        @Override
        public TriState checkRtl(char[] text, int start, int count) {
        public int checkRtl(CharSequence cs, int start, int count) {
            TriState result = TriState.UNKNOWN;
            int result = STATE_UNKNOWN;
            for (int i = start, e = start + count; i < e && result == TriState.UNKNOWN; ++i) {
            for (int i = start, e = start + count; i < e && result == STATE_UNKNOWN; ++i) {
                result = isRtlTextOrFormat(Character.getDirectionality(text[i]));
                result = isRtlTextOrFormat(Character.getDirectionality(cs.charAt(i)));
            }
            }
            return result;
            return result;
        }
        }
@@ -190,25 +196,24 @@ public class TextDirectionHeuristics {
     * Algorithm that uses the presence of any strong directional non-format
     * Algorithm that uses the presence of any strong directional non-format
     * character (e.g. excludes LRE, LRO, RLE, RLO) to determine the
     * character (e.g. excludes LRE, LRO, RLE, RLO) to determine the
     * direction of text.
     * direction of text.
     *
     */
     */
    private static class AnyStrong implements TextDirectionAlgorithm {
    private static class AnyStrong implements TextDirectionAlgorithm {
        private final boolean mLookForRtl;
        private final boolean mLookForRtl;


        @Override
        @Override
        public TriState checkRtl(char[] text, int start, int count) {
        public int checkRtl(CharSequence cs, int start, int count) {
            boolean haveUnlookedFor = false;
            boolean haveUnlookedFor = false;
            for (int i = start, e = start + count; i < e; ++i) {
            for (int i = start, e = start + count; i < e; ++i) {
                switch (isRtlText(Character.getDirectionality(text[i]))) {
                switch (isRtlText(Character.getDirectionality(cs.charAt(i)))) {
                    case TRUE:
                    case STATE_TRUE:
                        if (mLookForRtl) {
                        if (mLookForRtl) {
                            return TriState.TRUE;
                            return STATE_TRUE;
                        }
                        }
                        haveUnlookedFor = true;
                        haveUnlookedFor = true;
                        break;
                        break;
                    case FALSE:
                    case STATE_FALSE:
                        if (!mLookForRtl) {
                        if (!mLookForRtl) {
                            return TriState.FALSE;
                            return STATE_FALSE;
                        }
                        }
                        haveUnlookedFor = true;
                        haveUnlookedFor = true;
                        break;
                        break;
@@ -217,9 +222,9 @@ public class TextDirectionHeuristics {
                }
                }
            }
            }
            if (haveUnlookedFor) {
            if (haveUnlookedFor) {
                return mLookForRtl ? TriState.FALSE : TriState.TRUE;
                return mLookForRtl ? STATE_FALSE : STATE_TRUE;
            }
            }
            return TriState.UNKNOWN;
            return STATE_UNKNOWN;
        }
        }


        private AnyStrong(boolean lookForRtl) {
        private AnyStrong(boolean lookForRtl) {
+1147 −0

File added.

Preview size limit exceeded, changes collapsed.