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

Commit 955beb2b authored by Sangkyu Lee's avatar Sangkyu Lee Committed by Romain Guy
Browse files

Optimize drawHardwareAccelerated method in Editor class



When inserting a new line or breaking a line,
every display list was invalidated and rebuilt before.
However, we can reuse the display lists above intactly and also
reuse the display lists below with only updating drawing locations.

This patch reuses the display lists if possible.
The display lists above the inserted line are just reused
and the display lists below are reused with only updating
drawing locations not fullly rebuilt.

mIndexOfFirstChangedBlock is the index of the first block
which is moved by inserting or breaking a line.
So the display list whose index is >= mIndexOfFirstChangedBlock
only needs to update its drawing location.

Change-Id: Ica20deb0ebb5750de21356ed31fa9f86e657ff92
Signed-off-by: default avatarSangkyu Lee <sk82.lee@lge.com>
parent 4a623745
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -503,9 +503,16 @@ public class DynamicLayout extends Layout

        mNumberOfBlocks = newNumberOfBlocks;
        final int deltaLines = newLineCount - (endLine - startLine + 1);
        for (int i = firstBlock + numAddedBlocks; i < mNumberOfBlocks; i++) {
        if (deltaLines != 0) {
            // Display list whose index is >= mIndexFirstChangedBlock is valid
            // but it needs to update its drawing location.
            mIndexFirstChangedBlock = firstBlock + numAddedBlocks;
            for (int i = mIndexFirstChangedBlock; i < mNumberOfBlocks; i++) {
                mBlockEndLines[i] += deltaLines;
            }
        } else {
            mIndexFirstChangedBlock = mNumberOfBlocks;
        }

        int blockIndex = firstBlock;
        if (createBlockBefore) {
@@ -559,6 +566,20 @@ public class DynamicLayout extends Layout
        return mNumberOfBlocks;
    }

    /**
     * @hide
     */
    public int getIndexFirstChangedBlock() {
        return mIndexFirstChangedBlock;
    }

    /**
     * @hide
     */
    public void setIndexFirstChangedBlock(int i) {
        mIndexFirstChangedBlock = i;
    }

    @Override
    public int getLineCount() {
        return mInts.size() - 1;
@@ -697,6 +718,8 @@ public class DynamicLayout extends Layout
    private int[] mBlockIndices;
    // Number of items actually currently being used in the above 2 arrays
    private int mNumberOfBlocks;
    // The first index of the blocks whose locations are changed
    private int mIndexFirstChangedBlock;

    private int mTopPadding, mBottomPadding;

+28 −29
Original line number Diff line number Diff line
@@ -124,7 +124,6 @@ public class Editor {
    InputMethodState mInputMethodState;

    DisplayList[] mTextDisplayLists;
    int mLastLayoutHeight;

    boolean mFrozenWithFocus;
    boolean mSelectionMoved;
@@ -1289,20 +1288,11 @@ public class Editor {
                mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)];
            }

            // If the height of the layout changes (usually when inserting or deleting a line,
            // but could be changes within a span), invalidate everything. We could optimize
            // more aggressively (for example, adding offsets to blocks) but it would be more
            // complex and we would only get the benefit in some cases.
            int layoutHeight = layout.getHeight();
            if (mLastLayoutHeight != layoutHeight) {
                invalidateTextDisplayList();
                mLastLayoutHeight = layoutHeight;
            }

            DynamicLayout dynamicLayout = (DynamicLayout) layout;
            int[] blockEndLines = dynamicLayout.getBlockEndLines();
            int[] blockIndices = dynamicLayout.getBlockIndices();
            final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
            final int indexFirstChangedBlock = dynamicLayout.getIndexFirstChangedBlock();

            int endOfPreviousBlock = -1;
            int searchStartIndex = 0;
@@ -1327,7 +1317,8 @@ public class Editor {
                    if (blockIsInvalid) blockDisplayList.invalidate();
                }

                if (!blockDisplayList.isValid()) {
                final boolean blockDisplayListIsInvalid = !blockDisplayList.isValid();
                if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) {
                    final int blockBeginLine = endOfPreviousBlock + 1;
                    final int top = layout.getLineTop(blockBeginLine);
                    final int bottom = layout.getLineBottom(blockEndLine);
@@ -1344,6 +1335,8 @@ public class Editor {
                        right = (int) (max + 0.5f);
                    }

                    // Rebuild display list if it is invalid
                    if (blockDisplayListIsInvalid) {
                        final HardwareCanvas hardwareCanvas = blockDisplayList.start();
                        try {
                            // Tighten the bounds of the viewport to the actual text size
@@ -1358,17 +1351,23 @@ public class Editor {
                        } finally {
                            hardwareCanvas.onPostDraw();
                            blockDisplayList.end();
                        blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
                            // Same as drawDisplayList below, handled by our TextView's parent
                            blockDisplayList.setClipChildren(false);
                        }
                    }

                    // Valid disply list whose index is >= indexFirstChangedBlock
                    // only needs to update its drawing location.
                    blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
                }

                ((HardwareCanvas) canvas).drawDisplayList(blockDisplayList, null,
                        0 /* no child clipping, our TextView parent enforces it */);

                endOfPreviousBlock = blockEndLine;
            }

            dynamicLayout.setIndexFirstChangedBlock(numberOfBlocks);
        } else {
            // Boring layout is used for empty and hint text
            layout.drawText(canvas, firstLine, lastLine);
+0 −1
Original line number Diff line number Diff line
@@ -6459,7 +6459,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            mDeferScroll = -1;
            bringPointIntoView(Math.min(curs, mText.length()));
        }
        if (changed && mEditor != null) mEditor.invalidateTextDisplayList();
    }

    private boolean isShowingHint() {