use of android.text.style.ReplacementSpan in project android_frameworks_base by crdroidandroid.
the class BaseKeyListener method adjustReplacementSpan.
// Returns the offset of the replacement span edge if the offset is inside of the replacement
// span. Otherwise, does nothing and returns the input offset value.
private static int adjustReplacementSpan(CharSequence text, int offset, boolean moveToStart) {
if (!(text instanceof Spanned)) {
return offset;
}
ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset, ReplacementSpan.class);
for (int i = 0; i < spans.length; i++) {
final int start = ((Spanned) text).getSpanStart(spans[i]);
final int end = ((Spanned) text).getSpanEnd(spans[i]);
if (start < offset && end > offset) {
offset = moveToStart ? start : end;
}
}
return offset;
}
use of android.text.style.ReplacementSpan in project android_frameworks_base by crdroidandroid.
the class TextLine method getOffsetBeforeAfter.
/**
* Returns the next valid offset within this directional run, skipping
* conjuncts and zero-width characters. This should not be called to walk
* off the end of the line, since the returned values might not be valid
* on neighboring lines. If the returned offset is less than zero or
* greater than the line length, the offset should be recomputed on the
* preceding or following line, respectively.
*
* @param runIndex the run index
* @param runStart the start of the run
* @param runLimit the limit of the run
* @param runIsRtl true if the run is right-to-left
* @param offset the offset
* @param after true if the new offset should logically follow the provided
* offset
* @return the new offset
*/
private int getOffsetBeforeAfter(int runIndex, int runStart, int runLimit, boolean runIsRtl, int offset, boolean after) {
if (runIndex < 0 || offset == (after ? mLen : 0)) {
// return accurate values. These are a guess.
if (after) {
return TextUtils.getOffsetAfter(mText, offset + mStart) - mStart;
}
return TextUtils.getOffsetBefore(mText, offset + mStart) - mStart;
}
TextPaint wp = mWorkPaint;
wp.set(mPaint);
int spanStart = runStart;
int spanLimit;
if (mSpanned == null) {
spanLimit = runLimit;
} else {
int target = after ? offset + 1 : offset;
int limit = mStart + runLimit;
while (true) {
spanLimit = mSpanned.nextSpanTransition(mStart + spanStart, limit, MetricAffectingSpan.class) - mStart;
if (spanLimit >= target) {
break;
}
spanStart = spanLimit;
}
MetricAffectingSpan[] spans = mSpanned.getSpans(mStart + spanStart, mStart + spanLimit, MetricAffectingSpan.class);
spans = TextUtils.removeEmptySpans(spans, mSpanned, MetricAffectingSpan.class);
if (spans.length > 0) {
ReplacementSpan replacement = null;
for (int j = 0; j < spans.length; j++) {
MetricAffectingSpan span = spans[j];
if (span instanceof ReplacementSpan) {
replacement = (ReplacementSpan) span;
} else {
span.updateMeasureState(wp);
}
}
if (replacement != null) {
// the start or end of this span.
return after ? spanLimit : spanStart;
}
}
}
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);
} else {
return wp.getTextRunCursor(mText, mStart + spanStart, mStart + spanLimit, dir, mStart + offset, cursorOpt) - mStart;
}
}
use of android.text.style.ReplacementSpan in project android_frameworks_base by crdroidandroid.
the class MeasuredText method setPara.
/**
* Analyzes text for bidirectional runs. Allocates working buffers.
*/
void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir, StaticLayout.Builder builder) {
mBuilder = builder;
mText = text;
mTextStart = start;
int len = end - start;
mLen = len;
mPos = 0;
if (mWidths == null || mWidths.length < len) {
mWidths = ArrayUtils.newUnpaddedFloatArray(len);
}
if (mChars == null || mChars.length < len) {
mChars = ArrayUtils.newUnpaddedCharArray(len);
}
TextUtils.getChars(text, start, end, mChars, 0);
if (text instanceof Spanned) {
Spanned spanned = (Spanned) text;
ReplacementSpan[] spans = spanned.getSpans(start, end, ReplacementSpan.class);
for (int i = 0; i < spans.length; i++) {
int startInPara = spanned.getSpanStart(spans[i]) - start;
int endInPara = spanned.getSpanEnd(spans[i]) - start;
// The span interval may be larger and must be restricted to [start, end[
if (startInPara < 0)
startInPara = 0;
if (endInPara > len)
endInPara = len;
for (int j = startInPara; j < endInPara; j++) {
// object replacement character
mChars[j] = '';
}
}
}
if ((textDir == TextDirectionHeuristics.LTR || textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR || textDir == TextDirectionHeuristics.ANYRTL_LTR) && TextUtils.doesNotNeedBidi(mChars, 0, len)) {
mDir = Layout.DIR_LEFT_TO_RIGHT;
mEasy = true;
} else {
if (mLevels == null || mLevels.length < len) {
mLevels = ArrayUtils.newUnpaddedByteArray(len);
}
int bidiRequest;
if (textDir == TextDirectionHeuristics.LTR) {
bidiRequest = Layout.DIR_REQUEST_LTR;
} else if (textDir == TextDirectionHeuristics.RTL) {
bidiRequest = Layout.DIR_REQUEST_RTL;
} else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR) {
bidiRequest = Layout.DIR_REQUEST_DEFAULT_LTR;
} else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_RTL) {
bidiRequest = Layout.DIR_REQUEST_DEFAULT_RTL;
} else {
boolean isRtl = textDir.isRtl(mChars, 0, len);
bidiRequest = isRtl ? Layout.DIR_REQUEST_RTL : Layout.DIR_REQUEST_LTR;
}
mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels, len, false);
mEasy = false;
}
}
Aggregations