3535public 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