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

Commit 2ea5290f authored by Raph Levien's avatar Raph Levien
Browse files

Fix problems with StaticLayout indentation

The implementation of indendataion had two issues. First, the indent
pattern would restart on a new paragraph, which created problems when
a multi-paragraph text would flow into a shape. Second, the indents
didn't affect drawing position, which is ok for centered text but not
most of the other alignments. This patch fixes both.

Bug: 21904268
Change-Id: I53a3eb1c192fc0f8f0beace304832eed61b38497
parent f22e2e39
Loading
Loading
Loading
Loading
+19 −10
Original line number Diff line number Diff line
@@ -385,21 +385,22 @@ public abstract class Layout {
            int x;
            if (align == Alignment.ALIGN_NORMAL) {
                if (dir == DIR_LEFT_TO_RIGHT) {
                    x = left;
                    x = left + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                } else {
                    x = right;
                    x = right + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                }
            } else {
                int max = (int)getLineExtent(lineNum, tabStops, false);
                if (align == Alignment.ALIGN_OPPOSITE) {
                    if (dir == DIR_LEFT_TO_RIGHT) {
                        x = right - max;
                        x = right - max + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                    } else {
                        x = left - max;
                        x = left - max + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                    }
                } else { // Alignment.ALIGN_CENTER
                    max = max & ~1;
                    x = (right + left - max) >> 1;
                    x = ((right + left - max) >> 1) +
                            getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
                }
            }

@@ -545,9 +546,9 @@ public abstract class Layout {
        int x;
        if (align == Alignment.ALIGN_NORMAL) {
            if (dir == DIR_LEFT_TO_RIGHT) {
                x = left;
                x = left + getIndentAdjust(line, Alignment.ALIGN_LEFT);
            } else {
                x = right;
                x = right + getIndentAdjust(line, Alignment.ALIGN_RIGHT);
            }
        } else {
            TabStops tabStops = null;
@@ -565,14 +566,14 @@ public abstract class Layout {
            int max = (int)getLineExtent(line, tabStops, false);
            if (align == Alignment.ALIGN_OPPOSITE) {
                if (dir == DIR_LEFT_TO_RIGHT) {
                    x = right - max;
                    x = right - max + getIndentAdjust(line, Alignment.ALIGN_RIGHT);
                } else {
                    // max is negative here
                    x = left - max;
                    x = left - max + getIndentAdjust(line, Alignment.ALIGN_LEFT);
                }
            } else { // Alignment.ALIGN_CENTER
                max = max & ~1;
                x = (left + right - max) >> 1;
                x = (left + right - max) >> 1 + getIndentAdjust(line, Alignment.ALIGN_CENTER);
            }
        }
        return x;
@@ -745,6 +746,14 @@ public abstract class Layout {
        return 0;
    }

    /**
     * Returns the left indent for a line.
     *
     * @hide
     */
    public int getIndentAdjust(int line, Alignment alignment) {
        return 0;
    }

    /**
     * Returns true if the character at offset and the preceding character
+60 −1
Original line number Diff line number Diff line
@@ -103,6 +103,8 @@ public class StaticLayout extends Layout {
            b.mText = null;
            MeasuredText.recycle(b.mMeasuredText);
            b.mMeasuredText = null;
            b.mLeftIndents = null;
            b.mRightIndents = null;
            nFinishBuilder(b.mNativePtr);
            sPool.release(b);
        }
@@ -296,9 +298,10 @@ public class StaticLayout extends Layout {
         * @param leftIndents array of indent values for left margin, in pixels
         * @param rightIndents array of indent values for right margin, in pixels
         * @return this builder, useful for chaining
         * @see android.widget.TextView#setIndents
         */
        public Builder setIndents(int[] leftIndents, int[] rightIndents) {
            mLeftIndents = leftIndents;
            mRightIndents = rightIndents;
            int leftLen = leftIndents == null ? 0 : leftIndents.length;
            int rightLen = rightIndents == null ? 0 : rightIndents.length;
            int[] indents = new int[Math.max(leftLen, rightLen)];
@@ -393,6 +396,8 @@ public class StaticLayout extends Layout {
        int mMaxLines;
        int mBreakStrategy;
        int mHyphenationFrequency;
        int[] mLeftIndents;
        int[] mRightIndents;

        Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();

@@ -544,6 +549,9 @@ public class StaticLayout extends Layout {
        mLines = new int[mLineDirections.length];
        mMaximumVisibleLineCount = b.mMaxLines;

        mLeftIndents = b.mLeftIndents;
        mRightIndents = b.mRightIndents;

        generate(b, b.mIncludePad, b.mIncludePad);
    }

@@ -661,6 +669,23 @@ public class StaticLayout extends Layout {
            nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart,
                    firstWidth, firstWidthLineCount, restWidth,
                    variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency);
            if (mLeftIndents != null || mRightIndents != null) {
                // TODO(raph) performance: it would be better to do this once per layout rather
                // than once per paragraph, but that would require a change to the native
                // interface.
                int leftLen = mLeftIndents == null ? 0 : mLeftIndents.length;
                int rightLen = mRightIndents == null ? 0 : mRightIndents.length;
                int indentsLen = Math.max(1, Math.min(leftLen, rightLen) - mLineCount);
                int[] indents = new int[indentsLen];
                for (int i = 0; i < indentsLen; i++) {
                    int leftMargin = mLeftIndents == null ? 0 :
                            mLeftIndents[Math.min(i + mLineCount, leftLen - 1)];
                    int rightMargin = mRightIndents == null ? 0 :
                            mRightIndents[Math.min(i + mLineCount, rightLen - 1)];
                    indents[i] = leftMargin + rightMargin;
                }
                nSetIndents(b.mNativePtr, indents);
            }

            // measurement has to be done before performing line breaking
            // but we don't want to recompute fontmetrics or span ranges the
@@ -1154,6 +1179,38 @@ public class StaticLayout extends Layout {
        return mLines[mColumns * line + HYPHEN] & 0xff;
    }

    /**
     * @hide
     */
    @Override
    public int getIndentAdjust(int line, Alignment align) {
        if (align == Alignment.ALIGN_LEFT) {
            if (mLeftIndents == null) {
                return 0;
            } else {
                return mLeftIndents[Math.min(line, mLeftIndents.length - 1)];
            }
        } else if (align == Alignment.ALIGN_RIGHT) {
            if (mRightIndents == null) {
                return 0;
            } else {
                return -mRightIndents[Math.min(line, mRightIndents.length - 1)];
            }
        } else if (align == Alignment.ALIGN_CENTER) {
            int left = 0;
            if (mLeftIndents != null) {
                left = mLeftIndents[Math.min(line, mLeftIndents.length - 1)];
            }
            int right = 0;
            if (mRightIndents != null) {
                right = mRightIndents[Math.min(line, mRightIndents.length - 1)];
            }
            return (left - right) >> 1;
        } else {
            throw new AssertionError("unhandled alignment " + align);
        }
    }

    @Override
    public int getEllipsisCount(int line) {
        if (mColumns < COLUMNS_ELLIPSIZE) {
@@ -1250,4 +1307,6 @@ public class StaticLayout extends Layout {
        // breaks, widths, and flags should all have the same length
    }

    private int[] mLeftIndents;
    private int[] mRightIndents;
}