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

Commit 0c702b88 authored by Doug Felt's avatar Doug Felt Committed by Kenny Root
Browse files

Move shaping to native.

Add internal API (getTextRunAdvances) to Paint, use when measuring.
Add internal API (getTextRunCursor) to Paint, use when determining
valid cursor positions.

Remove java-level shaping code.  Remove 'prep' code in TextLine
(except for replacement text) since shaping now is done on the fly as
needed in native.

Provide explicit shaping context bounds to internal text measuring,
cursor movement, and rendering APIs.

Update for to changes in external API in ushape.h.

Change-Id: I146958b624802ce8553125e5c3c6c03031bc9608
parent a9aaf8ff
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ extends CharSequence
     * Just like {@link Canvas#drawTextRun}.
     * {@hide}
     */
    void drawTextRun(Canvas c, int start, int end,
    void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
            float x, float y, int flags, Paint p);

   /**
@@ -45,9 +45,22 @@ extends CharSequence
     */
    float measureText(int start, int end, Paint p);


    /**
     * Just like {@link Paint#getTextWidths}.
     */
    public int getTextWidths(int start, int end, float[] widths, Paint p);

    /**
     * Just like {@link Paint#getTextRunAdvances}.
     * @hide
     */
    float getTextRunAdvances(int start, int end, int contextStart, int contextEnd,
            int flags, float[] advances, int advancesIndex, Paint paint);

    /**
     * Just like {@link Paint#getTextRunCursor}.
     * @hide
     */
    int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset,
            int cursorOpt, Paint p);
}
+19 −20
Original line number Diff line number Diff line
@@ -1728,4 +1728,3 @@ public abstract class Layout {
    /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT =
        new Directions(new int[] { 0, RUN_LENGTH_MASK | RUN_RTL_FLAG });
}
+27 −48
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@ package android.text;

