Merge "TextView's sub display lists have tighten bounds"
This commit is contained in:
committed by
Android (Google) Code Review
commit
0b568ff179
@@ -117,7 +117,7 @@ public class DynamicLayout extends Layout
|
||||
|
||||
mObjects = new PackedObjectVector<Directions>(1);
|
||||
|
||||
mBlockEnds = new int[] { 0 };
|
||||
mBlockEndLines = new int[] { 0 };
|
||||
mBlockIndices = new int[] { INVALID_BLOCK_INDEX };
|
||||
mNumberOfBlocks = 1;
|
||||
|
||||
@@ -391,23 +391,23 @@ public class DynamicLayout extends Layout
|
||||
int firstBlock = -1;
|
||||
int lastBlock = -1;
|
||||
for (int i = 0; i < mNumberOfBlocks; i++) {
|
||||
if (mBlockEnds[i] >= startLine) {
|
||||
if (mBlockEndLines[i] >= startLine) {
|
||||
firstBlock = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = firstBlock; i < mNumberOfBlocks; i++) {
|
||||
if (mBlockEnds[i] >= endLine) {
|
||||
if (mBlockEndLines[i] >= endLine) {
|
||||
lastBlock = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
final int lastBlockEndLine = mBlockEnds[lastBlock];
|
||||
final int lastBlockEndLine = mBlockEndLines[lastBlock];
|
||||
|
||||
boolean createBlockBefore = startLine > (firstBlock == 0 ? 0 :
|
||||
mBlockEnds[firstBlock - 1] + 1);
|
||||
mBlockEndLines[firstBlock - 1] + 1);
|
||||
boolean createBlock = newLineCount > 0;
|
||||
boolean createBlockAfter = endLine < mBlockEnds[lastBlock];
|
||||
boolean createBlockAfter = endLine < mBlockEndLines[lastBlock];
|
||||
|
||||
int numAddedBlocks = 0;
|
||||
if (createBlockBefore) numAddedBlocks++;
|
||||
@@ -419,27 +419,27 @@ public class DynamicLayout extends Layout
|
||||
|
||||
if (newNumberOfBlocks == 0) {
|
||||
// Even when text is empty, there is actually one line and hence one block
|
||||
mBlockEnds[0] = 0;
|
||||
mBlockEndLines[0] = 0;
|
||||
mBlockIndices[0] = INVALID_BLOCK_INDEX;
|
||||
mNumberOfBlocks = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (newNumberOfBlocks > mBlockEnds.length) {
|
||||
if (newNumberOfBlocks > mBlockEndLines.length) {
|
||||
final int newSize = ArrayUtils.idealIntArraySize(newNumberOfBlocks);
|
||||
int[] blockEnds = new int[newSize];
|
||||
int[] blockEndLines = new int[newSize];
|
||||
int[] blockIndices = new int[newSize];
|
||||
System.arraycopy(mBlockEnds, 0, blockEnds, 0, firstBlock);
|
||||
System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, firstBlock);
|
||||
System.arraycopy(mBlockIndices, 0, blockIndices, 0, firstBlock);
|
||||
System.arraycopy(mBlockEnds, lastBlock + 1,
|
||||
blockEnds, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
|
||||
System.arraycopy(mBlockEndLines, lastBlock + 1,
|
||||
blockEndLines, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
|
||||
System.arraycopy(mBlockIndices, lastBlock + 1,
|
||||
blockIndices, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
|
||||
mBlockEnds = blockEnds;
|
||||
mBlockEndLines = blockEndLines;
|
||||
mBlockIndices = blockIndices;
|
||||
} else {
|
||||
System.arraycopy(mBlockEnds, lastBlock + 1,
|
||||
mBlockEnds, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
|
||||
System.arraycopy(mBlockEndLines, lastBlock + 1,
|
||||
mBlockEndLines, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
|
||||
System.arraycopy(mBlockIndices, lastBlock + 1,
|
||||
mBlockIndices, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
|
||||
}
|
||||
@@ -447,24 +447,24 @@ public class DynamicLayout extends Layout
|
||||
mNumberOfBlocks = newNumberOfBlocks;
|
||||
final int deltaLines = newLineCount - (endLine - startLine + 1);
|
||||
for (int i = firstBlock + numAddedBlocks; i < mNumberOfBlocks; i++) {
|
||||
mBlockEnds[i] += deltaLines;
|
||||
mBlockEndLines[i] += deltaLines;
|
||||
}
|
||||
|
||||
int blockIndex = firstBlock;
|
||||
if (createBlockBefore) {
|
||||
mBlockEnds[blockIndex] = startLine - 1;
|
||||
mBlockEndLines[blockIndex] = startLine - 1;
|
||||
mBlockIndices[blockIndex] = INVALID_BLOCK_INDEX;
|
||||
blockIndex++;
|
||||
}
|
||||
|
||||
if (createBlock) {
|
||||
mBlockEnds[blockIndex] = startLine + newLineCount - 1;
|
||||
mBlockEndLines[blockIndex] = startLine + newLineCount - 1;
|
||||
mBlockIndices[blockIndex] = INVALID_BLOCK_INDEX;
|
||||
blockIndex++;
|
||||
}
|
||||
|
||||
if (createBlockAfter) {
|
||||
mBlockEnds[blockIndex] = lastBlockEndLine + deltaLines;
|
||||
mBlockEndLines[blockIndex] = lastBlockEndLine + deltaLines;
|
||||
mBlockIndices[blockIndex] = INVALID_BLOCK_INDEX;
|
||||
}
|
||||
}
|
||||
@@ -473,10 +473,10 @@ public class DynamicLayout extends Layout
|
||||
* This package private method is used for test purposes only
|
||||
* @hide
|
||||
*/
|
||||
void setBlocksDataForTest(int[] blockEnds, int[] blockIndices, int numberOfBlocks) {
|
||||
mBlockEnds = new int[blockEnds.length];
|
||||
void setBlocksDataForTest(int[] blockEndLines, int[] blockIndices, int numberOfBlocks) {
|
||||
mBlockEndLines = new int[blockEndLines.length];
|
||||
mBlockIndices = new int[blockIndices.length];
|
||||
System.arraycopy(blockEnds, 0, mBlockEnds, 0, blockEnds.length);
|
||||
System.arraycopy(blockEndLines, 0, mBlockEndLines, 0, blockEndLines.length);
|
||||
System.arraycopy(blockIndices, 0, mBlockIndices, 0, blockIndices.length);
|
||||
mNumberOfBlocks = numberOfBlocks;
|
||||
}
|
||||
@@ -484,8 +484,8 @@ public class DynamicLayout extends Layout
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int[] getBlockEnds() {
|
||||
return mBlockEnds;
|
||||
public int[] getBlockEndLines() {
|
||||
return mBlockEndLines;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -633,8 +633,8 @@ public class DynamicLayout extends Layout
|
||||
* @hide
|
||||
*/
|
||||
public static final int INVALID_BLOCK_INDEX = -1;
|
||||
// Stores the line numbers of the last line of each block
|
||||
private int[] mBlockEnds;
|
||||
// Stores the line numbers of the last line of each block (inclusive)
|
||||
private int[] mBlockEndLines;
|
||||
// The indices of this block's display list in TextView's internal display list array or
|
||||
// INVALID_BLOCK_INDEX if this block has been invalidated during an edition
|
||||
private int[] mBlockIndices;
|
||||
|
||||
@@ -1241,24 +1241,21 @@ public class Editor {
|
||||
}
|
||||
|
||||
DynamicLayout dynamicLayout = (DynamicLayout) layout;
|
||||
int[] blockEnds = dynamicLayout.getBlockEnds();
|
||||
int[] blockEndLines = dynamicLayout.getBlockEndLines();
|
||||
int[] blockIndices = dynamicLayout.getBlockIndices();
|
||||
final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
|
||||
|
||||
final int mScrollX = mTextView.getScrollX();
|
||||
final int mScrollY = mTextView.getScrollY();
|
||||
canvas.translate(mScrollX, mScrollY);
|
||||
int endOfPreviousBlock = -1;
|
||||
int searchStartIndex = 0;
|
||||
for (int i = 0; i < numberOfBlocks; i++) {
|
||||
int blockEnd = blockEnds[i];
|
||||
int blockEndLine = blockEndLines[i];
|
||||
int blockIndex = blockIndices[i];
|
||||
|
||||
final boolean blockIsInvalid = blockIndex == DynamicLayout.INVALID_BLOCK_INDEX;
|
||||
if (blockIsInvalid) {
|
||||
blockIndex = getAvailableDisplayListIndex(blockIndices, numberOfBlocks,
|
||||
searchStartIndex);
|
||||
// Dynamic layout internal block indices structure is updated from Editor
|
||||
// Note how dynamic layout's internal block indices get updated from Editor
|
||||
blockIndices[i] = blockIndex;
|
||||
searchStartIndex = blockIndex + 1;
|
||||
}
|
||||
@@ -1272,28 +1269,38 @@ public class Editor {
|
||||
}
|
||||
|
||||
if (!blockDisplayList.isValid()) {
|
||||
final int blockBeginLine = endOfPreviousBlock + 1;
|
||||
final int top = layout.getLineTop(blockBeginLine);
|
||||
final int bottom = layout.getLineBottom(blockEndLine);
|
||||
|
||||
final HardwareCanvas hardwareCanvas = blockDisplayList.start();
|
||||
try {
|
||||
hardwareCanvas.setViewport(width, height);
|
||||
hardwareCanvas.setViewport(width, bottom - top);
|
||||
// The dirty rect should always be null for a display list
|
||||
hardwareCanvas.onPreDraw(null);
|
||||
hardwareCanvas.translate(-mScrollX, -mScrollY);
|
||||
layout.drawText(hardwareCanvas, endOfPreviousBlock + 1, blockEnd);
|
||||
hardwareCanvas.translate(mScrollX, mScrollY);
|
||||
// drawText is always relative to TextView's origin, this translation brings
|
||||
// this range of text back to the top of the viewport
|
||||
hardwareCanvas.translate(0, -top);
|
||||
layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
|
||||
hardwareCanvas.translate(0, top);
|
||||
} finally {
|
||||
hardwareCanvas.onPostDraw();
|
||||
blockDisplayList.end();
|
||||
if (View.USE_DISPLAY_LIST_PROPERTIES) {
|
||||
blockDisplayList.setLeftTopRightBottom(0, 0, width, height);
|
||||
blockDisplayList.setLeftTopRightBottom(0, top, width, bottom);
|
||||
// Same as drawDisplayList below, handled by our TextView's parent
|
||||
blockDisplayList.setClipChildren(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO When View.USE_DISPLAY_LIST_PROPERTIES is the only code path, the
|
||||
// width and height parameters should be removed and the bounds set above in
|
||||
// setLeftTopRightBottom should be used instead for quick rejection.
|
||||
((HardwareCanvas) canvas).drawDisplayList(blockDisplayList, width, height, null,
|
||||
DisplayList.FLAG_CLIP_CHILDREN);
|
||||
endOfPreviousBlock = blockEnd;
|
||||
0 /* no child clipping, our TextView parent enforces it */);
|
||||
endOfPreviousBlock = blockEndLine;
|
||||
}
|
||||
canvas.translate(-mScrollX, -mScrollY);
|
||||
} else {
|
||||
// Boring layout is used for empty and hint text
|
||||
layout.drawText(canvas, firstLine, lastLine);
|
||||
@@ -1572,11 +1579,9 @@ public class Editor {
|
||||
}
|
||||
|
||||
void onScrollChanged() {
|
||||
if (mPositionListener != null) {
|
||||
mPositionListener.onScrollChanged();
|
||||
}
|
||||
// Internal scroll affects the clip boundaries
|
||||
invalidateTextDisplayList();
|
||||
if (mPositionListener != null) {
|
||||
mPositionListener.onScrollChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,18 +45,18 @@ public class DynamicLayoutBlocksTest extends TestCase {
|
||||
public void printBlocks(String message) {
|
||||
System.out.print(message);
|
||||
for (int i = 0; i < dl.getNumberOfBlocks(); i++) {
|
||||
System.out.print(" " + Integer.toString(dl.getBlockEnds()[i]));
|
||||
System.out.print(" " + Integer.toString(dl.getBlockEndLines()[i]));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
public void checkInvariants() {
|
||||
assertTrue(dl.getNumberOfBlocks() > 0);
|
||||
assertTrue(dl.getNumberOfBlocks() <= dl.getBlockEnds().length);
|
||||
assertEquals(dl.getBlockEnds().length, dl.getBlockIndices().length);
|
||||
assertTrue(dl.getNumberOfBlocks() <= dl.getBlockEndLines().length);
|
||||
assertEquals(dl.getBlockEndLines().length, dl.getBlockIndices().length);
|
||||
|
||||
for (int i = 1; i < dl.getNumberOfBlocks(); i++) {
|
||||
assertTrue(dl.getBlockEnds()[i] > dl.getBlockEnds()[i-1]);
|
||||
assertTrue(dl.getBlockEndLines()[i] > dl.getBlockEndLines()[i-1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class DynamicLayoutBlocksTest extends TestCase {
|
||||
}
|
||||
|
||||
for (int i = 0; i < dl.getNumberOfBlocks(); i++) {
|
||||
assertEquals(ends[i], dl.getBlockEnds()[i]);
|
||||
assertEquals(ends[i], dl.getBlockEndLines()[i]);
|
||||
assertEquals(indices[i], dl.getBlockIndices()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user