Unhide getTextRunCursor APIs

This API is necessary for identifying the cursor locations.

Bug: 112327179
Test: atest android.graphics.cts.PaintTest
Change-Id: Ief6770bd622a296ae356094fe3ce58e9c4371088
This commit is contained in:
Seigo Nonaka
2018-09-17 14:09:25 -07:00
parent 93890b2e2e
commit fa95b83df7
7 changed files with 109 additions and 84 deletions

View File

@@ -14017,6 +14017,8 @@ package android.graphics {
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 int getTextRunCursor(char[], int, int, boolean, int, int);
method public int getTextRunCursor(java.lang.CharSequence, int, int, boolean, int, int);
method public float getTextScaleX();
method public float getTextSize();
method public float getTextSkewX();
@@ -14083,6 +14085,11 @@ package android.graphics {
method public void setWordSpacing(float);
method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
field public static final int CURSOR_AFTER = 0; // 0x0
field public static final int CURSOR_AT = 4; // 0x4
field public static final int CURSOR_AT_OR_AFTER = 1; // 0x1
field public static final int CURSOR_AT_OR_BEFORE = 3; // 0x3
field public static final int CURSOR_BEFORE = 2; // 0x2
field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
field public static final int DITHER_FLAG = 4; // 0x4
field public static final int EMBEDDED_BITMAP_TEXT_FLAG = 1024; // 0x400

View File

@@ -58,6 +58,6 @@ public interface GraphicsOperations extends CharSequence {
/**
* Just like {@link Paint#getTextRunCursor}.
*/
int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
int getTextRunCursor(int contextStart, int contextEnd, boolean isRtl, int offset,
int cursorOpt, Paint p);
}

View File

@@ -1551,7 +1551,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
*
* @param contextStart the start index of the context
* @param contextEnd the (non-inclusive) end index of the context
* @param dir either DIRECTION_RTL or DIRECTION_LTR
* @param dir 1 if the run is RTL, otherwise 0
* @param offset the cursor position to move from
* @param cursorOpt how to move the cursor, one of CURSOR_AFTER,
* CURSOR_AT_OR_AFTER, CURSOR_BEFORE,
@@ -1563,21 +1563,28 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
@Deprecated
public int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
int cursorOpt, Paint p) {
return getTextRunCursor(contextStart, contextEnd, dir == 1, offset, cursorOpt, p);
}
/** @hide */
@Override
public int getTextRunCursor(int contextStart, int contextEnd, boolean isRtl, int offset,
int cursorOpt, Paint p) {
int ret;
int contextLen = contextEnd - contextStart;
if (contextEnd <= mGapStart) {
ret = p.getTextRunCursor(mText, contextStart, contextLen,
dir, offset, cursorOpt);
isRtl, offset, cursorOpt);
} else if (contextStart >= mGapStart) {
ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen,
dir, offset + mGapLength, cursorOpt) - mGapLength;
isRtl, offset + mGapLength, cursorOpt) - mGapLength;
} else {
char[] buf = TextUtils.obtain(contextLen);
getChars(contextStart, contextEnd, buf, 0);
ret = p.getTextRunCursor(buf, 0, contextLen,
dir, offset - contextStart, cursorOpt) + contextStart;
isRtl, offset - contextStart, cursorOpt) + contextStart;
TextUtils.recycle(buf);
}

View File

@@ -802,14 +802,13 @@ public class TextLine {
}
}
int dir = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
int cursorOpt = after ? Paint.CURSOR_AFTER : Paint.CURSOR_BEFORE;
if (mCharsValid) {
return wp.getTextRunCursor(mChars, spanStart, spanLimit - spanStart,
dir, offset, cursorOpt);
runIsRtl, offset, cursorOpt);
} else {
return wp.getTextRunCursor(mText, mStart + spanStart,
mStart + spanLimit, dir, mStart + offset, cursorOpt) - mStart;
mStart + spanLimit, runIsRtl, mStart + offset, cursorOpt) - mStart;
}
}

View File

@@ -310,7 +310,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
return len;
}
offset = paint.getTextRunCursor(text, offset, len, Paint.DIRECTION_LTR /* not used */,
offset = paint.getTextRunCursor(text, offset, len, false /* LTR, not used */,
offset, Paint.CURSOR_AFTER);
return adjustReplacementSpan(text, offset, false /* move to the end */);

View File

@@ -12491,11 +12491,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
advancesIndex);
}
public int getTextRunCursor(int contextStart, int contextEnd, int dir,
public int getTextRunCursor(int contextStart, int contextEnd, boolean isRtl,
int offset, int cursorOpt, Paint p) {
int contextCount = contextEnd - contextStart;
return p.getTextRunCursor(mChars, contextStart + mStart,
contextCount, dir, offset + mStart, cursorOpt);
contextCount, isRtl, offset + mStart, cursorOpt);
}
}

