Merge "Optimize drawHardwareAccelerated method in Editor class"

This commit is contained in:
Romain Guy
2013-01-09 09:35:38 -08:00
committed by Android (Google) Code Review
3 changed files with 53 additions and 32 deletions

View File

@@ -503,8 +503,15 @@ public class DynamicLayout extends Layout
mNumberOfBlocks = newNumberOfBlocks;
final int deltaLines = newLineCount - (endLine - startLine + 1);
for (int i = firstBlock + numAddedBlocks; i < mNumberOfBlocks; i++) {
mBlockEndLines[i] += deltaLines;
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;
@@ -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;

View File

@@ -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,24 +1335,30 @@ public class Editor {
right = (int) (max + 0.5f);
}
final HardwareCanvas hardwareCanvas = blockDisplayList.start();
try {
// Tighten the bounds of the viewport to the actual text size
hardwareCanvas.setViewport(right - left, bottom - top);
// The dirty rect should always be null for a display list
hardwareCanvas.onPreDraw(null);
// drawText is always relative to TextView's origin, this translation brings
// this range of text back to the top left corner of the viewport
hardwareCanvas.translate(-left, -top);
layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
// No need to untranslate, previous context is popped after drawDisplayList
} finally {
hardwareCanvas.onPostDraw();
blockDisplayList.end();
blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
// Same as drawDisplayList below, handled by our TextView's parent
blockDisplayList.setClipChildren(false);
// 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
hardwareCanvas.setViewport(right - left, bottom - top);
// The dirty rect should always be null for a display list
hardwareCanvas.onPreDraw(null);
// drawText is always relative to TextView's origin, this translation brings
// this range of text back to the top left corner of the viewport
hardwareCanvas.translate(-left, -top);
layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
// No need to untranslate, previous context is popped after drawDisplayList
} finally {
hardwareCanvas.onPostDraw();
blockDisplayList.end();
// 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,
@@ -1369,6 +1366,8 @@ public class Editor {
endOfPreviousBlock = blockEndLine;
}
dynamicLayout.setIndexFirstChangedBlock(numberOfBlocks);
} else {
// Boring layout is used for empty and hint text
layout.drawText(canvas, firstLine, lastLine);

View File

@@ -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() {