Skip to content

Commit 0ae107f

Browse files
Gilles DebunneAndroid (Google) Code Review
authored andcommitted
Merge "Cut long text into multiple DL at start" into jb-dev
2 parents ab1c545 + 71afc39 commit 0ae107f

File tree

1 file changed

+65
-8
lines changed

1 file changed

+65
-8
lines changed

core/java/android/text/DynamicLayout.java

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
public class DynamicLayout extends Layout
3636
{
3737
private static final int PRIORITY = 128;
38+
private static final int BLOCK_MINIMUM_CHARACTER_LENGTH = 400;
3839

3940
/**
4041
* Make a layout for the specified text that will be updated as
@@ -117,10 +118,6 @@ public DynamicLayout(CharSequence base, CharSequence display,
117118

118119
mObjects = new PackedObjectVector<Directions>(1);
119120

120-
mBlockEndLines = new int[] { 0 };
121-
mBlockIndices = new int[] { INVALID_BLOCK_INDEX };
122-
mNumberOfBlocks = 1;
123-
124121
mIncludePad = includepad;
125122

126123
/*
@@ -170,7 +167,6 @@ public DynamicLayout(CharSequence base, CharSequence display,
170167
mObjects.insertAt(0, dirs);
171168

172169
// Update from 0 characters to whatever the real text is
173-
174170
reflow(base, 0, 0, base.length());
175171

176172
if (base instanceof Spannable) {
@@ -295,14 +291,12 @@ private void reflow(CharSequence s, int where, int before, int after) {
295291
// the very end of the buffer, then we already have a line that
296292
// starts there, so disregard the blank line.
297293

298-
if (where + after != len &&
299-
reflowed.getLineStart(n - 1) == where + after)
294+
if (where + after != len && reflowed.getLineStart(n - 1) == where + after)
300295
n--;
301296

302297
// remove affected lines from old layout
303298
mInts.deleteAt(startline, endline - startline);
304299
mObjects.deleteAt(startline, endline - startline);
305-
updateBlocks(startline, endline - 1, n);
306300

307301
// adjust offsets in layout for new height and offsets
308302

@@ -362,12 +356,70 @@ private void reflow(CharSequence s, int where, int before, int after) {
362356
mObjects.insertAt(startline + i, objects);
363357
}
364358

359+
updateBlocks(startline, endline - 1, n);
360+
365361
synchronized (sLock) {
366362
sStaticLayout = reflowed;
367363
reflowed.finish();
368364
}
369365
}
370366

367+
/**
368+
* Create the initial block structure, cutting the text into blocks of at least
369+
* BLOCK_MINIMUM_CHARACTER_SIZE characters, aligned on the ends of paragraphs.
370+
*/
371+
private void createBlocks() {
372+
int offset = BLOCK_MINIMUM_CHARACTER_LENGTH;
373+
mNumberOfBlocks = 0;
374+
final CharSequence text = mDisplay;
375+
376+
while (true) {
377+
offset = TextUtils.indexOf(text, '\n', offset);
378+
if (offset < 0) {
379+
addBlockAtOffset(text.length());
380+
break;
381+
} else {
382+
addBlockAtOffset(offset);
383+
offset += BLOCK_MINIMUM_CHARACTER_LENGTH;
384+
}
385+
}
386+
387+
// mBlockIndices and mBlockEndLines should have the same length
388+
mBlockIndices = new int[mBlockEndLines.length];
389+
for (int i = 0; i < mBlockEndLines.length; i++) {
390+
mBlockIndices[i] = INVALID_BLOCK_INDEX;
391+
}
392+
}
393+
394+
/**
395+
* Create a new block, ending at the specified character offset.
396+
* A block will actually be created only if has at least one line, i.e. this offset is
397+
* not on the end line of the previous block.
398+
*/
399+
private void addBlockAtOffset(int offset) {
400+
final int line = getLineForOffset(offset);
401+
402+
if (mBlockEndLines == null) {
403+
// Initial creation of the array, no test on previous block ending line
404+
mBlockEndLines = new int[ArrayUtils.idealIntArraySize(1)];
405+
mBlockEndLines[mNumberOfBlocks] = line;
406+
mNumberOfBlocks++;
407+
return;
408+
}
409+
410+
final int previousBlockEndLine = mBlockEndLines[mNumberOfBlocks - 1];
411+
if (line > previousBlockEndLine) {
412+
if (mNumberOfBlocks == mBlockEndLines.length) {
413+
// Grow the array if needed
414+
int[] blockEndLines = new int[ArrayUtils.idealIntArraySize(mNumberOfBlocks + 1)];
415+
System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, mNumberOfBlocks);
416+
mBlockEndLines = blockEndLines;
417+
}
418+
mBlockEndLines[mNumberOfBlocks] = line;
419+
mNumberOfBlocks++;
420+
}
421+
}
422+
371423
/**
372424
* This method is called every time the layout is reflowed after an edition.
373425
* It updates the internal block data structure. The text is split in blocks
@@ -388,6 +440,11 @@ private void reflow(CharSequence s, int where, int before, int after) {
388440
* @hide
389441
*/
390442
void updateBlocks(int startLine, int endLine, int newLineCount) {
443+
if (mBlockEndLines == null) {
444+
createBlocks();
445+
return;
446+
}
447+
391448
int firstBlock = -1;
392449
int lastBlock = -1;
393450
for (int i = 0; i < mNumberOfBlocks; i++) {

0 commit comments

Comments
 (0)