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 Original line Diff line number Diff line
@@ -503,9 +503,16 @@ public class DynamicLayout extends Layout


        mNumberOfBlocks = newNumberOfBlocks;
        mNumberOfBlocks = newNumberOfBlocks;
        final int deltaLines = newLineCount - (endLine - startLine + 1);
        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;
                mBlockEndLines[i] += deltaLines;
            }
            }
        } else {
            mIndexFirstChangedBlock = mNumberOfBlocks;
        }


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


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

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

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


    private int mTopPadding, mBottomPadding;
    private int mTopPadding, mBottomPadding;


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


    DisplayList[] mTextDisplayLists;
    DisplayList[] mTextDisplayLists;
    int mLastLayoutHeight;


    boolean mFrozenWithFocus;
    boolean mFrozenWithFocus;
    boolean mSelectionMoved;
    boolean mSelectionMoved;
@@ -1289,20 +1288,11 @@ public class Editor {
                mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)];
                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;
            DynamicLayout dynamicLayout = (DynamicLayout) layout;
            int[] blockEndLines = dynamicLayout.getBlockEndLines();
            int[] blockEndLines = dynamicLayout.getBlockEndLines();
            int[] blockIndices = dynamicLayout.getBlockIndices();
            int[] blockIndices = dynamicLayout.getBlockIndices();
            final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
            final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
            final int indexFirstChangedBlock = dynamicLayout.getIndexFirstChangedBlock();


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


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


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


                endOfPreviousBlock = blockEndLine;
                endOfPreviousBlock = blockEndLine;
            }
            }

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


    private boolean isShowingHint() {
    private boolean isShowingHint() {