import com.android.internal.util.ArrayUtils;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.icu.text.ArabicShaping;
import android.text.style.MetricAffectingSpan;
import android.text.style.ReplacementSpan;
import android.util.Log;
@@ -37,7 +37,6 @@ class MeasuredText {
    /* package */ boolean mEasy;
    /* package */ int mLen;
    private int mPos;
    private float[] mWorkWidths; // temp buffer for Paint.measureText, arrgh
    private TextPaint mWorkPaint;

    private MeasuredText() {
@@ -80,8 +79,7 @@ class MeasuredText {
    }

    /**
     * Analyzes text for
     * bidirectional runs.  Allocates working buffers.
     * Analyzes text for bidirectional runs.  Allocates working buffers.
     */
    /* package */
    void setPara(CharSequence text, int start, int end, int bidiRequest) {
@@ -94,7 +92,6 @@ class MeasuredText {

        if (mWidths == null || mWidths.length < len) {
            mWidths = new float[ArrayUtils.idealFloatArraySize(len)];
            mWorkWidths = new float[mWidths.length];
        }
        if (mChars == null || mChars.length < len) {
            mChars = new char[ArrayUtils.idealCharArraySize(len)];
@@ -116,7 +113,7 @@ class MeasuredText {
        }

        if (TextUtils.doesNotNeedBidi(mChars, 0, len)) {
            mDir = 1;
            mDir = Layout.DIR_LEFT_TO_RIGHT;
            mEasy = true;
        } else {
            if (mLevels == null || mLevels.length < len) {
@@ -124,56 +121,38 @@ class MeasuredText {
            }
            mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels, len, false);
            mEasy = false;

            // shape
            if (mLen > 0) {
                byte[] levels = mLevels;
                char[] chars = mChars;
                byte level = levels[0];
                int pi = 0;
                for (int i = 1, e = mLen;; ++i) {
                    if (i == e || levels[i] != level) {
                        if ((level & 0x1) != 0) {
                            AndroidCharacter.mirror(chars, pi, i - pi);
                            ArabicShaping.SHAPER.shape(chars, pi, i - pi);
                        }
                        if (i == e) {
                            break;
                        }
                        pi = i;
                        level = levels[i];
                    }
                }
            }
        }
    }

    float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) {
        int p = mPos;
        float[] w = mWidths, ww = mWorkWidths;
        int count = paint.getTextWidths(mChars, p, len, ww);
        int width = 0;
        if (count < len) {
            // must have surrogate pairs in here, pad out the array with zero
            // for the trailing surrogates
            char[] chars = mChars;
            for (int i = 0, e = mLen; i < count; ++i) {
                width += (w[p++] = ww[i]);
                if (p < e && chars[p] >= '\udc00' && chars[p] < '\ue000' &&
                        chars[p-1] >= '\ud800' && chars[p-1] < '\udc00') {
                    w[p++] = 0;
        if (fm != null) {
            paint.getFontMetricsInt(fm);
        }

        int p = mPos;
        mPos = p + len;

        if (mEasy) {
            int flags = mDir == Layout.DIR_LEFT_TO_RIGHT
                ? Canvas.DIRECTION_LTR : Canvas.DIRECTION_RTL;
            return paint.getTextRunAdvances(mChars, p, len, p, len, flags, mWidths, p);
        }
        } else {
            for (int i = 0; i < len; ++i) {
                width += (w[p++] = ww[i]);

        float totalAdvance = 0;
        int level = mLevels[p];
        for (int q = p, i = p + 1, e = p + len;; ++i) {
            if (i == e || mLevels[i] != level) {
                int flags = (level & 0x1) == 0 ? Canvas.DIRECTION_LTR : Canvas.DIRECTION_RTL;
                totalAdvance +=
                        paint.getTextRunAdvances(mChars, q, i - q, q, i - q, flags, mWidths, q);
                if (i == e) {
                    break;
                }
                q = i;
                level = mLevels[i];
            }
        mPos = p;
        if (fm != null) {
            paint.getFontMetricsInt(fm);
        }
        return width;
        return totalAdvance;
    }

    float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len,
+65 −21
Original line number Diff line number Diff line
@@ -1055,35 +1055,27 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
        }
    }


    /**
     * Don't call this yourself -- exists for Canvas to use internally.
     * {@hide}
     */
    public void drawTextRun(Canvas c, int start, int end,
            int contextStart, int contextEnd,
            float x, float y, int flags, Paint p) {
        checkRange("drawTextRun", start, end);

        // Assume context requires no more than 8 chars on either side.
        // This is ample, only decomposed U+FDFA falls into this
        // category, and no one should put a style break within it 
        // anyway.
        int cstart = start - 8;
        if (cstart < 0) {
            cstart = 0;
        }
        int cend = end + 8;
        int max = length();
        if (cend > max) {
            cend = max;
        }
        if (cend <= mGapStart) {
            c.drawTextRun(mText, start, end - start, x, y, flags, p);
        } else if (cstart >= mGapStart) {
            c.drawTextRun(mText, start + mGapLength, end - start, x, y, flags, p);
        int contextLen = contextEnd - contextStart;
        int len = end - start;
        if (contextEnd <= mGapStart) {
            c.drawTextRun(mText, start, len, contextStart, contextLen, x, y, flags, p);
        } else if (contextStart >= mGapStart) {
            c.drawTextRun(mText, start + mGapLength, len, contextStart + mGapLength,
                    contextLen, x, y, flags, p);
        } else {
            char[] buf = TextUtils.obtain(cend - cstart);
            getChars(cstart, cend, buf, 0);
            c.drawTextRun(buf, start - cstart, end - start, x, y, flags, p);
            char[] buf = TextUtils.obtain(contextLen);
            getChars(contextStart, contextEnd, buf, 0);
            c.drawTextRun(buf, start - contextStart, len, 0, contextLen, x, y, flags, p);
            TextUtils.recycle(buf);
        }
    }
@@ -1137,6 +1129,58 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
        return ret;
    }

    /**
     * Don't call this yourself -- exists for Paint to use internally.
     * {@hide}
     */
    public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags,
            float[] advances, int advancesPos, Paint p) {

        float ret;

        int contextLen = contextEnd - contextStart;
        int len = end - start;

        if (end <= mGapStart) {
            ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen,
                    flags, advances, advancesPos);
        } else if (start >= mGapStart) {
            ret = p.getTextRunAdvances(mText, start + mGapLength, len,
                    contextStart + mGapLength, contextLen, flags, advances, advancesPos);
        } else {
            char[] buf = TextUtils.obtain(contextLen);
            getChars(contextStart, contextEnd, buf, 0);
            ret = p.getTextRunAdvances(buf, start - contextStart, len,
                    0, contextLen, flags, advances, advancesPos);
            TextUtils.recycle(buf);
        }

        return ret;
    }

    public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset,
            int cursorOpt, Paint p) {

        int ret;

        int contextLen = contextEnd - contextStart;
        if (contextEnd <= mGapStart) {
            ret = p.getTextRunCursor(mText, contextStart, contextLen,
                    flags, offset, cursorOpt);
        } else if (contextStart >= mGapStart) {
            ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen,
                    flags, offset + mGapLength, cursorOpt);
        } else {
            char[] buf = TextUtils.obtain(contextLen);
            getChars(contextStart, contextEnd, buf, 0);
            ret = p.getTextRunCursor(buf, 0, contextLen,
                    flags, offset - contextStart, cursorOpt) + contextStart;
            TextUtils.recycle(buf);
        }

        return ret;
    }

    // Documentation from interface
    public void setFilters(InputFilter[] filters) {
        if (filters == null) {
+161 −193

File changed.

Preview size limit exceeded, changes collapsed.

Loading