diff options
-rw-r--r-- | core/java/android/text/DynamicLayout.java | 52 | ||||
-rw-r--r-- | core/java/android/widget/Editor.java | 43 | ||||
-rw-r--r-- | core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java | 10 |
3 files changed, 55 insertions, 50 deletions
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index ff5a467..dc58ef2 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -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; diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 040a385..900f0d3 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -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(); + } } /** diff --git a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java index 73da84f..2e42e5a 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java @@ -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]); } } |