Search in sources :

Example 6 with ReplacementSpan

use of android.text.style.ReplacementSpan in project android_frameworks_base by ParanoidAndroid.

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 flags = 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, flags, offset, cursorOpt);
    } else {
        return wp.getTextRunCursor(mText, mStart + spanStart, mStart + spanLimit, flags, mStart + offset, cursorOpt) - mStart;
    }
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint) MetricAffectingSpan(android.text.style.MetricAffectingSpan)

Example 7 with ReplacementSpan

use of android.text.style.ReplacementSpan in project android_frameworks_base by ParanoidAndroid.

the class MeasuredText method addStyleRun.

float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, Paint.FontMetricsInt fm) {
    TextPaint workPaint = mWorkPaint;
    workPaint.set(paint);
    // XXX paint should not have a baseline shift, but...
    workPaint.baselineShift = 0;
    ReplacementSpan replacement = null;
    for (int i = 0; i < spans.length; i++) {
        MetricAffectingSpan span = spans[i];
        if (span instanceof ReplacementSpan) {
            replacement = (ReplacementSpan) span;
        } else {
            span.updateMeasureState(workPaint);
        }
    }
    float wid;
    if (replacement == null) {
        wid = addStyleRun(workPaint, len, fm);
    } else {
        // Use original text.  Shouldn't matter.
        wid = replacement.getSize(workPaint, mText, mTextStart + mPos, mTextStart + mPos + len, fm);
        float[] w = mWidths;
        w[mPos] = wid;
        for (int i = mPos + 1, e = mPos + len; i < e; i++) w[i] = 0;
        mPos += len;
    }
    if (fm != null) {
        if (workPaint.baselineShift < 0) {
            fm.ascent += workPaint.baselineShift;
            fm.top += workPaint.baselineShift;
        } else {
            fm.descent += workPaint.baselineShift;
            fm.bottom += workPaint.baselineShift;
        }
    }
    return wid;
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint) MetricAffectingSpan(android.text.style.MetricAffectingSpan)

Example 8 with ReplacementSpan

use of android.text.style.ReplacementSpan in project XobotOS by xamarin.

the class TextLine method set.

/**
     * Initializes a TextLine and prepares it for use.
     *
     * @param paint the base paint for the line
     * @param text the text, can be Styled
     * @param start the start of the line relative to the text
     * @param limit the limit of the line relative to the text
     * @param dir the paragraph direction of this line
     * @param directions the directions information of this line
     * @param hasTabs true if the line might contain tabs or emoji
     * @param tabStops the tabStops. Can be null.
     */
void set(TextPaint paint, CharSequence text, int start, int limit, int dir, Directions directions, boolean hasTabs, TabStops tabStops) {
    mPaint = paint;
    mText = text;
    mStart = start;
    mLen = limit - start;
    mDir = dir;
    mDirections = directions;
    if (mDirections == null) {
        throw new IllegalArgumentException("Directions cannot be null");
    }
    mHasTabs = hasTabs;
    mSpanned = null;
    boolean hasReplacement = false;
    if (text instanceof Spanned) {
        mSpanned = (Spanned) text;
        ReplacementSpan[] spans = mSpanned.getSpans(start, limit, ReplacementSpan.class);
        spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
        hasReplacement = spans.length > 0;
    }
    mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
    if (mCharsValid) {
        if (mChars == null || mChars.length < mLen) {
            mChars = new char[ArrayUtils.idealCharArraySize(mLen)];
        }
        TextUtils.getChars(text, start, limit, mChars, 0);
        if (hasReplacement) {
            // Handle these all at once so we don't have to do it as we go.
            // Replace the first character of each replacement run with the
            // object-replacement character and the remainder with zero width
            // non-break space aka BOM.  Cursor movement code skips these
            // zero-width characters.
            char[] chars = mChars;
            for (int i = start, inext; i < limit; i = inext) {
                inext = mSpanned.nextSpanTransition(i, limit, ReplacementSpan.class);
                ReplacementSpan[] spans = mSpanned.getSpans(i, inext, ReplacementSpan.class);
                spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
                if (spans.length > 0) {
                    // transition into a span
                    chars[i - start] = '';
                    for (int j = i - start + 1, e = inext - start; j < e; ++j) {
                        // used as ZWNBS, marks positions to skip
                        chars[j] = '';
                    }
                }
            }
        }
    }
    mTabs = tabStops;
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint)

Example 9 with ReplacementSpan

use of android.text.style.ReplacementSpan in project XobotOS by xamarin.

the class MeasuredText method setPara.

/**
     * Analyzes text for bidirectional runs.  Allocates working buffers.
     */
void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir) {
    mText = text;
    mTextStart = start;
    int len = end - start;
    mLen = len;
    mPos = 0;
    if (mWidths == null || mWidths.length < len) {
        mWidths = new float[ArrayUtils.idealFloatArraySize(len)];
    }
    if (mChars == null || mChars.length < len) {
        mChars = new char[ArrayUtils.idealCharArraySize(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;
            for (int j = startInPara; j < endInPara; j++) {
                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 = new byte[ArrayUtils.idealByteArraySize(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;
    }
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint)

Example 10 with ReplacementSpan

use of android.text.style.ReplacementSpan in project android_frameworks_base by ResurrectionRemix.

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;
    }
}
Also used : ReplacementSpan(android.text.style.ReplacementSpan) Paint(android.graphics.Paint) MetricAffectingSpan(android.text.style.MetricAffectingSpan)

Aggregations

Paint (android.graphics.Paint)43 ReplacementSpan (android.text.style.ReplacementSpan)43 MetricAffectingSpan (android.text.style.MetricAffectingSpan)22 CharacterStyle (android.text.style.CharacterStyle)8 TextPaint (android.text.TextPaint)2