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

Commit 57a85740 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio
Browse files

Add BidiFormatter utility

See bug #7587797 Need BidiFormatter class in Android API

Change-Id: I999282b9a4c76d8b4a3fc254b0c12ca95fa6ea4a
parent 981e60ed
Loading
Loading
Loading
Loading
+57 −0
Original line number Original line Diff line number Diff line
@@ -22265,6 +22265,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);
@@ -22356,6 +22371,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.