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

Commit c4a1a927 authored by Kenny Root's avatar Kenny Root Committed by Android (Google) Code Review
Browse files

Merge "Fix alignment issues with RTL paragraphs."

parents d9f89b22 c982f60e
Loading
Loading
Loading
Loading
+320 −154

File changed.

Preview size limit exceeded, changes collapsed.

+41 −18
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.graphics.Paint;
import android.text.style.LeadingMarginSpan;
import android.text.style.LineHeightSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.TabStopSpan;
import android.text.style.LeadingMarginSpan.LeadingMarginSpan2;

/**
 * StaticLayout is a Layout for text that will not be edited after it
@@ -146,7 +148,7 @@ extends Layout
                paraEnd++;
            int paraLen = paraEnd - paraStart;

            int firstWidthLineCount = 1;
            int firstWidthLineLimit = mLineCount + 1;
            int firstwidth = outerwidth;
            int restwidth = outerwidth;

@@ -159,10 +161,16 @@ extends Layout
                    LeadingMarginSpan lms = sp[i];
                    firstwidth -= sp[i].getLeadingMargin(true);
                    restwidth -= sp[i].getLeadingMargin(false);
                    if (lms instanceof LeadingMarginSpan.LeadingMarginSpan2) {
                        firstWidthLineCount =
                            ((LeadingMarginSpan.LeadingMarginSpan2)lms)
                            .getLeadingMarginLineCount();
                    
                    // LeadingMarginSpan2 is odd.  The count affects all
                    // leading margin spans, not just this particular one,
                    // and start from the top of the span, not the top of the
                    // paragraph.
                    if (lms instanceof LeadingMarginSpan2) {
                        LeadingMarginSpan2 lms2 = (LeadingMarginSpan2) lms;
                        int lmsFirstLine = getLineForOffset(spanned.getSpanStart(lms2));
                        firstWidthLineLimit = lmsFirstLine + 
                            lms2.getLeadingMarginLineCount();
                    }
                }

@@ -214,7 +222,9 @@ extends Layout
            float fitwidth = w;
            int fitascent = 0, fitdescent = 0, fittop = 0, fitbottom = 0;

            boolean tab = false;
            boolean hasTabOrEmoji = false;
            boolean hasTab = false;
            TabStops tabStops = null;

            for (int spanStart = paraStart, spanEnd = spanStart, nextSpanStart;
                    spanStart < paraEnd; spanStart = nextSpanStart) {
@@ -252,8 +262,21 @@ extends Layout
                    if (c == '\n') {
                        ;
                    } else if (c == '\t') {
                        w = Layout.nextTab(sub, paraStart, paraEnd, w, null);
                        tab = true;
                        if (hasTab == false) {
                            hasTab = true;
                            hasTabOrEmoji = true;
                            // First tab this para, check for tabstops
                            TabStopSpan[] spans = spanned.getSpans(paraStart, 
                                    paraEnd, TabStopSpan.class);
                            if (spans.length > 0) {
                                tabStops = new TabStops(TAB_INCREMENT, spans);
                            }
                        }
                        if (tabStops != null) {
                            w = tabStops.nextTab(w);
                        } else {
                            w = TabStops.nextDefaultStop(w, TAB_INCREMENT);
                        }
                    } else if (c >= 0xD800 && c <= 0xDFFF && j + 1 < spanEnd) {
                        int emoji = Character.codePointAt(chs, j - paraStart);

@@ -275,7 +298,7 @@ extends Layout
                                            bm.getHeight();

                                w += wid;
                                tab = true;
                                hasTabOrEmoji = true;
                                j++;
                            } else {
                                w += widths[j - paraStart];
@@ -351,7 +374,7 @@ extends Layout
                                    okascent, okdescent, oktop, okbottom,
                                    v,
                                    spacingmult, spacingadd, chooseht,
                                    choosehtv, fm, tab,
                                    choosehtv, fm, hasTabOrEmoji,
                                    needMultiply, paraStart, chdirs, dir, easy,
                                    ok == bufend, includepad, trackpad,
                                    chs, widths, here - paraStart,
@@ -387,7 +410,7 @@ extends Layout
                                    okascent, okdescent, oktop, okbottom,
                                    v,
                                    spacingmult, spacingadd, chooseht,
                                    choosehtv, fm, tab,
                                    choosehtv, fm, hasTabOrEmoji,
                                    needMultiply, paraStart, chdirs, dir, easy,
                                    ok == bufend, includepad, trackpad,
                                    chs, widths, here - paraStart,
@@ -403,7 +426,7 @@ extends Layout
                                    fittop, fitbottom,
                                    v,
                                    spacingmult, spacingadd, chooseht,
                                    choosehtv, fm, tab,
                                    choosehtv, fm, hasTabOrEmoji,
                                    needMultiply, paraStart, chdirs, dir, easy,
                                    fit == bufend, includepad, trackpad,
                                    chs, widths, here - paraStart,
@@ -424,7 +447,7 @@ extends Layout
                                    fm.top, fm.bottom,
                                    v,
                                    spacingmult, spacingadd, chooseht,
                                    choosehtv, fm, tab,
                                    choosehtv, fm, hasTabOrEmoji,
                                    needMultiply, paraStart, chdirs, dir, easy,
                                    here + 1 == bufend, includepad,
                                    trackpad,
@@ -449,7 +472,7 @@ extends Layout
                        fitascent = fitdescent = fittop = fitbottom = 0;
                        okascent = okdescent = oktop = okbottom = 0;

                        if (--firstWidthLineCount <= 0) {
                        if (--firstWidthLineLimit <= 0) {
                            width = restwidth;
                        }
                    }
@@ -473,7 +496,7 @@ extends Layout
                        fittop, fitbottom,
                        v,
                        spacingmult, spacingadd, chooseht,
                        choosehtv, fm, tab,
                        choosehtv, fm, hasTabOrEmoji,
                        needMultiply, paraStart, chdirs, dir, easy,
                        paraEnd == bufend, includepad, trackpad,
                        chs, widths, here - paraStart,
@@ -613,7 +636,7 @@ extends Layout
                      int above, int below, int top, int bottom, int v,
                      float spacingmult, float spacingadd,
                      LineHeightSpan[] chooseht, int[] choosehtv,
                      Paint.FontMetricsInt fm, boolean tab,
                      Paint.FontMetricsInt fm, boolean hasTabOrEmoji,
                      boolean needMultiply, int pstart, byte[] chdirs,
                      int dir, boolean easy, boolean last,
                      boolean includepad, boolean trackpad,
@@ -700,7 +723,7 @@ extends Layout
        lines[off + mColumns + START] = end;
        lines[off + mColumns + TOP] = v;

        if (tab)
        if (hasTabOrEmoji)
            lines[off + TAB] |= TAB_MASK;

        lines[off + DIR] |= dir << DIR_SHIFT;
@@ -914,7 +937,7 @@ extends Layout
    private static final int DIR_SHIFT  = 30;
    private static final int TAB_MASK   = 0x20000000;

    private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
    private static final int TAB_INCREMENT = 20; // same as Layout, but that's private

    /*
     * This is reused across calls to generate()
+8 −52
Original line number Diff line number Diff line
@@ -25,10 +25,10 @@ import android.graphics.RectF;
import android.graphics.Paint.FontMetricsInt;
import android.icu.text.ArabicShaping;
import android.text.Layout.Directions;
import android.text.Layout.TabStops;
import android.text.style.CharacterStyle;
import android.text.style.MetricAffectingSpan;
import android.text.style.ReplacementSpan;
import android.text.style.TabStopSpan;
import android.util.Log;

/**
@@ -51,7 +51,7 @@ class TextLine {
    private int mDir;
    private Directions mDirections;
    private boolean mHasTabs;
    private TabStopSpan[] mTabs;
    private TabStops mTabs;

    private char[] mChars;
    private boolean mCharsValid;
@@ -117,11 +117,10 @@ class TextLine {
     * @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 spans array of paragraph-level spans, of which only TabStopSpans
     * are used.  Can be null.
     * @param tabStops the tabStops. Can be null.
     */
    void set(TextPaint paint, CharSequence text, int start, int limit, int dir,
            Directions directions, boolean hasTabs, Object[] spans) {
            Directions directions, boolean hasTabs, TabStops tabStops) {
        mPaint = paint;
        mText = text;
        mStart = start;
@@ -148,38 +147,8 @@ class TextLine {
                mChars = new char[ArrayUtils.idealCharArraySize(mLen)];
            }
            TextUtils.getChars(text, start, limit, mChars, 0);

            if (hasTabs) {
                TabStopSpan[] tabs = mTabs;
                int tabLen = 0;
                if (mSpanned != null && spans == null) {
                    TabStopSpan[] newTabs = mSpanned.getSpans(start, limit,
                            TabStopSpan.class);
                    if (tabs == null || tabs.length < newTabs.length) {
                        tabs = newTabs;
                    } else {
                        for (int i = 0; i < newTabs.length; ++i) {
                            tabs[i] = newTabs[i];
                        }
                    }
                    tabLen = newTabs.length;
                } else if (spans != null) {
                    if (tabs == null || tabs.length < spans.length) {
                        tabs = new TabStopSpan[spans.length];
                    }
                    for (int i = 0; i < spans.length; ++i) {
                        if (spans[i] instanceof TabStopSpan) {
                            tabs[tabLen++] = (TabStopSpan) spans[i];
                        }
                    }
                }

                if (tabs != null && tabLen < tabs.length){
                    tabs[tabLen] = null;
                }
                mTabs = tabs;
            }
        }
        mTabs = tabStops;
    }

    /**
@@ -993,23 +962,10 @@ class TextLine {
     * @return the (unsigned) tab position after this offset
     */
    float nextTab(float h) {
        float nh = Float.MAX_VALUE;
        boolean alltabs = false;

        if (mHasTabs && mTabs != null) {
            TabStopSpan[] tabs = mTabs;
            for (int i = 0; i < tabs.length && tabs[i] != null; ++i) {
                int where = tabs[i].getTabStop();
                if (where < nh && where > h) {
                    nh = where;
        if (mTabs != null) {
            return mTabs.nextTab(h);
        }
            }
            if (nh != Float.MAX_VALUE) {
                return nh;
            }
        }

        return ((int) ((h + TAB_INCREMENT) / TAB_INCREMENT)) * TAB_INCREMENT;
        return TabStops.nextDefaultStop(h, TAB_INCREMENT);
    }

    private static final int TAB_INCREMENT = 20;
+7 −4
Original line number Diff line number Diff line
@@ -18,13 +18,12 @@ package android.text.method;

import android.text.Layout;
import android.text.NoCopySpan;
import android.text.Layout.Alignment;
import android.text.Spannable;
import android.util.Log;
import android.text.Layout.Alignment;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.TextView;
import android.view.KeyEvent;

public class Touch {
    private Touch() { }
@@ -45,6 +44,7 @@ public class Touch {
        int left = Integer.MAX_VALUE;
        int right = 0;
        Alignment a = null;
        boolean ltr = true;

        for (int i = top; i <= bottom; i++) {
            left = (int) Math.min(left, layout.getLineLeft(i));
@@ -52,6 +52,7 @@ public class Touch {

            if (a == null) {
                a = layout.getParagraphAlignment(i);
                ltr = layout.getParagraphDirection(i) > 0;
            }
        }

@@ -59,10 +60,12 @@ public class Touch {
        int width = widget.getWidth();
        int diff = 0;

        // align_opposite does NOT mean align_right, we need the paragraph
        // direction to resolve it to left or right
        if (right - left < width - padding) {
            if (a == Alignment.ALIGN_CENTER) {
                diff = (width - padding - (right - left)) / 2;
            } else if (a == Alignment.ALIGN_OPPOSITE) {
            } else if (ltr == (a == Alignment.ALIGN_OPPOSITE)) {
                diff = width - padding - (right - left);
            }
        }
+10 −4
Original line number Diff line number Diff line
@@ -4847,6 +4847,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                break;

            case Gravity.RIGHT:
                // Note, Layout resolves ALIGN_OPPOSITE to left or
                // right based on the paragraph direction.
                alignment = Layout.Alignment.ALIGN_OPPOSITE;
                break;

@@ -5668,11 +5670,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        final int leftChar = mLayout.getOffsetForHorizontal(line, hs);
        final int rightChar = mLayout.getOffsetForHorizontal(line, hspace+hs);
        
        // line might contain bidirectional text
        final int lowChar = leftChar < rightChar ? leftChar : rightChar;
        final int highChar = leftChar > rightChar ? leftChar : rightChar;

        int newStart = start;
        if (newStart < leftChar) {
            newStart = leftChar;
        } else if (newStart > rightChar) {
            newStart = rightChar;
        if (newStart < lowChar) {
            newStart = lowChar;
        } else if (newStart > highChar) {
            newStart = highChar;
        }
        
        if (newStart != start) {