Loading core/java/android/widget/SpellChecker.java +8 −6 Original line number Diff line number Diff line Loading @@ -274,9 +274,11 @@ public class SpellChecker implements SpellCheckerSessionListener { ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0); SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j]; if (!isInDictionary && looksLikeTypo) { createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan); } editable.removeSpan(spellCheckSpan); break; } Loading @@ -292,20 +294,21 @@ public class SpellChecker implements SpellCheckerSessionListener { } } private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo, SpellCheckSpan spellCheckSpan) { private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo, SpellCheckSpan spellCheckSpan) { final int start = editable.getSpanStart(spellCheckSpan); final int end = editable.getSpanEnd(spellCheckSpan); if (start < 0 || end < 0) return; // span was removed in the meantime if (start < 0 || end <= start) return; // span was removed in the meantime // Other suggestion spans may exist on that region, with identical suggestions, filter // them out to avoid duplicates. First, filter suggestion spans on that exact region. // them out to avoid duplicates. SuggestionSpan[] suggestionSpans = editable.getSpans(start, end, SuggestionSpan.class); final int length = suggestionSpans.length; for (int i = 0; i < length; i++) { final int spanStart = editable.getSpanStart(suggestionSpans[i]); final int spanEnd = editable.getSpanEnd(suggestionSpans[i]); if (spanStart != start || spanEnd != end) { // Nulled (to avoid new array allocation) if not on that exact same region suggestionSpans[i] = null; } } Loading Loading @@ -353,8 +356,7 @@ public class SpellChecker implements SpellCheckerSessionListener { SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED); editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // TODO limit to the word rectangle region mTextView.invalidate(); mTextView.invalidateRegion(start, end); } private class SpellParser { Loading core/java/android/widget/TextView.java +40 −33 Original line number Diff line number Diff line Loading @@ -4323,15 +4323,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void invalidateCursor(int a, int b, int c) { if (a >= 0 || b >= 0 || c >= 0) { int start = Math.min(Math.min(a, b), c); int end = Math.max(Math.max(a, b), c); invalidateRegion(start, end); } } /** * Invalidates the region of text enclosed between the start and end text offsets. * * @hide */ void invalidateRegion(int start, int end) { if (mLayout == null) { invalidate(); } else { if (a >= 0 || b >= 0 || c >= 0) { int first = Math.min(Math.min(a, b), c); int last = Math.max(Math.max(a, b), c); int line = mLayout.getLineForOffset(first); int top = mLayout.getLineTop(line); int lineStart = mLayout.getLineForOffset(start); int top = mLayout.getLineTop(lineStart); // This is ridiculous, but the descent from the line above // can hang down into the line we really want to redraw, Loading @@ -4339,36 +4348,36 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // sure everything that needs to be redrawn really is. // (But not the whole line above, because that would cause // the same problem with the descenders on the line above it!) if (line > 0) { top -= mLayout.getLineDescent(line - 1); if (lineStart > 0) { top -= mLayout.getLineDescent(lineStart - 1); } int line2; int lineEnd; if (first == last) line2 = line; if (start == end) lineEnd = lineStart; else line2 = mLayout.getLineForOffset(last); lineEnd = mLayout.getLineForOffset(end); int bottom = mLayout.getLineTop(line2 + 1); int bottom = mLayout.getLineBottom(lineEnd); final int horizontalPadding = getCompoundPaddingLeft(); final int compoundPaddingLeft = getCompoundPaddingLeft(); final int verticalPadding = getExtendedPaddingTop() + getVerticalOffset(true); // If used, the cursor drawables can have an arbitrary dimension that can go beyond // the invalidated lines specified above. for (int i = 0; i < mCursorCount; i++) { Rect bounds = mCursorDrawable[i].getBounds(); top = Math.min(top, bounds.top); bottom = Math.max(bottom, bounds.bottom); // Horizontal bounds are already full width, no need to update int left, right; if (lineStart == lineEnd) { left = (int) mLayout.getPrimaryHorizontal(start); right = (int) (mLayout.getPrimaryHorizontal(end) + 1.0); left += compoundPaddingLeft; right += compoundPaddingLeft; } else { // Rectangle bounding box when the region spans several lines left = compoundPaddingLeft; right = getWidth() - getCompoundPaddingRight(); } invalidate(horizontalPadding + mScrollX, top + verticalPadding, horizontalPadding + mScrollX + getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight(), bottom + verticalPadding); } invalidate(mScrollX + left, verticalPadding + top, mScrollX + right, verticalPadding + bottom); } } Loading Loading @@ -5901,10 +5910,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (cursorOffsetVertical != 0) { canvas.translate(0, -cursorOffsetVertical); } invalidate(true); invalidate(true); // TODO invalidate cursor region only } else { stopAnimation(); invalidate(false); invalidate(false); // TODO invalidate cursor region only } } Loading Loading @@ -7725,9 +7734,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } if (what instanceof UpdateAppearance || what instanceof ParagraphStyle || (what instanceof SuggestionSpan && (((SuggestionSpan)what).getFlags() & SuggestionSpan.FLAG_AUTO_CORRECTION) != 0)) { if (what instanceof UpdateAppearance || what instanceof ParagraphStyle) { if (ims == null || ims.mBatchEditNesting == 0) { invalidate(); mHighlightPathBogus = true; Loading Loading
core/java/android/widget/SpellChecker.java +8 −6 Original line number Diff line number Diff line Loading @@ -274,9 +274,11 @@ public class SpellChecker implements SpellCheckerSessionListener { ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0); SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j]; if (!isInDictionary && looksLikeTypo) { createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan); } editable.removeSpan(spellCheckSpan); break; } Loading @@ -292,20 +294,21 @@ public class SpellChecker implements SpellCheckerSessionListener { } } private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo, SpellCheckSpan spellCheckSpan) { private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo, SpellCheckSpan spellCheckSpan) { final int start = editable.getSpanStart(spellCheckSpan); final int end = editable.getSpanEnd(spellCheckSpan); if (start < 0 || end < 0) return; // span was removed in the meantime if (start < 0 || end <= start) return; // span was removed in the meantime // Other suggestion spans may exist on that region, with identical suggestions, filter // them out to avoid duplicates. First, filter suggestion spans on that exact region. // them out to avoid duplicates. SuggestionSpan[] suggestionSpans = editable.getSpans(start, end, SuggestionSpan.class); final int length = suggestionSpans.length; for (int i = 0; i < length; i++) { final int spanStart = editable.getSpanStart(suggestionSpans[i]); final int spanEnd = editable.getSpanEnd(suggestionSpans[i]); if (spanStart != start || spanEnd != end) { // Nulled (to avoid new array allocation) if not on that exact same region suggestionSpans[i] = null; } } Loading Loading @@ -353,8 +356,7 @@ public class SpellChecker implements SpellCheckerSessionListener { SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED); editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // TODO limit to the word rectangle region mTextView.invalidate(); mTextView.invalidateRegion(start, end); } private class SpellParser { Loading
core/java/android/widget/TextView.java +40 −33 Original line number Diff line number Diff line Loading @@ -4323,15 +4323,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void invalidateCursor(int a, int b, int c) { if (a >= 0 || b >= 0 || c >= 0) { int start = Math.min(Math.min(a, b), c); int end = Math.max(Math.max(a, b), c); invalidateRegion(start, end); } } /** * Invalidates the region of text enclosed between the start and end text offsets. * * @hide */ void invalidateRegion(int start, int end) { if (mLayout == null) { invalidate(); } else { if (a >= 0 || b >= 0 || c >= 0) { int first = Math.min(Math.min(a, b), c); int last = Math.max(Math.max(a, b), c); int line = mLayout.getLineForOffset(first); int top = mLayout.getLineTop(line); int lineStart = mLayout.getLineForOffset(start); int top = mLayout.getLineTop(lineStart); // This is ridiculous, but the descent from the line above // can hang down into the line we really want to redraw, Loading @@ -4339,36 +4348,36 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // sure everything that needs to be redrawn really is. // (But not the whole line above, because that would cause // the same problem with the descenders on the line above it!) if (line > 0) { top -= mLayout.getLineDescent(line - 1); if (lineStart > 0) { top -= mLayout.getLineDescent(lineStart - 1); } int line2; int lineEnd; if (first == last) line2 = line; if (start == end) lineEnd = lineStart; else line2 = mLayout.getLineForOffset(last); lineEnd = mLayout.getLineForOffset(end); int bottom = mLayout.getLineTop(line2 + 1); int bottom = mLayout.getLineBottom(lineEnd); final int horizontalPadding = getCompoundPaddingLeft(); final int compoundPaddingLeft = getCompoundPaddingLeft(); final int verticalPadding = getExtendedPaddingTop() + getVerticalOffset(true); // If used, the cursor drawables can have an arbitrary dimension that can go beyond // the invalidated lines specified above. for (int i = 0; i < mCursorCount; i++) { Rect bounds = mCursorDrawable[i].getBounds(); top = Math.min(top, bounds.top); bottom = Math.max(bottom, bounds.bottom); // Horizontal bounds are already full width, no need to update int left, right; if (lineStart == lineEnd) { left = (int) mLayout.getPrimaryHorizontal(start); right = (int) (mLayout.getPrimaryHorizontal(end) + 1.0); left += compoundPaddingLeft; right += compoundPaddingLeft; } else { // Rectangle bounding box when the region spans several lines left = compoundPaddingLeft; right = getWidth() - getCompoundPaddingRight(); } invalidate(horizontalPadding + mScrollX, top + verticalPadding, horizontalPadding + mScrollX + getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight(), bottom + verticalPadding); } invalidate(mScrollX + left, verticalPadding + top, mScrollX + right, verticalPadding + bottom); } } Loading Loading @@ -5901,10 +5910,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (cursorOffsetVertical != 0) { canvas.translate(0, -cursorOffsetVertical); } invalidate(true); invalidate(true); // TODO invalidate cursor region only } else { stopAnimation(); invalidate(false); invalidate(false); // TODO invalidate cursor region only } } Loading Loading @@ -7725,9 +7734,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } if (what instanceof UpdateAppearance || what instanceof ParagraphStyle || (what instanceof SuggestionSpan && (((SuggestionSpan)what).getFlags() & SuggestionSpan.FLAG_AUTO_CORRECTION) != 0)) { if (what instanceof UpdateAppearance || what instanceof ParagraphStyle) { if (ims == null || ims.mBatchEditNesting == 0) { invalidate(); mHighlightPathBogus = true; Loading