View File

@@ -17,6 +17,7 @@
package android.graphics;
import android.annotation.ColorInt;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -37,6 +38,8 @@ import dalvik.annotation.optimization.FastNative;
import libcore.util.NativeAllocationRegistry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -309,38 +312,47 @@ public class Paint {
*/
public static final int DIRECTION_RTL = 1;
/** @hide */
@IntDef(prefix = { "CURSOR_" }, value = {
CURSOR_AFTER, CURSOR_AT_OR_AFTER, CURSOR_BEFORE, CURSOR_AT_OR_BEFORE
})
@Retention(RetentionPolicy.SOURCE)
public @interface CursorOption {}
/**
* Option for getTextRunCursor to compute the valid cursor after
* offset or the limit of the context, whichever is less.
* @hide
* Option for getTextRunCursor.
*
* Compute the valid cursor after offset or the limit of the context, whichever is less.
*/
public static final int CURSOR_AFTER = 0;
/**
* Option for getTextRunCursor to compute the valid cursor at or after
* the offset or the limit of the context, whichever is less.
* @hide
* Option for getTextRunCursor.
*
* Compute the valid cursor at or after the offset or the limit of the context, whichever is
* less.
*/
public static final int CURSOR_AT_OR_AFTER = 1;
/**
* Option for getTextRunCursor to compute the valid cursor before
* offset or the start of the context, whichever is greater.
* @hide
* Option for getTextRunCursor.
*
* Compute the valid cursor before offset or the start of the context, whichever is greater.
*/
public static final int CURSOR_BEFORE = 2;
/**
* Option for getTextRunCursor to compute the valid cursor at or before
* offset or the start of the context, whichever is greater.
* @hide
* Option for getTextRunCursor.
*
* Compute the valid cursor at or before offset or the start of the context, whichever is
* greater.
*/
public static final int CURSOR_AT_OR_BEFORE = 3;
/**
* Option for getTextRunCursor to return offset if the cursor at offset
* is valid, or -1 if it isn't.
* @hide
* Option for getTextRunCursor.
*
* Return offset if the cursor at offset is valid, or -1 if it isn't.
*/
public static final int CURSOR_AT = 4;
@@ -2410,34 +2422,32 @@ public class Paint {
}
/**
* Returns the next cursor position in the run. This avoids placing the
* cursor between surrogates, between characters that form conjuncts,
* between base characters and combining marks, or within a reordering
* cluster.
* Returns the next cursor position in the run.
*
* <p>ContextStart and offset are relative to the start of text.
* The context is the shaping context for cursor movement, generally
* the bounds of the metric span enclosing the cursor in the direction of
* movement.
* This avoids placing the cursor between surrogates, between characters that form conjuncts,
* between base characters and combining marks, or within a reordering cluster.
*
* <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
* cursor position, this returns -1. Otherwise this will never return a
* value before contextStart or after contextStart + contextLength.
* <p>
* ContextStart and offset are relative to the start of text.
* The context is the shaping context for cursor movement, generally the bounds of the metric
* span enclosing the cursor in the direction of movement.
*
* <p>
* If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
* returns -1. Otherwise this will never return a value before contextStart or after
* contextStart + contextLength.
*
* @param text the text
* @param contextStart the start of the context
* @param contextLength the length of the context
* @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
* @param isRtl true if the paragraph context is RTL, otherwise false
* @param offset the cursor position to move from
* @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
* {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
* {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
* @param cursorOpt how to move the cursor
* @return the offset of the next position, or -1
* @hide
*/
@UnsupportedAppUsage
public int getTextRunCursor(char[] text, int contextStart, int contextLength,
int dir, int offset, int cursorOpt) {
public int getTextRunCursor(@NonNull char[] text, @IntRange(from = 0) int contextStart,
@IntRange(from = 0) int contextLength, boolean isRtl, @IntRange(from = 0) int offset,
@CursorOption int cursorOpt) {
int contextEnd = contextStart + contextLength;
if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
| (offset - contextStart) | (contextEnd - offset)
@@ -2446,85 +2456,87 @@ public class Paint {
throw new IndexOutOfBoundsException();
}
return nGetTextRunCursor(mNativePaint, text, contextStart, contextLength, dir, offset,
cursorOpt);
return nGetTextRunCursor(mNativePaint, text, contextStart, contextLength,
isRtl ? DIRECTION_RTL : DIRECTION_LTR, offset, cursorOpt);
}
/**
* Returns the next cursor position in the run. This avoids placing the
* cursor between surrogates, between characters that form conjuncts,
* between base characters and combining marks, or within a reordering
* cluster.
* Returns the next cursor position in the run.
*
* <p>ContextStart, contextEnd, and offset are relative to the start of
* This avoids placing the cursor between surrogates, between characters that form conjuncts,
* between base characters and combining marks, or within a reordering cluster.
*
* <p>
* ContextStart, contextEnd, and offset are relative to the start of
* text. The context is the shaping context for cursor movement, generally
* the bounds of the metric span enclosing the cursor in the direction of
* movement.
*
* <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
* cursor position, this returns -1. Otherwise this will never return a
* value before contextStart or after contextEnd.
* <p>
* If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
* returns -1. Otherwise this will never return a value before contextStart or after
* contextEnd.
*
* @param text the text
* @param contextStart the start of the context
* @param contextEnd the end of the context
* @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
* @param isRtl true if the paragraph context is RTL, otherwise false
* @param offset the cursor position to move from
* @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
* {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
* {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
* @param cursorOpt how to move the cursor
* @return the offset of the next position, or -1
* @hide
*/
public int getTextRunCursor(CharSequence text, int contextStart,
int contextEnd, int dir, int offset, int cursorOpt) {
public int getTextRunCursor(@NonNull CharSequence text, @IntRange(from = 0) int contextStart,
@IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset,
@CursorOption int cursorOpt) {
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
return getTextRunCursor(text.toString(), contextStart, contextEnd,
dir, offset, cursorOpt);
isRtl, offset, cursorOpt);
}
if (text instanceof GraphicsOperations) {
return ((GraphicsOperations) text).getTextRunCursor(
contextStart, contextEnd, dir, offset, cursorOpt, this);
contextStart, contextEnd, isRtl, offset, cursorOpt, this);
}
int contextLen = contextEnd - contextStart;
char[] buf = TemporaryBuffer.obtain(contextLen);
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
int relPos = getTextRunCursor(buf, 0, contextLen, dir, offset - contextStart, cursorOpt);
int relPos = getTextRunCursor(buf, 0, contextLen, isRtl, offset - contextStart, cursorOpt);
TemporaryBuffer.recycle(buf);
return (relPos == -1) ? -1 : relPos + contextStart;
}
/**
* Returns the next cursor position in the run. This avoids placing the
* cursor between surrogates, between characters that form conjuncts,
* between base characters and combining marks, or within a reordering
* cluster.
* Returns the next cursor position in the run.
*
* <p>ContextStart, contextEnd, and offset are relative to the start of
* text. The context is the shaping context for cursor movement, generally
* the bounds of the metric span enclosing the cursor in the direction of
* movement.
* This avoids placing the cursor between surrogates, between characters that form conjuncts,
* between base characters and combining marks, or within a reordering cluster.
*
* <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
* cursor position, this returns -1. Otherwise this will never return a
* value before contextStart or after contextEnd.
* <p>
* ContextStart, contextEnd, and offset are relative to the start of text. The context is the
* shaping context for cursor movement, generally the bounds of the metric span enclosing the
* cursor in the direction of movement.
* </p>
*
* <p>
* If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
* returns -1. Otherwise this will never return a value before contextStart or after
* contextEnd.
* </p>
*
* @param text the text
* @param contextStart the start of the context
* @param contextEnd the end of the context
* @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
* @param isRtl true if the paragraph context is RTL, otherwise false.
* @param offset the cursor position to move from
* @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
* {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
* {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
* @param cursorOpt how to move the cursor
* @return the offset of the next position, or -1
* @hide
*/
public int getTextRunCursor(String text, int contextStart, int contextEnd,
int dir, int offset, int cursorOpt) {
public int getTextRunCursor(@NonNull String text, @IntRange(from = 0) int contextStart,
@IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset,
@CursorOption int cursorOpt) {
if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
| (offset - contextStart) | (contextEnd - offset)
| (text.length() - contextEnd) | cursorOpt) < 0)
@@ -2532,8 +2544,8 @@ public class Paint {
throw new IndexOutOfBoundsException();
}
return nGetTextRunCursor(mNativePaint, text, contextStart, contextEnd, dir, offset,
cursorOpt);
return nGetTextRunCursor(mNativePaint, text, contextStart, contextEnd,
isRtl ? DIRECTION_RTL : DIRECTION_LTR, offset, cursorOpt);
}
/**