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

Commit 88296d22 authored by Seigo Nonaka's avatar Seigo Nonaka Committed by Android (Google) Code Review
Browse files

Merge "Introduce full justification."

parents 3b6bcfb6 09da71a6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -39452,6 +39452,7 @@ package android.text {
    method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
    method public android.text.StaticLayout.Builder setIncludePad(boolean);
    method public android.text.StaticLayout.Builder setIndents(int[], int[]);
    method public android.text.StaticLayout.Builder setJustify(boolean);
    method public android.text.StaticLayout.Builder setLineSpacing(float, float);
    method public android.text.StaticLayout.Builder setMaxLines(int);
    method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -49061,6 +49062,7 @@ package android.widget {
    method public boolean getIncludeFontPadding();
    method public android.os.Bundle getInputExtras(boolean);
    method public int getInputType();
    method public boolean getJustify();
    method public final android.text.method.KeyListener getKeyListener();
    method public final android.text.Layout getLayout();
    method public float getLetterSpacing();
@@ -49169,6 +49171,7 @@ package android.widget {
    method public void setIncludeFontPadding(boolean);
    method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
    method public void setInputType(int);
    method public void setJustify(boolean);
    method public void setKeyListener(android.text.method.KeyListener);
    method public void setLetterSpacing(float);
    method public void setLineSpacing(float, float);
+3 −0
Original line number Diff line number Diff line
@@ -42670,6 +42670,7 @@ package android.text {
    method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
    method public android.text.StaticLayout.Builder setIncludePad(boolean);
    method public android.text.StaticLayout.Builder setIndents(int[], int[]);
    method public android.text.StaticLayout.Builder setJustify(boolean);
    method public android.text.StaticLayout.Builder setLineSpacing(float, float);
    method public android.text.StaticLayout.Builder setMaxLines(int);
    method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -52639,6 +52640,7 @@ package android.widget {
    method public boolean getIncludeFontPadding();
    method public android.os.Bundle getInputExtras(boolean);
    method public int getInputType();
    method public boolean getJustify();
    method public final android.text.method.KeyListener getKeyListener();
    method public final android.text.Layout getLayout();
    method public float getLetterSpacing();
@@ -52747,6 +52749,7 @@ package android.widget {
    method public void setIncludeFontPadding(boolean);
    method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
    method public void setInputType(int);
    method public void setJustify(boolean);
    method public void setKeyListener(android.text.method.KeyListener);
    method public void setLetterSpacing(float);
    method public void setLineSpacing(float, float);
+3 −0
Original line number Diff line number Diff line
@@ -39572,6 +39572,7 @@ package android.text {
    method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
    method public android.text.StaticLayout.Builder setIncludePad(boolean);
    method public android.text.StaticLayout.Builder setIndents(int[], int[]);
    method public android.text.StaticLayout.Builder setJustify(boolean);
    method public android.text.StaticLayout.Builder setLineSpacing(float, float);
    method public android.text.StaticLayout.Builder setMaxLines(int);
    method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -49363,6 +49364,7 @@ package android.widget {
    method public boolean getIncludeFontPadding();
    method public android.os.Bundle getInputExtras(boolean);
    method public int getInputType();
    method public boolean getJustify();
    method public final android.text.method.KeyListener getKeyListener();
    method public final android.text.Layout getLayout();
    method public float getLetterSpacing();
@@ -49471,6 +49473,7 @@ package android.widget {
    method public void setIncludeFontPadding(boolean);
    method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
    method public void setInputType(int);
    method public void setJustify(boolean);
    method public void setKeyListener(android.text.method.KeyListener);
    method public void setLetterSpacing(float);
    method public void setLineSpacing(float, float);
+7 −3
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ public class DynamicLayout extends Layout
        this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                spacingmult, spacingadd, includepad,
                StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE,
                ellipsize, ellipsizedWidth);
                false /* justify */, ellipsize, ellipsizedWidth);
    }

    /**
@@ -102,7 +102,8 @@ public class DynamicLayout extends Layout
                         int width, Alignment align, TextDirectionHeuristic textDir,
                         float spacingmult, float spacingadd,
                         boolean includepad, int breakStrategy, int hyphenationFrequency,
                         TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
                         boolean justify, TextUtils.TruncateAt ellipsize,
                         int ellipsizedWidth) {
        super((ellipsize == null)
                ? display
                : (display instanceof Spanned)
@@ -127,6 +128,7 @@ public class DynamicLayout extends Layout

        mIncludePad = includepad;
        mBreakStrategy = breakStrategy;
        mJustify = justify;
        mHyphenationFrequency = hyphenationFrequency;

        /*
@@ -300,7 +302,8 @@ public class DynamicLayout extends Layout
                .setEllipsizedWidth(mEllipsizedWidth)
                .setEllipsize(mEllipsizeAt)
                .setBreakStrategy(mBreakStrategy)
                .setHyphenationFrequency(mHyphenationFrequency);
                .setHyphenationFrequency(mHyphenationFrequency)
                .setJustify(mJustify);
        reflowed.generate(b, false, true);
        int n = reflowed.getLineCount();
        // If the new layout has a blank line at the end, but it is not
@@ -808,6 +811,7 @@ public class DynamicLayout extends Layout
    private TextUtils.TruncateAt mEllipsizeAt;
    private int mBreakStrategy;
    private int mHyphenationFrequency;
    private boolean mJustify;

    private PackedIntVector mInts;
    private PackedObjectVector<Directions> mObjects;
+123 −12
Original line number Diff line number Diff line
@@ -218,6 +218,11 @@ public abstract class Layout {
        mTextDir = textDir;
    }

    /** @hide */
    protected void setJustify(boolean justify) {
        mJustify = justify;
    }

    /**
     * Replace constructor properties of this Layout with new ones.  Be careful.
     */
@@ -266,6 +271,99 @@ public abstract class Layout {
        drawText(canvas, firstLine, lastLine);
    }

    private boolean isJustificationRequired(int lineNum) {
        if (!mJustify) return false;
        final int lineEnd = getLineEnd(lineNum);
        return lineEnd < mText.length() && mText.charAt(lineEnd - 1) != '\n';
    }

    private float getJustifyWidth(int lineNum) {
        Alignment paraAlign = mAlignment;
        TabStops tabStops = null;
        boolean tabStopsIsInitialized = false;

        int left = 0;
        int right = mWidth;

        final int dir = getParagraphDirection(lineNum);

        ParagraphStyle[] spans = NO_PARA_SPANS;
        if (mSpannedText) {
            Spanned sp = (Spanned) mText;
            final int start = getLineStart(lineNum);

            final boolean isFirstParaLine = (start == 0 || mText.charAt(start - 1) == '\n');

            if (isFirstParaLine) {
                final int spanEnd = sp.nextSpanTransition(start, mText.length(),
                        ParagraphStyle.class);
                spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);

                for (int n = spans.length - 1; n >= 0; n--) {
                    if (spans[n] instanceof AlignmentSpan) {
                        paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
                        break;
                    }
                }
            }

            final int length = spans.length;
            boolean useFirstLineMargin = isFirstParaLine;
            for (int n = 0; n < length; n++) {
                if (spans[n] instanceof LeadingMarginSpan2) {
                    int count = ((LeadingMarginSpan2) spans[n]).getLeadingMarginLineCount();
                    int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
                    if (lineNum < startLine + count) {
                        useFirstLineMargin = true;
                        break;
                    }
                }
            }
            for (int n = 0; n < length; n++) {
                if (spans[n] instanceof LeadingMarginSpan) {
                    LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
                    if (dir == DIR_RIGHT_TO_LEFT) {
                        right -= margin.getLeadingMargin(useFirstLineMargin);
                    } else {
                        left += margin.getLeadingMargin(useFirstLineMargin);
                    }
                }
            }
        }

        if (getLineContainsTab(lineNum)) {
            tabStops = new TabStops(TAB_INCREMENT, spans);
        }

        final Alignment align;
        if (paraAlign == Alignment.ALIGN_LEFT) {
            align = (dir == DIR_LEFT_TO_RIGHT) ?  Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
        } else if (paraAlign == Alignment.ALIGN_RIGHT) {
            align = (dir == DIR_LEFT_TO_RIGHT) ?  Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
        } else {
            align = paraAlign;
        }

        final int indentWidth;
        if (align == Alignment.ALIGN_NORMAL) {
            if (dir == DIR_LEFT_TO_RIGHT) {
                indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
            } else {
                indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
            }
        } else if (align == Alignment.ALIGN_OPPOSITE) {
            if (dir == DIR_LEFT_TO_RIGHT) {
                indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
            } else {
                indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
            }
        } else { // Alignment.ALIGN_CENTER
            indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
        }

        return right - left - indentWidth;
    }

    /**
     * @hide
     */
@@ -274,7 +372,7 @@ public abstract class Layout {
        int previousLineEnd = getLineStart(firstLine);
        ParagraphStyle[] spans = NO_PARA_SPANS;
        int spanEnd = 0;
        TextPaint paint = mPaint;
        final TextPaint paint = mPaint;
        CharSequence buf = mText;

        Alignment paraAlign = mAlignment;
@@ -288,6 +386,7 @@ public abstract class Layout {
        for (int lineNum = firstLine; lineNum <= lastLine; lineNum++) {
            int start = previousLineEnd;
            previousLineEnd = getLineStart(lineNum + 1);
            final boolean justify = isJustificationRequired(lineNum);
            int end = getLineVisibleEnd(lineNum, start, previousLineEnd);

            int ltop = previousLineBottom;
@@ -386,34 +485,42 @@ public abstract class Layout {
            }

            int x;
            final int indentWidth;
            if (align == Alignment.ALIGN_NORMAL) {
                if (dir == DIR_LEFT_TO_RIGHT) {
                    x = left + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                    indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                    x = left + indentWidth;
                } else {
                    x = right + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                    indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                    x = right - indentWidth;
                }
            } else {
                int max = (int)getLineExtent(lineNum, tabStops, false);
                if (align == Alignment.ALIGN_OPPOSITE) {
                    if (dir == DIR_LEFT_TO_RIGHT) {
                        x = right - max + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                        indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                        x = right - max - indentWidth;
                    } else {
                        x = left - max + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                        indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                        x = left - max + indentWidth;
                    }
                } else { // Alignment.ALIGN_CENTER
                    indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
                    max = max & ~1;
                    x = ((right + left - max) >> 1) +
                            getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
                    x = ((right + left - max) >> 1) + indentWidth;
                }
            }

            paint.setHyphenEdit(getHyphen(lineNum));
            Directions directions = getLineDirections(lineNum);
            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab) {
            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab && !justify) {
                // XXX: assumes there's nothing additional to be done
                canvas.drawText(buf, start, end, x, lbaseline, paint);
            } else {
                tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops);
                if (justify) {
                    tl.justify(right - left - indentWidth);
                }
                tl.draw(canvas, x, ltop, lbaseline, lbottom);
            }
            paint.setHyphenEdit(0);
@@ -1094,6 +1201,9 @@ public abstract class Layout {
        TextLine tl = TextLine.obtain();
        mPaint.setHyphenEdit(getHyphen(line));
        tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops);
        if (isJustificationRequired(line)) {
            tl.justify(getJustifyWidth(line));
        }
        float width = tl.metrics(null);
        mPaint.setHyphenEdit(0);
        TextLine.recycle(tl);
@@ -1118,6 +1228,9 @@ public abstract class Layout {
        TextLine tl = TextLine.obtain();
        mPaint.setHyphenEdit(getHyphen(line));
        tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops);
        if (isJustificationRequired(line)) {
            tl.justify(getJustifyWidth(line));
        }
        float width = tl.metrics(null);
        mPaint.setHyphenEdit(0);
        TextLine.recycle(tl);
@@ -1303,10 +1416,7 @@ public abstract class Layout {
                return end - 1;
            }

            // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace()
            if (!(ch == ' ' || ch == '\t' || ch == 0x1680 ||
                    (0x2000 <= ch && ch <= 0x200A && ch != 0x2007) ||
                    ch == 0x205F || ch == 0x3000)) {
            if (!TextLine.isLineEndSpace(ch)) {
                break;
            }

@@ -2086,6 +2196,7 @@ public abstract class Layout {
    private boolean mSpannedText;
    private TextDirectionHeuristic mTextDir;
    private SpanSet<LineBackgroundSpan> mLineBackgroundSpans;
    private boolean mJustify;

    public static final int DIR_LEFT_TO_RIGHT = 1;
    public static final int DIR_RIGHT_TO_LEFT = -1;
Loading