From 987eb3f109c646476d1310a54f7037a558ccfef3 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sat, 9 Aug 2014 00:11:41 +0900 Subject: [PATCH] Fix handling of line-end and RTL characters in CursorAnchorInfo This CL addresses line-end handling and RTL characters handling in CursorAnchorInfo. BUG: 16499624 Change-Id: Ie23569fb136751c40f79dd9886e279dc01cefae9 --- core/java/android/widget/Editor.java | 39 ++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 58f98013ee8ac..b37ee06da93cd 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3080,40 +3080,47 @@ public class Editor { composingTextEnd); builder.setComposingText(composingTextStart, composingText); } + // TODO: Optimize this loop by caching the result. for (int offset = composingTextStart; offset < composingTextEnd; offset++) { if (offset < 0) { continue; } + final boolean isRtl = layout.isRtlCharAt(offset); final int line = layout.getLineForOffset(offset); - final float left = layout.getPrimaryHorizontal(offset) + final int nextCharIndex = offset + 1; + final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset); + final float localTrailingEdgeX; + if (nextCharIndex != layout.getLineEnd(line)) { + localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex); + } else if (isRtl) { + localTrailingEdgeX = layout.getLineLeft(line); + } else { + localTrailingEdgeX = layout.getLineRight(line); + } + final float leadingEdgeX = localLeadingEdgeX + + viewportToContentHorizontalOffset; + final float trailingEdgeX = localTrailingEdgeX + viewportToContentHorizontalOffset; final float top = layout.getLineTop(line) + viewportToContentVerticalOffset; - // Here we are tentatively passing offset + 1 to calculate the other side of - // the primary horizontal to preserve as many positions as possible so that - // the IME can reconstruct the layout entirely. However, we should revisit this - // to have a clear specification about the relationship between the index of - // the character and its bounding box. See also the TODO comment below. - final float right = layout.getPrimaryHorizontal(offset + 1) - + viewportToContentHorizontalOffset; final float bottom = layout.getLineBottom(line) + viewportToContentVerticalOffset; - // Take TextView's padding and scroll into account. // TODO: Check right-top and left-bottom as well. - final boolean leftTopVisible = isPositionVisible(left, top); - final boolean rightBottomVisible = isPositionVisible(right, bottom); + final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top); + final boolean isTrailingEdgeBottomVisible = + isPositionVisible(trailingEdgeX, bottom); final int characterRectFlags; - if (leftTopVisible && rightBottomVisible) { + if (isLeadingEdgeTopVisible && isTrailingEdgeBottomVisible) { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE; - } else if (leftTopVisible || rightBottomVisible) { + } else if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE; } else { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE; } // Here offset is the index in Java chars. // TODO: We must have a well-defined specification. For example, how - // RTL, surrogate pairs, and composition letters are handled must be - // documented. - builder.addCharacterRect(offset, left, top, right, bottom, characterRectFlags); + // surrogate pairs and composition letters are handled must be documented. + builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom, + characterRectFlags); } }