summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYohei Yukawa <yukawa@google.com>2014-09-02 14:18:40 -0700
committerYohei Yukawa <yukawa@google.com>2014-09-08 02:17:54 +0000
commit5f183f0671dfa1d87ca6d741deb457170c432493 (patch)
treebbe26c8efa6ac5b36856227c2f58b437321aee9f
parenta3ca5a31a5db14e7c4597de074f01c1af6161872 (diff)
downloadframeworks_base-5f183f0671dfa1d87ca6d741deb457170c432493.zip
frameworks_base-5f183f0671dfa1d87ca6d741deb457170c432493.tar.gz
frameworks_base-5f183f0671dfa1d87ca6d741deb457170c432493.tar.bz2
L API proposal: Introduce IS_RTL flag
This CL introduces CursorAnchorInfo.FLAG_IS_RTL for better RTL support. This CL also renames *CharacterRect() with *CharacterBounds() so that they can look more consistent with other existing APIs. Rationale: CursorAnchorInfo.FLAG_IS_RTL addresses following issues. 1. There is no way to associate the RTL information with the insertion marker. 2. Returning mirrored (right < left) RectF for RTL in CursorAnchorInfo#getCharacterRect() is turned out to be bug-prone. Such usage of RectF is not fully supported. For example, RectF#isEmpty() always returns false when right < left. 3. There is no reliable to provide the RTL information when CursorAnchorInfo#getCharacterRect() returns an empty (right == left) RectF. Perhaps we could use +0.0 and -0.0, but I'm afraid that it is also bug-prone. BUG: 17365414 BUG: 17335734 Change-Id: Ic8c6fab58c01206872a34e7ee604cdda1581364d
-rw-r--r--api/current.txt7
-rw-r--r--api/removed.txt3
-rw-r--r--core/java/android/view/inputmethod/CursorAnchorInfo.java171
-rw-r--r--core/java/android/widget/Editor.java105
4 files changed, 192 insertions, 94 deletions
diff --git a/api/current.txt b/api/current.txt
index f59fd4f..9d89bdf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35899,8 +35899,8 @@ package android.view.inputmethod {
public final class CursorAnchorInfo implements android.os.Parcelable {
ctor public CursorAnchorInfo(android.os.Parcel);
method public int describeContents();
- method public android.graphics.RectF getCharacterRect(int);
- method public int getCharacterRectFlags(int);
+ method public android.graphics.RectF getCharacterBounds(int);
+ method public int getCharacterBoundsFlags(int);
method public java.lang.CharSequence getComposingText();
method public int getComposingTextStart();
method public float getInsertionMarkerBaseline();
@@ -35915,11 +35915,12 @@ package android.view.inputmethod {
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_HAS_INVISIBLE_REGION = 2; // 0x2
field public static final int FLAG_HAS_VISIBLE_REGION = 1; // 0x1
+ field public static final int FLAG_IS_RTL = 4; // 0x4
}
public static final class CursorAnchorInfo.Builder {
ctor public CursorAnchorInfo.Builder();
- method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
+ method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterBounds(int, float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo build();
method public void reset();
method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence);
diff --git a/api/removed.txt b/api/removed.txt
index 7f5f46c..3c16276 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -45,6 +45,8 @@ package android.view.inputmethod {
}
public final class CursorAnchorInfo implements android.os.Parcelable {
+ method public android.graphics.RectF getCharacterRect(int);
+ method public int getCharacterRectFlags(int);
method public boolean isInsertionMarkerClipped();
field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
@@ -55,6 +57,7 @@ package android.view.inputmethod {
}
public static final class CursorAnchorInfo.Builder {
+ method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
}
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index fe0f5b9..600fffe 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -35,9 +35,21 @@ import java.util.Objects;
* actually inserted.</p>
*/
public final class CursorAnchorInfo implements Parcelable {
+ /**
+ * The index of the first character of the selected text (inclusive). {@code -1} when there is
+ * no text selection.
+ */
private final int mSelectionStart;
+ /**
+ * The index of the first character of the selected text (exclusive). {@code -1} when there is
+ * no text selection.
+ */
private final int mSelectionEnd;
+ /**
+ * The index of the first character of the composing text (inclusive). {@code -1} when there is
+ * no composing text.
+ */
private final int mComposingTextStart;
/**
* The text, tracked as a composing region.
@@ -82,7 +94,7 @@ public final class CursorAnchorInfo implements Parcelable {
* Java chars, in the local coordinates that will be transformed with the transformation matrix
* when rendered on the screen.
*/
- private final SparseRectFArray mCharacterRects;
+ private final SparseRectFArray mCharacterBoundsArray;
/**
* Transformation matrix that is applied to any positional information of this class to
@@ -91,18 +103,24 @@ public final class CursorAnchorInfo implements Parcelable {
private final Matrix mMatrix;
/**
- * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
* insertion marker or character bounds have at least one visible region.
*/
public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
/**
- * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
* insertion marker or character bounds have at least one invisible (clipped) region.
*/
public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
/**
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
+ * insertion marker or character bounds is placed at right-to-left (RTL) character.
+ */
+ public static final int FLAG_IS_RTL = 0x04;
+
+ /**
* @removed
*/
public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
@@ -144,7 +162,7 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerTop = source.readFloat();
mInsertionMarkerBaseline = source.readFloat();
mInsertionMarkerBottom = source.readFloat();
- mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader());
+ mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
mMatrix = new Matrix();
mMatrix.setValues(source.createFloatArray());
}
@@ -166,7 +184,7 @@ public final class CursorAnchorInfo implements Parcelable {
dest.writeFloat(mInsertionMarkerTop);
dest.writeFloat(mInsertionMarkerBaseline);
dest.writeFloat(mInsertionMarkerBottom);
- dest.writeParcelable(mCharacterRects, flags);
+ dest.writeParcelable(mCharacterBoundsArray, flags);
final float[] matrixArray = new float[9];
mMatrix.getValues(matrixArray);
dest.writeFloatArray(matrixArray);
@@ -174,7 +192,6 @@ public final class CursorAnchorInfo implements Parcelable {
@Override
public int hashCode(){
- // TODO: Improve the hash function.
final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
+ mInsertionMarkerBaseline + mInsertionMarkerBottom;
int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
@@ -185,7 +202,7 @@ public final class CursorAnchorInfo implements Parcelable {
hash *= 31;
hash += Objects.hashCode(mComposingText);
hash *= 31;
- hash += Objects.hashCode(mCharacterRects);
+ hash += Objects.hashCode(mCharacterBoundsArray);
hash *= 31;
hash += Objects.hashCode(mMatrix);
return hash;
@@ -231,7 +248,7 @@ public final class CursorAnchorInfo implements Parcelable {
|| !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
return false;
}
- if (!Objects.equals(mCharacterRects, that.mCharacterRects)) {
+ if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
return false;
}
if (!Objects.equals(mMatrix, that.mMatrix)) {
@@ -250,7 +267,7 @@ public final class CursorAnchorInfo implements Parcelable {
+ " mInsertionMarkerTop=" + mInsertionMarkerTop
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
- + " mCharacterRects=" + Objects.toString(mCharacterRects)
+ + " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
+ " mMatrix=" + Objects.toString(mMatrix)
+ "}";
}
@@ -259,6 +276,19 @@ public final class CursorAnchorInfo implements Parcelable {
* Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
*/
public static final class Builder {
+ private int mSelectionStart = -1;
+ private int mSelectionEnd = -1;
+ private int mComposingTextStart = -1;
+ private CharSequence mComposingText = null;
+ private float mInsertionMarkerHorizontal = Float.NaN;
+ private float mInsertionMarkerTop = Float.NaN;
+ private float mInsertionMarkerBaseline = Float.NaN;
+ private float mInsertionMarkerBottom = Float.NaN;
+ private int mInsertionMarkerFlags = 0;
+ private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
+ private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
+ private boolean mMatrixInitialized = false;
+
/**
* Sets the text range of the selection. Calling this can be skipped if there is no
* selection.
@@ -268,8 +298,6 @@ public final class CursorAnchorInfo implements Parcelable {
mSelectionEnd = newEnd;
return this;
}
- private int mSelectionStart = -1;
- private int mSelectionEnd = -1;
/**
* Sets the text range of the composing text. Calling this can be skipped if there is
@@ -288,8 +316,6 @@ public final class CursorAnchorInfo implements Parcelable {
}
return this;
}
- private int mComposingTextStart = -1;
- private CharSequence mComposingText = null;
/**
* @removed
@@ -335,11 +361,33 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerFlags = flags;
return this;
}
- private float mInsertionMarkerHorizontal = Float.NaN;
- private float mInsertionMarkerTop = Float.NaN;
- private float mInsertionMarkerBaseline = Float.NaN;
- private float mInsertionMarkerBottom = Float.NaN;
- private int mInsertionMarkerFlags = 0;
+
+ /**
+ * Adds the bounding box of the character specified with the index.
+ *
+ * @param index index of the character in Java chars units. Must be specified in
+ * ascending order across successive calls.
+ * @param left x coordinate of the left edge of the character in local coordinates.
+ * @param top y coordinate of the top edge of the character in local coordinates.
+ * @param right x coordinate of the right edge of the character in local coordinates.
+ * @param bottom y coordinate of the bottom edge of the character in local coordinates.
+ * @param flags flags for this character bounds. See {@link #FLAG_HAS_VISIBLE_REGION},
+ * {@link #FLAG_HAS_INVISIBLE_REGION} and {@link #FLAG_IS_RTL}. These flags must be
+ * specified when necessary.
+ * @throws IllegalArgumentException If the index is a negative value, or not greater than
+ * all of the previously called indices.
+ */
+ public Builder addCharacterBounds(final int index, final float left, final float top,
+ final float right, final float bottom, final int flags) {
+ if (index < 0) {
+ throw new IllegalArgumentException("index must not be a negative integer.");
+ }
+ if (mCharacterBoundsArrayBuilder == null) {
+ mCharacterBoundsArrayBuilder = new SparseRectFArrayBuilder();
+ }
+ mCharacterBoundsArrayBuilder.append(index, left, top, right, bottom, flags);
+ return this;
+ }
/**
* Adds the bounding box of the character specified with the index.
@@ -358,21 +406,25 @@ public final class CursorAnchorInfo implements Parcelable {
* example.
* @throws IllegalArgumentException If the index is a negative value, or not greater than
* all of the previously called indices.
+ * @removed
*/
public Builder addCharacterRect(final int index, final float leadingEdgeX,
final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY,
final int flags) {
- if (index < 0) {
- throw new IllegalArgumentException("index must not be a negative integer.");
- }
- if (mCharacterRectBuilder == null) {
- mCharacterRectBuilder = new SparseRectFArrayBuilder();
+ final int newFlags;
+ final float left;
+ final float right;
+ if (leadingEdgeX <= trailingEdgeX) {
+ newFlags = flags;
+ left = leadingEdgeX;
+ right = trailingEdgeX;
+ } else {
+ newFlags = flags | FLAG_IS_RTL;
+ left = trailingEdgeX;
+ right = leadingEdgeX;
}
- mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
- trailingEdgeY, flags);
- return this;
+ return addCharacterBounds(index, left, leadingEdgeY, right, trailingEdgeY, newFlags);
}
- private SparseRectFArrayBuilder mCharacterRectBuilder = null;
/**
* Sets the matrix that transforms local coordinates into screen coordinates.
@@ -384,8 +436,6 @@ public final class CursorAnchorInfo implements Parcelable {
mMatrixInitialized = true;
return this;
}
- private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
- private boolean mMatrixInitialized = false;
/**
* @return {@link CursorAnchorInfo} using parameters in this {@link Builder}.
@@ -394,13 +444,15 @@ public final class CursorAnchorInfo implements Parcelable {
*/
public CursorAnchorInfo build() {
if (!mMatrixInitialized) {
- // Coordinate transformation matrix is mandatory when positional parameters are
- // specified.
- if ((mCharacterRectBuilder != null && !mCharacterRectBuilder.isEmpty()) ||
- !Float.isNaN(mInsertionMarkerHorizontal) ||
- !Float.isNaN(mInsertionMarkerTop) ||
- !Float.isNaN(mInsertionMarkerBaseline) ||
- !Float.isNaN(mInsertionMarkerBottom)) {
+ // Coordinate transformation matrix is mandatory when at least one positional
+ // parameter is specified.
+ final boolean hasCharacterBounds = (mCharacterBoundsArrayBuilder != null
+ && !mCharacterBoundsArrayBuilder.isEmpty());
+ if (hasCharacterBounds
+ || !Float.isNaN(mInsertionMarkerHorizontal)
+ || !Float.isNaN(mInsertionMarkerTop)
+ || !Float.isNaN(mInsertionMarkerBaseline)
+ || !Float.isNaN(mInsertionMarkerBottom)) {
throw new IllegalArgumentException("Coordinate transformation matrix is " +
"required when positional parameters are specified.");
}
@@ -424,8 +476,8 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerBottom = Float.NaN;
mMatrix.set(Matrix.IDENTITY_MATRIX);
mMatrixInitialized = false;
- if (mCharacterRectBuilder != null) {
- mCharacterRectBuilder.reset();
+ if (mCharacterBoundsArrayBuilder != null) {
+ mCharacterBoundsArrayBuilder.reset();
}
}
}
@@ -440,8 +492,8 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerTop = builder.mInsertionMarkerTop;
mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
- mCharacterRects = builder.mCharacterRectBuilder != null ?
- builder.mCharacterRectBuilder.build() : null;
+ mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
+ builder.mCharacterBoundsArrayBuilder.build() : null;
mMatrix = new Matrix(builder.mMatrix);
}
@@ -539,6 +591,19 @@ public final class CursorAnchorInfo implements Parcelable {
/**
* Returns a new instance of {@link RectF} that indicates the location of the character
* specified with the index.
+ * @param index index of the character in a Java chars.
+ * @return the character bounds in local coordinates as a new instance of {@link RectF}.
+ */
+ public RectF getCharacterBounds(final int index) {
+ if (mCharacterBoundsArray == null) {
+ return null;
+ }
+ return mCharacterBoundsArray.get(index);
+ }
+
+ /**
+ * Returns a new instance of {@link RectF} that indicates the location of the character
+ * specified with the index.
* <p>
* Note that coordinates are not necessarily contiguous or even monotonous, especially when
* RTL text and LTR text are mixed.
@@ -549,28 +614,32 @@ public final class CursorAnchorInfo implements Parcelable {
* the location. Note that the {@code left} field can be greater than the {@code right} field
* if the character is in RTL text. Returns {@code null} if no location information is
* available.
+ * @removed
*/
- // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
- // characters, and non-graphical chars.
public RectF getCharacterRect(final int index) {
- if (mCharacterRects == null) {
- return null;
+ return getCharacterBounds(index);
+ }
+
+ /**
+ * Returns the flags associated with the character bounds specified with the index.
+ * @param index index of the character in a Java chars.
+ * @return {@code 0} if no flag is specified.
+ */
+ public int getCharacterBoundsFlags(final int index) {
+ if (mCharacterBoundsArray == null) {
+ return 0;
}
- return mCharacterRects.get(index);
+ return mCharacterBoundsArray.getFlags(index, 0);
}
/**
* Returns the flags associated with the character rect specified with the index.
* @param index index of the character in a Java chars.
* @return {@code 0} if no flag is specified.
+ * @removed
*/
- // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
- // characters, and non-graphical chars.
public int getCharacterRectFlags(final int index) {
- if (mCharacterRects == null) {
- return 0;
- }
- return mCharacterRects.getFlags(index, 0);
+ return getCharacterBoundsFlags(index);
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 22138d0..3f168e8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3060,47 +3060,69 @@ public class Editor {
final CharSequence composingText = text.subSequence(composingTextStart,
composingTextEnd);
builder.setComposingText(composingTextStart, composingText);
- }
- // TODO: Optimize this loop by caching the result.
- for (int offset = composingTextStart; offset < composingTextEnd; offset++) {
- if (offset < 0) {
- continue;
- }
- final boolean isRtl = layout.isRtlCharAt(offset);
- final int line = layout.getLineForOffset(offset);
- final int nextCharIndex = offset + 1;
- final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset);
- final float localTrailingEdgeX;
- if (nextCharIndex != layout.getLineEnd(line)) {
- localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex);
- } else if (isRtl) {
- localTrailingEdgeX = layout.getLineLeft(line);
- } else {
- localTrailingEdgeX = layout.getLineRight(line);
- }
- final float leadingEdgeX = localLeadingEdgeX
- + viewportToContentHorizontalOffset;
- final float trailingEdgeX = localTrailingEdgeX
- + viewportToContentHorizontalOffset;
- final float top = layout.getLineTop(line) + viewportToContentVerticalOffset;
- final float bottom = layout.getLineBottom(line)
- + viewportToContentVerticalOffset;
- // TODO: Check right-top and left-bottom as well.
- final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
- final boolean isTrailingEdgeBottomVisible =
- isPositionVisible(trailingEdgeX, bottom);
- int characterRectFlags = 0;
- if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
- characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
- }
- if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) {
- characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+
+ final int minLine = layout.getLineForOffset(composingTextStart);
+ final int maxLine = layout.getLineForOffset(composingTextEnd - 1);
+ for (int line = minLine; line <= maxLine; ++line) {
+ final int lineStart = layout.getLineStart(line);
+ final int lineEnd = layout.getLineEnd(line);
+ final int offsetStart = Math.max(lineStart, composingTextStart);
+ final int offsetEnd = Math.min(lineEnd, composingTextEnd);
+ final boolean ltrLine =
+ layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
+ final float[] widths = new float[offsetEnd - offsetStart];
+ layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths);
+ final float top = layout.getLineTop(line);
+ final float bottom = layout.getLineBottom(line);
+ for (int offset = offsetStart; offset < offsetEnd; ++offset) {
+ final float charWidth = widths[offset - offsetStart];
+ final boolean isRtl = layout.isRtlCharAt(offset);
+ final float primary = layout.getPrimaryHorizontal(offset);
+ final float secondary = layout.getSecondaryHorizontal(offset);
+ // TODO: This doesn't work perfectly for text with custom styles and
+ // TAB chars.
+ final float left;
+ final float right;
+ if (ltrLine) {
+ if (isRtl) {
+ left = secondary - charWidth;
+ right = secondary;
+ } else {
+ left = primary;
+ right = primary + charWidth;
+ }
+ } else {
+ if (!isRtl) {
+ left = secondary;
+ right = secondary + charWidth;
+ } else {
+ left = primary - charWidth;
+ right = primary;
+ }
+ }
+ // TODO: Check top-right and bottom-left as well.
+ final float localLeft = left + viewportToContentHorizontalOffset;
+ final float localRight = right + viewportToContentHorizontalOffset;
+ final float localTop = top + viewportToContentVerticalOffset;
+ final float localBottom = bottom + viewportToContentVerticalOffset;
+ final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop);
+ final boolean isBottomRightVisible =
+ isPositionVisible(localRight, localBottom);
+ int characterBoundsFlags = 0;
+ if (isTopLeftVisible || isBottomRightVisible) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+ }
+ if (!isTopLeftVisible || !isTopLeftVisible) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+ }
+ if (isRtl) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+ }
+ // Here offset is the index in Java chars.
+ builder.addCharacterBounds(offset, localLeft, localTop, localRight,
+ localBottom, characterBoundsFlags);
+ }
}
- // Here offset is the index in Java chars.
- // TODO: We must have a well-defined specification. For example, how
- // surrogate pairs and composition letters are handled must be documented.
- builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom,
- characterRectFlags);
}
}
@@ -3127,6 +3149,9 @@ public class Editor {
if (!isTopVisible || !isBottomVisible) {
insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
}
+ if (layout.isRtlCharAt(offset)) {
+ insertionMarkerFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+ }
builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
}