Skip to content

Commit 12122bf

Browse files
Takako IshibashiJohan Redestig
authored andcommitted
Support surrogate pairs when layouting text
The current framework does not consider surrogate pairs when getting the index of the character. This bug becomes visible when creating the text including Emojis. For example cursor breaks up when it moves around the Emojis. Our proposed solution will consider the surrogate pairs when calculating the index. It will fix not only the Emoji case, but also the letters that use surrogate pairs. Change-Id: I4983f2e4df933c8af9d5f0cc27df871e8e10fed4
1 parent f3ee6f8 commit 12122bf

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

core/java/android/text/Layout.java

100644100755
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,9 @@ public int getOffsetForHorizontal(int line, float horiz) {
749749
if (line == getLineCount() - 1)
750750
max++;
751751

752+
if (line != getLineCount() - 1)
753+
max = TextUtils.getOffsetBefore(mText, getLineEnd(line));
754+
752755
int best = min;
753756
float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz);
754757

@@ -893,7 +896,7 @@ public int getOffsetToLeftOf(int offset) {
893896
Directions dirs = getLineDirections(line);
894897

895898
if (line != getLineCount() - 1)
896-
end--;
899+
end = TextUtils.getOffsetBefore(mText, end);
897900

898901
float horiz = getPrimaryHorizontal(offset);
899902

@@ -993,7 +996,7 @@ public int getOffsetToRightOf(int offset) {
993996
Directions dirs = getLineDirections(line);
994997

995998
if (line != getLineCount() - 1)
996-
end--;
999+
end = TextUtils.getOffsetBefore(mText, end);
9971000

9981001
float horiz = getPrimaryHorizontal(offset);
9991002

@@ -1564,7 +1567,8 @@ private static float measureText(TextPaint paint,
15641567
h = dir * nextTab(text, start, end, h * dir, tabs);
15651568
}
15661569

1567-
if (bm != null) {
1570+
if (j != there && bm != null) {
1571+
if (offset == start + j) return h;
15681572
workPaint.set(paint);
15691573
Styled.measureText(paint, workPaint, text,
15701574
j, j + 2, null);
@@ -1958,4 +1962,3 @@ public enum Alignment {
19581962
new Directions(new short[] { 0, 32767 });
19591963

19601964
}
1961-

core/java/android/text/StaticLayout.java

100644100755
Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,17 +313,21 @@ public StaticLayout(CharSequence source, int bufstart, int bufend,
313313
class);
314314

315315
if (spanned == null) {
316-
paint.getTextWidths(sub, i, next, widths);
316+
final int actualNum = paint.getTextWidths(sub, i, next, widths);
317+
if (next - i > actualNum)
318+
adjustTextWidths(widths, sub, i, next, actualNum);
317319
System.arraycopy(widths, 0, widths,
318320
end - start + (i - start), next - i);
319321

320322
paint.getFontMetricsInt(fm);
321323
} else {
322324
mWorkPaint.baselineShift = 0;
323325

324-
Styled.getTextWidths(paint, mWorkPaint,
325-
spanned, i, next,
326-
widths, fm);
326+
final int actualNum = Styled.getTextWidths(paint, mWorkPaint,
327+
spanned, i, next,
328+
widths, fm);
329+
if (next - i > actualNum)
330+
adjustTextWidths(widths, spanned, i, next, actualNum);
327331
System.arraycopy(widths, 0, widths,
328332
end - start + (i - start), next - i);
329333

@@ -966,6 +970,22 @@ private static int getFit(TextPaint paint,
966970
return low;
967971
}
968972

973+
private static void adjustTextWidths(float[] widths, CharSequence text,
974+
int curPos, int nextPos, int actualNum) {
975+
try {
976+
int dstIndex = nextPos - curPos - 1;
977+
for (int srcIndex = actualNum - 1; srcIndex >= 0; srcIndex--) {
978+
final char c = text.charAt(dstIndex + curPos);
979+
if (c >= 0xD800 && c <= 0xDFFF) {
980+
widths[dstIndex--] = 0.0f;
981+
}
982+
widths[dstIndex--] = widths[srcIndex];
983+
}
984+
} catch (IndexOutOfBoundsException e) {
985+
Log.e("text", "adjust text widths failed");
986+
}
987+
}
988+
969989
private int out(CharSequence text, int start, int end,
970990
int above, int below, int top, int bottom, int v,
971991
float spacingmult, float spacingadd,

core/java/android/text/Styled.java

100644100755
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,10 @@ public static int getTextWidths(TextPaint paint,
203203
}
204204
}
205205

206+
int result;
206207
if (replacement == null) {
207208
workPaint.getFontMetricsInt(fmi);
208-
workPaint.getTextWidths(text, start, end, widths);
209+
result = workPaint.getTextWidths(text, start, end, widths);
209210
} else {
210211
int wid = replacement.getSize(workPaint, text, start, end, fmi);
211212

@@ -214,8 +215,9 @@ public static int getTextWidths(TextPaint paint,
214215
for (int i = start + 1; i < end; i++)
215216
widths[i - start] = 0;
216217
}
218+
result = end - start;
217219
}
218-
return end - start;
220+
return result;
219221
}
220222

221223
/**

0 commit comments

Comments
 (0)