Loading core/java/android/text/DynamicLayout.java +26 −26 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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++; Loading @@ -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); } Loading @@ -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; } } Loading @@ -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; } Loading @@ -484,8 +484,8 @@ public class DynamicLayout extends Layout /** * @hide */ public int[] getBlockEnds() { return mBlockEnds; public int[] getBlockEndLines() { return mBlockEndLines; } /** Loading Loading @@ -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; Loading core/java/android/widget/Editor.java +24 −19 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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); Loading Loading @@ -1575,8 +1582,6 @@ public class Editor { if (mPositionListener != null) { mPositionListener.onScrollChanged(); } // Internal scroll affects the clip boundaries invalidateTextDisplayList(); } /** Loading core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java +5 −5 Original line number Diff line number Diff line Loading @@ -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]); } } Loading @@ -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]); } } Loading Loading
core/java/android/text/DynamicLayout.java +26 −26 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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++; Loading @@ -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); } Loading @@ -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; } } Loading @@ -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; } Loading @@ -484,8 +484,8 @@ public class DynamicLayout extends Layout /** * @hide */ public int[] getBlockEnds() { return mBlockEnds; public int[] getBlockEndLines() { return mBlockEndLines; } /** Loading Loading @@ -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; Loading
core/java/android/widget/Editor.java +24 −19 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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); Loading Loading @@ -1575,8 +1582,6 @@ public class Editor { if (mPositionListener != null) { mPositionListener.onScrollChanged(); } // Internal scroll affects the clip boundaries invalidateTextDisplayList(); } /** Loading
core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java +5 −5 Original line number Diff line number Diff line Loading @@ -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]); } } Loading @@ -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]); } } Loading