Skip to content

Commit 0b568ff

Browse files
Gilles DebunneAndroid (Google) Code Review
authored andcommitted
Merge "TextView's sub display lists have tighten bounds"
2 parents 80a7627 + 157aafc commit 0b568ff

File tree

3 files changed

+55
-50
lines changed

3 files changed

+55
-50
lines changed

core/java/android/text/DynamicLayout.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public DynamicLayout(CharSequence base, CharSequence display,
117117

118118
mObjects = new PackedObjectVector<Directions>(1);
119119

120-
mBlockEnds = new int[] { 0 };
120+
mBlockEndLines = new int[] { 0 };
121121
mBlockIndices = new int[] { INVALID_BLOCK_INDEX };
122122
mNumberOfBlocks = 1;
123123

@@ -391,23 +391,23 @@ void updateBlocks(int startLine, int endLine, int newLineCount) {
391391
int firstBlock = -1;
392392
int lastBlock = -1;
393393
for (int i = 0; i < mNumberOfBlocks; i++) {
394-
if (mBlockEnds[i] >= startLine) {
394+
if (mBlockEndLines[i] >= startLine) {
395395
firstBlock = i;
396396
break;
397397
}
398398
}
399399
for (int i = firstBlock; i < mNumberOfBlocks; i++) {
400-
if (mBlockEnds[i] >= endLine) {
400+
if (mBlockEndLines[i] >= endLine) {
401401
lastBlock = i;
402402
break;
403403
}
404404
}
405-
final int lastBlockEndLine = mBlockEnds[lastBlock];
405+
final int lastBlockEndLine = mBlockEndLines[lastBlock];
406406

407407
boolean createBlockBefore = startLine > (firstBlock == 0 ? 0 :
408-
mBlockEnds[firstBlock - 1] + 1);
408+
mBlockEndLines[firstBlock - 1] + 1);
409409
boolean createBlock = newLineCount > 0;
410-
boolean createBlockAfter = endLine < mBlockEnds[lastBlock];
410+
boolean createBlockAfter = endLine < mBlockEndLines[lastBlock];
411411

412412
int numAddedBlocks = 0;
413413
if (createBlockBefore) numAddedBlocks++;
@@ -419,52 +419,52 @@ void updateBlocks(int startLine, int endLine, int newLineCount) {
419419

420420
if (newNumberOfBlocks == 0) {
421421
// Even when text is empty, there is actually one line and hence one block
422-
mBlockEnds[0] = 0;
422+
mBlockEndLines[0] = 0;
423423
mBlockIndices[0] = INVALID_BLOCK_INDEX;
424424
mNumberOfBlocks = 1;
425425
return;
426426
}
427427

428-
if (newNumberOfBlocks > mBlockEnds.length) {
428+
if (newNumberOfBlocks > mBlockEndLines.length) {
429429
final int newSize = ArrayUtils.idealIntArraySize(newNumberOfBlocks);
430-
int[] blockEnds = new int[newSize];
430+
int[] blockEndLines = new int[newSize];
431431
int[] blockIndices = new int[newSize];
432-
System.arraycopy(mBlockEnds, 0, blockEnds, 0, firstBlock);
432+
System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, firstBlock);
433433
System.arraycopy(mBlockIndices, 0, blockIndices, 0, firstBlock);
434-
System.arraycopy(mBlockEnds, lastBlock + 1,
435-
blockEnds, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
434+
System.arraycopy(mBlockEndLines, lastBlock + 1,
435+
blockEndLines, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
436436
System.arraycopy(mBlockIndices, lastBlock + 1,
437437
blockIndices, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
438-
mBlockEnds = blockEnds;
438+
mBlockEndLines = blockEndLines;
439439
mBlockIndices = blockIndices;
440440
} else {
441-
System.arraycopy(mBlockEnds, lastBlock + 1,
442-
mBlockEnds, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
441+
System.arraycopy(mBlockEndLines, lastBlock + 1,
442+
mBlockEndLines, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
443443
System.arraycopy(mBlockIndices, lastBlock + 1,
444444
mBlockIndices, firstBlock + numAddedBlocks, mNumberOfBlocks - lastBlock - 1);
445445
}
446446

447447
mNumberOfBlocks = newNumberOfBlocks;
448448
final int deltaLines = newLineCount - (endLine - startLine + 1);
449449
for (int i = firstBlock + numAddedBlocks; i < mNumberOfBlocks; i++) {
450-
mBlockEnds[i] += deltaLines;
450+
mBlockEndLines[i] += deltaLines;
451451
}
452452

453453
int blockIndex = firstBlock;
454454
if (createBlockBefore) {
455-
mBlockEnds[blockIndex] = startLine - 1;
455+
mBlockEndLines[blockIndex] = startLine - 1;
456456
mBlockIndices[blockIndex] = INVALID_BLOCK_INDEX;
457457
blockIndex++;
458458
}
459459

460460
if (createBlock) {
461-
mBlockEnds[blockIndex] = startLine + newLineCount - 1;
461+
mBlockEndLines[blockIndex] = startLine + newLineCount - 1;
462462
mBlockIndices[blockIndex] = INVALID_BLOCK_INDEX;
463463
blockIndex++;
464464
}
465465

466466
if (createBlockAfter) {
467-
mBlockEnds[blockIndex] = lastBlockEndLine + deltaLines;
467+
mBlockEndLines[blockIndex] = lastBlockEndLine + deltaLines;
468468
mBlockIndices[blockIndex] = INVALID_BLOCK_INDEX;
469469
}
470470
}
@@ -473,19 +473,19 @@ void updateBlocks(int startLine, int endLine, int newLineCount) {
473473
* This package private method is used for test purposes only
474474
* @hide
475475
*/
476-
void setBlocksDataForTest(int[] blockEnds, int[] blockIndices, int numberOfBlocks) {
477-
mBlockEnds = new int[blockEnds.length];
476+
void setBlocksDataForTest(int[] blockEndLines, int[] blockIndices, int numberOfBlocks) {
477+
mBlockEndLines = new int[blockEndLines.length];
478478
mBlockIndices = new int[blockIndices.length];
479-
System.arraycopy(blockEnds, 0, mBlockEnds, 0, blockEnds.length);
479+
System.arraycopy(blockEndLines, 0, mBlockEndLines, 0, blockEndLines.length);
480480
System.arraycopy(blockIndices, 0, mBlockIndices, 0, blockIndices.length);
481481
mNumberOfBlocks = numberOfBlocks;
482482
}
483483

484484
/**
485485
* @hide
486486
*/
487-
public int[] getBlockEnds() {
488-
return mBlockEnds;
487+
public int[] getBlockEndLines() {
488+
return mBlockEndLines;
489489
}
490490

491491
/**
@@ -633,8 +633,8 @@ public int getEllipsisCount(int line) {
633633
* @hide
634634
*/
635635
public static final int INVALID_BLOCK_INDEX = -1;
636-
// Stores the line numbers of the last line of each block
637-
private int[] mBlockEnds;
636+
// Stores the line numbers of the last line of each block (inclusive)
637+
private int[] mBlockEndLines;
638638
// The indices of this block's display list in TextView's internal display list array or
639639
// INVALID_BLOCK_INDEX if this block has been invalidated during an edition
640640
private int[] mBlockIndices;

core/java/android/widget/Editor.java

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,24 +1241,21 @@ private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highligh
12411241
}
12421242

12431243
DynamicLayout dynamicLayout = (DynamicLayout) layout;
1244-
int[] blockEnds = dynamicLayout.getBlockEnds();
1244+
int[] blockEndLines = dynamicLayout.getBlockEndLines();
12451245
int[] blockIndices = dynamicLayout.getBlockIndices();
12461246
final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
12471247

1248-
final int mScrollX = mTextView.getScrollX();
1249-
final int mScrollY = mTextView.getScrollY();
1250-
canvas.translate(mScrollX, mScrollY);
12511248
int endOfPreviousBlock = -1;
12521249
int searchStartIndex = 0;
12531250
for (int i = 0; i < numberOfBlocks; i++) {
1254-
int blockEnd = blockEnds[i];
1251+
int blockEndLine = blockEndLines[i];
12551252
int blockIndex = blockIndices[i];
12561253

12571254
final boolean blockIsInvalid = blockIndex == DynamicLayout.INVALID_BLOCK_INDEX;
12581255
if (blockIsInvalid) {
12591256
blockIndex = getAvailableDisplayListIndex(blockIndices, numberOfBlocks,
12601257
searchStartIndex);
1261-
// Dynamic layout internal block indices structure is updated from Editor
1258+
// Note how dynamic layout's internal block indices get updated from Editor
12621259
blockIndices[i] = blockIndex;
12631260
searchStartIndex = blockIndex + 1;
12641261
}
@@ -1272,28 +1269,38 @@ private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highligh
12721269
}
12731270

12741271
if (!blockDisplayList.isValid()) {
1272+
final int blockBeginLine = endOfPreviousBlock + 1;
1273+
final int top = layout.getLineTop(blockBeginLine);
1274+
final int bottom = layout.getLineBottom(blockEndLine);
1275+
12751276
final HardwareCanvas hardwareCanvas = blockDisplayList.start();
12761277
try {
1277-
hardwareCanvas.setViewport(width, height);
1278+
hardwareCanvas.setViewport(width, bottom - top);
12781279
// The dirty rect should always be null for a display list
12791280
hardwareCanvas.onPreDraw(null);
1280-
hardwareCanvas.translate(-mScrollX, -mScrollY);
1281-
layout.drawText(hardwareCanvas, endOfPreviousBlock + 1, blockEnd);
1282-
hardwareCanvas.translate(mScrollX, mScrollY);
1281+
// drawText is always relative to TextView's origin, this translation brings
1282+
// this range of text back to the top of the viewport
1283+
hardwareCanvas.translate(0, -top);
1284+
layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
1285+
hardwareCanvas.translate(0, top);
12831286
} finally {
12841287
hardwareCanvas.onPostDraw();
12851288
blockDisplayList.end();
12861289
if (View.USE_DISPLAY_LIST_PROPERTIES) {
1287-
blockDisplayList.setLeftTopRightBottom(0, 0, width, height);
1290+
blockDisplayList.setLeftTopRightBottom(0, top, width, bottom);
1291+
// Same as drawDisplayList below, handled by our TextView's parent
1292+
blockDisplayList.setClipChildren(false);
12881293
}
12891294
}
12901295
}
12911296

1297+
// TODO When View.USE_DISPLAY_LIST_PROPERTIES is the only code path, the
1298+
// width and height parameters should be removed and the bounds set above in
1299+
// setLeftTopRightBottom should be used instead for quick rejection.
12921300
((HardwareCanvas) canvas).drawDisplayList(blockDisplayList, width, height, null,
1293-
DisplayList.FLAG_CLIP_CHILDREN);
1294-
endOfPreviousBlock = blockEnd;
1301+
0 /* no child clipping, our TextView parent enforces it */);
1302+
endOfPreviousBlock = blockEndLine;
12951303
}
1296-
canvas.translate(-mScrollX, -mScrollY);
12971304
} else {
12981305
// Boring layout is used for empty and hint text
12991306
layout.drawText(canvas, firstLine, lastLine);
@@ -1572,11 +1579,9 @@ boolean areSuggestionsShown() {
15721579
}
15731580

15741581
void onScrollChanged() {
1575-
if (mPositionListener != null) {
1576-
mPositionListener.onScrollChanged();
1577-
}
1578-
// Internal scroll affects the clip boundaries
1579-
invalidateTextDisplayList();
1582+
if (mPositionListener != null) {
1583+
mPositionListener.onScrollChanged();
1584+
}
15801585
}
15811586

15821587
/**

core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,18 @@ private void defineInitialState(int[] ends, int[] indices) {
4545
public void printBlocks(String message) {
4646
System.out.print(message);
4747
for (int i = 0; i < dl.getNumberOfBlocks(); i++) {
48-
System.out.print(" " + Integer.toString(dl.getBlockEnds()[i]));
48+
System.out.print(" " + Integer.toString(dl.getBlockEndLines()[i]));
4949
}
5050
System.out.println();
5151
}
5252

5353
public void checkInvariants() {
5454
assertTrue(dl.getNumberOfBlocks() > 0);
55-
assertTrue(dl.getNumberOfBlocks() <= dl.getBlockEnds().length);
56-
assertEquals(dl.getBlockEnds().length, dl.getBlockIndices().length);
55+
assertTrue(dl.getNumberOfBlocks() <= dl.getBlockEndLines().length);
56+
assertEquals(dl.getBlockEndLines().length, dl.getBlockIndices().length);
5757

5858
for (int i = 1; i < dl.getNumberOfBlocks(); i++) {
59-
assertTrue(dl.getBlockEnds()[i] > dl.getBlockEnds()[i-1]);
59+
assertTrue(dl.getBlockEndLines()[i] > dl.getBlockEndLines()[i-1]);
6060
}
6161
}
6262

@@ -78,7 +78,7 @@ private void assertState(int[] sizes, int[] indices) {
7878
}
7979

8080
for (int i = 0; i < dl.getNumberOfBlocks(); i++) {
81-
assertEquals(ends[i], dl.getBlockEnds()[i]);
81+
assertEquals(ends[i], dl.getBlockEndLines()[i]);
8282
assertEquals(indices[i], dl.getBlockIndices()[i]);
8383
}
8484
}

0 commit comments

Comments
 (0)