Merge "Fix DynamicLayout block index calculation after edit"

This commit is contained in:
Siyamed Sinir
2017-12-19 16:37:47 +00:00
committed by Android (Google) Code Review
2 changed files with 39 additions and 9 deletions

View File

@@ -492,7 +492,9 @@ public class DynamicLayout extends Layout
}
}
private void reflow(CharSequence s, int where, int before, int after) {
/** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void reflow(CharSequence s, int where, int before, int after) {
if (s != mBase)
return;
@@ -805,8 +807,8 @@ public class DynamicLayout extends Layout
return;
}
int firstBlock = -1;
int lastBlock = -1;
/*final*/ int firstBlock = -1;
/*final*/ int lastBlock = -1;
for (int i = 0; i < mNumberOfBlocks; i++) {
if (mBlockEndLines[i] >= startLine) {
firstBlock = i;
@@ -821,10 +823,10 @@ public class DynamicLayout extends Layout
}
final int lastBlockEndLine = mBlockEndLines[lastBlock];
boolean createBlockBefore = startLine > (firstBlock == 0 ? 0 :
final boolean createBlockBefore = startLine > (firstBlock == 0 ? 0 :
mBlockEndLines[firstBlock - 1] + 1);
boolean createBlock = newLineCount > 0;
boolean createBlockAfter = endLine < mBlockEndLines[lastBlock];
final boolean createBlock = newLineCount > 0;
final boolean createBlockAfter = endLine < mBlockEndLines[lastBlock];
int numAddedBlocks = 0;
if (createBlockBefore) numAddedBlocks++;
@@ -863,12 +865,18 @@ public class DynamicLayout extends Layout
if (numAddedBlocks + numRemovedBlocks != 0 && mBlocksAlwaysNeedToBeRedrawn != null) {
final ArraySet<Integer> set = new ArraySet<>();
final int changedBlockCount = numAddedBlocks - numRemovedBlocks;
for (int i = 0; i < mBlocksAlwaysNeedToBeRedrawn.size(); i++) {
Integer block = mBlocksAlwaysNeedToBeRedrawn.valueAt(i);
if (block > firstBlock) {
block += numAddedBlocks - numRemovedBlocks;
if (block < firstBlock) {
// block index is before firstBlock add it since it did not change
set.add(block);
}
if (block > lastBlock) {
// block index is after lastBlock, the index reduced to += changedBlockCount
block += changedBlockCount;
set.add(block);
}
set.add(block);
}
mBlocksAlwaysNeedToBeRedrawn = set;
}

View File

@@ -30,6 +30,7 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.text.style.ReplacementSpan;
import android.util.ArraySet;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -189,6 +190,27 @@ public class DynamicLayoutTest {
layout.getLineExtra(100);
}
@Test
public void testReflow_afterSpannableEdit() {
final String text = "a\nb:\uD83C\uDF1A c \n\uD83C\uDF1A";
final int length = text.length();
final SpannableStringBuilder spannable = new SpannableStringBuilder(text);
spannable.setSpan(new MockReplacementSpan(), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new MockReplacementSpan(), 10, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
final DynamicLayout layout = new DynamicLayout(spannable, new TextPaint(), WIDTH,
ALIGN_NORMAL, 1.0f /*spacingMultiplier*/, 0f /*spacingAdd*/, false /*includepad*/);
spannable.delete(8, 9);
spannable.replace(7, 8, "ch");
layout.reflow(spannable, 0, length, length);
final ArraySet<Integer> blocks = layout.getBlocksAlwaysNeedToBeRedrawn();
for (Integer value : blocks) {
assertTrue("Block index should not be negative", value >= 0);
}
}
@Test
public void testFallbackLineSpacing() {
// All glyphs in the fonts are 1em wide.